UEFI设备驱动与固件开发工程 - 第1节

1.1 UEFI 的起源与发展

1.1.1 从 BIOS 到 UEFI 的演进

传统 BIOS(Basic Input/Output System)自 1981 年 IBM PC 诞生以来,一直是 x86 平台固件的事实标准。然而,随着硬件技术的发展,BIOS 的局限性日益凸显:16 位实模式、1 MB 地址空间限制、MBR 分区表(最大 2.2 TB 磁盘支持)、以及缺乏标准化的驱动接口。

Intel 在 1998 年启动了 Intel Boot Initiative 项目,后更名为 EFI(Extensible Firmware Interface)。2005 年,UEFI 论坛成立,将 EFI 标准化为 UEFI(Unified Extensible Firmware Interface)。如今 UEFI 已成为 PC、服务器、嵌入式系统的标准固件接口。

特性 传统 BIOS UEFI
处理器模式 16 位实模式 32/64 位保护模式与长模式
地址空间 1 MB 限制 可寻址全部系统内存
磁盘分区 MBR(最大 2.2 TB) GPT(最大 9.4 ZB)
驱动模型 Option ROM(16 位) UEFI 驱动(PE32+ 格式)
网络支持 无原生支持 UEFI 网络栈(IPv4/IPv6)
用户界面 文本菜单 图形界面(HII)
安全启动 无 Secure Boot
关键里程碑:UEFI 2.0(2006 年)引入了驱动模型与协议接口;UEFI 2.3.1(2011 年)增加了 Secure Boot;UEFI 2.8(2019 年)增加了 HTTP Boot 与 TCG2 协议增强。

1.1.2 UEFI 的架构分层

UEFI 固件采用分层架构,从底层硬件抽象到操作系统加载,每一层都有明确的职责与接口。

UEFI 固件分层架构 硬件层(CPU、芯片组、内存、外设) UEFI 固件核心 SEC → PEI → DXE → BDS → TSL → RT UEFI 驱动与服务层 Boot Services | Runtime Services | Protocol Interfaces UEFI 应用 / OS Loader 操作系统(Windows / Linux / macOS)
驱动开发者视角:UEFI 驱动主要运行在 DXE(Driver Execution Environment) 阶段,通过 Protocol 接口与固件核心和其他驱动交互。理解这一分层是开发稳定驱动的前提。

1.2 与传统 BIOS 的区别

1.2.1 核心差异对比

UEFI 并非 BIOS 的简单升级,而是一次彻底的架构重构。以下从驱动开发角度列出最关键的差异:

对比维度 传统 BIOS UEFI 对驱动开发的影响
驱动格式 Option ROM(x86 实模式代码) PE32+ 格式(与 OS 一致) 可使用标准链接器与调试工具
驱动接口 INT 10h/13h 等软件中断 Protocol 接口(C 语言结构体指针) 类型安全、可扩展、面向对象
内存管理 无统一内存分配机制 AllocatePages / AllocatePool 驱动可动态申请内存
设备枚举 固定地址扫描 ACPI / 设备路径协议 支持热插拔与复杂拓扑
语言 汇编为主 C 语言为主(EDK II 框架) 降低开发门槛,可移植性高
调试支持 无标准调试接口 UEFI Serial / GDB / USB 调试 支持源码级调试

1.2.2 驱动模型对比

传统 BIOS 的 Option ROM 是扁平的、无生命周期的代码块;UEFI 驱动则遵循严格的 驱动绑定协议(Driver Binding Protocol),包含 Supported()、Start()、Stop() 三个核心接口,实现了驱动的即插即用与动态管理。

UEFI 驱动绑定协议生命周期 安装驱动 DriverEntry() Supported() 检查设备是否支持 Start() 初始化设备与 I/O 运行 Stop() 卸载驱动 与传统 BIOS 的关键区别 BIOS Option ROM 无生命周期管理,UEFI 驱动可动态加载/卸载,支持多实例与热插拔
常见误区:UEFI 驱动不是简单的“BIOS 驱动移植”。由于运行模式、内存模型、中断机制的彻底改变,传统 BIOS 驱动代码无法直接在 UEFI 环境下运行,必须按照 UEFI 驱动模型重新设计。

1.3 UEFI 的启动流程

1.3.1 启动阶段总览

UEFI 固件启动过程分为七个阶段,每个阶段有明确的目标与输出。驱动开发者需要重点关注 PEI 和 DXE 阶段。

阶段 全称 主要任务 驱动加载时机
SEC Security 安全验证、CPU 初始化、临时栈建立 无驱动加载
PEI Pre-EFI Initialization 内存初始化、PEIM 模块执行 PEIM(早期驱动)
DXE Driver Execution Environment 设备枚举、协议注册、驱动加载 UEFI 驱动主要加载阶段
BDS Boot Device Selection 启动设备选择、Boot Manager 执行 可选驱动加载
TSL Transient System Load OS Loader 执行 驱动卸载准备
RT Runtime OS 运行时固件服务 Runtime 驱动保留
AL After Life 系统关机/重启 驱动终止

1.3.2 启动流程详细图示

UEFI 启动流程(七阶段) SEC:安全验证与 CPU 初始化 PEI:内存初始化与 PEIM 执行 DXE:设备枚举、协议注册、驱动加载 ← UEFI 驱动开发核心阶段 → BDS:启动设备选择与 Boot Manager TSL:OS Loader 执行 RT:运行时服务(ExitBootServices 后) AL:系统关机 / 重启

1.3.3 驱动开发关键阶段详解

PEI 阶段:此时内存尚未完全初始化,驱动以 PEIM(PEI Module) 形式运行,使用 PEI Services 接口。PEIM 通常用于早期硬件初始化(如内存控制器、芯片组配置)。

DXE 阶段:这是 UEFI 驱动开发的主战场。DXE 阶段具备完整的内存管理、事件机制、协议注册与发现功能。驱动通过 DXE Services 和 Boot Services 与固件交互。

驱动加载顺序:DXE 阶段驱动加载遵循依赖关系(DEPEX 段)。每个驱动声明其依赖的协议,固件调度器按拓扑顺序加载驱动,确保所有依赖满足后才执行 Supported() 和 Start()。

1.3.4 启动流程中的关键事件

事件名称 触发时机 对驱动的影响
ExitBootServices() OS Loader 接管前 Boot Services 终止,Runtime 驱动保留
SetVirtualAddressMap() OS 启用虚拟地址后 Runtime 驱动需转换指针
ResetSystem() 系统重启/关机 驱动需清理资源
开发建议:在 DXE 阶段开发的驱动,如果需要在 OS 运行时继续提供服务(如 ACPI 表、UEFI Runtime 变量),必须实现 Runtime 驱动 并正确处理虚拟地址转换。否则驱动仅在启动阶段有效。