您的位置:首页 > 其它

uboot编译过程

2014-12-17 21:09 253 查看
本文基于u-boot-1.3.4,开发板fs2410,交叉编译工具路径/usr/local/arm/crosstool/gcc-3.4.5-glibc-2.3.6/arm-linux-gnu/bin

make fs2410_config

make all

简单的两条命令就可以编译完成。下面开始分析其详细过程,curdir为u-boot顶层目录

/////////////////

执行make fs2410_config的时候,顶层Makefile中有相对应的一个目标叫fs2410_config,所以会执行该目标的命令行:

@$(MKCONFIG) $(@:_config=) arm arm920t fs2410 NULL s3c24x0

MKCONFIG := $(SRCTREE)/mkconfig 顶层目录下的mkconfig shell脚本

$(@:_config=)就是将fs2410_config中的_config去掉变成fs2410

所以,实际上该命令就变成了:

./mkconfig fs2410 arm arm920t fs2410 NULL s3c24x0

$1=fs2410 $2=arm $3=arm920t $4=fs2410 $5=NULL $6=s3c24x0

********************./mkconfig文件分析******************************

从该文件的文件头中的英文说明可以看出,给该文件传递的参数的意义是什么?分别是

Target Architecture CPU Board [VENDOR] [SOC]

fs2410 arm arm920t fs2410 NULL s3c24x0

while [ $# -gt 0 ] ; do

case "$1" in

--) shift ; break ;;

-a) shift ; APPEND=yes ;;

-n) shift ; BOARD_NAME="${1%%_config}" ; shift ;;

*) break ;;

esac

done

$#为shell中的一个特殊变量,代表传入参数的个数,-gt是大于的意思,该行的意思是“当传入参数个数大于0时”进入循环

case "$1" in接着下面的几行意思表示,判断第一个参数中是否有-- -a -n参数,我们传入的参数都没有这些,所以他们根本没机会执行到

[ "${BOARD_NAME}" ] || BOARD_NAME="$1"

有或的意思,如果||前的[]中不为NULL,那么||后面的就屏蔽了,很不幸,这里||前面部分却为NULL,所以BOARD_NAME=fs2410(第一个参数的值)

[ $# -lt 4 ] && exit 1

[ $# -gt 6 ] && exit 1

参数个数正确性判断

echo "Configuring for ${BOARD_NAME} board..."

打印 Configuring for fs2410 board...

接下来判断"$SRCTREE" != "$OBJTREE"是否成立,显然不成立(参考顶层Makefile),所以略过没必要的行,如下:

if [ "$SRCTREE" != "$OBJTREE" ] ; then

...

else

cd ./include

rm -f asm

ln -s asm-$2 asm

fi

else分支中先进入inlcude目录,然后删除上一次编译时配置生成的asm文件,最后生成链接文件asm指向asm-arm

rm -f asm-$2/arch

删除include/asm-arm/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

如果$6参数字符串长度为0或者为NULL,那么条件成立,但是实际上条件不成立,$6=s3c2410,所以生成一个链接文件asm-arm/arch--->arch-s3c24x0

if [ "$2" = "arm" ] ; then

rm -f asm-$2/proc

ln -s ${LNPREFIX}proc-armv asm-$2/proc

fi

创建链接文件asm-arm/proc--->proc-armv

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 #存在第6个参数并且不为NULL

在include目录中创建config.mk文件,内容如下:

ARCH = arm

CPU = arm920t

BOARD= fs2410

SOC = s3c24x0

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

echo "#include <configs/$1.h>" >>config.h

在include目录中创建头文件config.h,内容为:

/* Automatically generated - do not edit */

#include <configs/fs2410.h>

exit 0

总结:

1. 打印 Configuring for fs2410 board...

2. 在include目录下创建3个链接文件 Create link to architecture specific headers

./include

asm--->asm-arm

./include/asm-arm

arch--->arch-s3c24x0

proc--->proc-armv

3. 在include目录中创建config.mk文件 Create include file for Make

ARCH = arm

CPU = arm920t

BOARD= fs2410

SOC = s3c24x0

4. 创建板级特殊头文件config.h Create board specific header file

/* Automatically generated - do not edit */

#include <configs/fs2410.h>

****************************************************************************************************

///////////////////////////

执行make all,从顶层的Makefile开始

U_BOOT_VERSION = 1.3.1

VERSION_FILE = ./include/version_autogenerated.h

HOSTARCH = i386

HOSTOS = Linux

export HOSTARCH HOSTOS

VENDOR= #开发商

我们通常在编译的时候没有指定安装目录,所以BULID_DIR为NULL

export TOPDIR SRCTREE OBJTREE

MKCONFIG := $(SRCTREE)/mkconfig

export MKCONFIG



# load ARCH, BOARD, and CPU configuration

include $(OBJTREE)/include/config.mk //这里将前面mkconfig脚本生成的include/config.mk文件包含进来了

export ARCH CPU BOARD VENDOR SOC

ifeq ($(ARCH),arm)

CROSS_COMPILE = /usr/local/arm/crosstool/gcc-3.4.5-glibc-2.3.6/arm-linux-gnu/bin/arm-linux-gnu-

endif

//配置交叉编译工具链

export CROSS_COMPILE

# load other configuration

include $(TOPDIR)/config.mk //将顶层目录的config.mk包含进来,该文件中将会包含其他.mk文件

***********************顶层config.mk文件分析**************************************************

obj :=

src :=

# clean the slate ...

PLATFORM_RELFLAGS =

PLATFORM_CPPFLAGS =

PLATFORM_LDFLAGS =

PLATFORM_CPPFLAGS+= -D__ARM__

inlcude ./arm_config.mk //PLATFORM_CPPFLAGS += -DCONFIG_ARM -D__ARM__

include ./cpu/arm920t/config.mk

//PLATFORM_RELFLAGS += -fno-strict-aliasing -fno-common -ffixed-r8 -msoft-float

//PLATFORM_CPPFLAGS += -march=armv4

//PLATFORM_CPPFLAGS +=$(call cc-option,-mapcs-32,-mabi=apcs-gnu)

//PLATFORM_RELFLAGS +=$(call cc-option,-mshort-load-bytes,/

$(call cc-option,-malignment-traps,))

include ./cpu/arm920t/s3c24x0/config.mk //没有该文件

BOARDDIR = fs2410

include ./board/fs2410/config.mk //TEXT_BASE = 0x33f80000 链接地址

# Load generated board configuration

include ./include/autoconf.mk

该文件中包含了一些重要的命令行参数:

CONFIG_ETHADDR="08:00:3e:26:0a:5b"

CONFIG_IPADDR="192.168.1.134"

CONFIG_GATEWAYIP="192.168.1.1"

CONFIG_NETMASK="255.255.255.0"

CONFIG_SERVERIP="192.168.1.23"

CONFIG_BOOTARGS=""root=/dev/nfs rw nfsroot=" MK_STR(CONFIG_SERVERIP) ":" MK_STR(CONFIG_ROOTPATH) " ip=" MK_STR(CONFIG_IPADDR) ":" MK_STR(CONFIG_SERVERIP) ":" MK_STR(CONFIG_GATEWAYIP) ":" MK_STR(CONFIG_NETMASK) ":" MK_STR(CONFIG_HOSTNAME) ":" MK_STR(CONFIG_NETDEV)
":off console=" MK_STR(CONFIG_CONSOLE) "," MK_STR(CONFIG_BAUDRATE)"

CONFIG_BOOTCOMMAND="nand read 30008000 40000 1c0000 /; go 30008000"

CONFIG_LOADADDR="0x30800000"

HOSTCC = gcc

HOSTCFLAGS = -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer

HOSTSTRIP = strip

AS = $(CROSS_COMPILE)as

LD = $(CROSS_COMPILE)ld

CC = $(CROSS_COMPILE)gcc

CPP = $(CC) -E

AR = $(CROSS_COMPILE)ar

NM = $(CROSS_COMPILE)nm

STRIP = $(CROSS_COMPILE)strip

OBJCOPY = $(CROSS_COMPILE)objcopy

OBJDUMP = $(CROSS_COMPILE)objdump

RANLIB = $(CROSS_COMPILE)RANLIB

LDSCRIPT := $(TOPDIR)/board/$(BOARDDIR)/u-boot.lds // ./board/fs2410/u-boot.lds u-boot链接文件

&&&&&&&&&&&&&&&& ./board/fs2410/u-boot.lds内容

OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")

/*OUTPUT_FORMAT("elf32-arm", "elf32-arm", "elf32-arm")*/

OUTPUT_ARCH(arm)

ENTRY(_start)

SECTIONS

{

. = 0x00000000;

. = ALIGN(4);

.text :

{

cpu/arm920t/start.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 = .;

}

&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&

CPPFLAGS := $(DBGFLAGS) $(OPTFLAGS) $(RELFLAGS) -D__KERNEL__ -DTEXT_BASE=$(TEXT_BASE)

CPPFLAGS += -I$(TOPDIR)/include

CPPFLAGS += -fno-builtin -ffreestanding -nostdinc -isystem $(gccincdir) -pipe $(PLATFORM_CPPFLAGS)

CFLAGS := $(CPPFLAGS) -Wall -Wstrict-prototypes

/**********************************************

预定义的宏:

c/c++:

__KERNEL__

TEXT_BASE=0x33f80000

CONFIG_ARM

__ARM__

汇编:

__ASSEMBLY__

__KERNEL__

TEXT_BASE=0x33f80000

CONFIG_ARM

__ARM__

*********************************************/

AFLAGS := $(AFLAGS_DEBUG) -D__ASSEMBLY__ $(CPPFLAGS)

LDFLAGS += -Bstatic -T $(LDSCRIPT) -Ttext $(TEXT_BASE) $(PLATFORM_LDFLAGS) //链接选项

%%%%%%%%注意%%%%%%%%%%%%%

从很早之前用u-boot的时候我心里就有个疑惑,为什么这里使用了-T指定了链接脚本之后,又用-Ttext指定text的开始地址,今天突然想通了,原来是这样:

先来看一下三星cpu专用bootloader vivi在这里是怎么的

Makefile中有这么一句:

LINKFLAGS = -T arch/vivi.lds -Bstatic

但是在arch下没有vivi.lds,而是有vivi.lds.in,下面是.in文件的内容:

SECTIONS {

. = TEXTADDR;

.text : { *(.text) }

.data ALIGN(4) : { *(.data) }

.bss ALIGN(4) : { *(.bss) *(COMMON) }

}

很显然TEXTADDR是要被替换的,在哪里替换的呢?还是在Makefile中了:

LDSCRIPT = arch/vivi.lds.in



ifeq ($(CONFIG_ARCH_S3C2410),y)

MACHINE = s3c2410

ifeq ($(CONFIG_S3C2410_NAND_BOOT),y)

TEXTADDR = 0x33f00000

else

TEXTADDR = 0x00000000

endif

endif



vivi: $(HEAD) arch/vivi.lds

arch/vivi.lds: $(LDSCRIPT)

@sed s/TEXTADDR/$(TEXTADDR)/ $(LDSCRIPT) >$@

这个链接地址就这样被替换了,后来我想来想,这里这个vivi的做法和u-boot的做法其实本质上是一样的,怎么说,

就是为了支持多种平台不同的链接要求或者方便使用者修改而将最终的链接地址弄成来一个

变量来代替。u-boot中也是使用变量来代替,然后在命令行中用-Ttext来指定,这样在链接的时候最终的链接地址

还是取决于-Ttext,而不会使用.lds文件中规定的地址。甚至如果不考虑地址对其的话,完全可以不使用.lds文件,直接在

命令行中使用-Ttext xxxxxxx来实现链接。

下面顺便列出ld的常用需选项:

-b TARGET 设置目标文件的文件格式

-e ADDRESS 设置目标文件的开始地址

-EB 链接big-endian的目标文件

-EL 链接small-endian的目标文件

-l LIBNAME 创建执行程序时要链接的库文件(比如某个库为test,则可以为-ltest)

-L DIRECTORY 寻找要链接的库文件时搜索的文件路径

-o FILE 设置输出文件的名字

-s 去除输出文件中的所有符号信息

-S 去除输出文件中的调试符号信息

-T FILE 读取链接描述脚本,以确定符号等的定位地址

-v 输出ld的版本信息

-x 去除所有的局部符号信息

-X 去除临时的局部符号信息,默认情况下会设置这个选项

-Bstatic 创建的输出文件链接静态链接库

-Bdynamic 创建的输出文件链接动态链接库

-Tbss ADDRESS 设置section bss的起始地址

-Tdata ADDRESS 设置section data的起始地址

-Ttext ADDRESS 设置section text的起始地址

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

***********************顶层config.mk文件分析 end**************************************************

列出u-boot所需目标文件列表:顺序很重要,也就是说OBJS = cpu/$(CPU)/start.o必须放在第一个的位置

这里是cpu/arm920t/start.o文件

LIBS = lib_generic/libgeneric.a

。。。

。。。

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 $< $@

$(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.sha1: $(obj)u-boot.bin

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

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

$(OBJDUMP) -d $< > $@

$(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

实际编译的打印信息如下:

编译汇编代码时:

/usr/local/arm/crosstool/gcc-3.4.5-glibc-2.3.6/arm-linux-gnu/bin/arm-linux-gnu-gcc -D__ASSEMBLY__ -g -Os -fno-strict-aliasing -fno-common -ffixed-r8 -msoft-float -malignment-traps -D__KERNEL__ -DTEXT_BASE=0x33F80000 -I/home/lzg/sdc/u-boot-1.3.1_fs_modified/include
-fno-builtin -ffreestanding -nostdinc -isystem /usr/local/arm/crosstool/gcc-3.4.5-glibc-2.3.6/arm-linux-gnu/bin/../lib/gcc/arm-linux-gnu/3.4.5/include -pipe -DCONFIG_ARM -D__ARM__ -march=armv4 -mapcs-32 -c -o start.o start.S

__ASSEMBLY__ __KERNEL__ TEXT_BASE=0x33F80000 CONFIG_ARM __ARM__

编译c代码时

/usr/local/arm/crosstool/gcc-3.4.5-glibc-2.3.6/arm-linux-gnu/bin/arm-linux-gnu-gcc -g -Os -fno-strict-aliasing -fno-common -ffixed-r8 -msoft-float -malignment-traps -D__KERNEL__ -DTEXT_BASE=0x33F80000 -I/home/lzg/sdc/u-boot-1.3.1_fs_modified/include -fno-builtin
-ffreestanding -nostdinc -isystem /usr/local/arm/crosstool/gcc-3.4.5-glibc-2.3.6/arm-linux-gnu/bin/../lib/gcc/arm-linux-gnu/3.4.5/include -pipe -DCONFIG_ARM -D__ARM__ -march=armv4 -mapcs-32 -Wall -Wstrict-prototypes -c -o cmd_mac.o cmd_mac.c

__KERNEL__ TEXT_BASE=0x33F80000 CONFIG_ARM __ARM__

UNDEF_SYM=`/usr/local/arm/crosstool/gcc-3.4.5-glibc-2.3.6/arm-linux-gnu/bin/arm-linux-gnu-objdump -x lib_generic/libgeneric.a board/fs2410/libfs2410.a cpu/arm920t/libarm920t.a cpu/arm920t/s3c24x0/libs3c24x0.a lib_arm/libarm.a fs/cramfs/libcramfs.a fs/fat/libfat.a
fs/fdos/libfdos.a fs/jffs2/libjffs2.a fs/reiserfs/libreiserfs.a fs/ext2/libext2fs.a net/libnet.a disk/libdisk.a drivers/bios_emulator/libatibiosemu.a drivers/block/libblock.a drivers/hwmon/libhwmon.a drivers/i2c/libi2c.a drivers/input/libinput.a drivers/misc/libmisc.a
drivers/mtd/libmtd.a drivers/mtd/nand/libnand.a drivers/mtd/nand_legacy/libnand_legacy.a drivers/mtd/onenand/libonenand.a drivers/net/libnet.a drivers/net/sk98lin/libsk98lin.a drivers/pci/libpci.a drivers/pcmcia/libpcmcia.a drivers/rtc/librtc.a drivers/serial/libserial.a
drivers/usb/libusb.a drivers/video/libvideo.a post/libpost.a post/drivers/libpostdrivers.a common/libcommon.a libfdt/libfdt.a |sed -n -e 's/.*/(__u_boot_cmd_.*/)/-u/1/p'|sort|uniq`;/

cd /home/lzg/sdc/u-boot-1.3.1_fs_modified && /usr/local/arm/crosstool/gcc-3.4.5-glibc-2.3.6/arm-linux-gnu/bin/arm-linux-gnu-ld -Bstatic -T /home/lzg/sdc/u-boot-1.3.1_fs_modified/board/fs2410/u-boot.lds -Ttext 0x33F80000 $UNDEF_SYM cpu/arm920t/start.o /

--start-group lib_generic/libgeneric.a board/fs2410/libfs2410.a cpu/arm920t/libarm920t.a cpu/arm920t/s3c24x0/libs3c24x0.a lib_arm/libarm.a fs/cramfs/libcramfs.a fs/fat/libfat.a fs/fdos/libfdos.a fs/jffs2/libjffs2.a fs/reiserfs/libreiserfs.a fs/ext2/libext2fs.a
net/libnet.a disk/libdisk.a drivers/bios_emulator/libatibiosemu.a drivers/block/libblock.a drivers/hwmon/libhwmon.a drivers/i2c/libi2c.a drivers/input/libinput.a drivers/misc/libmisc.a drivers/mtd/libmtd.a drivers/mtd/nand/libnand.a drivers/mtd/nand_legacy/libnand_legacy.a
drivers/mtd/onenand/libonenand.a drivers/net/libnet.a drivers/net/sk98lin/libsk98lin.a drivers/pci/libpci.a drivers/pcmcia/libpcmcia.a drivers/rtc/librtc.a drivers/serial/libserial.a drivers/usb/libusb.a drivers/video/libvideo.a post/libpost.a post/drivers/libpostdrivers.a
common/libcommon.a libfdt/libfdt.a --end-group -L /usr/local/arm/crosstool/gcc-3.4.5-glibc-2.3.6/arm-linux-gnu/bin/../lib/gcc/arm-linux-gnu/3.4.5 -lgcc /

-Map u-boot.map -o u-boot

链接成u-boot elf32

/usr/local/arm/crosstool/gcc-3.4.5-glibc-2.3.6/arm-linux-gnu/bin/arm-linux-gnu-objcopy --gap-fill=0xff -O srec u-boot u-boot.srec

/usr/local/arm/crosstool/gcc-3.4.5-glibc-2.3.6/arm-linux-gnu/bin/arm-linux-gnu-objcopy --gap-fill=0xff -O binary u-boot u-boot.bin

生成.bin文件和.srec文件
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: