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 管固件向操作系统描述平台是什么。

固件规范分层与协作关系 平台硬件:CPU / 芯片组 / 内存 / 总线 / 外设 PI 规范(固件内部) SEC → PEI → DXE → BDS 阶段划分、模块调度、交接 UEFI 规范(对外接口) Boot Services / Runtime Services Protocol / 设备路径 / 变量服务 ACPI 规范 DSDT / FADT / MADT 等表 电源管理与设备枚举 SMBIOS 规范 Type 0 / 1 / 4 / 17 等结构 平台身份与资产信息 操作系统 / 引导加载器 / 管理工具 通过 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 结构?用这三个问题定位模块职责,比死记目录结构更有效。