序言
开始Linux的第一步,是搞清楚bootloader,目前比较流行的bootloader有很多,如LILO、GRUB、Redboot、ARMboot、u-boot等等,我的板子使用的是u-boot,所以今天的主题就是它
的编译脚本,今天的内容主要分为如下几个部分
- shell语法学习
- 脚本解析
- 脚本总结
shell语法学习
因为这个脚本是一个shell脚本,所以在开始分析之前我们有必要先补习一下分析过程中会用到的语法
条件测试
#if条件
if condition;
then
commands;
fi
#else if 和 else
if condition;
then
commands
else if condition; then
commands;
else
commands;
fi
#! /bin/sh -
#case语句
case $1 in
s|start)
echo "start..."
;;
stop)
echo "stop ..."
;;
reload)
echo "reload..."
;;
*)
echo "Usage: $name [start|stop|reload]"
exit 1
;;
esac
在case中要注意:
- *) 相当于其他语言中的default。
- 除了*)模式,各个分支中;;是必须的,;;相当于其他语言中的break
- | 分割多个模式,相当于or
算数比较
比较条件通常放置在封闭的括号中,一定要主要在[或]与操作数之间要有空格。
[$var -eq 0 ] or [$var -eq 0]
对变量或值进行算数条件测试
[ $var -eq 0] #当$var等于0时,返回真
[ $var -ne 0] #当$var不为0时,返回真
其它重要的操作符如下
- -gt:大于。
- -lt:小于。
- -ge:大于或等于
- -le:小于或等于
-a时逻辑与,-o时逻辑或,结合二者可以对多个条件进行测试
[ $var1 -ne 0 -a $var2 -gt 2 ]
[ $var1 -ne 0 -o $var2 -gt 2 ]
文件系统相关测试
我们可以使用不同的条件标志测试各种文件系统相关的属性
- [ -f $file_var]:如果给定的变量包含正常的文件路径或文件名,则返回真
- [-x $var]:如果给定的变量包含的文件可执行,则返回真
- [-d $var]:如果给定的变量包含的是目录,则返回真
- [-e $var]:如果给定的变量包含的文件存在,则返回真
- [-c $var]:如果给定的变量包含的是一个字符设备文件的路径,则返回真
- [-b $var]:如果给定的变量包含的是一个块设备文件的路径,则返回真
- [-w $var]:如果给定变量包含的文件可写,则返回真
- [-r $var]:如果给定的变量包含的文件可读,则返回真
- [-L $var]:如果给定的变量包含的是一个符号链接,则返回真
字符串比较
测试空串
[[ -z $str1 ]]:如果str1为空串,则返回真
[[ -n $str1 ]]:如果str1不为空串,则返回真
脚本参数访问
传入脚本的参数可以通过下列形式访问
- $0是脚本名称
- $1是第一个参数
- $2是第二个参数
- $n是第n个参数
脚本解析
文件概览
脚本的名字叫做build_uboot.sh,编译脚本是用来处理文件的,所以在开始介绍之前,我们还是先来看看有哪些文件,文件的组织结构是怎样的
下面是这个脚本所能涉及到的最高层目录
我们可以看到一共有五个文件,其中iTop4412_Kernel_3.0和它的压缩包暂时不用看,这是后面的LINUX内核才用到的。我们这里只需要关注剩下的三个文件夹,由于我们的板子是确定的,所以其中的CodeSign4SecureBoot_POP文件夹也不用考虑了,最终,我们只需要关注CodeSign4SecureBoot_SCP文件夹和iTop4412_uboot文件夹,我们先来看看CodeSign4SecureBoot_SCP文件夹
- a1100_padding.bin:第一个a1100_padding.bin是全零补全文件,根据我上一篇文章4412启动流程分析,我们可以知道每个文件的部分的引导代码占用的空间是固定的,但是有时候我们写的代码又没那么多,还剩一些空间,这些空间就需要这些padding来补全。
- bl2.bin:这是BL2的二进制文件
- codesigner_v21:是用来生成私钥和公钥的
- Exynos4412_V21.prv:私钥
- Exynos4412_V21.spk:公钥
- paddingaa:暂时不管
- tzsw_SMDK4412_SCP_2GB.bin:TZSW文件,暂时不管
- E4412_N.bl1.SCP2G.bin:BL2
这个文件夹主要是用来提供BL1、BL2、a1100_padding.bin以及TZSW的。
下面我们进入iTop4412_uboot文件夹
文件有点多,里面包含了u-boot的源文件,这个文件夹是用来生成u-boot.bin的,最终由BL1、BL2、TZSW以及u-boot.bin合成的文件也在这里,也就是图中的u-boot-iTOP-4412.bin,我们今天的主角build_uboot.sh也在这个目录里。文件我们就不在这里一一列举作用了,如果想看作用的,可以去看这个讯为的官方u-boot教程。
脚本解析
下面我们就进入今天的正题,开始探究build_uboot.sh。
这个文件一共有142行,我们来逐行观察
1~10行
#!/bin/sh
if [ -z $1 ]
then
echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
echo "Please use correct make config.for example make SCP_1GDDR for SCP 1G DDR CoreBoard linux,android OS"
echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
exit 0
fi
第一行用来指定执行器是/bin/sh,第4行到最后,进行了一个判断,如果传入的第一个参数为空,那么就输出一些错误提示,然后结束
12~29行
if [ "$1" = "SCP_1GDDR" ] || [ "$1" = "SCP_2GDDR" ] || [ "$1" = "SCP_1GDDR_Ubuntu" ] || [ "$1" = "SCP_2GDDR_Ubuntu" ]
then
sec_path="../CodeSign4SecureBoot_SCP/"
CoreBoard_type="SCP"
elif [ "$1" = "POP_1GDDR" ] || [ "$1" = "POP_1GDDR_Ubuntu" ]
then
sec_path="../CodeSign4SecureBoot_POP/"
CoreBoard_type="POP"
elif [ "$1" = "POP_2GDDR" ] || [ "$1" = "POP_2GDDR_Ubuntu" ]
then
sec_path="../CodeSign4SecureBoot_POP/"
CoreBoard_type="POP2G"
else
echo "make config error,please use correct params......"
exit 0
fi
连续几个if-elif用来判断传入的参数是什么,也就是确定我们需要为哪一块板子编译u-boot,然后根据板子的类型来设定文件夹变量以及板子类型变量。
32~34行
CPU_JOB_NUM=$(grep processor /proc/cpuinfo | awk '{field=$NF};END{print field+1}')
ROOT_DIR=$(pwd)
CUR_DIR=${ROOT_DIR##*/}
第一行用来确定CPU的核数,也就是我们在虚拟机中设置的CPU核数,第二行用来设定根文件夹,用来设定当前目录等于根目录
38~44行
#clean
make distclean # 删除由./configure产生的文件
#rm link file
#${}是用来进行变量名替换的,加上{}比较精确,这里的意思是删除掉这两个文件
rm ${ROOT_DIR}/board/samsung/smdkc210/lowlevel_init.S
rm ${ROOT_DIR}/cpu/arm_cortexa9/s5pc210/cpu_init.S
47~142
这是一个大的case结构,我们要拆开来看,首先看48~51
clean)
echo make clean
make mrproper
;;
如果参数1为clean,那么就执行下面的两条指令
再看54~60
if [ ! -d $sec_path ]
then
echo "**********************************************"
echo "[ERR]please get the CodeSign4SecureBoot first"
echo "**********************************************"
return
fi
如果sec_path不是一个目录,打印出错信息,退出
62~93行
if [ "$1" = "SCP_1GDDR" ]
then
make itop_4412_android_config_scp_1GDDR
elif [ "$1" = "SCP_2GDDR" ]
then
make itop_4412_android_config_scp_2GDDR
elif [ "$1" = "POP_1GDDR" ]
then
make itop_4412_android_config_pop_1GDDR
elif [ "$1" = "POP_2GDDR" ]
then
make itop_4412_android_config_pop_2GDDR
elif [ "$1" = "SCP_1GDDR_Ubuntu" ]
then
make itop_4412_ubuntu_config_scp_1GDDR
elif [ "$1" = "SCP_2GDDR_Ubuntu" ]
then
make itop_4412_ubuntu_config_scp_2GDDR
elif [ "$1" = "POP_1GDDR_Ubuntu" ]
then
make itop_4412_ubuntu_config_pop_1GDDR
elif [ "$1" = "POP_2GDDR_Ubuntu" ]
then
make itop_4412_ubuntu_config_pop_2GDDR
fi
通过参数来确定编译哪一种u-boot.bin
95
make -j$CPU_JOB_NUM
多核并行编译
97~103
if [ ! -f checksum_bl2_14k.bin ]
then
echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
echo "There are some error(s) while building uboot, please use command make to check."
echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
exit 0
fi
如果没有checksum_bl2_14k.bin这个文件,则给出错误提示,退出
105~109
cp -rf checksum_bl2_14k.bin $sec_path
cp -rf u-boot.bin $sec_path
rm checksum_bl2_14k.bin
cd $sec_path
将checksum_bl2_14k.bin和u-boot.bin复制到sec_path,删除checksum_bl2_14k.bin并跳转到sec_path
116~130
if [ "$CoreBoard_type" = "SCP" ]
then
cat E4412_N.bl1.SCP2G.bin bl2.bin all00_padding.bin u-boot.bin tzsw_SMDK4412_SCP_2GB.bin > u-boot-iTOP-4412.bin
elif [ "$CoreBoard_type" = "POP" ]
then
cat E4412.S.BL1.SSCR.EVT1.1.bin E4412.BL2.TZ.SSCR.EVT1.1.bin all00_padding.bin u-boot.bin E4412.TZ.SSCR.EVT1.1.bin > u-boot-iTOP-4412.bin
elif [ "$CoreBoard_type" = "POP2G" ]
then
cat bl2.bin u-boot.bin E4412.TZ.SSCR.EVT1.1.bin > u-boot-iTOP-4412.bin
else
echo "make uboot image error......"
fi
将BL1、BL2、padding、u-boot.bin、tzsw_SMDK4412_SCP_2GB.bin合在一起最终形成完整的uboot镜像u-boot-iTOP-4412.bin
132~142
mv u-boot-iTOP-4412.bin $ROOT_DIR
rm checksum_bl2_14k.bin
#rm BL2.bin.signed.4412
rm u-boot.bin
echo
echo
;;
esac
将u-boot-iTOP-4412.bin移动到uboot的根目录下,将sec_path下面的checksum_bl2_14k.bin以及u-boot.bin移除。esac是case的结束符。
脚本总结
整个脚本的核心功能主要是两个部分,一是编译得到u-boot.bin,二是将BL1、BL2、u-boot.bin、以及TZSW组织到一起最终形成完整的uboot烧写镜像u-boot-iTOP-4412.bin。
如有不对之处请指正,感谢!
stay foolish, stay hungry