ATF源码结构分析:BL1/BL2/BL31/BL32/BL33各阶段作用
ATF(ARM Trusted Firmware)的源码结构,说白了就是一套分级启动的骨架。我刚接触ATF时,面对一堆BL开头的目录也懵过——BL1、BL2、BL31……这些到底谁先跑?谁管谁?
今天咱们就把这五个阶段拆开揉碎,讲清楚每个BL的职责、关键文件,以及Makefile是怎么把它们串起来的。
1. 整体启动流程:一张图看懂
先上我手绘的SVG框架图,把BL1到BL33的调用关系画清楚。你盯着这张图看三分钟,后面讲细节就不会迷路。
2. 各BL阶段详解
2.1 BL1 — 启动的起点
BL1是固化在芯片ROM里的代码,上电后CPU第一条指令就落在它身上。它做的事情很纯粹:初始化最基本的硬件(比如串口、DRAM控制器),然后从Flash里找到BL2镜像,加载到SRAM,最后跳过去。
关键目录与文件:
bl1/bl1_main.c— BL1主逻辑,包括异常向量表、平台初始化bl1/bl1_entrypoint.S— 汇编入口,设置栈指针、跳转到C代码plat/<平台>/bl1_plat_setup.c— 平台相关的初始化(比如时钟、电源)
2.2 BL2 — 可信启动的管家
BL2是可信启动链的核心。它负责验证并加载BL31、BL32、BL33的镜像。说白了,它就是个安全加载器。BL2运行在EL3,但很快会把控制权交给BL31。
关键目录与文件:
bl2/bl2_main.c— BL2主流程,调用平台接口加载镜像bl2/bl2_image_load.c— 镜像加载逻辑,支持FIP包解析plat/<平台>/bl2_plat_setup.c— 平台内存布局、存储设备初始化
2.3 BL31 — EL3的运行时守护者
BL31是ATF里最复杂的组件。它运行在EL3,提供运行时服务:PSCI(电源管理)、SMC(安全监控调用)处理、中断路由等。BL31一旦启动,就常驻内存,直到系统关机。
关键目录与文件:
bl31/bl31_main.c— BL31初始化入口,注册服务bl31/runtime_svc.c— 运行时服务框架,处理SMC请求services/std_svc/psci/— PSCI实现,CPU开关、挂起/恢复plat/<平台>/bl31_plat_setup.c— 平台中断控制器、GIC初始化
2.4 BL32 — 安全世界的可选组件
BL32是可选的安全OS,比如OP-TEE、Trusty。它运行在S-EL1,提供安全服务(密钥管理、安全存储)。如果不需要安全OS,BL32可以跳过,BL31直接加载BL33。
关键目录与文件:
bl32/bl32_main.c— BL32入口,初始化安全OSplat/<平台>/bl32_plat_setup.c— 安全内存、安全外设配置
2.5 BL33 — 非安全世界的启动加载器
BL33就是UEFI、Uboot或任何非安全侧启动加载器。它运行在EL2或EL1,负责加载操作系统。ATF对BL33的干预很少——跳过去后,BL33就独立运行了。
关键目录与文件:
bl33/bl33_main.c— BL33入口,设置EL2/EL1上下文plat/<平台>/bl33_plat_setup.c— 非安全内存、设备树传递
3. 关键目录与文件说明
ATF源码的目录结构很清晰,我整理了一张表,方便你对照查找:
| 目录/文件 | 作用 | 所属阶段 |
|---|---|---|
bl1/ |
BL1源码,包括入口、主逻辑、平台适配 | BL1 |
bl2/ |
BL2源码,镜像加载、校验、FIP解析 | BL2 |
bl31/ |
BL31源码,运行时服务、PSCI、SMC处理 | BL31 |
bl32/ |
BL32源码,安全OS入口 | BL32 |
bl33/ |
BL33入口,非安全侧启动加载器适配 | BL33 |
plat/ |
平台相关代码,每个平台一个子目录 | 所有阶段 |
include/ |
公共头文件,架构定义、接口声明 | 所有阶段 |
Makefile |
顶层构建文件,控制整个编译流程 | 构建系统 |
4. Makefile构建系统解析
ATF的Makefile体系,说实话,刚看时有点绕。它不像普通项目一个Makefile搞定,而是分层嵌套的。顶层Makefile调用各BL的Makefile,最终生成多个独立的镜像文件。
核心构建流程:
- 顶层Makefile解析配置(平台、调试等级、安全OS选择)
- 根据配置生成
build/<平台>/目录 - 依次编译BL1、BL2、BL31、BL32、BL33
- 调用
fiptool打包成FIP镜像
常用构建命令示例:
# 编译QEMU平台,debug模式
make PLAT=qemu DEBUG=1 all
# 编译FVP平台,带OP-TEE
make PLAT=fvp SPD=opteed all
# 只编译BL31
make PLAT=qemu BL31=1
# 清理
make PLAT=qemu clean
PLAT— 目标平台,比如qemu、fvp、zynqmpDEBUG— 0为release,1为debug(带符号表)SPD— 安全调度器,选择BL32(如opteed、trusty)LOG_LEVEL— 日志等级,40为INFO,50为VERBOSE
make PLAT=qemu,结果发现改动没生效——因为Makefile检测到BL2的.o文件没变化,跳过了重新编译。后来我养成习惯:改完代码先make clean再全量编译,或者用make PLAT=qemu BL2=1强制重编BL2。
5. 小结
ATF的源码结构,说白了就是五个BL + 一个Makefile。BL1是ROM里的硬汉,BL2是安全管家,BL31是EL3的常驻守护者,BL32是可选的秘密花园,BL33是通往OS的大门。Makefile则像一根线,把它们串成完整的启动链。
我个人建议:刚开始学ATF时,先盯着BL31看——它最复杂,也最核心。把PSCI和SMC处理搞明白,其他BL自然就通了。嗯,今天就到这儿,下回咱们聊BL31的PSCI实现细节。