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,我都会先让他们看这张图。

ATF 启动架构分层图 BL1 (Boot ROM) 安全世界 EL3,固化在芯片 ROM 中,不可修改 BL2 (Trusted Boot Firmware) 安全世界 EL1,加载并验证后续镜像 BL31 (EL3 Runtime Firmware) 安全世界 EL3,运行时服务 BL32 (Trusted OS) 安全世界 EL1,如 OP-TEE BL33 (Non-Trusted Firmware) 非安全世界 EL2/EL1,如 UEFI、U-Boot 说明 BL1 → BL2 → BL31/BL32 → BL33,严格按顺序执行,不可跳级

这张图里,从上到下是时间顺序。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 依次打印信息,那种感觉比看任何文档都直观。