3. BL1阶段日志解读:ROM代码执行、平台初始化、认证模块加载

BL1阶段,说白了就是芯片上电后跑的第一段代码。这段代码通常固化在ROM里,你改不了它。我刚开始接触ATF时,总觉得BL1没啥好看的——反正都是厂家写死的,出问题也动不了。后来被一个启动失败的问题折腾了两周,才发现BL1日志里藏着关键线索。

嗯,这一章我们就来聊聊BL1阶段的日志到底怎么看。ROM代码执行、平台初始化、认证模块加载,这三个环节一个都不能少。

3.1 ROM代码执行:第一行代码的足迹

芯片复位后,PC指针直接跳到一个固定地址——通常是ROM的起始位置。这时候MMU还没开,DDR还没初始化,代码只能在SRAM或者内部RAM里跑。

BL1启动的核心特征:

  • 运行在EL3异常级别,最高权限
  • 使用物理地址,没有虚拟内存映射
  • 堆栈空间极其有限,通常只有几KB
  • 依赖硬件看门狗,防止卡死

日志里怎么判断ROM代码开始执行了?看下面这个典型输出:

NOTICE:  BL1: v2.8(release):v2.8-rc0-123-gabcdef
NOTICE:  BL1: Built : 14:30:00, Mar 15 2024
INFO:    BL1: RAM 0x00000000 - 0x0003FFFF
INFO:    BL1:复位原因: 上电复位

我个人习惯先看版本号和构建时间。如果版本号跟你烧录的固件对不上,那说明ROM代码可能被篡改过,或者芯片进入了恢复模式。我在项目中遇到过一回,板子怎么都起不来,日志里BL1版本号显示的是v2.4,但我明明烧的是v2.8。后来发现是芯片的eFuse配置把BL1加载路径指向了备份区。

小技巧:复位原因字段很重要。上电复位、看门狗复位、软件复位,不同原因对应的排查方向完全不同。如果是看门狗复位,那大概率是BL1执行超时了。

3.2 平台初始化:时钟、电源、存储控制器

ROM代码跑完最基本的设置后,会跳转到BL1的入口。这时候才开始真正的平台初始化。说白了,就是让芯片知道自己长什么样——几个核、多少缓存、外设怎么映射。

日志里常见的初始化步骤:

INFO:    BL1: 平台初始化开始
INFO:    BL1: 配置系统计数器
INFO:    BL1: 配置GICv3
INFO:    BL1: 配置MMU(EL3页表)
INFO:    BL1: 配置UART控制台
INFO:    BL1: 平台初始化完成

你想想看,如果日志卡在"配置系统计数器"这一步,那大概率是晶振没起振,或者时钟源选择有问题。我调试过一块板子,日志停在"配置GICv3"就不动了。查了半天,发现是GIC的基地址在datasheet里写错了——我用的芯片是修订版B,但代码里配的还是修订版A的地址。

初始化步骤 常见失败原因 日志特征
系统计数器 晶振故障、时钟源配置错误 卡死无输出
GIC初始化 基地址错误、中断号冲突 打印后立即重启
MMU页表 内存属性配置错误、地址重叠 打印后进入异常
UART控制台 波特率不匹配、引脚复用错误 输出乱码或无输出
存储控制器 时序参数错误、DDR训练失败 反复重试打印

注意:UART控制台初始化如果失败,你后面什么都看不到。我建议在硬件设计阶段就把UART引脚固定下来,不要用复用功能。否则调试时连日志都抓不到,那才叫抓瞎。

3.3 认证模块加载:信任链的第一环

BL1的另一个核心任务,就是加载并验证BL2的镜像。这是整个信任链的起点。如果BL1不认BL2的签名,系统直接死给你看。

认证流程大致是这样的:

INFO:    BL1: 加载BL2镜像
INFO:    BL1: BL2: 加载地址 0x04001000
INFO:    BL1: BL2: 镜像大小 0x0001E000
INFO:    BL1: 验证BL2证书
INFO:    BL1: 使用ROTPK验证
INFO:    BL1: 证书验证成功
INFO:    BL1: 跳转到BL2

这里有个关键点——ROTPK(一次性可编程密钥)。这个密钥在芯片出厂时烧进去,或者通过eFuse写入。一旦写入,就不能改了。我遇到过一台设备,升级固件后启动失败,日志显示"证书验证失败"。查了半天,发现是客户自己生成了新的密钥对,但没把公钥烧进eFuse。说白了,就是钥匙和锁不匹配。

认证失败的常见原因:

  • 证书签名算法不匹配(比如BL1用RSA2048,证书却是RSA4096)
  • ROTPK哈希值不一致
  • 证书链不完整(缺少中间CA证书)
  • 镜像被篡改或损坏

我曾经被一个"间歇性认证失败"的问题折磨了三天。日志有时候能过,有时候过不了。最后发现是eFuse的读取时序有问题——温度一高,读取出来的ROTPK就多了一个bit错误。嗯,硬件问题,软件背锅。

3.4 BL1阶段的核心流程图

下面这张图把BL1阶段的执行流程串起来了。你可以对照着日志,一步步看系统走到哪了。

BL1阶段执行流程图 芯片复位 ROM代码执行 平台初始化 加载BL2镜像 证书验证 验证通过? 跳转到BL2 打印错误并停机 说明:BL1阶段所有操作都在EL3异常级别,使用物理地址。 认证失败时,系统不会自动重启,而是进入死循环等待硬件看门狗复位。

3.5 实战:从日志定位BL1阶段问题

说了这么多,咱们来点实际的。假设你拿到一份启动日志,只有下面这几行:

NOTICE:  BL1: v2.8(release)
INFO:    BL1: 平台初始化开始
INFO:    BL1: 配置系统计数器
(然后就没有然后了)

怎么分析?

  1. 看最后一条有效日志——"配置系统计数器"。这说明代码卡在了这一步,或者这一步之后崩溃了。
  2. 检查硬件——系统计数器依赖外部晶振或者芯片内部的RC振荡器。用示波器量一下晶振引脚,看有没有波形。
  3. 检查代码——如果硬件没问题,那可能是计数器基地址配置错了。我遇到过一款SoC,它的系统计数器地址在参考手册里写的是0x2A430000,但实际芯片里是0x2A830000。嗯,手册勘误页里有写,但谁没事去看勘误页呢?

我的排查习惯:遇到BL1卡死,先看复位原因,再看卡在哪个初始化步骤。如果复位原因是"看门狗复位",那说明BL1曾经跑完过,但后续代码执行超时了。这时候重点查DDR初始化或者认证模块——这两个环节最容易超时。

BL1阶段的日志虽然短,但信息密度很高。版本号、复位原因、初始化步骤、认证结果,每一行都可能指向问题的根因。说白了,你不需要看懂每一行汇编代码,但你要知道日志里哪些字段是关键的,哪些异常是致命的。