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 ★☆☆☆☆

下图展示了顶层目录之间的依赖关系与数据流:

U-Boot 顶层目录依赖关系图 顶层 Makefile arch/ (架构核心) board/ (板级硬件) include/configs/ common/ (通用逻辑) drivers/ (设备驱动) lib/ (基础库) net/ (网络协议) fs/ (文件系统) 说明: • arch/ 和 board/ 是移植的核心,直接与硬件交互。 • include/configs/ 通过宏定义控制整个编译流程。 • common/ 提供启动主循环和命令解析,依赖 drivers/ 和 lib/。

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/ 目录在启动流程中的位置:

common/ 目录在启动流程中的角色 arch/arm/cpu/start.S 架构级入口 common/board_f.c board_init_f() common/board_r.c board_init_r() common/main.c 主循环 (cli_loop) • board_f.c 在重定位前执行,负责初始化串口、时钟、DDR 等。 • board_r.c 在重定位后执行,初始化完整驱动栈,最后进入 main.c 的命令循环。

2.6 目录间协作关系总结

U-Boot 的启动流程本质上是这四个目录的协作过程:

  1. arch/ 提供 CPU 级入口和异常处理,设置最基本的执行环境。
  2. board/ 提供板级硬件初始化代码,如 DDR 时序、GPIO 复用。
  3. include/configs/ 通过宏定义控制 board/ 和 arch/ 的编译路径。
  4. common/ 提供启动主循环,调用 board/ 和 arch/ 的函数,最终进入命令行。
调试建议: 当 U-Boot 无法启动时,首先检查 include/configs/ 中的内存地址和串口基地址是否正确;然后通过 arch/arm/cpu/start.S 中的 LED 点灯或串口输出定位死机位置;最后检查 board/ 中的 dram_init() 返回值是否与硬件匹配。