uboot源码分析 (1) --makefile分析

1.为什么需要uboot,不能直接用linux启动。
答:linux内核对uboot初始化过的硬件照样要重新初始化一遍,那么为什么需要uboot呢,因为linux内核很大,为了减少硬件成本,必须放在相对便宜的储存器中。要知道,CPU只能够访问具有直接运行代码的存储设备,即内存。
而对于要启动设备而已,这个内存不仅要cup能够直接访问,而且断电不丢失数据。既然要有这么个内存,那么为了花费更小的硬件成本,就必须让内存尽量小,这也就是不能用来直接开启linux内核的原因。用尽可能短小精悍的代码初始化必要的硬件后,就把内核搬运到内存中(断电数据丢失,即RAM)中,然后启动内核,这是目前所有设备都采用的一种非常的设计方案。

分析uboot,首先就要分析makefile,makefile和链接脚本(uboot.lds)决定了代码的各种存放位置以及编译和链接的先后顺序。
 .我们首先编译uboot,make xxxx_config,查看makefile做了什么事情:
%_config::    unconfig
    @$(MKCONFIG) -A $(@:_config=) -->mkconfig -A xxxx
然后进入mkconfig
关键点:
line=`egrep -i "^[[:space:]]*${2}[[:space:]]" boards.cfg`
即查找有xxxx字符的这一行,然后把内容赋值给line变量

boards.cfg文件部分内容:
--------------------------------------------------------------------------------------------------------------------------
# Target                     ARCH        CPU         Board name          Vendor            SoC         Options
###########################################################################################################

qong                         arm         arm1136     -                   davedenx       mx31
mx31ads                      arm         arm1136     -                   freescale      mx31
imx31_litekit                arm         arm1136     -                   logicpd        mx31
omap2420h4                   arm         arm1136     -                   ti             omap24xx
tnetv107x_evm                arm         arm1176     tnetv107xevm        ti             tnetv107x
smdk6450             arm     arm11         smdk6450         samsung    s5p6450
armadillo                    arm         arm720t
ep7312                       arm         arm720t
impa7                        arm         arm720t
modnet50                     arm         arm720t
lpc2292sodimm                arm         arm720t     -                   -              lpc2292
SMN42                        arm         arm720t     -                   siemens        lpc2292
---------------------------------------------------------------------------------------------------------------------------
假设xxxx是qong那么
line=qong                         arm         arm1136     -                   davedenx       mx31
关键代码:set ${line}
这句代码之后:从makefile传递给mkconfig的参数就是:$1=qong $2=arm $3=arm1136 $4=devedenx $5=mx31
继续看mkconfig发现:
开始的
arch=""
cpu=""
board=""
vendor=""
soc=""
变成:
arch=$2
cpu=$3
board=$4
vendor=$5
soc=$6

关键点:
cd ${OBJTREE}/include2
ln -s ${LNPREFIX}arch-${cpu} asm/arch
ln -s ${LNPREFIX}proc-armv asm/proc
echo "ARCH   = ${arch}"  >  config.mk
echo "CPU    = ${cpu}"   >> config.mk
echo "BOARD  = ${board}" >> config.mk

cat << EOF >> config.h
#define CONFIG_BOARDDIR board/$BOARDDIR
#include <config_defaults.h>
#include <configs/${CONFIG_NAME}.h>
#include <asm/config.h>
EOF

可以看出,创建了两个文件:
include/config.mk //这个文件是给makefile使用的
include/config.h 编译程序时的包含具体soc型号的头文件
(此命令退出了)
这个命令的作用就是配置了我们需要针对的具体型号的配置信息。后续make的时候,就是根据这些信息配置编译的。


2.make all 
代码片段:

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 $< $@
        $(BOARD_SIZE_CHECK)
ifeq ($(CONFIG_S5PC210),y)
        ./mkbl2 u-boot.bin bl2.bin 14336
endif

$(obj)u-boot:    depend \
        $(SUBDIRS) $(OBJS) $(LIBBOARD) $(LIBS) $(LDSCRIPT) $(obj)u-boot.lds
一句话就是:
进入各个编译目录,讲.c文件编译成.o文件,然后根据u-boot.lds的链接规则,进行链接成文件u-boot,最重要的是最前面的代码段是哪里,这直接关系到设备已启动的代码是什么
我查看的一个arch/arm/cpu/arm7目录下的uboot-lds如下:
----------------------------------------------------------------------------------------------------------------------------------------------------------------
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(_start)
SECTIONS
{
 . = 0x00000000;
 . = ALIGN(4);
 .text :
 {
  arch/arm/cpu/armv7/start.o (.text)
  board/samsung/xyd4412/libxyd4412.o (.text)
  arch/arm/cpu/armv7/exynos/libexynos.o (.text)
  *(.text)
 }
 . = ALIGN(4);
 .rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }
 . = ALIGN(4);
 .data : {
  *(.data)
 }
 . = ALIGN(4);
 . = .;
 __u_boot_cmd_start = .;
 .u_boot_cmd : { *(.u_boot_cmd) }
 __u_boot_cmd_end = .;
 . = ALIGN(4);
 .rel.dyn : {
  __rel_dyn_start = .;
  *(.rel*)
  __rel_dyn_end = .;
 }
 .dynsym : {
  __dynsym_start = .;
  *(.dynsym)
 }
 .bss __rel_dyn_start (OVERLAY) : {
  __bss_start = .;
  *(.bss)
   . = ALIGN(4);
  _end = .;
 }
 /DISCARD/ : { *(.dynstr*) }
 /DISCARD/ : { *(.dynamic*) }
 /DISCARD/ : { *(.plt*) }
 /DISCARD/ : { *(.interp*) }
 /DISCARD/ : { *(.gnu*) }
}
------------------------------------------------------------------------------------------------------------------------------------------------------------------
可以看出,放在最前面的是arch/arm/cpu/armv7/start.o 那么意味着start.o是入门点。
好了,makefile分析至此,后面就根据入口函数分析uboot走势流程了
 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章