(二) u-boot 配置、编译过程分析
2017-07-28 18:50
441 查看
由于u-boot比较庞大,所以我们分开来分析,对于一个大型的项目我们想快速的了解其代码架构和内容,最方便的方法就是分析Makefile,所以我用uboot-1.1.6来分析Makefile。通过对u-boot的分析想要得到以下内容:
1. U-boot的入口
2. 链接地址
由顶层Readme文件说明,可以知道如果要使用开发板board/,就先执行
U-Boot.bin: 二进制可执行文件,它就是直接烧入NandFlash、NORFlash的文件
U-Boot:ELF格式的可执行文件
U-Boot.srec:Motorola S-Record格式的可执行文件
② 配置执行
@代表的是目标100ask24x0_config, 那么$(@:_config=)就是将100ask24x0_config中的_config替换为空,得到100ask24x0
从上面我们可以知道,如果要在board目录下新建一个开发板的目录,则在include/configs目录下也要建立一个文件
U-boot还没有类似Linux一样的可视化配置界面(比如使用make menuconfig来配置),要手动修改配置文件
而u-boot.srec u-boot.bin又依赖于u-boot
② 通过展开编译命令(当然有点麻烦)我们可以直接执行
打开u-boot-1.1.6/board/100ask24x0/u-boot.lds
③ 在连接脚本中,最先连接运行的是
链接地址:board/100ask24x0/config.mk -> 0x33F80000
1. U-boot的入口
2. 链接地址
由顶层Readme文件说明,可以知道如果要使用开发板board/,就先执行make <boadr_name>_config
命令进行配置,然后执行make all
,就可以生成如下3个文件
U-Boot.bin: 二进制可执行文件,它就是直接烧入NandFlash、NORFlash的文件U-Boot:ELF格式的可执行文件
U-Boot.srec:Motorola S-Record格式的可执行文件
一、U-boot配置过程分析
① 先从Makefile文件中分析一下配置过程
搜索100ask24x0_config
② 配置执行make 100ask24x0_config
的时候,就相当执行这条命令:
@$(MKCONFIG) $(@:_config=) arm arm920t 100ask24x0 NULL s3c24x0
③ 我们先在Makefile文件中搜索一下 MKCONFIG看一下是什么东西?
OBJTREE := $(if $(BUILD_DIR),$(BUILD_DIR),$(CURDIR)) SRCTREE := $(CURDIR) TOPDIR := $(SRCTREE) LNDIR := $(OBJTREE) export TOPDIR SRCTREE OBJTREE MKCONFIG := $(SRCTREE)/mkconfig export MKCONFIG
④ 从上可以看出,在源文件的目录下面有一个mkconfig文件;
我们执行配置命令的时候,就相当执行这条脚本命令:
mkconfig 100ask24x0 arm arm920t 100ask24x0 NULL s3c24x0
@代表的是目标100ask24x0_config, 那么$(@:_config=)就是将100ask24x0_config中的_config替换为空,得到100ask24x0
⑤ 接着需要打开mkconfig文件分析。mkconfig文件代码如下:
#!/bin/sh -e ## 上面这句指定执行该脚本所使用的解释器, -e相当于使用/bin/bash # Script to create header files and links to configure # U-Boot for a specific board. # # Parameters: Target Architecture CPU Board [VENDOR] [SOC] # # (C) 2002-2006 DENX Software Engineering, Wolfgang Denk <wd@denx.de> # # mkconfig 100ask24x0 arm arm920t 100ask24x0 NULL s3c24x0 # $0 $1 $2 $3 $4 $5 $6 APPEND=no # Default: Create new config file BOARD_NAME="" # Name to print in make output #分析传入的参数里面有没有 "--",“-a”等 while [ $# -gt 0 ] ; do case "$1" in --) shift ; break ;; -a) shift ; APPEND=yes ;; -n) shift ; BOARD_NAME="${1%%_config}" ; shift ;; *) break ;; esac done #判断BOARD_NAME有没有定义,如果没有则为:$1,其中$1为传入的第一个参数,依次类推 [ "${BOARD_NAME}" ] || BOARD_NAME="$1" #判断参数的个数,不合条件就退出 [ $# -lt 4 ] && exit 1 [ $# -gt 6 ] && exit 1 #打印这一句话 echo "Configuring for ${BOARD_NAME} board..." # # Create link to architecture specific headers # #判断源代码目录和目标文件目录是否一致 #如果这两个不相等,可以看一下makefile文件,这两个是从makefile里面来的 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 #建立一个asm的链接文件,它指向asm-;配置的时候临时生成指向某一个架构,如果为i386架构,则为asm-i386 ln -s asm-$2 asm #ln -s asm-arm asm fi rm -f asm-$2/arch # rm -f asm-arm/arch #如果第六个参数为NULL或者为空 LNPREFIX没有被定义 if [ -z "$6" -o "$6" = "NULL" ] ; then ln -s ${LNPREFIX}arch-$3 asm-$2/arch else #我们这里执行这个分支 #建立一个链接文件,指向${LNPREFIX}arch-$6,其中$6为传进来的参数 ln -s ${LNPREFIX}arch-$6 asm-$2/arch # ln -s arch-s3c24x0 asm-arm/arch fi if [ "$2" = "arm" ] ; then rm -f asm-$2/proc ln -s ${LNPREFIX}proc-armv asm-$2/proc # ln -s proc-armv asm-arm/proc fi # # Create include file for Make # #新建一个config.mk文件,> 表示新建 # >新建 >>追加 echo "ARCH = $2" > config.mk #在config.mk追加, >> 表示追加 echo "CPU = $3" >> config.mk echo "BOARD = $4" >> config.mk #判断第5个参数,追加 VENDOR = xx [ "$5" ] && [ "$5" != "NULL" ] && echo "VENDOR = $5" >> config.mk #判断第6个参数,追加 SOC = xx [ "$6" ] && [ "$6" != "NULL" ] && echo "SOC = $6" >> config.mk # # Create board specific header file # if [ "$APPEND" = "yes" ] # Append to existing config file then echo >> config.h else > config.h # Create new config file fi #把以下内容追加到config.h文件中去 echo "/* Automatically generated - do not edit */" >>config.h echo "#include <configs/$1.h>" >>config.h #其中 #include <configs/$1.h> 就是生成的配置文件 exit 0
⑥ 总结一下:在我们的配置过程中我们主要有一下工作:
# mkconfig 100ask24x0 arm arm920t 100ask24x0 NULL s3c24x0 # $0 $1 $2 $3 $4 $5 $6
1. 开发板名称BOARD_NAME = $1 = 100ask24x0 2. 创建于开发板相关的头文件的链接,如下:
ln -s asm-arm($2) asm ln -s arch-s3c24x0($6) asm-arm($2)/arch ln -s proc-armv asm-arm($2)/proc # 如果$2不是arm的话,此行没有
3. 创建顶层Makefile包含的文件include/config.mk,如下所示:
ARCH = $2 = arm CPU = $3 = arm920t BOARD = $4 = 100ask24x0 VENDOR = $5 = NULL # $5为空,或者是NULL的话,此行没有 SOC = $6 = s3c24x0 # $6为空,或者是NULL的话,此行没有
4. 创建开发板相关头文件include/config.h
/* Automatically generated - do not edit */ #include <configs/100ask24x0($1).h>
从上面我们可以知道,如果要在board目录下新建一个开发板的目录,则在include/configs目录下也要建立一个文件<board_name.h>
,里面存放的就是<board_name>
的配置信息。
U-boot还没有类似Linux一样的可视化配置界面(比如使用make menuconfig来配置),要手动修改配置文件include/configs/<board_name>.h
来裁减、设置 U-Boot。
二、U-boot编译过程分析
① 接着分析一下编译过程,在makefile文件里面,有如下代码:
include $(OBJTREE)/include/config.mk
这里的config.mk就是上面配置生成的配置文件,这就将配置与编译结合起来了;
注:在我们执行make的时候其将会生成第一个目标也就是all,以all为突破口我们找到all.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 $< $@
而u-boot.srec u-boot.bin又依赖于u-boot
$(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
② 通过展开编译命令(当然有点麻烦)我们可以直接执行make
/ make all
然后找到和这条命令相似的命令,通过得到的命令我们可以顺利的找到其在编译过程中所用到的链接器脚本
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 \
打开u-boot-1.1.6/board/100ask24x0/u-boot.lds
/* * (C) Copyright 2002 * Gary Jennejohn, DENX Software Engineering, <gj@denx.de> * * See file CREDITS for list of people who contributed to this * project. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA */ OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") /*OUTPUT_FORMAT("elf32-arm", "elf32-arm", "elf32-arm")*/ OUTPUT_ARCH(arm) ENTRY(_start)//入口地址_start SECTIONS { . = 0x00000000; . = ALIGN(4); .text : //代码段排布 { cpu/arm920t/start.o (.text) //先是该代码,最先连接运行 board/100ask24x0/boot_init.o (.text) *(.text) } . = ALIGN(4); .rodata : { *(.rodata) } . = ALIGN(4); .data : { *(.data) } . = ALIGN(4); .got : { *(.got) } . = .; __u_boot_cmd_start = .; .u_boot_cmd : { *(.u_boot_cmd) } __u_boot_cmd_end = .; . = ALIGN(4); __bss_start = .; .bss : { *(.bss) } _end = .; }
③ 在连接脚本中,最先连接运行的是cpu/arm920t/start.o
,在cpu/arm920t/start.S我们可以轻松找到其所有代码的入口
.globl _start _start: b reset ldr pc, _undefined_instruction ldr pc, _software_interrupt ldr pc, _prefetch_abort ldr pc, _data_abort ldr pc, _not_used ldr pc, _irq ldr pc, _fiq _undefined_instruction: .word undefined_instruction _software_interrupt: .word software_interrupt _prefetch_abort: .word prefetch_abort _data_abort: .word data_abort _not_used: .word not_used _irq: .word irq _fiq: .word fiq .balignl 16,0xdeadbeef ...................
④ 至此我们找到了正个程序的入口,但是其的链接地址又在什么地方呢?
- Ⅰ .我们先来搜索一下上面的连接地址0x33F80000
board/100ask24x0/config.mk:25:TEXT_BASE = 0x33F80000
- Ⅱ.我们进入board/100ask24x0/config.mk一探究竟
TEXT_BASE = 0x33F80000
- Ⅲ.我们主Makefile中怎样连接到这里的呢,目标u-boot有一个配置符号,很熟悉:
我们再来回顾一遍,通过make后逆向的过程验证一下:
⑤ 我们来小结一下U-boot编译中获得的东西:
第一个文件:cpu/arm920t/start.S链接地址:board/100ask24x0/config.mk -> 0x33F80000
三、总结:
相关文章推荐
- u-boot2013.01 sdmk2410 配置和编译过程分析
- u-boot-1.1.6的配置编译过程分析.doc
- u-boot-2012.04.01的配置编译过程分析.doc
- 初学u-boot之源码配置编译过程分析
- U-Boot--配置过程分析
- U-Boot编译过程分析
- u-boot编译链接过程分析(ARM)
- uboot1.1.6配置、编译、链接分析
- U-Boot编译过程完全分析2-include/autoconf.mk和make all
- u-boot编译过程分析
- U-Boot编译过程完全分析
- 详细分析make uboot 最后的编译链接的具体执行过程
- U-Boot 配置、编译、链接过程
- U-Boot编译过程完全分析
- u-boot-2016.09 make编译过程分析(一)
- u-boot配置和编译过程详解
- U-Boot编译过程完全分析
- u-boot 2014-10 Makefile 配置过程分析
- U-Boot编译过程完全分析