4、ROM Code阶段:芯片上电后的第一条指令

芯片上电那一刻,CPU到底先干了什么?

很多人以为是从Flash里读代码。其实不是。芯片复位后,CPU会从一个固定的物理地址取指——这个地址,指向的就是芯片内部固化的BootROM。说白了,芯片的第一口气,是ROM给的。

4.1 芯片上电后的第一条指令

不同架构的CPU,复位向量地址不一样。ARM Cortex-A系列通常是0x00000000或0xFFFF0000,RISC-V一般是0x80000000或0x00000000。但不管地址是多少,这个位置存放的必须是有效指令,而且是在芯片流片时就写死在ROM里的。

关键点:BootROM是只读的,不可篡改。这是TEE信任链的物理根。

我调试过一块RISC-V芯片,上电后死活跑不起来。用逻辑分析仪抓片选信号,发现CPU根本没访问外部Flash。后来查手册才知道,那颗芯片的复位向量是0x00010000,不是默认的0x00000000。嗯,这种坑,手册不仔细看真的会栽。

4.2 BootROM的职责

BootROM虽然小,但活儿不少。我把它拆成几个核心任务:

  • 硬件初始化——设置时钟、PLL、DDR控制器、中断控制器等。这时候连栈都还没设好,只能用汇编写。
  • 自检与安全校验——检查芯片是否被篡改,比如efuse状态、调试接口是否锁定。
  • 启动介质探测——按优先级扫描eMMC、UART、SPI Flash等设备,找到可用的启动镜像。
  • 加载并跳转——把下一级Bootloader(比如SPL或BL2)读到SRAM或DDR里,然后跳过去执行。

我个人习惯把BootROM看作“芯片的BIOS”,但它比BIOS更封闭——你改不了它,只能用它。

经验之谈:我在项目中遇到过BootROM里有个bug,导致某些批次的芯片在低温下无法从eMMC启动。最后只能靠修改下一级Bootloader来绕过。所以,别以为ROM代码就不会出问题——它只是你改不了而已。

4.3 启动介质选择

BootROM怎么知道从哪个设备启动?

通常靠硬件管脚的电平组合。芯片会采样几个GPIO的状态,然后查表决定启动顺序。常见的启动介质有:

启动介质 典型场景 速度 安全性
eMMC 量产设备、手机、平板 高 中(可加密分区)
UART 开发调试、工厂烧录 低 低(明文传输)
SPI Flash 嵌入式设备、IoT 中 低(可读可写)
USB 开发板、恢复模式 中 低
NAND Flash 老旧设备、工业控制 中 低

你想想看,如果BootROM先尝试从UART启动,那生产线上只要插着串口线,芯片就可能卡在等待串口数据的状态,永远进不了eMMC。所以量产设备的启动顺序,通常会把eMMC放在第一位,UART放在最后。

注意:我曾经见过一块开发板,BootROM默认先检测SPI Flash,再检测eMMC。结果SPI Flash里有个残留的旧镜像,导致芯片每次都从SPI启动,eMMC里的新系统死活跑不起来。排查了一整天才发现是启动优先级的问题。

4.4 ROM Code阶段的日志输出

BootROM能不能打印日志?

能,但有限。因为这时候UART可能还没初始化,DDR也没准备好。很多芯片的BootROM会通过一个专用的调试接口(比如JTAG或SWD)输出状态码,或者用GPIO闪烁来指示进度。

我习惯在调试时先看这几个信号:

  • 复位状态寄存器——确认芯片是否真的从复位中释放了。
  • 启动设备选择寄存器——确认BootROM识别到的启动介质对不对。
  • 错误状态寄存器——如果启动失败,这里会留下错误码。

举个例子,某款芯片的BootROM错误码定义:

0x01 — 时钟初始化失败
0x02 — DDR训练失败
0x03 — eMMC初始化超时
0x04 — SPI Flash校验失败
0x05 — 镜像签名验证失败

看到0x05,基本可以断定是安全校验没通过。这时候别急着换硬件,先检查efuse是否烧录了正确的公钥哈希。

4.5 ROM Code阶段的信任根

TEE的安全启动,起点就在BootROM。芯片出厂时,厂商会把一个公钥哈希烧进efuse。BootROM在加载下一级镜像前,会用这个哈希验证镜像的签名。如果验证失败,芯片直接死循环——这就是所谓的“硬锁”。

我遇到过最头疼的情况:efuse被误烧,导致所有镜像都无法启动。那批芯片只能报废。所以,烧efuse之前,一定要 triple-check。

一句话总结:BootROM是TEE信任链的第一环。它不可改、不可跳、不可绕过。理解了BootROM,你就理解了芯片启动的“宪法”。

4.6 ROM Code阶段流程图

下面这张图,把BootROM的完整流程画出来了。建议你对照着看,能更直观地理解每个步骤。

BootROM 启动流程图 芯片上电 / 复位 CPU 从复位向量取指 硬件初始化(时钟/PLL/IO) 自检与安全校验 探测启动介质 加载下一级镜像 验证签名 通过 → 跳转执行 失败 → 死循环 说明 复位向量地址由芯片 架构决定,不可更改 说明 efuse 中存储公钥哈希 用于验证镜像签名 说明 启动顺序由硬件管脚 电平组合决定

这张图里,从“芯片上电”到“验证签名”是一条直线。但实际项目中,每个环节都可能出岔子。比如“探测启动介质”这一步,如果eMMC没焊好,BootROM就会超时,然后尝试下一个介质。你看到的日志可能就是一行Boot device not found。

嗯,ROM Code阶段的内容就这些。别看它简单,但它是整个TEE安全启动的基石。后面所有章节,都会反复提到“信任根”这个概念——它的源头就在这里。