4、BL2阶段日志解读:可信启动流程、FIP镜像解析、SCP_BL2/BL31/BL32镜像加载
BL2阶段,说白了就是ATF的“信任根”落地的地方。我刚开始接触ATF时,总觉得BL1才是起点,后来才发现——BL2才是真正建立信任链的关键环节。它负责验证所有后续镜像的合法性,然后才敢把它们加载到内存里。
这一章,我们重点看三件事:可信启动流程怎么走、FIP镜像怎么解析、以及SCP_BL2/BL31/BL32这三个镜像的加载细节。日志里每一行输出,背后都对应着硬件状态和软件逻辑的交互。
4.1 可信启动流程:信任链是怎么建立的?
ARM平台的可信启动,核心思想是“逐级验证”。BL1验证BL2,BL2验证后续所有镜像。这个链条一旦断了,系统就不敢往下走。
我遇到过一个问题:某款芯片在量产时,BL2日志里突然出现Authentication failed。查了半天,发现是证书签名工具链版本不一致导致的。嗯,这种坑踩过一次就记住了。
典型的可信启动流程如下:
- BL1加载BL2:从BootROM读取BL2镜像,验证其数字签名。
- BL2初始化平台:设置DDR、时钟、中断控制器等。
- BL2解析FIP:从Flash中读取FIP镜像,提取各个组件的证书和镜像。
- BL2验证SCP_BL2:使用公钥验证SCP_BL2的签名。
- BL2验证BL31:同样走证书链验证。
- BL2验证BL32:如果启用了TEE,这一步必须过。
- BL2跳转到BL31:所有验证通过后,交出控制权。
关键点:BL2的验证是强制性的。如果任何一个镜像验证失败,系统会直接挂死或进入错误处理流程。日志里如果看到ERROR或PANIC,基本就是这里出了问题。
下面这张图,是我自己画的可信启动流程。你看一眼,应该就能理解整个链条是怎么串起来的。
4.2 FIP镜像解析:BL2怎么找到各个组件?
FIP(Firmware Image Package)是ATF用来打包多个镜像的文件格式。BL2启动时,会从Flash的固定偏移读取FIP头部,然后根据头部信息找到每个子镜像的位置。
FIP的结构其实不复杂。我拆开看过很多次,核心就三部分:
- 头部:包含魔数、版本、镜像数量。
- 目录表:每个条目描述一个子镜像的UUID、偏移、大小。
- 镜像数据:按目录表顺序排列的二进制数据。
日志里常见的FIP相关输出长这样:
INFO: Loading image 'scp_bl2' from FIP at 0x1000
INFO: Image 'scp_bl2': offset 0x2000, size 0x8000
INFO: Authentication of 'scp_bl2' passed
INFO: Loading image 'bl31' from FIP at 0x1000
INFO: Image 'bl31': offset 0xA000, size 0x10000
INFO: Authentication of 'bl31' passed
INFO: Loading image 'bl32' from FIP at 0x1000
INFO: Image 'bl32': offset 0x1A000, size 0x20000
INFO: Authentication of 'bl32' passed
你看,每一行都告诉你:从FIP的哪个基地址加载、镜像在FIP内的偏移、大小、以及验证结果。如果某个镜像加载失败,日志里会直接报ERROR,比如:
ERROR: Failed to load image 'bl32' from FIP
ERROR: Image 'bl32' not found in FIP table
遇到这种错误,我一般先检查FIP镜像是否完整。用fiptool可以查看FIP内容:
fiptool info fip.bin
输出会列出所有子镜像的UUID和大小。如果某个镜像缺失,那就是打包时漏了。
小技巧:FIP的魔数是0xD0B5B0A2(小端序)。如果你在二进制里看到这个值,基本就能确认是FIP头部。我经常用hexdump直接看Flash内容来验证。
4.3 SCP_BL2镜像加载:系统控制处理器的固件
SCP_BL2是给SCP(System Control Processor)用的固件。SCP负责电源管理、时钟控制等底层硬件操作。BL2需要先把它加载到SCP的专用内存里,然后启动SCP。
日志里SCP_BL2的加载过程通常是这样:
INFO: Loading SCP_BL2 image
INFO: SCP_BL2: base address 0x04000000, size 0x10000
INFO: SCP_BL2: loaded to SCP SRAM at 0x20000000
INFO: SCP_BL2: authentication passed
INFO: SCP_BL2: releasing SCP out of reset
这里要注意几个关键信息:
- base address:FIP里SCP_BL2的起始偏移。
- loaded to:SCP SRAM的物理地址。不同平台不一样,我见过0x20000000、0x2E000000等。
- releasing SCP out of reset:BL2把SCP从复位状态释放,SCP开始执行自己的固件。
注意:SCP_BL2的加载地址是平台相关的。如果地址配置错了,SCP可能跑不起来。我曾经遇到过SCP_BL2加载后SCP没反应,查了半天发现是SCP SRAM的基地址在设备树里写错了。
4.4 BL31镜像加载:EL3运行时固件
BL31是ATF的核心组件,运行在EL3异常级别。它负责安全监控、中断路由、PSCI等功能。BL2加载BL31时,会把它放到DRAM的特定区域。
日志输出示例:
INFO: Loading BL31 image
INFO: BL31: base address 0x04010000, size 0x20000
INFO: BL31: loaded to DRAM at 0x80000000
INFO: BL31: authentication passed
INFO: BL31: entry point 0x80001000
关键点:
- loaded to DRAM:BL31被加载到DRAM地址0x80000000。这个地址通常在BL2初始化DDR后可用。
- entry point:BL31的入口地址。BL2最后会跳转到这个地址。
我个人的习惯是,看到entry point后,会记下这个地址。如果后续BL31启动失败,可以用JTAG直接跳到这个地址看代码是否跑飞。
4.5 BL32镜像加载:安全世界的操作系统
BL32是TEE(Trusted Execution Environment)的镜像,比如OP-TEE或Trusty。它运行在S-EL1,提供安全服务。BL2加载BL32是可选的——如果平台不需要TEE,这一步会跳过。
日志输出:
INFO: Loading BL32 image
INFO: BL32: base address 0x04030000, size 0x40000
INFO: BL32: loaded to DRAM at 0x90000000
INFO: BL32: authentication passed
INFO: BL32: entry point 0x90001000
如果平台没有BL32,日志里会直接跳过:
INFO: BL32: not present, skipping
常见问题:BL32加载失败时,日志可能显示Authentication failed或Image corrupt。我遇到过一种情况:BL32镜像大小超过了FIP里声明的size,导致加载时内存越界。后来在打包脚本里加了大小检查才解决。
4.6 三个镜像的对比
为了方便你快速对比,我整理了一张表:
| 镜像 | 运行位置 | 异常级别 | 主要功能 | 加载目标 |
|---|---|---|---|---|
| SCP_BL2 | SCP内部SRAM | SCP自有 | 电源管理、时钟控制 | SCP SRAM |
| BL31 | 主CPU | EL3 | 安全监控、PSCI、中断路由 | DRAM |
| BL32 | 主CPU | S-EL1 | TEE安全服务 | DRAM |
你看,SCP_BL2和BL31/BL32的加载目标完全不同。SCP_BL2必须放在SCP能直接访问的SRAM里,而BL31/BL32则放在主CPU的DRAM里。这个区别在日志里一眼就能看出来。
4.7 实战:从日志定位BL2阶段的问题
最后,我分享几个实战中常见的日志异常模式:
- FIP解析失败:日志显示
Invalid FIP header。原因通常是FIP镜像损坏或Flash读取错误。我建议先检查Flash的读写时序。 - 镜像验证失败:日志显示
Authentication failed。可能是证书过期、公钥不匹配、或者签名算法不一致。我曾经因为证书链里多了一个中间证书导致验证失败,折腾了两天。 - 镜像加载地址冲突:日志显示
Overlapping memory regions。这说明两个镜像的加载地址有重叠。检查平台内存布局文件platform_def.h里的地址定义。 - SCP_BL2启动超时:日志显示
SCP did not respond。SCP固件可能卡住了,或者SCP SRAM的时钟没配好。
嗯,BL2阶段的日志解读,说白了就是盯着那几行关键输出:加载地址、大小、验证结果。只要这些信息对得上,信任链就能顺利建立。如果对不上,那就按我上面说的方向去排查,基本不会跑偏。