3. UEFI启动流程
UEFI规范把平台固件从加电到操作系统接管的过程划分为七个阶段:SEC、PEI、DXE、BDS、TSL、RT、AL。前五个阶段是“启动期”,后两个阶段是“运行期”。理解这条链路的关键,不是背下缩写,而是看清每个阶段解决什么问题、把什么数据交给下一阶段,以及交接时依赖哪些结构。
一、七个阶段的职责与执行顺序
SEC(Security Phase)是加电后的第一段代码,运行在只读存储器的复位向量处。此时内存尚未初始化,可用资源只有CPU缓存和极少量SRAM。SEC的核心任务是建立临时RAM(CAR,Cache As RAM)、验证并解压PEI核心、处理复位类型,最后把控制权交给PEI入口。它还要负责最基础的信任根,例如验证固件卷的完整性。
PEI(Pre-EFI Initialization)阶段的目标是“把内存准备好”。它通过PEI核心调度一系列PEIM(PEI Module),完成内存控制器初始化、芯片组早期配置、发现并描述固件卷。PEI结束时会产生HOB(Hand-Off Block)列表,这是PEI交给DXE最重要的数据结构,里面记录了内存布局、已初始化硬件、固件卷位置等信息。
DXE(Driver Execution Environment)阶段是固件功能的主体。DXE调度器按依赖关系加载并执行DXE驱动,建立启动服务、运行时服务、协议数据库。驱动通过Protocol互相发现和调用,形成完整的固件服务生态。DXE结束时,系统已经具备访问磁盘、网络、输入输出等能力。
BDS(Boot Device Selection)阶段负责“选谁启动”。它枚举启动项、执行启动策略、加载启动设备上的UEFI应用或操作系统加载器。BDS是启动期与运行期的分界点:一旦成功移交控制权,固件就进入TSL。
TSL(Transient System Load)是操作系统加载器运行、但操作系统内核尚未完全接管的过渡期。此时Boot Services仍然可用,加载器可以继续调用固件服务读取文件、分配内存。当加载器调用ExitBootServices()后,Boot Services被销毁,进入RT。
RT(Runtime)阶段操作系统已接管系统,固件只保留运行时服务,例如变量读写、时间服务、复位服务。这些服务在OS运行期间仍可被调用,但不再参与设备枚举和启动决策。
AL(After Life)是固件生命周期的最后阶段,发生在系统关机、休眠或复位前。平台在此阶段保存必要状态、执行清理,然后交还控制权给硬件复位或断电流程。
二、阶段间交接机制:HOB、协议与事件
阶段之间不是简单的函数调用,而是通过规范定义的数据结构交接。PEI到DXE的核心是HOB列表。HOB是一段段连续内存块,每块有类型和长度,常见类型包括PHIT HOB(描述内存范围)、FV HOB(固件卷位置)、GUID HOB(自定义数据)。DXE核心启动后首先解析HOB,把内存和固件卷信息注册到系统表中。
DXE到BDS的交接依赖协议数据库和启动服务。DXE驱动通过InstallProtocolInterface把能力暴露出去,BDS通过LocateProtocol查找启动策略、设备路径、控制台等协议。BDS本身也是一个DXE应用,它调用Boot Services完成启动项枚举和加载。
TSL到RT的交接由ExitBootServices()触发。这个调用会销毁所有Boot Services,包括内存分配、事件、协议接口。调用前加载器必须获取内存映射键值,调用时传入该键值,若内存映射已变化则调用失败,需要重新获取。这是实际开发中最容易踩坑的交接点。
三、典型场景:一次正常启动的日志观察
在QEMU或真实平台上打开串口日志,可以看到阶段切换的痕迹。下面是一段简化日志,展示了从SEC到BDS的关键输出:
SEC: CAR initialized, reset vector 0xFFFFFFF0
PEI: PEI Core dispatched, HOB list created
PEI: Memory init done, 0x00000000 - 0x7FFFFFFF
DXE: DXE Core started, protocol database ready
DXE: Loaded driver: PciBusDxe, ScsiBusDxe, GraphicsOutputDxe
BDS: Boot option #1: UEFI Shell
BDS: Connecting device path PciRoot(0x0)/Pci(0x1F,0x2)/Sata(0x0)
TSL: ExitBootServices() called, memory map key = 0x9A3C
RT: Runtime services available
从日志可以看出,PEI结束时打印内存范围,说明HOB已生成;DXE阶段出现驱动加载,说明协议数据库在扩展;BDS阶段出现启动项和设备路径,说明启动策略生效;TSL阶段出现ExitBootServices,说明控制权即将完全移交。
四、常见误区与复盘
| 阶段 | 核心职责 | 关键交接物 | 典型失败现象 |
|---|---|---|---|
| SEC | 建立临时RAM、验证信任根 | 复位向量、CAR | 无串口输出、复位循环 |
| PEI | 初始化内存、生成HOB | HOB列表 | 内存大小识别错误、DXE无法启动 |
| DXE | 加载驱动、建立协议 | 协议数据库、启动服务 | 设备不可见、驱动依赖缺失 |
| BDS | 枚举启动项、加载启动器 | 启动项、设备路径 | 找不到启动设备、启动项丢失 |
| TSL | OS加载器运行、移交控制权 | ExitBootServices() | 内存映射键值失效、移交失败 |
| RT | 提供运行时服务 | 变量服务、时间服务 | 变量读写异常、复位服务不可用 |
| AL | 关机/休眠前收尾 | 状态保存、清理 | 休眠恢复失败、状态丢失 |
把七个阶段串起来看,UEFI启动流程本质上是一条“资源逐步可用、服务逐步建立、控制权逐步移交”的链路。SEC解决“能跑”,PEI解决“有内存”,DXE解决“有服务”,BDS解决“启动谁”,TSL解决“交给谁”,RT解决“留下什么”,AL解决“怎么收尾”。掌握每个阶段的交接物,比记住缩写顺序更有实战价值。