U-Boot 整个流程分为4 大阶段Boot ROM芯片固化代码SPLU-Boot SPL / Secondary Program LoaderU-Boot 主程序u-boot.bin/u-boot.img启动 Linux Kernel阶段 1Boot ROMSoC 出厂固化上电复位CPU 从Boot ROM 固定地址开始执行初始化时钟、引脚、片上 SRAM读取 Boot Strapping Pin判断启动介质SD/eMMC/SPI/NAND从启动介质的固定偏移位置读取SPL将 SPL 加载到片上 SRAM校验可选安全启动后跳转到 SPL 入口这就是你上一问的Boot ROM 如何加载 SPL阶段 2SPLU-Boot SPLSPL 是极小版本的 U-Boot因为片上 SRAM 很小只能放几十 KB。SPL 核心任务只有一个初始化 DDR然后加载完整 U-Boot 到 DDR具体步骤进一步初始化时钟、PLL、电源初始化DDR 控制器 DDR PHY最关键从启动介质读取完整 U-Boot 镜像将 U-Boot 加载到DDR 内存跳转到 DDR 中的U-Boot 入口SPL 执行完就彻底退出不再回来阶段 3U-Boot 主程序真正的 U-Boot这部分代码在 DDR 里运行功能完整。分为汇编启动阶段和C 语言阶段。3.1 汇编阶段start.S设置 CPU 模式SVC/EL3/EL2关中断、关 MMU、关 Cache设置栈指针 SP清零 BSS 段调用 C 语言入口函数board_init_f3.2 C 语言第一阶段board_init_f初始化基础硬件时钟、串口、DDR初始化全局数据结构体gd_t准备重定位地址跳转到board_init_r3.3 C 语言第二阶段board_init_r这是 U-Boot 最核心的初始化阶段初始化各种外设GPIOI2C、SPIMMC/eMMC/SDEthernet、USBNAND、Flash 等初始化命令系统初始化环境变量env显示控制台提示符进入主循环等待命令 或 自动启动内核3.4 自动启动逻辑U-Boot 倒计时结束后执行run bootcmdbootcmd通常做这些事从 MMC/Flash/NET 读取设备树 dtb读取Linux 内核镜像 zImage/Image设置启动参数bootargs调用bootm/booti启动内核阶段 4启动 Linux KernelU-Boot 校验内核镜像准备设备树DTB地址填充内核启动参数跳转到内核入口地址U-Boot 生命周期结束CPU 控制权交给 LinuxU-Boot 启动总览[SoC 上电/复位] ↓ [BootROM (BL1, 片内ROM)] ↓ [SPL (BL2, 片内SRAM)] ↓ [U-Boot 主体 (DRAM)] ↓ [引导 Linux 内核]BootROM 阶段BL1硬件复位从固定 ROM 地址执行最小初始化时钟、看门狗、片内 SRAM检测启动介质eMMC/SD/NAND/QSPI加载 SPL 到片内 SRAM跳转至 SPL 入口_startSPL 阶段BL2SRAM 执行SPL _start (start.S) ↓ reset: 设置SVC模式、关中断、关MMU/Cache ↓ lowlevel_init: 初始化DDR控制器、训练DDR ↓ _main (crt0.S): 分配临时栈、初始化gd ↓ board_init_f: 初始化串口、打印启动信息、计算重定位地址 ↓ relocate_code: 从Flash/QSPI加载U-Boot主体到DRAM ↓ 清除BSS段 ↓ 跳转至 DRAM 中 U-Boot 的 _startU-Boot 主体阶段DRAM 执行3.1 重定位前Pre-RelocationU-Boot _start (start.S) ↓ reset: 同SPL关中断、关MMU/Cache ↓ _main (crt0.S): 1. 分配栈与gd全局数据区 2. board_init_f: 初始化串口、时钟、DRAM、环境变量基础、打印版本 3. 计算重定位偏移量 4. relocate_code: 将U-Boot自身从低地址搬移到DRAM高地址 5. relocate_vectors: 重定位中断向量表 6. 清除BSS段 ↓ 跳转至 board_init_r重定位后地址3.2 重定位后Post-Relocationboard_init_r: 1. 完整初始化外设MMC/SD、以太网、USB、I2C、SPI、NAND 2. 加载并解析环境变量env_import 3. 初始化命令行、设备树FDT 4. 进入 run_main_loop ↓ run_main_loop: - 启动倒计时autoboot - 倒计时结束 → 执行 bootcmd - 倒计时内按回车 → 进入 U-Boot Shell引导 Linux 内核bootcmd 执行执行 bootcmd如bootz 0x80800000 - 0x83000000 ↓ do_bootz / do_bootm: 1. 关闭中断 2. 加载内核镜像、DTB到DRAM 3. 解析内核头部、校验 4. 处理设备树注入 bootargs 到 /chosen 节点 5. 按 Linux ABI 设置寄存器 - r0 0 - r1 Machine IDARM32/ 0ARM64 - r2 DTB 物理地址 ↓ boot_jump_linux: 关闭Cache、跳转至内核入口 ↓ Linux 内核开始执行完整启动流程图SoC 上电 ↓ BootROM (ROM) ↓ 加载 SPL 到 SRAM ↓ SPL _start → reset → lowlevel_init (DDR) → _main → board_init_f → 加载 U-Boot 到 DRAM → 跳转 U-Boot _start ↓ U-Boot _start → reset → _main → board_init_f → relocate_code搬移自身→ 清除BSS → 跳转 board_init_r ↓ board_init_r → 外设初始化 → 环境变量 → run_main_loop ↓ ┌───────────────────────────────────────────────────┐ │ 倒计时结束 → 执行 bootcmd → bootz/bootm → 加载内核DTB → 跳转内核 │ │ 按回车 → U-Boot Shell可手动执行命令 │ └───────────────────────────────────────────────────┘ ↓ Linux 内核启动关键函数与文件ARM64/ARM32入口arch/arm/cpu/armv8/start.SARM64/start.SARM32SPL 主流程arch/arm/lib/crt0.S→_main重定位前初始化common/board_f.c→board_init_f重定位后初始化common/board_r.c→board_init_r引导内核common/bootm.c→do_bootm/do_bootzU-Boot 代码路径对应表最顶层目录uboot/ ├── arch/ # 架构相关代码ARM、RISC-V、x86 ├── board/ # 开发板硬件相关最常改 ├── common/ # 通用命令、主循环、核心逻辑 ├── drivers/ # 所有驱动GPIO、I2C、MMC、ETH、USB ├── include/ # 头文件 ├── lib/ # 库函数字符串、打印、数学 ├── cmd/ # 命令实现ls、mmc、bootm 等 ├── configs/ # 板级配置文件 ├── Makefile # 编译入口 └── Kconfig # 配置菜单Boot ROM 加载的 SPL 代码arch/arm/mach-xxx/ # SoC 厂商底层mach-imx/ mach-rockchip/ mach-sunxi arch/arm/cpu/armv7/start.S # SPL 入口汇编 spl/ # SPL 专用代码U-Boot 最入口汇编阶段arch/arm/cpu/armv7/start.S # 整个 U-Boot 入口点 _start arch/arm/lib/crt0.S # 准备 C 语言运行环境清零 bss、设置栈C 语言第一阶段早期初始化common/board_f.c # board_init_f() 早期初始化C 语言第二阶段完整初始化common/board_r.c # board_init_r() 核心初始化 common/main.c # U-Boot 主循环、命令行板级硬件初始化board/xxx/xxx.c # 板级初始化最常改 board/xxx/Kconfig # 板级配置SoC 底层时钟、DDR、复位arch/arm/mach-imx/ # NXP i.MX 系列 arch/arm/mach-rockchip/ # 瑞芯微 RK 系列 arch/arm/mach-sunxi/ # 全志 SOC存储驱动MMC/SD/eMMC/SPI Flash/NANDdrivers/mmc/ # SD / eMMC drivers/spi/ # SPI 控制器 drivers/mtd/spi/ # SPI Nor Flash drivers/mtd/nand/ # NAND Flash网口、USB、串口drivers/net/ # 以太网 drivers/usb/ # USB drivers/serial/ # 串口uboot命令cmd/boot.c # boot、bootm、booti cmd/mmc.c # mmc read / write cmd/fat.c # fatload、fatls cmd/nand.c # nand 命令 cmd/bootz.c # 启动 zImage 内核环境变量、启动参数common/env_common.c # 环境变量通用逻辑 env/ # env 存储MMC、Flash、FAT内核启动核心common/bootm.c # bootm 命令启动内核 common/image.c # 内核镜像、设备树处理bootm /booti这两个命令是U-Boot 启动 Linux 内核的核心命令作用都是跳转到内核、启动系统区别只在于内核镜像格式不同。bootm启动U-Boot 专用镜像格式uImage适用镜像uImage特点用mkimage工具给 zImage加了 64 字节 U-Boot 头包含校验和、加载地址、入口地址、时间戳等老 ARM 平台ARM9、ARM11、Cortex-A8 早期用得多ARM64 不支持 bootmbooti启动Linux 原生裸镜像Image/zImage适用镜像ImageARM64、zImageARM32特点Linux 内核原生编译出来的格式没有 U-Boot 头需要配合设备树 DTB一起启动ARM64 平台只能用 booti不能用 bootm
uboot 启动流程
发布时间:2026/5/28 19:14:35
U-Boot 整个流程分为4 大阶段Boot ROM芯片固化代码SPLU-Boot SPL / Secondary Program LoaderU-Boot 主程序u-boot.bin/u-boot.img启动 Linux Kernel阶段 1Boot ROMSoC 出厂固化上电复位CPU 从Boot ROM 固定地址开始执行初始化时钟、引脚、片上 SRAM读取 Boot Strapping Pin判断启动介质SD/eMMC/SPI/NAND从启动介质的固定偏移位置读取SPL将 SPL 加载到片上 SRAM校验可选安全启动后跳转到 SPL 入口这就是你上一问的Boot ROM 如何加载 SPL阶段 2SPLU-Boot SPLSPL 是极小版本的 U-Boot因为片上 SRAM 很小只能放几十 KB。SPL 核心任务只有一个初始化 DDR然后加载完整 U-Boot 到 DDR具体步骤进一步初始化时钟、PLL、电源初始化DDR 控制器 DDR PHY最关键从启动介质读取完整 U-Boot 镜像将 U-Boot 加载到DDR 内存跳转到 DDR 中的U-Boot 入口SPL 执行完就彻底退出不再回来阶段 3U-Boot 主程序真正的 U-Boot这部分代码在 DDR 里运行功能完整。分为汇编启动阶段和C 语言阶段。3.1 汇编阶段start.S设置 CPU 模式SVC/EL3/EL2关中断、关 MMU、关 Cache设置栈指针 SP清零 BSS 段调用 C 语言入口函数board_init_f3.2 C 语言第一阶段board_init_f初始化基础硬件时钟、串口、DDR初始化全局数据结构体gd_t准备重定位地址跳转到board_init_r3.3 C 语言第二阶段board_init_r这是 U-Boot 最核心的初始化阶段初始化各种外设GPIOI2C、SPIMMC/eMMC/SDEthernet、USBNAND、Flash 等初始化命令系统初始化环境变量env显示控制台提示符进入主循环等待命令 或 自动启动内核3.4 自动启动逻辑U-Boot 倒计时结束后执行run bootcmdbootcmd通常做这些事从 MMC/Flash/NET 读取设备树 dtb读取Linux 内核镜像 zImage/Image设置启动参数bootargs调用bootm/booti启动内核阶段 4启动 Linux KernelU-Boot 校验内核镜像准备设备树DTB地址填充内核启动参数跳转到内核入口地址U-Boot 生命周期结束CPU 控制权交给 LinuxU-Boot 启动总览[SoC 上电/复位] ↓ [BootROM (BL1, 片内ROM)] ↓ [SPL (BL2, 片内SRAM)] ↓ [U-Boot 主体 (DRAM)] ↓ [引导 Linux 内核]BootROM 阶段BL1硬件复位从固定 ROM 地址执行最小初始化时钟、看门狗、片内 SRAM检测启动介质eMMC/SD/NAND/QSPI加载 SPL 到片内 SRAM跳转至 SPL 入口_startSPL 阶段BL2SRAM 执行SPL _start (start.S) ↓ reset: 设置SVC模式、关中断、关MMU/Cache ↓ lowlevel_init: 初始化DDR控制器、训练DDR ↓ _main (crt0.S): 分配临时栈、初始化gd ↓ board_init_f: 初始化串口、打印启动信息、计算重定位地址 ↓ relocate_code: 从Flash/QSPI加载U-Boot主体到DRAM ↓ 清除BSS段 ↓ 跳转至 DRAM 中 U-Boot 的 _startU-Boot 主体阶段DRAM 执行3.1 重定位前Pre-RelocationU-Boot _start (start.S) ↓ reset: 同SPL关中断、关MMU/Cache ↓ _main (crt0.S): 1. 分配栈与gd全局数据区 2. board_init_f: 初始化串口、时钟、DRAM、环境变量基础、打印版本 3. 计算重定位偏移量 4. relocate_code: 将U-Boot自身从低地址搬移到DRAM高地址 5. relocate_vectors: 重定位中断向量表 6. 清除BSS段 ↓ 跳转至 board_init_r重定位后地址3.2 重定位后Post-Relocationboard_init_r: 1. 完整初始化外设MMC/SD、以太网、USB、I2C、SPI、NAND 2. 加载并解析环境变量env_import 3. 初始化命令行、设备树FDT 4. 进入 run_main_loop ↓ run_main_loop: - 启动倒计时autoboot - 倒计时结束 → 执行 bootcmd - 倒计时内按回车 → 进入 U-Boot Shell引导 Linux 内核bootcmd 执行执行 bootcmd如bootz 0x80800000 - 0x83000000 ↓ do_bootz / do_bootm: 1. 关闭中断 2. 加载内核镜像、DTB到DRAM 3. 解析内核头部、校验 4. 处理设备树注入 bootargs 到 /chosen 节点 5. 按 Linux ABI 设置寄存器 - r0 0 - r1 Machine IDARM32/ 0ARM64 - r2 DTB 物理地址 ↓ boot_jump_linux: 关闭Cache、跳转至内核入口 ↓ Linux 内核开始执行完整启动流程图SoC 上电 ↓ BootROM (ROM) ↓ 加载 SPL 到 SRAM ↓ SPL _start → reset → lowlevel_init (DDR) → _main → board_init_f → 加载 U-Boot 到 DRAM → 跳转 U-Boot _start ↓ U-Boot _start → reset → _main → board_init_f → relocate_code搬移自身→ 清除BSS → 跳转 board_init_r ↓ board_init_r → 外设初始化 → 环境变量 → run_main_loop ↓ ┌───────────────────────────────────────────────────┐ │ 倒计时结束 → 执行 bootcmd → bootz/bootm → 加载内核DTB → 跳转内核 │ │ 按回车 → U-Boot Shell可手动执行命令 │ └───────────────────────────────────────────────────┘ ↓ Linux 内核启动关键函数与文件ARM64/ARM32入口arch/arm/cpu/armv8/start.SARM64/start.SARM32SPL 主流程arch/arm/lib/crt0.S→_main重定位前初始化common/board_f.c→board_init_f重定位后初始化common/board_r.c→board_init_r引导内核common/bootm.c→do_bootm/do_bootzU-Boot 代码路径对应表最顶层目录uboot/ ├── arch/ # 架构相关代码ARM、RISC-V、x86 ├── board/ # 开发板硬件相关最常改 ├── common/ # 通用命令、主循环、核心逻辑 ├── drivers/ # 所有驱动GPIO、I2C、MMC、ETH、USB ├── include/ # 头文件 ├── lib/ # 库函数字符串、打印、数学 ├── cmd/ # 命令实现ls、mmc、bootm 等 ├── configs/ # 板级配置文件 ├── Makefile # 编译入口 └── Kconfig # 配置菜单Boot ROM 加载的 SPL 代码arch/arm/mach-xxx/ # SoC 厂商底层mach-imx/ mach-rockchip/ mach-sunxi arch/arm/cpu/armv7/start.S # SPL 入口汇编 spl/ # SPL 专用代码U-Boot 最入口汇编阶段arch/arm/cpu/armv7/start.S # 整个 U-Boot 入口点 _start arch/arm/lib/crt0.S # 准备 C 语言运行环境清零 bss、设置栈C 语言第一阶段早期初始化common/board_f.c # board_init_f() 早期初始化C 语言第二阶段完整初始化common/board_r.c # board_init_r() 核心初始化 common/main.c # U-Boot 主循环、命令行板级硬件初始化board/xxx/xxx.c # 板级初始化最常改 board/xxx/Kconfig # 板级配置SoC 底层时钟、DDR、复位arch/arm/mach-imx/ # NXP i.MX 系列 arch/arm/mach-rockchip/ # 瑞芯微 RK 系列 arch/arm/mach-sunxi/ # 全志 SOC存储驱动MMC/SD/eMMC/SPI Flash/NANDdrivers/mmc/ # SD / eMMC drivers/spi/ # SPI 控制器 drivers/mtd/spi/ # SPI Nor Flash drivers/mtd/nand/ # NAND Flash网口、USB、串口drivers/net/ # 以太网 drivers/usb/ # USB drivers/serial/ # 串口uboot命令cmd/boot.c # boot、bootm、booti cmd/mmc.c # mmc read / write cmd/fat.c # fatload、fatls cmd/nand.c # nand 命令 cmd/bootz.c # 启动 zImage 内核环境变量、启动参数common/env_common.c # 环境变量通用逻辑 env/ # env 存储MMC、Flash、FAT内核启动核心common/bootm.c # bootm 命令启动内核 common/image.c # 内核镜像、设备树处理bootm /booti这两个命令是U-Boot 启动 Linux 内核的核心命令作用都是跳转到内核、启动系统区别只在于内核镜像格式不同。bootm启动U-Boot 专用镜像格式uImage适用镜像uImage特点用mkimage工具给 zImage加了 64 字节 U-Boot 头包含校验和、加载地址、入口地址、时间戳等老 ARM 平台ARM9、ARM11、Cortex-A8 早期用得多ARM64 不支持 bootmbooti启动Linux 原生裸镜像Image/zImage适用镜像ImageARM64、zImageARM32特点Linux 内核原生编译出来的格式没有 U-Boot 头需要配合设备树 DTB一起启动ARM64 平台只能用 booti不能用 bootm