uboot的官网可以通过谷歌搜索得到,显示结果第一个链接就是。

官网::

​http://www.denx.de/wiki/U-Boot​

ftp下载:

ftp://ftp.denx.de/pub/u-boot/



本文以uboot 2014.07为例,一般第一步总是类似这样:

make smdkc100_config

然后执行make


先看Makefile第481 行

%_config:: outputmakefile

@$(MKCONFIG) -A $(@:_config=)

当输入make smdkc100_config时,就会匹配到%_config目标,%是通配符,即输入XXX_config格式的目标就会匹配到%_config。

MKCONFIG的定义在前面:

MKCONFIG := $(srctree)/mkconfig

export MKCONFIG


srctree的定义:

srctree := $(if $(KBUILD_SRC),$(KBUILD_SRC),$(CURDIR))//if KBUILD_SRC被定义,则srctree=KBUILD_SRC,else = CURDIR,


KBUILD_SRC的定义:

ifeq ($(KBUILD_SRC),)

# OK, Make called in directory where kernel src resides

# Do we want to locate output files in a separate directory?

#O就是output目录变量,使用方法:make O= XXXDIR

ifeq ("$(origin O)", "command line")

#如果O变量来自命令行(origin返回变量的来源)

  KBUILD_OUTPUT := $(O)

endif


事实上我没用O去定义KBUILD_SRC变量,所以srctree=当前目录,也就是uboot的目录

objtree := $(CURDIR)

src := $(srctree)


以上语句可翻译为:

smdkc100_config:: outputmakefile

./mkconfig -A $(@:_config=)


这里的规则用了双冒号 :: 

1.        双冒号规则中,当依赖文件比目标更新时。规则将会被执行。对于一个没有依赖而只有命令行的双冒号规则,当引用此目标时,规则的命令将会被无条件执行。而普通规则,当规则的目标文件存在时,此规则的命令永远不会被执行(目标文件永远是最新的)。


$(@:_config=):请看Gnu Make中文手册5.3.1 变量的替换引用。

$(@)代表目标smdkc100_config,$(@:_config=):表示用等号后面的内容替代掉:和=之间的内容,=后面为空,那么_config就等于被删去了,$(@:_config=)就代表smdkc100

./mkconfig -A $(@:_config=)



现在可以看mkconfig文件了。mkconfig没有目标,从第一句开始执行:

第一个if段:


if [ \( $# -eq 2 \) -a \( "$1" = "-A" \) ] ; then

# Automatic mode

line=`awk '($0 !~ /^#/ && $7 ~ /^'"$2"'$/) { print $1, $2, $3, $4, $5, $6, $7, $8 }' $srctree/boards.cfg`

if [ -z "$line" ] ; then

echo "make: *** No rule to make target \`$2_config'.  Stop." >&2

exit 1

fi


set ${line}

# add default board name if needed

[ $# = 3 ] && set ${line} ${1}

fi


######    $#表示传入参数个数,由上可知$# = 2,符合条件。 -a表示逻辑与。$1表示第一个参数,等于-A,符合条件,所以then后面的语句被执行。

这段代码符号比较多,看起来比较复杂,请百度shell 符号,你会有所收获。


line=`awk**************`

用倒引号``把命令的输出作为字串,如果是"",则里面的内容不被当做命令执行,而是当做纯粹的字符串,但可引用变量

'  '单引号内的内容作为字串,但变量$符号不会起作用(忽略任何引用),

单括号()内可以的内容可以执行命令,也就是说,()内先执行,再用''把()的输出当做纯字串,大括号同理。

//斜杠表示里面的内容是正则表达式。

($0 !~ /^#/ && $7 ~ /^'"$2"'$/)

在awk命令里,$不是shell变量符号,而是域标记。但是也有例外:双引号""中的$可以引用变量(参见《LINUX与UNIX SHELL编程指南》67页,9.2.2节,“域和记录”和第15章,引号),所以这里的$7 为boards.cfg里的域7,而$2则表示mkconfig的第二个参数,没错,就是smdkc100,/^'"$2"'$/表示只包含变量$2的行,依然是smdkc100。

$0表示所有域,$0 !~ /^#/ 意思是,awk排除以#开头的行,这句话用来排除那些以#开头的注释内容。$7 ~ /^'"$2"'$/表示记录的域7必须为smdkc100。


boards.cfg只有下面这行符合条件:

Active  arm         armv7          s5pc1xx     samsung         smdkc100            smdkc100

然后执行{ print $1, $2, $3, $4, $5, $6, $7, $8 }

这样line就等于Active  arm         armv7          s5pc1xx     samsung         smdkc100            smdkc100


接下来:

set ${line}

# add default board name if needed

[ $# = 3 ] && set ${line} ${1}


set命令

参见《高级bash脚本编程指南》202页

set 命令用来修改内部脚本变量的值.一个作用就是触发选项标志位来帮助决定脚本的行

为.另一个应用就是以一个命令的结果(set `command`)来重新设置脚本的位置参数.脚本

将会从命令的输出中重新分析出位置参数。


所以mkconfig 的位置参数被重新定义为$(line)的内容,即:

$1=Active  $2=arm         $3=armv7          $4=s5pc1xx     $5=samsung         $6=smdkc100            $7=smdkc100  $8=-(注意是短破折号,不是空格)

补充一下,以上排列为:

# Status, Arch, CPU:SPLCPU, SoC, Vendor, Board name, Target, Options

 

对于[ $# = 3 ] && set ${line} ${1}:

&&的说明参见《LINUX与UNIX SHELL编程指南》6.1 使用&&

这里先判断$# 是否等于 3(明显不等),相等则执行&&右边的命令。那么,直接跳过吧。





​1​

​while​​ ​​[ $# -gt 0 ] ; ​​​​do​


​2​

​case​​ ​​"$1"​​ ​​in​


​3​

​--) shift ; ​​​​break​​ ​​;;​


​4​

​-a) shift ; APPEND=yes ;;​


​5​

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


​6​

​-t) shift ; TARGETS=​​​​"`echo $1 | sed 's:_: :g'` ${TARGETS}"​​ ​​; shift ;;​


​7​

​*)  ​​​​break​​ ​​;;​


​8​

​esac​


​9​

​done​

其实上面的参数都不会匹配到。(没有指定-a -n -t选项)

这里只说一下${7%_config},结果等于smdkc100 ,请百度shell 截取 变量。

%号截取,删除右边字符,保留左边字符


echo ${var%/*}


%/* 表示从右边开始,删除第一个 / 号及右边的字符



实际上$7本身等于smdkc100了,那么${7%_config}依然是smdkc100。

后面的代码比较简单了,实现如下功能:


变量arch="arm"

建立软连接:

arch\arm\include\asm\arch-s5pc1xx 生成链接符号 arch\arm\include\asm\arch



进入include目录




​01​

​# Create include file for Make​


​02​

​#​


​03​

​( echo ​​​​"ARCH   = ${arch}"​


​04​

​if​​ ​​[ ! -z ​​​​"$spl_cpu"​​ ​​] ; then​


​05​

​echo ​​​​'ifeq ($(CONFIG_SPL_BUILD),y)'​


​06​

​echo ​​​​"CPU    = ${spl_cpu}"​


​07​

​echo ​​​​"else"​


​08​

​echo ​​​​"CPU    = ${cpu}"​


​09​

​echo ​​​​"endif"​


​10​

​else​


​11​

​echo ​​​​"CPU    = ${cpu}"​


​12​

​fi​


​13​

​echo ​​​​"BOARD  = ${board}"​


​14​

 


​15​

​[ ​​​​"${vendor}"​​ ​​] && echo ​​​​"VENDOR = ${vendor}"​


​16​

​[ ​​​​"${soc}"​​    ​​] && echo ​​​​"SOC    = ${soc}"​


​17​

​exit​​ ​​0 ) > config.mk​

include目录下生成config.mk,内容为:

ARCH   = arm

CPU    = armv7

BOARD  = smdkc100

VENDOR = samsung

SOC    = s5pc1xx


include目录下创建config.h


for i in ${TARGETS} ; do

i="`echo ${i} | sed '/=/ {s/=/ /;q; } ; { s/$/ 1/; }'`"

echo "#define CONFIG_${i}" >>config.h ;

done

 ${TARGETS} 为空,所以以上for循环不会被执行。





​01​

​echo ​​​​"#define CONFIG_SYS_ARCH  \"${arch}\""​​  ​​>> config.h​


​02​

​echo ​​​​"#define CONFIG_SYS_CPU   \"${cpu}\""​​   ​​>> config.h​


​03​

​echo ​​​​"#define CONFIG_SYS_BOARD \"${board}\""​​ ​​>> config.h​


​04​

 


​05​

​[ ​​​​"${vendor}"​​ ​​] && echo ​​​​"#define CONFIG_SYS_VENDOR \"${vendor}\""​​ ​​>> config.h​


​06​

 


​07​

​[ ​​​​"${soc}"​​    ​​] && echo ​​​​"#define CONFIG_SYS_SOC    \"${soc}\""​​    ​​>> config.h​


​08​

 


​09​

​[ ​​​​"${board}"​​  ​​] && echo ​​​​"#define CONFIG_BOARDDIR board/$BOARDDIR"​​ ​​>> config.h​


​10​

​cat << EOF >> config.h​


​11​

​#include <config_cmd_defaults.h>​


​12​

​#include <config_defaults.h>​


​13​

​#include <configs/${CONFIG_NAME}.h>​


​14​

​#include <asm/config.h>​


​15​

​#include <config_fallbacks.h>​


​16​

​#include <config_uncmd_spl.h>​


​17​

​EOF​


​18​

 


​19​

​exit​​ ​​0​



​1​

​cat << EOF >> config.h表示以下内容追加到config.h中,直到出现EOF标记为止。​

最终config.h内容为:





​01​

​/* Automatically generated - do not edit */​


​02​

​#define CONFIG_SYS_ARCH  "arm"​


​03​

​#define CONFIG_SYS_CPU   "armv7"​


​04​

​#define CONFIG_SYS_BOARD "smdkc100"​


​05​

​#define CONFIG_SYS_VENDOR "samsung"​


​06​

​#define CONFIG_SYS_SOC    "s5pc1xx"​


​07​

​#define CONFIG_BOARDDIR board/samsung/smdkc100​


​08​

​#include <config_cmd_defaults.h>​


​09​

​#include <config_defaults.h>​


​10​

​#include <configs/smdkc100.h>​


​11​

​#include <asm/config.h>​


​12​

​#include <config_fallbacks.h>​


​13​

​#include <config_uncmd_spl.h>​


 


作者:​​柒月​