文章目录
U-Boot的编译
配置完成后,执行“make all”即可编译,从Makefile中可以了解到U-Boot使用了那些文件、那个文件首先执行、可执行文件占用内存的情况。
先确定用到的那些文件,下面所示为Makefile中与ARM相关的部分。
include $(OBJTREE)/include/config.mk
export ARCH CPU BOARD VENDOR SOC
...
ifeq ($(ARCH),arm)
CROSS_COMPILE = arm-linux-
endif
...
# load other configuration
include $(TOPDIR)/config.mk
找到BOARDDIR、LDFLAGS的值
BOARDDIR = $(BOARD)
...
sinclude $(TOPDIR)/board/$(BOARDDIR)/config.mk # include board specific rules
...
LDSCRIPT := $(TOPDIR)/board/$(BOARDDIR)/u-boot.lds
...
LDFLAGS += -Bstatic -T $(LDSCRIPT) -Ttext $(TEXT_BASE) $(PLATFORM_LDFLAGS)
原文件顶层目录下的config.mk分析
在board/smdk2410/config.mk中,定义了"TEXT_BASE=0x33F80000"。
所以,最终结果如下:BOARDDIR为 smdk2410:LDFLAGS中有“-T board/smdk2410/U-Boot.lds -Ttext 0x33F80000”字样。
继续分析Makefile
#########################################################################
# U-Boot objects....order is important (i.e. start must be first)
OBJS = cpu/$(CPU)/start.o
...
LIBS = lib_generic/libgeneric.a
LIBS += board/$(BOARDDIR)/lib$(BOARD).a
LIBS += cpu/$(CPU)/lib$(CPU).a
...
LIBS += lib_$(ARCH)/lib$(ARCH).a
LIBS += fs/cramfs/libcramfs.a fs/fat/libfat.a fs/fdos/libfdos.a fs/jffs2/libjffs2.a \
fs/reiserfs/libreiserfs.a fs/ext2/libext2fs.a
LIBS += net/libnet.a
...
LIBS += $(BOARDLIBS)
...
OBJS、LINS所代表的.a,.o文件就是U-Boot的构成,它们通过如下命令有相应的源文件(或相应子目录下的文件)编译的到。
$(OBJS):
$(MAKE) -C cpu/$(CPU) $(if $(REMOTE_BUILD),$@,$(notdir $@))
$(LIBS):
$(MAKE) -C $(dir $(subst $(obj),,$@))
$(SUBDIRS):
$(MAKE) -C $@ all
U-Boot的连接过程
当所有的OBJS,LIBS所表示的.a和.o文件都生成以后,就剩下最后的连接了,这对应Makefile中如下几行
$(obj)u-boot.srec: $(obj)u-boot
$(OBJCOPY) ${OBJCFLAGS} -O srec $< $@
$(obj)u-boot.bin: $(obj)u-boot
$(OBJCOPY) ${OBJCFLAGS} -O binary $< $@
...
$(obj)u-boot: depend version $(SUBDIRS) $(OBJS) $(LIBS) $(LDSCRIPT)
UNDEF_SYM=`$(OBJDUMP) -x $(LIBS) |sed -n -e 's/.*\(__u_boot_cmd_.*\)/-u\1/p'|sort|uniq`;\
cd $(LNDIR) && $(LD) $(LDFLAGS) $$UNDEF_SYM $(__OBJS) \
--start-group $(__LIBS) --end-group $(PLATFORM_LIBS) \
-Map u-boot.map -o u-boot
board/smdk2410/U-Boot.lds文件如下:
SECTIONS
{
. = 0x00000000;
. = ALIGN(4);
.text :
{
cpu/arm920t/start.o (.text)
*(.text)
}
. = ALIGN(4);
.rodata : { *(.rodata) }
. = ALIGN(4);
.data : { *(.data) }
. = ALIGN(4);
.got : { *(.got) }
. = .;
__u_boot_cmd_start = .;
.u_boot_cmd : { *(.u_boot_cmd) }
__u_boot_cmd_end = .;
. = ALIGN(4);
__bss_start = .;
.bss : { *(.bss) }
_end = .;
}
总结U-Boot的编译流程
- 首先编译cpu/$(CPU)/start.S,对于不同的CPU,还可能编译cpu/ $(CPU)下的其他文件(为什么要先编译它呢?因为U-Boot的入口点在这个文件中)
- 然后,对于平台/开发板相关的每个目录、每个通用目录都是使用它们各自的Makefidle生成相应的库。
- 将1、2步骤生成的.a和.o文件按照board/$(BOARDDIR)/config.mk文件中指定的代码起始地址、board/ $(BORADDIR)/U-Boot.lds连接脚本进行连接。
- 第3步得到的就是ELF格式的U-Boot,后面Makefile还会将它转换为二进制格式,S-Record格式。
总结
总结以下,U-Boot很难,我们现在也只是分析了Makefile中核心的部分,但是这个Makefile有2000多行,所以这会是一个漫长的过程。
加油,相信终有一天能彻底明白其思想!