1. U-Boot概述:历史、作用与启动流程

U-Boot(全称 Das U-Boot,德语“潜艇”之意)是嵌入式系统中应用最广泛的 引导加载程序(Bootloader)。它负责在硬件上电后完成最底层的初始化,并将操作系统内核加载到内存中执行。理解 U-Boot 的历史定位、核心作用以及启动流程,是进行移植工作的基础。

1.1 U-Boot的历史沿革

U-Boot 并非一蹴而就,它经历了从专用引导程序到通用引导程序的演进过程。下表总结了其关键发展阶段:

时间 事件 说明
1999年 PPCBoot 诞生 由 Magnus Damm 为 PowerPC 架构开发,功能单一,仅支持串口下载和 Flash 烧写。
2002年 更名为 U-Boot 项目由 Wolfgang Denk 接管,并扩展支持 ARM、MIPS、x86 等多种架构,成为通用引导程序。
2008年 进入主线维护期 Denx Software Engineering 主导维护,社区贡献激增,支持超过 200 种开发板。
2013年 设备树(DT)全面支持 U-Boot 开始原生支持 Flattened Device Tree (FDT),实现内核与板级硬件描述的分离。
至今 持续演进 支持 RISC-V、安全启动(Secure Boot)、EFI 引导、OP-TEE 等现代特性。
关键认知: U-Boot 的通用性使其成为嵌入式 Linux 生态的事实标准。移植 U-Boot 的核心工作,就是让它在特定硬件上完成“从复位向量到内核入口”的过渡。

1.2 在嵌入式系统中的作用

U-Boot 在嵌入式系统中的角色可以概括为“硬件初始化器”和“内核加载器”。其具体职责包括:

  • 硬件早期初始化:设置时钟(PLL)、初始化 DDR 控制器、配置串口(UART)用于调试输出。
  • 引导介质管理:支持从 NAND Flash、eMMC、SD 卡、SPI Flash、网络(TFTP)等多种介质读取内核镜像。
  • 设备树传递:将编译好的设备树二进制文件(.dtb)加载到内存,并将地址传递给内核。
  • 交互式调试:提供命令行接口(CLI),允许开发者手动修改环境变量、测试内存、烧写固件。
  • 安全启动链:验证内核镜像签名,确保系统仅运行经过授权的代码。

下图展示了 U-Boot 在嵌入式系统软件栈中的位置:

U-Boot在嵌入式系统软件栈中的位置 嵌入式系统软件栈 用户应用程序 / 中间件 Linux 内核 / RTOS U-Boot 引导加载程序 设备树 (DTB) / 硬件抽象层 SoC / DDR / Flash / 外设 U-Boot 是硬件与操作系统之间的桥梁,负责初始化 DDR 并传递设备树

1.3 启动流程概览

U-Boot 的启动流程可以分为 三个阶段,每个阶段都有明确的入口和职责。理解这个流程是移植工作的第一步。

阶段一:SPL(Secondary Program Loader)

SPL 是 U-Boot 的第一阶段引导程序,通常运行在芯片内部 SRAM 中。由于 SRAM 容量极小(通常 4KB~128KB),SPL 的代码必须极度精简。其主要任务包括:

  • 设置 CPU 为 SVC 模式,关闭中断。
  • 初始化时钟和 DDR 控制器(关键步骤)。
  • 从引导介质加载 U-Boot 主程序(u-boot.img)到 DDR。
  • 跳转到 DDR 中的 U-Boot 主程序入口。

阶段二:U-Boot 主程序(Proper)

主程序运行在 DDR 中,拥有完整的驱动框架和命令行环境。其执行流程如下:

  1. board_init_f: 初始化串口、定时器、I2C 等早期外设,并规划内存布局。
  2. relocate_code: 将 U-Boot 自身从 Flash 或加载地址重定位到 DDR 的高端地址。
  3. board_init_r: 初始化完整的驱动模型(DM)、环境变量、网络栈、文件系统等。
  4. 进入主循环: 等待用户输入命令,或执行自动启动脚本(bootcmd)。

阶段三:加载内核与设备树

当执行 bootm 或 bootz 命令时,U-Boot 完成最后一步:

  • 从 Flash/网络加载内核镜像(zImage/Image)到指定内存地址。
  • 加载设备树二进制文件(.dtb)到内存。
  • 设置内核启动参数(如 console、root 等)。
  • 跳转到内核入口点,将控制权交给操作系统。

下图以流程图形式展示了完整的启动链路:

U-Boot 启动流程 U-Boot 启动流程(三阶段) 上电复位 / ROM Code SPL 阶段(SRAM) 初始化时钟 & DDR 加载 u-boot.img 到 DDR 跳转到 DDR 入口 U-Boot Proper(DDR) board_init_f relocate_code board_init_r 加载内核 & DTB bootm / bootz 命令 设置启动参数 跳转到内核入口 Linux 内核启动
移植关注点: 在移植过程中,SPL 阶段的 DDR 初始化 是最容易出错的环节。如果 DDR 时序参数配置错误,系统将无法进入 U-Boot Proper 阶段。后续章节将详细讲解如何通过寄存器级调试和内存测试工具验证 DDR 初始化正确性。

1.4 本章小结

U-Boot 作为嵌入式系统的“第一段代码”,其历史演进反映了嵌入式 Linux 生态的成熟过程。它的核心作用在于:初始化硬件 → 加载内核 → 传递控制权。启动流程的三阶段(SPL → Proper → 内核加载)是移植工作的主线,后续所有章节都将围绕这条主线展开。