zynqMP multiboot實現

zynqMP支持multiboot功能,根據選擇的啓動模式爲QSPI32,可知系統會從FLASH的0地址開始查詢可用的鏡像,如果在0地址處未找到可用的系統鏡像,則會偏移32K的地方繼續尋找可用的鏡像文件。

       目前FLASH上的分區如下:

分區名稱

包含文件

起始地址

終止地址

分區長度

flash0

zynq.bin

0x00000000

0x20000000

32MB

flash1

zynq_bk.bin

0x20000000

0x40000000

32MB

flash2

log

0x40000000

0x80000000

64MB

       上電後,zynqMP首先會從FLASH的0地址處開始校驗鏡像的頭部信息,如果可用,就直接將這塊分區的鏡像搬移到內存中去運行;如果flash0分區中的鏡像文件被破壞,那麼zynqMP就會自動往後偏移32K的地址去查找可用的鏡像,也就是從0x8000的地址繼續查找,如果不可用,繼續偏移32K,一直到遍歷FLASH的所有空間。

       在項目中,一個完整的zynqMP.bin文件約爲32M,所以直接在偏移0地址32M的地方存放備份鏡像文件。(注意32M是32K的整數倍,因爲偏移是按32K爲單位進行的)。

       zynqMP.bin中包含有fsbl、PMW、ATF、uboot、dtb、Image、rootfs等內容。dtb、Image、rootfs共同組成image.ub文件。

       要想實現備份鏡像能正常啓動內核,就需要將內核存放的地址告訴uboot,也就是設置uboot的  CONFIG_EXTRA_ENV_SETTINGS。由於zynqMP.bin是從32M的地址開始存放,image.ub的存放地址是相當於32M(0x2000000)偏移940000,內核存放的地址就是0x2940000

思考:爲何需要將內核地址告訴u-boot就行,那zynqMP又是如何知道u-boot的地址呢?

答案:zynqMP以32K爲偏移單位來自動搜尋可用的鏡像,那如何來判斷可用還是不可用呢?其實是通過FSBL文件的前部分字節來判斷的,也就是說找到FSBL後,就認爲鏡像可用,ATF、PMW以及U-BOOT都是緊挨着存放的,也就是說FSBL正常執行了,U-BOOT就正常執行了,但內核與U-boot不是放在一起的,所以內核的地址要告訴u-boot纔行。

具體設置如下:

#define CONFIG_EXTRA_ENV_SETTINGS \

       SERIAL_MULTI \

       CONSOLE_ARG \

       PSSERIAL0 \

       "nc=setenv stdout nc;setenv stdin nc;\0" \

       "ethaddr=00:0a:35:00:22:01\0" \

       "autoload=no\0" \

       "clobstart=0x10000000\0" \

       "netstart=0x10000000\0" \

       "dtbnetstart=0x11800000\0" \

       "loadaddr=0x10000000\0" \

       "bootsize=0x900000\0" \

       "bootstart=0x0\0" \

       "boot_img=BOOT.BIN\0" \

       "load_boot=tftpboot ${clobstart} ${boot_img}\0" \

       "update_boot=setenv img boot; setenv psize ${bootsize}; setenv installcmd \"install_boot\"; run load_boot test_img; setenv img; setenv psize; setenv installcmd\0" \

       "install_boot=sf probe 0 && sf erase ${bootstart} ${bootsize} && " \

              "sf write ${clobstart} ${bootstart} ${filesize}\0" \

       "bootenvsize=0x40000\0" \

       "bootenvstart=0x900000\0" \

       "eraseenv=sf probe 0 && sf erase ${bootenvstart} ${bootenvsize}\0" \

       "kernelsize=0x1600000\0" \

       "kernelstart=0x2940000\0" \

       "kernel_img=image.ub\0" \

       "load_kernel=tftpboot ${clobstart} ${kernel_img}\0" \

       "update_kernel=setenv img kernel; setenv psize ${kernelsize}; setenv installcmd \"install_kernel\"; run load_kernel test_crc; setenv img; setenv psize; setenv installcmd\0" \

       "install_kernel=sf probe 0 && sf erase ${kernelstart} ${kernelsize} && " \

              "sf write ${clobstart} ${kernelstart} ${filesize}\0" \

       "cp_kernel2ram=sf probe 0 && sf read ${netstart} ${kernelstart} ${kernelsize}\0" \

       "dtb_img=system.dtb\0" \

       "load_dtb=tftpboot ${clobstart} ${dtb_img}\0" \

       "update_dtb=setenv img dtb; setenv psize ${dtbsize}; setenv installcmd \"install_dtb\"; run load_dtb test_img; setenv img; setenv psize; setenv installcmd\0" \

       "fault=echo ${img} image size is greater than allocated place - partition ${img} is NOT UPDATED\0" \

       "test_crc=if imi ${clobstart}; then run test_img; else echo ${img} Bad CRC - ${img} is NOT UPDATED; fi\0" \

      "test_img=setenv var \"if test ${filesize} -gt ${psize}\\; then run fault\\; else run ${installcmd}\\; fi\"; run var; setenv var\0" \

       "netboot=tftpboot ${netstart} ${kernel_img} && bootm\0" \

       "default_bootcmd=run cp_kernel2ram && bootm ${netstart}\0" \

""

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章