S3C2450自动升级

S3C2450 自动升级

 

    在 BSP 包中,有两个 bootloader 文件夹,一个命名为 bootloader, 另一个命名为 bootloader_update Bootloader 文件夹用于 USB 下载,调试用, bootloader_update 用于生产,自动升级用。下面重点介绍 bootloader_update 文件夹。

Bootloader_update 文件夹下有四个文件夹,分别是 BLCOMMON Eboot_boot FAT_LIB 以及 IROM_SD_TOOL BLCOMMON 文件夹编译后生成 oal_blcommon.lib 文件,供 Eboot_boot 调用。 FAT_LIB 文件夹里面包含三个静态库文件 FAT_LIB.lib HSMMCEBOOT_LIB.lib 以及 SDREAD_UPDATE.lib 。这些静态库封装了一些用于升级的函数。 Eboot_boot 文件夹编译后将会产生生产用的 Eboot.bin 文件,该文件即能够启动系统,也能够通过硬件平台的按键控制,实现自动升级。 IROM_SD_TOOL 文件夹编译后,会将前面的 Eboot.bin 文件封装成 SD 卡识别的程序,最终生成 IROM_SD_EBOOT.nb0 。通过三星提供的 IROM_Fusing_Tool 工具,将该文件烧到 SD 卡后, 2450 平台就能够实现从 SD 卡启动了。当然前提是硬件本身要设置跳线成 SD 卡启动。

主程序中 (Eboot_boot 文件夹 ) 定义了三个重要的变量: AUTO_UPDATE_FROM_SD

ERASE_ALL_FLASH_BLOCKS

SHOW_UPDATE_LOGO

AUTO_UPDATE_FROM_SD 为真时, Eboot 将会进入升级程序,为假时将引导 flash 中的 NK ,启动系统。

ERASE_ALL_FLASH_BLOCKS 为真时, Eboot 将会格式化 flash ,然后依次升级 block0.nb0,eboot.bin,nk.bin ,随后启动系统。

SHOW_UPDATE_LOGO 为真时, LCD 上将会出现升级文件的提示,否则显示开机 LOGO

其中 AUTO_UPDATE_FROM_SD 标志位通过硬件平台的按键判断,当拨动电源键后在两秒之内回拨到 LOCK 位置, Eboot 将识别到该 LOCK 标志,这时将 AUTO_UPDATE_FROM_SD 置高,程序进入升级状态。

ERASE_ALL_FLASH_BLOCKS 标志位通过从 SD 卡中的 update.txt 文件中读取。

AUTO_UPDATE_FROM_SD 的相关代码如下:

if(1 == UPDATA_ALL_IMAGE)

      {

               AUTO_UPDATE_FROM_SD =TRUE;        

               ERASE_ALL_FLASH_BLOCKS =TRUE;    

               SHOW_UPDATE_LOGO = TRUE;

      }

else if( _FAT_Boot_ReadFile(_BOOT_TYPE_SD_BIN, _UPDATE_FILE_DETECT)  ||auto_updatekey_isPressed() )

      {

          // 自动升级健按下进行自动升级  

               AUTO_UPDATE_FROM_SD=TRUE;         

            }

      else

      {

            AUTO_UPDATE_FROM_SD = FALSE;

      }


    其中 _FAT_Boot_ReadFile() 函数用于从 SD 卡中读取 _UPDATE_FILE_DETECT 文件,该字符串在最前面有如下定义:

#define _UPDATE_FILE_DETECT           "DETECT  BIN"

auto_updatekey_isPressed() 函数用于检测拍照键是否按下,从这里可以看出,如果 SD 卡中存在 detect.bin 文件,则升级时不用再按住拍照键了。如果没有则必须按住拍照键。

Flash 格式化的程序如下:

    if(1)// format flash.

               {

                         //ADDED BY ZHOUPENG FOR TEST

                         ReadDeviceSerialNumber(Serial_Block_Number,pBuf8);

                         ReadDeviceSerialNumber(Smit_Device_Serial_Block_Number,pBuf9);       

                         OALMSG(TRUE, (TEXT(" ++Format FIL (Erase All Blocks)/r/n")));

                       if (VFL_Close() != VFL_SUCCESS)

                       {

                                OALMSG(TRUE, (TEXT("[ERR] VFL_Close() Failure/r/n")));

                       }

                       if (WMR_Format_FIL() == FALSE32)

                       {

                                OALMSG(TRUE, (TEXT("[ERR] WMR_Format_FIL() Failure/r/n")));

                       }

                         if (WMR_Format_VFL() == FALSE32)

                         {

                                  OALMSG(TRUE, (TEXT("[ERR] WMR_Format_VFL() Failure/r/n")));

                         }

                         if (WMR_Format_FTL() == FALSE32)

                         {

                                  OALMSG(TRUE, (TEXT("[ERR] WMR_Format_FTL() Failure/r/n")));

                         }

                         OALMSG(TRUE, (TEXT("[INF] You can not use VFL before Format VFL/r/n")));

                         OALMSG(TRUE, (TEXT(" --Format FIL (Erase All Blocks)/r/n")));

                        WriteDeviceSerialNumber(Serial_Block_Number,pBuf8);

                         WriteDeviceSerialNumber(Smit_Device_Serial_Block_Number,pBuf9);                         

               }

      下载映像的函数如下:

 

static BOOL DownloadImage (LPDWORD pdwImageStart, LPDWORD pdwImageLength, LPDWORD pdwLaunchAddr)

{

         BYTE hdr[BL_HDRSIG_SIZE];

         DWORD dwRecLen, dwRecChk, dwRecAddr;

         BOOL fIsFlash = FALSE;

         LPBYTE lpDest = NULL;

         int nPkgNum = 0;

         BYTE nNumDownloadFiles = 1;

         DWORD dwImageStart = 0;

         DWORD dwImageLength = 0;

         RegionInfo *pCurDownloadFile;

         int i;

         *pdwImageStart = *pdwImageLength = *pdwLaunchAddr = 0;

 

         g_DownloadManifest.dwNumRegions = 0 ;

         for( i = 0 ; i < BL_MAX_BIN_REGIONS ; i++)

         {

                   g_DownloadManifest.Region[i].dwRegionStart = 0;

                   g_DownloadManifest.Region[i].dwRegionLength = 0;

                   g_DownloadManifest.Region[i].szFileName[0] = '/0';       

         }

         do

         {

                   // *.bin 文件的前 7 个字节数据读入 hdr(header) 数组

                   if (!OEMReadData (BL_HDRSIG_SIZE, hdr))

                   {

                            EdbgOutputDebugString ("/r/nUnable to read image signature./r/n");

                            HALT (BLERR_MAGIC);

                            return (FALSE);

                   }

                   // An N000FF packet is manufactured by Platform Builder when we're

                   // downloading multiple files or when we're downloading a .nb0 file.

                   if (!memcmp (hdr, "N000FF/x0A", BL_HDRSIG_SIZE))// 比较数据相等时 memcmp 返回 0

                   {

                            // read the packet checksum.

                            //

                            if (!OEMReadData (sizeof (DWORD), (LPBYTE) &dwRecChk))

                            {

                                     EdbgOutputDebugString("/r/nUnable to read download manifest checksum./r/n");

                                     HALT (BLERR_MAGIC);

                                     return (FALSE);

                            }

 

                            // read BIN region descriptions (start address and length).

                            //

                            if (!OEMReadData (sizeof (DWORD), (LPBYTE) &g_DownloadManifest.dwNumRegions) ||

                            !OEMReadData ((g_DownloadManifest.dwNumRegions * sizeof(RegionInfo)), (LPBYTE) &g_DownloadManifest.Region[0]))

                            {

                                     EdbgOutputDebugString("/r/nUnable to read download manifest information./r/n");

                                     HALT (BLERR_MAGIC);

                                     return (FALSE);

                            }

                            // verify the packet checksum.

                            if (!VerifyChecksum((g_DownloadManifest.dwNumRegions * sizeof(RegionInfo)), (LPBYTE) &g_DownloadManifest.Region[0], dwRecChk))

                            {

                                     EdbgOutputDebugString ("/r/nDownload manifest packet failed checksum verification./r/n");

                                     HALT (BLERR_CHECKSUM);

                                     return (FALSE);

                            }

                            if (g_pOEMMultiBINNotify)

                            {

                                     g_pOEMMultiBINNotify((PDownloadManifest)&g_DownloadManifest);

                            }

                            // look for next download...

                            nNumDownloadFiles = (BYTE)(g_DownloadManifest.dwNumRegions + 1);      // +1 to account for this packet.

                            continue;

                   }

                   // Is this an old X000FF multi-bin packet header?  It's no longer supported.

                   else if (!memcmp (hdr, "X000FF/x0A", BL_HDRSIG_SIZE))

                   {

                            EdbgOutputDebugString ("ERROR: The X000FF packet is an old-style multi-bin download manifest and it's no longer supported. /r/nPlease update your Platform Builder installation in you want to download multiple files./r/n");

                            HALT (BLERR_MAGIC);

                            return (FALSE);

                   }

                   // Is this a standard bin image?  Check for the usual bin file signature.

                   else if (!memcmp (hdr, "B000FF/x0A", BL_HDRSIG_SIZE))//lqm: 下载 xip.bin,nk.bin,eboot.bin 时在这里执行

                   {

                            g_bBINDownload = TRUE;

 

                            if (!OEMReadData (sizeof (DWORD), (LPBYTE) &dwImageStart)// 读取 *.bin 7 个头字节后的一个 DWORD dwImageStart *.bin 记录了其映像起始地址

                                     || !OEMReadData (sizeof (DWORD), (LPBYTE) &dwImageLength))// 读取上面接着的一个 DWORD dwImageLength *.bin 记录了其映像长度

                            {

                                     EdbgOutputDebugString ("Unable to read image start/length/r/n");

                                     HALT (BLERR_MAGIC);

                                     return (FALSE);

                            }

                   }

                   // If the header signature isn't recognized, we'll assume the

                   // download file is a raw .nb0 file.

                   //

                   else

                   {

                            g_bBINDownload = FALSE;

                   }

                   if (!g_DownloadManifest.dwNumRegions)

                   {

                            g_DownloadManifest.dwNumRegions              = 1;                           // 声明 *.bin 有一条记录

                            g_DownloadManifest.Region[0].dwRegionStart  = dwImageStart;     // 声明这条记录的起始地址

                            g_DownloadManifest.Region[0].dwRegionLength = dwImageLength;// 声明这条记录的映像长度

                            // Provide the download manifest to the OEM.

                            if (g_pOEMMultiBINNotify)

                            {

                                     g_pOEMMultiBINNotify((PDownloadManifest)&g_DownloadManifest);

                            }

                   }

                   // Locate the current download manifest entry (current download file).

                   pCurDownloadFile = &g_DownloadManifest.Region[g_DownloadManifest.dwNumRegions - nNumDownloadFiles];// 当前下载文件指向 *.bin 开始

                   // give the OEM a chance to verify memory. 内存校验

                   if (g_pOEMVerifyMemory && !g_pOEMVerifyMemory (pCurDownloadFile->dwRegionStart, pCurDownloadFile->dwRegionLength))

                   {

                            EdbgOutputDebugString ("!OEMVERIFYMEMORY: Invalid image/r/n");//lqm: 很多情况下都会执行到这里 ! 映像不能获得 ?

                            HALT (BLERR_OEMVERIFY);

                            return (FALSE);

                   }

                   // check for flash image. Start erasing if it is.

                   if ( (fIsFlash = OEMIsFlashAddr(pCurDownloadFile->dwRegionStart))//lqm: 校验起始地址是否在 Flash 相应地址区域,如果是则擦除相应下载区域

                   && !OEMStartEraseFlash (pCurDownloadFile->dwRegionStart, pCurDownloadFile->dwRegionLength))

                   {

                            EdbgOutputDebugString ("Invalid Flash Address/Length/r/n");

                            HALT (BLERR_FLASHADDR);

                            return (FALSE);

                   }

                   // if we're downloading a binary file, we've already downloaded part of the image when searching

                   // for a file header.  copy what we've read so far to the destination buffer, then finish downloading.

                   if (!g_bBINDownload)

                   {

                            lpDest = OEMMapMemAddr (pCurDownloadFile->dwRegionStart, pCurDownloadFile->dwRegionStart);

                            memcpy(lpDest, hdr, BL_HDRSIG_SIZE);

                            // complete the file download...

                            // read data block

                            if (!OEMReadData ((pCurDownloadFile->dwRegionLength - BL_HDRSIG_SIZE), (lpDest + BL_HDRSIG_SIZE)))

                            {

                                     EdbgOutputDebugString ("ERROR: failed when reading raw binary file./r/n");

                                     HALT (BLERR_CORRUPTED_DATA);

                                     return (FALSE);

                            }

                   }

                   // we're downloading a .bin file - download each .bin record in turn...

                   else// 开始下载 *.bin 文件到 DRAM 中。

                   {

                            while (OEMReadData (sizeof (DWORD), (LPBYTE) &dwRecAddr) &&   // 读取 *.bin 的第 n 条记录的地址 .

                            OEMReadData (sizeof (DWORD), (LPBYTE) &dwRecLen)  && // 读取 *.bin 的第 n 条记录的长度 .

                            OEMReadData (sizeof (DWORD), (LPBYTE) &dwRecChk))    // 读取 *.bin 的第 n 条记录的校验和 .

                            {

                                     // last record of .bin file uses sentinel values for address and checksum.

                                     // 最后一条记录表示结束 . 其地址和校验和均为 0.

                                     if (!dwRecAddr && !dwRecChk)

                                     {

                                               break;// 读到最后一条记录时跳出循环

                                     }

                                     // map the record address (FLASH data is cached, for example)

                                     // 将存入的记录地址映射到指针地址 lpDest

                                     lpDest = OEMMapMemAddr (pCurDownloadFile->dwRegionStart, dwRecAddr);

                                     // read data block

                                     if (!OEMReadData (dwRecLen, lpDest))// 读取 *.bin 的第 n 条记录的内容到 lpDest. 这里先把 *.bin 的数据读到 DRAM 中。

                                     {

                                               EdbgOutputDebugString ("****** Data record %d corrupted, ABORT!!! ******/r/n", nPkgNum);

                                               HALT (BLERR_CORRUPTED_DATA);

                                               return (FALSE);

                                     }

                                     if (!VerifyChecksum (dwRecLen, lpDest, dwRecChk))// 每读取一条记录则校验一次数据

                                     {

                                               EdbgOutputDebugString ("****** Checksum failure on record %d, ABORT!!! ******/r/n", nPkgNum);

                                               HALT (BLERR_CHECKSUM);

                                               return (FALSE);

                                     }

                                     // Look for ROMHDR to compute ROM offset.  NOTE: romimage guarantees that the record containing

                                     // the TOC signature and pointer will always come before the record that contains the ROMHDR contents.

                                     //

                                     if (dwRecLen == sizeof(ROMHDR) && (*(LPDWORD) OEMMapMemAddr(pCurDownloadFile->dwRegionStart, pCurDownloadFile->dwRegionStart + ROM_SIGNATURE_OFFSET) == ROM_SIGNATURE))

                                     {

                                               DWORD dwTempOffset = (dwRecAddr - *(LPDWORD)OEMMapMemAddr(pCurDownloadFile->dwRegionStart, pCurDownloadFile->dwRegionStart + ROM_SIGNATURE_OFFSET + sizeof(ULONG)));

                                               ROMHDR *pROMHdr = (ROMHDR *)lpDest;

                                               // Check to make sure this record really contains the ROMHDR.

                                               //

                                               if ((pROMHdr->physfirst == (pCurDownloadFile->dwRegionStart - dwTempOffset)) &&

                                                        (pROMHdr->physlast  == (pCurDownloadFile->dwRegionStart - dwTempOffset + pCurDownloadFile->dwRegionLength)) &&

                                                        (DWORD)(HIWORD(pROMHdr->dllfirst << 16) <= pROMHdr->dlllast) &&

                                                        (DWORD)(LOWORD(pROMHdr->dllfirst << 16) <= pROMHdr->dlllast))

                                               {

                                                        g_dwROMOffset = dwTempOffset;

                                                        EdbgOutputDebugString("rom_offset=0x%x./r/n", g_dwROMOffset);

                                               }

                                     }

                                     // verify partial checksum

                                     OEMShowProgress (nPkgNum ++);

                                     // lqm added Progress in LCD.10-01-22

                                     while( nPkgNum>=8 )

                                     {

                                               nPkgNum = 0;

                                               LcdDrawString(">");

                                     }

                                     // end added.

                            }

                   }

                   if (g_bBINDownload)

                   {

                            // Does this .bin file contain a TOC?

                            if (*(LPDWORD) OEMMapMemAddr(pCurDownloadFile->dwRegionStart, pCurDownloadFile->dwRegionStart + ROM_SIGNATURE_OFFSET) == ROM_SIGNATURE)    //+ ksk 20051219

                            {

                                     // Contain the kernel?

                                     if (IsKernelRegion(pCurDownloadFile->dwRegionStart, pCurDownloadFile->dwRegionLength))

                                     {

                                               *pdwImageStart  = pCurDownloadFile->dwRegionStart;

                                               *pdwImageLength = pCurDownloadFile->dwRegionLength;

                                               *pdwLaunchAddr  = dwRecLen;

                                     }

                            }

                            // No TOC - not made by romimage.  However, if we're downloading more than one

                            // .bin file, it's probably chain.bin which doesn't have a TOC (and which isn't

                            // going to be downloaded on its own) and we should ignore it.

                            //

                            else if (g_DownloadManifest.dwNumRegions == 1)

                            {

                                     *pdwImageStart  = pCurDownloadFile->dwRegionStart;

                                     *pdwImageLength = pCurDownloadFile->dwRegionLength;

                                     *pdwLaunchAddr  = dwRecLen;

                            }

                   }

                   else    // Raw binary file.

                   {

                            *pdwImageStart  = pCurDownloadFile->dwRegionStart;

                            *pdwLaunchAddr  = pCurDownloadFile->dwRegionStart;

                            *pdwImageLength = pCurDownloadFile->dwRegionLength;

                   }

                   // write to flash if it's flash image

                   if (fIsFlash)

                   {

                            // finish the flash erase

                            if (!OEMFinishEraseFlash ())

                            {

                                     HALT (BLERR_FLASH_ERASE);

                                     return (FALSE);

                            }

                            // Before writing the image to flash, optionally check the image signature.

                            if (g_bBINDownload && g_pOEMCheckSignature)

                            {

                                     if (!g_pOEMCheckSignature(pCurDownloadFile->dwRegionStart, g_dwROMOffset, *pdwLaunchAddr, TRUE))

                                     HALT(BLERR_CAT_SIGNATURE);

                            }

                   }

         }

         while (--nNumDownloadFiles);

 

         if (fIsFlash)

         {

                   nNumDownloadFiles = (BYTE)g_DownloadManifest.dwNumRegions;

                   while (nNumDownloadFiles--)

                   {

                            if (!OEMWriteFlash (g_DownloadManifest.Region[nNumDownloadFiles].dwRegionStart, g_DownloadManifest.Region[nNumDownloadFiles].dwRegionLength))

                            {

                                     HALT (BLERR_FLASH_WRITE);

                                     return (FALSE);

                            }

                   }

         }

         return (TRUE);

}

 

上面程序中有如下代码:

OEMShowProgress (nPkgNum ++);

while( nPkgNum>=8 )

{

           nPkgNum = 0;

           LcdDrawString(">");

}

该程序放在反复从 SD 卡中读取 xip.bin 的一条条记录的 while 循环中,这里是为了在升级界面上显示升级的进度。 LcdDrawString(“>”) 函数是调用了 LcdDraw.c 中的函数,用于在 LCD 上绘图。

这里一定要了解 xip.bin 的文件格式,否则很难理解整个数据流的流程。

Xip.bin 以及 NK.bin 的组成:

组成:标记 (7)+Image 开始地址 (1)+Image 长度 (1) 
             
记录 0 地址 + 记录 0 + 记录 0 校验和 + 记录 0 内容 ( 文件内容 )
            
记录 1 地址 + 记录 1 + 记录 1 校验和 + 记录 1 内容 ( 文件内容 )
              ......

      结束符号

从上面的程序可以看出,

if (!OEMReadData (BL_HDRSIG_SIZE, hdr))

           {

                    EdbgOutputDebugString ("/r/nUnable to read image signature./r/n");

                    HALT (BLERR_MAGIC);

                    return (FALSE);

           }

即是将 xip.bin 的前 7 个字节的数据读到数组 hdr ,供后面分析所读的文件的类型。

if (!OEMReadData (sizeof (DWORD), (LPBYTE) &dwImageStart)// 读取 *.bin 7 个头字节后的一个 DWORD dwImageStart *.bin 记录了其映像起始地址

                             || !OEMReadData (sizeof (DWORD), (LPBYTE) &dwImageLength))// 读取上面接着的一个 DWORD dwImageLength *.bin 记录了其映像长度

                    {

                             EdbgOutputDebugString ("Unable to read image start/length/r/n");

                             HALT (BLERR_MAGIC);

                             return (FALSE);

                    }

则是将紧接着前 7 个字节的两个 WORD 数据读到 dwImageStart dwImageLength 。随后的

while (OEMReadData (sizeof (DWORD), (LPBYTE) &dwRecAddr) &&   

// 读取 *.bin 的第 n 条记录的地址 .

                    OEMReadData (sizeof (DWORD), (LPBYTE) &dwRecLen)  &&

  // 读取 *.bin 的第 n 条记录的长度 .

                    OEMReadData (sizeof (DWORD), (LPBYTE) &dwRecChk))  

  // 读取 *.bin 的第 n 条记录的校验和 .

则开始一条条的解析 xip.bin 的记录。

if (!OEMReadData (dwRecLen, lpDest))

{

           EdbgOutputDebugString ("****** Data record %d corrupted, ABORT!!! ******/r/n", nPkgNum);

                                       HALT (BLERR_CORRUPTED_DATA);

           return (FALSE);

}

用于将读取到的第 N 条记录存放到 lpDest.

分析要下载的文件并写入 flash 的代码如下:

void OEMLaunch( DWORD dwImageStart, DWORD dwImageLength, DWORD dwLaunchAddr, const ROMHDR *pRomHdr )

{

DWORD dwPhysLaunchAddr;

         OALMSG(1, (TEXT("+OEMLaunch./r/n")));

// If the user requested that a disk image (stored in RAM now) be written to the SmartMedia card, so it now.

if (g_bDownloadImage) // && (g_pBootCfg->ConfigFlags & TARGET_TYPE_NAND))

{

           // Since this platform only supports RAM images, the image cache address is the same as the image RAM address.

           switch (g_ImageType)

           {

           case IMAGE_TYPE_STEPLDR://stepldr.bin

                    if (!WriteRawImageToBootMedia(dwImageStart, dwImageLength, dwLaunchAddr))

                    {

                             OALMSG(OAL_ERROR, (TEXT("ERROR: OEMLaunch: Failed to store image to Smart Media./r/n")));

                             goto CleanUp;

                    }

                    OALMSG(TRUE, (TEXT("INFO: Step loader image stored to Smart Media.  Please Reboot.  Halting.../r/n")));

            if (g_bAutoDownload == TRUE)

            {

                             return ;

            }

                    while(1);

                    break;

 

           case IMAGE_TYPE_LOADER://eboot.bin

                    g_pTOC->id[0].dwLoadAddress = dwImageStart;

                    g_pTOC->id[0].dwTtlSectors = FILE_TO_SECTOR_SIZE(dwImageLength);

                    if (!WriteRawImageToBootMedia(dwImageStart, dwImageLength, dwLaunchAddr))

                    {

                             OALMSG(OAL_ERROR, (TEXT("ERROR: OEMLaunch: Failed to store image to Smart Media./r/n")));

                             goto CleanUp;

                    }

                    if (dwLaunchAddr && (g_pTOC->id[0].dwJumpAddress != dwLaunchAddr))

                    {

                             g_pTOC->id[0].dwJumpAddress = dwLaunchAddr;

                           #if 0 // don't write TOC after download Eboot

                             if ( !TOC_Write() ) {

                                       EdbgOutputDebugString("*** OEMLaunch ERROR: TOC_Write failed! Next boot may not load from disk *** /r/n");

                             }

                             TOC_Print();

                           #endif   // by hmseo - 061123

                    }

                    OALMSG(TRUE, (TEXT("INFO: Eboot image stored to Smart Media.  Please Reboot.  Halting.../r/n")));

                    if (g_bAutoDownload == TRUE)

                    {

                             return ;

                    }

                    while(1);

                    break;      

           case IMAGE_TYPE_RAMIMAGE://NK.bin

                    OALMSG(1, (TEXT("+IMAGE_TYPE_RAMIMAGE dwImageStart:%08x.,dwLaunchAddr : %08x/r/n"),dwImageStart,dwLaunchAddr));

                    g_pTOC->id[g_dwTocEntry].dwLoadAddress = dwImageStart;

                    g_pTOC->id[g_dwTocEntry].dwTtlSectors = FILE_TO_SECTOR_SIZE(dwImageLength);

                    // NK.bin 写到 flash.

                    if (!WriteOSImageToBootMedia(dwImageStart, dwImageLength, dwLaunchAddr))

                    {

                             OALMSG(OAL_ERROR, (TEXT("ERROR: OEMLaunch: Failed to store image to Smart Media./r/n")));

                             goto CleanUp;

                    }

                    EdbgOutputDebugString("INFO1:dwLaunchAdd : %08x  g_pTOC->id[0].dwJumpAddress :%08x, g_pTOC->id[1].dwJumpAddress :%08x/r /r/n", dwLaunchAddr, g_pTOC->id[0].dwJumpAddress,g_pTOC->id[1].dwJumpAddress);

                    if (dwLaunchAddr && (g_pTOC->id[g_dwTocEntry].dwJumpAddress != dwLaunchAddr))

                    {

                             g_pTOC->id[g_dwTocEntry].dwJumpAddress = dwLaunchAddr;

                             if ( !TOC_Write() ) // TOC 文件

                             {

                                       EdbgOutputDebugString("*** OEMLaunch ERROR: TOC_Write failed! Next boot may not load from disk *** /r/n");

                             }

                             //masked by denis_wei for test 2009-02-05   TOC_Print();

                    }

                    else

                    {

                             dwLaunchAddr= g_pTOC->id[g_dwTocEntry].dwJumpAddress;

                             EdbgOutputDebugString("INFO2: using TOC[%d] dwJumpAddress: 0x%x/r/n", g_dwTocEntry, dwLaunchAddr);

                    }

                    break;

           }

           if(ERASE_ALL_FLASH_BLOCKS)//lqm added.10-01-22

           {

                    LcdSetStringPosition(1,15);// lqm added.10-01-22

                    LcdDrawString("Starting WINCE,Please Wait......");// lqm added.10-01-22

                    //LcdSetStringPosition(1,16);// lqm added.10-01-22

           }

           if ( !ReadOSImageFromBootMedia( ) )// FLASH 读取映像到 DRAM.

           {

                    OALMSG(OAL_ERROR, (TEXT("OEMPlatformInit ERROR: Failed to load kernel region into RAM./r/n")));

                    SpinForever();

           }

}

         OALMSG(1, (TEXT("waitforconnect/r/n")));

         if (dwLaunchAddr && (g_pTOC->id[g_dwTocEntry].dwJumpAddress != dwLaunchAddr))

{

           g_pTOC->id[g_dwTocEntry].dwJumpAddress = dwLaunchAddr;

}

else

{

           dwLaunchAddr= g_pTOC->id[g_dwTocEntry].dwJumpAddress;

           OALMSG(OAL_INFO, (TEXT("INFO: using TOC[%d] dwJumpAddress: 0x%x/r/n"), g_dwTocEntry, dwLaunchAddr));

}

 

// Jump to downloaded image (use the physical address since we'll be turning the MMU off)...

//

dwPhysLaunchAddr = (DWORD)OALVAtoPA((void *)dwLaunchAddr);

OALMSG(TRUE, (TEXT("INFO: OEMLaunch: Jumping to Physical Address 0x%Xh (Virtual Address 0x%Xh).../r/n/r/n/r/n"), dwPhysLaunchAddr, dwLaunchAddr));

// Jump...

if( g_bAutoDownload == TRUE )

{

OALMSG(TRUE, (TEXT("INFO: auto update (BLOCK0IMAGE  EBOOT  NK) SUCCESS!/r/n")));}

Launch(dwPhysLaunchAddr);// 跳到指定物理地址运行程序 .

CleanUp:

 

OALMSG(TRUE, (TEXT("ERROR: OEMLaunch: Halting.../r/n")));

SpinForever();

}

在上面代码中,如下代码用于将已经读入 DRAM 的数据烧写到 flash.

if (!WriteOSImageToBootMedia(dwImageStart, dwImageLength, dwLaunchAddr))

{

           OALMSG(OAL_ERROR, (TEXT("ERROR: OEMLaunch: Failed to store image to Smart Media./r/n")));

           goto CleanUp;

}

整个 bootloader 代码量大,但是细下心来慢慢分析,其实不难理解。这里就不一一分析了。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值