以下内容源于朱有鹏嵌入式课程的学习与整理,如有侵权请告知删除。
一、/mkconfig脚本概览
在uboot的根目录下执行“make x210_sd_config”进行配置时,x210_sd_config是目标。在主Makefile中2589行有如下代码。
x210_sd_config : unconfig@$(MKCONFIG) $(@:_config=) arm s5pc11x x210 samsung s5pc110@echo "TEXT_BASE = 0xc3e00000" > $(obj)board/samsung/x210/config.mk
该目标的操作部分调用了MKCONFIG所表示的脚本,即/mkconfig脚本。
该脚本接收6个参数,分别是x210_sd,arm,s5pc11x,x210,samsung,s5pc110。
该脚本完成一些符号连接的创建,以及头文件include/config.h、include/config.mk的创建。
- include/config.mk文件内容如下。
ARCH = arm CPU = s5pc11x BOARD = x210 VENDOR = samsung SOC = s5pc110
- 创建include/config.mk文件,是为了让主Makefile在第133行展开。
# load ARCH, BOARD, and CPU configurationinclude $(obj)include/config.mk export ARCH CPU BOARD VENDOR SOC
- include/config.h文件中仅有一行代码,即“#include<configs/x210_sd.h>”。如下。
/* Automatically generated - do not edit */ #include <configs/x210_sd.h>
- 配置前,configs文件夹就已经位于/include文件夹下,它的每个文件对应一个开发板的头文件。这些头文件都是一些宏定义配置文件,是移植时最主要的文件。
- x210开发板的uboot的/include/configs里面有两个头文件:x210_nand.h、x210_sd.h。
xjh@ubuntu:~/iot/embedded_basic_course/uboot/uboot_jiuding/include/configs# ls x210_nand.h x210_sd.h xjh@ubuntu:~/iot/embedded_basic_course/uboot/uboot_jiuding/include/configs#
- x210_sd.h文件被用来生成autoconfig.mk文件,后者被主Makefile引入而指导整个编译过程。x210_sd.h文件中的宏会影响大部分.c文件里的一些条件编译的选择,从而实现可移植性。
二、分析/mkconfig脚本
输入“”make x210_sd_config时,/mkconfig脚本会被主Makefile调用。该脚本的主要内容为:
1、解析输入参数。
APPEND=no # Default: Create new config file BOARD_NAME="" # Name to print in make outputwhile [ $# -gt 0 ] ; docase "$1" in--) shift ; break ;;-a) shift ; APPEND=yes ;;-n) shift ; BOARD_NAME="${1%%_config}" ; shift ;;*) break ;;esac done
- 这个脚本在主Makefile中被执行前,会被传入6个参数,分别是x210_sd,arm,s5pc11x,x210,samsung,s5pc110。
- 所以$#=6($#的值是输入参数个数),$1=x210_sd,$2=arm,$3=s5pc11x,$4=x210,$5=samsung,$6=s5pc110。
- 本段代码的功能为解析传入本脚本的参数。首先利用while循环,判断$#的值(即参数个数),是否大于0,如果大于0则进入循环。
- shell的switch case语法中是不需要break的,故此处的switch case是为了跳出外面的while循环。
- 每个case的结束都需要加“;”,执行语句结束也要加“;”,所以每行case的最后都会有两个分号。
- 这段代码上来先判断$1的值(即第一个参数),如果为一些特定的值,那么会进行shift操作,即向左移动参数列表一次,将第一个参数移出参数列表。
- 但由于我们第一个参数为x210_sd,故只符合最后一个case,即“*”,也就是通配符,直接break跳出了while循环。其实这整段代码对我们没有产生什么作用。
[ "${BOARD_NAME}" ] || BOARD_NAME="$1"
- 本句是缩写的if判断语句,判断变量BOARD_NAME是否为空,由于在12行处对其赋为空值,所以此处将它的值赋为第一个参数的值,即x210_sd。
[ $# -lt 4 ] && exit 1 [ $# -gt 6 ] && exit 1 echo "Configuring for ${BOARD_NAME} board..."
- 开头两句是缩写的if判断语句。如果参数个数小于4,则这个脚本程序将退出,并返回1(表示出错);同样,如果参数个数大于6,则这个脚本程序将退出,并返回1(表示出错)。
- 最后一句为打印配置信息。
2、创建符号链接、头文件。
从这里开始的代码便是创建符号链接及一些头文件,其根本目的是使uboot具有可移植性。uboot中有很多功能平行的代码文件,各自属于各自不同的平台/开发板/cpu。通过那些传入/mkconfig脚本的参数,可以创建指向我们所需要的文件的符号链接。
uboot不直接与这些功能平行的代码建立联系,而是使用符号链接来屏蔽许多用不到的代码。比如某个源文件中包含一个 #include “asm/xx.h”,其中asm是/mkconfig脚本所创建的符号链接,它指向/include/asm-arm,由此便可以定位到真正的路径,即“/include/asm-arm/xx.h”。
综上所述,创建符号链接的本质是通过不同的参数,令源代码文件包含特定的文件。
# # Create link to architecture specific headers # if [ "$SRCTREE" != "$OBJTREE" ] ; thenmkdir -p ${OBJTREE}/includemkdir -p ${OBJTREE}/include2cd ${OBJTREE}/include2rm -f asmln -s ${SRCTREE}/include/asm-$2 asmLNPREFIX="../../include2/asm/"cd ../includerm -rf asm-$2rm -f asmmkdir asm-$2ln -s asm-$2 asm elsecd ./includerm -f asmln -s asm-$2 asm fi
- 本段代码功能是确定和汇编指令集相关文件夹。
- 首先判断是否使用了“外部输出文件夹编译”功能,如果未使用则进入源码目录下的include目录,删除原本存在的符号链接asm。
- 最后创建符号链接asm,使其链接到asm-arm文件夹。
rm -f asm-$2/archif [ -z "$6" -o "$6" = "NULL" ] ; thenln -s ${LNPREFIX}arch-$3 asm-$2/arch elseln -s ${LNPREFIX}arch-$6 asm-$2/arch fi
- 删除指令集文件夹下原本存在的符号链接arch。
- 然后确定指令集文件夹下的架构文件夹,但是这段代码其实是历史遗留代码,创建的是有问题的,真正的确定架构文件夹是在后面。
#这里省略了一堆和其他soc有关的代码,只保留了我们的s5pv210if [ "$3" = "s5pc11x" ] ; thenrm -f regs.hln -s $6.h regs.hrm -f asm-$2/archln -s arch-$3 asm-$2/arch fi
- 本段代码旨在确定cpu的寄存器头文件,和确定指令集文件夹下的架构文件夹。
- 首先判断第三个参数是不是s5pc11x,然后删除原本存在的符号链接regs.h,再创建regs.h链接到s5pc110.h。
- 最后删除原本./include/asm-arm目录下的符号链接arch,再在./include/asm-arm目录下创建符号链接arch,使其链接到arch-s5pc110这个架构文件夹。
if [ "$2" = "arm" ] ; thenrm -f asm-$2/procln -s ${LNPREFIX}proc-armv asm-$2/proc fi
- 本段代码旨在确定指令集文件夹下的proc文件夹。在./include/asm-arm目录下创建proc,指向proc-armv文件夹。
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
- 本段是创建include/config.mk,由于之前所停留的目录一直是include目录下,故config.mk将被创建在include目录下
- bash语法中的>功能是创建文件并填充内容,>>功能是额外添加内容,所以第2,3,4个参数都被添加到这个文件中去了,当5,5,6存在且不为0时,第5,6个参数才被添加。
if [ "$APPEND" = "yes" ] # Append to existing config file thenecho >> config.h else> config.h # Create new config file fi echo "/* Automatically generated - do not edit */" >>config.h echo "#include <configs/$1.h>" >>config.hexit 0
- 本段的功能主要是创建根目录下include/config.h这个文件,这个.h文件内只有一句话,即#include “configs/x210_sd.h”。
- 从某种意义上来说,./include/config.h这个文件的功能就是符号链接,它指向了真正的配置头文件./include/configs/x210_sd.h。
- APPEND变量是在本文件一开始的地方定义的,值默认是no,当本脚本文件被传参数-a时,它会被赋值yes(具体代码大概在17行)。
- 创建完config.h之后,再向其填充入内容,最后shell结束,返回值0(表示正常)。