uboot的mkconfig是一个shell脚本。对于笔者这种Linux学习初学者,不太可能认真的把shell脚本学习一遍。但是,倘若不能理解mkconfig的含义,又很难从整体的理解uboot(我认为只片面地理解程序代码,而不明白它们的连接、编译,也就是Makefile是不行的。对于致力于从事Linux开发者而言,总有一天要涉及到这方面的内容)。
笔者认为“echo”是一个绝好的命令,它可以打印出我们想知道的很多内容的信息。以此类推,凡是能通过界面生动地告知我们计算机内部数据的工具,都是绝佳的。例如串口工具,当然这要归功于printf函数的强大功能。我就是通过这个命令,一点一点的把mkconfig中的内容打印出来,这样我们很容易就知道它的含义。首先,我把mkconfig的代码插入。红色字体的代码是我加入的打印命令。
1 #!/bin/sh -e
2
3 echo "$""#"=$#
4 echo "$""1"=$1
5 echo "$""2"=$2
6 echo "$""3"=$3
7 echo "$""4"=$4
8 echo "$""5"=$5
9 echo "$""6"=$6
10
11 while [ $# -gt 0 ] ; do
12 case "$1" in
13 --) shift ; break ;;
14 -a) shift ; APPEND=yes ;;
15 -n) shift ; BOARD_NAME="${1%%_config}" ; shift ;;
16 *) break ;;
17 esac
18 done
19
20 echo "BOARD_NAME="$BOARD_NAME
21 [ "${BOARD_NAME}" ] || BOARD_NAME="$1"
22 echo "BOARD_NAME="$BOARD_NAME
23
24 echo "$""#"=$#
25 [ $# -lt 4 ] && exit 1
26 [ $# -gt 6 ] && exit 1
27
28 echo "Configuring for ${BOARD_NAME} board..."
29
30 echo "$""SRCTREE="$SRCTREE
31 echo "$""OBJTREE="$OBJTREE
32 #
33 # Create link to architecture specific headers
34 #
35 if [ "$SRCTREE" != "$OBJTREE" ] ; then
36 mkdir -p ${OBJTREE}/include
37 mkdir -p ${OBJTREE}/include2
38 cd ${OBJTREE}/include2
39 rm -f asm
40 ln -s ${SRCTREE}/include/asm-$2 asm
41 LNPREFIX="../../include2/asm/"
42 cd ../include
43 rm -rf asm-$2
44 rm -f asm
45 mkdir asm-$2
46 ln -s asm-$2 asm
47 else
48 cd ./include
49 rm -f asm
50 ln -s asm-$2 asm
51 fi
52
53 rm -f asm-$2/arch
54
55 if [ -z "$6" -o "$6" = "NULL" ] ; then
56 ln -s ${LNPREFIX}arch-$3 asm-$2/arch
57 else
58 ln -s ${LNPREFIX}arch-$6 asm-$2/arch
59 fi
60
61 if [ "$2" = "arm" ] ; then
62 rm -f asm-$2/proc
63 ln -s ${LNPREFIX}proc-armv asm-$2/proc
64 fi
65
66 pwd
67 #
68 # Create include file for Make
69 #
70 echo "ARCH = $2" > config.mk
71 echo "CPU = $3" >> config.mk
72 echo "BOARD = $4" >> config.mk
73
74 [ "$5" ] && [ "$5" != "NULL" ] && echo "VENDOR = $5" >> config.mk
75
76 [ "$6" ] && [ "$6" != "NULL" ] && echo "SOC = $6" >> config.mk
77
78 #
79 # Create board specific header file
80 #
81 if [ "$APPEND" = "yes" ] # Append to existing config file
82 then
83 echo >> config.h
84 else
85 > config.h # Create new config file
86 fi
87 echo "/* Automatically generated - do not edit */" >>config.h
88 echo "#include <configs/$1.h>" >>config.h
89
90 exit 0
我再把运行结果图片贴出来。
(1) 从中,我们不难看出$#、$1、$2、$3、$4、$5、$6的含义。$#代表传入参数的个数,$1代表第一个参数,一次类推。
(2)第11到18行,是包含了"while[]"语句、case语句,并利用了break语句。这分别与c语言中的"while()"语句、switch-case语句、break语句类似。"-gt"是判断第一个数是否大于第二个数,这里放在"while[]"语句中也就好像是c语言中"while()"语句的条件判断,如果为真就循环。由于"$#"大于0,所以执行循环;又由于"$1"中没有"--"、"-a"、"-n"等符号,所以执行"*)"后边的break语句;break语句具有跳出循环的作用,所以就跳出这个循环。总结这一段语句并没有起到任何作用。
(3)源代码第20行打印出"BOARD_NAME"是空的,而经过第21行的处理后,到了第22行打印的时候就变成了smdk2410,你就知道第21行做了什么样的工作。第21行的内容如下,中括号里边判断"BOARD_NAME"是否为真(有内容),"||"代表"else"的意思。由于一开始"BOARD_NAME"为空,所以执行BOARD_NAME="$1"。
21 [ "${BOARD_NAME}" ] || BOARD_NAME="$1"
(4)第24行到第26行,判断参数个数是否在允许范围内,如果不在就直接跳出。第25行内容如下,"-lt"是小于的意思,"&&"是“如果条件为真,就执行后边语句”的意思。首先判断"$#"是否小于4,由于"$#"不小于4,所以也不会执行“exit 1”这句话。
25 [ $# -lt 4 ] && exit 1
(5)第30到51行,目的是建立链接文件(我把链接文件理解为windows下的快捷方式)。
30 echo "$""SRCTREE="$SRCTREE
31 echo "$""OBJTREE="$OBJTREE
32 #
33 # Create link to architecture specific headers
34 #
35 if [ "$SRCTREE" != "$OBJTREE" ] ; then
36 mkdir -p ${OBJTREE}/include
37 mkdir -p ${OBJTREE}/include2
38 cd ${OBJTREE}/include2
39 rm -f asm
40 ln -s ${SRCTREE}/include/asm-$2 asm
41 LNPREFIX="../../include2/asm/"
42 cd ../include
43 rm -rf asm-$2
44 rm -f asm
45 mkdir asm-$2
46 ln -s asm-$2 asm
47 else
48 cd ./include
49 rm -f asm
50 ln -s asm-$2 asm
51 fi
"if then else fi"语句跟c语言中if-else语句类似,只不过形式上有区别。第30到第31行,是打印出""SRCTREE"(源代码目录)、"OBJTREE"(目标代码目录)的内容。我们看到运行结果图片上打印的是空。这是因为mkconfig文件并没有定义这两个变量,所以直接使用就是空。事实上,这两个参数是从顶层Makefile中导出的,顶层Makefile中定义了这两个变量。
可以看到,当使用"make smdk2410_config"命令来调用mkconfig脚本时,就能把Makefile中那两个参数传入到mkconfig脚本中。由于,if语句判断两个目录相同,所以执行else分支;先进入include目录中,然后把asm链接文件删除,再重新建立指向"asm-$2"的链接文件asm。通过"ls -l asm"命令可以看出asm文件与普通文件/文件夹的区别,你也可以在linux操作系统下查看"u-boot/inlclude"目录中asm文件的图标来理解这种链接文件的内涵。
最后,我想谈一谈我对asm这个链接文件的认识。通过,执行"make smdk2410_config"命令,可以将asm-arm这个文件夹被调出来,而其他的例如asm-avr32那些则不会被调出来。通过建立asm这个链接文件,可以从众多的架构中只选择出对应架构的文件。
(6)第53到64行是建立asm-$2/arch和asm-$2/proc这两个链接文件。建立方式,与(5)中建立asm链接文件的方法都一样,先将远离的链接文件删除,然后重新建立一个新的链接文件。"-z"是逻辑判断空串的意思,"-o"是逻辑或的意思。
53 rm -f asm-$2/arch
54
55 if [ -z "$6" -o "$6" = "NULL" ] ; then
56 ln -s ${LNPREFIX}arch-$3 asm-$2/arch
57 else
58 ln -s ${LNPREFIX}arch-$6 asm-$2/arch
59 fi
60
61 if [ "$2" = "arm" ] ; then
62 rm -f asm-$2/proc
63 ln -s ${LNPREFIX}proc-armv asm-$2/proc
64 fi
(7)第67到76行是在include目录下建立一个顶层Makefile包含的文件config.mk。">"是重定向符号,我的理解就是能够创建一个新的文件。">>"可以将ehco后边的字符串追加到config.mk后边,而不去覆盖它。
67 #
68 # Create include file for Make
69 #
70 echo "ARCH = $2" > config.mk
71 echo "CPU = $3" >> config.mk
72 echo "BOARD = $4" >> config.mk
73
74 [ "$5" ] && [ "$5" != "NULL" ] && echo "VENDOR = $5" >> config.mk
75
76 [ "$6" ] && [ "$6" != "NULL" ] && echo "SOC = $6" >> config.mk
(8)第78句到88句是在include目录下建立一个头文件config.h。建立的方法与(7)中建立config.mk的方法类似。
78 #
79 # Create board specific header file
80 #
81 if [ "$APPEND" = "yes" ] # Append to existing config file
82 then
83 echo >> config.h
84 else
85 > config.h # Create new config file
86 fi
87 echo "/* Automatically generated - do not edit */" >>config.h
88 echo "#include <configs/$1.h>" >>config.h
最后,我想谈谈我对include/config.h的认识。由于,uboot支持众多的开发板,所以在编译过程中,注定对应开发板的文件被编译,而那些不匹配的将被抛弃。而config.h可以看做是一个针对开发板预留的一个头文件,这里边究竟是哪个开发板的头文件,将来可以通过这部分shell程序添加进去。
总结
(1)开发板名称BOARD_NAME等于$1
(2)创建到平台/开发板相关的头文件的链接,如下所示
ln -s asm-$2 asm
ln -s arch-$6 asm-$2/arch
ln -s pro-armv asm-$2/proc
(3)创建顶层Makeflie包含的文件include/config.mk,如下所示:
ARCH = $2
CPU = $3
BOARD = $4
VENDOR = $5
SOC = $6
(4)创建开发板相关的头文件include/config.h,如下所示:
/* Automatically generated - do not edit */
#include <configs/$1.h>"
参考资料:韦东山 《嵌入式Linux应用开发完全手册》
linux命令及shell.pdf