程序检测系统是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.”





评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值