嵌入式板子上电后,最先运行的不是 Linux,而是芯片 ROM 中固定的启动代码。ROM 从预设介质读取第一阶段程序;受片上 SRAM 容量限制,这一阶段常是 SPL/TPL,负责最小引脚、时钟和 DRAM 初始化;随后加载完整 U-Boot。U-Boot 再根据环境、bootflow 或脚本找到内核、DTB、initramfs/根文件系统信息,设置启动参数并将控制权交给 Linux。
启动阶段各自承担什么责任
ROM 的能力由芯片固定,通常只知道从某些存储偏移读取并校验少量数据。SPL/TPL 必须在非常受限的 SRAM 里完成 DRAM training、时钟和必要存储驱动初始化。U-Boot proper 在 DRAM 可用后提供命令行、环境变量、网络/存储驱动、镜像验证和更灵活的启动策略。
地址、格式和一致性是常见故障源
U-Boot 中 kernel、DTB、initramfs 的加载地址不能互相覆盖,也不能覆盖 U-Boot 自身、FDT 工作区或内核解压区域。镜像格式也必须与启动命令匹配:booti、bootz、bootm 处理的镜像类型不同;FIT 可以将 kernel、FDT、ramdisk、哈希/签名组合成一份可验证镜像,但仍要确保配置节点选择的是正确板级 DTB。
1 | 加载镜像 -> 校验大小/哈希 -> 检查加载地址与保留区 |
不要因为“U-Boot 已经显示 Loaded”就假设内核一定拿到了正确数据。应在 U-Boot 中检查内存内容、FDT 信息和环境变量,并把最终命令行写入启动日志。
按最后一条日志分层排障
串口完全无输出,先查 ROM/SPL、供电、时钟和串口引脚;SPL 输出后死在 DRAM,查 training/时序;U-Boot 能起来却无法加载镜像,查存储、分区、文件系统和地址;“Starting kernel …”后无输出,查 console、DTB、内核镜像和启动参数;内核有输出却挂根失败,则转向 root=、驱动和 rootfs。
安全启动或 OTA 场景还要验证镜像签名、回滚计数、A/B 槽选择和掉电恢复。启动链是信任链与恢复链的一部分,不应只在正常镜像上测试一次。