学习笔记--- U-BOOT 的配置与编译分析

首先进入uboot  根目录,首先配置,然后才能进行编译。

所以先执行make smdk2410_config进行配置:

在makefile里面可以找到这条指令对应执行的内容为:

smdk2410_config	:	unconfig
	@$(MKCONFIG) $(@:_config=) arm arm920t smdk2410 NULL s3c24x0

这个分为7个部分,第一个部分是执行的shell脚本文件, 其他的都是需要传入这个脚本文件的参数。
那么执行的脚本文件是什么?在makefile里面查看MKCONFIG变量:

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

MKCONFIG	:= $(SRCTREE)/mkconfig
这个变量就是根目录里面的mkconfig脚本文件。

然后这个脚本文件的第一个参数是

$(@:_config=)

表示过滤smdk2410_config的_config部分,所以参数为 smdk2410

所以执行make smdk2410_config实际上就是执行了下面的这条指令:

mkconfig smdk2410 arm arm920t smdk2410 NULL s3c24x0

后面的参数在脚本文件里面的表示方法是:

mkconfig smdk2410 arm arm920t smdk2410 NULL s3c24x0

   $0             $1         $2    $3         $4          $5       $6

也就是说$1-$6分别表示第一个到第六个参数

再来看下mkconfig这个脚本文件:

#!/bin/sh -e

# 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>
#

APPEND=no	# Default: Create new config file
BOARD_NAME=""	# Name to print in make output

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}" ] || BOARD_NAME="$1"

[ $# -lt 4 ] && exit 1
[ $# -gt 6 ] && exit 1

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

#
# Create link to architecture specific headers
#
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

#
# Create include file for Make
#
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

#
# 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
echo "/* Automatically generated - do not edit */" >>config.h
echo "#include <configs/$1.h>" >>config.h

exit 0

14行while循环,这一句判断 $1 ,case 条件是判断$1 是不是-a -n ,所以都不符合,循环无效,往下走;

23行[ "${BOARD_NAME}" ] || BOARD_NAME="$1"  表示如果BOARD_NAME有值那么就是本身,如果不是就执行BOARD_NAME="$1" ,也就表示BOARD_NAME=“smdk2410”;

25行:

[ $# -lt 4 ] && exit 1
[ $# -gt 6 ] && exit 1

其中$# 表示参数个数,这里表示如果参数个数小于4个退出,大于6个也退出。这里我们是6个参数,不会退出,继续执行;

然后在终端打印一行这个信息:

echo "Configuring for ${BOARD_NAME} board..." 实际上是 "Configuring for smdk2410 board..."

33行if [ "$SRCTREE" != "$OBJTREE" ] ; then   这一行条件不满足,两个变量的值在makefile前面就定义了。这里执行到46行:

cd ./include            
rm -f asm
ln -s asm-$2 asm

        rm -f asm-$2/arch

进入include目录,删除之前建立的旧asm,再建立一个新的链接文件asm,链接到asm-$2 也就是asm-arm,然后删除asm-arm里面的arch;

53行如果$6为空或者=NULL的话就执行ln -s ${LNPREFIX}arch-$3 asm-$2/arch,这里显然条件不满足,所以执行ln -s ${LNPREFIX}arch-$6 asm-$2/arch创建一个新的arch文件,LNPREFIX未定义,所以为空,所以这句话相当于执行:ln -s arch-s3c24x0 asm-arm/arch 创建的arch链接到arch-s3c24x0文件夹;

59行if [ "$2" = "arm" ] ; 成立,执行:

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

删除asm-arm/proc链接文件,创建新的proc文件链接到proc-armv文件夹;

上面创建了三个链接文件,创建的目的就是为了统一头文件在源代码里面的名称都为同一个名称,和具体平台和架构的名称无关,这样代码里面类似#include "arch-s3c24x0/memory" 这样的语句就可以用 #include "arch/memory" 来表示了。变换平台就不需要修改代码了。

67-69行:

echo "ARCH   = $2" >  config.mk        #>表示创建文件
echo "CPU    = $3" >> config.mk         #>>表示往文件里面写数据
echo "BOARD  = $4" >> config.mk

创建一个config.mk文件,并写入信息:

ARCH=arm  

CPU=arm920t  

BOARD=smdk2410  

71行

[ "$5" ] && [ "$5" != "NULL" ] && echo "VENDOR = $5" >> config.mk     #如果5参数存在而且不等于NULL 那么写入VENDOR = $5 到config.mk
[ "$6" ] && [ "$6" != "NULL" ] && echo "SOC    = $6" >> config.mk       #如果6参数存在而且不等于NULL 那么写入SOC   = $6 到config.mk

所以SOC   = s3c24x0 也写入config.mk  ;

78行if [ "$APPEND" = "yes" ]   APPEND 变量在第11行定义为no,所以条件不成立,执行> config.h 创建config.h 文件;

最后将"/* Automatically generated - do not edit */" 与"#include <configs/$1.h>" 写入config.h文件,也就是"#include <configs/smdk2410.h>" 。

最后退出。

所以通过解读shell脚本,实际上运行的脚本如下:

APPEND=no	# Default: Create new config file
BOARD_NAME=""	# Name to print in make output

BOARD_NAME="smdk2410"
echo "Configuring for smdk2410 board..."

cd ./include
rm -f asm
ln -s asm-arm asm

rm -f asm-arm/arch
ln -s arch-s3c24x0 asm-arm/arch

rm -f asm-arm/proc
ln -s proc-armv asm-$2/proc

echo "ARCH   = arm" >  config.mk
echo "CPU    = arm920t" >> config.mk
echo "BOARD  = smdk2410" >> config.mk
echo "SOC    = s3c24x0" >> config.mk

> config.h		# Create new config file
echo "/* Automatically generated - do not edit */" >>config.h
echo "#include <configs/smdk2410.h>" >>config.h

exit 0
这就是配置过程做的事情,再来看下makefile编译部分:

编译uboot直接用make命令进行编译;

在输入make的时候,实际上就是执行make all 

我们在makefile里面找到这个入口点:239行,前面都是些变量赋值等操作,这里是真正要执行的编译工作。

#########################################################################
#########################################################################

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

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

$(OBJS):
		$(MAKE) -C cpu/$(CPU) $(if $(REMOTE_BUILD),$@,$(notdir $@))

$(LIBS):
		$(MAKE) -C $(dir $(subst $(obj),,$@))

$(SUBDIRS):
		$(MAKE) -C $@ all

$(NAND_SPL):	version
		$(MAKE) -C nand_spl/board/$(BOARDDIR) all

$(U_BOOT_NAND):	$(NAND_SPL) $(obj)u-boot.bin
		cat $(obj)nand_spl/u-boot-spl-16k.bin $(obj)u-boot.bin > $(obj)u-boot-nand.bin

version:
		@echo -n "#define U_BOOT_VERSION \"U-Boot " > $(VERSION_FILE); \
		echo -n "$(U_BOOT_VERSION)" >> $(VERSION_FILE); \
		echo -n $(shell $(CONFIG_SHELL) $(TOPDIR)/tools/setlocalversion \
			 $(TOPDIR)) >> $(VERSION_FILE); \
		echo "\"" >> $(VERSION_FILE)

gdbtools:
		$(MAKE) -C tools/gdb all || exit 1

updater:
		$(MAKE) -C tools/updater all || exit 1

env:
		$(MAKE) -C tools/env all || exit 1

depend dep:
		for dir in $(SUBDIRS) ; do $(MAKE) -C $$dir _depend ; done

tags ctags:
		ctags -w -o $(OBJTREE)/ctags `find $(SUBDIRS) include \
				lib_generic board/$(BOARDDIR) cpu/$(CPU) lib_$(ARCH) \
				fs/cramfs fs/fat fs/fdos fs/jffs2 \
				net disk rtc dtt drivers drivers/sk98lin common \
			\( -name CVS -prune \) -o \( -name '*.[ch]' -print \)`

etags:
		etags -a -o $(OBJTREE)/etags `find $(SUBDIRS) include \
				lib_generic board/$(BOARDDIR) cpu/$(CPU) lib_$(ARCH) \
				fs/cramfs fs/fat fs/fdos fs/jffs2 \
				net disk rtc dtt drivers drivers/sk98lin common \
			\( -name CVS -prune \) -o \( -name '*.[ch]' -print \)`

$(obj)System.map:	$(obj)u-boot
		@$(NM) $< | \
		grep -v '\(compiled\)\|\(\.o$$\)\|\( [aUw] \)\|\(\.\.ng$$\)\|\(LASH[RL]DI\)' | \
		sort > $(obj)System.map
从代码可以为了产生最后我们想要的文件,有很多依赖关系,太复杂了,没时间分析了。只能通过在开发板上make一下uboot才能知道哦具体干了些什么事情;具体就不详述了,总之最后我们知道的信息有几点:

1 uboot代码的入口在哪里  ----  cpu/$(CPU)/start.S

2 uboot代码放在SDRAM的哪个地址开始运行  ---- 在链接的时候通过board/$(BOARD)/config.mk里面设置TEXT_BASE指定的,

   TEXT_BASE 表示board/$(BOARD)/u-boot.lds链接脚本里面的text段运行的地址,而cpu/$(CPU)/start.o放在text段的最开始,所以从TEXT_BASE开始运行。





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值