Как определить, загрузился ли WinPE(4) из UEFI или BIOS?
Я ищу способ надежного определения, когда я загружаюсь в WinPE 4 (powershell) (или в качестве альтернативы WinPE 3 (vbs)), загрузился ли я из системы UEFI или BIOS? (без запуска стороннего exe-файла, так как я в ограниченной среде)
Это существенно меняет способ разбиения развертывания Windows по мере изменения и форматирования разделов. (GPT против MBR и т. Д.)
У меня есть один рабочий, который является адаптацией этого кода C++ в powershell v3, но он выглядит довольно взломанным:
## 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()
}
Это выглядит довольно просто, просто чтобы получить простой флаг.
Кто-нибудь знает, есть ли лучший способ сделать это?
5 ответов
Он не менее хакерский, в том смысле, что он все еще требует взаимодействия с powershell, но код взаимодействия может быть более аккуратным, если вы используете (или можете вызвать): GetFirmwareType()
,
Это возвращает FIRMWARE_TYPE
Перечень документирован здесь. Я не могу поверить, учитывая, что обе функции введены в Windows 8 и экспортированы kernel32.dll, что собственная документация Microsoft указывает вам на "использование фиктивной переменной"!
Внутренне GetFirmwareType
звонки NtQuerySystemInformation
, Я углублюсь в то, что он делает, но я не думаю, что это обязательно будет просветляющим.
К сожалению, это работает только для PE4 (Windows 8), так как эти функции были добавлены только тогда.
Самый простой способ - запустить PowerShell:
$(Get-ComputerInfo).BiosFirmwareType
Это может быть немного поздно, но если кто-то знает, что они работают в WinPE, следующий код должен работать:
$isuefi = (Get-ItemProperty -Path HKLM:\System\CurrentControlSet\Control).PEFirmwareType -eq 2
$env:firmware_type
Не уверен, с какой версией это поддерживается. Возврат
UEFI
и
Legacy
в моих тестах.
Однако это при полной установке, обратите внимание на подтверждение существования в WinPE
У меня нет системы UEFI для тестирования, но эта статья, кажется, подразумевает, что есть значение реестра, которое вы можете запросить в PE, чтобы узнать, в каком режиме он был загружен:
Я не знаю, поможет ли это (на основе решения C#), но:
Win32_DiskPartition имеет свойства "Bootable" (bool), "BootPartition" (bool) и "Type" (строка). Для моей системы UEFI "Тип" возвращается как строка "GPT: Система".
Теперь для всех загрузочных разделов Win32_DiskPartition, которые являются загрузочными разделами и имеют указанный тип, определите, являются ли какие-либо из них внутренними.
Надеюсь это поможет.
Похоже, что среда PE имеет папку, специфичную для среды PE. Кроме того, здесь описывается переменная%TargetDir%, свойство TARGETDIR.
Наконец, вы можете проверить, работаете ли вы с X: там также должна быть папка с образом boot.wim, который вы можете проверить. Я считаю, что путь будет X:\Sources\Boot.wim, но с двойной проверкой.
if ( Test-Path "%TargetDir%\Windows\wpeprofiles" ) {
Write-host "You're in Windows PE"
}