天天看點

WinCE6.0 BootloaderMain源碼分析之DownloadImage

   先聲明一下,圖檔太大,顯示效果不佳,可以拖拽到新視窗中看。

     在做好下載下傳前的準備後,開始正式下載下傳鏡像。DownloadImage函數定義在檔案blcommon.c中,下面是的源代碼:

三個參數都是輸出參數,分别輸出鏡像的開始位置、鏡像的大小以及啟動鏡像的位址。這裡注意,鏡像的開始處會有一些頭資訊,是以開始位置與啟動鏡像的位址是不一樣的。

217到222行通過OEMReadData函數讀取鏡像的前面7個位元組,這7個位元組代表了鏡像檔案的格式。每一個鏡像檔案在檔案資料的起始位置都有7個位元組的特征碼,與鏡像檔案的格式一一對應:

"N000FF\x0A"----- 該類型的鏡像檔案的資料是多區段的記錄型鏡像檔案的區段資訊 

"X000FF\x0A"----- 該類型隻在WinCE5.0及以前的版本中用于多區段的鏡像檔案 

"B000FF\x0A"----- 最普通常用的記錄型鏡像檔案格式,以.bin為檔案名字尾 

"S000FF\x0A"----- 帶有數字簽名的鏡像檔案,以.bin為檔案名字尾 

"R000FF\x0A"----- 帶有數字簽名的鏡像檔案,以.nk0為檔案名字尾 

無特征碼        ----- 這時當做原始鏡像檔案進行處理

OEMReadData函數在上面的源代碼中使用了很多次,由OEM使用者自己實作,其定義在檔案main.c中,根據下載下傳鏡像的方式不同(以太網或USB),調用不同的接口讀取鏡像資料,實作的源碼如下:

BOOL OEMReadData(DWORD dwData, PUCHAR pData) 

        BOOL ret; 

         OALMSG(OAL_FUNC, (TEXT("+OEMReadData.\r\n"))); 

        //OALMSG(TRUE, (TEXT("\r\nINFO: dwData = 0x%x, pData = 0x%x \r\n"), dwData, pData)); 

        if ( g_bUSBDownload == FALSE ) 

        { 

                ret = EbootEtherReadData(dwData, pData); 

        } 

        else if ( g_bUSBDownload == TRUE ) // jylee 

                ret = UbootReadData(dwData, pData); 

        }         

        return(ret); 

}

227到269行表示使用的是多區段的記錄型鏡像檔案格式,多區段的鏡像起始就是作業系統或者BootLoader的運作時二進制資料分散在不連續的實體存儲區間。多區段意味着多檔案,即需要下載下傳多個檔案,是以在267行中用nNumDownLoadFiles來記錄下載下傳的檔案數量。該類型的鏡像檔案并不是真正的WinCE作業系統或者BootLoader的二進制運作時資料,隻是供下載下傳多區段型鏡像所使用的頭資訊,稱為Manifest前導資料。當作業系統的鏡像隻有一個區段,或者是使用自身包含有存儲位置頭資訊的記錄型鏡像檔案格式時,就可以不使用Manifest前導資料。這點要注意,否則下面的一些代碼就看不明白了。該類型的鏡像檔案使用專門的DownloadManifest型的全局變量g_DownloadManifest來存放。下面看看這種類型的鏡像檔案的資料結構。緊随7位元組的格式類型特征碼後是4位元組的校驗碼,然後是4位元組的區段個數。接下來便是存放在g_DownloadManifest.Region數組各個元素中的資料。RegionInfo結構體有3個成員dwRegionStart、dwRegionLength、szFileName,分别為鏡像區段在實體存儲的起始位址、以位元組為機關的區段長度和與鏡像區段對應的鏡像檔案的檔案名。

231行開始首先讀取4位元組的校驗碼,然後讀取區段數量,存儲到g_DownloadManifest.dwNumRegions中,然後把該鏡像區段的資料都讀取到g_DownloadManifest結構體中,最後調用VerifyChecksum函數對資料執行校驗。

263行的OEMMultiBINNotify函數是當BootLoader要下載下傳多區段的作業系統鏡像時調用來向使用者發出通知。

272到278行表示的是WinCE5.0及之前版本支援的多區段的鏡像檔案,由于分析的平台是以WinCE6.0為作業系統的,是以這裡直接傳回FALSE。

281到292行表示的是最常用最普通的記錄型鏡像檔案格式,下面對這種.bin的鏡像檔案的内部結構進行描述。最初的7位元組特征碼之後是鏡像檔案在目标系統中的目的地的實體存儲起始位置和以位元組為機關的長度,各占4位元組,對應RegionInfo結構體的dwRegionStart和dwRegionLength兩個成員。再接下來便是具體存放作業系統二進制資料的擁有相同結構的多條Record記錄,每條Record包括4位元組的記憶體起始位址dwRecAddr、4位元組的記錄長度dwRecLen、4位元組的校驗碼dwRecChk和dwRecLen個位元組的記錄資料組成。校驗無誤以後将去除頭資訊的記錄資料存放到dwRecAddr指定位址的實體存儲位置。如果記錄的目的存儲位置是Flash儲存設備,則要先緩存到RAM記憶體中,待整個鏡像檔案下載下傳完以後再一起寫入Flash。在源代碼中,281到292行隻讀出了dwRegionStart和dwRegionLength。

305到317行是當僅僅下載下傳了單個的.bin檔案時,沒有填充g_DownloadManifest結構體,無法通知使用者,是以此時要人工手動填充DownloadManifest結構體,隻是沒有鏡像區段對應的檔案名。

324到329行調用函數EMVerifyMemory檢測目前下載下傳的鏡像對應的虛拟記憶體位址區域是否映射到了使用者可以使用的實體存儲區域。

332到338行表示當下載下傳的鏡像的目的存儲位址是Flash時,擦除Flash。函數OEMIsFlashAddr和OEMStartEraseFlash的定義都在檔案\WINCE600\PLATFORM\<BSP name>\SRC\BOOTLOADER\EBOOT\flash.h中。OEMIsFlashAddr用來判斷一個給定的位址值是否落在系統的Flash儲存設備範圍内。OEMStartEraseFlash負責初始化并啟動Flash存儲器的擦除程序。本平台的源碼中,這兩個函數都是空的,沒有任何操作。

342到356行是當g_bBINDownload為FALSE時進行的處理,即下載下傳的鏡像是最普通常用的原始型鏡像檔案,以.nb0為檔案字尾的二進制檔案。這裡需要解釋的是為何要調用OEMMapMemAddr函數之後才開始讀取鏡像檔案?由于Flash操作速度比RAM慢,在片擦除的時候可能會使讀寫操作停滞,這樣在每次下載下傳作業系統鏡像檔案的時候可能是下載下傳停滞。調用OEMMapMemAddr将Flash位址映射到RAM位址中,這樣向Flash寫資料實際上先寫到RAM中,然後再寫到Flash中,就不會感覺到下載下傳停滞了。

      358到416行是用來下載下傳.bin檔案,按照一定的順序依次下載下傳鏡像的所有記錄。結合該類型鏡像檔案格式,相信大家很容易明白。同樣這裡也用到了OEMMapMemAddr函數進行Flash位址映射來防止下載下傳停滞現象。391行到406行是用來尋找作業系統鏡像檔案中的全局變量資料資訊TOC的,首先比較資料長度dwRecLen與sizeof(ROMHDR)的大小,以此來判斷該條記錄是否為TOC記錄,dwTempOffset取得的是RAM記憶體的偏移位址,398到401行的if語句是進一步通過TOC的成員判斷該條記錄确實是TOC記錄的。ROM_SIGNATURE_OFFSET和ROM_SIGNATURE兩個宏定義都在頭檔案\WINCE600\PUBLIC\COMMOM\OAK\INC\romldr.c中。 

430到454行根據下載下傳的bin檔案是否包含有TOC和核心分别對三個輸出參數進行設定。433行是判斷bin檔案是夠有TOC資料,如果有調用IsKernelRegion函數判斷檔案中是否有核心(通過查找是否有nk.exe的檔案名),如果有則傳回NK.bin的起始位址,長度和跳轉位址。447行表示bin鏡像隻含有一個區段,同樣傳回鏡像的起始位址、大小和啟動位址。這裡需要注意的是啟動位址指派為dwRecLen,因為通常bin檔案的最後一條記錄是位址dwRecAddr和校驗和dwRecChk都為0,而dwRecLen标示的其實是實際的入口點。

455到460行是當鏡像檔案為原始的二進制檔案時,對三個輸出參數進行指派。

463到477行表示如果鏡像檔案的目的存儲位址是Flash,則調用OEMFinishEraseFlash函數結束Flash存儲器的擦除程序,而且即将進入寫鏡像檔案到Flash的處理階段。在寫鏡像到Flash之前,調用g_pOEMCheckSignature對鏡像進行校驗。該函數用于驗證WinCE image中的署名并檢查其有效性。pCurDownloadFile->dwRegionStart為被下載下傳image的存儲起始位址,g_dwROMOffset為config.bib檔案中定義的ROMOFFSET的值,*pdwLaunchAddr為被加載的位址,最後一個參數為TURE表示是被下載下傳的image檔案。

482到493行,調用函數OEMWriteFlash将暫存在RAM記憶體緩沖區中的一個或者多個作業系統鏡像區段的資料寫入Flash儲存設備。

本文轉自jazka 51CTO部落格,原文連結:http://blog.51cto.com/jazka/605776,如需轉載請自行聯系原作者