U-Boot 顶层 Makefile 详解1之U-Boot 工程目录分析

系列文章目录

U-Boot 顶层 Makefile 详解



一、前言

分析uboot 的顶层 Makefile,理清了 uboot 的编译流程


二、U-Boot 工程目录分析

本节我们以 EMMC 版本的核心板为例讲解,为了方便,uboot 启动源码分析就在 Windows下进行,将正点原子提供的 uboot 源码进行解压,解压完成以后的目录如图所示:

在这里插入图片描述


图是正点原子提供的未编译的 uboot 源码目录,我们在分析 uboot 源码之前一定要先在 Ubuntu 中编译一下 uboot 源码,因为编译过程会生成一些文件,而生成的这些恰恰是分析uboot 源码不可或缺的文件。使用上一节创建的 shell 脚本来完成编译工作,参考文章,并通过FTP将编译后的uboot打包压缩发送到windows下,然后将编译后的uboot解压,解压后的目录如图所示:
在这里插入图片描述对比编译前和编译后的uboot,可以看出编译后的 uboot 要比没编译之前多了好多文件,这些文件夹或文件的含义见表所示:
在这里插入图片描述在这里插入图片描述表中的很多文件夹和文件我们都不需要去关心,我们要关注的文件夹或文件如下:


三、关注文件夹—arch文件夹

这个文件夹里面存放着和架构有关的文件,如图所示:
在这里插入图片描述从图可以看出有很多架构,比如 arm、avr32、m68k 等,我们现在用的是 ARM 芯
片,所以只需要关心 arm 文件夹即可,打开 arm 文件夹里面内容如图所示:
在这里插入图片描述

mach 开头的文件夹是跟具体的设备有关的,比如“mach-exynos”就是跟三星的 exyons 系列 CPU 有关的文件。
我们使用的是 I.MX6ULL,所以要关注“imx-common”这个文件夹。另外“cpu”这个文件夹也是和 cpu 架构有关的,打开以后如图所示:

在这里插入图片描述
从图可以看出有多种 ARM 架构相关的文件夹,I.MX6ULL 使用的 Cortex-A7 内核,
Cortex-A7 属于 armv7,所以我们要关心“armv7”这个文件夹。cpu 文件夹里面有个名为“uboot.lds”的链接脚本文件,这个就是 ARM 芯片所使用的 u-boot 链接脚本文件!armv7 这个文件夹里面的文件都是跟 ARMV7 架构有关的,是我们分析 uboot 启动源码的时候需要重点关注的。


四、关注文件夹—board文件夹

board 文件夹就是和具体的板子有关的,打开此文件夹,里面全是不同的板子,毫无疑问正点原子的开发板肯定也在里面(正点原子添加的),borad 文件夹里面有个名为“freescale”的文件夹,如图所示:

在这里插入图片描述所有使用 freescale 芯片的板子都放到此文件夹中,I.MX 系列以前属于 freescale,只是freescale 后来被 NXP 收购了。
打开此 freescale 文件夹,在里面找到和mx6u(I.MX6UL/ULL)有关的文件夹,如图所示:
在这里插入图片描述

图中有 5 个文件夹,这 5 个文件夹对应 5 种板子,以“mx6ul”开头的表示使用
I.MX6UL 芯片的板子,以 mx6ull 开头的表示使用 I.MX6ULL 芯片的板子。mx6ullevk 是 NXP官方的I.MX6ULL 开发板,正点原子的ALPHA开发板就是在这个基础上开发的,因此 mx6ullevk也是正点原子的开发板。我们后面移植 uboot 到时候就是参考 NXP 官方的开发板,也就是要参考 mx6ullevk 这个文件夹来定义我们的板子。


五、关注文件夹—configs文件夹

此文件夹为 uboot 配置文件,uboot 是可配置的,但是你要是自己从头开始一个一个项目的配置,那就太麻烦了,因此一般半导体或者开发板厂商都会制作好一个配置文件。我们可以在这个做好的配置文件基础上来添加自己想要的功能,这些半导体厂商或者开发板厂商制作好的配置文件统一命名为“xxx_defconfig”,xxx 表示开发板名字,这些 defconfig 文件都存放在 configs文件夹,因此,NXP 官方开发板和正点原子的开发板配置文件肯定也在这个文件夹中,如图所示:

在这里插入图片描述
图中这 6 个文件就是正点原子 I.MX6U-ALPHA 开发板所对应的 uboot 默认配置文件。
我们只关心 mx6ull_14x14_ddr512_emmc_defconfig 和mx6ull_14x14_ddr256_nand_defconfig这两个文件,分别是正点原子 I.MX6ULL EMMC 核心板和 NAND 核心板的配置文件。使用“make xxx_defconfig”命令即可配置 uboot,比如:在参考文章中就有下面这一句:
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-mx6ull_14x14_ddr512_emmc_defconfig
这个就是调用 mx6ull_14x14_ddr512_emmc_defconfig 来配置 uboot,只是这个命令还带了一些其它参数而已。


六、关注文件夹—.u-boot.xxx_cmd文件

.u-boot.xxx_cmd 是一系列的文件,这些文件都是编译生成的,都是一些命令文件,比如文件.u-boot.bin.cmd,看名字应该是和 u-boot.bin 有关的,此文件的内容如下:

1 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文件。还有一些其它的.u-boot.lds.xxx.cmd 文件,大家自行分析一下,关于.u-boot.lds.xxx.cmd 文件就讲解到这里。


七、关注文件夹—Makefile文件

在这里插入图片描述

这个是顶层 Makefile 文件,Makefile 是支持嵌套的,也就是顶层 Makefile 可以调用子目录中的 Makefile 文件。Makefile 嵌套在大项目中很常见,一般大项目里面所有的源代码都不会放到同一个目录中,各个功能模块的源代码都是分开的,各自存放在各自的目录中。每个功能模块目录下都有一个 Makefile,这个 Makefile 只处理本模块的编译链接工作,这样所有的编译链接工作就不用全部放到一个 Makefile 中,可以使得 Makefile 变得简洁明了。

uboot 源码根目录下的 Makefile 是顶层 Makefile,他会调用其它的模块的 Makefile 文件,
比如 drivers/adc/Makefile。
在这里插入图片描述

当然了,顶层 Makefile 要做的工作可远不止调用子目录 Makefile 这么简单,关于顶层 Makefile 的内容我们稍后会有详细的讲解。


八、关注文件夹—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 的复制文件。
在这里插入图片描述


九、关注文件夹—.config文件

uboot 配置文件,使用命令“make xxx_defconfig”配置 uboot 以后就会自动生成,.config 内
容如下:

1 #
2 # Automatically generated file; DO NOT EDIT.
3 # U-Boot 2016.03 Configuration
4 #
5 CONFIG_CREATE_ARCH_SYMLINK=y
6 CONFIG_HAVE_GENERIC_BOARD=y
7 CONFIG_SYS_GENERIC_BOARD=y
8 # CONFIG_ARC is not set
9 CONFIG_ARM=y
10 # CONFIG_AVR32 is not set
11 # CONFIG_BLACKFIN is not set
12 # CONFIG_M68K is not set
13 # CONFIG_MICROBLAZE is not set
14 # CONFIG_MIPS is not set
15 # CONFIG_NDS32 is not set
16 # CONFIG_NIOS2 is not set
17 # CONFIG_OPENRISC is not set
18 # CONFIG_PPC is not set
19 # CONFIG_SANDBOX is not set
20 # CONFIG_SH is not set
21 # CONFIG_SPARC is not set
22 # CONFIG_X86 is not set
23 CONFIG_SYS_ARCH="arm"
24 CONFIG_SYS_CPU="armv7"
25 CONFIG_SYS_SOC="mx6"
26 CONFIG_SYS_VENDOR="freescale"
27 CONFIG_SYS_BOARD="mx6ull_alientek_emmc"
28 CONFIG_SYS_CONFIG_NAME="mx6ull_alientek_emmc"
29
30 ......
31
32 #
33 # Boot commands
34 #
35 CONFIG_CMD_BOOTD=y
36 CONFIG_CMD_BOOTM=y
37 CONFIG_CMD_ELF=y
38 CONFIG_CMD_GO=y
39 CONFIG_CMD_RUN=y
40 CONFIG_CMD_IMI=y
41 CONFIG_CMD_IMLS=y
42 CONFIG_CMD_XIMG=y
43
44 #
45 # Environment commands
46 #
47 CONFIG_CMD_EXPORTENV=y
48 CONFIG_CMD_IMPORTENV=y
49 CONFIG_CMD_EDITENV=y
50 CONFIG_CMD_SAVEENV=y
51 CONFIG_CMD_ENV_EXISTS=y
52
53 ......
54
55 #
56 # Library routines
57 #
58 # CONFIG_CC_OPTIMIZE_LIBS_FOR_SPEED is not set
59 CONFIG_HAVE_PRIVATE_LIBGCC=y
60 # CONFIG_USE_PRIVATE_LIBGCC is not set
61 CONFIG_SYS_HZ=1000
62 # CONFIG_USE_TINY_PRINTF is not set
63 CONFIG_REGEX=y

可以看出.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

在该代码中有如下所示一行代码:

obj-$(CONFIG_CMD_BOOTM) += bootm.o

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 内核中都是采用这种方法来选择使能某个功能,编译对应的源码文件。


十、关注文件夹—README

README 文件描述了 uboot 的详细信息,包括 uboot 该如何编译、uboot 中各文件夹的含义、相应的命令等等。建议大家详细的阅读此文件,可以进一步增加对 uboot 的认识。
关于 uboot 根目录中的文件和文件夹的含义就讲解到这里,接下来下一节就要开始分析 uboot 的启动流程了


END
在这里插入图片描述

相关推荐

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-16 19:18:01       67 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-16 19:18:01       72 阅读
  3. 在Django里面运行非项目文件

    2024-07-16 19:18:01       58 阅读
  4. Python语言-面向对象

    2024-07-16 19:18:01       69 阅读

热门阅读

  1. 每天一个数据分析题(四百三十一)- 卡方检验

    2024-07-16 19:18:01       22 阅读
  2. buttonrpc解析—server篇

    2024-07-16 19:18:01       20 阅读
  3. Haproxy负载均衡

    2024-07-16 19:18:01       23 阅读
  4. redhat基础的环境搭建

    2024-07-16 19:18:01       22 阅读
  5. 【阶乘】个人练习-Leetcode-LCP 22. 黑白方格画

    2024-07-16 19:18:01       21 阅读
  6. EnableFeignClients详解

    2024-07-16 19:18:01       24 阅读
  7. 自动驾驶的规划控制简介

    2024-07-16 19:18:01       19 阅读
  8. 查看 RocketMQ 中的重试队列和死信队列

    2024-07-16 19:18:01       22 阅读
  9. 靖江美食元宇宙

    2024-07-16 19:18:01       20 阅读
  10. python实现自动更新prometheus规则

    2024-07-16 19:18:01       20 阅读
  11. POSIX 标准-信号量sem_t

    2024-07-16 19:18:01       19 阅读
  12. 文件访问:C/C++/MFC

    2024-07-16 19:18:01       19 阅读