CheckSum是shi一yi種zhong用yong於yu檢jian查zha數shu據ju文wen件jian有you沒mei有you發fa生sheng變bian化hua的de方fang法fa,對dui於yu一yi些xie重zhong要yao的de數shu據ju文wen件jian為wei了le檢jian查zha傳chuan輸shu過guo程cheng過guo程cheng中zhong有you沒mei有you數shu據ju的de損sun壞huai或huo丟diu失shi,常chang常chang會hui用yong到daoCheckSum算法。
WinCE中經常用到CheckSum的地方就是對即將燒寫進Flash中的image文件進行校驗,和燒寫完對寫入的數據進行完整性檢查,一般這裏的image有OSimage和UT的bin文件兩種。
CheckSum的(de)原(yuan)理(li)是(shi)把(ba)一(yi)個(ge)文(wen)件(jian)以(yi)二(er)進(jin)製(zhi)的(de)方(fang)式(shi)打(da)開(kai),將(jiang)裏(li)麵(mian)所(suo)有(you)的(de)字(zi)節(jie)的(de)值(zhi)一(yi)個(ge)一(yi)個(ge)的(de)累(lei)加(jia)起(qi)來(lai),一(yi)直(zhi)到(dao)最(zui)後(hou)一(yi)個(ge)字(zi)節(jie),最(zui)後(hou)得(de)到(dao)一(yi)個(ge)累(lei)加(jia)值(zhi),它(ta)就(jiu)是(shi)我(wo)們(men)要(yao)的(de)CheckSum的結果。從CheckSum的這個特性可知數據值為0的字節是不會影響到最終的結果,這種特性我認為也是CheckSum的一個弱點,不能像MD5,SHA1等摘要算法一樣基本上能反映出哪怕一個bit的改動,但是這個特性也給WinCE運行期間計算保存在Flash上的image數據文件的完整性帶來了方便。
為了從Flash中得到正確的CheckSum值必須先了解image在Flash中的燒寫方式,這包括了解image文件內部是怎麼組織的,Flash的分區和塊的分配是如何進行的。
先以Sumsung的FLASH為例來分析一下Flash的分區大體原則:
WinCE的Flash分區大體分為Nand BootLoader(NBL)區,Binfs區和文件區,NBL區存放BootLoader和燒寫Image的工具程序,Binfs分區存放MBR、image的XIPKERNEL.bin、Chain.bin和NK.bin等OS的數據。文件區一般格式化為FAT分區讓WinCE上層的磁盤和分區管理程序管理。Flash的分區是由UT在燒入image的時候決定的,包括每個分區的起止塊地址,分區的大小和類型等,Detail如下:
1)NBL區一般占10個塊(128K/塊)的大小,分區雖小但是卻是最重要的部分,保存著UT的三大模塊:NBL1(bootloader),NBL2(IPL,Init Program Loader)和NBL3(Upgrade Tools),其中NBL1和NBL2共同保存在FlASH的第一個block中,FLASH芯片在生產的時候廠商都會特別保障這些block的可靠性,特別是保存了最開始bootloader代碼和IPL的第一塊。按經驗來講,NBL的三個模塊加起來一共大約400多K,其占用的10塊的block=128K×10 byte的空間大部分是空餘的,為了下麵敘述方便,這裏假設NBL3_END_BLCOK為NBL的最後的block編號。
2)Binfs分區緊接著BL分區,即CE_START_BLOCK=NBL3_END_BLCOK+1,然後一般會將Binfs分區的第一個塊存放MBR,MBR在這裏僅僅是個標誌,不像PC的硬盤中的MBR主要用來保存分區表的信息和引導代碼。所以Binfs分區中保存OS數據的起止block範圍為CE_START_BLOCK+1到CE_START_BLOCK+CE_MAX_BLOCK為止,我接觸的項目中其大小一般為250個塊左右,大約等於30Mbytes,WinCE的image一般不會超過這個大小,如果需要可以在分區時加大它的大小。
3)Flash的文件分區就是將剩下的block模擬成為和硬盤,CF卡類似的塊設備讓WinCE加載成盤符使用。
現在回到正題:如何計算CheckSum。
1)UT的CheckSum計算
UT的bin文件是由bootloader.bin(NBL1),IPL.bin(NBL2)和UpgradeTools.bin(NBL3)這三文件打成的一個封包,然後用PC上的checksum工具計算出checksum值,我們的目的就是在WinCE起來後用AP能通過讀Flash的NBL的三個分區並實時計算到這個值。
UT的bin文件最後會被完整的燒寫到NAND Flash的編號為0到NBL3_END_BLCOK的block中(雖然會被分為三塊燒,但是數據是完整的),具體占用多少block由bin文件的大小決定,剩餘的空間會以0填滿。雖然不知道bin文件具體的結尾的位置,但是知道剩餘空間填0的這個特性後,我們就可以直接調用NAND Flash的驅動程序,而且可以使用輕量級的不帶壞塊管理的驅動代碼直接去讀0到NBL3_END_BLCOK的所有數據,然後把每個byte累加起來就能得到CheckSum的值了。
2)IMG的CheckSum計算
大家都知道,如果定義了MultiXIP region的話,WinCE的image用romimage編譯出來會生成多個bin文件,這裏假設我們在配置image的bib文件中定義了兩個region:XIPKernel和NK,那麼在執行romimage ce.bib 之後我們會得到XIPKernel.bin,NK.bin,Chain.bin三個文件,最後調用makebinfs生成一個ceimgb.nb0的image鏡像文件,我們也會先用CheckSum工具對ceimgb.nb0進行運算得到其完整的CheckSum值。
燒寫的過程和UT有兩點不同:1)燒寫內容選擇上,UT的bin文件的所有數據會被燒入Flash,而IMG的鏡像文件包含了一些不需要燒入的頭信息,所以可能導致燒入Flash的數據不完整;2)燒寫使用的NAND Flash的函數不一樣,因為IMG燒寫在FLASH中的位置位於普通的不受特殊保護的塊區,所以要考慮到壞塊的管理,所以在調用具體的讀寫接口的時候要使用較高一層的代碼,拿samsung的flash驅動PoketStoreII為例,燒寫UT時用的讀寫函數為NF_ReadPage ,而燒寫IMG鏡像使用的時STL_Read/Write。
第一個不同點決定了我們如果要能計算得到正確的IMG的CheckSum值則必須將沒有燒入到Flash中的ceimgb.nb0的頭部數據燒寫到為保存IMG預留的並且沒有被占用的Flash中,比如IMG預留空間的最後一塊,塊號為CE_START_BLOCK+CE_MAX_BLOCK。我們通過修改燒寫IMG的代碼,在燒寫完IMG的三個bin的數據後把從0x0到0x248(記不太清楚,大概)的數據寫到塊CE_START_BLOCK+CE_MAX_BLOCK中。這樣的話因為其他的空餘空間被0填充,我們就可以調用STL_READ把從CE_START_BLOCK+1(+1是為了略過MBR塊)到CE_START_BLOCK+CE_MAX_BLOCK數據全讀取出來並且累加得到最後的CheckSum值。