U-Boot 初始化、重定位与主循环
U-Boot 启动后不是直接进入命令行。它需要先完成一系列初始化,等内存、console、设备模型和环境变量准备好后,才会进入主循环并等待你的命令。
本章会涉及源码路径,但目标不是让你背完整调用栈。你只需要先建立一张大地图:早期初始化做什么,为什么要重定位,什么时候进入主循环。
1. 两个重要阶段
可以先把 U-Boot proper 的启动粗略分成两段:
board_init_f():早期初始化,运行条件有限,通常还没有完整运行环境。board_init_r():重定位之后的初始化,运行环境更完整,最终进入主循环。
源码中可以这样查找:
# [Host]
rg "void board_init_f|board_init_r" common arch
在 U-Boot v2026.07 中,你还可以重点查看:
# [Host]
sed -n '1,220p' common/board_f.c
sed -n '1,220p' common/board_r.c
这两个文件里有初始化序列。不要一开始逐行细读,先看函数名和注释,理解每个阶段大概在准备什么。
2. 为什么要重定位
许多平台上,U-Boot 最初运行的位置并不是最终位置。早期代码可能在 ROM 映射区、SRAM 或固件加载地址处运行。等 DRAM 初始化完成后,U-Boot 会把自己搬到更合适的 DRAM 高地址区域,这个过程叫 relocation。
重定位之后,U-Boot 可以拥有更完整的栈、堆、全局数据和驱动运行环境。
你可以从 bdinfo 观察重定位相关信息:
# [U-Boot]
bdinfo
重点看 relocaddr、reloc off、malloc_start、malloc_end 等字段。不同平台输出可能不同,但它们能帮助你理解 U-Boot 运行位置和内存分配区域。
3. 早期初始化通常做什么
早期初始化阶段资源有限,所以它通常只做必须的事:
- 建立临时栈。
- 准备 Global Data。
- 初始化最基本的 console。
- 获取或初始化 DRAM 信息。
- 计算重定位地址。
- 准备把 U-Boot 搬到 DRAM 中运行。
在这个阶段,很多驱动和命令还不能用。真实硬件上如果卡在这里,可能连完整错误日志都没有。