第 6 章 Bootloader
6.2 U-Boot 编程
6.2.3 U-Boot 的编译
U-Boot 的源码是通过 GCC 和 Makefile 组织编译的。顶层目录下的 Makefile 首先可以设 置开发板的定义,然后递归地调用各级子目录下的 Makefile,最后把编译过的程序链接成 U-Boot 映像。
1.顶层目录下的 Makefile
它负责 U-Boot 整体配置编译。按照配置的顺序阅读其中关键的几行。
每一种开发板在 Makefile 都需要有板子配置的定义。例如 smdk2410 开发板的定义 如下。
smdk2410_config : unconfig
@./mkconfig $(@:_config=) arm arm920t smdk2410 NULL s3c24x0
执行配置 U-Boot 的命令 make smdk2410_config,通过./mkconfig 脚本生成 include/config.
mk 的配置文件。文件内容正是根据 Makefile 对开发板的配置生成的。
tyw藏书
ARCH = arm CPU = arm920t BOARD = smdk2410 SOC = s3c24x0
上面的 include/config.mk 文件定义了 ARCH、CPU、BOARD、SOC 这些变量。这样硬件 平台依赖的目录文件可以根据这些定义来确定。SMDK2410 平台相关目录如下。
board/smdk2410/
cpu/arm920t/
cpu/arm920t/s3c24x0/
lib_arm/
include/asm-arm/
include/configs/smdk2410.h
再回到顶层目录的 Makefile 文件开始的部分,其中下列几行包含了这些变量的定义。
# load ARCH, BOARD, and CPU configuration include include/config.mk
export ARCH CPU BOARD VENDOR SOC
Makefile 的编译选项和规则在顶层目录的 config.mk 文件中定义。各种体系结构通用的 规则直接在这个文件中定义。通过 ARCH、CPU、BOARD、SOC 等变量为不同硬件平台定 义不同选项。不同体系结构的规则分别包含在 ppc_config.mk、arm_config.mk、mips_config.mk 等文件中。
顶层目录的 Makefile 中还要定义交叉编译器,以及编译 U-Boot 所依赖的目标文件。
ifeq ($(ARCH),arm)
CROSS_COMPILE = arm-linux- //交叉编译器的前缀
#endif
export CROSS_COMPILE
…
# U-Boot objects....order is important (i.e. start must be first) OBJS = cpu/$(CPU)/start.o //处理器相关的目标文件
…
LIBS = lib_generic/libgeneric.a //定义依赖的目录,每个目录下先把目标 文件连接成*.a 文件。
LIBS += board/$(BOARDDIR)/lib$(BOARD).a LIBS += cpu/$(CPU)/lib$(CPU).a
ifdef SOC
LIBS += cpu/$(CPU)/$(SOC)/lib$(SOC).a endif
LIBS += lib_$(ARCH)/lib$(ARCH).a
tyw藏书
…
然后还有 U-Boot 映像编译的依赖关系。
ALL = u-boot.srec u-boot.bin System.map all: $(ALL)
u-boot.srec: u-boot
$(OBJCOPY) ${OBJCFLAGS} -O srec $< $@
u-boot.bin: u-boot
$(OBJCOPY) ${OBJCFLAGS} -O binary $< $@
……
u-boot: depend $(SUBDIRS) $(OBJS) $(LIBS) $(LDSCRIPT) UNDEF_SYM='$(OBJDUMP) -x $(LIBS) \
|sed -n -e 's/.*\(__u_boot_cmd_.*\)/-u\1/p'|sort|uniq`;\
$(LD) $(LDFLAGS) $$UNDEF_SYM $(OBJS) \
--start-group $(LIBS) $(PLATFORM_LIBS) --end-group \ -Map u-boot.map -o u-boot
Makefile 缺省的编译目标为 all,包括 u-boot.srec、u-boot.bin、System.map。u-boot.srec 和 u-boot.bin 又依赖于 U-Boot。U-Boot 就是通过 ld 命令按照 u-boot.map 地址表把目标文 件组装成 u-boot。
其他 Makefile 内容就不再详细分析了,上述代码分析应该可以为阅读代码提供了一个线索。
2.开发板配置头文件
除了编译过程 Makefile 以外,还要在程序中为开发板定义配置选项或者参数。这个头文 件是 include/configs/<board_name>.h。<board_name>用相应的 BOARD 定义代替。
这个头文件中主要定义了两类变量。
一类是选项,前缀是 CONFIG_,用来选择处理器、设备接口、命令、属性等。例如:
#define CONFIG_ARM920T 1
#define CONFIG_DRIVER_CS8900 1
另一类是参数,前缀是 CFG_,用来定义总线频率、串口波特率、Flash 地址等参数。
例如:
#define CFG_FLASH_BASE 0x00000000
#define CFG_PROMPT "=>"
3.编译结果
根据对 Makefile 的分析,编译分为 2 步。第 1 步配置,例如:make smdk2410_config;
第 2 步编译,执行 make 就可以了。
编译完成后,可以得到 U-Boot 各种格式的映像文件和符号表,如表 6.3 所示。
tyw藏书
表 6.3 U-Boot 编译生成的映像文件
文 件 名 称 说 明 文 件 名 称 说 明
System.map U-Boot 映像的符号表 u-boot.bin U-Boot 映像原始的二进制格式 u-boot U-Boot 映像的 ELF 格式 u-boot.srec U-Boot 映像的 S-Record 格式
U-Boot 的 3 种映像格式都可以烧写到 Flash 中,但需要看加载器能否识别这些格式。一 般 u-boot.bin 最为常用,直接按照二进制格式下载,并且按照绝对地址烧写到 Flash 中就可以 了。U-Boot 和 u-boot.srec 格式映像都自带定位信息。
4.U-Boot 工具
在 tools 目录下还有些 U-Boot 的工具。这些工具有的也经常用到。表 6.4 说明了几种工 具的用途。
表 6.4 U-Boot 的工具
工 具 名 称 说 明 工 具 名 称 说 明
bmp_logo 制作标记的位图结构体 img2srec 转换 SREC 格式映像
envcrc 校验 u-boot 内部嵌入的环境变量 mkimage 转换 U-Boot 格式映像 gen_eth_addr 生成以太网接口 MAC 地址 updater U-Boot 自动更新升级工具
这些工具都有源代码,可以参考改写其他工具。其中 mkimage 是很常用的一个工具,Linux 内核映像和 ramdisk 文件系统映像都可以转换成 U-Boot 的格式。