U-Boot 编译过程解析

解压u-boot-2010.03.tar.bz2就可以得到全部U-Boot源程序。在顶层目录下有29个子目录,分别存放和管理不同的源程序。这些目录中所要存放的文件有其规则,可以分为3类。


  ● 与处理器体系结构或者开发板硬件直接相关。

  ● 一些通用的函数或者驱动程序。

  ● U-Boot的应用程序、工具或者文件。


  表1.5列出了U-Boot顶层目录下各级目录的存放原则。


  表1.5 U-Boot的源码顶层目录说明
  U-Boot的源代码包含对几十种处理器、数百种开发板的支持。可是对于特定的开发板,配置编译过程只需其中部分程序。这里以S3C2410处理器为例,具体分析S3C2410处理器和开发板所依赖的程序,以及U-Boot的通用函数和工具。


  U-Boot的源码是通过gcc和Makefile组织编译的。顶层目录下的Makefile可以设置开发板的定义,然后递归地调用各级子目录下的Makefile,最后把编译过的程序链接成U-Boot映像。


  1)顶层目录下的Makefile


  Makefile负责U-Boot整体配置编译,按照配置的顺序阅读其中关键的几行。


  每一种开发板在Makefile下都需要有主板配置的定义。例如,smdk2410开发板的定义如下:

  smdk2410_config : unconfig

  $(MKCONFIG) $(:_config=) arm arm920t smdk2410 samsung s3c24x0

  执行配置U-Boot的命令make smdk2410_config,通过mkconfig脚本生成include/config.mk的配置文件,文件内容正是根据Makefile对开发板的配置生成的。
  ARCH = arm

  CPU = arm920t

  BOARD = smdk2410

  VENDOR = samsung

  SoC = s3c24x0

  上面的include/config.mk文件定义了ARCH、CPU、BOARD、VENDOR、SoC这些变量,这样,硬件平台依赖的目录文件可以根据这些定义来确定。SMDK2410平台相关目录如下:
  board/Samsung/smdk2410

  cpu/arm920t/

  cpu/arm920t/s3c24x0/

  lib_arm/

  include/configs/smdk2410.h

  再回到顶层目录的Makefile文件开始的部分,其中,下列几行包含了这些变量的定义:
  # load ARCH, BOARD, and CPU configuration

  include $(obj)include/config.mk

  export ARCH CPU BOARD VENDOR SOC

  Makefile的编译选项和规则在顶层目录的config.mk文件中定义,各种体系结构通用的规则直接在这个文件中定义。通过ARCH、CPU、BOARD、VENDOR、SoC等变量为不同硬件平台定义不同选项。不同体系结构的规则分别包含在ppc_config.mk、arm_config.mk、mips_config.mk等文件中。

  顶层目录的Makefile中还要定义交叉编译器,以及编译U-Boot所依赖的目标文件
  ifeq (arm,$(ARCH))

  CROSS_COMPILE ?=arm-none-linux-gnueabi-

  # 交叉编译器的前缀

  endif

  # load other configuration

  include $(TOPDIR)/config.mk

  # U-Boot objects....order is important (i.e. start must be first)

  OBJS = cpu/$(CPU)/start.o # 处理器相关的目标文件

  …

  #定义依赖的目录,每个目录下先把目标文件连接成*.a文件
  LIBS = lib_generic/libgeneric.a

  LIBS += lib_generic/lzma/liblzma.a

  LIBS += lib_generic/lzo/liblzo.a

  LIBS += $(shell if [ -f board/$(VENDOR)/common/Makefile ];

  Then echo "board/$(VENDOR)/common/lib$(VENDOR).a"; fi)

  LIBS += cpu/$(CPU)/lib$(CPU).a

  ifdef SOC

  LIBS += cpu/$(CPU)/$(SOC)/lib$(SOC).a

  endif

  ifeq ($(CPU),ixp)

  LIBS += cpu/ixp/npe/libnpe.a

  endif

  LIBS += lib_$(ARCH)/lib$(ARCH).a

  …

  还有U-Boot镜像编译的依赖关系如下:
  ALL += $(obj)u-boot.srec $(obj)u-boot.bin $(obj)System.map $(U_BOOT_NAND)

  $(U_BOOT_ONENAND)

  all: $(ALL)

  $(obj)u-boot.hex: $(obj)u-boot

  $(OBJCOPY) ${OBJCFLAGS} -O ihex $< $

  $(obj)u-boot.srec: $(obj)u-boot

  $(OBJCOPY) -O srec $< $

  $(obj)u-boot.bin: $(obj)u-boot

  $(OBJCOPY) ${OBJCFLAGS} -O binary $< $

  $(obj)u-boot.ldr: $(obj)u-boot

  $(CREATE_LDR_ENV)

  $(LDR) -T $(CONFIG_BFIN_CPU) -c $ $< $(LDR_FLAGS)

  $(obj)u-boot.ldr.hex: $(obj)u-boot.ldr

  $(OBJCOPY) ${OBJCFLAGS} -O ihex $< $ -I binary

  $(obj)u-boot.ldr.srec: $(obj)u-boot.ldr

  $(OBJCOPY) ${OBJCFLAGS} -O srec $< $ -I 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.imx: $(obj)u-boot.bin

  $(obj)tools/mkimage -n $(IMX_CONFIG) -T imximage \

  -e $(TEXT_BASE) -d $< $

  $(obj)u-boot.kwb: $(obj)u-boot.bin

  $(obj)tools/mkimage -n $(KWD_CONFIG) -T kwbimage \

  -a $(TEXT_BASE) -e $(TEXT_BASE) -d $< $

  $(obj)u-boot.sha1: $(obj)u-boot.bin

  $(obj)tools/ubsha1 $(obj)u-boot.bin

  $(obj)u-boot.dis: $(obj)u-boot

  $(OBJDUMP) -d $< > $

  Makefile默认的编译目标为all,包括u-boot.srec、u-boot.bin和System.map。u-boot.srec和u-boot.bin就是通过ld命令按照U-Boot.map地址表把目标文件组装成U-Boot的。其他Makefile内容就不再详细分析了,通过上述代码分析应该可以为读者阅读代码提供一些线索。


  2)开发板配置头文件

  除了编译过程Makefile以外,还要在程序中为开发板定义配置选项或者参数。这个头文件是include/configs/<board_name>.h。<board_name>用相应的BOARD定义代替
  这个头文件中主要定义了两类形式的参数。
  一类形式的参数用来选择处理器、设备接口、命令、属性等,以及定义总线频率、串口波特率、Flash地址等参数。

  大部分参数前缀是CONFIG_,例如:
  #define CONFIG_ARM920T 1

  #define CONFIG_KGDB_BAUDRATE 115200

  #define CONFIG_CS8900

  #define CONFIG_KGDB_BAUDRATE 115200

  另一类形式的参数为:
  #define PHYS_FLASH_SIZE 0x00100000

  #define USE_920T_MMU 1

  根据对Makefile的分析,编译分为两步。第1步是配置,如make smdk2410_config;第2步是编译,执行make就可以了
  编译完成后,可以得到U-Boot各种格式的映像文件和符号表,如表1.6所示。

  表1.6 U-Boot编译生成的映像文件
  U-Boot的3种映像格式都可以烧写到Flash中,但需要看加载器能否识别这些格式。一般u-boot.bin最为常用,直接按照二进制格式下载,并且按照绝对地址烧写到Flash中就可以了。U-Boot和u-boot.srec格式映像都自带定位信息
上一篇:Spring 的事务测试


下一篇:Django - 自定义 Filter