1.u-boot制作命令
make forlinx_nand_ram256_config;
make all;
2.顶层mkconfig分析,参考 U-BOOT顶层目录mkconfig分析
mkconfig脚本执行后会生成以下3个文件,这些文件中提供的变量会在Makefile中其它地方使用。
MKCONFIG := $(SRCTREE)/mkconfig forlinx_nand_ram256_config : unconfig @$(MKCONFIG) smdk6410 arm s3c64xx smdk6410 samsung s3c6410 NAND ram256 unconfig: @rm -f $(obj)include/config.h $(obj)include/config.mk \ $(obj)board/*/config.tmp $(obj)board/*/*/config.tmp
./include/config.mk
./board/samsung/smdk6410/config.mk
./include/config.h
3.顶层config.mk分析,参考 u-boot顶层目录config.mk分析
这个文件设置的变量会在Makefile其它地方使用。
# load ARCH, BOARD, and CPU configuration include $(OBJTREE)/include/config.mk export ARCH CPU BOARD VENDOR SOC
4.变量打印,修改Makefile查看变量的具体内容。
display1: @echo "PLATFORM_RELFLAGS : $(PLATFORM_RELFLAGS)" @echo "PLATFORM_CPPFLAGS : $(PLATFORM_CPPFLAGS)" @echo "CPPFLAGS : $(CPPFLAGS)" @echo "CFLAGS : $(CFLAGS)" @echo "AFLAGS : $(AFLAGS)" @echo "LDFLAGS : $(LDFLAGS)" @echo "CPP: $(CPP)" @echo "MAKE: $(MAKE)" @echo "CROSS_COMPILE: $(CROSS_COMPILE)" @echo "BOARDDIR : $(BOARDDIR)" @echo "HOSTCC : $(HOSTCC)" @echo "HOSTCFLAGS : $(HOSTCFLAGS)" @echo "ALL : $(ALL)" @echo "SUBDIRS : $(SUBDIRS)" @echo "OBJS : $(OBJS)" @echo "__OBJS : $(__OBJS)" @echo "LIBS : $(LIBS)" @echo "__LIBS : $(__LIBS)" @echo "LDSCRIPT: $(LDSCRIPT)"
执行make display1即可查看到各个变量的具体值如下:
1 PLATFORM_RELFLAGS : -fno-strict-aliasing -fno-common -ffixed-r8 -msoft-float 2 PLATFORM_CPPFLAGS : -DCONFIG_ARM -D__ARM__ -march=armv5t 3 CPPFLAGS : -g -Os -fno-strict-aliasing -fno-common -ffixed-r8 -msoft-float -D__KERNEL__ -DTEXT_BASE=0xCFE00000 -I/home/yjg/arm6410/qudong/01-uboot/uboot_ok6410/include -fno-builtin -ffreestanding -nostdinc -isystem /usr/local/arm/4.3.2/bin/../lib/gcc/arm-none-linux-gnueabi/4.3.2/include -pipe -DCONFIG_ARM -D__ARM__ -march=armv5t 4 CFLAGS : -g -Os -fno-strict-aliasing -fno-common -ffixed-r8 -msoft-float -D__KERNEL__ -DTEXT_BASE=0xCFE00000 -I/home/yjg/arm6410/qudong/01-uboot/uboot_ok6410/include -fno-builtin -ffreestanding -nostdinc -isystem /usr/local/arm/4.3.2/bin/../lib/gcc/arm-none-linux-gnueabi/4.3.2/include -pipe -DCONFIG_ARM -D__ARM__ -march=armv5t -Wall -Wstrict-prototypes 5 AFLAGS : -D__ASSEMBLY__ -g -Os -fno-strict-aliasing -fno-common -ffixed-r8 -msoft-float -D__KERNEL__ -DTEXT_BASE=0xCFE00000 -I/home/yjg/arm6410/qudong/01-uboot/uboot_ok6410/include -fno-builtin -ffreestanding -nostdinc -isystem /usr/local/arm/4.3.2/bin/../lib/gcc/arm-none-linux-gnueabi/4.3.2/include -pipe -DCONFIG_ARM -D__ARM__ -march=armv5t 6 LDFLAGS : -Bstatic -T /home/yjg/arm6410/qudong/01-uboot/uboot_ok6410/board/samsung/smdk6410/u-boot.lds -Ttext 0xCFE00000 7 CPP: /usr/local/arm/4.3.2/bin/arm-linux-gcc -E 8 MAKE: make 9 CROSS_COMPILE: /usr/local/arm/4.3.2/bin/arm-linux- 10 BOARDDIR : samsung/smdk6410 11 HOSTCC : gcc 12 HOSTCFLAGS : -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer 13 ALL : u-boot.srec u-boot.bin System.map 14 SUBDIRS : tools examples post post/cpu 15 OBJS : cpu/s3c64xx/start.o 16 __OBJS : cpu/s3c64xx/start.o 17 LIBS : lib_generic/libgeneric.a board/samsung/smdk6410/libsmdk6410.a cpu/s3c64xx/libs3c64xx.a cpu/s3c64xx/s3c6410/libs3c6410.a lib_arm/libarm.a fs/cramfs/libcramfs.a fs/fat/libfat.a fs/fdos/libfdos.a fs/jffs2/libjffs2.a fs/reiserfs/libreiserfs.a fs/ext2/libext2fs.a net/libnet.a disk/libdisk.a rtc/librtc.a dtt/libdtt.a drivers/libdrivers.a drivers/nand/libnand.a drivers/nand_legacy/libnand_legacy.a drivers/onenand/libonenand.a drivers/sk98lin/libsk98lin.a post/libpost.a post/cpu/libcpu.a common/libcommon.a 18 __LIBS : lib_generic/libgeneric.a board/samsung/smdk6410/libsmdk6410.a cpu/s3c64xx/libs3c64xx.a cpu/s3c64xx/s3c6410/libs3c6410.a lib_arm/libarm.a fs/cramfs/libcramfs.a fs/fat/libfat.a fs/fdos/libfdos.a fs/jffs2/libjffs2.a fs/reiserfs/libreiserfs.a fs/ext2/libext2fs.a net/libnet.a disk/libdisk.a rtc/librtc.a dtt/libdtt.a drivers/libdrivers.a drivers/nand/libnand.a drivers/nand_legacy/libnand_legacy.a drivers/onenand/libonenand.a drivers/sk98lin/libsk98lin.a post/libpost.a post/cpu/libcpu.a common/libcommon.a 19 LDSCRIPT: /home/yjg/arm6410/qudong/01-uboot/uboot_ok6410/board/samsung/smdk6410/u-boot.lds
从上面可以看出make的最终目标为ALL : u-boot.srec u-boot.bin System.map
ALL = $(obj)u-boot.srec $(obj)u-boot.bin $(obj)System.map $(U_BOOT_NAND)
all: $(ALL)
u-boot.srec u-boot.bin都依赖于u-boot
$(obj)u-boot.srec: $(obj)u-boot $(OBJCOPY) ${OBJCFLAGS} -O srec $< $@ $(obj)u-boot.bin: $(obj)u-boot $(OBJCOPY) ${OBJCFLAGS} -O binary $< $@ $(OBJDUMP) -d $< > $<.dis $(obj)System.map: $(obj)u-boot @$(NM) $< | \ grep -v '\(compiled\)\|\(\.o$$\)\|\( [aUw] \)\|\(\.\.ng$$\)\|\(LASH[RL]DI\)' | \ sort > $(obj)System.map
5. make u-boot分析,参考 详细分析make uboot 最后的编译链接的具体执行过程
$(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
上述目标的生成可分解为4个步骤:
5.0 生成版本信息文件:
生成include/version_autogenerated.h文件,内容如下:
#define U_BOOT_VERSION "U-Boot 1.1.6"
version: @echo -n "#define U_BOOT_VERSION \"U-Boot " > $(VERSION_FILE); \ echo -n "$(U_BOOT_VERSION)" >> $(VERSION_FILE); \ echo -n $(shell $(CONFIG_SHELL) $(TOPDIR)/tools/setlocalversion \ $(TOPDIR)) >> $(VERSION_FILE); \ echo "\"" >> $(VERSION_FILE) VERSION = 1 PATCHLEVEL = 1 SUBLEVEL = 6 EXTRAVERSION = U_BOOT_VERSION = $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) VERSION_FILE = $(obj)include/version_autogenerated.h
5.1 确定UNDEF_SYM变量值
打印出UNDEF_SYM变量值如下,其中的-u__u_boot_cmd_xxx用作arm-linux-ld命令的参数,意思就是,在ld的时候不定义这些符号,即不定义__u_boot_cmd_xxx,等等这些符号,我的理解是因为开始需要从某个库中载入其他的符号,而这个时候还没有载入到那个包含此符号定义的库,所以暂时先加入这个-u说明,先不定义这些符号,等到所有的库都加载完了再去找这些符号的定义,此时已经加载完所有的库了,也就能找到这些符号的定义了。
-u__u_boot_cmd_base -u__u_boot_cmd_bdinfo -u__u_boot_cmd_bootelf -u__u_boot_cmd_bootm -u__u_boot_cmd_bootp -u__u_boot_cmd_bootvx -u__u_boot_cmd_branch -u__u_boot_cmd_cmp -u__u_boot_cmd_cp -u__u_boot_cmd_crc32 -u__u_boot_cmd_date -u__u_boot_cmd_dcache -u__u_boot_cmd_dnw -u__u_boot_cmd_echo -u__u_boot_cmd_end -u__u_boot_cmd_erase -u__u_boot_cmd_exit -u__u_boot_cmd_fatinfo -u__u_boot_cmd_fatload -u__u_boot_cmd_fatls -u__u_boot_cmd_flinfo -u__u_boot_cmd_go -u__u_boot_cmd_help -u__u_boot_cmd_icache -u__u_boot_cmd_imls -u__u_boot_cmd_itest -u__u_boot_cmd_loadb -u__u_boot_cmd_loads -u__u_boot_cmd_loady -u__u_boot_cmd_loop -u__u_boot_cmd_md -u__u_boot_cmd_mm -u__u_boot_cmd_movi -u__u_boot_cmd_mtest -u__u_boot_cmd_mw -u__u_boot_cmd_nand -u__u_boot_cmd_nboot -u__u_boot_cmd_nfs -u__u_boot_cmd_nm -u__u_boot_cmd_ping -u__u_boot_cmd_printenv -u__u_boot_cmd_protect -u__u_boot_cmd_question_mark -u__u_boot_cmd_rarpboot -u__u_boot_cmd_reset -u__u_boot_cmd_saveenv -u__u_boot_cmd_setenv -u__u_boot_cmd_sleep -u__u_boot_cmd_start -u__u_boot_cmd_test -u__u_boot_cmd_tftpboot -u__u_boot_cmd_usb -u__u_boot_cmd_version
5.2 切换到u-boot顶层目录
5.3 arm-linux-ld链接生成最终elf类型的u-boot。
这里要注意连接器脚本文件u-boot.lds
LDFLAGS : -Bstatic -T /home/yjg/arm6410/qudong/01-uboot/uboot_ok6410/board/samsung/smdk6410/u-boot.lds -Ttext 0xCFE00000
从其中可以发现cpu/s3c64xx/start.S是u-boot执行的第一个文件,后面就从这个函数入手分析u-boot的启动流程。
1 OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") 2 /*OUTPUT_FORMAT("elf32-arm", "elf32-arm", "elf32-arm")*/ 3 OUTPUT_ARCH(arm) 4 ENTRY(_start) 5 SECTIONS 6 { 7 . = 0x00000000; 8 9 . = ALIGN(4); 10 .text : 11 { 12 cpu/s3c64xx/start.o (.text) 13 cpu/s3c64xx/s3c6410/cpu_init.o (.text) 14 cpu/s3c64xx/onenand_cp.o (.text) 15 cpu/s3c64xx/nand_cp.o (.text) 16 cpu/s3c64xx/movi.o (.text) 17 *(.text) 18 lib_arm/div0.o 19 } 20 21 . = ALIGN(4); 22 .rodata : { *(.rodata) } 23 24 . = ALIGN(4); 25 .data : { *(.data) } 26 27 . = ALIGN(4); 28 .got : { *(.got) } 29 30 __u_boot_cmd_start = .; 31 .u_boot_cmd : { *(.u_boot_cmd) } 32 __u_boot_cmd_end = .; 33 34 . = ALIGN(4); 35 .mmudata : { *(.mmudata) } 36 37 . = ALIGN(4); 38 __bss_start = .; 39 .bss : { *(.bss) } 40 _end = .; 41 }