2. ATF启动流程详解:BL1、BL2、BL31、BL32、BL33的加载与执行、SP_MIN与TSPD
好,我们直接进入正题。ATF的启动流程,说白了就是ARM Trusted Firmware从复位到交出控制权给操作系统的一整套动作。很多初学者一上来就被BL1、BL2、BL31这些缩写搞晕了,其实没那么复杂。你把它想象成一个接力赛——每个阶段跑一段,跑完了把棒子交给下一棒。
我个人习惯把ATF启动分成五个阶段:BL1、BL2、BL31、BL32、BL33。每个阶段都有明确的职责和生命周期。下面我带你一个一个拆开看。
2.1 整体启动流程概览
先看一张总图,把整个流程串起来。这张图我画了很多次,每次给团队新人讲启动流程都会先贴出来。
嗯,这里要注意:BL1和BL2在完成使命后就不再运行了,它们的内存也会被回收。真正常驻的是BL31和BL32。BL33启动后,整个系统就进入了正常世界。
2.2 BL1:第一级启动加载器
BL1是系统上电后执行的第一段代码。它存储在片上ROM里,出厂就烧好了,你改不了。这也是整个信任链的根。
BL1的核心职责:
- 初始化最基本的硬件(时钟、串口、DRAM控制器)
- 从Flash/MMC加载BL2到SRAM
- 验证BL2的签名(如果使能了认证链)
- 跳转到BL2入口
我在项目中遇到过一个问题:某款芯片的BL1在DRAM初始化时踩了一个硬件坑——它的DRAM控制器需要先做一次dummy访问才能稳定。查了两天才定位到,最后在BL1的初始化序列里加了一个伪读取搞定。这种问题在芯片勘误表里经常有,但很少有人会提前看。
2.3 BL2:可信启动加载器
BL2运行在SRAM中,由BL1加载并验证。它的任务很明确:把剩下的镜像都准备好。
BL2的工作流程:
- 从存储设备读取镜像描述信息(FIP格式)
- 解析镜像列表,找到BL31、BL32、BL33的位置
- 逐个加载到内存,验证签名
- 配置内存布局,确保各镜像不重叠
- 跳转到BL31入口
你想想看,BL2其实就是一个微型的bootloader。它不负责运行操作系统,只负责把东西搬到该放的位置。搬完了,它的使命就结束了。
2.4 BL31:EL3运行时固件
BL31是ATF的核心。它运行在EL3,是系统里权限最高的软件。一旦BL31启动,它就不会退出了——它会一直驻留,处理各种安全相关的请求。
BL31的主要功能:
| 功能模块 | 说明 |
|---|---|
| SMC处理 | 接收来自正常世界和安全世界的SMC调用,路由到对应处理函数 |
| PSCI | 电源状态管理,包括CPU开关、挂起、系统重启等 |
| 中断管理 | 配置GIC,处理安全中断和普通中断的路由 |
| TSPD | Trusted Service Provider Dispatcher,负责与BL32通信 |
这里要重点说一下TSPD。它是BL31里的一个模块,专门用来对接BL32(也就是TEE)。TSPD做的事情说白了就是:当正常世界想调用TEE的服务时,它负责把SMC请求转发给BL32,再把结果返回给正常世界。
2.5 BL32:安全世界OS(TEE)
BL32就是我们课程的主角之一——OP-TEE。它运行在安全世界,提供安全服务。
BL32的加载方式:
- BL2将BL32镜像加载到安全DRAM
- BL31通过TSPD初始化BL32
- BL32初始化完成后,进入等待状态
- 当有SMC请求时,BL32被唤醒执行对应服务
我记得第一次调OP-TEE时,发现BL32启动后马上就panic了。查了半天,原来是安全DRAM的地址配置错了——BL2把镜像放到了非安全区域,BL31一跳过去就访问违例。这种问题在移植新平台时特别常见,一定要仔细核对内存地址映射。
2.6 BL33:非安全世界Bootloader
BL33就是正常世界的bootloader,通常是U-Boot或者EDK2。它运行在EL2或EL1,负责加载操作系统内核。
BL31在完成所有初始化后,会通过一条SMC指令将控制权交给BL33。从这一刻起,系统就进入了正常世界。但BL31并没有闲着——它还在EL3等着,随时准备处理来自正常世界的SMC请求。
2.7 SP_MIN与TSPD
这两个概念容易混淆,我单独拿出来讲。
SP_MIN 是ATF提供的一个最小化安全分区管理器。它适用于不需要完整TEE的场景。说白了,如果你只需要PSCI和基本的安全服务,不需要跑OP-TEE,那SP_MIN就够了。它体积小,启动快,但功能也有限。
TSPD 是BL31里的一个调度模块,专门用于对接TEE。它实现了以下功能:
- 初始化TEE(BL32)
- 转发SMC请求到TEE
- 管理TEE的上下文切换
- 处理TEE返回的结果
两者的选择很简单:用OP-TEE就选TSPD,不用就选SP_MIN。我在一个低功耗IoT项目里用过SP_MIN,因为那个芯片只有256KB SRAM,跑OP-TEE太勉强了。SP_MIN加上PSCI,刚好够用。
- BL1 → BL2 → BL31 → (BL32) → BL33,这是标准启动链
- BL31是常驻EL3的运行时,负责SMC、PSCI、中断路由
- TSPD是BL31与BL32之间的桥梁
- SP_MIN是TSPD的轻量替代方案,适用于无TEE场景
好了,这一章的内容就到这里。启动流程是ATF的基础,后面的章节我们会深入每个阶段的代码实现。你先把这张图印在脑子里,后面写代码时就知道自己在哪个阶段了。