u-boot-2014.10 make流程分析

u-boot-2014.10在做完xxx_defconfig后,它会根据configs/<board>_defconfig创建的.config配置文件。接着使用make命令进行编译,则执行默认目标all

# That's our default target when none is given on thecommand line
PHONY := _all
_all:
…
# We process the rest of the Makefile if this is thefinal invocation of make
ifeq ($(skip-makefile),)
 
# If building an external module we do not care about theall: rule
# but instead _all depend on modules
PHONY += all
ifeq ($(KBUILD_EXTMOD),)
_all: all
else
_all: modules
endif

其中skip-makefile和KBUILD_EXTMOD都未定义,所以运行_all:all

all:        $(ALL-y)

需要依赖条件$(ALL-y),而$(ALL-y)的定义如下

ALL-y += u-boot.srec u-boot.bin System.mapbinary_size_check

l 需要依赖条件u-boot.srec

u-boot.hex u-boot.srec: u-boot FORCE
    $(call if_changed,objcopy)

l 需要依赖条件u-boot.bin

u-boot.bin: u-boot FORCE
    $(call if_changed,objcopy)
    $(callDO_STATIC_RELA,$<,$@,$(CONFIG_SYS_TEXT_BASE))
    $(BOARD_SIZE_CHECK)

l 需要依赖条件System.map

System.map: u-boot
        @$(call SYSTEM_MAP,$<) > $@

l  需要依赖条件binary_size_check

binary_size_check: u-boot.bin FORCE
    @file_size=$(shell wc -c u-boot.bin | awk '{print $$1}') ; \
    map_size=$(shell cat u-boot.map | \
        awk '/_image_copy_start/{start = $$1} /_image_binary_end/ {end = $$1} END {if (start != ""&& end != "") print "ibase=16; " toupper(end)" - " toupper(start)}' \
        | sed 's/0X//g' \
        | bc); \
    if [ "" != "$$map_size" ]; then \
        if test $$map_size -ne $$file_size; then \
            echo "u-boot.mapshows a binary size of $$map_size" >&2 ; \
            echo "  but u-boot.bin shows $$file_size" >&2 ; \
            exit 1; \
        fi \
    fi

依赖u-boot.srec u-boot.bin System.map都需要u-boot这个elf文件其依赖关系如下

u-boot: $(u-boot-init) $(u-boot-main) u-boot.lds
    $(call if_changed,u-boot__)
ifeq ($(CONFIG_KALLSYMS),y)
    $(call cmd,smap)
    $(call cmd,u-boot__) common/system_map.o
endif

要生成u-boot elf文件需要用到$(u-boot-init) $(u-boot-main) u-boot.lds依赖关系,

u-boot-init依赖定义为

u-boot-init := $(head-y)

其中head-y定义为

head-y := $(CPUDIR)/start.o

u-boot-init指向start.s第一个启动文件


u-boot-main依赖定义为

u-boot-main := $(libs-y)

其中libs-y定义为各种库和驱动。

 

u-boot.lds依赖定义为

u-boot.lds: $(LDSCRIPT) prepare FORCE
    $(callif_changed_dep,cpp_lds)

LDSCRIPT依赖定义为

ifndef LDSCRIPT
    #LDSCRIPT :=$(srctree)/board/$(BOARDDIR)/u-boot.lds.debug
    ifdefCONFIG_SYS_LDSCRIPT
        # need to stripoff double quotes
        LDSCRIPT := $(srctree)/$(CONFIG_SYS_LDSCRIPT:"%"=%)
    endif
endif
 
# If there is no specified link script, we look in anumber of places for it
ifndef LDSCRIPT
    ifeq ($(wildcard $(LDSCRIPT)),)
        LDSCRIPT := $(srctree)/board/$(BOARDDIR)/u-boot.lds
    endif
    ifeq ($(wildcard $(LDSCRIPT)),)
        LDSCRIPT := $(srctree)/$(CPUDIR)/u-boot.lds
    endif
    ifeq ($(wildcard $(LDSCRIPT)),)
        LDSCRIPT := $(srctree)/arch/$(ARCH)/cpu/u-boot.lds
    endif
endif

当配置文件中定义了CONFIG_SYS_LDSCRIPT,则使用指定的,如果没有定义,到这三个位置寻找连接文件。

Prepare依赖等于为

# All the preparing..
prepare: prepare0

prepare0依赖定义为

prepare0: archprepare FORCE
    $(Q)$(MAKE) $(build)=.

Archprepare依赖定义为

archprepare: prepare1scripts_basic

scripts_basic依赖定义为

make -f scripts/Makefile.build obj=scripts/basic
rm -f .tmp_quiet_recordmcount

详细见u-boot-2014-10 Makefile配置过程分析

prepare1依赖定义为

prepare1: prepare2 $(version_h) $(timestamp_h) include/config/auto.conf

其中version_h为

version_h := include/generated/version_autogenerated.h

timestamp_h为

timestamp_h := include/generated/timestamp_autogenerated.h

prepare2依赖定义为

prepare2: prepare3outputmakefile

其中outputmakefile得不到执行(详细见u-boot-2014-10 Makefile配置过程分析)

prepare3依赖定义为

prepare3: include/config/uboot.release

其中nclude/config/uboot.release依赖为

include/config/uboot.release: include/config/auto.conf FORCE
    $(call filechk,uboot.release)

现在有两个地方都使用了include/config/auto.conf依赖,其定义如下

include/config/%.conf: $(KCONFIG_CONFIG) include/config/auto.conf.cmd
    $(Q)$(MAKE) -f $(srctree)/Makefilesilentoldconfig

其中KCONFIG_CONFIG =.config

依赖$(KCONFIG_CONFIG) include/config/auto.conf.cmd被强制更新

# To avoid any implicit rule to kick in, define an emptycommand
$(KCONFIG_CONFIG) include/config/auto.conf.cmd: ;

接着执行命令

make -f ./Makefilesilentoldconfig

接着会在顶层Makefile中匹配

%config: scripts_basicoutputmakefile FORCE
    +$(Q)$(CONFIG_SHELL) $(srctree)/scripts/multiconfig.sh $@

这里的流程与配置很相似,scripts_basic依赖是调用makefile.build编译scripts/basic目录下的文件,ouputmakefile依赖和FORCE不会执行。

接着调用scripts/multiconfig.sh脚本,其参数为silentoldconfig(这部分分析可以参考Makefile配置流程分析)

progname=multiconfig.sh
target=silentoldconfig
case $target in
*_defconfig)
   do_board_defconfig $target;;
*_config)
    # backwardcompatibility
   do_board_defconfig ${target%_config}_defconfig;;
<span style="color:#ff0000;">silentoldconfig)
   do_silentoldconfig;;</span>
defconfig)
    do_defconfig;;
savedefconfig)
   do_savedefconfig;;
*)
    do_others$target;;
esac

接下来调用do_silentoldconfig函数进行配置

do_silentoldconfig () {
    run_make_config silentoldconfig
    subimages=$(get_enabled_subimages)
 
    for obj in $subimages
    do
        mkdir -p $obj/include/config $obj/include/generated
       run_make_config silentoldconfig $obj
    done
 
    # If thefollowing part fails, include/config/auto.conf should be
    # deleted so"make silentoldconfig" will be re-run on the next build.
    autoconf includeinclude/autoconf.mk include/autoconf.mk.dep ||{
        rm -finclude/config/auto.conf
        exit 1
    }
 
    #include/config.h has been updated after "make silentoldconfig".
    # We need totouch include/config/auto.conf so it gets newer
    # thaninclude/config.h.
    # Otherwise,'make silentoldconfig' would be invoked twice.
    touch include/config/auto.conf
 
    for obj in $subimages
    do
        autoconf$obj/include $obj/include/autoconf.mk || {
            rm -f include/config/auto.conf
            exit 1
        }
    done
}

这里需要关注run_make_config函数和autoconf函数

首先调用run_make_config进行配置

target=$1
objdir=$2
 
# Linux expects defconfig files inarch/$(SRCARCH)/configs/ directory,
# but U-Boot has them in configs/ directory.
# Give SRCARCH=.. to fake scripts/kconfig/Makefile.
options="SRCARCH=..KCONFIG_OBJDIR=$objdir"
if [ "$objdir" ]; then
options="$optionsKCONFIG_CONFIG=$objdir/$KCONFIG_CONFIG"
mkdir -p $objdir
fi
 
build scripts/kconfig $options$target

拓展后

target= silentoldconfig
objdir=
make -f ./scripts/Makefile.build obj="scripts/kconfigsilentoldconfig"

接着使用 ./scripts /Makefile .build调用 scripts/kconfig目录下的Makefile文件进行接下来的配置, scripts/kconfig/Makefile规则匹配

silentoldconfig: $(obj)/conf
    $(Q)mkdir -p include/config include/generated
    $< --$@ $(Kconfig)
拓展后

silentoldconfig: /scripts/kconfig/conf
    mkdir -p include/config include/generated
    /scripts/kconfig/conf --silentoldconfigKconfig

其先创建两个文件,然后再使用conf进行接下来的配置。Conf源码在scripts/kconfig目录下,当conf运行后,首先解析silentoldconfig

while ((opt = getopt_long(ac, av, "", long_opts, NULL)) != -1) {
        input_mode = (enum input_mode)opt;
        switch (opt) {
        case silentoldconfig:
            sync_kconfig= 1;
            break;
        case defconfig:
        case savedefconfig:
            defconfig_file= optarg;
            break;
            ......
}

sync_kconfig 这个变量会为 1

调用函数conf_parse(name);将Kconfig中的配置信息放到一个链表中。

接着获取.config中的配置信息

if (sync_kconfig) {
        name = conf_get_configname();
        if (stat(name, &tmpstat)) {
            fprintf(stderr, _("***\n"
                "***Configuration file \"%s\" not found!\n"
                "***\n"
                "*** Pleaserun some configurator (e.g. \"make oldconfig\" or\n"
                "***\"make menuconfig\" or \"make xconfig\").\n"
                "***\n"), name);
            exit(1);
        }
    }

接着的input_mode为silentoldconfig,所以会执行conf_read(NULL)函数;conf_read(NULL);函数用来读取 .config 文件。读取的各种相关内容主要存放在一个 struct symbol 结构链表里,而各个结构的相关指针则放在一个 symbol_hash[] 的数组中,对于数组中元素的寻找通过 fnv32 哈希算法进行定位。

switch (input_mode) {
    .....
    case savedefconfig:
    case silentoldconfig:
    case oldaskconfig:
    case oldconfig:
    case listnewconfig:
    case olddefconfig:
       conf_read(NULL);
        break;
    case allnoconfig:
    case allyesconfig:
    .....
}

由于sync_kconfig变量为1所以在最后进入下面分支

if (sync_kconfig) {
        /* silentoldconfigis used during the build so we shall update autoconf.
         * Allother commands are only used to generate a config.
         */
        if (conf_get_changed() && conf_write(NULL)) {
            fprintf(stderr, _("\n*** Errorduring writing of the configuration.\n\n"));
            exit(1);
        }
        if (conf_write_autoconf()) {
            fprintf(stderr, _("\n*** Errorduring update of the configuration.\n\n"));
            return 1;
        }

在 if(conf_get_changed() && conf_write(NULL)) 这个判断里,conf_get_changed()函数判断 .config 文件是否做过变动,如果是,那么会调用 conf_write(NULL) 来重新写.config 文件。接着调用conf_write_autoconf()函数,在该函数里面会创建auto.conf.cmd、autoconf.h、tristate.conf、auto.conf等文件,并将注释写入到其中

conf_write_heading(out, &kconfig_printer_cb, NULL);
 
    conf_write_heading(tristate, &tristate_printer_cb, NULL);
 
    conf_write_heading(out_h, &header_printer_cb, NULL);

然后通过for_all_symbols(I,sym)循环的往后3个文件分别写入相关的内容

for_all_symbols(i, sym) {
        sym_calc_value(sym);
        if (!(sym->flags & SYMBOL_WRITE) || !sym->name)
            continue;
 
        /* write symbol toauto.conf, tristate and header files */
        conf_write_symbol(out, sym, &kconfig_printer_cb, (void *)1);
 
        conf_write_symbol(tristate, sym, &tristate_printer_cb, (void *)1);
 
        conf_write_symbol(out_h, sym, &header_printer_cb, NULL);
    }

Conf运行完成后,返回到scripts/multiconfig.sh脚本中的do_silentoldconfig函数,并接着向下运行

Run_make_config函数讲解完成后,现在分析autoconf函数

  # If thefollowing part fails, include/config/auto.conf should be
    # deleted so"make silentoldconfig" will be re-run on the next build.
    autoconfinclude include/autoconf.mk include/autoconf.mk.dep || {
        rm -f include/config/auto.conf
        exit 1
    }

当前半部分为真则不执行下半部分的内容。这里的autoconf函数定义如下

autoconf () {
    debug $progname: $MAKE -f $srctree/scripts/Makefile.autoconf obj="$@"
    $MAKE -f $srctree/scripts/Makefile.autoconf obj="$@"
}

其调用的是makefile.autoconf

拓展后得到

make -f ./scripts/Makefile.autoconf obj="includeinclude/autoconf.mk include/autoconf.mk.dep"

由于没有传递目标到Makefile.autoconf,所以Makefile.autoconf采用默认配置

include/config.h: scripts/Makefile.autoconfcreate_symlink FORCE
    $(call filechk,config_h)

依赖scripts/Makefile.autoconfcreate_symlink

create_symlink:
ifneq ($(KBUILD_SRC),)
    $(Q)mkdir -p include/asm
endif
    $(Q)ln -fsn $(srctree)/arch/$(ARCH)/include/asm/arch-$(if $(SOC),$(SOC),$(CPU)) \
        $(if $(KBUILD_SRC),,arch/$(ARCH)/)include/asm/arch

将其拓展后

create_symlink:
         ln-fsn arch/arm/include/asm/arch-s3c24x0 arch/arm/include/asm/arch

可以得到这里是创建一个软连接。

整体流程解析完成后,接着就是编译,生成u-boot

arm-linux-ld   -pie  --gc-sections -Bstatic -Ttext 0x0 \
 -o u-boot -T u-boot.lds arch/arm/cpu/arm920t/start.o \
 --start-group  arch/arm/cpu/built-in.o \
 arch/arm/cpu/arm920t/built-in.o  \
 arch/arm/cpu/arm920t/s3c24x0/built-in.o \
 arch/arm/lib/built-in.o  \
 board/samsung/common/built-in.o  \
 board/samsung/smdk2410/built-in.o  \
 common/built-in.o  disk/built-in.o  drivers/built-in.o \
 drivers/dma/built-in.o  drivers/gpio/built-in.o  \
 drivers/i2c/built-in.o  drivers/mmc/built-in.o  \
 drivers/mtd/built-in.o  drivers/mtd/nand/built-in.o \
 drivers/mtd/onenand/built-in.o  drivers/mtd/spi/built-in.o \
 drivers/mtd/ubi/built-in.o  drivers/net/built-in.o  \
 drivers/net/phy/built-in.o  drivers/pci/built-in.o  \
 drivers/power/built-in.o  drivers/power/battery/built-in.o  \
 drivers/power/fuel_gauge/built-in.o  drivers/power/mfd/built-in.o  \
 drivers/power/pmic/built-in.o  drivers/serial/built-in.o \
 drivers/spi/built-in.o  drivers/usb/eth/built-in.o \
 drivers/usb/gadget/built-in.o  drivers/usb/host/built-in.o \
 drivers/usb/musb-new/built-in.o  drivers/usb/musb/built-in.o \
 drivers/usb/phy/built-in.o  drivers/usb/ulpi/built-in.o \
 fs/built-in.o  lib/built-in.o  lib/libfdt/built-in.o  net/built-in.o\
 test/built-in.o  test/dm/built-in.o --end-group arch/arm/lib/eabi_compat.o \
 -L /usr/local/arm/4.3.2/bin/../lib/gcc/arm-none-linux-gnueabi/4.3.2/armv4t  -lgcc -Map u-boot.map

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
u-boot-2016.11.tar.bz2是一个开源软件项目的压缩文件。该压缩文件是u-boot引导加载程序的源代码和相关文件的打包形式。u-boot(Universal Bootloader)是一款用于嵌入式系统的开源引导加载程序,用于初始化硬件并启动操作系统。 u-boot-2016.11.tar.bz2文件的扩展名.tar.bz2表示它是使用tar和bzip2两种工具进行压缩的。.tar是一个常用的文件打包工具,它可以将多个文件和目录打包成一个文件。.bz2是一个压缩工具,可以将文件进行高效压缩。 要使用u-boot-2016.11.tar.bz2文件,首先需要将其解压缩。可以使用tar命令进行解压缩,命令为tar -xjf u-boot-2016.11.tar.bz2。这将解压缩文件,并将源代码和其他相关文件提取到当前目录下。 解压缩后,可以在提取出的文件中找到u-boot引导加载程序的源代码和相关文件。可以根据需要进行定制和编译,生成适合特定硬件平台的引导加载程序。u-boot支持多种处理器架构和开发板,可以根据需要进行配置。 根据u-boot-2016.11.tar.bz2文件的版本号来看,它是2016年11月发布的版本。这意味着该版本已经存在一段时间,并可能具有稳定性和经过验证的特性。对于需要使用u-boot的开发者和嵌入式系统制造商,这个版本可以作为一个可靠的基础进行开发和定制。 总之,u-boot-2016.11.tar.bz2是u-boot引导加载程序的源代码和相关文件的压缩包。解压缩后,可以通过定制和编译源代码,生成适合特定硬件平台的引导加载程序。这个版本已经存在一段时间,并可能具有可靠的特性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值