2. ATF启动流程详解:从BL1到BL31的完整启动链路与各阶段职责

ARM Trusted Firmware (ATF) 是嵌入式Linux快速启动的基石。本章将深入剖析从BL1到BL31的完整启动链路,明确每个启动阶段(Boot Level)的核心职责、数据流与切换条件。理解这一链路是后续进行启动优化、裁剪与测量时间的关键前提。

2.1 ATF启动阶段总览

ATF将安全世界的启动划分为四个连续的阶段:BL1、BL2、BL31,以及可选的BL32(Trusted OS)。每个阶段运行在不同的异常级别(Exception Level),拥有独立的代码段、栈空间和MMU配置。下表总结了各阶段的核心属性:

阶段 异常级别 物理存储位置 核心职责 执行后跳转目标
BL1 EL3 ROM (BootROM) 最早期初始化、平台配置、加载BL2 BL2入口
BL2 S-EL1 Flash / eMMC 加载BL31、BL32、BL33镜像,构建内存布局 BL31入口
BL31 EL3 DRAM 运行时服务、中断管理、PSCI、安全监控 BL32 / BL33入口
BL32 (可选) S-EL1 DRAM 可信操作系统(如OP-TEE) BL33入口
BL33 EL2 / EL1 DRAM 非安全世界引导程序(如U-Boot、UEFI) OS内核
关键概念: BL1是唯一固化在ROM中的阶段,不可修改。后续所有阶段(BL2、BL31、BL32、BL33)均存储在非易失性存储器(Flash/eMMC)中,由前一个阶段加载到DRAM后执行。这种设计使得固件更新只需替换Flash中的镜像,无需更换硬件。

2.2 BL1:ROM固件与最早期初始化

BL1是系统上电或复位后执行的第一段代码,通常存储在芯片内部的BootROM中。其执行环境极为受限:无DRAM、无栈、无MMU。BL1必须在极小的SRAM或Cache-as-RAM中完成初始化。

BL1核心流程

  1. 架构初始化: 设置异常向量表、配置系统控制寄存器(SCR_EL3、SCTLR_EL3)、初始化通用计时器。
  2. 平台初始化: 配置UART(早期调试输出)、时钟、电源管理单元(PMU)基础寄存器。
  3. 加载BL2: 从Flash指定偏移读取BL2镜像,验证其签名(如果使能Trusted Board Boot),然后拷贝到SRAM或预先保留的DRAM区域。
  4. 跳转: 清理缓存、设置BL2的入口参数(如平台ID、内存信息),执行ERET切换到BL2。
优化关注点: BL1的执行时间直接决定了系统从上电到可见第一行日志的延迟。常见优化包括:减少UART轮询等待、使用硬件加速器进行镜像校验、最小化SRAM初始化步骤。
BL1启动流程图 上电 / 复位 架构初始化 (异常向量 / 系统寄存器) 平台初始化 (UART / 时钟 / PMU) 加载 & 验证 BL2 (Flash → SRAM) 跳转 BL2 执行环境:ROM 无DRAM / 无MMU

2.3 BL2:安全世界加载器

BL2运行在安全-EL1(S-EL1),拥有比BL1更丰富的执行环境。此时DRAM通常已经初始化完毕,BL2可以将后续镜像加载到DRAM中。BL2是ATF启动链中唯一负责“加载”其他所有镜像的阶段。

BL2核心职责

  • 解析FIP(Firmware Image Package): 从Flash读取FIP表,定位BL31、BL32、BL33镜像的偏移与大小。
  • 认证镜像: 如果使能TBBR(Trusted Board Boot Requirements),使用公钥验证每个镜像的数字签名。
  • 构建内存布局: 为BL31、BL32、BL33分配DRAM区域,确保非安全世界无法访问安全内存。
  • 传递平台参数: 将平台配置信息(如内存大小、GIC基址)通过寄存器或共享内存传递给BL31。
常见陷阱: BL2阶段的镜像加载顺序至关重要。如果BL31的基地址与BL32的栈区域重叠,会导致运行时数据损坏。务必检查平台内存映射表(Memory Map Table)中的地址区间是否互斥。

2.4 BL31:EL3运行时固件

BL31是ATF启动链中最重要的阶段,它驻留在EL3,负责管理安全世界与非安全世界之间的上下文切换。一旦BL31初始化完成,它将不再主动执行代码,而是作为“安全监控器”等待异常(SMC、IRQ、FIQ)触发。

BL31初始化流程

步骤 操作 说明
1 设置EL3运行时栈 为异常处理提供独立的栈空间
2 初始化中断控制器(GIC) 配置安全中断与组0/组1路由
3 注册运行时服务 PSCI、SIP(SiP Service)、TOS(Trusted OS Service)
4 配置系统计数器 确保非安全世界可读取安全计数器
5 跳转到BL32或BL33 根据配置选择进入Trusted OS或直接启动非安全引导程序
BL31运行时服务架构图 BL31 运行时固件 (EL3 安全监控器) PSCI 服务 SIP 服务 TOS 服务 非安全世界 安全世界 (TOS) SMC 异常入口 核心机制:通过SMC指令触发EL3异常 BL31根据服务ID分发到对应处理函数

2.5 BL32与BL33:安全OS与非安全引导

BL32(可选)是可信操作系统,如OP-TEE、Trusty。它运行在S-EL1,提供安全服务(如密钥管理、安全存储)。BL33则是非安全世界的引导程序,通常是U-Boot或UEFI固件,运行在EL2(虚拟化)或EL1(非虚拟化)。

启动链切换时序

BL1 → BL2 → BL31 → BL32 → BL33 → Linux Kernel
                ↓
           (可选) 直接跳转 BL33

如果系统不需要Trusted OS,BL31在完成初始化后直接跳转到BL33。此时BL31仍然驻留在EL3,为后续的PSCI调用(如CPU_OFF、SYSTEM_SUSPEND)提供服务。

快速启动优化点: 在BL31阶段,可以提前初始化非安全世界的GIC和定时器,减少BL33的初始化时间。此外,如果BL33是U-Boot,可以通过ATF传递“快速启动标志”跳过U-Boot中的硬件重枚举。

2.6 启动链路中的关键数据结构

ATF使用entry_point_info结构体在阶段间传递参数。该结构体包含入口地址、SPSR(Saved Program Status Register)、以及平台定义的上下文信息。

/* 摘自 include/lib/psci/psci.h */
typedef struct entry_point_info {
    uintptr_t pc;           /* 入口地址 */
    uint32_t spsr;          /* 目标异常级别 */
    uint32_t args[4];       /* 通用参数寄存器 */
    uint32_t context_id;    /* 上下文标识 */
} entry_point_info_t;

在BL2跳转到BL31时,会将BL31的entry_point_info写入寄存器X0~X3。BL31解析这些参数后,再为BL32或BL33构造新的entry_point_info。

2.7 本章小结

  • ATF启动链严格遵循BL1→BL2→BL31→(BL32)→BL33的顺序,每个阶段运行在特定的异常级别。
  • BL1是ROM固件,负责最早期初始化和加载BL2;BL2是加载器,负责加载所有后续镜像;BL31是EL3运行时固件,提供安全监控服务。
  • BL32(Trusted OS)为可选阶段,BL33是非安全引导程序,最终启动Linux内核。
  • 理解每个阶段的职责与数据传递方式,是进行启动时间测量与优化的基础。