Xilinx FSBL 代碼簡析

前言

    在分析ZYNQ7000啓動流程時,發現FSBL工程在其中起到了非常重要的作用。參考了許多別人分析的過程,在這裏也總結一下自己的代碼分析流程。如有問題,歡迎指正。

1. 在FSBL工程中首先找到main函數,第一眼看到的就是ps7_init();從註釋可以看到這裏是對MIO, PLL, CLK, DDR進行初始化。

  1. int main(void)  

  2. {  

  3.     u32 BootModeRegister = 0;  

  4.     u32 HandoffAddress = 0;  

  5.     u32 Status = XST_SUCCESS;  

  6.   

  7.     /* 

  8.      * PCW initialization for MIO,PLL,CLK and DDR 

  9.      */  

  10.     Status = ps7_init();  

  11.     if (Status != FSBL_PS7_INIT_SUCCESS) {  

  12.         fsbl_printf(DEBUG_GENERAL,"PS7_INIT_FAIL : %s\r\n",  

  13.                         getPS7MessageInfo(Status));  

  14.         OutputStatus(PS7_INIT_FAIL);  

  15.         /* 

  16.          * Calling FsblHookFallback instead of Fallback 

  17.          * since, devcfg driver is not yet initialized 

  18.          */  

  19.         FsblHookFallback();  

  20.     }  

 

2. 進入到函數ps7_init();中也可以看到這裏通過識別PS_VERSION對外設首先進行初始化

  1. // MIO init  

  2. ret = ps7_config (ps7_mio_init_data);    

  3. if (ret != PS7_INIT_SUCCESS) return ret;  

  4.   

  5. // PLL init  

  6. ret = ps7_config (ps7_pll_init_data);   

  7. if (ret != PS7_INIT_SUCCESS) return ret;  

  8.   

  9. // Clock init  

  10. ret = ps7_config (ps7_clock_init_data);  

  11. if (ret != PS7_INIT_SUCCESS) return ret;  

  12.   

  13. // DDR init  

  14. ret = ps7_config (ps7_ddr_init_data);  

  15. if (ret != PS7_INIT_SUCCESS) return ret;  

  16.     

  17. // Peripherals init  

  18. ret = ps7_config (ps7_peripherals_init_data);  

  19. if (ret != PS7_INIT_SUCCESS) return ret;  

  20. //xil_printf ("\n PCW Silicon Version : %d.0", pcw_ver);  

  21. return PS7_INIT_SUCCESS;  

3. 接下來在main函數中清cache關cache以及註冊異常處理函數

  1. /* 

  2.  * Flush the Caches 

  3.  */  

  4. Xil_DCacheFlush();  

  5.   

  6. /* 

  7.  * Disable Data Cache 

  8.  */  

  9. Xil_DCacheDisable();  

  10.   

  11. /* 

  12.  * Register the Exception handlers 

  13.  */  

  14. RegisterHandlers();  

 

4. DDR初始化完成後,在該函數中對DDR進行基本的讀寫測試

  1. u32 DDRInitCheck(void)  

  2. {  

  3.     u32 ReadVal;  

  4.   

  5.     /* 

  6.      * Write and Read from the DDR location for sanity checks 

  7.      */  

  8.     Xil_Out32(DDR_START_ADDR, DDR_TEST_PATTERN);  

  9.     ReadVal = Xil_In32(DDR_START_ADDR);  

  10.     if (ReadVal != DDR_TEST_PATTERN) {  

  11.         return XST_FAILURE;  

  12.     }  

  13.   

  14.     /* 

  15.      * Write and Read from the DDR location for sanity checks 

  16.      */  

  17.     Xil_Out32(DDR_START_ADDR + DDR_TEST_OFFSET, DDR_TEST_PATTERN);  

  18.     ReadVal = Xil_In32(DDR_START_ADDR + DDR_TEST_OFFSET);  

  19.     if (ReadVal != DDR_TEST_PATTERN) {  

  20.         return XST_FAILURE;  

  21.     }  

  22.   

  23.     return XST_SUCCESS;  

  24. }  

 

5.  PCAP的初始化,這裏不太清楚具體是什麼設備。

  1. /* 

  2.  * PCAP initialization 

  3.  */  

  4. Status = InitPcap();  

  5. if (Status == XST_FAILURE) {  

  6.     fsbl_printf(DEBUG_GENERAL,"PCAP_INIT_FAIL \n\r");  

  7.     OutputStatus(PCAP_INIT_FAIL);  

  8.     /* 

  9.      * Calling FsblHookFallback instead of Fallback 

  10.      * since, devcfg driver is not yet initialized 

  11.      */  

  12.     FsblHookFallback();  

  13. }  

  14.   

  15. fsbl_printf(DEBUG_INFO,"Devcfg driver initialized \r\n");  

6. 從當前抓到的log版本號爲:Silicon Version 3.1

  1. void GetSiliconVersion(void)  

  2. {  

  3.     /* 

  4.      * Get the silicon version 

  5.      */  

  6.     Silicon_Version = XDcfg_GetPsVersion(DcfgInstPtr);  

  7.     if(Silicon_Version == SILICON_VERSION_3_1) {  

  8.         fsbl_printf(DEBUG_GENERAL,"Silicon Version 3.1\r\n");  

  9.     } else {  

  10.         fsbl_printf(DEBUG_GENERAL,"Silicon Version %lu.0\r\n",  

  11.                 Silicon_Version + 1);  

  12.     }  

  13. }  

7. 函數MarkFSBLIn()中設置了REBOOT_STATE,從寄存器BOOT_MODE_REG(0xF8000000U + 0x25C)的低3bit獲取啓動模式。

  1. /* 

  2.  * Store FSBL run state in Reboot Status Register 

  3.  */  

  4. MarkFSBLIn();  

  5.   

  6. /* 

  7.  * Read bootmode register 

  8.  */  

  9. BootModeRegister = Xil_In32(BOOT_MODE_REG);  

  10. BootModeRegister &= BOOT_MODES_MASK;  

8. 基於目前調試的ZYNQ7000有以下幾種啓動模式,在這裏我們重點關注以QSPI模式啓動

  1. /* 

  2.  * Boot Modes 

  3.  */  

  4. #define JTAG_MODE           0x00000000 /**< JTAG Boot Mode */  

  5. #define QSPI_MODE           0x00000001 /**< QSPI Boot Mode */  

  6. #define NOR_FLASH_MODE      0x00000002 /**< NOR Boot Mode */  

  7. #define NAND_FLASH_MODE     0x00000004 /**< NAND Boot Mode */  

  8. #define SD_MODE             0x00000005 /**< SD Boot Mode */  

  9. #define MMC_MODE            0x00000006 /**< MMC Boot Device */  

9. 從代碼中可以看出在判斷啓動模式爲QSPI模式後,做了兩件事

  1. if (BootModeRegister == QSPI_MODE) {  

  2.     fsbl_printf(DEBUG_GENERAL,"Boot mode is QSPI\n\r");  

  3.     InitQspi();  

  4.     MoveImage = QspiAccess;  

  5.     fsbl_printf(DEBUG_INFO,"QSPI Init Done \r\n");  

  6. } else  

(1)首先對QSPI進行初始化,這裏我們簡單的過一下QSPI初始化的代碼

  1. u32 InitQspi(void)  

  2. {  

  3.     XQspiPs_Config *QspiConfig;  

  4.     int Status;  

  5.     u32 ConfigCmd;  

  6.   

  7.     QspiInstancePtr = &QspiInstance;  

  8.   

  9.     /* 

  10.      * Set up the base address for access 

  11.      */  

  12.     FlashReadBaseAddress = XPS_QSPI_LINEAR_BASEADDR;      // 表示QSPI Flash的基地址,從SDK中hdf文件中可以得到相應的硬件配置信息

  13.   

  14.     /* 

  15.      * Initialize the QSPI driver so that it's ready to use 

  16.      */  

  17.     QspiConfig = XQspiPs_LookupConfig(QSPI_DEVICE_ID);  

  18.     if (NULL == QspiConfig) {  

  19.         return XST_FAILURE;  

  20.     }  

  21.   

  22.     Status = XQspiPs_CfgInitialize(QspiInstancePtr, QspiConfig,  

  23.                     QspiConfig->BaseAddress);  

  24.     if (Status != XST_SUCCESS) {  

  25.         return XST_FAILURE;  

  26.     }  

  27.   

  28.     /* 

  29.      * Set Manual Chip select options and drive HOLD_B pin high. 

  30.      */  

  31.     XQspiPs_SetOptions(QspiInstancePtr, XQSPIPS_FORCE_SSELECT_OPTION |  

  32.             XQSPIPS_HOLD_B_DRIVE_OPTION);  

  33.   

  34.     /* 

  35.      * Set the prescaler for QSPI clock 

  36.      */  

  37.     XQspiPs_SetClkPrescaler(QspiInstancePtr, XQSPIPS_CLK_PRESCALE_8);  

  38.   

  39.     /* 

  40.      * Assert the FLASH chip select. 

  41.      */  

  42.     XQspiPs_SetSlaveSelect(QspiInstancePtr);  

  43.   

  44.     /* 

  45.      * Read Flash ID and extract Manufacture and Size information 

  46.      */  

  47.     Status = FlashReadID();  // 該函數非常重要,用來獲取flash的製造廠商及size信息。

  48.     if (Status != XST_SUCCESS) {  

  49.         return XST_FAILURE;  

  50.     }  

從獲取的log信息看當前flash信息如下:

Single Flash Information

FlashID=0x20 0xBB 0x19

MICRON 256M Bits

QSPI is in single flash connection

QSPI is in 4-bit mode

QSPI Init Done 

符合我們拿到的flash芯片手冊:【N25q256.pdf】

 

做完以上這些以後,根據拿到的器件信息設置了QSPI Flash的IO模式並使能了控制器。以上完成QSPI Flash的初始化操作

 

(2)函數指針賦值,把QspiAccess賦值給MoveImage

這裏我們主要關注MoveImage()函數。結合函數的註釋和函數中的主要代碼(即memcpy函數)該函數實現了從flash上搬移一定大小的數據到內存固定的地址上去。

  1. /******************************************************************************/  

  2. /** 

  3. * This function provides the QSPI FLASH interface for the Simplified header 

  4. * functionality. 

  5. * @param    SourceAddress is address in FLASH data space 

  6. * @param    DestinationAddress is address in DDR data space 

  7. * @param    LengthBytes is the length of the data in Bytes 

  8. * @return 

  9. *       - XST_SUCCESS if the write completes correctly 

  10. *       - XST_FAILURE if the write fails to completes correctly 

  11. * @note none. 

  12. ****************************************************************************/  

  13. u32 QspiAccess( u32 SourceAddress, u32 DestinationAddress, u32 LengthBytes)  

  14. {  

  15.     u8  *BufferPtr;  

  16.     u32 Length = 0;  

  17.     u32 BankSel = 0;  

  18.     u32 LqspiCrReg;  

  19.     u32 Status;  

  20.     u8 BankSwitchFlag = 1;  

  21.   

  22.     /* 

  23.      * Linear access check 

  24.      */  

  25.     if (LinearBootDeviceFlag == 1) {  

  26.         /* 

  27.          * Check for non-word tail, add bytes to cover the end 

  28.          */  

  29.         if ((LengthBytes%4) != 0){  

  30.             LengthBytes += (4 - (LengthBytes & 0x00000003));  

  31.         }  

  32.   

  33.         memcpy((void*)DestinationAddress,  

  34.               (const void*)(SourceAddress + FlashReadBaseAddress),  

  35.               (size_t)LengthBytes);  

  36.     } else {  

 

10. QSPI Flash以後分別是

(1)NAND BOOT MODE

(2)NOR BOOT MODE

(3)SD BOOT MODE

// 以上幾種模式的處理流程和QSPI Flash的處理流程類似,都是對設備的初始化以及函數指針的賦值

(4)JTAG  BOOT MODE

從代碼中看到函數FsblHandoffJtagExit最終順序執行到FsblHandoffExit,其中bx    lr指令就是跳轉到用戶代碼執行。

  1. FsblHandoffJtagExit  

  2.         mcr  p15,0,r0,c7,c5,0       ;/* Invalidate Instruction cache */  

  3.         mcr  p15,0,r0,c7,c5,6       ;/* Invalidate branch predictor array */  

  4.   

  5.         dsb  

  6.         isb                         ;/* make sure it completes */  

  7.   

  8.     ldr r4, =0  

  9.         mcr  p15,0,r4,c1,c0,0       ;/* disable the ICache and MMU */  

  10.   

  11.         isb                         ;/* make sure it completes */  

  12. Loop  

  13.     wfe  

  14.     b Loop  

  15.   

  16. FsblHandoffExit  

  17.         mov  lr, r0 ;/* move the destination address into link register */  

  18.   

  19.         mcr  p15,0,r0,c7,c5,0       ;/* Invalidate Instruction cache */  

  20.         mcr  p15,0,r0,c7,c5,6       ;/* Invalidate branch predictor array */  

  21.   

  22.         dsb  

  23.         isb                         ;/* make sure it completes */  

  24.   

  25.     ldr r4, =0  

  26.         mcr  p15,0,r4,c1,c0,0       ;/* disable the ICache and MMU */  

  27.   

  28.         isb                         ;/* make sure it completes */  

  29.   

  30.   

  31.         bx      lr  ;/* force the switch, destination should have been in r0 */  

  32.   

  33. Ldone b     Ldone                   ;/* Paranoia: we should never get here */  

  34.     END  

 

11. 首先從我們打印log信息得到:Handoff Address: 0x00100000即ddr的起始地址,在hdf文件中可以查到

初步猜測裏面應該完成了FPGA bit文件在PL中的加載,以及搬移裸機的軟件elf文件到內存中去。

做完這些工作最終調用了FsblHandoff函數,通過該函數跳轉到DDR中執行應用程序。

  1. /* 

  2.      * Load boot image 

  3.      */  

  4.     HandoffAddress = LoadBootImage();  

  5.   

  6.     fsbl_printf(DEBUG_INFO,"Handoff Address: 0x%08lx\r\n",HandoffAddress);  

  7.   

  8.     /* 

  9.      * For Performance measurement 

  10.      */  

  11. #ifdef FSBL_PERF  

  12.     XTime tEnd = 0;  

  13.     fsbl_printf(DEBUG_GENERAL,"Total Execution time is ");  

  14.     FsblMeasurePerfTime(tCur,tEnd);  

  15. #endif  

  16.   

  17.     /* 

  18.      * FSBL handoff to valid handoff address or 

  19.      * exit in JTAG 

  20.      */  

  21.     FsblHandoff(HandoffAddress);  

12. 接下來我們詳細分析LoadBootImage()這個函數

因爲我們的Silicon_Version不是1,所以我們執行以下代碼。這段代碼的作用是從multiboot寄存器中讀取要執行的image的地址,其實如果就一個image的話可以不用管這個,這個算出來的imagestartaddress一定是0。

結合我們拿到的log:

Multiboot Register: 0x0000C000

Image Start Address: 0x00000000

  1. else {  

  2.         /* 

  3.          * read the multiboot register 

  4.          */  

  5.         MultiBootReg =  XDcfg_ReadReg(DcfgInstPtr->Config.BaseAddr,  

  6.                 XDCFG_MULTIBOOT_ADDR_OFFSET);  

  7.   

  8.         fsbl_printf(DEBUG_INFO,"Multiboot Register: 0x%08lx\r\n",MultiBootReg);  

  9.   

  10.         /* 

  11.          * Compute the image start address 

  12.          */  

  13.         ImageStartAddress = (MultiBootReg & PCAP_MBOOT_REG_REBOOT_OFFSET_MASK)  

  14.                                     * GOLDEN_IMAGE_OFFSET;  

  15.     }  

  16.     fsbl_printf(DEBUG_INFO,"Image Start Address: 0x%08lx\r\n",ImageStartAddress);

 

13. 這一段是讀取在flash中的每個部分的頭文件信息,包括大小起始地址等。也就是在生成BOOT的時候加入的幾個文件,比如說先加的是FSBL,然後是BIT,最後是APP,那麼這裏的部分的數量就是3個。

結合log,這裏跳過FSBL了,所以從Partition Number:1 開始加載bit;然後在Partition Number:2加載軟件elf文件。

  1. /* 

  2.  * Get partitions header information 

  3.  */  

  4. Status = GetPartitionHeaderInfo(ImageStartAddress);  

  5. if (Status != XST_SUCCESS) {  

  6.     fsbl_printf(DEBUG_GENERAL, "Partition Header Load Failed\r\n");  

  7.     OutputStatus(GET_HEADER_INFO_FAIL);  

  8.     FsblFallback();  

  9. }  

14. 從函數Status = GetPartitionHeaderInfo(ImageStartAddress);

    ->Status = GetFsblLength(ImageBaseAddress, &FsblLength);

在該函數中調用了MoveImage函數,實際上是把BOOT.bin image的0x40地址的4字節賦值給FsblLength,從而獲取到Fsbl的size大小。這裏需要了解一下BOOT.bin的結構。

在boot.bin中從地址0-0x8BF可以分成17個部分,每個部分都有一定的含義 

1. 0x000  中斷向量表 

2. 0x020  固定值 0xaa995566 

3. 0x024  固定值 0x584c4e58  ASCII: XLNX 

4. 0x028  如果是0xa5c3c5a3或者0x3a5c3c5a爲加密的 

5. 0x02C  bootrom頭版本號,不用管 

6. 0x030  從bootrom開始到app地址的總數(bytes) 

7. 0x034  從loadimage拷到OCM的長度 【上電後BootRom會主動把FSBL拷貝到OCM中執行】

8. 0x038  目的地址到哪兒拷貝FSBL 

9. 0x03C  開始執行的地址 

10. 0x040  同7 【此處代碼邏輯中其實是把該字段的值賦給FSBL的size】

11. 0x044  0x01爲固定值 

12. 0x048  校驗和(從0x020-0x047)按32-bit word 相加取反 

13. 0x04C  bootgen相關 

14. 0x098  image頭的表指針 

15. 0x09C  partition頭的表指針 

16. 0x0A0  寄存器初始化的參數 

17. 0x8A0  fsbl user defined 

18. 0x8C0  fsbl開始的地方 

如果是從qspi加載的話,bootrom會把數據從qspi拷貝到OCM中,在OCM中運行,也就是0地址運行。

 

  1. u32 GetFsblLength(u32 ImageAddress, u32 *FsblLength)  

  2. {  

  3.     u32 Status;  

  4.   

  5.     Status = MoveImage(ImageAddress + IMAGE_TOT_BYTE_LEN_OFFSET,  

  6.                             (u32)FsblLength, 4);  

  7.     if (Status != XST_SUCCESS) {  

  8.         fsbl_printf(DEBUG_GENERAL,"Move Image failed reading FsblLength\r\n");  

  9.         return XST_FAILURE;  

  10.     }  

  11.   

  12.     return XST_SUCCESS;  

  13. }  

 

15. 結合14項中BOOT.bin的頭信息,下面函數通過image偏移地址0x9C獲取partition頭的表指針。還記得13項中提供的log打印:Partition Header Offset:0x00000C80

    分析代碼基於該partition header開始計算partition count,正常情況下最多遍歷15個partition,我們這裏實際只有3個,即FSBL, BIT, ELF。

    分析代碼正常的一個partion的表頭信息結構如下:

    ​    ​    ​struct HeaderArray {

    ​    ​    ​ u32 Fields[16];

    ​    ​    ​};

最後的一個partion的表頭的內容應該如下:

    ​* 0x00000000

    ​* 0x00000000

    ​* ....

    ​* 0x00000000

    ​* 0x00000000

    ​* 0xFFFFFFFF

即前15個元素均爲0,最後一個元素全爲F,這時判斷所有partition遍歷完畢,得到當前的partition的個數

  1. u32 GetPartitionHeaderStartAddr(u32 ImageAddress, u32 *Offset)  

  2. {  

  3.     u32 Status;  

  4.   

  5.     Status = MoveImage(ImageAddress + IMAGE_PHDR_OFFSET, (u32)Offset, 4);  

  6.     if (Status != XST_SUCCESS) {  

  7.         fsbl_printf(DEBUG_GENERAL,"Move Image failed\r\n");  

  8.         return XST_FAILURE;  

  9.     }  

  10.   

  11.     return XST_SUCCESS;  

  12. }  

16. 首先我們這裏不再解析partition 0即FSBL,直接從partition 1開始解析。在函數HeaderDump中把當前所有partition的大小即其實地址都解析出來。結合如下log我們可以看到FPGA bit和軟件的elf文件的信息。

Partition Header Offset:0x00000C80

Partition Count: 3

Partition Number: 1

Header Dump

Image Word Len: 0x00427028    ​// 這裏應該是bit文件的大小,單位是word。轉換0x00427028 * 4 / 1024 ≈ 17009KB,查看工程符合當前bit文件的大小

Data Word Len: 0x00427028

Partition Word Len:0x00427028

Load Addr: 0x00000000

Exec Addr: 0x00000000

Partition Start: 0x000055D0

Partition Attr: 0x00000020    ​// Bitstream

Partition Checksum Offset: 0x00000000

Section Count: 0x00000001

Checksum: 0xFF385746

Bitstream

 

In FsblHookAfterBitstreamDload function 

Partition Number: 2

Header Dump

Image Word Len: 0x00004002

Data Word Len: 0x00004002

Partition Word Len:0x00004002

Load Addr: 0x00100000

Exec Addr: 0x00100000

Partition Start: 0x0042C600    ​// 0x0042C600 - 0x000055D0 = 0x427030,可以看到bit文件和軟件elf基本上是連續的

Partition Attr: 0x00000010    ​// Application

Partition Checksum Offset: 0x00000000

Section Count: 0x00000001

Checksum: 0xFF9C7788

Application

 

  1. PartitionNum = 1;  

  2.   

  3. while (PartitionNum < PartitionCount) {  

  4.   

  5.     fsbl_printf(DEBUG_INFO, "Partition Number: %lu\r\n", PartitionNum);  

  6.   

  7.     HeaderPtr = &PartitionHeader[PartitionNum];  

  8.   

  9.     /* 

  10.      * Print partition header information 

  11.      */  

  12.     HeaderDump(HeaderPtr);  

 

17. 當解析當前partition屬性爲Bitstream時,設置如下代碼中的flag

  1.         if (PartitionAttr & ATTRIBUTE_PL_IMAGE_MASK) {  

  2.             fsbl_printf(DEBUG_INFO, "Bitstream\r\n");  

  3.             PLPartitionFlag = 1;  

  4.             PSPartitionFlag = 0;  

  5.             BitstreamFlag = 1;  

  6.             if (ApplicationFlag == 1) {  

  7. #ifdef STDOUT_BASEADDRESS  

  8.                 xil_printf("\r\nFSBL Warning !!!"  

  9.                         "Bitstream not loaded into PL\r\n");  

  10.                 xil_printf("Partition order invalid\r\n");  

  11. #endif  

  12.                 break;  

  13.             }  

  14.         }  

通過函數PcapLoadPartition完成了PL的加載,這裏不再做深入分析。

  1.    /* 

  2.      * Load Signed PL partition in Fabric 

  3.      */  

  4.     if (PLPartitionFlag) {  

  5.         Status = PcapLoadPartition((u32*)PartitionStartAddr,  

  6.                 (u32*)PartitionLoadAddr,  

  7.                 PartitionImageLength,  

  8.                 PartitionDataLength,  

  9.                 EncryptedPartitionFlag);  

  10.         if (Status != XST_SUCCESS) {  

  11.             fsbl_printf(DEBUG_GENERAL,"BITSTREAM_DOWNLOAD_FAIL\r\n");  

  12.             OutputStatus(BITSTREAM_DOWNLOAD_FAIL);  

  13.             FsblFallback();  

  14.         }  

  15.     }  

  16. }  

  17.   

  18.   

  19. /* 

  20.  * FSBL user hook call after bitstream download 

  21.  */  

  22. if (PLPartitionFlag) {  

  23.     Status = FsblHookAfterBitstreamDload();  

  24.     if (Status != XST_SUCCESS) {  

  25.         fsbl_printf(DEBUG_GENERAL,"FSBL_AFTER_BSTREAM_HOOK_FAIL\r\n");  

  26.         OutputStatus(FSBL_AFTER_BSTREAM_HOOK_FAIL);  

  27.         FsblFallback();  

  28.     }  

18. 根據partition屬性爲Application時設置如下的flag

  1. if (PartitionAttr & ATTRIBUTE_PS_IMAGE_MASK) {  

  2.  fsbl_printf(DEBUG_INFO, "Application\r\n");  

  3.  PSPartitionFlag = 1;  

  4.  PLPartitionFlag = 0;  

  5.  ApplicationFlag = 1;  

  6. }  

​    ​在這裏會把elf文件搬移到DDR地址0x00100000上,而bit文件會搬移到0x00000000地址上去。

  1. /* 

  2.  * Move partitions from boot device 

  3.  */  

  4. Status = PartitionMove(ImageStartAddress, HeaderPtr);  

  5. if (Status != XST_SUCCESS) {  

  6.     fsbl_printf(DEBUG_GENERAL,"PARTITION_MOVE_FAIL\r\n");  

  7.     OutputStatus(PARTITION_MOVE_FAIL);  

  8.     FsblFallback();  

  9. }  

 

 

 

 

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