U-Boot 启动过程:从上电到 Linux
前面介绍了 Bootloader 的作用与 U-Boot 的基本定位。本章沿着一次完整启动逐阶段展开,重点分析每个阶段运行在哪里、接收什么、完成什么,以及如何把系统交给下一阶段。
本教程以 Mainline U-Boot v2026.07 为基准。本章给出的是通用模型,不代表所有 SoC、开发板和产品都采用完全相同的启动链。
学习目标
阅读本章后,你将能够:
- 说明从上电到用户空间运行所经历的主要阶段
- 分析每个启动阶段的输入、任务和输出
- 区分 Boot ROM、早期加载程序、平台固件、U-Boot 和 Linux 的职责
- 区分镜像的存储位置、加载地址和执行地址
- 理解 U-Boot 向 AArch64 Linux 移交控制权时需要准备什么
- 根据串口日志初步定 位启动故障
前置知识
建议先阅读嵌入式系统与 Bootloader与U-Boot 简介。Bootloader 的定义与职责边界见第一章,本章不再重复展开。
1. 启动不是一个动作,而是一连串交接
日常所说的“启动 Linux”容易让人误以为设备只执行了一次加载和跳转。实际上,嵌入式系统通常会经历多个软件阶段:
图中的阶段并非全部必选。例如:
- 简单平台可能没有单独的平台固件
- U-Boot SPL 可以同时承担早期初始化和镜像加载
- 某些平台直接使用厂商 Loader,不使用 U-Boot SPL
- TF-A、OP-TEE 或 OpenSBI 只会出现在适用的架构和平台中
- 特殊系统可以跳过 U-Boot proper,直接从早期阶段启动 Linux
因此,不要把图中的名称当成固定公式。分析任意启动链时,更有效的方法是对每个阶段提出四个问题:
- 代码从哪里读取?
- 代码在哪里运行?
- 这个阶段建立了哪些运行条件?
- 它向下一阶段传递了什么?
这四个问题贯穿本章,也会成为后续阅读启动日志和排查故障的基本方法。
2. 怎样才算“启动完成”
“设备启动了”可能指不同的时间点:
| 现象 | 实际含义 |
|---|---|
| 出现 U-Boot 横幅 | U-Boot proper 已经开始运行 |
出现 U-Boot 提示符 => | U-Boot 已完成基本初始化并进入交互环境 |
出现 Starting kernel ... | U-Boot 即将或已经把控制权交给内核 |
出现 Linux version ... | Linux 内核的早期代码已经开始运行 |
| 根文件系统挂载成功 | 内核已经找到并挂载 rootfs |
启动 init | 系统开始进入用户空间 |
| 出现登录提示符或业务界面 | 用户空间已完成产品定义的关键启动流程 |
所以,“内核开始执行”和“系统可用”是两个不同的里程碑。
本教程把完整启动过程的终点定义为:
Linux 已挂载根文件系统,启动
init,并进入可以运行系统服务和应用程序的用户空间。
3. 阶段一:上电与处理器复位
设备上电或收到复位信号后,电源、时钟和复位控制电路会使处理器进入芯片规定的初始状态。处理器随后从架构和 SoC 设计指定的复位入口开始取指。
在这个时刻,不能假定整套硬件已经可用:
- 外部 DRAM 通常还不能使用
- 大多数外设尚未初始化
- 时钟可能处于安全的初始频率
- 多核系统通常只让一个主处理器核心先执行
- Cache、MMU 和中断控制器处于架构规定或平台规定的状态
- 串口可能还没有配置,因此看不到任何输出
冷启动、热复位、看门狗复位和从低功耗状态恢复的路径也可能不同。
本阶段的关键结果只有一个:
处理器进入一个确定的初始状态,并开始执行启动链的第一段代码。
4. 阶段二:Boot ROM
许多 SoC 在芯片内部集成了一段不可由普通用户修改的只读程序,通常称为 Boot ROM、ROM Code 或 Primary Bootloader。它由芯片厂商实现,是处理器复位后最先执行的软件。
4.1 Boot ROM 如何选择启动来源
Boot ROM 通常会综合读取启动模式引脚、eFuse / OTP、介质中的启动标记、按键或恢复条件等信息,然后按 SoC 规则尝试从 eMMC、SD、SPI NOR、NAND、USB、UART 或网络等介质加载下一阶段。
具体支持哪些介质、从哪个偏移读取、镜像头采用什么格式,都由 SoC 决定,不能从一块开发板类推到另一块开发板。