2. 固件与UEFI基础
在进入 EDK II 平台固件开发之前,必须先建立一套“共同语言”。固件工程师日常说的 UEFI、PI、ACPI、SMBIOS 并不是同义词,它们分别描述平台启动与运行期不同层面的契约。理解这些规范的边界与协作关系,是读懂 EDK II 代码结构、包依赖和启动流程的前提。
一、固件是什么:从加电到操作系统的第一段代码
固件(Firmware)是存储在非易失性存储介质中、在处理器复位后最先获得执行权的软件。它负责把“刚上电、几乎什么都不能用”的裸硬件,逐步初始化到能够加载操作系统引导程序的状态。与通用操作系统不同,固件与具体芯片组、主板、外设拓扑强相关,因此具有明显的平台绑定特征。
从职责上看,固件至少完成四件事:建立最基本的 CPU 与内存运行环境;枚举并初始化关键总线与外设;向操作系统提供标准化的启动时与运行时接口;在交接控制权后仍保留部分运行期服务。EDK II 正是实现这些职责的一套开源开发框架。
关键认识:固件不是“一个小型操作系统”,而是平台硬件与操作系统之间的契约实现层。它既要懂硬件,也要按规范对外提供稳定接口。
二、UEFI、PI、ACPI、SMBIOS 的层次关系
这几个规范经常被并列提及,但它们关注的层面不同:
- UEFI 规范:定义操作系统加载器与固件之间的接口,包括启动服务(Boot Services)、运行时服务(Runtime Services)、协议(Protocol)机制、设备路径、变量服务等。它回答的是“操作系统如何调用固件”。
- PI 规范:Platform Initialization 规范,定义固件内部各阶段(SEC、PEI、DXE、BDS 等)的划分、阶段间交接方式以及固件模块之间的发现与调度规则。它回答的是“固件内部如何组织与推进”。
- ACPI 规范:定义操作系统如何发现平台电源管理、设备枚举与配置信息,核心产物是 ACPI 表(如 DSDT、FADT、MADT)。它回答的是“操作系统如何理解平台硬件拓扑与电源行为”。
- SMBIOS 规范:定义平台管理信息的标准结构,如主板、BIOS、处理器、内存、机箱等信息,供操作系统与管理工具读取。它回答的是“平台身份与资产信息如何标准化描述”。
可以用一句话概括它们的分工:PI 管固件内部怎么跑,UEFI 管固件对外怎么被调用,ACPI 与 SMBIOS 管固件向操作系统描述平台是什么。
三、核心术语与 EDK II 中的对应关系
在 EDK II 工程中,这些规范会直接映射为目录结构、包(Package)和模块(Module)类型。例如,DXE 驱动通常实现 UEFI 协议;PEI 模块运行在 PEI 阶段;ACPI 表往往由 DXE 阶段的驱动生成并安装到系统表;SMBIOS 结构则由专门的 SMBIOS 驱动填充。
| 术语 | 规范归属 | 主要作用 | EDK II 中的典型体现 |
|---|---|---|---|
| Boot Services | UEFI | 启动期可用的内存、协议、事件等服务 | gBS 全局指针,DXE 驱动广泛使用 |
| Runtime Services | UEFI | 操作系统运行期仍可调用的变量、时间等服务 | gRT 全局指针,变量驱动实现 |
| PEI 阶段 | PI | 早期内存初始化与最小化硬件准备 | PEIM 模块,PEI Core 调度 |
| DXE 阶段 | PI | 驱动分发与设备初始化 | DXE 驱动,DXE Core 调度 |
| DSDT | ACPI | 描述平台设备与电源管理方法 | ASL 编译为 AML,由驱动安装 |
| SMBIOS Type 1 | SMBIOS | 描述系统制造商、产品名、版本等信息 | SMBIOS 驱动填充结构表 |
四、典型场景:一次加电启动中规范如何依次登场
假设一台搭载 EDK II 固件的主板加电。SEC 阶段在只读环境完成最早期初始化;PEI 阶段建立临时内存并准备关键硬件;DXE 阶段调度大量驱动,安装 UEFI 协议、生成 ACPI 表、填充 SMBIOS 结构;BDS 阶段按启动策略选择引导项,调用 UEFI 启动服务加载操作系统加载器。操作系统启动后,通过 ACPI 表了解设备与电源拓扑,通过 SMBIOS 读取平台资产信息,并在需要时调用 UEFI 运行时服务读写变量。
加电复位
→ SEC:建立临时运行环境
→ PEI:内存初始化、PEIM 调度
→ DXE:驱动分发、协议安装、ACPI/SMBIOS 生成
→ BDS:选择并加载引导项
→ OS Loader:调用 UEFI Boot Services
→ OS:读取 ACPI 表与 SMBIOS 结构,使用 Runtime Services
五、常见误区与复盘要点
误区一:把 UEFI 等同于固件全部。UEFI 只定义对外接口,固件内部阶段划分与调度属于 PI 规范。只懂 UEFI 而不懂 PI,很难理解 EDK II 的启动流程。
误区二:认为 ACPI 和 SMBIOS 是“可选装饰”。操作系统依赖它们完成设备枚举、电源管理和平台识别,缺失或错误会直接导致启动异常或功能缺失。
误区三:混淆规范版本与实现版本。EDK II 支持多个 UEFI/PI 版本特性,具体行为取决于平台配置与代码实现,不能仅凭规范版本推断实际表现。
复盘建议:学习 EDK II 时,遇到一个模块先问三个问题——它运行在哪个 PI 阶段?它实现或消费哪个 UEFI 协议?它是否生成 ACPI 表或 SMBIOS 结构?用这三个问题定位模块职责,比死记目录结构更有效。