uboot的mkconfig分析

时间:2020-12-26 19:30:48

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

我再把运行结果图片贴出来。

uboot的mkconfig分析

(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中定义了这两个变量。

uboot的mkconfig分析

可以看到,当使用"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