UEFI开发学习24 – UEFI 中的 Boot Manager

一、简介

Boot Manager即引导管理器,从UEFI初始化到进入操作系统的过程中,使用了两个引导管理器。

第一个是UEFI 固件中的引导管理器,也就是UEFI手册中第三章所定义的固件引导管理器(Firmware Boot Manager),第二个则是操作系统中的引导管理器。

图1 固件引导管理器

图2 Windows引导管理器

二、启动流程

UEFI初始化至BDS(Boot Device Select,即引导设备选择)阶段后,控制权递交给了固件引导管理器,它将处理加载操作系统的引导项,如Windows系统,引导项是一个bootmgfw.efi文件,它即是Windows引导管理器。Windows引导管理器可以显示操作系统的引导项,如在多个操作系统共存的时候,将根据用户选择,加载对应系统的OS Loader(Windows对应的为winload.efi文件),最后OS Loader将启动ntoskrnl.exe程序,开始系统内核初始化。

图3 Windows启动流程

三、引导管理器

这一篇主要介绍固件引导管理器,所以下文所提到的引导管理器都指的是固件引导管理器。

引导管理器的工作主要是解析存储在SPI ROM内,NVRAM中的Global Variable各项boot相关的值,加载指定的项,而被加载的项称为LoadOption。

3.1 Global Variable

Global Variable是UEFI中定义的一组数据,它们共用一个GUID,通过不同的Variable Name进行区分。具体定义如下:

图4 Global Variable定义

其中,Attribute表示:

NV:在系统重启或掉电情况下,拥有此属性的值依然可以保存,没有此属性的值将丢失。

BS:在ExitBootServices() 调用后,该值将不可用,意味着只能在ExitBootServices() 调用前访问,且在OS系统下不可见。

RT:在ExitBootServices() 调用前后均可访问,OS下亦可。

AT:此属性的Variable需要校验权限。

3.2 LoadOption

LoadOption主要有Boot,Driver,SysPrep,OsRecovery,PlatformRecovery几种类型。在上图中可知道,这些Variable属性是RT,BS,和NV,意味着它们在exitbootservice()调用前后都可以被访问。

3.2.1 加载项Boot

Boot类型一般指的是操作系统的引导,也就是一个可以启动操作系统的EFI APP,它是一个特殊的APP,需要放在efiboot目录下,格式为FAT(FAT12、FAT16、FAT32)的分区中,并且APP的名字需要命名为bootxxxx.efi,xxxx表示平台架构类型,如x86、32位架构为BootIa32.efi,x86、64位架构为BootX64.efi,Arm、64位架构为BootAa64.efi,国产龙芯LoongArch64为BootLa64.efi等。当然,APP的入口必须符合UEFI image定义的入口,否则将无法被加载执行。

typedef
EFI_STATUS(EFIAPI *EFI_IMAGE_ENTRY_POINT) (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
);
UEFI Image定义

EfiBoot是UEFI定义的通用系统引导目录,系统安装完成后,操作系统还会生成系统的引导项,如Windows Boot Manager,它的引导文件放在EfiMicrosoftbootmgfw.efi,实际上bootmgfw.efi是复制bootx64.efi后重命名而来的,这样做的意义大概是为了实现同磁盘多系统引导的功能。比如要在同一硬盘安装windows和linux系统,而UEFI定义的引导文件是固定为EfiBootxxxx.efi的,这样便会造成引导冲突。要解决此问题,只能重新新建引导,把引导文件放到其它目录,如Windows放到EfiMicrosoft,Ubuntu放到EfiUbuntu。而通过BootX64.efi启用的系统,则作为主系统,可以通过系统的引导管理器管理其它系统引导,这样便实现了多系统共存。

引导文件存放的媒介可以有多种类型,如UEFI固件的FV(EFI Shell),U盘,CDROM,SSD,HDD等存储设备。这些设备会在UEFI初始化过程中枚举出来,然后生成相应的引导项。

引导项的信息被保存在以BootXXXX命名的Global Variable中,XXXX表示引导的编号,宽度为四个字符,如Boot0000。同时,引导编号将会添加到BootOrder这个Global Variable中,用来表示引导的优先顺序,如果要更改引导项优先级,只要修改BootOrder中编号的顺序即可。

引导管理器首先读取的是BootOrder中编号,接着再根据编号生成BootXXXX引导项,然后用引导项名便可取得引导信息。

如前文所述,BootXXXX和BootOrder是全局可被访问的,意味着在efi shell或操作系统中也可以创建引导项,下面来做实验。

EFI Shell 下使用bcfg命令查询所有引导项:

bcfg boot dump

使用bcfg命令添加引导项UEFI Test Boot:

bcfg boot add 1 fs2:EFIBootbootX64.efi "UEFI Test Boot"

重启后可在引导菜单显示:

进EFI Shell后使用bcfg命令删除引导项:

    bcfg boot rm 01
    可以看到UEFI Test Boot引导已经被删除。

    3.2.2 加载项driver

    driver同boot一样,有DriverOrder和DriverXXXX两种Global Variable,它在加载Boot之前被执行。设计driver加载项的目的是可以允许加载额外的UEFI Driver。举个简单的例子,比如要在setup界面中截图,而bios又不支持,此时可以新建一个Driver0000指向截图驱动(截图驱动可以放在U盘或磁盘的ESP分区中),并将驱动编号添加到DriverOrder中,以后UEFI固件每次初始化都会加载该驱动,这样就可以在setup界面使用截图功能了。

    添加DriverXXXX同样可以使用bcfg命令实现,方法跟boot一样,所以不多举例了,文中示例的UEFI截图便是使用此方法获取的。

    3.2.3 加载项SysPrep

    SysPrep可以让UEFI固件在启动OS之前,执行除固件外的EFI APP,执行顺序在Driver之后,Boot之前。

    使用方法同Driver类似,这里便不再赘述了。

    需要注意的是,不论是Driver还是SysPrep类型,由于是UEFI固件之外的,当安全启动打开的时候,它们都必须经过签名,否则是无法被执行的。

    3.3 OsIndications

    OsIndications是一个可选的Global Variable,默认可能不会在UEFI固件中建立,所以如果在Efi Shell中用setvar命令访问它的时候,可能提示不存在。OsIndications是一个指示器,用于指示当前需要启动哪个加载项。UEFI手册中定义了几个OsIndications类型:

    当其中的某个bit被置起来时,BootOrder中的引导项将被忽略,而优先加载OsIndications对应的加载项,加载后该bit被清除。

    实例1 设置启动后进入BIOS Setup

    a. 进入Efi shell,用setvar命令查看OsIndications状态

    setvar OsIndications
    
    
    提示不存在

    b. 建立OsIndications,并设置为Setup

    setvar OsIndications -guid 8BE4DF61-93CA-11D2-AA0D-00E098032B8C -rt -bs -nv =0x00000001
    
    

    c. 重启后便可进入BIOS Setup

    操作系统一般都有个重启进入UEFI Firmware的选项,利用的便是此原理。Windows下可使用如下命令进入BIOS Setup:
    shutdown -r -t 0 -fw
    
    
    如果OsIndications没有建立,输入指令后则会报错,重新输入一次即可。

    本文到此结束...

    版权声明:
    作者:bin
    链接:https://ay123.net/mystudy/uefi/1610/
    来源:爱影博客
    文章版权归作者所有,未经允许请勿转载。

    THE END
    分享
    二维码
    海报
    UEFI开发学习24 – UEFI 中的 Boot Manager
    一、简介 Boot Manager即引导管理器,从UEFI初始化到进入操作系统的过程中,使用了两个引导管理器。 第一个是UEFI 固件中的引导管理器,也就是UEFI手册中第三……
    <<上一篇
    下一篇>>
    文章目录
    关闭
    目 录