很多人第一次看启动链时,会下意识觉得:
系统能不能启动,主要看 U-Boot。
因为它看得见、能敲命令、能改环境变量、能直接做实验。
但真正从启动链顺序看,U-Boot 其实不是第一棒。
在它前面,还有一个更底层、也更容易被忽略的角色:
BootROM
很多人第一次接触这个词时,脑子里会把它理解成:
• 某种 bootloader
• U-Boot 的前身
• 或者“芯片上电后自动干点事的地方”
这些说法都不算完全错,但都不够准确。
如果只用一句话来定义 BootROM,我会这么说:
BootROM 是芯片内部固化的第一阶段启动代码,它决定系统最初从哪启动、去哪里找镜像、把第一棒交给谁。
也正因为这样,它天然决定了:
• 启动介质怎么选
• 第一阶段镜像怎么找
• 什么镜像格式才算“合法”
• 系统能不能进入后续 bootloader 阶段
换句话说,BootROM 不是你平时最常打交道的那一层,
但它却决定了:
你后面有没有机会看到 U-Boot。
一句话先讲明白
如果只记一句话,可以先记这个:
BootROM 的本质,不是“把 Linux 启动起来”,而是“把系统从硬件上电状态,拉到第一阶段可执行代码”。
它只负责第一棒,但这第一棒至关重要。
如果再压缩成一句最容易记的话,就是:
BootROM 决定“从哪起跑”,U-Boot 决定“怎么往下跑”。
这两者一定不要混。
第一,BootROM 是什么?
BootROM 一般是 SoC 内部固化在芯片 ROM 里的启动代码。
它不是你后来烧进去的,也不是你在工程里随意修改的。
它有几个非常鲜明的特点:
• 写死在芯片里
• 上电后最先执行
• 代码能力有限
• 强依赖厂商定义的启动规则
• 通常只负责第一阶段引导
所以 BootROM 不是“完整 bootloader”,更不是“可任意定制的系统层”。
它的角色更像是:
芯片出厂时自带的一段最早启动逻辑。
它要解决的不是“系统最后怎么进 Linux”,而是:
系统上电后第一步到底往哪走。
第二,BootROM 上电后到底在做什么?
它做的事情通常没有你想象中那么多,但每一步都很关键。
可以把它大致概括成 4 件事:
1. 读取启动模式
首先,BootROM 要知道:
这块芯片现在应该从哪种介质启动。
这个信息通常来自:
• strap 管脚
• 拨码开关
• eFuse
• 固定硬件配置
• 芯片内部启动模式寄存器
也就是说,系统最初从 SD、eMMC、SPI NOR、NAND 还是其他介质启动,往往不是 U-Boot 决定的,而是 BootROM 先决定的。
2. 去目标介质找第一阶段镜像
知道启动介质后,BootROM 会按芯片厂商规定的格式和位置,去找第一阶段镜像。
这个“找”的过程一般不是随便找文件,而通常有明确规则,比如:
• 固定偏移
• 固定头格式
• 固定镜像名或表项
• 固定加载位置
所以很多启动失败,本质上不是镜像“没有”,而是:
BootROM 没在它认得的位置和格式里找到合法镜像。
3. 把镜像搬到指定位置
找到镜像后,BootROM 会把它拷到:
• OCRAM
• SRAM
• 某些芯片指定的早期运行内存区域
注意,这时通常 DDR 还没完全可用。
所以第一阶段镜像为什么常常很小?
因为 BootROM 能用的资源有限。
4. 跳转执行
最后,BootROM 把控制权交给第一阶段代码。
到这一步,它的使命基本完成。
所以你可以把 BootROM 整体理解成:
它不负责把系统一路带到 Linux,只负责把系统从“死硬件”状态拉到“第一段软件开始跑”。
第三,为什么说它决定了系统“从哪启动”?
因为在大多数 SoC 上,最早的启动路径不是 U-Boot 自己选的,而是 BootROM 按硬件规则定的。
这就意味着:
1. 启动介质先由 BootROM 决定
比如芯片上电后先查:
• SD
• eMMC
• SPI NOR
• NAND
• USB 下载模式
这些顺序或选择逻辑,往往已经被 SoC 设计固定了。
2. 第一阶段镜像格式也由 BootROM 约束
BootROM 不是万能解析器,它通常只认厂商定义好的镜像头、布局或固定入口。
所以你不能随便丢一个二进制上去,就指望它启动。
3. 第一阶段代码位置和大小也常受限制
因为早期运行环境有限,BootROM 可操作的内存和外设初始化能力都有限。
所以它天然会影响:
• 镜像布局
• 第一阶段代码大小
• 启动链分层方式
换句话说,BootROM 不是“启动链里一个可有可无的小步骤”,而是:
启动链规则的第一制定者。
第四,BootROM 和 U-Boot 到底有什么区别?
这是最容易混的一点。
你可以直接按下面这个方式记:
BootROM
负责:
• 决定从哪里起步
• 找第一阶段镜像
• 拉起第一阶段代码
特点:
• 固化在芯片里
• 基本不能改
• 能力有限
• 强依赖硬件启动规则
U-Boot
负责:
• 选择 Linux 启动链路
• 加载 kernel / dtb / initrd
• 设置 bootargs
• 执行 bootm / booti / bootz
特点:
• 你自己编译和烧录
• 能交互、能改环境变量
• 能力完整得多
• 属于你日常可控的 bootloader 层
所以最核心的区别就是:
BootROM 负责把系统拉出第一步,U-Boot 负责把 Linux 真正拉起来。
第五,为什么现场很多启动问题其实卡在 BootROM?
因为这一层一旦出问题,后面几乎都不会有明显日志。
它最典型的现象就是:
• 上电后没输出
• 串口完全安静
• 看不到 U-Boot banner
• 启动行为和预期介质不一致
• 某个启动介质总是“像没烧进去一样”
这时候很多人会先怀疑:
• U-Boot 坏了
• 镜像错了
• Linux 起不来
但其实更应该先问:
BootROM 有没有成功把第一阶段代码拉起来?
常见卡点包括:
• 启动模式拨错
• 镜像头格式不对
• 镜像烧录偏移不对
• 介质本身没被 BootROM 正确识别
• 早期供电/时钟问题导致 BootROM 后续动作失败
这一层最麻烦的地方在于:
日志最少,但位置最靠前。
所以你越低估它,越容易在启动问题里走弯路。
第六,工程上到底应该怎么理解 BootROM?
最稳的理解方式不是把它看成“另一个 bootloader”,而是把它看成:
启动链的硬件入口控制器。
它决定的是:
• 从哪种介质读
• 按什么规则读
• 第一阶段交给谁
所以你可以把启动链想成:
• BootROM 定起点
• SPL / TF-A 定早期环境
• U-Boot 定 Linux 启动方式
• Kernel 定系统核心环境
• rootfs 定用户空间
只要把这个边界记清,很多启动问题的归属马上就会清楚。
最后怎么一句话记住?
如果你在面试、分享、技术交流时想快速讲清楚,可以直接说:
BootROM 是芯片内部固化的第一阶段启动代码,它决定系统最初从哪种介质启动、按什么规则找到第一阶段镜像,并把控制权交给后续 bootloader。
如果再压缩成一句最容易记的话,就是:
BootROM 定入口,U-Boot 定启动。
这句非常适合直接拿去用。
结尾
很多人做 Linux 启动时,最容易把视线全部放在 U-Boot 和 kernel 上。
这当然没错,因为那是你最常操作的层。
但如果你真的想把启动链吃透,就一定不能跳过 BootROM。
因为它决定的不是细节,而是:
整条启动链最开始能不能成立。
你后面看到的 U-Boot、kernel、rootfs,前提都是:
BootROM 先把第一棒交出去了。
这也是为什么真正做板级 bring-up 和底层排障的人,一定会对 BootROM 保持足够敬畏。
下一篇:为什么同一个镜像,换个启动介质系统就起不来?