1、课程导论与背景:为什么需要UEFI+ATF协同?系统启动流程全景图
1.1 一个老问题:系统启动到底有多复杂?
做固件这么多年,我经常被问到同一个问题:「系统启动不就是把电插上,然后按一下开机键吗?」
嗯,从用户角度看确实是这样。但从我们固件工程师的角度看,从按下电源键到操作系统跑起来,中间要经历的事情,比你想象的多得多。
我举个例子。你有一台ARM服务器,或者一台带安全启动的x86设备。电源键按下之后,CPU要初始化、内存要训练、外设要枚举、安全环境要建立、操作系统镜像要验证……每一步都可能出问题。而且,不同架构的启动方式还不一样。
x86有UEFI,ARM有ATF(ARM Trusted Firmware)。它们各自管各自的一亩三分地,但问题是——现代系统越来越复杂,这两者必须协同工作。我在一个项目中就遇到过,UEFI和ATF各自跑得挺好,但一对接就死机。查了三天,发现是两者对内存布局的理解不一致。
说白了,UEFI+ATF协同不是「锦上添花」,而是「不得不做」。
1.2 为什么需要UEFI+ATF协同?
先看两个架构各自的定位。
| 维度 | UEFI(x86/ARM通用) | ATF(ARM专用) |
|---|---|---|
| 核心职责 | 平台初始化、Boot Manager、OS加载 | 安全监控、PSCI电源管理、异常处理 |
| 运行特权级 | EL2(Hypervisor级)或EL1(OS级) | EL3(最高特权级,Secure Monitor) |
| 安全焦点 | Secure Boot、Measured Boot | TrustZone、安全启动链、运行时安全服务 |
| 启动阶段 | SEC → PEI → DXE → BDS → TSL → RT | BL1 → BL2 → BL31 → BL32 → BL33 |
你仔细看这张表,会发现一个关键问题:UEFI和ATF在启动流程上有重叠,但又不完全重合。
ATF的BL33阶段,通常就是加载UEFI固件。而UEFI的SEC阶段,又需要ATF提前把EL3环境搭好。这两者之间,存在一个「握手」的过程。
我个人的习惯是,把ATF看作「地基」,UEFI看作「房子」。地基没打好,房子盖得再漂亮也白搭。反过来,地基打好了,房子设计不合理,也住不舒坦。
核心矛盾:UEFI需要ATF提供安全服务(如PSCI、RME),ATF需要UEFI完成平台初始化。两者必须共享内存、中断、电源状态等资源。一旦信息不同步,系统就会在启动过程中「卡死」或「崩溃」。
1.3 系统启动流程全景图
下面这张图,是我自己画的一个全景流程。它把UEFI和ATF的启动阶段放在一起对比,你看完就能明白「协同」到底发生在哪里。
你看,ATF从BL1到BL33,UEFI从SEC到OS Loader。两者在BL33/SEC这个点交汇。但交汇不是简单的「你干完我干」,而是需要协商。
举个例子。ATF在BL31阶段注册了PSCI服务,UEFI在DXE阶段需要调用PSCI来开关CPU核心。怎么调?通过SMC指令。ATF在EL3捕获SMC异常,然后执行对应的PSCI函数。这个过程,就是协同。
一个小技巧:我在调试UEFI+ATF协同问题时,习惯先在ATF的BL31里加一个SMC日志,打印出所有来自UEFI的SMC调用。这样能快速判断是UEFI没发SMC,还是ATF没正确处理。
1.4 协同中的常见「坑」
说实话,UEFI+ATF协同的坑,我踩过不少。这里列几个典型的,你以后遇到了可以少走弯路。
- 内存布局冲突:ATF在EL3有自己的内存区域(如Trusted SRAM),UEFI在非安全世界也有自己的内存。两者如果对同一块物理地址的理解不一致,就会出问题。我曾经遇到过UEFI把ATF的代码段给覆盖了,结果系统一调用PSCI就崩溃。
- 中断路由混乱:ARM GIC(通用中断控制器)支持中断分组。安全中断要路由到EL3,非安全中断路由到EL1/EL2。如果UEFI配置GIC时不小心把安全中断也路由到了非安全世界,ATF就收不到关键中断了。
- PSCI版本不匹配:UEFI调用PSCI时,会检查版本。ATF实现的PSCI版本如果低于UEFI要求的版本,调用就会失败。我建议你在UEFI代码里加一个PSCI版本检查的日志,方便定位。
- 启动顺序依赖:有些平台要求ATF必须先完成某些初始化,UEFI才能开始工作。比如,ATF需要先配置好系统计数器,UEFI才能用它来计时。如果顺序搞反了,UEFI读到的计数器值就是错的。
特别注意:在ARMv8.4及以上架构中,RME(Realm Management Extension)引入了新的安全等级。ATF需要管理Realm世界,UEFI需要与之交互。这个协同比传统TrustZone更复杂。如果你在做新平台,一定要先确认ATF版本是否支持RME,以及UEFI是否适配了RME接口。
1.5 为什么选择UEFI+ATF?
你可能会问:「既然这么麻烦,为什么不用uboot+ATF?或者直接用UEFI跑在x86上?」
原因很简单:生态和标准化。
UEFI有成熟的驱动模型、协议栈、安全启动框架。ATF提供了ARM架构上最权威的EL3实现。两者结合,既能利用UEFI的丰富生态,又能发挥ARM的安全特性。
我个人的经验是,如果你在做ARM服务器、边缘计算设备或者高端嵌入式系统,UEFI+ATF几乎是唯一的选择。uboot虽然轻量,但在安全启动、ACPI支持、UEFI兼容性方面,差距还是明显的。
而且,现在很多芯片厂商(如NXP、TI、Rockchip)都在推UEFI+ATF方案。你学会了这个组合,以后换平台也能快速上手。
1.6 本章小结
这一章,我们聊了UEFI和ATF各自的定位,为什么需要协同,以及协同中常见的坑。核心就一句话:UEFI负责「功能」,ATF负责「安全」。两者必须紧密配合,系统才能稳定启动。