zoukankan      html  css  js  c++  java
  • UBoot配置编译及Makefile分析

    一、 UBoot配置编译初步分析

    1. UBoot源码结构

    (1)UBoot工程项目中的文件可以分为3类

    ① 第1类目录:与处理器体系结构或开发板硬件直接相关

    ② 第2类目录:一些通用的函数或驱动程序

    ③ 第3类目录:UBoot的应用程序、工具或文档

    2. UBoot的配置编译

    make <board_name>_config
    make

    3. UBoot的配置编译初步分析

    (1)顶层目下的Makefile:每一种开发板在顶层Makefile中都有自己的配置规则

    mini2440_config    :    unconfig
        @$(MKCONFIG) $(@:_config=) arm arm920t mini2440 samsung s3c24x0    

    (2)执行make mini2440_config命令,将通过UBoot顶层目录下的mkconfig脚本生成配置文件include/config.mk

    ARCH   = arm
    CPU    = arm920t
    BOARD  = mini2440
    VENDOR = samsung
    SOC    = s3c24x0

    (3)而顶层目录的Makefile则包含了include/config.mk文件

    # load ARCH, BOARD, and CPU configuration
    include $(obj)include/config.mk
    export    ARCH CPU BOARD VENDOR SOC

    (4)Makefile的编译选项和规则

    ① 各种体系结构通用的规则直接在顶层目录的config.mk文件中,通过ARCH、CPU、BOARD、SOC等变量为不同平台定义不同选项。

    ② 不同体系结构的规则分别包含在各自的lib_xxx目录下的config.mk文件中

    (5)开发板配置头文件:移植时为开发板定义配置选项及参数,文件名为include/configs/<board_name>.h

    #define CONFIG_ARM920T            /* This is an ARM920T Core    */
    #define CONFIG_S3C24X0            /* in a SAMSUNG S3C24X0 SoC */

    (6)编译结果

    ① 根据对Makefile的分析,编译分为两步:第1步配置,如make mini2440_config;第2步编译,执行make命令

    ② 编译完成后可得到UBoot的各种格式的映像文件和符号表

    System.map:

    u-boot:

    u-boot.bin:

    u-boot.srec:

    (7)UBoot常用工具:编译完成后在tools目录下会生成一些常用工具

    ① bmp_logo

    ② img2srec

    ③ envcrc

    ④ mkimage

    ⑤ gen_eth_addr

    ⑥ updater

    二、UBoot配置编译详细分析

    1. 主机构建环境配置过程:顶层Makefile

    (1)定义主机系统架构:HOSTARCH:=i386

    HOSTARCH := $(shell uname -m | 
        sed -e s/i.86/i386/ 
            -e s/sun4u/sparc64/ 
            -e s/arm.*/arm/ 
            -e s/sa110/arm/ 
            -e s/powerpc/ppc/ 
            -e s/ppc64/ppc/ 
            -e s/macppc/ppc/)

    ① “sed -e s/abc/def/”:表示从标准输入中查找内容为“abc”的字符串,然后替换为def。其中“abc”中可以用“.”作为通配符

    ② uname -m:输出主机CPU架构类型

    (2)定义主机操作系统类型:HOSTOS:=linux

    HOSTOS := $(shell uname -s | tr '[:upper:]' '[:lower:]' | 
            sed -e 's/(cygwin).*/cygwin/')

    (3)定义脚本解释器:SHELL:=/bin/bash

    SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; 
        else if [ -x /bin/bash ]; then echo /bin/bash; 
        else echo sh; fi; fi)

    (4)设定编译输出目录:BUILD_DIR:=./

    ① 执行“make O=/tmp/build”命令可以将输出目录设置为特定目录

    ifdef O
    ifeq ("$(origin O)", "command line")
    BUILD_DIR := $(O)
    endif
    endif

    ② 与UBoot源码目录和输出目录相关的变量

    OBJTREE        := $(if $(BUILD_DIR),$(BUILD_DIR),$(CURDIR))
    SRCTREE        := $(CURDIR)
    TOPDIR        := $(SRCTREE)
    LNDIR        := $(OBJTREE)

     

    2. 目标机相关配置过程

    (1)顶层Makefie中与具体开发板相关的配置规则

    mini2440_config    :    unconfig
        @$(MKCONFIG) $(@:_config=) arm arm920t mini2440 samsung s3c24x0    

    其中依赖“unconfig”的定义如下

    unconfig:
        @rm -f $(obj)include/config.h $(obj)include/config.mk 
            $(obj)board/*/config.tmp $(obj)board/*/*/config.tmp 
            $(obj)include/autoconf.mk $(obj)include/autoconf.mk.dep

    unconfig的作用是清除上次执行make *_config命令产生的配置文件

    (2)将具体开发板相关的配置规则替换变量后

    ./mkconfig mini2440 arm arm920t mini2440 samsung s3c24x0

    也就是以“mini2440 arm arm920t mini2440 samsung s3c24x0”为参数执行mkconfig脚本

    (3)mkconfig的用法

    # Parameters:  Target  Architecture  CPU  Board [VENDOR] [SOC]

    ① 确定开发板名称:BOARD_NAME:=mini2440

    while [ $# -gt 0 ] ; do
        case "$1" in
        --) shift ; break ;;
        -a) shift ; APPEND=yes ;;
        -n) shift ; BOARD_NAME="${1%%_config}" ; shift ;;
        -t) shift ; TARGETS="`echo $1 | sed 's:_: :g'` ${TARGETS}" ; shift ;;
        *)  break ;;
        esac
    done
    
    [ "${BOARD_NAME}" ] || BOARD_NAME="$1"

    ② 检查参数合法性

    [ $# -lt 4 ] && exit 1
    [ $# -gt 6 ] && exit 1
    
    if [ "${ARCH}" -a "${ARCH}" != "$2" ]; then
        echo "Failed: $ARCH=${ARCH}, should be '$2' for ${BOARD_NAME}" 1>&2
        exit 1
    fi

     ③ 创建到目标板相关目录的链接

    if [ "$SRCTREE" != "$OBJTREE" ] ; then
        mkdir -p ${OBJTREE}/include
        mkdir -p ${OBJTREE}/include2
        cd ${OBJTREE}/include2
        rm -f asm
        ln -s ${SRCTREE}/include/asm-$2 asm
        LNPREFIX="../../include2/asm/"
        cd ../include
        rm -rf asm-$2
        rm -f asm
        mkdir asm-$2
        ln -s asm-$2 asm
    else
        cd ./include
        rm -f asm
        ln -s asm-$2 asm
    fi

    rm -f asm-$2/arch

    if [ -z "$6" -o "$6" = "NULL" ] ; then
        ln -s ${LNPREFIX}arch-$3 asm-$2/arch
    else
        ln -s ${LNPREFIX}arch-$6 asm-$2/arch
    fi

    if [ "$2" = "arm" ] ; then
        rm -f asm-$2/proc
        ln -s ${LNPREFIX}proc-armv asm-$2/proc
    fi

    ④ 构建include/config.mk文件

    echo "ARCH   = $2" >  config.mk
    echo "CPU    = $3" >> config.mk
    echo "BOARD  = $4" >> config.mk
    
    [ "$5" ] && [ "$5" != "NULL" ] && echo "VENDOR = $5" >> config.mk
    
    [ "$6" ] && [ "$6" != "NULL" ] && echo "SOC    = $6" >> config.mk

    ⑤ 构建include/config.h文件

    if [ "$APPEND" = "yes" ]    # Append to existing config file
    then
        echo >> config.h
    else
        > config.h        # Create new config file
    fi
    echo "/* Automatically generated - do not edit */" >>config.h
    
    for i in ${TARGETS} ; do
        echo "#define CONFIG_MK_${i} 1" >>config.h ;
    done
    
    cat << EOF >> config.h
    #define CONFIG_BOARDDIR board/$BOARDDIR
    #include <config_defaults.h>
    #include <configs/$1.h>
    #include <asm/config.h>
    EOF
    
    exit 0

    (4)总结"make mini2440_config"的执行结果

    ① 创建到目标板相关文件的链接

    ln -s asm-arm asm
    ln -s arch-s3c24x0 asm-arm/arch
    ln -s proc-armv asm-arm/proc

    ② 创建include/config.mk文件

    ARCH   = arm
    CPU    = arm920t
    BOARD  = mini2440
    VENDOR = samsung
    SOC    = s3c24x0

    ③ 创建与目标板相关的头文件include/config.h

    #define CONFIG_BOARDDIR board/samsung/mini2440
    #include <config_defaults.h>
    #include <configs/mini2440.h>
    #include <asm/config.h>

    3. make命令执行过程

    (1)include/autoconf.mk生成过程

    主Makefile开始部分,会包含如下头文件

    sinclude $(obj)include/autoconf.mk.dep
    sinclude $(obj)include/autoconf.mk

    include/autoconf.mk文件是与开发板相关的一些宏定义,在Makefile执行过程中,需要根据某些宏来确定执行哪些操作

    include/autoconf.mk的生成规则

    $(obj)include/autoconf.mk: $(obj)include/config.h
        @$(XECHO) Generating $@ ;
        set -e ;
        : Extract the config macros ;
        $(CPP) $(CFLAGS) -DDO_DEPS_ONLY -dM include/common.h |
            sed -n -f tools/scripts/define2mk.sed > $@.tmp &&
        mv $@.tmp $@

      * 根据上面的规则,编译器提取额include/common.h中定义的宏,然后输出给tools/scripts/define2mk.sed脚本处理,处理的结果是生成include/autoconf.mk文件

      * include/common.h中包含include/config,h文件,而include/config.h文件包含configs/mini2440、asm/config.h等文件

    (2)config.mk执行过程:

    主Makefile中接着将由make mini2440_config生成的config.mk文件包含进来

    # load ARCH, BOARD, and CPU configuration
    include $(obj)include/config.mk
    export    ARCH CPU BOARD VENDOR SOC

    ① 设置obj与src

    ifneq ($(OBJTREE),$(SRCTREE))
    ifeq ($(CURDIR),$(SRCTREE))
    dir :=
    else
    dir := $(subst $(SRCTREE)/,,$(CURDIR))
    endif
    
    obj := $(if $(dir),$(OBJTREE)/$(dir)/,$(OBJTREE)/)
    src := $(if $(dir),$(SRCTREE)/$(dir)/,$(SRCTREE)/)
    
    $(shell mkdir -p $(obj))
    else
    obj :=
    src :=
    endif

    ② 设置编译选项:下面3个变量表示交叉编译选项

    PLATFORM_RELFLAGS =
    PLATFORM_CPPFLAGS =
    PLATFORM_LDFLAGS =

      * 变量CC和CFLAGS将会在后面的代码中定义。

      * 函数cc-option用于检查编译器CC是否支持某选项,定义如下

    cc-option = $(shell if $(CC) $(CFLAGS) $(1) -S -o /dev/null -xc /dev/null 
            > /dev/null 2>&1; then echo "$(1)"; else echo "$(2)"; fi ;)

      * 函数cc-option使用示例

    FLAGS += $(call cc-option, option1, option2)

    ③ 指定交叉编译工具

    AS    = $(CROSS_COMPILE)as
    LD    = $(CROSS_COMPILE)ld
    CC    = $(CROSS_COMPILE)gcc
    CPP    = $(CC) -E
    AR    = $(CROSS_COMPILE)ar
    NM    = $(CROSS_COMPILE)nm
    LDR    = $(CROSS_COMPILE)ldr
    STRIP    = $(CROSS_COMPILE)strip
    OBJCOPY = $(CROSS_COMPILE)objcopy
    OBJDUMP = $(CROSS_COMPILE)objdump
    RANLIB    = $(CROSS_COMPILE)RANLIB

      * 对于arm开发板,CROSS_COMPILE定义于lib_arm/config.mk文件中

    CROSS_COMPILE ?= arm-linux-

    ④ 包含与开发板相关的配置文件

      * 包含文件lib_arm/config.mk:该文件中指定了交叉编译前缀,添加了一些与CPU架构相关的编译选项,最后还指定了UBoot的连接器脚本cpu/arm920t/u-boot.lds

    ifdef    ARCH
    sinclude $(TOPDIR)/lib_$(ARCH)/config.mk    # include architecture dependend rules
    endif

      * 包含文件cpu/arm920t/config.mk

      * 包含文件cpu/arm920t/s3c24x0/config.mk

      * 包含文件board/samsung/mini2440/config.mk:TEXT_BASE定义于此文件中

    ⑤ 指定隐含的编译规则:

    # Allow boards to use custom optimize flags on a per dir/file basis
    BCURDIR := $(notdir $(CURDIR))
    $(obj)%.s:    %.S
        $(CPP) $(AFLAGS) $(AFLAGS_$(@F)) $(AFLAGS_$(BCURDIR)) -o $@ $<
    $(obj)%.o:    %.S
        $(CC)  $(AFLAGS) $(AFLAGS_$(@F)) $(AFLAGS_$(BCURDIR)) -o $@ $< -c
    $(obj)%.o:    %.c
        $(CC)  $(CFLAGS) $(CFLAGS_$(@F)) $(CFLAGS_$(BCURDIR)) -o $@ $< -c
    $(obj)%.i:    %.c
        $(CPP) $(CFLAGS) $(CFLAGS_$(@F)) $(CFLAGS_$(BCURDIR)) -o $@ $< -c
    $(obj)%.s:    %.c
        $(CC)  $(CFLAGS) $(CFLAGS_$(@F)) $(CFLAGS_$(BCURDIR)) -o $@ $< -c -S

    4. UBoot镜像生成过程

    (1)顶层Makefile定义了LIBS变量,用以指明UBoot需要的库文件

    LIBS  = lib_generic/libgeneric.a
    LIBS += lib_generic/lzma/liblzma.a
    LIBS += lib_generic/lzo/liblzo.a

    (2)下面的代码定义了Makefile第一个目标all的依赖

    # Always append ALL so that arch config.mk's can add custom ones
    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 $< $@

    (3)uboot文件的生成规则

    $(obj)u-boot:    depend $(SUBDIRS) $(OBJS) $(LIBBOARD) $(LIBS) $(LDSCRIPT) $(obj)u-boot.lds
            $(GEN_UBOOT)
    ifeq ($(CONFIG_KALLSYMS),y)
            smap=`$(call SYSTEM_MAP,u-boot) | 
                awk '$$2 ~ /[tTwW]/ {printf $$1 $$3 "\\000"}'` ; 
            $(CC) $(CFLAGS) -DSYSTEM_MAP=""$${smap}"" 
                -c common/system_map.c -o $(obj)common/system_map.o
            $(GEN_UBOOT) $(obj)common/system_map.o
    endif

    ① depend 依赖:

    ② (SUBDIRS)依赖:

    ③ (OBJS)依赖

    ④ (LIBBOARD)依赖

    ⑤ (LIBS)依赖

    ⑥ (LDSCRIPT)依赖

    ⑦ (obj)u-boot.lds依赖

     (4)编译生成u-boot镜像的命令GEN_UBOOT

    GEN_UBOOT = 
            UNDEF_SYM=`$(OBJDUMP) -x $(LIBBOARD) $(LIBS) | 
            sed  -n -e 's/.*($(SYM_PREFIX)__u_boot_cmd_.*)/-u1/p'|sort|uniq`;
            cd $(LNDIR) && $(LD) $(LDFLAGS) $$UNDEF_SYM $(__OBJS) 
                --start-group $(__LIBS) --end-group $(PLATFORM_LIBS) 
                -Map u-boot.map -o u-boot

    ① 第一部分:

    UNDEF_SYM=`arm-linux-objdump -x board/samsung/mini2440/libmini2449.a... | 
    sed  -n -e 's/.*(__u_boot_cmd_.*)/-u1/p'|sort|uniq`;

    替换相应变量后

    UNDEF_SYM=`$(OBJDUMP) -x $(LIBBOARD) $(LIBS) | 
            sed  -n -e 's/.*($(SYM_PREFIX)__u_boot_cmd_.*)/-u1/p'|sort|uniq`;

    将编译u-boot所生成的库中包含__u_boot_cmd_的所有标号,替换为-u__u_boot_cmd_形式的标号,排序(sort),并保证唯一(uniq),然后将所有这样的标号组成的字符串赋值给UNDEF_SYM

    ②第二部分:

    cd $(LNDIR) && $(LD) $(LDFLAGS) $$UNDEF_SYM $(__OBJS) 
                --start-group $(__LIBS) --end-group $(PLATFORM_LIBS) 
                -Map u-boot.map -o u-boot

    替换相应变量后

    cd $(OBJTREE) && arm-linux-ld -Bstatic -T u-boot.lds -Ttext 0x33F80000  $UNDEF_SYM 
      cpu/arm920t/start.o --start-group lib_generic/libgeneric.a ... board/samsung/
      mini2440/libmini2440.a --end-group ... -Map u-boot.map -o u-boot

    (5)从ELF文件u-boot中提取二进制文件u-boot.bin

    $(obj)u-boot.bin:    $(obj)u-boot
            $(OBJCOPY) ${OBJCFLAGS} -O binary $< $@

    替换变量后

    $(obj)u-boot.bin:    $(obj)u-boot
            arm-linux-objcopy --gap-fill=0xff -O binary u-boot uboot.bin

    后记:以上分析基于uboot2010.03版本,后续版本中的Makefile组织可能会略有不同

  • 相关阅读:
    超详细mysql left join,right join,inner join用法分析
    sql FOR XML PATH
    sql server 使用for xml path 将1列多行转换为字符串连接起来,俗称 sql 合并字符
    菜鸟疑问之新建网站与新建web应用程序区别
    asp.net常用函数表
    屌丝逆袭--Asp.net快速入门学习教程 第1晚
    MongoDB学习记录(一)
    Git的SSH-key生成、导入及使用
    atom编辑器使用“apm install”无法响应的解决方案
    Knockout.js组件系统的详解之(一)
  • 原文地址:https://www.cnblogs.com/wulei0630/p/10635666.html
Copyright © 2011-2022 走看看