了解u-boot的童靴都清楚u-boot.bin的生成分为两个步骤:配置和编译。下面我们先来说一下配置的过程,执行的命令是
make -C $BOOTLDR_PATH ARCH=arm CROSS_COMPILE=$CROSS_COMPILER_KERNEL_PREFIX s3c2440_config
这条指令的意思是进入到$BOOTLDR_PATH
目录,执行make
,指定芯片架构ARCH为ARM
,指定编译工具链CROSS_COMPILE,目标是s3c2440_config
。
打开boot目录下的Makefile,大概1000行,还是比较简单的。搜索目标s3c2440_config:
,没找到,搜索_config:
,找到了
%_config:: unconfig
@$(MKCONFIG) -A $(@:_config=)
注意
_config:
最后的:号,因为这个可以去除掉全部非目标的搜索记录。
嗯,就是这里,%
表示通配符,也就说执行make s3c2440_config
和make xxxxx_config
目标都是这个。依赖目标是unconfig
,搜索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
这是一个伪目标,所做的动作是删除生成的中间文件。继续看命令
@$(MKCONFIG) -A $(@:_config=)`
找到MKCONFIG
的定义
SRCTREE := $(CURDIR)
MKCONFIG := $(SRCTREE)/mkconfig
CURDIR
是Makefile的内嵌变量,表示当前目录。$(@:_config=)
表示将$@
中的_config
替换为空,也就是说上面这条命令等价于$(SRCTREE)/mkconfig -A s3c2440
,看样子重点是文件$(SRCTREE)/mkconfig
。打开文件mkconfig
,上来就是判断,这在shell脚本中是非常常见的。
if [ \( $# -eq 2 \) -a \( "$1" = "-A" \) ] ; then
# Automatic mode
line=`egrep -i "^[[:space:]]*${2}[[:space:]]" boards.cfg` || {
echo "make: *** No rule to make target \`$2_config'. Stop." >&2
exit 1
}
set ${line}
# add default board name if needed
[ $# = 3 ] && set ${line} ${1}
fi
当入参数目为2
,并且第一个入参为-A
时,line等于egrep -i "^[[:space:]]*${2}[[:space:]]" boards.cfg
的结果,实际上后面这个就是将文件boards.cfg
中含有s3c2440
字符的一行赋值给line
,line
的内容是smdk2440 arm arm920t - samsung s3c24x0
。重点是下面一句,set ${line}
,重新设置$1
等等。下面就是一些赋值行为
CONFIG_NAME="${1%_config}" # $1为smdk2440,去除$1中的_config还是smdk2440
BOARD_NAME="${1%_config}"
arch="$2" # 等于arm
cpu=`echo $3 | awk 'BEGIN {FS = ":"} ; {print $1}'` # 等于arm920t
board=${BOARD_NAME}
vendor=$5 # 等于samsung
soc=$6 # 等于s3c24x0
下面执行的是一些创建软链接的行为
cd ./include
rm -f asm
ln -s ../arch/${arch}/include/asm asm # 创建软链接 asm -> ../arch/arm/include/asm
rm -f asm/arch
ln -s ${LNPREFIX}arch-${soc} asm/arch # 创建软链接 arch -> arch-s3c24x0
rm -f asm/proc
ln -s ${LNPREFIX}proc-armv asm/proc # 创建软链接 proc -> proc-armv
下面将创建文件include/config.mk
( echo "ARCH = ${arch}"
if [ ! -z "$spl_cpu" ] ; then
echo 'ifeq ($(CONFIG_SPL_BUILD),y)'
echo "CPU = ${spl_cpu}"
echo "else"
echo "CPU = ${cpu}"
echo "endif"
else
echo "CPU = ${cpu}"
fi
echo "BOARD = ${board}"
[ "${vendor}" ] && echo "VENDOR = ${vendor}"
[ "${soc}" ] && echo "SOC = ${soc}"
exit 0 ) > config.mk
向include/config.mk
写入
ARCH = arm
CPU = arm920t
BOARD = smdk2440
VENDOR = samsung
SOC = s3c24x0
BOARDDIR=${vendor}/${board} # 等于samsung/smdk2440
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
i="`echo ${i} | sed '/=/ {s/=/ /;q; } ; { s/$/ 1/; }'`"
echo "#define CONFIG_${i}" >>config.h ;
done
echo "#define CONFIG_SYS_ARCH \"${arch}\"" >> config.h
echo "#define CONFIG_SYS_CPU \"${cpu}\"" >> config.h
echo "#define CONFIG_SYS_BOARD \"${board}\"" >> config.h
[ "${vendor}" ] && echo "#define CONFIG_SYS_VENDOR \"${vendor}\"" >> config.h
[ "${soc}" ] && echo "#define CONFIG_SYS_SOC \"${soc}\"" >> config.h
cat << EOF >> config.h
#define CONFIG_BOARDDIR board/$BOARDDIR
#include
#include
#include
#include
#include
#include
EOF
上面这段生成文件include/config.h
,并写入
/* Automatically generated - do not edit */
#define CONFIG_SYS_ARCH "arm"
#define CONFIG_SYS_CPU "arm920t"
#define CONFIG_SYS_BOARD "smdk2440"
#define CONFIG_SYS_VENDOR "samsung"
#define CONFIG_BOARDDIR board/samsung/smdk2440
#include
#include
#include
#include
#include
#include
根据上面的分析我们可以知道boot的配置过程
- 根据芯片在
boards.cfg
查找到此款芯片的相关信息; - 对
include/asm
下的一些目录进行软链接操作; - 将芯片的相关信息写入
include/config.mk
和include/config.h
include/config.mk
是后面编译时需要使用的,include/config.h
则是代码中的。