2. U-Boot 源码结构分析:顶层目录结构、board目录、arch目录、include/configs目录、common目录功能解析
U-Boot 源码采用分层模块化设计,理解其目录结构是进行移植与调试的第一步。本章将深入解析五个核心目录:顶层根目录、板级支持目录 board/、架构相关目录 arch/、配置头文件目录 include/configs/ 以及通用功能目录 common/。
学习提示: 在阅读源码时,建议从顶层 Makefile 和
include/configs/ 下的板级配置入手,再逐步深入到 arch/ 和 board/ 目录,这样能快速建立从“配置”到“硬件初始化”的全局视图。
2.1 顶层目录结构总览
U-Boot 顶层目录是项目的根,包含了构建系统、核心框架、文档和工具。下表列出了关键目录及其职责:
| 目录/文件 | 功能描述 | 移植关注度 |
|---|---|---|
arch/ |
CPU 架构相关代码(ARM、RISC-V、x86 等) | ★★★★★ |
board/ |
特定板级初始化代码(DDR、GPIO、时钟等) | ★★★★★ |
common/ |
通用命令、控制台、环境变量、启动逻辑 | ★★★★☆ |
include/ |
全局头文件,包括 configs/ 板级配置 |
★★★★★ |
drivers/ |
设备驱动框架(串口、网卡、MMC、NAND 等) | ★★★☆☆ |
lib/ |
通用库函数(字符串、加密、CRC、时间等) | ★★☆☆☆ |
net/ |
网络协议栈(TFTP、NFS、DHCP 等) | ★★☆☆☆ |
fs/ |
文件系统支持(FAT、EXT4、UBIFS 等) | ★★☆☆☆ |
scripts/ |
构建脚本、DTB 编译、配置工具 | ★★☆☆☆ |
tools/ |
主机端工具(mkimage、fdtget 等) | ★☆☆☆☆ |
doc/ |
文档与 README | ★☆☆☆☆ |
下图展示了顶层目录之间的依赖关系与数据流:
2.2 board/ 目录:板级硬件初始化
board/ 目录存放与具体开发板强相关的初始化代码。每个板子通常有一个独立的子目录,命名规则为 board/<厂商>/<板名>/。该目录是移植 U-Boot 时修改最频繁的区域。
典型文件结构如下:
board/
└── myvendor/
└── myboard/
├── Kconfig # 板级 Kconfig 配置选项
├── Makefile # 编译规则
├── myboard.c # 板级初始化函数(board_init、dram_init 等)
├── myboard.h # 板级私有头文件
├── lowlevel_init.S # 极早期硬件初始化(时钟、DDR 控制器)
└── imx8mm_evk.c # 特定 SoC 的板级支持(如 i.MX8M Mini)
移植关键点: 在
board/ 目录中,lowlevel_init.S 负责在 C 环境运行前配置最基本的时钟和 DDR,而 myboard.c 中的 board_init_f() 和 dram_init() 是 U-Boot 启动流程中最早调用的 C 函数之一。
2.3 arch/ 目录:CPU 架构核心
arch/ 目录按 CPU 架构组织,例如 arch/arm/、arch/riscv/、arch/x86/。以 ARM 架构为例,其内部结构如下:
arch/arm/
├── cpu/ # 具体 CPU 核(armv7、armv8、arm11 等)
│ ├── armv7/
│ │ ├── start.S # 架构级启动入口(reset vector)
│ │ ├── cache_v7.c # 缓存管理
│ │ └── cpu.c # CPU 初始化
│ └── armv8/
│ ├── start.S # AArch64 启动入口
│ ├── exceptions.S
│ └── cache_v8.c
├── dts/ # 设备树源文件(.dts)
├── include/ # 架构相关头文件
│ └── asm/
│ ├── arch/ # SoC 级头文件
│ ├── global_data.h
│ └── io.h
├── lib/ # 架构通用库(memcpy、setjmp 等)
└── mach-*/ # SoC 厂商目录(mach-imx、mach-sunxi 等)
arch/arm/cpu/armv7/start.S 是 ARMv7 架构的入口点,它设置了异常向量表、切换到 SVC 模式、初始化栈指针,然后跳转到 board_init_f()。这是整个 U-Boot 启动流程的“第一行代码”。
2.4 include/configs/ 目录:板级配置头文件
include/configs/ 目录包含所有开发板的配置头文件,文件名通常为 <board_name>.h。这些头文件通过宏定义控制 U-Boot 的编译行为,是移植过程中最关键的配置入口。
一个典型的配置头文件片段如下:
/* include/configs/myboard.h */
#ifndef __MYBOARD_CONFIG_H
#define __MYBOARD_CONFIG_H
/* 内存配置 */
#define CONFIG_NR_DRAM_BANKS 1
#define PHYS_SDRAM 0x80000000
#define PHYS_SDRAM_SIZE 0x20000000 /* 512 MB */
/* 串口配置 */
#define CONFIG_CONS_INDEX 1
#define CONFIG_BAUDRATE 115200
#define CONFIG_SYS_NS16550
#define CONFIG_SYS_NS16550_SERIAL
#define CONFIG_SYS_NS16550_REG_SIZE -4
#define CONFIG_SYS_NS16550_COM1 0x021E8000
/* 环境变量存储 */
#define CONFIG_ENV_IS_IN_MMC
#define CONFIG_ENV_OFFSET 0xE0000
#define CONFIG_ENV_SIZE 0x20000
/* 启动命令 */
#define CONFIG_BOOTCOMMAND \
"mmc dev 0; fatload mmc 0:1 ${loadaddr} kernel.itb; bootm ${loadaddr}"
/* 网络配置 */
#define CONFIG_IPADDR 192.168.1.100
#define CONFIG_SERVERIP 192.168.1.10
#endif /* __MYBOARD_CONFIG_H */
常见错误: 在移植时,如果
include/configs/ 中的宏定义与设备树(.dts)中的属性冲突,U-Boot 会优先使用宏定义。务必确保两者一致,否则可能导致外设初始化失败。
2.5 common/ 目录:通用功能与启动逻辑
common/ 目录包含了 U-Boot 的通用功能模块,如控制台、命令解析、环境变量管理和主启动循环。该目录不依赖具体板级或架构,是 U-Boot 的“业务逻辑层”。
核心文件及其功能:
| 文件 | 功能 |
|---|---|
main.c |
U-Boot 主循环:初始化完成后进入命令行交互 |
board_r.c |
重定位后的板级初始化(board_init_r) |
board_f.c |
重定位前的板级初始化(board_init_f) |
console.c |
控制台输入输出管理 |
command.c |
命令注册与解析框架 |
env_common.c |
环境变量通用接口 |
autoboot.c |
自动启动逻辑(倒计时、按键中断) |
cli_hush.c |
Hush shell 解析器(支持脚本) |
下图展示了 common/ 目录在启动流程中的位置:
2.6 目录间协作关系总结
U-Boot 的启动流程本质上是这四个目录的协作过程:
- arch/ 提供 CPU 级入口和异常处理,设置最基本的执行环境。
- board/ 提供板级硬件初始化代码,如 DDR 时序、GPIO 复用。
- include/configs/ 通过宏定义控制 board/ 和 arch/ 的编译路径。
- common/ 提供启动主循环,调用 board/ 和 arch/ 的函数,最终进入命令行。
调试建议: 当 U-Boot 无法启动时,首先检查
include/configs/ 中的内存地址和串口基地址是否正确;然后通过 arch/arm/cpu/start.S 中的 LED 点灯或串口输出定位死机位置;最后检查 board/ 中的 dram_init() 返回值是否与硬件匹配。