[第1课时 · 3/6] U-Boot 的核心功能与启动过程

0. 这一节要解决什么

U-Boot 拿到控制权之后,到内核跑起来之前,它到底做了什么?

1. U-Boot 是什么:干两件大事

  1. 加载内核:把 Kernel、DTB(设备树)和启动参数从存储读出来、组装好、交给 CPU 去执行内核
  2. 提供一个交互命令行:在自动启动前的几秒倒计时里按键打断,就能进入 => 提示符手动操作

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 节)就是把封装拆开、逐个对象验证的手段。