1.制作SD系统启动卡
首先需要将SD卡进行分区,然后将相应的程序和文件拷贝到对应的位置,上一篇文章SD卡启动与uboot 、zImage、dtb、rootfs固化已经详细介绍了,接下来重点介绍i如何通过mx6mksdboot.sh脚本文件完成所有的分区和拷贝的工作
#! /bin/sh
#I.MX6 SD卡启动系统烧写脚本
#版本v1.0
#打印用法
usage ()
{
echo "
用法示例:
sudo ./imx6mksdboot.sh /dev/sdb
"
exit 1
}
#Uboot默认值
Uboot='u-boot.imx'
#execute执行语句成功与否打印
execute ()
{
$* >/dev/null
if [ $? -ne 0 ]; then
echo
echo "错误: 执行 $*"
echo
exit 1
fi
}
#参数判断 sudo ./imx6mksdboot.sh /dev/sdb
if [ $# -ne 1 ];then
usage
fi
#块设备判断
device=$1
test -z $device && usage
#测试制卡包当前目录下是否缺失制卡所需要的文件
sdkdir=$PWD
if [ ! -d $sdkdir ]; then
echo "错误: $sdkdir目录不存在"
exit 1
fi
if [ ! -f $sdkdir/filesystem/*.tar.* ]; then
echo "错误: $sdkdir/filesystem/下找不到文件系统压缩包"
exit 1
fi
if [ ! -f $sdkdir/boot/zImage ]; then
echo "错误: $sdkdir/boot/下找不到zImage"
exit 1
fi
#判断选择的块设备是否存在及是否是一个块设备
if [ ! -b $device ]; then
echo "错误: $device 不是一个块设备文件"
exit 1
fi
#这里防止选错设备,否则会影响Ubuntu系统的启动
if [ $device = '/dev/sda' ];then
echo "请不要选择sda设备,/dev/sda通常是您的Ubuntu硬盘!
继续操作你的系统将会受到影响!脚本已自动退出"
exit 1
fi
echo "即将进行制作SD系统启动卡,大约花费几分钟时间,请耐心等待!"
echo "************************************************************"
echo "* 注意:这将会清除$device所有的数据 *"
echo "* 在脚本执行时请不要将$device拔出 *"
echo "* 请按<Enter>确认继续 *"
echo "************************************************************"
read enter
#格式化前要卸载
for i in `ls -1 $device?`; do
echo "卸载 device '$i'"
umount $i 2>/dev/null
done
#执行格式化$device
execute "dd if=/dev/zero of=$device bs=1024 count=1024"
#第一个分区为64M用来存放设备树与内核镜像文件,因为设备树与内核都比较小,不需要太大的空间
#第二个分区为SD卡的总大小-64M,用来存放文件系统
cat << END | fdisk -H 255 -S 63 $device
n
p
1
+64M
n
p
2
t
1
c
a
1
w
END
#两个分区处理
PARTITION1=${device}1
PARTITION2=${device}2
#第一个分区创建为Fat32格式
echo "格式化 ${PARTITION1} ..."
if [ -b ${PARTITION1} ]; then
mkfs.vfat -F 32 -n "boot" ${PARTITION1}
else
echo "错误: /dev下找不到 SD卡 boot分区"
fi
#第二个分区创建为ext4格式
echo "格式化${PARTITION2} ..."
if [ -b ${PARITION2} ]; then
mkfs.ext4 -F -L "rootfs" ${PARTITION2}
else
echo "错误: /dev下找不到 SD卡 rootfs分区"
fi
while [ ! -e $device ]
do
sleep 1
echo "wait for $device appear"
done
echo "正在烧写${Uboot}到${device}"
execute "dd if=$sdkdir/boot/$Uboot of=$device bs=1024 seek=1 conv=fsync"
sync
echo "烧写${Uboot}到${device}完成!"
#创建分区的挂载目录,目录已进程ID命名
if [ ! -e "/tmp/sdk/$$" ];then
execute "mkdir -p /tmp/sdk/$$"
fi
echo "正在准备复制..."
echo "正在复制设备树与内核到${PARTITION1},请稍候..."
execute "mount ${PARTITION1} /tmp/sdk/$$"
execute "cp -r $sdkdir/boot/*${flash}*.dtb /tmp/sdk/$$/"
execute "cp -r $sdkdir/boot/zImage /tmp/sdk/$$/"
#execute "cp $sdkdir/boot/alientek.bmp /tmp/sdk/$$/"
execute "cp $sdkdir/boot/$Uboot /tmp/sdk/$$/"
sync
echo "复制设备树与内核到${PARTITION1}完成!"
echo "卸载${PARTITION1}"
execute "umount /tmp/sdk/$$"
sleep 1
#解压文件系统到文件系统分区
#挂载文件系统分区
execute "mount ${PARTITION2} /tmp/sdk/$$"
echo "正在解压文件系统到${PARTITION2} ,请稍候..."
rootfs=`ls -1 filesystem/*.tar.*`
execute "tar jxfm $rootfs -C /tmp/sdk/$$"
execute "cp $sdkdir/imx6mkemmcboot.sh /tmp/sdk/$$/"
sync
echo "解压文件系统到${PARTITION2}完成!"
#判断是否存在这个目录,如果不存在就为文件系统创建一个modules目录
if [ ! -e "/tmp/sdk/$$/lib/modules/" ];then
mkdir -p /tmp/sdk/$$/lib/modules/
fi
echo "正在解压模块到${PARTITION2}/lib/modules/ ,请稍候..."
modules=`ls -1 modules/*.tar.*`
execute "tar jxfm $modules -C /tmp/sdk/$$/lib/modules/"
sync
echo "解压模块到${PARTITION2}/lib/modules/完成!"
echo "卸载${PARTITION2}"
execute "umount /tmp/sdk/$$"
execute "rm -rf /tmp/sdk/$$"
sync
echo "SD卡启动系统烧写完成!"
执行imx6mksdboot.sh脚本的目录结构如下
boot文件夹是存在uboot zImage dtb
filesystem文件夹是存放根文件系统,目前脚本里边是仅支持tar.bz2方式压缩的根文件系统,其它格式需要改一下脚本
modules文件夹是存放用户自己打包的驱动
脚本执行流程分析
1.判断用法 sudo ./imx6mksdboot.sh /dev/sdxx
sdxx是SD卡的设备节点,用户根据实际情况来选择
2.判断用户传进来的参数/dev/sdxx是否是块设备文件
3.判断制卡包的目录结构和制卡所需的文件是否完整
4.提示用户SD系统启动卡制作即将开始,并等待用户按回车确认
5.格式化SD卡前先卸载所有的分区,然后用fdisk命令创建boot和rootfs分区
6.使用dd命令烧录uboot到SD卡第二个扇区开始的地方
7.挂载SD卡的boolt分区,并将uboot zImage dtb文件拷贝到SD卡的boot分区
8.挂载SD卡的rootfs分区,并将文件系统压缩包解压到SD卡的rootfs分区,同时拷贝imx6mkemmcboot.sh脚本到根文件系统下的根目录,linux内核跑起来后,将程序从SD卡固化到内部emmc的时候需要该脚本
9.判断上一步解压后的根文件系统是否存在/lib/modules/目录,如果没有则创建目录,然后将模块的压缩包解压置该目录下
10.解挂SD卡,系统启动卡烧录完成
需要注意的是根文件系统中必须mkfs.ext4命令和mmc命令,否则执行imx6mkemmcboot.sh的时候无法对内部emmc进行分区和格式化
buildroot构建根文件系统默认是没有mkfs.ext4命令的,需要手动配置如下:
2.固化程序
固化是指将uboot zImage rootfs从SD卡固化到内部emmc。imx6mkemmcboot.sh脚本代码如下
#!/bin/sh
#I.MX6 eMMC启动系统烧写脚本
#版本v1.0
#Uboot默认值
Uboot='u-boot.imx'
#sd卡块设备
sd_blk='mmcblk0'
sd_device="/dev/${sd_blk}"
#mmc块设备
mmc_blk='mmcblk1'
mmc_device="/dev/${mmc_blk}"
#execute执行语句成功与否打印
execute ()
{
$* >/dev/null
if [ $? -ne 0 ]; then
echo
echo "错误: 执行 $*"
echo
exit 1
fi
}
#检查sd卡是否插入
if [ ! -e ${sd_device} ];then
echo \"${sd_device}不存在...\"
exit 1
fi
if [ ! -e ${mmc_device} ];then
echo \"${mmc_device}不存在...\"
exit 1
fi
#分区前要卸载
for i in `ls -1 ${mmc_device}p?`; do
echo "卸载 device '$i'"
umount $i 2>/dev/null
done
#清空${mmc_device}
execute "dd if=/dev/zero of=${mmc_device} bs=1024 count=1024"
#第一个分区为32M用来存放设备树与内核镜像文件,因为设备树与内核都比较小,不需要太大的空间
#第二个分区为eMMC的总大小-32M,用来存放文件系统
cat << END | fdisk -H 255 -S 63 ${mmc_device}
n
p
1
+32M
n
p
2
t
1
c
a
1
w
END
sleep 3
#上面分区后系统会自动挂载,所以这里再一次卸载
for i in `ls -1 ${mmc_device}p?`; do
echo "卸载 device '$i'"
umount $i 2>/dev/null
done
#两个分区处理
PARTITION1=${mmc_device}p1
PARTITION2=${mmc_device}p2
#第一个分区创建为Fat32格式
echo "Formating ${PARTITION1} ..."
if [ -b ${PARTITION1} ]; then
mkfs.vfat -F 32 -n "boot" ${PARTITION1}
else
echo "错误: /dev下找不到 eMMC boot分区"
fi
#第二个分区创建为ext4格式
echo "格式化${PARTITION2} ..."
if [ -b ${PARITION2} ]; then
mkfs.ext4 -F -L "rootfs" ${PARTITION2}
else
echo "错误: /dev下找不到 eMMC rootfs分区"
fi
#这是各个分区的名字,不包括路径
SD_PARTITION1_NAME=${sd_blk}p1
SD_PARTITION2_NAME=${sd_blk}p2
MMC_PARTITION1_NAME=${mmc_blk}p1
MMC_PARTITION2_NAME=${mmc_blk}p2
#创建SD卡和emmc分区的挂载目录,并挂载
if [ ! -e "/tmp/${SD_PARTITION1_NAME}" ];then
execute "mkdir -p /tmp/${SD_PARTITION1_NAME}"
fi
if [ ! -e "/tmp/${SD_PARTITION2_NAME}" ];then
execute "mkdir -p /tmp/${SD_PARTITION2_NAME}"
fi
if [ ! -e "/tmp/${MMC_PARTITION1_NAME}" ];then
execute "mkdir -p /tmp/${MMC_PARTITION1_NAME}"
fi
if [ ! -e "/tmp/${MMC_PARTITION2_NAME}" ];then
execute "mkdir -p /tmp/${MMC_PARTITION2_NAME}"
fi
echo "挂载${SD_PARTITION1_NAME}"
execute "mount /dev/${SD_PARTITION1_NAME} /tmp/${SD_PARTITION1_NAME}"
echo "挂载${SD_PARTITION2_NAME}"
execute "mount /dev/${SD_PARTITION2_NAME} /tmp/${SD_PARTITION2_NAME}"
echo "挂载${MMC_PARTITION1_NAME}"
execute "mount /dev/${MMC_PARTITION1_NAME} /tmp/${MMC_PARTITION1_NAME}"
echo "挂载${MMC_PARTITION2_NAME}"
execute "mount /dev/${MMC_PARTITION2_NAME} /tmp/${MMC_PARTITION2_NAME}"
#烧写u-boot.imx到emmc boot0分区
echo "正在烧写${Uboot}到${mmc_device}"
#烧写前,先使能mmcblk1boot0
echo 0 > /sys/block/${mmc_blk}boot0/force_ro
execute "dd if=/tmp/${SD_PARTITION1_NAME}/$Uboot of=${mmc_device}boot0 bs=1024 seek=1 conv=fsync"
execute "dd if=/tmp/${SD_PARTITION1_NAME}/$Uboot of=${mmc_device}boot0 bs=1024 seek=500 conv=fsync"
echo 1 >/sys/block/${mmc_blk}boot0/force_ro
#烧写内核与设备树到 emmc mmcblk1p1
echo "正在准备复制..."
echo "正在复制设备树与内核到${PARTITION1},请稍候..."
execute "cp -r tmp/${SD_PARTITION1_NAME}/*emmc*.dtb /tmp/${MMC_PARTITION1_NAME}/"
execute "cp -r tmp/${SD_PARTITION1_NAME}/zImage /tmp/${MMC_PARTITION1_NAME}/"
sync
echo "复制设备树与内核到${PARTITION1}完成!"
#复制文件系统到 emmc mmcblk1p2
echo "正在复制文件系统到${PARTITION2},请稍候..."
execute "rm /tmp/${MMC_PARTITION2_NAME}/* -rf"
execute "cp /tmp/${SD_PARTITION2_NAME}/* -a /tmp/${MMC_PARTITION2_NAME}/"
sync
echo "复制文件系统到${PARTITION2}完成!"
echo "卸载${SD_PARTITION1_NAME}"
execute "umount /tmp/${SD_PARTITION1_NAME}"
echo "卸载${SD_PARTITION2_NAME}"
execute "umount /tmp/${SD_PARTITION2_NAME}"
echo "卸载${MMC_PARTITION1_NAME}"
execute "umount /tmp/${MMC_PARTITION1_NAME}"
echo "卸载${MMC_PARTITION2_NAME}"
execute "umount /tmp/${MMC_PARTITION2_NAME}"
execute "rm -rf /tmp/${SD_PARTITION1_NAME}"
execute "rm -rf /tmp/${SD_PARTITION2_NAME}"
execute "rm -rf /tmp/${MMC_PARTITION1_NAME}"
execute "rm -rf /tmp/${MMC_PARTITION2_NAME}"
#使能启动分区
execute "mmc bootpart enable 1 1 ${mmc_device}"
sync
echo "eMMC启动系统烧写完成!"
脚本分析如下:
1.检查SD卡和EMMC的设备节点是否存在
2.清空内部emmc并创建boot和rootfs分区
3.挂载sd和和emmc各分区
4.烧写u-boot.imx到emmc boot0分区,烧写前,先使能mmcblk1boot0
5.复制内核与设备树文件到 emmc mmcblk1p1
6.复制文件系统到 emmc mmcblk1p2
7.使能启动分区
测试文件已上传到https://download.csdn.net/download/qq_24330911/87020397