1. UEFI基础概念:UEFI与BIOS的区别、UEFI启动流程、UEFI固件架构概述
大家好,我是你们的讲师。今天咱们来聊聊UEFI安全启动联调实战的第一章——基础概念。说实话,我见过太多工程师一上来就扎进代码里,结果连UEFI和BIOS到底差在哪都没搞明白。嗯,这章咱们就把地基打牢。
1.1 UEFI与BIOS:到底有什么区别?
先问大家一个问题:你电脑开机时,屏幕上闪过的那几行白字,是BIOS还是UEFI?
很多人觉得这俩是一回事。其实不然。我刚开始做固件时也这么认为,直到有一次调试一块新主板,死活进不去设置界面,才发现BIOS和UEFI完全是两套东西。
咱们直接上对比表,一目了然:
| 对比项 | 传统BIOS | UEFI |
|---|---|---|
| 运行模式 | 16位实模式 | 32位/64位保护模式 |
| 寻址能力 | 1MB限制 | 理论无限制 |
| 磁盘分区 | MBR(主引导记录) | GPT(GUID分区表) |
| 启动速度 | 较慢(逐项检测) | 较快(并行初始化) |
| 用户界面 | 文本菜单,键盘操作 | 图形界面,支持鼠标 |
| 扩展性 | 差,依赖特定硬件 | 好,支持驱动模块 |
| 安全启动 | 不支持 | 原生支持 |
说白了,BIOS是上世纪80年代的老古董,UEFI是它的现代化替代品。我个人习惯把BIOS比作「老式电话交换机」,而UEFI就是「现代IP网络」——功能更强、更灵活、也更安全。
1.2 UEFI启动流程:从按下电源键到操作系统
你按下电源键的那一瞬间,UEFI到底干了什么?我拆解给你看。
整个流程大致分七个阶段,我习惯叫它「七步走」:
- SEC(安全验证)阶段:CPU复位,执行第一条指令。这里做最基础的硬件自检和安全验证。
- PEI(EFI前期初始化)阶段:初始化内存控制器,把内存时序调好。嗯,这一步出问题最常见——我遇到过内存颗粒虚焊导致PEI卡死的案例。
- DXE(驱动执行环境)阶段:加载各种驱动——磁盘、网卡、显卡等。这是最复杂的阶段,也是安全启动的关键战场。
- BDS(启动设备选择)阶段:扫描启动设备,按优先级选择从哪个盘启动。
- TSL(临时系统加载)阶段:加载操作系统引导器(比如Windows的bootmgfw.efi)。
- RT(运行时)阶段:把控制权交给操作系统,UEFI进入后台服务模式。
- AL(高级配置)阶段:操作系统接管后,UEFI提供运行时服务接口。
为了让你更直观地理解,我画了一张流程图:
1.3 UEFI固件架构概述
UEFI固件不是一个大而全的「铁板一块」,它更像一个模块化的操作系统。你想想看,它要管理内存、加载驱动、提供界面、还要跟操作系统交互——这复杂度不亚于一个小型OS。
我习惯把UEFI固件架构分成三层:
- 底层硬件抽象层:直接跟CPU、芯片组、内存控制器打交道。这部分代码通常由芯片厂商提供,我们一般不动它。
- 中间服务层:包括启动服务(Boot Services)和运行时服务(Runtime Services)。启动服务在操作系统接管前可用,运行时服务则一直可用。
- 上层应用层:包括UEFI Shell、设置界面、网络协议栈等。这部分是我们做定制化开发的主要战场。
来看一个典型的UEFI固件结构代码片段——这是我在项目中常用的一个模块初始化框架:
// UEFI驱动入口点示例
EFI_STATUS
EFIAPI
MyDriverEntryPoint (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
// 1. 获取启动服务表
// 这一步很关键,所有系统服务都通过这个表访问
Status = gBS->LocateProtocol (
&gEfiSimpleFileSystemProtocolGuid,
NULL,
(VOID**)&gFileSystem
);
if (EFI_ERROR (Status)) {
// 我遇到过文件系统协议找不到的情况
// 通常是DXE阶段驱动加载顺序问题
return Status;
}
// 2. 注册协议接口
Status = gBS->InstallMultipleProtocolInterfaces (
&ImageHandle,
&gEfiMyCustomProtocolGuid,
&mMyCustomProtocol,
NULL
);
ASSERT_EFI_ERROR (Status);
// 3. 注册事件回调(比如定时器事件)
Status = gBS->CreateEvent (
EVT_TIMER | EVT_NOTIFY_SIGNAL,
TPL_CALLBACK,
MyTimerCallback,
NULL,
&mTimerEvent
);
if (!EFI_ERROR (Status)) {
gBS->SetTimer (mTimerEvent, TimerPeriodic, 10000000); // 1秒周期
}
return EFI_SUCCESS;
}
gBS 是全局的Boot Services指针。千万别在RT阶段(操作系统接管后)还调用Boot Services函数——那会导致系统崩溃。我见过有人把 gBS->AllocatePool 放在运行时服务里调用,结果蓝屏了。
说到UEFI固件架构,还有一个概念必须提——Protocol(协议)。这是UEFI里最核心的通信机制。说白了,就是「你提供接口,我调用接口」。每个驱动都注册一个或多个Protocol,其他驱动通过GUID找到它并调用。
举个例子:你想读写硬盘,不需要知道硬盘是SATA还是NVMe,只需要找到 gEfiBlockIoProtocolGuid 这个Protocol,调用它的 ReadBlocks() 函数就行。这就是UEFI的抽象能力。
好了,这一章的基础概念就讲到这里。记住:UEFI不是BIOS的升级版,它是完全不同的架构。下一章我们会深入安全启动的核心——签名验证机制。到时候我会带大家手撕一个实际的签名验证流程。
可可精品资料库