u-boot分析与使用

u-boot分析之编译体验

初识uboot

uboot是BootLoader的一种,用以启动内核。

uboot打补丁、配置与编译

uboot官方是有提供源程序的,我们在上面进行修改或者添加代码的话需要打补丁,步骤如下:
1 解压缩uboot

tar xjf u-boot-1.1.6.tar.bz2

2 进入解压后的文件夹

cd u-boot-1.1.6/

3 打补丁

patch -p1 <…/u-boot-1.1.6_jz2440.patch

4 配置

make 100ask24x0_config

5.编译

make

diff -urN u-boot-1.1.6/board/100ask24x0/100ask24x0.c u-boot-1.1.6_jz2440/board/100ask24x0/100ask24x0.c
--- u-boot-1.1.6/board/100ask24x0/100ask24x0.c	1970-01-01 07:00:00.000000000 +0700
+++ u-boot-1.1.6_jz2440/board/100ask24x0/100ask24x0.c	2010-11-26 12:54:37.034090906 +0800

—代表要打的位置,我们当前已经在u-boot-1.1.6文件夹下了,所以需要忽略第一个参数,用参数-p?进行忽略。
如:-p1表示忽略第一个“/”前的参数。

.patch文件的讲解

“-”表示修改前的代码,“+”表示修改后的代码,如下列代码所示。

diff -urN u-boot-1.1.6/common/cmd_load.c u-boot-1.1.6_jz2440/common/cmd_load.c
--- u-boot-1.1.6/common/cmd_load.c	2006-11-02 22:15:01.000000000 +0800
+++ u-boot-1.1.6_jz2440/common/cmd_load.c	2010-11-26 12:54:38.142063808 +0800
@@ -34,6 +34,8 @@
 DECLARE_GLOBAL_DATA_PTR;
 
 #if (CONFIG_COMMANDS & CFG_CMD_LOADB)
+/* support xmodem, www.100ask.net */
+static ulong load_serial_xmodem (ulong offset);
 static ulong load_serial_ymodem (ulong offset);
 #endif
 

其中

@@ -34,6 +34,8 @@

表示修改前的代码中的34行,总共6行,修改后的代码中的34行,总共8行。

另外一个例子,下列代码中,-代表原本的代码,+代表之后的修改的代码。

 int do_load_serial (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
 {
-	ulong offset = 0;
-	ulong addr;
-	int i;
-	char *env_echo;
-	int rcode = 0;
-#ifdef	CFG_LOADS_BAUD_CHANGE
-	int load_baudrate, current_baudrate;
+    ulong offset = 0;
+    ulong addr;
+    int i;
+    char *env_echo;
+    int rcode = 0;
+#ifdef  CFG_LOADS_BAUD_CHANGE
+    int load_baudrate, current_baudrate;
 
-	load_baudrate = current_baudrate = gd->baudrate;
+    load_baudrate = current_baudrate = gd->baudrate;
 #endif

u-boot分析之Makefile结构分析

分为两部分讲解:配置分析、编译分析

make 100ask24x0_config配置分析

在uboot的Makefile文件中可以看到有这么一条语句:

100ask24x0_config : unconfig
@$(MKCONFIG) $(@:_config=) arm arm920t 100ask24x0 NULL s3c24x0
执行了make 100ask24x0_config之后想当于执行了上面的第二行语句。

我们再找到MKCONFIG的定义:

MKCONFIG := $(SRCTREE)/mkconfig

可知,MKCONFIG就是根目录下的mkconfig文件。$(@:_config=) 的结果就是将“100ask24x0_config”的“_config”去掉(因为后面是=“空格”,相当于替换了),结果为“100ask24x0”,所以“make 100ask24x0_config”实际上执行的就是如下命令:

mkconfig 100ask24x0 arm arm920t 100ask24x0 NULL s3c24x0

打开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

分析如下:
1.下列代码块是对传输的参数进行分析,有无“–”“-a”“-n”等

while [ $# -gt 0 ] ; do
	case "$1" in
	--) shift ; break ;;
	-a) shift ; APPEND=yes ;;
	-n) shift ; BOARD_NAME="${1%%_config}" ; shift ;;
	*)  break ;;
	esac
done

2.“BOARD_NAME”是否定义,如果定义了,则BOARD_NAME="$1"不会执行。

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

$1表示第一个参数:

mkconfig100ask24x0s3c24x0
$0$1$…$6

执行完此句话后,BOARD_NAME = 100ask24x0

3.$#参数的个数,小于4个会退出,大于6个也会退出

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

4.打印这句话

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

“SRCTREE”会等于“OBJTREE”,因为在Makefile中有语句使其相等了。

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

故而会执行下面的else

ln -s asm-$2 asm
相当于会建立一个链接文件,让asm指向asm-arm。此处目的是方便代码书写。例子:

#include <asm/type.h>
//可能会有#include <asm-i386/type.h>
//或者其他#include <asm-arm/type.h>

我们不想把代码改来改去,配置时临时生成,让asm指向某个架构

6.删除
rm -f asm-$2/arch

7.如果第六个参数为空或者等于null的话执行第一条,这里不满足,执行的是第二条。

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

此句也是建立链接文件,LNPREFIX没有定义相当于空的,最后执行为:
ln -s arch-s3c24x0 asm-arm/arch

8.下一句同理。

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

9.建立一个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

[]括起来的才是条件,后面的是执行的语句。

10.“APPEND”==NO,创建一个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
echo "#include <configs/$1.h>" >>config.h

exit 0

make编译分析

在makefile中有这边一段代码

OBJS  = cpu/$(CPU)/start.o
...
...
LIBS  = lib_generic/libgeneric.a
LIBS += board/$(BOARDDIR)/lib$(BOARD).a
LIBS += cpu/$(CPU)/lib$(CPU).a
...
...

LIBS 把所有涉及的文件编译好后打包成一个.a的库

在makefile中有这边一段代码

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):
	echo $(OBJS)	
		$(MAKE) -C cpu/$(CPU) $(if $(REMOTE_BUILD),$@,$(notdir $@))

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

我们执行make的时候,如果不指定目标,则会生成第一个目标。我们最终想生成u-boot.bin,u-boot.bin依赖于下面的这一句话$(obj)u-boot.bin: $(obj)u-boot 这里的$(obj)u-boot是elf格式的。
$(obj)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编译结果

通过上面我们知道了以下知识:
1.第一个文件是 cpu/arm920t/start.S
2.链接地址由以下决定:board/100ask24x0/u-boot.lds和0x33F80000

0x33F80000要修改的话在config.mk中修改。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值