这里以基于 IMX6_L4.1.15_2.1.0_MFG_TOOL 修改后的文件为说明,官方下载可以去 NXP 官网直接搜。

# mfgtool 工具

mfgtool 工具是 freescale 为 i.MX 系列处理器打造的 Linux Firmware (uboot/kernel) 烧录工具,被收购后由 NXP 维护,其工具支持单独烧录某一系统分区,支持烧录 spi flash、 nor flash、sd card、nand flash、emmc 等存储介质,只需简单的配置,即可将编译好的镜像文件和文件系统烧录到完整的板上。同时 mfgtool 工具也作为一个可量产性的工具,它支持多通道的烧录。

最新版的 mfgtool 工具可看:https://github.com/nxp-imx/mfgtools

对于官方 L4.1.15_2.1.0 版本,解压后里面有两个压缩包,两个压缩包的区别在名字上已经写的很详细了。 “without-rootfs” 和 “with-rootfs”,一个是没有文件系统和一个是具有文件系统,对比可以看到 without-rootfs 中的 rootfs 是个空的包。

# 配置文件

在该版本中,主要用到的配置 UICfg.ini、cfg.ini 以及 ucl2.xml。

# UICfg.ini

UICfg.ini 文件用于配置端口数量,表示同时支持多少个单板。

UICfg.ini 文件的格式如下:

[UICfg]
PortMgrDlg=1

例如,如果一次只支持一个单板,则应该设置 PortMgrDlg=1 。目前最多支持 4 块单板,所以 PortMgrDlg 可以设置为 1 - 4,默认为 1。

# cfg.ini

cfg.ini 文件用于配置目标芯片配置文件和目标操作列表。

该文件的格式如下所示:

[profiles]
chip = Linux
[platform]
board = SabreSD
[LIST]
name = SDCard
[variable]
board = sabresd
mmc = 0
6uluboot = 14x14ddr3arm2
6uldtb = 14x14-ddr3-arm2
lite = 
initramfs = fsl-image-mfgtool-initramfs-imx_mfgtools.cpio.gz.u-boot
seek = 1
rootfs = rootfs
6ulnor = qspi1
part_nor = 0
part_uboot = 0
part_kernel = 1
part_dtb = 2
part_rootfs = 3
  • profiles/chip 为目标配置文件名称(不区分大小写)。

  • LIST/name 为目标操作列表名称(区分大小写),可在 profiles/CHIP_PROFILE/OS Firmware/ucl2.xml 文件中找到。 ucl2.xml 内容在后续说明。

  • platform/board 目前预留,未使用,请忽略。

  • variableucl2.xml 文件中的引用变量,其引用的方式为 %…%

# ucl2.xml

以下为个人自用修改后的版本,适用于 6UL 和 6ULL:

<!--
* Copyright (C) 2012, Freescale Semiconductor, Inc. All Rights Reserved.
* The CFG element contains a list of recognized usb devices.
*  DEV elements provide a name, class, vid and pid for each device.
*
* Each LIST element contains a list of update instructions.
*  "Install" - Erase media and install firmware.
*  "Update" - Update firmware only.
*
* Each CMD element contains one update instruction of attribute type.
*  "pull" - Does UtpRead(body, file) transaction.
*  "push" - Does UtpWrite(body, file) transaction.
*  "drop" - Does UtpCommand(body) then waits for device to disconnect.
*  "boot" - Finds configured device, forces it to "body" device and downloads "file".
*  "find" - Waits for "timeout" seconds for the "body" device to connect.
*  "show" - Parse and show device info in "file".  
-->
<UCL>
  <CFG>
    <STATE name="BootStrap" dev="MX6UL" vid="15A2" pid="007D"/>
    <STATE name="BootStrap" dev="MX6ULL" vid="15A2" pid="0080"/>
    <STATE name="Updater"   dev="MSC" vid="066F" pid="37FF"/>
  </CFG>
  
  <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="MX6UL MX6ULL">Loading U-boot</CMD>
		
	<CMD state="BootStrap" type="load" file="firmware/zImage" address="0x80800000"
		loadSection="OTH" setSection="OTH" HasFlashHeader="FALSE" ifdev="MX6UL MX6ULL">Loading Kernel.</CMD>
	<CMD state="BootStrap" type="load" file="firmware/%initramfs%" address="0x83800000"
		loadSection="OTH" setSection="OTH" HasFlashHeader="FALSE" ifdev="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="MX6UL MX6ULL">Loading device tree.</CMD>
	<CMD state="BootStrap" type="jump" > Jumping to OS image. </CMD>
	<!-- create partition -->
	<CMD state="Updater" type="push" body="send" file="mksdcard.sh.tar">Sending partition shell</CMD>
	<CMD state="Updater" type="push" body="$ tar xf $FILE "> Partitioning...</CMD>
	<CMD state="Updater" type="push" body="$ sh mksdcard.sh /dev/mmcblk%mmc%"> Partitioning...</CMD>
	<!-- 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>
	<!-- 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-imx6ul%lite%%6uluboot%_emmc.imx" ifdev="MX6UL 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>
	<!-- 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"/>
	<!-- burn kernel -->
	<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>
	<!-- burn dtb -->
	<CMD state="Updater" type="push" body="send" file="files/zImage-imx6ul%lite%-%6uldtb%-emmc.dtb" ifdev="MX6UL MX6ULL">Sending Device Tree file</CMD>
	<CMD state="Updater" type="push" body="$ cp $FILE /mnt/mmcblk%mmc%p1/imx6ul%lite%-%6uldtb%.dtb" ifdev="MX6UL MX6ULL">write device tree to sd card</CMD>
	<!-- 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%.tar.bz2" ifdev="MX6UL MX6ULL">Sending and writting rootfs</CMD>
	<CMD state="Updater" type="push" body="frf">Finishing rootfs 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>
  </LIST>
  <!-- burn uboot only because spi-nor flash is small (4M). kernel is beyond 5M now -->
  <LIST name="Nor Flash" desc="Choose Nor flash as media">
	<CMD state="BootStrap" type="boot" body="BootStrap" file ="firmware/u-boot-imx6ul%lite%%6uluboot%_sd.imx" ifdev="MX6UL MX6ULL">Loading U-boot</CMD>
	<CMD state="BootStrap" type="load" file="firmware/zImage" address="0x80800000"
		loadSection="OTH" setSection="OTH" HasFlashHeader="FALSE" ifdev="MX6UL MX6ULL">Loading Kernel.</CMD>
	<CMD state="BootStrap" type="load" file="firmware/%initramfs%" address="0x83800000"
		loadSection="OTH" setSection="OTH" HasFlashHeader="FALSE" ifdev="MX6UL MX6ULL">Loading Initramfs.</CMD>
	<CMD state="BootStrap" type="load" file="firmware/zImage-imx6ul%lite%-%6uldtb%.dtb" address="0x83000000"
		loadSection="OTH" setSection="OTH" HasFlashHeader="FALSE" ifdev="MX6UL MX6ULL">Loading device tree.</CMD>
	<CMD state="BootStrap" type="jump" > Jumping to OS image. </CMD>
	<CMD state="Updater" type="push" body="$ flash_erase /dev/mtd%part_nor% 0 0">Erasing Boot partition</CMD>
	<CMD state="Updater" type="push" body="send" file="files/u-boot-imx6ul%lite%%6uluboot%_%nor%.imx" ifdev="MX6UL MX6ULL">Sending u-boot.bin</CMD>
	<CMD state="Updater" type="push" body="$ dd if=$FILE of=/dev/mtd%part_nor% bs=1k seek=%seek%" ifdev="MX6UL MX6ULL">write U-Boot to NOR flash</CMD>
	<CMD state="Updater" type="push" body="$ echo Update Complete!">Done</CMD>
  </LIST>
  <LIST name="Quad Nor Flash" desc="Choose Quad Nor flash as media">
	<CMD state="BootStrap" type="boot" body="BootStrap" file ="firmware/u-boot-imx6ul%lite%%6uluboot%_%6ulnor%.imx" ifdev="MX6UL MX6ULL">Loading U-boot</CMD>
	<CMD state="BootStrap" type="load" file="firmware/zImage" address="0x80800000"
		loadSection="OTH" setSection="OTH" HasFlashHeader="FALSE" ifdev="MX6UL MX6ULL">Loading Kernel.</CMD>
	<CMD state="BootStrap" type="load" file="firmware/%initramfs%" address="0x83800000"
		loadSection="OTH" setSection="OTH" HasFlashHeader="FALSE" ifdev="MX6UL MX6ULL">Loading Initramfs.</CMD>
	<CMD state="BootStrap" type="load" file="firmware/zImage-imx6ul%lite%-%6uldtb%.dtb" address="0x83000000"
		loadSection="OTH" setSection="OTH" HasFlashHeader="FALSE" ifdev="MX6UL MX6ULL">Loading device tree.</CMD>
	<CMD state="BootStrap" type="jump" > Jumping to OS image. </CMD>
	<CMD state="Updater" type="push" body="$ flash_erase /dev/mtd0 0 20">Erasing Boot partition</CMD>
	<CMD state="Updater" type="push" body="send" file="files/u-boot-imx6ul%lite%%6uluboot%_%6ulnor%.imx" ifdev="MX6UL MX6ULL">Sending u-boot.bin</CMD>
	<CMD state="Updater" type="push" body="$ dd if=$FILE of=/dev/mtd0 bs=1k seek=4" ifdev="MX6UL MX6ULL">write U-Boot to NOR flash</CMD>
	<!--QSPI header-->
	<CMD state="Updater" type="push" body="send" file="qspi-header.sh.tar">Sending qspi header shell</CMD>
	<CMD state="Updater" type="push" body="$ tar xf $FILE "> Extracting...</CMD>
	<CMD state="Updater" type="push" body="send" file="files/%norconfig%">Sending QSPI header config file</CMD>
	<CMD state="Updater" type="push" body="$ sh qspi-header.sh $FILE"> Generating the ascii value header</CMD>
	<!--hexdump to convert ascii value to hex file-->
	<CMD state="Updater" type="push" body="$ busybox hexdump -R qspi-tmp > qspi-header">Converting ascii value to hex file</CMD>
	<CMD state="Updater" type="push" body="$ dd if=qspi-header of=/dev/mtd0 bs=1k seek=1" ifdev="MX6UL MX6ULL">Writing header to NOR flash</CMD>
	<!--delete temporary files-->
	<CMD state="Updater" type="push" body="$ rm qspi-tmp">Deleting temporary file</CMD>
	<CMD state="Updater" type="push" body="$ rm qspi-header">Deleting temporary file</CMD>
	<CMD state="Updater" type="push" body="$ echo Update Complete!">Done</CMD>
  </LIST>
  <LIST name="NAND Flash" desc="Choose NAND as media">
	<CMD state="BootStrap" type="boot" body="BootStrap" file ="firmware/u-boot-imx6ul%lite%%6uluboot%_%nand%.imx" ifdev="MX6UL MX6ULL">Loading U-boot</CMD>
	<CMD state="BootStrap" type="load" file="firmware/zImage" address="0x80800000"
		loadSection="OTH" setSection="OTH" HasFlashHeader="FALSE" ifdev="MX6UL MX6ULL">Loading Kernel.</CMD>
	<CMD state="BootStrap" type="load" file="firmware/%initramfs%" address="0x83800000"
				loadSection="OTH" setSection="OTH" HasFlashHeader="FALSE" ifdev="MX6UL MX6ULL">Loading Initramfs.</CMD>
	<CMD state="BootStrap" type="load" file="firmware/zImage-imx6ul%lite%-%6uldtb%-%nanddtb%.dtb" address="0x83000000"
		loadSection="OTH" setSection="OTH" HasFlashHeader="FALSE" ifdev="MX6UL MX6ULL">Loading device tree.</CMD>
	<CMD state="BootStrap" type="jump" > Jumping to OS image. </CMD>
	<!--burn the uboot to NAND: -->	
	<CMD state="Updater" type="push" body="$ mount -t debugfs debugfs /sys/kernel/debug">Mounting debugfs</CMD>
	<CMD state="Updater" type="push" body="$ flash_erase /dev/mtd%part_uboot% 0 0">Erasing Boot partition</CMD>
	<CMD state="Updater" type="push" body="send" file="files/u-boot-imx6ul%lite%%6uluboot%_%nand%.imx" ifdev="MX6UL MX6ULL">Sending u-boot.bin</CMD>
	<CMD state="Updater" type="push" body="$ kobs-ng init -x -v --chip_0_device_path=/dev/mtd%part_uboot% $FILE">Flashing Bootloader</CMD>
	<!--burn the kernel to NAND: -->
	<CMD state="Updater" type="push" body="$ flash_erase /dev/mtd%part_kernel% 0 0">Erasing Kernel partition</CMD>
	<CMD state="Updater" type="push" body="send" file="files/zImage">Sending kernel zImage</CMD>
	<CMD state="Updater" type="push" body="$ nandwrite -p /dev/mtd%part_kernel% -p $FILE">Flashing Kernel</CMD>
	<!--burn the dtb to NAND: -->
	<CMD state="Updater" type="push" body="$ flash_erase /dev/mtd%part_dtb% 0 0">Erasing dtb partition</CMD>
	<CMD state="Updater" type="push" body="send" file="files/zImage-imx6ul%lite%-%6uldtb%-%nanddtb%.dtb" ifdev="MX6UL MX6ULL">Sending Device Tree file</CMD>
	<CMD state="Updater" type="push" body="$ nandwrite -p /dev/mtd%part_dtb% -p $FILE">Flashing dtb</CMD>
	<!--burn the rootfs to NAND: -->
	<CMD state="Updater" type="push" body="$ flash_erase /dev/mtd%part_rootfs% 0 0">Erasing rootfs partition</CMD>
	<CMD state="Updater" type="push" body="$ ubiformat /dev/mtd%part_rootfs%"/>
	<CMD state="Updater" type="push" body="$ ubiattach /dev/ubi_ctrl -m %part_rootfs%">Attaching UBI partition</CMD>
	<CMD state="Updater" type="push" body="$ ubimkvol /dev/ubi0 -Nrootfs -m"/>
	<CMD state="Updater" type="push" body="$ mkdir -p /mnt/mtd%part_rootfs%"/>
	<CMD state="Updater" type="push" body="$ mount -t ubifs ubi0:rootfs /mnt/mtd%part_rootfs%"/>
	<CMD state="Updater" type="push" body="pipe tar -jxv -C /mnt/mtd%part_rootfs%" file="files/%rootfs%.tar.bz2" ifdev="MX6UL MX6ULL">Sending and writting rootfs</CMD>
	<CMD state="Updater" type="push" body="frf">Finishing rootfs write</CMD>
	<CMD state="Updater" type="push" body="$ umount /mnt/mtd%part_rootfs%">Unmounting rootfs partition</CMD>
	<CMD state="Updater" type="push" body="$ echo Update Complete!">Done</CMD>
  </LIST>
</UCL>

这是一个 xml 文件,所以遵循 xml 语法,根元素 <UCL> <UCL/> ,它表示更新命令列表(Update Command List,UCL);标签 <CFG> </CFG> ,元素中包含可识别 usb 设备的列表;标签 <LIST> </LIST> ,元素 name 用于匹配 cfg.ini 文件中的 LIST/name 参数或脚本输入参数,元素 desc 用于描述说明;标签 <CMD> </CMD> 嵌套于 <LIST> </LIST> 下,属于命令标签,在不同的阶段下命令是不一样的(大致分为两个阶段 BootStrap 和 Updater),mfgtool 工具的命令分为主机特定命令(Host Specific Commands)与固件特定命令(Firmware Specific Commands),其中主机特定命令是由 mfgtool 工具解析和执行,而固件特定命令由目标设备上的固件运行解析和执行。

# 烧录文件

mfgtool 文件目录下的文件夹和文件非常多,除了上面的配置文件外,还有烧录脚本文件(.vbs)和烧录所需文件(uboot、kernel、dtb、rootfs)

# 烧录脚本文件

在 win 平台下,目录下的 MfgTool2.exe 就是烧写工具,以 .vbs 结尾的文件就是烧写的配置文件;而在 Linux 平台下, mfgtoolcli 是该平台的烧写工具,可以通过执行 linux-cvbs.sh 脚本转换 .vbs 文件为 Linux 平台下的脚本。

该烧写工具能支持多款 i.MX 系统的 SoC 系统烧写,还能支持 Nand Flash、eMMC 和 SD 卡等存储介质的烧写;因此,在对每一款 SoC 进行系统烧写之前,需要进行配置并指定好需要烧写的芯片以及存储介质等,然后通过执行相应的脚本文件运行;一般常用的脚本有如下几个:

脚本文件名描述
mfgtool2-yocto-mx-evk-emmcEMMC 烧写脚本
mfgtool2-yocto-mx-evk-nandNand 烧写脚本
mfgtool2-yocto-mx-evk-qspi-nor-n25q256aQSPI Flash 烧写脚本,型号为 n25q256a

关于烧写脚本命令参数,其烧写工具命令行的格式如下:

MfgTool2.exe [-c] [chip profile folder name] [-l] [list name] [-p] [number] [-s] [variable=value]

一般我们只用到:

  • -c:指定目标配置文件的名称。如果不指定则读取 cfg.iniprofiles/chip 的值。
  • -l:指示目标操作列表名称。如果不指定则读取 cfg.iniLIST/name 的值。
  • -p:表示同时支持的单板数量。如果不指定则读取 UICfg.iniUICfg/PortMgrDlg 的值。
  • -s:设置 ucl2.xml 中的变量值;支持多变量配置。如果不指定则读取 cfg.ini 中所需的 variable 引用变量值。

更多格式可看目录下的 ~\Document\V2\Manufacturing Tool V2 Quick Start Guide.docx 文档。

note:

可能会想,为什么没有列出 SD Card 烧写脚本,是因为用 SD Card 作烧写,用命令操作会好一点。

# 烧录所需文件

前面说到,在执行 ucl2.xml 的一系列操作中,存在两个阶段:

  • 第一阶段(把系统烧写到 DRAM 中,然后 Jumping to OS image,以此为运行平台)

    其所需的文件有:(以 ucl2.xmleMMC 标签为例)

    运行固件下载文件
    ubootfirmware/u-boot-imx6ul%lite%%6uluboot%_emmc.imx
    kernelfirmware/zImage
    initramfsfirmware/%initramfs%
    dtbfirmware/zImage-imx6ul%lite%-%6uldtb%-emmc.dtb

    结合上面图表中可以看出来,存放第一阶段所需的固件路径是 profiles/CHIP_PROFILE/OS Firmware/firmwareCHIP_PROFILE 是由 cfg.ini 中的 profiles/chip 参数或 mfgtool2-yocto-mx-evk-emmc 脚本里 -c 所带参数决定,不区分大小写;对应的文件也依据 ucl2.xmlBootStrap 状态下的 file 元素定义的文件名为基准。

    tips:一般这里是不需要改动了,因为只是为了引导实际烧写而提供一个运行平台而已。

  • 第二阶段(通过从 DRAM 中启动的运行平台将目标镜像固化到存储介质中)

    其所需的文件有:(以 ucl2.xmleMMC 标签为例)

    目标固件下载文件
    ubootfiles/u-boot-imx6ul%lite%%6uluboot%_emmc.imx
    kernelfiles/zImage
    dtbfiles/zImage-imx6ul%lite%-%6uldtb%-emmc.dtb
    rootfsfiles/%rootfs%.tar.bz2

    同样的,在第二阶段存放所需的固件路径是 profiles/CHIP_PROFILE/OS Firmware/files ,对应的文件则依据 ucl2.xmlUpdater 状态下的 file 元素定义的文件名为基准。

总结一下烧录流程:

第一步:烧录 profiles/CHIP_PROFILE/OS Firmware/firmware 路径下的 uboot、kernel、initramfs、dtb 到 DRAM 中;然后执行 Jumping to OS image,这时候在已运行的系统中去执行第二个步骤。

第二步:通过从 DRAM 中已经启动的系统上,将 profiles/CHIP_PROFILE/OS Firmware/files 路径下的目标固件 uboot、kernel、dtb、rootfs 烧写到存储介质中上,如 eMMC、Nand 等。因此在实际使用中,当需要更新系统或设备树时,真正需要更改的是这几个文件。

更新于 阅读次数

请我喝[茶]~( ̄▽ ̄)~*

夏沫の浅雨 微信支付

微信支付

夏沫の浅雨 支付宝

支付宝