程序检测系统是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: UEFI引导程序是一种新一代的计算机引导程序,全称为统一可扩展固件接口(Unified Extensible Firmware Interface)。下面我会简要介绍一个UEFI引导程序的实现。 UEFI引导程序的实现主要包括以下几个步骤。首先,需要进行UEFI固件的配置。这包括设置UEFI固件的启动模式、开启UEFI的安全启动功能、设置固件密码等。 接下来,需要编写引导程序的代码。UEFI引导程序通常使用C语言进行编写。编写代码时需要调用UEFI提供的API函数,通过这些函数可以获取硬件信息、控制设备、加载系统镜像等。 然后,需要编译和链接引导程序的代码。UEFI引导程序的代码需要经过编译器的编译,生成二进制文件。然后通过链接器将生成的二进制文件与UEFI固件的其他模块进行链接,生成最终的UEFI引导程序。 随后,将编译和链接好的UEFI引导程序文件加载到UEFI固件中。这可以通过将UEFI引导程序文件复制到固件中的特定目录中来实现。 最后,设置UEFI固件的启动顺序。UEFI固件可以通过设置启动菜单或者在固件设置界面中,将UEFI引导程序设置为第一启动选项,以确保计算机在开机时会首先加载并执行UEFI引导程序。 以上就是一个UEFI引导程序的实现的基本过程。实现一个UEFI引导程序需要了解UEFI规范和相关API函数的使用,同时需要具备编程和编译的技能。UEFI引导程序的实现是计算机启动过程中的重要环节,它负责加载操作系统并进行硬件初始化,为系统的正常运行奠定基础。 ### 回答2: 一个UEFI引导程序的实现需要遵循UEFI规范,并按照相关的指导进行开发和编写。 首先,UEFI(统一可扩展固件接口)是一个用于操作系统引导的标准接口,它取代了传统的BIOS固件接口。UEFI引导程序的实现需要了解UEFI规范中的各种协议和API,以及UEFI固件的功能和工作原理。 其次,UEFI引导程序一般包括三个主要组成部分:引导管理器、操作系统加载器和驱动加载器。引导管理器是UEFI固件的一部分,负责启动UCPU并初始化硬件环境。操作系统加载器是负责加载和启动操作系统的组件,它可以是UEFI应用程序或EFI可执行文件。驱动加载器则负责加载和初始化设备驱动程序。 在实现UEFI引导程序时,需要根据具体的硬件平台和需求来开发适当的代码。通常,可以使用C语言编写UEFI应用程序,并使用UEFI提供的库函数来操作和访问各种协议和设备。 UEFI引导程序的实现过程包括以下几个步骤:首先,需要写入合适的硬盘分区或可移动设备,以便UEFI固件能够检测到该引导程序。其次,需要在UEFI固件中的启动选项中添加该引导程序的信息。然后,编写引导管理器代码,实现启动UCPU和初始化硬件环境的功能。接下来,编写操作系统加载器代码,实现加载和启动操作系统的功能。最后,编写驱动加载器代码,实现加载和初始化设备驱动程序的功能。 总结来说,UEFI引导程序的实现需要了解UEFI规范和相关的编程知识,并按照规范和需求进行开发和编写,以实现启动UCPU、加载和启动操作系统,以及加载和初始化设备驱动程序的功能。 ### 回答3: UEFI(Unified Extensible Firmware Interface)是一种用于计算机引导和初始化的固件接口标准,它取代了传统的BIOS(Basic Input/Output System)。一个UEFI引导程序的实现通常包含了以下几个主要步骤。 首先,UEFI引导程序的实现需要创建一个硬盘分区或逻辑卷来存储引导程序文件。这可以在计算机启动时的配置界面或者使用专门的工具进行。 接下来,UEFI引导程序的实现需要为引导程序创建一个适当的文件系统。常见的文件系统包括FAT32和NTFS。引导程序文件应该被存储在该文件系统的根目录或者一个特定的目录下,以便UEFI固件可以找到它。 然后,在硬盘分区或逻辑卷上创建完文件系统后,UEFI引导程序的实现需要将引导程序文件复制到相应的目录中。这可以使用操作系统提供的命令行工具或者图形界面工具来完成。 最后,UEFI引导程序的实现需要在计算机的固件配置中指定引导程序的位置。这可以通过进入计算机的UEFI配置界面并设置引导选项来完成。用户可以手动选择要引导的设备和引导文件,也可以调整引导的顺序。 在完成上述步骤之后,计算机下次启动时将会加载UEFI引导程序,并根据其配置进行引导操作。这样,计算机能够正常启动操作系统或其他引导程序。 总之,一个UEFI引导程序的实现包括创建适当的分区和文件系统、复制引导程序文件以及在固件配置中设置引导选项。这样,计算机就能够使用UEFI引导程序来正确启动操作系统
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值