2. U-Boot源码结构:顶层目录、board、arch、common、drivers等关键目录解析
拿到一份U-Boot源码,第一件事是什么?我个人的习惯是——先看目录结构。别急着编译,也别急着改代码。你得先搞清楚,这个庞大的工程里,什么东西放在哪里。
U-Boot的源码目录,说白了就是一套高度模块化的嵌入式启动方案。它不像Linux内核那么复杂,但麻雀虽小五脏俱全。今天我就带你走一遍,把那些关键目录挨个说清楚。
2.1 顶层目录:一眼看穿全局
解压U-Boot源码后,你会在顶层看到一堆文件和文件夹。我挑几个最重要的说:
| 目录/文件 | 作用 | 我的经验 |
|---|---|---|
| board/ | 板级相关代码,每个板子一个子目录 | 移植时最常改的地方 |
| arch/ | CPU架构相关代码(ARM、RISC-V、x86等) | 启动汇编就在这里 |
| common/ | 通用核心功能,如命令行、环境变量 | 调试时经常翻 |
| drivers/ | 各种外设驱动(串口、网卡、Flash等) | 加新硬件必看 |
| include/ | 头文件、配置宏定义 | 配置板子全靠它 |
| configs/ | 默认配置文件(defconfig) | make xxx_defconfig 的源头 |
| scripts/ | 编译脚本、Kconfig工具 | 一般不用动 |
| tools/ | 主机端工具(mkimage等) | 打包镜像时用 |
嗯,这里要注意:board/ 和 arch/ 是移植工作的主战场。其他目录虽然也重要,但大部分时候你不需要动它们。
2.2 board/ 目录:板级代码的根据地
每个板子都在 board/ 下有自己的文件夹。命名规则一般是 board/厂商/板子名。比如:
board/
├── freescale/
│ ├── mx6ul_14x14_evk/
│ └── ls1046ardb/
├── rockchip/
│ ├── evb_rk3399/
│ └── tinker_board/
└── mycompany/
└── myboard/ ← 你自己新建的板子目录
这个目录里放什么?说白了就是三样东西:
- 板子初始化代码(如
board.c、board_init.c) - 板级设备树文件(.dts 或 .dtsi)
- 板子特有的配置头文件
2.3 arch/ 目录:CPU架构的核心
U-Boot支持多种CPU架构。以最常用的ARM为例,arch/arm/ 下的结构是这样的:
arch/arm/
├── cpu/ ← CPU核心代码
│ ├── armv7/
│ ├── armv8/
│ └── ...
├── dts/ ← 设备树文件
├── include/ ← 架构相关头文件
├── lib/ ← 架构通用库函数
└── mach-*/ ← 厂商SoC相关代码
这里有个关键点:启动时的第一条指令就在 arch/arm/cpu/ 下。我记得第一次看U-Boot启动流程时,在 arch/arm/cpu/armv7/start.S 里找了半天入口。那个文件里就是最底层的汇编代码——设置CPU模式、关中断、初始化栈指针。
2.4 common/ 目录:U-Boot的“内脏”
common/ 目录包含了U-Boot的核心功能模块。这里的东西,你几乎每天都会打交道:
- main.c — U-Boot的主循环入口
- command/ — 所有命令行命令的实现(如
md、mw、bootm) - env/ — 环境变量管理(保存、加载、默认值)
- bootm.c — 启动内核的核心逻辑
- console.c — 控制台输入输出
你想想看,你在U-Boot命令行里敲的每一个命令,背后都是 common/command/ 里的代码在干活。如果你要添加自定义命令,也是在这里加。
2.5 drivers/ 目录:硬件驱动的仓库
U-Boot的驱动模型(Driver Model)把所有外设驱动都放在 drivers/ 下。按功能分类:
| 子目录 | 驱动类型 | 典型场景 |
|---|---|---|
| serial/ | 串口驱动 | 调试输出、控制台 |
| net/ | 网卡驱动 | TFTP下载、网络启动 |
| mmc/ | SD卡/eMMC驱动 | 从存储设备加载镜像 |
| spi/ | SPI Flash驱动 | 存储U-Boot本身 |
| usb/ | USB主机/设备驱动 | U盘启动、USB下载 |
| gpio/ | GPIO驱动 | 控制LED、复位等 |
这里有个趋势:新版本的U-Boot越来越依赖设备树来配置驱动。你不需要在C代码里硬编码引脚信息,而是在.dts文件里描述硬件,驱动自己解析。这样做的好处是——换板子时,改设备树就行,驱动代码不用动。
2.6 其他重要目录
除了上面几个,还有几个目录值得提一下:
- include/configs/ — 板级配置头文件。老版本U-Boot全靠这个文件配置,新版本逐渐被Kconfig替代,但很多项目还在用。
- configs/ — 默认配置文件。执行
make xxx_defconfig时,就是从这读取配置。 - lib/ — 通用库函数,比如字符串处理、CRC校验、sha256等。
- fs/ — 文件系统支持(ext4、fat、ubifs等)。
2.7 一张图看懂U-Boot源码结构
说了这么多,不如一张图来得直观。下面这张SVG图展示了U-Boot源码的核心目录层次和它们之间的关系:
2.8 总结一下:移植时你该关注什么
说了这么多,其实就一句话:移植U-Boot,本质上就是填好 board/、配好 arch/、选好 drivers/。具体来说:
- 先找参考板 — 在 board/ 下找一个和你硬件最接近的板子
- 复制并改名 — 整个目录复制,改成你的板子名
- 改配置 — 修改 include/configs/ 下的头文件,或者用Kconfig重新配置
- 调驱动 — 在 drivers/ 下找到对应的外设驱动,确认是否支持你的芯片
- 编译测试 — 用
make编译,烧录到板子上看串口输出
核心原则: 不要试图一次性理解所有目录。你只需要关注 board/、arch/、configs/ 和 drivers/ 这四个目录。其他目录,用到的时候再去看。