--- title: U-Boot启动流程详解 tags: [U-Boot, 启动流程, 嵌入式, Makefile, ARM] created: 2026-09-17 updated: 2026-09-17 pdf_ref: - "36_第三十一章 U-Boot顶层Makefile详解.pdf" - "37_第三十二章 U-Boot启动流程详解.pdf" --- # U-Boot启动流程详解 > **关联知识**: [[01-ARM架构与裸机编程/02-ARM汇编与启动流程]] | [[06-系统移植与启动/01-U-Boot基础与命令]] ## 一、U-Boot源码结构 ### 1.1 目录总览 ```mermaid mindmap root((U-Boot源码)) arch/ 体系结构 board/ 板级支持 cmd/ 命令实现 common/ 通用代码 drivers/ 设备驱动 configs/ 配置文件 include/ 头文件 Makefile 顶层构建 ``` ### 1.2 核心目录详解 | 目录 | 用途 | 关键子目录 | | ---------- | ---------------- | -------------------------------- | | `arch/` | 体系结构相关代码 | `arm/`, `arm64/`, `riscv/` | | `board/` | 板级定制代码 | `freescale/`, `ti/`, `rockchip/` | | `cmd/` | U-Boot命令实现 | `bootm.c`, `md.c`, `tftp.c` | | `common/` | 通用启动代码 | `main.c`, `bootm.c`, `cli.c` | | `drivers/` | 设备驱动程序 | `serial/`, `mmc/`, `net/` | | `fs/` | 文件系统支持 | `ext4/`, `fat/`, `ubifs/` | | `include/` | 头文件 | `configs/`, `asm/` | | `net/` | 网络协议栈 | `tftp.c`, `nfs.c`, `bootp.c` | | `lib/` | 库函数 | `string.c`, `printf.c` | | `tools/` | 构建工具 | `mkimage`, `binman` | ### 1.3 架构目录详解 (arch/arm) ```text arch/arm/ +-- cpu/ | +-- armv7/ | | +-- start.S # reset、save_boot_params、cpu_init_cp15、cpu_init_crit | | +-- lowlevel_init.S# 低级初始化(设置 SP、调用 s_init) | +-- u-boot.lds # 链接脚本模板(编译后生成根目录 u-boot.lds) +-- imx-common/ # NXP i.MX系列通用代码 +-- mach-mx6/ # i.MX6系列SoC支持 +-- lib/ | +-- vectors.S # _start 与中断向量表 | +-- crt0.S # _main 与 C 运行时初始化 | +-- relocate.S # relocate_code / relocate_vectors +-- include/asm/arch-mx6/ # i.MX6寄存器定义 ``` ### 1.4 板级目录结构 ```text board/freescale/ +-- mx6ullevk/ # NXP官方开发板 | +-- mx6ullevk.c | +-- imximage-ddr512.cfg.cfgtmp | +-- plugin.S +-- mx6ull_alientek_emmc/ # 正点原子EMMC版 | +-- mx6ull_alientek_emmc.c | +-- imximage-ddr512.cfg.cfgtmp | +-- panel.c +-- mx6ull_alientek_nand/ # 正点原子NAND版 +-- common/ +-- etherboot.c ``` ### 1.5 关键文件说明 | 文件 | 说明 | 重要程度 | | -------------------------------------------- | ------------- | -------- | | `arch/arm/cpu/armv7/start.S` | 启动入口代码 | 最高 | | `arch/arm/lib/crt0.S` | C运行时初始化 | 最高 | | `arch/arm/lib/vectors.S` | 中断向量表 | 高 | | `arch/arm/cpu/u-boot.lds` | 链接脚本模板 | 高 | | `board/freescale/mx6ull_alientek_emmc/` | 板级支持包 | 高 | | `include/configs/mx6ull_alientek_emmc.h` | 板级配置 | 最高 | | `configs/mx6ull_14x14_ddr512_emmc_defconfig` | 默认配置 | 最高 | ### 1.6 编译生成的关键文件 | 文件 | 来源 | 用途 | | ------------------ | --------------- | ------------------ | | `u-boot` | ELF格式镜像 | 调试用 | | `u-boot.bin` | objcopy生成 | 二进制可执行镜像 | | `u-boot-nodtb.bin` | 无设备树版本 | u-boot.bin的源文件 | | `u-boot.imx` | mkimage添加头部 | NXP专用,含IVT/DCD | | `u-boot.lds` | 链接脚本 | 定义内存布局 | | `u-boot.map` | 映射文件 | 查看函数链接地址 | | `.config` | 配置文件 | 编译选项 | ### 1.7 .u-boot.xxx_cmd 文件分析 ```bash # .u-boot.bin.cmd - 生成u-boot.bin cmd_u-boot.bin := cp u-boot-nodtb.bin u-boot.bin # .u-boot-nodtb.bin.cmd - ELF转二进制 cmd_u-boot-nodtb.bin := arm-linux-gnueabihf-objcopy \ --gap-fill=0xff -j .text -j .secure_text -j .rodata -j .hash \ -j .data -j .got -j .got.plt -j .u_boot_list -j .rel.dyn \ -O binary u-boot u-boot-nodtb.bin # .u-boot.imx.cmd - 生成NXP专用镜像 cmd_u-boot.imx := ./tools/mkimage \ -n board/freescale/mx6ull_alientek_emmc/imximage.cfg.cfgtmp \ -T imximage -e 0x87800000 -d u-boot.bin u-boot.imx ``` --- ## 二、顶层Makefile详解 ### 2.1 Makefile 核心变量 ```makefile # 版本信息(顶层 Makefile 第 5~9 行) VERSION = 2016 PATCHLEVEL = 03 SUBLEVEL = EXTRAVERSION = NAME = # VERSION/PATCHLEVEL/SUBLEVEL 共同构成 2016.03;EXTRAVERSION、NAME 一般不使用 # 交叉编译工具链(第 245~246 行:主机架构==目标架构时 CROSS_COMPILE 为空) ifeq ($(HOSTARCH),$(ARCH)) CROSS_COMPILE ?= endif # 实际编译时通过 make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- 传入, # 也可直接在顶层 Makefile 中写死 ARCH=arm / CROSS_COMPILE=arm-linux-gnueabihf- ``` 以下`CONFIG_SYS_*`来自板级配置头文件(经`make xxx_defconfig`写入`.config`),而非顶层 Makefile: ```text CONFIG_SYS_ARCH="arm" CONFIG_SYS_CPU="armv7" CONFIG_SYS_SOC="mx6" CONFIG_SYS_VENDOR="freescale" CONFIG_SYS_BOARD="mx6ull_alientek_emmc" CONFIG_SYS_CONFIG_NAME="mx6ull_alientek_emmc" CONFIG_SYS_TEXT_BASE=0x87800000 ``` ### 2.2 主要Makefile目标 | 命令 | 说明 | | -------------------- | --------------- | | `make xxx_defconfig` | 配置U-Boot | | `make menuconfig` | 图形化配置 | | `make all` | 编译所有目标 | | `make u-boot.bin` | 生成二进制镜像 | | `make u-boot.imx` | 生成NXP专用镜像 | | `make clean` | 清理编译文件 | | `make mrproper` | 彻底清理 | ### 2.3 配置过程详解 ```mermaid flowchart TD A[make xxx_defconfig] --> B[silentoldconfig] B --> C[生成 .config] C --> D[生成 include/config/] D --> E[生成 include/generated/] E --> F[配置完成] ``` ### 2.4 编译规则详解 ```makefile # 目标依赖关系(顶层 Makefile) u-boot: $(u-boot-init) $(u-boot-main) u-boot.lds FORCE $(call if_changed,u-boot__) u-boot-nodtb.bin: u-boot FORCE $(call if_changed,objcopy) $(call DO_STATIC_RELA,$<,$@,$(CONFIG_SYS_TEXT_BASE)) u-boot.bin: u-boot-nodtb.bin FORCE $(call if_changed,copy) # 即 cp u-boot-nodtb.bin u-boot.bin # u-boot-init = $(head-y) = arch/arm/cpu/armv7/start.o # u-boot-main = $(libs-y) = 所有子目录的 built-in.o ``` 展开后实际执行的链接命令(来自 `.u-boot.cmd`): ```bash arm-linux-gnueabihf-ld.bfd -pie --gc-sections -Bstatic -Ttext 0x87800000 \ -o u-boot -T u-boot.lds arch/arm/cpu/armv7/start.o \ --start-group arch/arm/cpu/built-in.o arch/arm/cpu/armv7/built-in.o \ arch/arm/imx-common/built-in.o arch/arm/lib/built-in.o \ board/freescale/common/built-in.o \ board/freescale/mx6ull_alientek_emmc/built-in.o \ cmd/built-in.o common/built-in.o disk/built-in.o drivers/built-in.o \ ... fs/built-in.o lib/built-in.o net/built-in.o ... --end-group \ arch/arm/lib/eabi_compat.o -lgcc -Map u-boot.map ``` `u-boot.lds` 的生成规则:`u-boot.lds: $(LDSCRIPT) prepare FORCE`(`$(LDSCRIPT)` 即 `arch/arm/cpu/u-boot.lds`)。 ### 2.5 链接脚本关键配置 ```text OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") OUTPUT_ARCH(arm) ENTRY(_start) SECTIONS { . = 0x00000000; /* 注意:链接脚本里是 0x00000000,不是 0x87800000 */ . = ALIGN(4); .text : { *(.__image_copy_start) *(.vectors) arch/arm/cpu/armv7/start.o (.text*) *(.text*) } .rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) } .data : { *(.data*) } .u_boot_list : { KEEP(*(SORT(.u_boot_list*))); } .image_copy_end : { *(.__image_copy_end) } .rel_dyn_start : { *(.__rel_dyn_start) } .rel.dyn : { *(.rel*) } .rel_dyn_end : { *(.__rel_dyn_end) } .end : { *(.__end) } _image_binary_end = .; .bss_start __rel_dyn_start (OVERLAY) : { KEEP(*(.__bss_start)); __bss_base = .; } .bss __bss_base (OVERLAY) : { *(.bss*) . = ALIGN(4); __bss_limit = .; } .bss_end __bss_limit (OVERLAY) : { KEEP(*(.__bss_end)); } ... } ``` > 真正的加载地址由链接时的 `-Ttext 0x87800000` 决定,链接脚本本身从 `0x00000000` 开始。入口点是 `_start`,定义在 `arch/arm/lib/vectors.S` 中,其后紧跟中断向量表(`.vectors` 段)。 **关键地址变量(示例编译值,以实际编译为准):** | 变量 | 数值 | 描述 | | -------------------- | ---------- | ------------------ | | `__image_copy_start` | 0x87800000 | U-Boot拷贝首地址 | | `__image_copy_end` | 0x8785dd54 | U-Boot拷贝结束地址 | | `__rel_dyn_start` | 0x8785dd54 | .rel.dyn段起始 | | `__rel_dyn_end` | 0x878668f4 | .rel.dyn段结束 | | `_image_binary_end` | 0x878668f4 | 镜像结束地址 | | `__bss_start` | 0x8785dd54 | BSS段起始 | | `__bss_end` | 0x878a8e74 | BSS段结束 | ### 2.6 编译选项详解 ```text # 链接选项(.u-boot.cmd) -pie # 位置无关可执行文件 --gc-sections # 回收未使用的段 -Bstatic # 静态链接 -Ttext 0x87800000 # U-Boot 链接/加载地址 # 生成 u-boot-nodtb.bin 时(.u-boot-nodtb.bin.cmd) --gap-fill=0xff $(call DO_STATIC_RELA,$<,$@,$(CONFIG_SYS_TEXT_BASE)) # 修正 .rel.dyn 重定位表 # 交叉工具变量(顶层 Makefile 第 333~347 行) CC = $(CROSS_COMPILE)gcc LD = $(CROSS_COMPILE)ld.bfd(若 ld.bfd 不可用则回退为 $(CROSS_COMPILE)ld) OBJCOPY = $(CROSS_COMPILE)objcopy AR = $(CROSS_COMPILE)ar NM = $(CROSS_COMPILE)nm OBJDUMP = $(CROSS_COMPILE)objdump ``` ### 2.7 Kbuild系统 ```mermaid flowchart TD A[Kconfig] --> B[配置系统] B --> C[.config] C --> D[Kbuild] D --> E[编译规则] E --> F[OBJ文件] F --> G[链接] G --> H[U-Boot镜像] ``` ### 2.8 编译日志分析 ```bash $ make mx6ull_14x14_ddr512_emmc_defconfig HOSTCC scripts/basic/fixdep HOSTCC scripts/kconfig/conf.o SHIPPED scripts/kconfig/conf # configuration written to .config $ make -j8 arm-linux-gnueabihf-gcc ... arch/arm/cpu/armv7/start.S arm-linux-gnueabihf-gcc ... arch/arm/lib/crt0.S ... arm-linux-gnueabihf-ld ... u-boot arm-linux-gnueabihf-objcopy ... u-boot-nodtb.bin cp u-boot-nodtb.bin u-boot.bin ./tools/mkimage ... u-boot.imx ``` --- ## 三、U-Boot启动流程 ### 3.1 启动流程总览 ```mermaid flowchart TD A[上电/复位] --> B[reset向量] B --> C[save_boot_params] C --> D[save_boot_params_ret] D --> E[cpu_init_cp15] E --> F[cpu_init_crit] F --> G[lowlevel_init] G --> H[_main入口] H --> I[board_init_f_alloc_reserve] I --> J[board_init_f] J --> K[relocate_code重定位] K --> L[relocate_vectors] L --> M[c_runtime_cpu_setup] M --> N[清零BSS段] N --> O[board_init_r] O --> P[main_loop主循环] ``` ### 3.2 启动阶段划分 > ⚠️ **来源说明**:本节不属于《I.MX6U嵌入式Linux驱动开发指南》内容,为扩展知识(书中未讲 SPL;此处用于说明 I.MX6U 与常见 SPL 架构的区别)。 I.MX6U 的 U-Boot **不是 SPL 架构**(默认直接使用完整的`u-boot.imx`)。上电后由芯片内部的 Boot ROM 把`u-boot.imx`加载到 DDR 的`0x87800000`处执行,之后 U-Boot 自身再经历“重定位前 → 重定位 → 重定位后”三个阶段: ```mermaid flowchart LR subgraph ROM[Boot ROM] A1[解析 u-boot.imx 头部] --> A2[加载到 DDR 0x87800000] end subgraph F[board_init_f(重定位前)] B1[初始化串口/定时器/DDR] --> B2[规划内存并计算重定位地址] end subgraph R[board_init_r(重定位后)] C1[初始化外设/MMC/网络] --> C2[环境变量/控制台] --> C3[main_loop 命令行] end subgraph Linux D1[加载内核与设备树] --> D2[传递参数] --> D3[跳转执行] end A2 --> B1 B2 --> R C3 --> D1 ``` **各阶段职责:** | 阶段 | 职责 | 关键函数 | | ------------------------ | -------------------------------------------------------------- | --------------------------------------- | | Boot ROM | 从启动设备加载`u-boot.imx`到 DDR | 芯片固化代码 | | board_init_f(重定位前) | 初始化串口/定时器/DDR,`init_sequence_f[]`,计算重定位目的地址 | `board_init_f()` | | 重定位 | 将 U-Boot 拷贝到 DDR 高地址,修正`.rel.dyn`,重定位向量表 | `relocate_code()`、`relocate_vectors()` | | board_init_r(重定位后) | 初始化 MMC/NAND/网络/环境变量,进入命令行 | `board_init_r()`、`main_loop()` | | Linux | 挂载rootfs,启动init | `boot_jump_linux()`、`kernel_entry()` | ### 3.3 内存布局 ```text OCRAM (内部RAM, 128KB): 0x00900000 +---------------------+ <- IRAM_BASE_ADDR | OCRAM | 0x0091FE08 +---------------------+ <- lowlevel_init 中 sp -= GD_SIZE(248) 0x0091FF00 +---------------------+ <- CONFIG_SYS_INIT_SP_ADDR (sp 初始值) 0x00920000 +---------------------+ OCRAM结束 (0x20000, 128KB) DRAM (外部DDR, 512MB): 0x80000000 +---------------------+ <- DRAM起始 (gd->ram_size=0x20000000) 0x80800000 +---------------------+ <- Linux内核(zImage)加载地址 0x83000000 +---------------------+ <- 设备树(dtb)加载地址 0x87800000 +---------------------+ <- U-Boot链接/初始加载地址 | U-Boot代码 | 0x878a8e74 +---------------------+ <- BSS段结束 (__bss_end) | ... | 0x9EF44E90 +---------------------+ <- 重定位后最终的 sp (gd->start_addr_sp) 0x9FF47000 +---------------------+ <- U-Boot重定位后的运行地址 (gd->relocaddr) | ... | 0xA0000000 +---------------------+ <- DRAM最高地址 (gd->ram_top) ``` ### 3.4 重定位前阶段(board_init_f) `_main`中先调用`board_init_f_alloc_reserve`预留早期 malloc 与 gd 区域,再调用`board_init_f`运行`init_sequence_f[]`,主要工作是初始化串口、定时器、DDR 等,并“自顶向下”规划内存,最终算出重定位目的地址。 ```text board_init_f(重定位前)职责: +-- 1. setup_mon_len:设置 gd->mon_len = __bss_end - _start +-- 2. arch_cpu_init / board_early_init_f:CPU 与板级早期初始化(串口 IO) +-- 3. timer_init / get_clocks:定时器与时钟 +-- 4. env_init / init_baud_rate / serial_init / console_init_f:环境变量、波特率、串口、控制台 +-- 5. dram_init:设置 gd->ram_size(正点原子 EMMC 版为 512MB) +-- 6. setup_dest_addr:设置 gd->ram_size、gd->ram_top=0xA0000000、gd->relocaddr=0xA0000000 +-- 7. reserve_*:从高地址向下依次预留 MMU TLB、U-Boot、malloc、bd、gd、栈等 +-- 8. setup_reloc:把旧 gd 拷贝到 gd->new_gd ``` 关键中间结果(示例):`gd->relocaddr = 0xA0000000` → `reserve_mmu`后 `0x9FFF0000` → `reserve_uboot`后 `0x9FF47000` → `reserve_malloc`(16MB+8KB)后 `0x9EF45000` → `reserve_board`(80B)→ `reserve_global_data`(248B)→ `reserve_stacks` 后最终 `gd->start_addr_sp = 0x9EF44E90`。 ### 3.5 U-Boot主阶段详解 ```text U-Boot主阶段职责: +-- 1. 初始化更多外设 (NAND/EMMC/USB/网络/显示) +-- 2. 网络初始化 (网卡驱动/IP配置/TFTP/NFS) +-- 3. 命令初始化 (注册命令/解析bootargs/启动脚本) +-- 4. 环境变量处理 (读取/设置默认值/保存) +-- 5. 启动Linux内核 (加载zImage/设备树/传递参数/跳转) ``` ### 3.6 重定位过程 ```mermaid flowchart TD A[board_init_f执行] --> B[计算重定位地址] B --> C[复制U-Boot到新位置] C --> D[修正重定位表] D --> E[更新全局数据指针] E --> F[跳转到新地址继续执行] F --> G[board_init_r执行] ``` ### 3.7 网络初始化 ```text 网络初始化流程: +-- 1. 网卡驱动初始化 (读取MAC/配置PHY/初始化DMA) +-- 2. 网络协议栈初始化 (ARP/IP/UDP/TFTP/NFS) +-- 3. 网络参数配置 | +-- ipaddr - 开发板IP | +-- serverip - 服务器IP | +-- gatewayip - 网关 | +-- netmask - 子网掩码 +-- 4. 网络测试 (ping/TFTP下载) ``` ### 3.8 命令初始化 ```c // 常用启动命令 bootm [addr] [initrd] [fdt] // 启动内核镜像 bootz [addr] [initrd] [fdt] // 启动zImage内核 run