第1阶段——u-boot分析之make指令(2)
通过make 100ask24x0_config 指令配置好芯片选型后,使用make指令来生成uboot.bin文件
本文学习目标:
对Makefile文件进行基本了解,掌握make指令是怎么实现生成uboot.bin的过程
1.接下来开始分析make指令,首先打开u-boot-1.1.6/Makefile文件:
117 include $(OBJTREE)/include/config.mk //调用config.mk这个文件 118 ... 124 ifeq ($(ARCH),ppc) //判断config.mk这个文件中ARCH是否等于ppc 125 CROSS_COMPILE = powerpc-linux- 126 endif 127 ifeq ($(ARCH),arm) //判断config.mk这个文件中ARCH是否等于arm 128 CROSS_COMPILE = arm-linux- 129 endif ... 164 include $(TOPDIR)/config.mk
因为执行了make 100ask24x0_config 后,其中include/config.mk内容为:
ARCH = arm CPU = arm920t BOARD = 100ask24x0 SOC = s3c24x0
由于ARCH=arm,所以第127行为真,执行第128行语句使用arm-linux-来制定交叉编译器前缀。
其中第164行的config.mk是属于顶层目录的config,主要通过arm,arm920t,100ask24x0,s3c24x0来确定编译器、编译选项等
2.打开config.mk(主要作用如下几段):
45 PLATFORM_LDFLAGS = ... 88 BOARDDIR = $(BOARD) //$(BOARD)=100ask24x0 ... 91 sinclude $(TOPDIR)/board/$(BOARDDIR)/config.mk //调用 board/100ask24x0/config.mk中第25行"TEXT_BASE=0x33F80000." ... 143 LDSCRIPT := $(TOPDIR)/board/$(BOARDDIR)/u-boot.lds //LDSCRIPT=.//board/100ask24x0/u-boot.lds ... 189 LDFLAGS += -Bstatic -T $(LDSCRIPT) -Ttext $(TEXT_BASE) $(PLATFORM_LDFLAGS)
如下图,通过grep查找内容指令可以看出u-boot设置的TEXT_BASE地址为0x33F80000(若boot太大或SDRAM太小,可以减小TEXT_BASE基地址)
相当于向LDFLAGS内容中追加了"-T board/100ask24x0/u-boot.lds -Ttext 0x33F80000"字段,(LDFLAGS:属于u-boot第四个依赖文件)
3.继续看makefile:
169 OBJS = cpu/$(CPU)/start.o //u-boot需要的目标文件,OBJS等于目标文件cpu/$(CPU)/start.o ... 193 LIBS = lib_generic/libgeneric.a //u-boot需要的库文件,LIBS等于库文件lib_generic/libgeneric.a 194 LIBS += board/$(BOARDDIR)/lib$(BOARD).a //追加库文件board/100ask24x0/lib100ask24x0.a 195 LIBS += cpu/$(CPU)/lib$(CPU).a //追加库文件cpu/arm920t/libarm920t.a ... 214 LIBS := $(addprefix $(obj),$(LIBS)) //addprefix为加前缀函数,其中obj=空,所以LIBS地址不变 ... 222 SUBDIRS = tools \ //SUBDIRS伪命令:用来执行tools,examples,post,post\cpu子目录下面的make文件。 223 examples \ 224 post \ 225 post/cpu ... 239 ALL = $(obj)u-boot.srec $(obj)u-boot.bin $(obj)System.map $(U_BOOT_NAND) //all的依赖文件 240 241 all: $(ALL) //使用make命令,相当于执行make all ... 249 $(obj)u-boot.bin: $(obj)u-boot //生成u-boot.bin需要elf格式的u-boot,elf也就是通过ld链接文件生成的。 250 $(OBJCOPY) ${OBJCFLAGS} -O binary $< $@ //执行:arm-linux-objcopy -O binary u-boot u-boot.bin ... 262 $(obj)u-boot: depend version $(SUBDIRS) $(OBJS) $(LIBS) $(LDSCRIPT) //生成elf格式的u-boot所需要的依赖文件 263 UNDEF_SYM=`$(OBJDUMP) -x $(LIBS) |sed -n -e 's/.*\(__u_boot_cmd_.*\)/-u\1/p'|sort|uniq`;\ 264 cd $(LNDIR) && $(LD) $(LDFLAGS) $$UNDEF_SYM $(__OBJS) \ 265 --start-group $(__LIBS) --end-group $(PLATFORM_LIBS) \ 266 -Map u-boot.map -o u-boot
在第263行和266行翻译出内容如下所示:
UNDEF_SYM=`arm-linux-objdump -x lib_generic/libgeneric.a board/100ask24x0/lib100ask24x0.a cpu/arm920t/libarm920t.a cpu/arm920t/s3c24x0/libs3c24x0.a lib_arm/libarm.a fs/cramfs/libcramfs.a fs/fat/libfat.afs/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/usb/libusb.a drivers/sk98lin/libsk98lin.a common/libcommon.a
|sed -n -e 's/.*\(__u_boot_cmd_.*\)/-u\1/p'|sort|uniq`;\
cd /work/system/u-boot-1.1.6 &&
arm-linux-ld -Bstatic -T /work/system/u-boot-1.1.6/board/100ask24x0/u-boot.lds -Ttext 0x33F80000
$UNDEF_SYM cpu/arm920t/start.o \
--start-group
lib_generic/libgeneric.a board/100ask24x0/lib100ask24x0.a
cpu/arm920t/libarm920t.a cpu/arm920t/s3c24x0/libs3c24x0.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/usb/libusb.a
drivers/sk98lin/libsk98lin.a
common/libcommon.a
--end-group -L
/work/tools/gcc-3.4.5-glibc-2.3.6/lib/gcc/arm-linux/3.4.5 -lgcc \
-Map u-boot.map -o u-boot
在第263行和266行就是在制作elf格式的u-boot, 其中$(LIBS)和$(__LIBS)就是库文件,$(LD)为连接选项,$(__OBJS)为目标文件,
$(LDFLAGS)指定程序的布局与地址,为"/work/system/u-boot-1.1.6/board/100ask24x0/u-boot.lds -Ttext 0x33F80000 ..."
4.board/100ask24x0/u-boot.lds文件如下所示:
OUTPUT_ARCH(arm) //设置输出文件的体系架构。 ENTRY(_start) //将_start这个全局符号设置成入口地址,进行复位初始化 SECTIONS //输出文件的内容布局 { . = 0x00000000; //指定地址0x00000000,最终运行地址在0x33F80000+0x00000000 . = ALIGN(4); //代码以4字节对齐 .text : //指定.text section段(位于0x33F80000) { cpu/arm920t/start.o (.text) //添加第一个目标文件cpu/arm920t/start.o里面的.text代码段 board/100ask24x0/boot_init.o (.text) //添加第二个目标文件board/100ask24x0/boot_init.o里面的.text代码段 *(.text) //*(.data) 表示添加剩下的全部文件的.text代码段 } . = ALIGN(4); .rodata : { *(.rodata) } //指定.rodata section段(位于0x33F80000+.text section),将所有的.rodata只读数据段合并成一个.rodata只读数据段 . = ALIGN(4); .data : { *(.data) } //指定读写数据段 . = ALIGN(4); .got : { *(.got) } //指定got段,got段是uboot自定义的一个段 . = .; __u_boot_cmd_start = .; //把__u_boot_cmd_start赋值为当前位置, 即起始位置 .u_boot_cmd : { *(.u_boot_cmd) } // u_boot_cmd段,所有的u-boot命令相关的定义都放在这个位置 __u_boot_cmd_end = .; // *u_boot_cmd段结束位置 . = ALIGN(4); __bss_start = .; //把__bss_start赋值为当前位置,即bss段的开始位置 .bss : { *(.bss) } //指定bss段,这里NOLOAD的意思是这段不需装载,仅在执行域中才会有这段 _end = .; //把_end赋值为当前位置,即bss段的结束位置 }
人间有真情,人间有真爱。