CheckSum是一種用于檢查數(shù)據(jù)文件有沒有發(fā)生變化的方法,對(duì)于一些重要的數(shù)據(jù)文件為了檢查傳輸過程過程中有沒有數(shù)據(jù)的損壞或丟失,常常會(huì)用到CheckSum算法。
WinCE中經(jīng)常用到CheckSum的地方就是對(duì)即將燒寫進(jìn)Flash中的image文件進(jìn)行校驗(yàn),和燒寫完對(duì)寫入的數(shù)據(jù)進(jìn)行完整性檢查,一般這里的image有OSimage和UT的bin文件兩種。
CheckSum的原理是把一個(gè)文件以二進(jìn)制的方式打開,將里面所有的字節(jié)的值一個(gè)一個(gè)的累加起來,一直到最后一個(gè)字節(jié),最后得到一個(gè)累加值,它就是我們要的CheckSum的結(jié)果。從CheckSum的這個(gè)特性可知數(shù)據(jù)值為0的字節(jié)是不會(huì)影響到最終的結(jié)果,這種特性我認(rèn)為也是CheckSum的一個(gè)弱點(diǎn),不能像MD5,SHA1等摘要算法一樣基本上能反映出哪怕一個(gè)bit的改動(dòng),但是這個(gè)特性也給WinCE運(yùn)行期間計(jì)算保存在Flash上的image數(shù)據(jù)文件的完整性帶來了方便。
為了從Flash中得到正確的CheckSum值必須先了解image在Flash中的燒寫方式,這包括了解image文件內(nèi)部是怎么組織的,F(xiàn)lash的分區(qū)和塊的分配是如何進(jìn)行的。
先以Sumsung的FLASH為例來分析一下Flash的分區(qū)大體原則:
WinCE的Flash分區(qū)大體分為Nand BootLoader(NBL)區(qū),Binfs區(qū)和文件區(qū),NBL區(qū)存放BootLoader和燒寫Image的工具程序,Binfs分區(qū)存放MBR、image的XIPKERNEL.bin、Chain.bin和NK.bin等OS的數(shù)據(jù)。文件區(qū)一般格式化為FAT分區(qū)讓W(xué)inCE上層的磁盤和分區(qū)管理程序管理。Flash的分區(qū)是由UT在燒入image的時(shí)候決定的,包括每個(gè)分區(qū)的起止塊地址,分區(qū)的大小和類型等,Detail如下:
1)NBL區(qū)一般占10個(gè)塊(128K/塊)的大小,分區(qū)雖小但是卻是最重要的部分,保存著UT的三大模塊:NBL1(bootloader),NBL2(IPL,Init Program Loader)和NBL3(Upgrade Tools),其中NBL1和NBL2共同保存在FlASH的第一個(gè)block中,F(xiàn)LASH芯片在生產(chǎn)的時(shí)候廠商都會(huì)特別保障這些block的可靠性,特別是保存了最開始bootloader代碼和IPL的第一塊。按經(jīng)驗(yàn)來講,NBL的三個(gè)模塊加起來一共大約400多K,其占用的10塊的block=128K×10 byte的空間大部分是空余的,為了下面敘述方便,這里假設(shè)NBL3_END_BLCOK為NBL的最后的block編號(hào)。
2)Binfs分區(qū)緊接著BL分區(qū),即CE_START_BLOCK=NBL3_END_BLCOK+1,然后一般會(huì)將Binfs分區(qū)的第一個(gè)塊存放MBR,MBR在這里僅僅是個(gè)標(biāo)志,不像PC的硬盤中的MBR主要用來保存分區(qū)表的信息和引導(dǎo)代碼。所以Binfs分區(qū)中保存OS數(shù)據(jù)的起止block范圍為CE_START_BLOCK+1到CE_START_BLOCK+CE_MAX_BLOCK為止,我接觸的項(xiàng)目中其大小一般為250個(gè)塊左右,大約等于30Mbytes,WinCE的image一般不會(huì)超過這個(gè)大小,如果需要可以在分區(qū)時(shí)加大它的大小。
3)Flash的文件分區(qū)就是將剩下的block模擬成為和硬盤,CF卡類似的塊設(shè)備讓W(xué)inCE加載成盤符使用。
現(xiàn)在回到正題:如何計(jì)算CheckSum。
1)UT的CheckSum計(jì)算
UT的bin文件是由bootloader.bin(NBL1),IPL.bin(NBL2)和UpgradeTools.bin(NBL3)這三文件打成的一個(gè)封包,然后用PC上的checksum工具計(jì)算出checksum值,我們的目的就是在WinCE起來后用AP能通過讀Flash的NBL的三個(gè)分區(qū)并實(shí)時(shí)計(jì)算到這個(gè)值。
UT的bin文件最后會(huì)被完整的燒寫到NAND Flash的編號(hào)為0到NBL3_END_BLCOK的block中(雖然會(huì)被分為三塊燒,但是數(shù)據(jù)是完整的),具體占用多少block由bin文件的大小決定,剩余的空間會(huì)以0填滿。雖然不知道bin文件具體的結(jié)尾的位置,但是知道剩余空間填0的這個(gè)特性后,我們就可以直接調(diào)用NAND Flash的驅(qū)動(dòng)程序,而且可以使用輕量級(jí)的不帶壞塊管理的驅(qū)動(dòng)代碼直接去讀0到NBL3_END_BLCOK的所有數(shù)據(jù),然后把每個(gè)byte累加起來就能得到CheckSum的值了。
2)IMG的CheckSum計(jì)算
大家都知道,如果定義了MultiXIP region的話,WinCE的image用romimage編譯出來會(huì)生成多個(gè)bin文件,這里假設(shè)我們?cè)谂渲胕mage的bib文件中定義了兩個(gè)region:XIPKernel和NK,那么在執(zhí)行romimage ce.bib 之后我們會(huì)得到XIPKernel.bin,NK.bin,Chain.bin三個(gè)文件,最后調(diào)用makebinfs生成一個(gè)ceimgb.nb0的image鏡像文件,我們也會(huì)先用CheckSum工具對(duì)ceimgb.nb0進(jìn)行運(yùn)算得到其完整的CheckSum值。
燒寫的過程和UT有兩點(diǎn)不同:1)燒寫內(nèi)容選擇上,UT的bin文件的所有數(shù)據(jù)會(huì)被燒入Flash,而IMG的鏡像文件包含了一些不需要燒入的頭信息,所以可能導(dǎo)致燒入Flash的數(shù)據(jù)不完整;2)燒寫使用的NAND Flash的函數(shù)不一樣,因?yàn)镮MG燒寫在FLASH中的位置位于普通的不受特殊保護(hù)的塊區(qū),所以要考慮到壞塊的管理,所以在調(diào)用具體的讀寫接口的時(shí)候要使用較高一層的代碼,拿samsung的flash驅(qū)動(dòng)PoketStoreII為例,燒寫UT時(shí)用的讀寫函數(shù)為NF_ReadPage ,而燒寫IMG鏡像使用的時(shí)STL_Read/Write。
第一個(gè)不同點(diǎn)決定了我們?nèi)绻苡?jì)算得到正確的IMG的CheckSum值則必須將沒有燒入到Flash中的ceimgb.nb0的頭部數(shù)據(jù)燒寫到為保存IMG預(yù)留的并且沒有被占用的Flash中,比如IMG預(yù)留空間的最后一塊,塊號(hào)為CE_START_BLOCK+CE_MAX_BLOCK。我們通過修改燒寫IMG的代碼,在燒寫完IMG的三個(gè)bin的數(shù)據(jù)后把從0x0到0x248(記不太清楚,大概)的數(shù)據(jù)寫到塊CE_START_BLOCK+CE_MAX_BLOCK中。這樣的話因?yàn)槠渌目沼嗫臻g被0填充,我們就可以調(diào)用STL_READ把從CE_START_BLOCK+1(+1是為了略過MBR塊)到CE_START_BLOCK+CE_MAX_BLOCK數(shù)據(jù)全讀取出來并且累加得到最后的CheckSum值。