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下亦可。
3.2 LoadOption
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 );
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
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类型:
实例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
shutdown -r -t 0 -fw
本文到此结束...
版权声明:
作者:bin
链接:https://ay123.net/mystudy/uefi/1610/
来源:爱影博客
文章版权归作者所有,未经允许请勿转载。
共有 0 条评论