分析uboot编译过程 make
查看顶层Makefile
include $(OBJTREE)/include/config.mk 包含的就是配置时生成的config.mk文件
export ARCH CPU BOARD VENDOR SOC
从include/config.mk得到以下几个参数的值
ARCH = arm
CPU = arm920t
BOARD = 100ask24x0
SOC = s3c24x0
ifeq ($(ARCH),arm) // ARCH = arm, 所以交叉编译工具链就是arm-linux-
CROSS_COMPILE = arm-linux-
endif
继续分析顶层Makefile
OBJS = cpu/$(CPU)/start.o # OBJS = cpu/arm920t/start.o
# obj :=
# src :=
# addprefix 是makefile中的函数,是添加前缀的函数 $(addprefix src/,foo) ==> src/foo
# 因为$(obj)为空 所以以下结果为 OBJS := $(OBJS)
OBJS := $(addprefix $(obj),$(OBJS))
LIBS = lib_generic/libgeneric.a
LIBS += board/$(BOARDDIR)/lib$(BOARD).a # LIBS += board/100ask24x0/lib100ask24x0.a
LIBS += cpu/arm920t/libarm920t.a
#########################################################################
#########################################################################
ALL = $(obj)u-boot.srec $(obj)u-boot.bin $(obj)System.map $(U_BOOT_NAND)
all: $(ALL)
$(obj)u-boot.hex: $(obj)u-boot
$(OBJCOPY) ${OBJCFLAGS} -O ihex $< $@
$(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.img: $(obj)u-boot.bin
./tools/mkimage -A $(ARCH) -T firmware -C none \
-a $(TEXT_BASE) -e 0 \
-n $(shell sed -n -e 's/.*U_BOOT_VERSION//p' $(VERSION_FILE) | \
sed -e 's/"[ ]*$$/ for $(BOARD) board"/') \
-d $< $@
$(obj)u-boot.dis: $(obj)u-boot
$(OBJDUMP) -d $< > $@
$(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
$(OBJS):
echo $(OBJS)
$(MAKE) -C cpu/$(CPU) $(if $(REMOTE_BUILD),$@,$(notdir $@))
$(LIBS):
$(MAKE) -C $(dir $(subst $(obj),,$@))
直接从编译执行的命令输出反推:
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.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 |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 \
-Map u-boot.map -o u-boot
arm-linux-objcopy --gap-fill=0xff -O srec u-boot u-boot.srec
arm-linux-objcopy --gap-fill=0xff -O binary u-boot u-boot.bin
arm-linux-ld命令生成u-boot链接文件, 链接文件依赖于链接文件和.o 和.a这些原材料,
而这些原材料是怎么组织成u-boot这个链接文件的, 哪些代码会放在最前面, 是由链接脚本u-boot.lds决定的
下面分析链接脚本 board/100ask24x0/u-boot.lds
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
/*OUTPUT_FORMAT("elf32-arm", "elf32-arm", "elf32-arm")*/
OUTPUT_ARCH(arm)
ENTRY(_start)
SECTIONS
{
. = 0x00000000; /* 当前地址=0*/ 会加上arm-linux-ld命令指定的-Ttext参数指定的值0x33F80000, 也就是内容会从0x33F80000这个位置开始排放
. = ALIGN(4);
.text :
{
cpu/arm920t/start.o (.text) /* 最开始排放cpu/arm920t/start.o文件的text段, 之后是board/100ask24x0/boot_init.o文件的text段, 然后是其他所有.o文件的text段*/
board/100ask24x0/boot_init.o (.text)
*(.text)
}
. = ALIGN(4);
.rodata : { *(.rodata) } / *4字节对齐后排放所有文件的只读数据段 */
. = ALIGN(4);
.data : { *(.data) } / *4字节对齐后排放所有文件的数据段 */
. = ALIGN(4);
.got : { *(.got) } / *4字节对齐后排放所有文件的got段 */
. = .;
__u_boot_cmd_start = .;
.u_boot_cmd : { *(.u_boot_cmd) } / *然后排放所有文件的u_boot_cmd段 */
__u_boot_cmd_end = .;
. = ALIGN(4);
__bss_start = .;
.bss : { *(.bss) } / *然后排放所有文件的bss段 */
/* 初始值为0的静态变量和全局变量 或 没有初始化的静态变量和全局变量就放在.bss段 */
_end = .;
}
从第一个文件cpu/arm920t/start.S分析就可以知道整个uboot的流程