11.1 U-boot 工程目录分析
将正点原子提供的 uboot 源码进行解压,解压完成以后的目录如图
编译正点原子提供的 uboot 源码,然后将其发送到 Windows 下,编译后的目录如图:
对于上述文件:
1、arch 文件夹
这个文件夹里面存放着和架构有关的文件 。比如 arm、m68k、x86 等,我们现在用的是 ARM 芯片,所以只需要关心 arm 文件夹即可。
只截取了一部分,还有一部分 mach-xxx 的文件夹。mach 开头的文件夹是跟具体的设备有关的,比如“mach-exynos”就是跟三星的 exyons 系列 CPU 有关的文件。我们使用的是 STM32MP1,所以要关注“mach-stm32mp”这个文件夹。
另外“cpu”这个文件夹也是和 cpu架构有关的。打开后如图:
从图可以看出有多种 ARM 架构相关的文件夹, STM32MP1 使用的 Cortex-A7 内核,Cortex-A7 属于 armv7,所以我们要关心“armv7”这个文件夹。cpu 文件夹里面有个名为“u-boot.lds”的链接脚本文件,这个就是 ARM 芯片所使用的 u-boot 链接脚本文件!armv7 这个文件夹里面的文件都是跟 ARMV7 架构有关的,是我们分析 uboot 启动源码的时候需要重点关注的。
2、board 文件夹
board 文件夹就是和具体的板子有关的,打开此文件夹,里面全是不同的板子,毫无疑问正点原子的开发板肯定也在里面(正点原子添加的),borad 文件夹里面有个名为“st”的文件夹。所有使用 ST 芯片的板子都放到此文件夹中,打开“st”文件夹:
图 11.1.7 中有 stm32f429-discovery、stm32f469-evaluation、stm32f746-discovery 等目录,对STM32 熟悉的朋友一眼就看出来,这些是 ST 官方的 STM32 开发板。stm32mp1 这个目录就是
针对 STM32MP1 系列芯片对应的板子。
3、configs 文件夹
此文件夹为 uboot 配置文件夹,uboot 是可配置的。半导体厂商或者开发板厂商制作好的配置文件统一命名为“xxx_defconfig”,xxx 表示开发板名字,这些 defconfig 文件都存放在configs 文件夹。打开后如图:
图 中 stm32mp157d_atk_defconfig 就是正点原子 STM32MP157 开发板对应的默认配置文件。使用“make xxx_defconfig”命令即可配置 uboot。
make stm32mp157d_atk_defconfig
上述命令就是配置正点原子 STM32MP157 核心板所使用的 uboot。在编译 uboot 之前一定要使用 defconfig 来配置 uboot!
make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabihf- stm32mp157d_atk_defconfig
这个就是调用 stm32mp157d_atk_defconfig 来配置 uboot,只是这个命令还带了一些其它参
数而已。ARCH 用来指定 CPU 架构为 arm,CROSS_COMPILE 用来指定所使用的交叉编译器
为 arm-none-linux-gnueabihf-gcc。
4、.u-boot.xxx_cmd 文件
.u-boot.xxx_cmd 是一系列的文件,这些文件都是编译生成的,都是一些命令文件,比如文件
.u-boot.bin.cmd。是和 u-boot.bin 有关的,此文件的内容如下:
cmd_u-boot.bin := cp u-boot-dtb.bin u-boot.bin
.u-boot.bin.cmd 里面定义了一个变量:cmd_u-boot.bin,此变量的值为“cp u-boot-dtb.bin u-
boot.bin”。也就是拷贝一份 u-boot-dtb.bin 文件,并且重命名为 u-boot.bin,这个就是 u-boot.bin的来源,来自于文件 u-boot-dtb.bin。
那么 u-boot-dtb.bin 怎么来的呢? 文件.u-boot-dtb.bin.cmd 就是用于生成 u-boot.dtb.bin。
cmd_u-boot-dtb.bin := cat u-boot-nodtb.bin dts/dt.dtb > u-boot-dtb.bin
上述为cmd_u-boot-dtb.bin 代码。
cmd_u-boot-dtb.bin 用于将设备树.dtb 文件和 uboot 的 bin 文件结合起来,STM32MP157 的
uboot 用到了设备树(Device Tree)。因此最终生成的 uboot bin 文件里面要有.dtb 内容。
u-boot-nodtb.bin 就是原始的、不含 dtb 的 uboot bin 文件。
u-boot-nodtb.bin 是用.u-boot-nodtb.bin.cmd 文件生成的,内容如下
cmd_u-boot-nodtb.bin := arm-none-linux-gnueabihf-objcopy --gap-fill=0xff-j .text -j .secure_text -j .secure_data -j .rodata -j .hash -j .data-j .got -j .got.plt -j .u_boot_list -j .rel.dyn -j .binman_sym_table -j.text_rest -j .dtb.init.rodata -j .efi_runtime -j .efi_runtime_rel -O binary u-boot u-boot-nodtb.bin
这里用到了 arm-none-linux-gnueabihf-objcopy。使用 objcopy 将 ELF 格式的 u-boot 文件转换为二进制的 u-boot-nodtb.bin 文件。
文件 u-boot 是 ELF 格式的文件。.u-boot.cmd 用于生成 u-boot。u-boot.cmd 代码如下:
cmd_u-boot := arm-none-linux-gnueabihf-ld.bfd
Bstatic
--gc-sections -
--no-dynamic-linker -Ttext 0xC0100000 -o u-boot -T u-boot.lds
arch/arm/cpu/armv7/start.o --start-group
arch/arm/cpu/armv7/built-in.o
stm32mp/built-in.o
arch/arm/cpu/built-in.o
arch/arm/lib/built-in.o
board/st/common/built-in.o
in.o cmd/built-in.o
in.o drivers/dma/built-in.o
common/built-in.o
drivers/i2c/built-in.o
in.o
-pie
board/st/stm32mp1/built-
disk/built-in.o
drivers/built-
drivers/gpio/built-in.o
drivers/net/built-in.o
drivers/power/built-in.o
drivers/power/mfd/built-in.o
drivers/net/phy/built-
drivers/power/battery/built-in.o
drivers/power/domain/built-in.o
drivers/power/fuel_gauge/built-in.o
drivers/power/pmic/built-in.o
drivers/power/regulator/built-in.o
drivers/spi/built-in.o
arch/arm/mach-
drivers/serial/built-in.o
drivers/usb/cdns3/built-in.o
drivers/usb/common/built-in.o
drivers/usb/emul/built-in.o
drivers/usb/dwc3/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 env/built-in.o
in.o
fs/built-in.o
lib/built-
net/built-in.o --end-group arch/arm/lib/eabi_compat.o
arch/arm/lib/lib.a -Map u-boot.map;
true
.u-boot.cmd 使用到了 arm-none-linux-gnueabihf-ld.bfd,也就是链接工具,使用 ld.bfd 将各个built-in.o 文件链接在一起就形成了 u-boot 文件。 uboot 在编译的时候会将同一个目录中的所有.c文件都编译在一起,并命名为 built-in.o,相当于将众多的.c 文件对应的.o 文件集合在一起,这个就是 u-boot 文件的来源。
如果我们要向 STM32MP157 内部烧写 uboot,此时烧写的是 u-boot.stm32 文件,而不是 u-
boot.bin 文件。u-boot.stm32 是由文件.u-boot.stm32.cmd 来完成的,此文件内容如下:
cmd_u-boot.stm32 := ./tools/mkimage -T stm32image -a 0xC0100000 -e0xC0100000 -d u-boot.bin u-boot.stm32 >u-boot.stm32.log && cat u-boot.stm32.log
可以看出,这里用到了工具 tools/mkimage,和 stm32image,通过这两个工具将u-boot.bin
转换为 u-boot.stm32。文件.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。
6、u-boot.xxx 文件
u-boot.xxx 同样也是一系列文件,包括 u-boot、 u-boot-dtb.bin、 u-boot-nodtb.bin、 u-boot.bin、u-boot.cfg、u-boot.dtb、u-boot.lds、u-boot.map、u-boot.srec、u-boot.stm32 和 u-boot.sym,这些文件的含义如下:
u-boot: 编译出来的 ELF 格式的 uboot 镜像文件。
u-boot-dtb.bin: 编译出来的含有设备树.dtb 的 uboot 镜像文件。
u-boot-nodtb.bin: 编译出来的不含有设备树.dtb 的 uboot 镜像文件,和 u-boot.bin 一样。
u-boot.bin: 编译出来的二进制格式的 uboot 可执行镜像文件。
u-boot.cfg: uboot 的另外一种配置文件。
u-boot.dtb: uboot 设备树编译后的.dtb 文件。
u-boot.lds: 链接脚本。
u-boot.map: uboot 映射文件,通过查看此文件可以知道某个函数被链接到了哪个地址上。
u-boot.srec: S-Record 格式的镜像文件。
u-boot.stm32: 最终要写到 STM32MP157 的 uboot 文件。
u-boot.sym: uboot 符号文件。
7、.config 文件
uboot 配置文件,使用命令“make xxx_defconfig”配置 uboot 以后就会自动生成,.config 内
容如下(太长,省略):
.config 文件中都是以“CONFIG_”开始的配置项,这些配置项就是 Makefile 中的变量,因此后面都跟有相应的值,uboot 的顶层 Makefile 或子 Makefile 会调用这些变量值。
在.config 中会有大量的变量值为‘y’,这些为‘y’的变量一般用于控制某项功能是否使能,为
‘y’的话就表示功能使能。
CONFIG_CMD_BOOTM=y
如果使能了 bootd 这个命令的话,CONFIG_CMD_BOOTM 就为‘y’。在 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 += help.o
6 obj-y += version.o
7
8 ......
9 CFLAGS_ethsw.o := -Wno-enum-conversion
上述代码的第四行命令,如果有CONFIG_CMD_BOOTM=y,将其展开就是:obj-y += bootm.o
也就是给 obj-y 追加了一个“bootm.o”,obj-y 包含着所有要编译的文件对应的.o 文件,这里表示需要编译文件 cmd/bootm.c。
相当于通过“CONFIG_CMD_BOOTD=y”来使能 bootm 这个命令,进而编译 cmd/bootm.c 这个文件,这个文件实现了命令 bootm。在 uboot 和 Linux 内核中都是采用这种方法来选择使能某个功能,编译对应的源码文件。
8、README
README 文件描述了 uboot 的详细信息,包括 uboot 该如何编译、uboot 中各文件夹的含
义、相应的命令等等。建议大家详细的阅读此文件,可以进一步增加对 uboot 的认识。
关于 uboot 根目录中的文件和文件夹的含义就讲解到这里,接下来就要开始分析 uboot 的
顶层 Makefile 了。