U-Boot 顶层 Makefile 详解
1、U-Boot 工程目录分析
我们在分析 uboot 源码之前一定要
先在 Ubuntu 中编译一下 uboot 源码,因为编译过程会生成一些文件,而生成的这些恰恰是分析
uboot 源码不可或缺的文件。使用上一章创建的 shell 脚本来完成编译工作,命令如下:
cd alientek_uboot //进入正点原子 uboot 源码目录
./mx6ull_alientek_emmc.sh //编译 uboot
cd ../ //返回上一级目录
tar -vcjf alientek_uboot.tar.bz2 alientek_uboot //压缩
这些文件夹或文件的含义见表 31.1.1 所示:
名字 | 描述 | 备注 |
---|---|---|
api | 与硬件无关的 API 函数。 | uboot 自带 |
arch | 与架构体系有关的代码。 | uboot 自带 |
board | 不同板子(开发板)的定制代码。 | uboot 自带 |
cmd | 命令相关代码。 | uboot 自带 |
common | 通用代码。 | uboot 自带 |
configs | 配置文件。 | uboot 自带 |
disk | 磁盘分区相关代码 | uboot 自带 |
doc | 文档。 | uboot 自带 |
drivers | 驱动代码。 | uboot 自带 |
dts | 设备树。 | uboot 自带 |
examples | 示例代码。 | uboot 自带 |
fs | 文件系统。 | uboot 自带 |
include | 头文件。 | uboot 自带 |
lib | 库文件。 | uboot 自带 |
Licenses | 许可证相关文件。 | uboot 自带 |
net | 网络相关代码。 | uboot 自带 |
post | 上电自检程序。 | uboot 自带 |
scripts | 脚本文件。 | uboot 自带 |
test | 测试代码。 | uboot 自带 |
tools | 工具文件夹。 | uboot 自带 |
.config 配置文件, | 重要的文件。 | 编译生成的文件 |
.gitignore git | 工具相关文件。 | uboot 自带 |
.mailmap | 邮件列表。 | uboot 自带 |
.u-boot.xxx.cmd(一系列) | 这是一系列的文件,用于保存着一些命令。 | 编译生成的文件 |
config.mk | 某个 Makefile 会调用此文件。 | uboot 自带 |
imxdownload | 正点原子编写的 SD 卡烧写软件。 | 正点原子提供 |
Kbuild | 用于生成一些和汇编有关的文件。 | uboot 自带 |
Kconfig | 图形配置界面描述文件。 | uboot 自带 |
MAINTAINERS | 维护者联系方式文件。 | uboot 自带 |
MAKEALL | 一个 shell 脚本文件,帮助编译uboot 的。 | uboot 自带 |
Makefile | 主 Makefile,重要文件! | uboot 自带 |
mx6ull_alientek_emmc.sh | 上一章编写的编译脚本文件 | 上一章编写的。 |
mx6ull_alientek_nand.sh | 上一章编写的编译脚本文件 | 上一章编写的。 |
README | 相当于帮助文档。 | uboot 自带 |
snapshot.commint | ??? | uboot 自带 |
System.map | 系统映射文件 | 编译出来的文件 |
u-boot | 编译出来的 u-boot 文件。 | 编译出来的文件 |
u-boot.xxx(一系列) | 生成的一些 u-boot 相关文件,包括u-boot.bin、 u-boot.imx.等 | 编译出来的文件 |
我们要关注的文件夹或文件如下:
1、 arch 文件夹
这个文件夹里面存放着和架构有关的文件,我们现在用的是 ARM 芯
片,所以只需要关心 arm 文件夹即可。mach 开头的文件夹是跟具体
的设备有关的,比如“ mach-exynos”就是跟三星的 exyons 系列 CPU 有关的文件。我们使用的
是 I.MX6ULL,所以要关注“ imx-common”这个文件夹。另外“ cpu”这个文件夹也是和 cpu 架
构有关的,I.MX6ULL 使用的 Cortex-A7 内核,Cortex-A7 属于 armv7,所以我们要关心“ armv7”这个文件夹。
cpu 文件夹里面有个名为“ uboot.lds”的链接脚本文件,这个就是 ARM 芯片所使用的 u-boot 链接脚本文件! armv7 这个文
件夹里面的文件都是跟 ARMV7 架构有关的,是我们分析 uboot 启动源码的时候需要重点关注
的。
2、 board 文件夹
board 文件夹就是和具体的板子有关的,打开此文件夹,里面全是不同的板子,毫无疑问正
点原子的开发板肯定也在里面(正点原子添加的), borad 文件夹里面有个名为“ freescale”的文
件夹。
所有使用 freescale 芯片的板子都放到此文件夹中, I.MX 系列以前属于 freescale,只是
freescale 后来被 NXP 收购了。打开此 freescale 文件夹,在里面找到和 mx6u(I.MX6UL/ULL)有
关的文件夹。
以“ mx6ul”开头的表示使用
I.MX6UL 芯片的板子,以 mx6ull 开头的表示使用 I.MX6ULL 芯片的板子。 mx6ullevk 是 NXP
官方的 I.MX6ULL开发板,正点原子的 ALPHA开发板就是在这个基础上开发的,因此 mx6ullevk
也是正点原子的开发板。我们后面移植 uboot 到时候就是参考 NXP 官方的开发板,也就是要参考 mx6ullevk 这个文件夹来定义我们的板子。
3、 configs 文件夹
此文件夹为 uboot 配置文件, uboot 是可配置的,但是你要是自己从头开始一个一个项目的
配置,那就太麻烦了,因此一般半导体或者开发板厂商都会制作好一个配置文件。我们可以在
这个做好的配置文件基础上来添加自己想要的功能,这些半导体厂商或者开发板厂商制作好的
配置文件统一命名为“ xxx_defconfig”,xxx 表示开发板名字,这些 defconfig 文件都存放在 configs
文件夹,因此, NXP 官方开发板和正点原子的开发板配置文件肯定也在这个文件夹中。
我们只关心 mx6ull_14x14_ddr512_emmc_defconfig 和 mx6ull_14x14_ddr256_nand_defconfig
这两个文件,分别是正点原子 I.MX6ULL EMMC 核心板和 NAND 核心板的配置文件。使用
“ make xxx_defconfig”命令即可配置 uboot,比如:
make mx6ull_14x14_ddr512_emmc_defconfig
上述命令就是配置正点原子的 I.MX6ULL EMMC 核心板所使用的 uboot。
在编译 uboot 之前一定要使用 defconfig 来配置 uboot!
4、 .u-boot.xxx_cmd 文件
.u-boot.xxx_cmd 是一系列的文件,这些文件都是编译生成的,都是一些命令文件,比如文
件.u-boot.bin.cmd,看名字应该是和 u-boot.bin 有关的,此文件的内容如下:
cmd_u-boot.bin := cp u-boot-nodtb.bin u-boot.bin
.u-boot.bin.cmd 里面定义了一个变量: cmd_u-boot.bin,此变量的值为“ cp u-boot-nodtb.bin
u-boot.bin”,也就是拷贝一份 u-boot-nodtb.bin 文件,并且重命名为 u-boot.bin,这个就是 u-boot.bin
的来源,来自于文件 u-boot-nodtb.bin。
那 么 u-boot-nodtb.bin 是 怎 么 来 的 呢 ? 文 件 .u-boot-nodtb.bin.cmd 就 是 用 于 生 成 uboot.nodtb.bin 的,此文件内容如下:
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-bootnodtb.bin
这里用到了 arm-linux-gnueabihf-objcopy,使用 objcopy 将 ELF 格式的 u-boot 文件转换为二
进制的 u-boot-nodtb.bin 文件。
文件 u-boot 是 ELF 格式的文件,文件.u-boot.cmd 用于生成 u-boot,文件内容如下:
cmd_u-boot := 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
drivers/dma/built-in.o drivers/gpio/built-in.o drivers/i2c/builtin.o drivers/mmc/built-in.o drivers/mtd/built-in.o
drivers/mtd/onenand/built-in.o drivers/mtd/spi/built-in.o
drivers/net/built-in.o drivers/net/phy/built-in.o drivers/pci/builtin.o drivers/power/built-in.o drivers/power/battery/built-in.o
drivers/power/fuel_gauge/built-in.o drivers/power/mfd/built-in.o
drivers/power/pmic/built-in.o drivers/power/regulator/built-in.o
drivers/serial/built-in.o drivers/spi/built-in.o
drivers/usb/dwc3/built-in.o drivers/usb/emul/built-in.o
drivers/usb/eth/built-in.o drivers/usb/gadget/built-in.o
drivers/usb/gadget/udc/built-in.o drivers/usb/host/built-in.o
drivers/usb/musb-new/built-in.o drivers/usb/musb/built-in.o
drivers/usb/phy/built-in.o drivers/usb/ulpi/built-in.o fs/built-in.o
lib/built-in.o net/built-in.o test/built-in.o test/dm/built-in.o --
end-group arch/arm/lib/eabi_compat.o -L /usr/local/arm/gcc-linaro-
4.9.4-2017.01-x86_64_arm-linux-gnueabihf/bin/../lib/gcc/arm-linuxgnueabihf/4.9.4 -lgcc -Map u-boot.map
.u-boot.cmd 使用到了 arm-linux-gnueabihf-ld.bfd,也就是链接工具,使用 ld.bfd 将各个 builtin.o 文件链接在一起就形成了 u-boot 文件。 uboot 在编译的时候会将同一个目录中的所有.c 文件
都编译在一起,并命名为 built-in.o,相当于将众多的.c 文件对应的.o 文件集合在一起,这个就
是 u-boot 文件的来源。
如果我们要用 NXP 提供的 MFGTools 工具向开发板烧写 uboot,此时烧写的是 u-boot.imx
文件,而不是 u-boot.bin 文件。u-boot.imx 是在 u-boot.bin 文件的头部添加了 IVT、 DCD 等信息。
这个工作是由文件.u-boot.imx.cmd 来完成的,此文件内容如下:
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
可以看出,这里用到了工具 tools/mkimage,而 IVT、 DCD 等数据保存在了文件
board/freescale/mx6ullevk/imximage-ddr512.cfg.cfgtmp 中 ( 如 果 是 NAND 核 心 板 的 话 就 是
imximage-ddr256.cfg.cfgtmp),工具 mkimage 就是读取文件 imximage-ddr512.cfg.cfgtmp 里面的
信息,然后将其添加到文件 u-boot.bin 的头部,最终生成 u-boot.imx。
文件.u-boot.lds.cmd 就是用于生成 u-boot.lds 链接脚本的,由于.u-boot.lds.cmd 文件内容太
多,这里就不列出来了。uboot 根目录下的 u-boot.lds 链接脚本就是来源于 arch/arm/cpu/u-boot.lds
文件。
5、 Makefile 文件
这个是顶层 Makefile 文件, Makefile 是支持嵌套的,也就是顶层 Makefile 可以调用子目录
中的 Makefile 文件。 Makefile 嵌套在大项目中很常见,一般大项目里面所有的源代码都不会放
到同一个目录中,各个功能模块的源代码都是分开的,各自存放在各自的目录中。每个功能模
块目录下都有一个 Makefile,这个 Makefile 只处理本模块的编译链接工作,这样所有的编译链
接工作就不用全部放到一个 Makefile 中,可以使得 Makefile 变得简洁明了。
uboot 源码根目录下的 Makefile 是顶层 Makefile,他会调用其它的模块的 Makefile 文件,
比如 drivers/adc/Makefile。当然了,顶层 Makefile 要做的工作可远不止调用子目录 Makefile 这
么简单,关于顶层 Makefile 的内容我们稍后会有详细的讲解。
6、 u-boot.xxx 文件
u-boot.xxx 同样也是一系列文件,包括 u-boot、u-boot.bin、u-boot.cfg、u-boot.imx、u-boot.lds、
u-boot.map、 u-boot.srec、 u-boot.sym 和 u-boot-nodtb.bin,这些文件的含义如下:
u-boot:编译出来的 ELF 格式的 uboot 镜像文件。
u-boot.bin:编译出来的二进制格式的 uboot 可执行镜像文件。
u-boot.cfg: uboot 的另外一种配置文件。
u-boot.imx: u-boot.bin 添加头部信息以后的文件, NXP 的 CPU 专用文件。
u-boot.lds:链接脚本。
u-boot.map: uboot 映射文件,通过查看此文件可以知道某个函数被链接到了哪个地址上。
u-boot.srec: S-Record 格式的镜像文件。
u-boot.sym: uboot 符号文件。
u-boot-nodtb.bin:和 u-boot.bin 一样, u-boot.bin 就是 u-boot-nodtb.bin 的复制文件。
7、 .config 文件
uboot 配置文件,使用命令“ make xxx_defconfig”配置 uboot 以后就会自动生成.
可以看出.config 文件中都是以“ CONFIG_”开始的配置项,这些配置项就是 Makefile 中的
变量,因此后面都跟有相应的值, uboot 的顶层 Makefile 或子 Makefile 会调用这些变量值。
在.config 中会有大量的变量值为‘ y’,这些为‘ y’的变量一般用于控制某项功能是否使能,为
‘ y’的话就表示功能使能,比如:
CONFIG_CMD_BOOTD=y
如果使能了 bootd 这个命令的话, CONFIG_CMD_BOOTM 就为‘ y’。在 cmd/Makefile 中
有如下代码:
示例代码 31.1.6 cmd/Makefile 代码
1 ifndef CONFIG_SPL_BUILD
2 # core command
3 obj-y += boot.o
4 obj-$(CONFIG_CMD_BOOTM) += bootm.o
5 obj-y