3、ATF(ARM Trusted Firmware)基础:架构分层与各BL的作用
ATF,全称 ARM Trusted Firmware。说白了,它是 ARM 平台上的安全世界固件标准。我刚开始接触它的时候,觉得这玩意儿就是个黑盒。后来啃了几个月代码,才摸清楚它的门道。
ATF 的核心价值是什么?它定义了从芯片上电到操作系统启动之间,安全世界该怎么运转。你想想看,CPU 一上电,所有外设都还没初始化,内存都还没准备好,这时候谁来管?就是 ATF 的 BL1 来接手。
ATF 把整个启动过程分成了 5 个阶段:BL1、BL2、BL31、BL32、BL33。每个阶段都有明确的分工。我习惯把这 5 个阶段比作一个接力赛——每一棒跑一段,交接棒的时候不能出岔子。
核心要点:ATF 的 5 个 BL(Boot Loader)阶段,分别对应不同的权限等级和执行环境。理解它们的关系,是掌握 ARM 安全启动的关键。
3.1 ATF 架构分层概览
先看一张整体架构图。这张图我画了很多遍,每次给团队新人讲 ATF,我都会先让他们看这张图。
这张图里,从上到下是时间顺序。BL1 最先跑,BL33 最后跑。BL31 和 BL32 是并行启动的,它们俩一个管运行时服务,一个管安全操作系统。
3.2 BL1:Boot ROM,一切的开端
BL1 是芯片上电后执行的第一段代码。它固化在芯片内部的 ROM 里,出厂就写死了,你改不了。我遇到过有人想修改 BL1 来修复 bug,结果发现 ROM 是只读的——只能通过芯片改版来解决。
BL1 的任务很简单:
- 初始化最基本的硬件(时钟、栈、部分外设)
- 从存储介质(比如 SPI Flash、eMMC)加载 BL2 到 SRAM
- 验证 BL2 的签名(如果开启了安全启动)
- 跳转到 BL2 的入口
经验之谈:BL1 的代码量通常很小,几千行汇编加少量 C。因为 ROM 空间有限,而且运行在 SRAM 里,不能做太复杂的事情。我见过有些芯片的 BL1 只有 32KB 空间,写代码时得精打细算。
3.3 BL2:可信启动固件,承上启下
BL2 是第一个运行在 DRAM 初始化之后的阶段。它由 BL1 加载到 SRAM 或 DRAM 中执行。BL2 的权限等级是安全世界 EL1。
BL2 的核心职责:
- 初始化更复杂的硬件(比如 DDR 内存控制器)
- 从存储介质加载 BL31、BL32、BL33 的镜像
- 验证这些镜像的完整性(哈希校验 + 签名验证)
- 构建并传递启动信息给后续阶段
我记得有一次调试一个启动失败的问题,发现 BL2 加载 BL31 时,因为 DDR 时序没配好,导致数据读出来全是错的。折腾了两天才定位到是 DDR 初始化参数的问题。嗯,这里要注意:BL2 里的 DDR 初始化代码,一定要仔细核对芯片手册。
3.4 BL31:EL3 运行时固件,安全世界的管家
BL31 是 ATF 里最核心的组件之一。它运行在安全世界 EL3,是最高权限等级。BL31 一旦启动,就常驻内存,不会退出。
BL31 提供哪些服务?
- SMC 处理:非安全世界通过 SMC 指令调用安全服务,BL31 负责路由
- PSCI:电源状态管理,比如 CPU 休眠、唤醒、关核
- 中断管理:安全中断和非安全中断的路由与分发
- 上下文切换:在安全世界和非安全世界之间切换时,保存/恢复寄存器
注意:BL31 的代码质量直接影响系统稳定性。我见过因为 BL31 里一个中断处理没写好,导致系统随机死锁的案例。调试这种问题非常痛苦,因为 EL3 的异常很难抓到。
3.5 BL32:可信操作系统,安全应用的运行环境
BL32 是一个可选组件。它运行在安全世界 EL1,提供一个安全操作系统环境。最典型的实现是 OP-TEE(Open Portable Trusted Execution Environment)。
BL32 能做什么?
- 运行安全应用(Trusted Applications,TA)
- 提供安全存储、加密服务
- 管理安全外设(比如指纹传感器、安全键盘)
我参与过一个项目,需要在 BL32 里跑一个自定义的 TA,用来做设备唯一密钥的生成和管理。当时踩了不少坑——BL32 的调试手段非常有限,只能靠串口打印日志。后来我习惯在 BL32 里加一个专门的调试命令接口,方便排查问题。
3.6 BL33:非安全固件,操作系统的入口
BL33 是最后一个阶段。它运行在非安全世界,通常是 EL2(虚拟化)或 EL1(非虚拟化)。BL33 就是我们熟悉的 UEFI 或者 U-Boot。
BL33 的任务:
- 初始化非安全世界的硬件(比如网卡、存储控制器)
- 加载操作系统内核(Linux、Windows 等)
- 通过 SMC 调用 BL31 提供的服务(比如 PSCI 来管理 CPU)
这里有个关键点:BL33 不能直接访问安全世界的资源。它必须通过 SMC 指令,让 BL31 代为执行。这就是 ARM 的安全隔离机制。
3.7 各 BL 阶段对比
为了方便记忆,我把 5 个 BL 的关键属性整理成了一张表。这张表我经常贴在工位上,写代码时扫一眼就能想起来。
| 阶段 | 权限等级 | 执行位置 | 主要功能 | 是否可选 |
|---|---|---|---|---|
| BL1 | EL3 (安全) | ROM + SRAM | 硬件初始化,加载 BL2 | 必选 |
| BL2 | EL1 (安全) | SRAM/DRAM | 加载并验证后续镜像 | 必选 |
| BL31 | EL3 (安全) | DRAM (常驻) | 运行时服务,SMC/PSCI | 必选 |
| BL32 | EL1 (安全) | DRAM | 可信操作系统 (如 OP-TEE) | 可选 |
| BL33 | EL2/EL1 (非安全) | DRAM | UEFI/U-Boot,加载 OS | 必选 |
总结一下:ATF 的 5 个 BL 阶段,从 BL1 到 BL33,权限逐级降低,功能越来越复杂。BL1 和 BL2 负责安全启动,BL31 提供运行时服务,BL32 运行安全应用,BL33 最终引导操作系统。每个阶段都依赖前一个阶段完成初始化,环环相扣。
我个人觉得,理解 ATF 架构最好的方法,就是实际编译一次 ATF 源码,然后在 QEMU 上跑一遍。看着串口日志里 BL1、BL2、BL31 依次打印信息,那种感觉比看任何文档都直观。