MfgTools工具目录
MfgTool工具是一个NXP提供的OTG烧录工具,工具主目录主要由以下文件组成:
Profiles/目录:
(一)ProfilesLinuxOS Firmwarefiles中,存储着将要烧写到存储介质(启动介质)的目标镜像(uboot、内核、文件系统、设备树等)
(二)ProfilesLinuxOS Firmwarefirmware中,存储着引导烧写的镜像(uboot、内核、ramfs文件系统、设备树)
(三)ProfilesLinuxOS Firmware中,存储着ucl2.xml脚本和mksdcard.sh.tar分区脚本。
mx6ull-4gemmc-512mddr-qt5.6.vbs主要用于启动MfgTool2.exe程序,并向其传递配置参数,MfgTool2.exe程序会根据这些参数执行ProfilesLinuxOS Firmwareucl2.xml中的命令。
MfgTool工具工作过程
MfgTool工具工作过程主要分以下几个步骤:
(一)拨码无误,开发板上电之后,首先boot ROM(SOC内部code,boot ROM具体作用在以后章节会进一步讲解)开始运行,对USB外设进行初始化,并将开发板枚举成HID设备。
(二)Mfgtool工具检测到此HID设备,并与之建立连接。然后Mfgtool工具会解析Firmware目录下uboot,并使用uboot中的内存配置信息对开发板DDR进行初始化配置。
(三)DDR内存初始化完成之后,Mfgtool工具就会按照mfgtoolsProfilesLinuxOS Firmwareucl2.xml脚本中的命令将mfgtoolsProfilesLinuxOS Firmwarefirmware目录下uboot镜像、内核镜像、设备树以及ramfs加载到DDR内存中指定地址,然后发送指令给boot ROM,跳转到DDR内存的uboot入口地址,执行uboot,uboot进而启动内核,内核挂载ramfs文件系统。
(四)系统启动之后,会枚举USB作为一个MSC设备,此时SoC可以和主机进行高速数据传输。
(五)然后,Mfgtool会逐一执行mfgtoolsProfilesLinuxOS Firmwareucl2.xml脚本中的命令,将mfgtoolsProfilesLinuxOS Firmwarefiles目录下的uboot、内核镜像、设备树文件、文件系统等逐一烧写到存储介质(启动介质)中。
ucl2.xml文件讲解
xml文件中会根据不同的板卡类型,选择不同的LIST,主要讲解EMMC版本的烧录流程:
(一)将引导镜像加载到DDR
在文件中查找<LIST name="eMMC" desc="Choose eMMC as media">
<LIST name="eMMC" desc="Choose eMMC as media">
<CMD state="BootStrap" type="boot" body="BootStrap" file ="firmware/u-boot-imx6ul%lite%%6uluboot%_emmc.imx" ifdev="MX6ULL">Loading U-boot</CMD>
<CMD state="BootStrap" type="load" file="firmware/zImage_emmc" address="0x80800000"
loadSection="OTH" setSection="OTH" HasFlashHeader="FALSE" ifdev="MX6SL MX6SX MX7D MX6UL MX6ULL">Loading Kernel.</CMD>
<CMD state="BootStrap" type="load" file="firmware/%initramfs%" address="0x83800000"
loadSection="OTH" setSection="OTH" HasFlashHeader="FALSE" ifdev="MX6SL MX6SX MX7D MX6UL MX6ULL">Loading Initramfs.</CMD>
<CMD state="BootStrap" type="load" file="firmware/zImage-imx6ul%lite%-%6uldtb%-emmc.dtb" address="0x83000000"
loadSection="OTH" setSection="OTH" HasFlashHeader="FALSE" ifdev="MX6ULL">Loading device tree.</CMD>
<CMD state="BootStrap" type="jump" > Jumping to OS image. </CMD>
可以看到先是加载了ProfilesLinuxOS Firmwarefirmware目录下的u-boot-imx6ul%lite%%6uluboot%_emmc.imx也就是固件下的u-boot-imx6ull14x14evk_emmc.imx文件。
这两个名称是如何定义的呢?在mfgtoos的根目录下的mx6ull-4gemmc-512mddr-qt5.6.vbs和cfg.ini文件中有相关定义,可以右键使用文本格式打开这两个文件进行查看。
cfg.ini文件如下:
[profiles]
chip = Linux
[platform]
board = SabreSD
[LIST]
name = SDCard
[variable]
board = sabresd
mmc = 0
sxuboot=sabresd
sxdtb=sdb
7duboot=sabresd
7ddtb=sdb
6uluboot=14x14ddr3arm2
6uldtb=14x14-ddr3-arm2
6ulldtb=14x14-ddr3-arm2
ldo=
plus=
lite=l
initramfs=fsl-image-mfgtool-initramfs-imx_mfgtools.cpio.gz.u-boot
seek = 1
sxnor=qspi2
7dnor=qspi1
6ulnor=qspi1
nor_part=0
可以看到,lite=l,6uluboot=14x14ddr3arm2,lite的定义没问题是l,但是6uluboot的定义也不是14x14evk呀,别着急看下一个文件。
mx6ull-8gemmc-512mddr-qt5.6.vbs:
Set wshShell = CreateObject("WScript.shell")
wshShell.run "mfgtool2.exe -c ""linux"" -l ""eMMC"" -s ""board=sabresd"" -s ""mmc=1"" -s ""6uluboot=14x14evk"" -s ""6uldtb=14x14-evk"""
Set wshShell = Nothing
能看到这里又重新定义了6uluboot的名称,在ucl2.xml文件中使用%lite%和%6uluboot%来引用这两个变量。所以u-boot-imx6ul%lite%%6uluboot%_emmc.imx就是u-boot-imx6ull14x14evk_emmc.imx文件。
这样芯片就会自动解析uboot然后对DDR进行初始化,引导固件中的uboot就开始运行了。
接下来就是将ProfilesLinuxOS Firmwarefirmware目录下的zImage_emmc加载到DDR的“0x80800000”地址,命令如下:
<CMD state="BootStrap" type="load" file="firmware/zImage_emmc" address="0x80800000"
loadSection="OTH" setSection="OTH" HasFlashHeader="FALSE" ifdev="MX6SL MX6SX MX7D MX6UL MX6ULL">Loading Kernel.</CMD>
然后是加载虚拟文件系统,将ProfilesLinuxOS Firmwarefirmware目录下的fsl-image-mfgtool-initramfs-imx_mfgtools.cpio.gz.u-boot加载到DDR的“0x83800000”,%initramfs%的定义在上文的cfg.ini文件中可以找到。这个虚拟文件系统又叫rmadisk,是将内存的一块地址虚拟成硬盘来使用,断电后是不会保存的。
<CMD state="BootStrap" type="load" file="firmware/%initramfs%" address="0x83800000"
loadSection="OTH" setSection="OTH" HasFlashHeader="FALSE" ifdev="MX6SL MX6SX MX7D MX6UL MX6ULL">Loading Initramfs.</CMD>
然后加载设备树文件,将ProfilesLinuxOS Firmwarefirmware目录下的zImage-imx6ull-14x14-evk-emmc.dtb加载到DDR的“0x83000000”,最后jump命令跳转到虚拟文件系统中。
<CMD state="BootStrap" type="load" file="firmware/zImage-imx6ul%lite%-%6uldtb%-emmc.dtb" address="0x83000000"
loadSection="OTH" setSection="OTH" HasFlashHeader="FALSE" ifdev="MX6ULL">Loading device tree.</CMD>
<CMD state="BootStrap" type="jump" > Jumping to OS image. </CMD>
(二)EMMC分区,进入到虚拟文件系统后就可以对EMMC进行分区了。
先是将ProfilesLinuxOS Firmware下的mksdcard.sh.tar包发送到了虚拟文件系统中。
<!-- create partition -->
<CMD state="Updater" type="push" body="send" file="mksdcard.sh.tar">Sending partition shell</CMD>
然后使用tar命令将压缩包解压:
<CMD state="Updater" type="push" body="$ tar xf $FILE "> Partitioning...</CMD>
最后执行mksdcard.sh对mmcblk1进行格式化和分区操作。%mmc%在上文中的mx6ull-8gemmc-512mddr-qt5.6.vbs文件中有定义。
<CMD state="Updater" type="push" body="$ sh mksdcard.sh /dev/mmcblk%mmc%"> Partitioning...</CMD>
接下来看一下mksdcard.sh中是如何进行格式化和分区的,在windows上解压mksdcard.sh.tar并打开mksdcard.sh脚本:
#!/bin/sh
# partition size in MB
BOOT_ROM_SIZE=10
# wait for the SD/MMC device node ready
while [ ! -e $1 ]
do
sleep 1
echo “wait for $1 appear”
done
# call sfdisk to create partition table
# destroy the partition table
node=$1
dd if=/dev/zero of=${node} bs=1024 count=1
sfdisk --force ${node} << EOF
${BOOT_ROM_SIZE}M,500M,0c
600M,,83
EOF
先是循环检测虚拟文件系统中/dev/mmcblk1节点是否注册成功,$1就是传进来的第一个参数/dev/mmcblk1。
# wait for the SD/MMC device node ready
while [ ! -e $1 ]
do
sleep 1
echo “wait for $1 appear”
done
如果识别到了mmcblk1设备,就使用dd命令将EMMC的前1KB的空间清0,EMMC的前1KB空间保存的是它的分区表信息,所以在正常使用情况下千万不能执行如下操作。
# call sfdisk to create partition table
# destroy the partition table
node=$1
dd if=/dev/zero of=${node} bs=1024 count=1
接下来就是使用sfdisk命令对EMMC进行分区操作。
sfdisk --force ${node} << EOF
${BOOT_ROM_SIZE}M,500M,0c
600M,,83
EOF
0c为fat32格式,83为ext3格式,其中10-500M为fat32格式,使用来存储镜像的分区。600M之后的空间都为ext3格式的分区,是给文件系统来用的。在开发板的命令行执行df -h命令即可看到这些分区,如下:
root@ELF1:~# df -h
Filesystem Size Used Avail Use% Mounted on
/dev/root 6.5G 746M 5.5G 12% /
devtmpfs 89M 4.0K 89M 1% /dev
tmpfs 40K 0 40K 0% /mnt/ .psplash
tmpfs 249M 140K 249M 1% /run
tmpfs 249M 140K 249M 1% /var/volatile
/dev/mmcblk1p1 500M 12M 488M 3% /run/media/mmcblk1p1
(三)格式化和烧录
uboot分区格式化和烧录,先是清除了mmcblk1偏移量768之后的8k字节,此位置存放的是uboot的环境变量。
<!-- burn uboot -->
<CMD state="Updater" type="push" body="$ dd if=/dev/zero of=/dev/mmcblk%mmc% bs=1k seek=768 conv=fsync count=8">clear u-boot arg</CMD>
然后使能mmcblk1boot0的写操作,将ProfilesLinuxOS Firmwarefiles目录下的u-boot.imx烧写到mmcblk1boot0分区。
<!-- access boot partition -->
<CMD state="Updater" type="push" body="$ echo 0 > /sys/block/mmcblk%mmc%boot0/force_ro">access boot partition 1</CMD>
<CMD state="Updater" type="push" body="send" file="files/ u-boot.imx" ifdev="MX6ULL">Sending u-boot.bin</CMD>
<CMD state="Updater" type="push" body="$ dd if=$FILE of=/dev/mmcblk%mmc%boot0 bs=512 seek=2">write U-Boot to sd card</CMD>
<CMD state="Updater" type="push" body="$ echo 1 > /sys/block/mmcblk%mmc%boot0/force_ro"> re-enable read-only access </CMD>
<CMD state="Updater" type="push" body="$ mmc bootpart enable 1 1 /dev/mmcblk%mmc%">enable boot partion 1 to boot</CMD>
接下来是格式化FAT32分区,并烧写zImage、logo图片和dtb文件,同样的先是检测/dev下有没有mmcblk1p1节点,使用mkfs.vfat命令将分区格式化为fat格式,再使用mdir命令创建挂载目录/mnt/mmcblk1p1,最后使用mount命令/dev下的mmcblk1p1挂载到新建的目录上。
<!-- create fat partition -->
<CMD state="Updater" type="push" body="$ while [ ! -e /dev/mmcblk%mmc%p1 ]; do sleep 1; echo "waiting..."; done ">Waiting for the partition ready</CMD>
<CMD state="Updater" type="push" body="$ mkfs.vfat /dev/mmcblk%mmc%p1">Formatting rootfs partition</CMD>
<CMD state="Updater" type="push" body="$ mkdir -p /mnt/mmcblk%mmc%p1"/>
<CMD state="Updater" type="push" body="$ mount -t vfat /dev/mmcblk%mmc%p1 /mnt/mmcblk%mmc%p1"/>
有了挂载目录,就可以将ProfilesLinuxOS Firmwarefiles目录下的镜像烧录到EMMC了,其实就是一个拷贝的操作。
先是拷贝ProfilesLinuxOS Firmwarefiles目录的zImage文件到EMMC。
<!-- burn zImage -->
<CMD state="Updater" type="push" body="send" file="files/zImage">Sending kernel zImage</CMD>
<CMD state="Updater" type="push" body="$ cp $FILE /mnt/mmcblk%mmc%p1/zImage">write kernel image to sd card</CMD>
<CMD state="Updater" type="push" body="$ cp $FILE /mnt/mmcblk%mmc%p1/zImagebak">write kernel image to sd card</CMD>
然后是logo图片,
<!-- burn logo -->
<CMD state="Updater" type="push" body="send" file="files/logo.bmp">Sending logo bmp</CMD>
<CMD state="Updater" type="push" body="$ cp $FILE /mnt/mmcblk%mmc%p1/logo.bmp">write logo bmp to sd card</CMD>
然后是dtb文件,再使用umount命令将挂载目录卸载掉。
<!-- burn dtb -->
<CMD state="Updater" type="push" body="send" <CMD state="Updater" type="push" body="send" file="files/imx6ull-elf1-emmc.dtb" ifdev="MX6ULL">Sending Device Tree file</CMD>
<CMD state="Updater" type="push" body="$ cp $FILE /mnt/mmcblk%mmc%p1/imx6ull-elf1-emmc.dtb" ifdev="MX6ULL">write device tree to sd card</CMD>
<CMD state="Updater" type="push" body="$ umount /mnt/mmcblk%mmc%p1">Unmounting vfat partition</CMD>
最后是格式化ext3分区并烧录文件系统,与fat分区是同样的操作,先是使用mkfs.ext3命令将分区格式化为ext3格式,然后使用mkdir命令创建挂载分区目录/mnt/mmcblk1p2,并将分区挂载到目录上。
<!-- burn rootfs -->
<CMD state="Updater" type="push" body="$ mkfs.ext3 -F -E nodiscard /dev/mmcblk%mmc%p2">Formatting rootfs partition</CMD>
<CMD state="Updater" type="push" body="$ mkdir -p /mnt/mmcblk%mmc%p2"/>
<CMD state="Updater" type="push" body="$ mount -t ext3 /dev/mmcblk%mmc%p2 /mnt/mmcblk%mmc%p2"/>
有了挂载目录,就可以将ProfilesLinuxOS Firmwarefiles下的文件系统压缩包rootfs.tar.bz2和模块驱动压缩包modules.tar.bz2解压到挂载目录中了,解压之后使用umount命令卸载挂载目录。
<CMD state="Updater" type="push" body="pipe tar -jxv -C /mnt/mmcblk%mmc%p2" file="files/rootfs.tar.bz2" ifdev="MX6UL MX7D MX6ULL">Sending and writting rootfs</CMD>
<CMD state="Updater" type="push" body="frf">Finishing rootfs write</CMD>
<CMD state="Updater" type="push" body="pipe tar -jxv -C /mnt/mmcblk%mmc%p2" file="files/modules.tar.bz2" ifdev="MX6UL MX7D MX6ULL">Sending and writting modules</CMD>
<CMD state="Updater" type="push" body="frf">Finishing modules software write</CMD>
<CMD state="Updater" type="push" body="$ umount /mnt/mmcblk%mmc%p2">Unmounting rootfs partition</CMD>
<CMD state="Updater" type="push" body="$ echo Update Complete!">Done</CMD>
(四)烧录技巧
前面了解了整个烧录的流程,我们就可以对ucl2.xml文件进行修改来方便烧写,其中烧录文件系统是最耗时的,因为文件系统的压缩包比较大,需要完全把压缩包解压到EMMC中,如果我们想要加快烧录时间,不希望烧录文件系统,我们就可以将ucl2.xml文件中烧录文件系统的部分屏蔽掉,屏蔽语法为<!-- -->方法如下:
<!-- burn rootfs -->
<!--
<CMD state="Updater" type="push" body="$ mkfs.ext3 -F -E nodiscard /dev/mmcblk%mmc%p2">Formatting rootfs partition</CMD>
<CMD state="Updater" type="push" body="$ mkdir -p /mnt/mmcblk%mmc%p2"/>
<CMD state="Updater" type="push" body="$ mount -t ext3 /dev/mmcblk%mmc%p2 /mnt/mmcblk%mmc%p2"/>
<CMD state="Updater" type="push" body="pipe tar -jxv -C /mnt/mmcblk%mmc%p2" file="files/rootfs-qt.tar.bz2" ifdev="MX6UL MX7D MX6ULL">Sending and writting rootfs</CMD>
<CMD state="Updater" type="push" body="frf">Finishing rootfs write</CMD>
<CMD state="Updater" type="push" body="pipe tar -jxv -C /mnt/mmcblk%mmc%p2" file="files/modules.tar.bz2" ifdev="MX6UL MX7D MX6ULL">Sending and writting modules</CMD>
<CMD state="Updater" type="push" body="frf">Finishing modules software write</CMD>
<CMD state="Updater" type="push" body="$ umount /mnt/mmcblk%mmc%p2">Unmounting rootfs partition</CMD>
<CMD state="Updater" type="push" body="$ echo Update Complete!">Done</CMD>
-->
通过上面的学习,我们对Mfgtools工具的烧录原理已经有了充分的理解,那么我们就可以将这个工具进行修改变成自己的工具啦