RogerWilco
RogerWilco

Reputation: 81

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

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?

Upvotes: 8

Views: 8324

Answers (6)

NiKiZe
NiKiZe

Reputation: 1432

$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

Upvotes: 1

Giovanni Bassi
Giovanni Bassi

Reputation: 839

The easieast way by far is to run on PowerShell:

$(Get-ComputerInfo).BiosFirmwareType

Upvotes: 2

Alyssa Haroldsen
Alyssa Haroldsen

Reputation: 3731

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

Upvotes: 1

awp2513
awp2513

Reputation: 11

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.

Upvotes: -2

user257111
user257111

Reputation:

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.

Upvotes: 3

tkrn
tkrn

Reputation: 606

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"

}

Upvotes: -1

Related Questions