MfgTools工具目錄
MfgTool工具是一個NXP提供的OTG燒錄工具,工具主目錄主要由以下文件組成:
Profiles/目錄:
(一)ProfilesLinuxOS Firmwarefiles中,存儲著將要燒寫到存儲介質(zhì)(啟動介質(zhì))的目標(biāo)鏡像(uboot、內(nèi)核、文件系統(tǒng)、設(shè)備樹等)
(二)ProfilesLinuxOS Firmwarefirmware中,存儲著引導(dǎo)燒寫的鏡像(uboot、內(nèi)核、ramfs文件系統(tǒng)、設(shè)備樹)
(三)ProfilesLinuxOS Firmware中,存儲著ucl2.xml腳本和mksdcard.sh.tar分區(qū)腳本。
mx6ull-4gemmc-512mddr-qt5.6.vbs主要用于啟動MfgTool2.exe程序,并向其傳遞配置參數(shù),MfgTool2.exe程序會根據(jù)這些參數(shù)執(zhí)行ProfilesLinuxOS Firmwareucl2.xml中的命令。
MfgTool工具工作過程
MfgTool工具工作過程主要分以下幾個步驟:
(一)撥碼無誤,開發(fā)板上電之后,首先boot ROM(SOC內(nèi)部code,boot ROM具體作用在以后章節(jié)會進一步講解)開始運行,對USB外設(shè)進行初始化,并將開發(fā)板枚舉成HID設(shè)備。
(二)Mfgtool工具檢測到此HID設(shè)備,并與之建立連接。然后Mfgtool工具會解析Firmware目錄下uboot,并使用uboot中的內(nèi)存配置信息對開發(fā)板DDR進行初始化配置。
(三)DDR內(nèi)存初始化完成之后,Mfgtool工具就會按照mfgtoolsProfilesLinuxOS Firmwareucl2.xml腳本中的命令將mfgtoolsProfilesLinuxOS Firmwarefirmware目錄下uboot鏡像、內(nèi)核鏡像、設(shè)備樹以及ramfs加載到DDR內(nèi)存中指定地址,然后發(fā)送指令給boot ROM,跳轉(zhuǎn)到DDR內(nèi)存的uboot入口地址,執(zhí)行uboot,uboot進而啟動內(nèi)核,內(nèi)核掛載ramfs文件系統(tǒng)。
(四)系統(tǒng)啟動之后,會枚舉USB作為一個MSC設(shè)備,此時SoC可以和主機進行高速數(shù)據(jù)傳輸。
(五)然后,Mfgtool會逐一執(zhí)行mfgtoolsProfilesLinuxOS Firmwareucl2.xml腳本中的命令,將mfgtoolsProfilesLinuxOS Firmwarefiles目錄下的uboot、內(nèi)核鏡像、設(shè)備樹文件、文件系統(tǒng)等逐一燒寫到存儲介質(zhì)(啟動介質(zhì))中。
ucl2.xml文件講解
xml文件中會根據(jù)不同的板卡類型,選擇不同的LIST,主要講解EMMC版本的燒錄流程:
(一)將引導(dǎo)鏡像加載到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文件中有相關(guān)定義,可以右鍵使用文本格式打開這兩個文件進行查看。
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進行初始化,引導(dǎo)固件中的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>
然后是加載虛擬文件系統(tǒng),將ProfilesLinuxOS Firmwarefirmware目錄下的fsl-image-mfgtool-initramfs-imx_mfgtools.cpio.gz.u-boot加載到DDR的“0x83800000”,%initramfs%的定義在上文的cfg.ini文件中可以找到。這個虛擬文件系統(tǒng)又叫rmadisk,是將內(nèi)存的一塊地址虛擬成硬盤來使用,斷電后是不會保存的。
<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>
然后加載設(shè)備樹文件,將ProfilesLinuxOS Firmwarefirmware目錄下的zImage-imx6ull-14x14-evk-emmc.dtb加載到DDR的“0x83000000”,最后jump命令跳轉(zhuǎn)到虛擬文件系統(tǒng)中。
<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分區(qū),進入到虛擬文件系統(tǒng)后就可以對EMMC進行分區(qū)了。
先是將ProfilesLinuxOS Firmware下的mksdcard.sh.tar包發(fā)送到了虛擬文件系統(tǒng)中。
<!-- 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>
最后執(zhí)行mksdcard.sh對mmcblk1進行格式化和分區(qū)操作。%mmc%在上文中的mx6ull-8gemmc-512mddr-qt5.6.vbs文件中有定義。
<CMD state="Updater" type="push" body="$ sh mksdcard.sh /dev/mmcblk%mmc%"> Partitioning...</CMD>
接下來看一下mksdcard.sh中是如何進行格式化和分區(qū)的,在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
先是循環(huán)檢測虛擬文件系統(tǒng)中/dev/mmcblk1節(jié)點是否注冊成功,$1就是傳進來的第一個參數(shù)/dev/mmcblk1。
# wait for the SD/MMC device node ready
while [ ! -e $1 ]
do
sleep 1
echo “wait for $1 appear”
done
如果識別到了mmcblk1設(shè)備,就使用dd命令將EMMC的前1KB的空間清0,EMMC的前1KB空間保存的是它的分區(qū)表信息,所以在正常使用情況下千萬不能執(zhí)行如下操作。
# call sfdisk to create partition table
# destroy the partition table
node=$1
dd if=/dev/zero of=${node} bs=1024 count=1
接下來就是使用sfdisk命令對EMMC進行分區(qū)操作。
sfdisk --force ${node} << EOF
${BOOT_ROM_SIZE}M,500M,0c
600M,,83
EOF
0c為fat32格式,83為ext3格式,其中10-500M為fat32格式,使用來存儲鏡像的分區(qū)。600M之后的空間都為ext3格式的分區(qū),是給文件系統(tǒng)來用的。在開發(fā)板的命令行執(zhí)行df -h命令即可看到這些分區(qū),如下:
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分區(qū)格式化和燒錄,先是清除了mmcblk1偏移量768之后的8k字節(jié),此位置存放的是uboot的環(huán)境變量。
<!-- 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分區(qū)。
<!-- 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分區(qū),并燒寫zImage、logo圖片和dtb文件,同樣的先是檢測/dev下有沒有mmcblk1p1節(jié)點,使用mkfs.vfat命令將分區(qū)格式化為fat格式,再使用mdir命令創(chuàng)建掛載目錄/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分區(qū)并燒錄文件系統(tǒng),與fat分區(qū)是同樣的操作,先是使用mkfs.ext3命令將分區(qū)格式化為ext3格式,然后使用mkdir命令創(chuàng)建掛載分區(qū)目錄/mnt/mmcblk1p2,并將分區(qū)掛載到目錄上。
<!-- 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下的文件系統(tǒng)壓縮包rootfs.tar.bz2和模塊驅(qū)動壓縮包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文件進行修改來方便燒寫,其中燒錄文件系統(tǒng)是最耗時的,因為文件系統(tǒng)的壓縮包比較大,需要完全把壓縮包解壓到EMMC中,如果我們想要加快燒錄時間,不希望燒錄文件系統(tǒng),我們就可以將ucl2.xml文件中燒錄文件系統(tǒng)的部分屏蔽掉,屏蔽語法為<!-- -->方法如下:
<!-- 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>
-->
通過上面的學(xué)習(xí),我們對Mfgtools工具的燒錄原理已經(jīng)有了充分的理解,那么我們就可以將這個工具進行修改變成自己的工具啦