2. UEFI 基础架构

理解 UEFI,不能只把它当成“新一代 BIOS”的代名词。UEFI 是一套由规范驱动的固件接口体系,它把固件从“面向中断向量的黑盒”重构为“面向协议、服务与模块的工程化平台”。要真正掌握 UEFI 开发,必须同时看清四条主线:UEFI 规范体系、PI 规范、与 Legacy BIOS 的差异,以及启动流程与固件分区布局。

一、UEFI 规范体系:接口契约而非实现

UEFI 规范由 UEFI Forum 维护,核心文档包括《UEFI Specification》与《PI Specification》。UEFI 规范定义的是操作系统加载器与固件之间的运行时契约,例如启动服务(Boot Services)、运行时服务(Runtime Services)、协议(Protocol)、设备路径、变量服务、事件与计时器等。它并不规定固件内部如何初始化芯片组,也不规定代码放在哪个物理地址。

因此,UEFI 规范回答的是“外部可见行为”:操作系统通过 EFI_BOOT_SERVICES 和 EFI_RUNTIME_SERVICES 能调用什么;驱动通过 EFI_DRIVER_BINDING_PROTOCOL 如何绑定设备;应用如何用 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL 读取文件。规范只保证接口语义,不保证实现细节,这为不同厂商的固件实现留下了空间。

二、PI 规范:固件内部的工程骨架

如果说 UEFI 规范面向操作系统,那么 PI(Platform Initialization)规范面向固件开发者。PI 规范把固件启动划分为若干阶段:SEC、PEI、DXE、BDS、TSL、RT、AL。它定义了 PEI 核心、PEIM、DXE 核心、DXE 驱动、协议数据库、HOB(Hand-Off Block)等机制,使芯片组初始化、内存初始化、驱动调度和启动策略能够以模块化方式协作。

PI 规范的关键价值在于“阶段解耦”:SEC 阶段负责最早期环境准备;PEI 阶段在内存尚未完全可用时完成关键初始化,并通过 HOB 传递信息;DXE 阶段在内存可用后调度大量驱动,建立协议数据库;BDS 阶段执行启动策略,选择启动项;TSL 阶段把控制权交给操作系统加载器。UEFI 规范与 PI 规范的关系可以概括为:PI 负责“固件怎么跑起来”,UEFI 负责“固件向 OS 提供什么”。

UEFI 规范体系与 PI 启动阶段协作关系 UEFI 规范(面向 OS/加载器) Boot Services / Runtime Services Protocol / Handle / Device Path 变量服务 / 事件 / 计时器 定义外部接口契约,不规定内部实现 PI 规范(面向固件内部) SEC / PEI / DXE / BDS / TSL / RT / AL PEIM / DXE Driver / HOB / 协议数据库 调度、发现、初始化、启动策略 定义固件内部工程骨架与阶段协作 协作 固件启动阶段(PI 规范划分) SEC PEI DXE BDS TSL RT AL 固件分区布局(典型 UEFI 固件卷) FV Header SEC/PEI 模块 DXE 驱动 BDS/启动项 NVRAM 变量

三、UEFI 与 BIOS/Legacy 的差异

传统 Legacy BIOS 以 16 位实模式中断服务为核心,操作系统通过 INT 13h 读盘、INT 10h 显示、INT 15h 获取内存信息。它没有统一的驱动模型,扩展卡通过 Option ROM 在实模式下挂钩中断,容易冲突且难以调试。UEFI 则运行在 32/64 位保护模式或长模式下,使用协议和句柄组织服务,驱动可以按绑定协议动态加载,启动过程可被策略控制。

更关键的是启动介质与分区布局的差异。Legacy 使用 MBR 分区表和活动分区引导扇区;UEFI 使用 GPT 分区表,并从 EFI 系统分区(ESP)加载 .efi 可执行文件。ESP 通常为 FAT32 格式,路径如 \EFI\BOOT\BOOTX64.EFI 或 \EFI\Microsoft\Boot\bootmgfw.efi。UEFI 还提供安全启动(Secure Boot)、变量存储和运行时服务,使启动链具备可验证性和可管理性。

对比维度 Legacy BIOS UEFI
运行模式 16 位实模式 32/64 位保护模式或长模式
服务模型 中断向量(INT 13h 等) Boot/Runtime Services + Protocol
分区表 MBR GPT
启动文件 活动分区引导扇区 ESP 中的 .efi 可执行文件
驱动扩展 Option ROM 挂钩中断 UEFI Driver 绑定协议
安全能力 较弱 Secure Boot、变量、度量

四、启动流程概览与固件分区布局

典型 UEFI 启动流程如下:上电后 CPU 从复位向量进入 SEC 阶段,建立临时内存环境并定位固件卷;随后进入 PEI 阶段,完成内存初始化、芯片组早期配置,并通过 HOB 把信息传递给 DXE;DXE 阶段调度驱动,建立协议数据库,枚举 PCI、USB、存储等设备;BDS 阶段读取启动变量,按启动顺序加载 ESP 中的 .efi 文件;操作系统加载器调用 ExitBootServices() 后进入 TSL,固件仅保留运行时服务;系统关机或休眠时进入 RT/AL 阶段。

固件分区布局方面,现代 UEFI 固件通常把代码和数据组织为固件卷(Firmware Volume, FV)。FV 内部包含文件、节(Section)和模块,SEC/PEI 模块常位于早期 FV,DXE 驱动位于主 FV,BDS 和启动策略可能位于独立 FV。NVRAM 中保存启动项、启动顺序和安全启动密钥等变量。ESP 则是磁盘上的 FAT32 分区,存放操作系统加载器和固件更新程序。

实操提示:在 UEFI Shell 中可用 map 查看设备映射,用 fs0: 进入 ESP,用 ls \EFI\BOOT 查看启动文件。调试启动问题时,先确认 ESP 是否存在、启动项是否指向正确的 .efi 文件,再检查 Secure Boot 是否阻止了未签名加载器。

常见误区:把 UEFI 等同于“图形化 BIOS 设置界面”是典型误解。图形界面只是实现层的一部分,UEFI 的核心是规范化的服务与协议。另一个误区是认为 UEFI 一定比 Legacy 启动更快;实际速度取决于固件实现、驱动数量和启动策略,不能一概而论。

五、复盘:从规范到代码的映射

开发 UEFI 驱动时,代码中会直接体现规范分层:入口点 InitializeDriver() 对应 DXE 驱动加载;InstallProtocolInterface() 对应协议数据库注册;gBS->LocateProtocol() 对应启动服务查询;gRT->GetVariable() 对应运行时变量读取。理解 PI 阶段与 UEFI 服务的对应关系,才能在调试时快速判断问题发生在 SEC、PEI、DXE 还是 BDS。

// 典型 DXE 驱动入口与协议安装
EFI_STATUS
EFIAPI
InitializeMyDriver(
  IN EFI_HANDLE        ImageHandle,
  IN EFI_SYSTEM_TABLE  *SystemTable
)
{
  EFI_STATUS Status;
  Status = gBS->InstallProtocolInterface(
             &ImageHandle,
             &gEfiMyProtocolGuid,
             EFI_NATIVE_INTERFACE,
             &gMyProtocol
           );
  return Status;
}

综上,UEFI 基础架构可以概括为“两层规范 + 一条启动链 + 一套分区布局”:UEFI 规范定义对外服务契约,PI 规范定义固件内部阶段与模块协作,启动链从 SEC 到 AL 逐级推进,固件卷与 ESP 承载代码和数据。掌握这四者之间的关系,是后续协议开发、驱动移植和启动排障的基础。