0. 这一节要解决什么
U-Boot 拿到控制权之后,到内核跑起来之前,它到底做了什么?
1. U-Boot 是什么:干两件大事
- 加载内核:把 Kernel、DTB(设备树)和启动参数从存储读出来、组装好、交给 CPU 去执行内核
- 提供一个交互命令行:在自动启动前的几秒倒计时里按键打断,就能进入
=>提示符手动操作
2. 接手后先做四件事
确认设备 → 选择路径 → 准备对象 → 交出控制权
(串口、存储可用)(eMMC/SD/网络)(Kernel、DTB、参数)(跳转到 Kernel)
3. 自动启动的完整链条
preboot → bootdelay 倒计时 → bootcmd
| 环节 | 是什么 | 在哪看 |
|---|---|---|
preboot |
自动启动前的预备脚本,可以留空 | printenv preboot |
bootdelay |
倒计时秒数;设为 0 就没有打断窗口 | printenv bootdelay |
bootcmd |
默认启动脚本,到点自动执行 | printenv bootcmd |
倒计时期间按任意键,流程就停在这里,把控制权交给你。
4. 为什么要打断倒计时?
把自动脚本拆开,逐条确认设备、文件、地址和参数:
- 存储设备就绪了吗?→
mmc dev - 要加载的文件真的在那个分区吗?→
ls - 文件读进内存了吗?多大?→
load后看${filesize} bootargs对不对?→printenv bootargs
这正是本课最后一个知识点 [第1课时 · 6/6] 使用 U-Boot 手动启动 Kernel 要做的事。
5. U-Boot 交给 Kernel 的对象
Kernel 实际执行的内核镜像
DTB 这块板子的硬件描述(像一份硬件说明书)
bootargs 控制台、root 等启动参数(像启动时的简短指令)
initrd 可选的早期内存文件系统
↓
Kernel 解析设备描述 → 使用启动参数 → 开始初始化
对象可以分开:U-Boot 分别加载 Kernel、DTB 和可选 initrd。
对象也可以被封装:平台镜像(如 boot.img)可能把多个对象组合在一起;关键是交接时内容与格式正确。
6. 本节小结
- U-Boot 的两件大事:加载内核 + 可对话的命令行
- 自动启动链:
preboot → bootdelay 倒计时 → bootcmd bootcmd是一段 U-Boot 脚本,不是内核读的文件- 交接给内核的是四个对象:Kernel / DTB / bootargs / (initrd)
7. 本节思考
Q1:bootdelay=0 时还能进入 U-Boot 命令行吗?
查看答案
靠倒计时打断是不行了——没有窗口。但有别的入口:按住板上 RECOVERY 键复位可进 Loader 模式;或者先把 bootdelay 改回非 0 并 saveenv(前提是你之前存过可用环境)。这也是为什么不要随手把 bootdelay 设成 0 还保存。
Q2:bootcmd 里的内容和 Kernel 里的代码,谁先执行?它们之间是怎么传递信息的?
查看答案
bootcmd 先执行——它是 U-Boot 的脚本。它把 Kernel、DTB 装进内存,把 bootargs 写进 DTB 的 /chosen 节点,然后跳转到内核入口。内核启动早期从 DTB 里把 bootargs 取出来解析。传递媒介是内存和 DTB,不是文件。
Q3:既然有 boot.img 把东西打包在一起,为什么还要理解"对象可以分开"?
查看答案
因为排障时必须能拆开看:镜像加载成功但启动失败,你要能判断是 Kernel 没跑起来、DTB 不匹配,还是 bootargs 写错了。手动启动(第 6/6 节)就是把封装拆开、逐个对象验证的手段。