3. 启动流程总览:从 ROM Code 到 TEE 内核的完整启动链路

这一章,我们来聊聊 TEE 的整个启动过程。说白了,就是设备上电后,从芯片内部固化的第一行代码开始,一直到 TEE 内核跑起来,这中间到底发生了什么。

我刚开始接触 TEE 时,觉得这东西就是个黑盒。后来调过几次启动日志,才慢慢摸清门道。你会发现,整个启动链路其实被分成了几个清晰的阶段。每个阶段都有明确的任务,也有各自的坑。

3.1 启动链路全景图

先给你一张总图,把整个流程串起来。这样你心里有个谱,后面再细看每个阶段时,就不会迷路。

核心要点:TEE 的启动是一个「逐级验证、逐级加载」的过程。每一级只信任上一级,上一级验证通过后,才把控制权交给下一级。这就是所谓的「信任链」。

TEE 启动链路全景图 TEE 启动链路全景图 ROM Code 芯片固化,不可修改 BL1 BootROM 加载 BL2 可信固件加载 BL31 EL3 Runtime OP-TEE OS TEE 内核 Normal World U-Boot / Linux 💡 关键路径说明: ROM Code → BL1 → BL2 → BL31 → OP-TEE OS(安全世界) BL2 同时负责加载 Normal World 的 U-Boot/Linux(非安全世界)

3.2 关键阶段划分

整个启动链路,按 ARM Trusted Firmware (ATF) 的规范,被划分为几个 Boot Loader 阶段。每个阶段都有编号:BL1、BL2、BL31。OP-TEE 作为 TEE OS,在 BL31 之后加载。

阶段 名称 运行位置 主要职责
ROM Code 芯片固件 片上 ROM 初始化硬件,加载 BL1
BL1 BootROM SRAM 验证 BL2,加载 BL2
BL2 可信固件 DRAM 验证 BL31、OP-TEE、U-Boot
BL31 EL3 Runtime DRAM 提供 Secure Monitor,切换世界
OP-TEE TEE OS 安全 DRAM 提供安全服务,运行 TA

我的经验:调试启动问题时,我习惯先看日志里有没有打印 BL2 的版本号。如果连 BL2 都没跑起来,那问题大概率出在 BL1 或更早的硬件初始化上。别一上来就盯着 OP-TEE 的日志看,那会绕弯路。

3.3 逐级详解

3.3.1 ROM Code

这是芯片出厂时固化在 ROM 里的代码。你改不了它,也删不掉它。上电后,CPU 的第一条指令就从这里开始。

ROM Code 做的事很简单:

  • 初始化最基本的硬件(时钟、SRAM、看门狗)
  • 从 Boot Device(比如 eMMC、NAND Flash)读取 BL1
  • 把 BL1 加载到 SRAM 中,然后跳转过去

嗯,这里要注意。ROM Code 本身不做任何安全验证。它只是机械地把 BL1 加载进来。真正的信任链,从 BL1 才开始。

3.3.2 BL1

BL1 是第一个可被信任的代码。它运行在 SRAM 里,空间非常有限。我见过有些芯片的 SRAM 只有 64KB,BL1 得精打细算才能塞进去。

BL1 的核心任务:

  1. 验证 BL2 的签名——用公钥检查 BL2 的镜像是否被篡改过
  2. 加载 BL2——把 BL2 从 Flash 复制到 DRAM 中
  3. 配置安全内存——设置 TrustZone 的内存保护

我曾经踩过的坑:有一次 BL1 总是验证 BL2 失败,日志里报签名错误。查了半天,发现是 Flash 里烧录的 BL2 镜像和 BL1 里硬编码的公钥不匹配。说白了,就是固件版本没对齐。从那以后,我每次烧录都会 double-check 公钥哈希值。

3.3.3 BL2

BL2 是可信固件的核心。它运行在 DRAM 里,空间比 BL1 宽裕多了。BL2 负责加载和验证后续所有的镜像。

BL2 做的事:

  • 验证 BL31(EL3 Runtime)的签名
  • 验证 OP-TEE OS 的签名
  • 验证 U-Boot(或其它 Bootloader)的签名
  • 配置安全和非安全世界的内存布局

你想想看,BL2 就像个安检员。所有要进入系统的代码,都得经过它的检查。它说不行,那就真不行。

3.3.4 BL31

BL31 是运行在 EL3(异常级别 3)的 Runtime 固件。EL3 是 ARM 架构里权限最高的级别,比安全世界和非安全世界都高。

BL31 的主要职责:

  • 提供 Secure Monitor Call (SMC) 处理
  • 负责安全世界和非安全世界之间的切换
  • 管理电源状态(CPU 休眠、唤醒等)

说白了,BL31 就是个「看门人」。非安全世界想调用安全服务,得通过 SMC 指令先找 BL31,BL31 再转发给 OP-TEE。

3.3.5 OP-TEE OS

OP-TEE 是 TEE 的内核。它运行在安全世界里,提供安全服务。OP-TEE 启动后,会初始化安全内存、加载可信应用(TA)、注册 SMC 处理函数。

OP-TEE 启动日志里,你会看到类似这样的输出:

I/TC: OP-TEE version: 3.22.0
I/TC: Initialized
I/TC: SMC handler registered
I/TC: TA: supplicant ready

看到这三行,基本可以确认 OP-TEE 已经跑起来了。

3.4 信任链的传递

整个启动过程,核心就是信任链的传递。每一级都验证下一级的签名,确保没有被篡改。

信任链的传递路径:

  1. ROM Code(硬件信任根)→ 加载 BL1
  2. BL1(验证 BL2 签名)→ 加载 BL2
  3. BL2(验证 BL31、OP-TEE、U-Boot 签名)→ 加载各镜像
  4. BL31 → 启动 OP-TEE 和 Normal World

关键点:信任链的根是 ROM Code。ROM Code 是硬件固化的,无法被篡改。只要 ROM Code 是安全的,整个链条就是安全的。这就是「信任根」的概念。

3.5 启动日志中的关键线索

调试启动问题时,日志是你的第一手资料。我总结了几条关键线索,你可以对照着看:

日志内容 含义 常见问题
NOTICE: BL1: v2.8 BL1 启动成功 如果没看到,检查硬件或 Flash
ERROR: BL2: image auth failed BL2 验证镜像签名失败 固件版本不匹配,或镜像损坏
I/TC: OP-TEE version: 3.22.0 OP-TEE 启动成功 如果没看到,检查 BL2 是否加载了 OP-TEE
U-Boot: Starting kernel Normal World 启动 如果卡在这里,检查设备树配置

我的习惯:每次拿到新的开发板,我会先做一次「干净启动」——把日志全部抓下来,逐行对照。这样后面出了问题,才知道哪些是正常的,哪些是异常的。别偷懒,这个习惯能帮你省很多时间。

3.6 小结

这一章我们走完了 TEE 的完整启动链路。从 ROM Code 到 OP-TEE,每一级都有明确的分工。记住信任链的传递方式,这是理解 TEE 安全性的基础。