How do I detect if WinPE(4) has booted from a UEFI or BIOS?
Asked Answered
Z

6

8

I am looking for a way to reliably detect when I boot into WinPE 4 (powershell) (or WinPE 3 (vbs) as an alternative), have I booted from a UEFI or BIOS System? (without running a third party exe as I am in a restricted environment)

This significantly changes how I would be partitioning a windows deployment as the partitions layout changes and format. (GPT vs. MBR, etc)

I have one working that is an adaptation of this C++ code in powershell v3 but it feels pretty hack-ish :

## Check if we can get a dummy flag from the UEFI via the Kernel
## [Bool] check the result of the kernel's fetch of the dummy GUID from UEFI
## The only way I found to do it was using the C++ compiler in powershell
Function Compile-UEFIDectectionClass{
    $win32UEFICode= @'
    using System;
    using System.Runtime.InteropServices;

    public class UEFI
    {
       [DllImport("kernel32.dll")]
       public static extern UInt32 GetFirmwareEnvironmentVariableA([MarshalAs(UnmanagedType.LPWStr)] string lpName, [MarshalAs(UnmanagedType.LPWStr)] string lpGuid, IntPtr pBuffer, UInt32 nSize); 

       public static UInt32 Detect()
       {
            return GetFirmwareEnvironmentVariableA("", "{00000000-0000-0000-0000-000000000000}", IntPtr.Zero, 0);
       }
    }
    '@

Add-Type $win32UEFICode
}


## A Function added just to check if the assembly for 
## UEFI is loaded as is the name of the class above in C++.
Function Check-IsUEFIClassLoaded{
     return ([System.AppDomain]::CurrentDomain.GetAssemblies() | % { $_.GetTypes()} | ? {$_.FullName -eq "UEFI"}).Count 
}

## Just incase someone was to call my code without running the Compiled code run first
If (!(Check-IsUEFIClassLoaded)){
    Compile-UEFIDectectionClass
}

## The meat of the checking.
## Returns 0 or 1 ([BOOL] if UEFI or not)
Function Get-UEFI{
    return [UEFI]::Detect()
}

This seems pretty over the top just to get a simple flag.

Does anyone know if there is there a better way to get this done?

Zr answered 22/5, 2013 at 20:46 Comment(0)
O
3

It is no less hacky, in the sense it will still require interop from powershell, but the interop code might be neater if you use (or can call): GetFirmwareType().

This returns a FIRMWARE_TYPE enumeration documented here. I can't believe given both functions are introduced in Windows 8 and exported by kernel32.dll that Microsoft's own documentation points you at "using a dummy variable"!

Internally, GetFirmwareType calls NtQuerySystemInformation. I will dig into what it is doing, but I do not think it is necessarily going to be enlightening.

Unfortunately, this only works for PE4 (Windows 8) since these functions were only added then.

Overcrop answered 11/7, 2013 at 14:32 Comment(1)
This is the method the Get-ComputerInfo cmdlet uses behind the scenes to populate the BiosFirmwareType property.Copy
K
2

The easieast way by far is to run on PowerShell:

$(Get-ComputerInfo).BiosFirmwareType
Kirkman answered 3/2, 2020 at 22:45 Comment(3)
This works for me on WinPE v10.1.18362.1 for Windows 10 v1903, although, oddly, on v10.1.17763.1 for v1809 Get-ComputerInfo fails with error CimSessionOptions instance is invalid: unsupported protocol or unrecognized custom option. Verify parameter passed to the CimSessionOptions(string) constructor and/or parameters passed to the CimSessionOptions.SetCustomOption(string, string) or CimSessionOptions.SetCustomOption(string, int) method.Copy
I tested it on Windows 10 10.0.18363.628 (1909), and Server Core 10.0.17763.914 (1809).Kirkman
Downside with $(Get-ComputerInfo -Property BiosFirmwareType).BiosFirmwareType is that is quite slow (seems to poulate a lot of things that is then thrown away)Boardinghouse
R
1

This may be a little late, but if one knows they are running in WinPE, the following code should work:

$isuefi = (Get-ItemProperty -Path HKLM:\System\CurrentControlSet\Control).PEFirmwareType -eq 2
Radicand answered 12/7, 2014 at 22:5 Comment(0)
B
1

$env:firmware_type

Not sure since what version this is supported. Returns UEFI and Legacy in my tests.

However this is on full installation, Have note confirmed existence in WinPE

Boardinghouse answered 4/11, 2020 at 15:15 Comment(0)
A
-1

It looks like the PE environment has a folder that is specific to the PE environment. In addition, the variable %TargetDir% is described here, TARGETDIR property.

Lastly, you could check if you are running from X: There should be also a folder that has the boot.wim image you can check for. I believe the path would be X:\Sources\Boot.wim but double check.

if ( Test-Path "%TargetDir%\Windows\wpeprofiles" ) {

     Write-host "You're in Windows PE"

}
Alb answered 12/6, 2013 at 12:0 Comment(1)
It isn't whether or not I am in WinPE to begin with. It is when I am in PE, have I been booted by UEFI or Legacy BIOS.Zr
P
-2

I don't know if this will help (based on C# solution), but:

Win32_DiskPartition has the properties "Bootable" (bool), "BootPartition" (bool), and "Type" (string). For my UEFI system, "Type" comes back as the string "GPT: System".

Now, for all Win32_DiskPartitions that are bootable, are a boot partition, and have the specified type, determine if any of them are internal.

Hope this helps.

Palette answered 29/8, 2013 at 16:15 Comment(2)
This won't help. The WinPE (installer) environment is likely to be running against blank hard drives, and the presence of particular partition types on a drive does not guarantee that the current system can boot from them (the drive may have been transplanted from a different system).Intone
There is nothing that makes it invalid to have GPT on a disk even if booted in EFI mode, Likewise a disk partitioned with a FAT32 boot partition can be booted in EFI mode even without GPT, and some firmware even support NTFS. The only thing that enforces this to be correct is the windows installation, but there is other ways than windows setup to get windows on a disk.Boardinghouse

© 2022 - 2024 — McMap. All rights reserved.