天天看點

程式檢測系統是bios引導還是uefi引導程式檢測系統是bios引導還是uefi引導

程式檢測系統是bios引導還是uefi引導

//百度很多資料都沒有找到,  終于在谷歌上找到很多有用的資料了,   最後在微軟的網站找到最有用的資料了.
//判斷流程可以這樣:
//1, 支援efi引導的//隻有win7及以上, 是以xp, 03系統就隻能夠bios引導
//2, win7,8,8.1,10等系統, 可以用下面的代碼, 本質上就是GetFirmwareEnvironmentVariableA, 或者GetFirmwareType這兩個api的調用

#include <Windows.h>
#include <Winbase.h>	//GetFirmwareEnvironmentVariableA  和   GetFirmwareType的頭檔案
#include <iostream>
using namespace std;
void main()
{
	//For Windows 8/Server 2012 and above可用
	/*
	typedef enum _FIRMWARE_TYPE {
	FirmwareTypeUnknown = 0,
	FirmwareTypeBios = 1,
	FirmwareTypeUefi = 2,
	FirmwareTypeMax = 3
	} FIRMWARE_TYPE, *PFIRMWARE_TYPE;
	*/
	FIRMWARE_TYPE a;
	GetFirmwareType(&a);
	switch (a)
	{
	case FirmwareTypeUnknown:
		cout << "不知名引導" << endl; break;
	case FirmwareTypeBios:
		cout << "Bios引導" << endl; break;
	case FirmwareTypeUefi:
		cout << "Uefi引導" << endl; break;
	case FirmwareTypeMax:
		cout << "Not implemented" << endl; break;
	}

	//Windows 7/Server 2008R2 and above可用
	GetFirmwareEnvironmentVariableA("", "{00000000-0000-0000-0000-000000000000}", NULL, 0);
	if (GetLastError() == ERROR_INVALID_FUNCTION)
		//API not supported; this is a legacy BIOS
		cout << "Bios引導" << endl; 
	else
		//API error (expected) but call is supported.This is UEFI.
		cout << "Uefi引導" << endl; 
		
	system("pause");
}

           

/

下面貼上找到的最好的微軟資料(三個辦法判斷bios和efi引導)

 腳本 Determine UEFI or Legacy BIOS from PowerShell (Three methods)

https://gallery.technet.microsoft.com/scriptcenter/Determine-UEFI-or-Legacy-7dc79488

UEFI和BIOS啟動模式對比

http://www.upanok.com/jiaocheng/115.html

UEFI boot: how does that actually work, then?

https://www.happyassassin.net/2014/01/25/uefi-boot-how-does-that-actually-work-then/

BIOS Mode - See if Windows Boot in UEFI or Legacy Mode

http://www.eightforums.com/tutorials/29504-bios-mode-see-if-windows-boot-uefi-legacy-mode.html

<#

This script shows three methods to determine the underlying system firmware (BIOS) type - either UEFI or Legacy BIOS.

The first method relies on the fact that Windows setup detects the firmware type as a part of the Windows installation

routine and records its findings in the setupact.log file in the \Windows\Panther folder.  It's a trivial task to use

Select-String to extract the relevent line from this file and to pick off the (U)EFI or BIOS keyword it contains.

To do a proper job there are two choices; both involve using Win32 APIs which we call from PowerShell through a compiled

(Add-Type) class using P/Invoke.

For Windows 7/Server 2008R2 and above, the GetFirmwareEnvironmentVariable Win32 API (designed to extract firmware environment

variables) can be used.  This API is not supported on non-UEFI firmware and will fail in a predictable way when called - this 

will identify a legacy BIOS.  On UEFI firmware, the API can be called with dummy parameters, and while it will still fail 

(probably!) the resulting error code will be different from the legacy BIOS case.

For Windows 8/Server 2012 and above there's a more elegant solution in the form of the GetFirmwareType() API.  This

returns an enum (integer) indicating the underlying firmware type.

Chris Warwick, @cjwarwickps,  September 2013

chrisjwarwick.wordpress.com

#>

# First method, one-liner, extract answer from setupact.log using Select-String and tidy-up with -replace

# Look in the setup logfile to see what bios type was detected (EFI or BIOS)

(Select-String 'Detected boot environment' C:\Windows\Panther\setupact.log -AllMatches ).line -replace '.*:\s+'

<#

Second method, use the GetFirmwareEnvironmentVariable Win32 API.

From MSDN (http://msdn.microsoft.com/en-ca/library/windows/desktop/ms724325%28v=vs.85%29.aspx):

"Firmware variables are not supported on a legacy BIOS-based system. The GetFirmwareEnvironmentVariable function will 

always fail on a legacy BIOS-based system, or if Windows was installed using legacy BIOS on a system that supports both 

legacy BIOS and UEFI. 

"To identify these conditions, call the function with a dummy firmware environment name such as an empty string ("") for 

the lpName parameter and a dummy GUID such as "{00000000-0000-0000-0000-000000000000}" for the lpGuid parameter. 

On a legacy BIOS-based system, or on a system that supports both legacy BIOS and UEFI where Windows was installed using 

legacy BIOS, the function will fail with ERROR_INVALID_FUNCTION. On a UEFI-based system, the function will fail with 

an error specific to the firmware, such as ERROR_NOACCESS, to indicate that the dummy GUID namespace does not exist."

From PowerShell, we can call the API via P/Invoke from a compiled C# class using Add-Type.  In Win32 any resulting

API error is retrieved using GetLastError(), however, this is not reliable in .Net (see 

blogs.msdn.com/b/adam_nathan/archive/2003/04/25/56643.aspx), instead we mark the pInvoke signature for 

GetFirmwareEnvironmentVariableA with SetLastError=true and use Marshal.GetLastWin32Error()

Note: The GetFirmwareEnvironmentVariable API requires the SE_SYSTEM_ENVIRONMENT_NAME privilege.  In the Security 

Policy editor this equates to "User Rights Assignment": "Modify firmware environment values" and is granted to 

Administrators by default.  Because we don't actually read any variables this permission appears to be optional.

#>

Function IsUEFI {

<#

.Synopsis

   Determines underlying firmware (BIOS) type and returns True for UEFI or False for legacy BIOS.

.DESCRIPTION

   This function uses a complied Win32 API call to determine the underlying system firmware type.

.EXAMPLE

   If (IsUEFI) { # System is running UEFI firmware... }

.OUTPUTS

   [Bool] True = UEFI Firmware; False = Legacy BIOS

.FUNCTIONALITY

   Determines underlying system firmware type

#>

[OutputType([Bool])]

Param ()

Add-Type -Language CSharp -TypeDefinition @'

    using System;

    using System.Runtime.InteropServices;

    public class CheckUEFI

    {

        [DllImport("kernel32.dll", SetLastError=true)]

        static extern UInt32 

        GetFirmwareEnvironmentVariableA(string lpName, string lpGuid, IntPtr pBuffer, UInt32 nSize);

        const int ERROR_INVALID_FUNCTION = 1; 

        public static bool IsUEFI()

        {

            // Try to call the GetFirmwareEnvironmentVariable API.  This is invalid on legacy BIOS.

            GetFirmwareEnvironmentVariableA("","{00000000-0000-0000-0000-000000000000}",IntPtr.Zero,0);

            if (Marshal.GetLastWin32Error() == ERROR_INVALID_FUNCTION)

                return false;     // API not supported; this is a legacy BIOS

            else

                return true;      // API error (expected) but call is supported.  This is UEFI.

        }

    }

'@

    [CheckUEFI]::IsUEFI()

}

<#

Third method, use GetFirmwareTtype() Win32 API.

In Windows 8/Server 2012 and above there's an API that directly returns the firmware type and doesn't rely on a hack.

GetFirmwareType() in kernel32.dll (http://msdn.microsoft.com/en-us/windows/desktop/hh848321%28v=vs.85%29.aspx) returns 

a pointer to a FirmwareType enum that defines the following:

typedef enum _FIRMWARE_TYPE { 

  FirmwareTypeUnknown  = 0,

  FirmwareTypeBios     = 1,

  FirmwareTypeUefi     = 2,

  FirmwareTypeMax      = 3

} FIRMWARE_TYPE, *PFIRMWARE_TYPE;

Once again, this API call can be called in .Net via P/Invoke.  Rather than defining an enum the function below 

just returns an unsigned int.

#>

# Windows 8/Server 2012 or above:

Function Get-BiosType {

<#

.Synopsis

   Determines underlying firmware (BIOS) type and returns an integer indicating UEFI, Legacy BIOS or Unknown.

   Supported on Windows 8/Server 2012 or later

.DESCRIPTION

   This function uses a complied Win32 API call to determine the underlying system firmware type.

.EXAMPLE

   If (Get-BiosType -eq 1) { # System is running UEFI firmware... }

.EXAMPLE

    Switch (Get-BiosType) {

        1       {"Legacy BIOS"}

        2       {"UEFI"}

        Default {"Unknown"}

    }

.OUTPUTS

   Integer indicating firmware type (1 = Legacy BIOS, 2 = UEFI, Other = Unknown)

.FUNCTIONALITY

   Determines underlying system firmware type

#>

[OutputType([UInt32])]

Param()

Add-Type -Language CSharp -TypeDefinition @'

    using System;

    using System.Runtime.InteropServices;

    public class FirmwareType

    {

        [DllImport("kernel32.dll")]

        static extern bool GetFirmwareType(ref uint FirmwareType);

        public static uint GetFirmwareType()

        {

            uint firmwaretype = 0;

            if (GetFirmwareType(ref firmwaretype))

                return firmwaretype;

            else

                return 0;   // API call failed, just return 'unknown'

        }

    }

'@

    [FirmwareType]::GetFirmwareType()

}

# An electron is pulled-up for speeding. The policeman says, “Sir, do you realise you were travelling at 130mph?” The electron says, “Oh great, now I’m lost.”

繼續閱讀