替代imx6ull mfgtool的方法
1. 背景
用mfgtool烧写imx6ull非常麻烦,要在windows下操作,每次也要等很久,我的使用场景就是两种:
第一种: 将boot/dtb/zImage/rootfs烧到一张sd卡,用sd卡启动(最方便,ubuntu PC操作)
第二种: 在sd卡启动的系统上,将镜像全部烧写到emmc(需要利用单板烧写)
2. 解题方法
因为NXP提供的烧写工具mfgtool就可以将准备好的上述镜像文件烧写到emmc或者sd卡中,而且mfgtool的原理是先下载并启动一个制作好的linux(ramfs), 再利用这个linux去烧写emmc或者sd卡。既然都是linux系统,我完全可以参考mfgtool的实现,在自己的ubuntu上实现sd卡的烧写,节省时间
参考ucl2.xml的流程:
3. 烧写脚本使用方法
@如果在ubuntu PC上烧写,需要看好你的sd卡是/dev/sdx,不要烧到了ubuntu本身的硬盘,并且需要注意的是要禁用ubuntu系统自己身的自动挂载功能,否则在脚本的磁盘操作中要告警:
ubuntu系统的磁盘自动挂载功能是由udisks2.service做的,如果你的系统会自动挂载U盘,不妨使用systemctl status udisks2.service看看日志就知道自动挂载是不是它干的,那么怎么禁用它呢?
参考: udisks - ArchWiki (archlinux.org)
自己写一个规则然后systemctl restart systemd-udevd来生效,比如我自己的系统上:
@如果在imx6ull上烧写emmc,也要禁用系统的自动挂载用能,比如我的单板上的自动挂载功能如下, 禁用即可
烧写过程截图:
ubuntu PC烧写:
imx6ull单板烧写:
4. 脚本代码
#!/bin/bash
# this script used to burn uboot/dtb/kernel/rootfs on sd card or emmc
readonly EMMC=/dev/mmcblk1
readonly EMMC_BOOT0=mmcblk1boot0
readonly EMMC_BOOT1=mmcblk1boot1
# create partition
function create_partition() {
# partition size in MB
local BOOT_ROM_SIZE=10
# wait for the SD/MMC device node ready
while [ ! -e "$1" ]
do
sleep 1
echo "[DEBUG]wait for $1 appear"
done
# call sfdisk to create partition table
# destroy the partition table
local node=$1
dd if=/dev/zero of="$1" bs=1024 count=1 conv=fsync
# two partitions:
# part1: boot: 10M~138M: zImage & dtb
# part2: rootfs: 138M~end: rootfs
#^-- SC1039: Use <<- instead of << if you want to indent the end token.
#^-- SC1040: When using <<-, you can only indent with tabs.
sfdisk --force "${node}" <<- PARTINFO
${BOOT_ROM_SIZE}M,128M,c
138M,,83
write
PARTINFO
#keep the name of BOOT_DEVICE
BOOT_DEVICE=$1
BOOT_PART=1
ROOTFS_PART=2
if [ "${BOOT_MEDIA}" = "${EMMC}" ]
then
BOOT_DEVICE=${EMMC}
BOOT_PART=p1
ROOTFS_PART=p2
fi
}
# burn uboot
function burn_uboot() {
# clear uboot env
dd if=/dev/zero of=${BOOT_DEVICE} bs=1k seek=768 count=8 conv=fsync
# burn uboot
if [ "${BOOT_DEVICE}" = "${EMMC}" ]
then
echo 0 > /sys/block/${EMMC_BOOT0}/force_ro
dd if="$1" of=${BOOT_DEVICE}boot0 bs=512 seek=2 conv=fsync
echo 1 > /sys/block/${EMMC_BOOT0}/force_ro
mmc bootpart enable 1 1 ${BOOT_DEVICE} #default boot0
else
dd if="$1" of=${BOOT_DEVICE} bs=1k seek=1 conv=fsync
fi
}
# burn boot part
function burn_bootpart() {
while [ ! -e "${BOOT_DEVICE}${BOOT_PART}" ]
do
echo "[debug]waiting bootpart...1"
sleep 1
done
# format to FAT32
mkfs.vfat -F 32 -n boot ${BOOT_DEVICE}${BOOT_PART}
#while [ ! -e "${BOOT_DEVICE}${BOOT_PART}" ]
#do
#echo "[debug]waiting bootpart...2"
#sleep 1
#done
mkdir -p /mnt/mmcblk0p1
mount -t vfat ${BOOT_DEVICE}${BOOT_PART} /mnt/mmcblk0p1
cp "$1" /mnt/mmcblk0p1 #dtb
cp "$2" /mnt/mmcblk0p1 #zImage
sleep 3
sync
umount /mnt/mmcblk0p1
sleep 1
rm -rf /mnt/mmcblk0p1
sync
}
# burn rootfs
function burn_rootfs() {
while [ ! -e "${BOOT_DEVICE}${ROOTFS_PART}" ]
do
echo "[debug]waiting rootfspart...1"
sleep 1
done
# format to ext3
mkfs.ext3 -F -j -L rootfs "${BOOT_DEVICE}${ROOTFS_PART}"
while [ ! -e "${BOOT_DEVICE}${ROOTFS_PART}" ]
do
echo "[debug]waiting rootfspart...2"
sleep 1
done
mkdir -p /mnt/mmcblk0p2
mount -t ext3 "${BOOT_DEVICE}${ROOTFS_PART}" /mnt/mmcblk0p2
echo "[DEBUG]buring rootfs......"
tar -jxf "$1" -C /mnt/mmcblk0p2 #rootfs.tar.bz2
sleep 1
tar -jxf "$2" -C /mnt/mmcblk0p2/lib/modules #modules.tar.bz2
sleep 1
sync
sleep 3
umount /mnt/mmcblk0p2
sleep 1
rm -rf /mnt/mmcblk0p2
sync
}
function usage() {
echo "#################################################################################################################"
echo "# Usage: ./burn_sdcard.sh <path> <uboot-name> <dtb-name> <zImage-name> <rootfs-name> <modules-name> <BOOT_MEDIA>#"
echo "# Instruction : burn <your files locations> <your files> <to where> #"
echo "# Sd card Example: ./burn_sdcard.sh . uboot.imx dtb zImage rootfs.tar.bz2 modules.tar.bz2 /dev/sda #"
echo "# Emmc Example: ./burn_sdcard.sh . uboot.imx dtb zImage rootfs.tar.bz2 modules.tar.bz2 /dev/mmcblk1 #"
echo "#################################################################################################################"
exit 0
}
#======main======
if [ $# -ne 7 ]
then
usage
fi
readonly ABSOLUTE_PATH=$1
readonly UBOOT_IMG=${ABSOLUTE_PATH}/$2
readonly DTB=${ABSOLUTE_PATH}/$3
readonly ZIMAGE=${ABSOLUTE_PATH}/$4
readonly ROOTFS=${ABSOLUTE_PATH}/$5
readonly MODULES=${ABSOLUTE_PATH}/$6
readonly BOOT_MEDIA=$7 #/dev/sda | /dev/mmcblk1
#check exist? no here
echo "[DEBUG]burning......"
create_partition "${BOOT_MEDIA}"
burn_uboot "${UBOOT_IMG}"
echo "@@@@@@@@@@@@@@@@@@@@"
echo "checkcheckcheckcheck"
ls -la ${BOOT_MEDIA}*
echo "@@@@@@@@@@@@@@@@@@@@"
burn_bootpart "${DTB}" "${ZIMAGE}"
burn_rootfs "${ROOTFS}" "${MODULES}"
wait
echo "[DEBUG]burn ${BOOT_MEDIA} complete!"
5. 参考资料
1). ubuntu-debian怎么禁用自动挂载:
udisks - ArchWiki (archlinux.org)
2). shell脚本进入subshell场景分析
进入子shell的各种情况分析_什么情况下会进入子shell、-CSDN博客
3). dd命令的conv=fsync oflag=dsync/sync
dd命令的conv=fsync,oflag=sync/dsync_oflag=dsync-CSDN博客
最后,有个大佬跟我说自己写shell脚本可以用工具shellcheck去检查一下,apt update;apt install shell check;就可以使用了,当然这个脚本我没有使用,有不对的地方日后来改或者你给我留言