第四課、XIP與HIVE
power 10:48 2009-8-25
我們的Image主要由兩部分組成:XIPKERNEL.bin和NK.bin,XIPKERNEL.bin中的東西就是那些WinCE中比較核心的又需要經常載入的一些程式和DLL檔案,這些檔案會被Boot Loader在剛啟動的時候拷貝到RAM中去,這樣就可以在RAM中XIP(Excute in place)了。在NK.bin中的基本上是需要但不至於要常駐記憶體的一些程式和DLL了,比如我們BuildIn下的大部分驅動,比如微軟的IE,mediaplayer等應用程式,甚至連裝置管理員device.exe也可以放到這裡面,這些檔案只有在需要的時候才被複製到記憶體中去執行,節約了記憶體並且也加快了啟動的時間。嘿,到這裡大概知道binfs的工作原理和重要性吧。
binfs 在燒image的時候會自動把XIPKERNEL和NK分別儲存到flash的特定的邏輯扇區上.啟動的時候Boot Loader會先把XIPKERNEL複製到RAM中,然後跳到RAM中的XIPKERNEL的進入點去執行,這個時候會跑一些OEMinit之類的CPU,記憶體,中短等初始化的過程,接著OS會從註冊表中找到binfs的一些設定,然後載入binfs的驅動使binfs分區對OS來講是可用的,假如device.exe是在NK.bin中的話,那麼在這個時候就可以用/binfs/device.exe(/binfs是假設的裝載路徑)來調用它了,如果這個時候binfs沒有初始化成功那麼,device.exe得不到執行,那麼系統肯定就起不來了。
現在來講講HIVE,其實HIVE是個很簡單的東西,都怪和binfs牽到一起搞得很多問題都走錯了方向.這麼說吧,WinCE下面就兩種註冊表,一種是RAM based,另外就是HIVE based了,預設用的是前者,如果用前者PB會在編譯的時候把common.reg和platform.reg的內容做到一個叫reginit.ini的檔案然後壓縮成default.***的檔案放到XIPKERNEL中去,image在起來的時候會把這個檔案解壓到RAM中形成RAM based註冊表,既然是RAM based那麼所有的改動都會在斷電後蒸發,哈哈。怎麼辦呢?其實再笨你也能想出來,儲存到磁碟上不就結了嗎!?對你太聰明了,但是你想如果你把註冊表全放到磁碟(SDMMC或HDD或Flash)上WinCE怎麼在沒有載入你磁碟的驅動的情況下讀到註冊表呢?而一般情況載入磁碟的驅動程式也是要註冊表的支援啊!嘿,對了,這就是HIVE想到的,看它怎麼做,它把註冊表分成兩部分(其實是三部分,當時大體還是兩步分,把user.hv和system.hv做一部分),第一部分就是叫做boot.hv的註冊表,裡面的東西就是一些在沒有拿到儲存在磁碟的註冊表之前引導時需要的一些設定,這部分的註冊表和RAM based的是一樣的,改了之後斷電就沒了,所以這部分的登錄機碼都是不需要改動的,需要改動的都放到第二部分就是了,這第二部分就是system.hv和user.hv了,也就是一直提到的要放到磁碟上的註冊表. 編譯的時候PB會根據platform.reg和Common.reg中的標籤判斷哪些表項放到boot.hv中,這個標籤就是;HIVE BOOT SECTION ;END BOOT SECTION,夾在這個標籤之間的表項PB在編譯的時候會把它們塞到boot.hv中去(boot.hv是二進位檔案,要看裡面到底放了哪些表項用一個老外寫的工具吧,好像叫d_readvol.exe,到google上找得到的),其他的內容會分別塞到default.hv和user.hv中去,最後會把這三個hv檔案統統塞到XIPKERNEL中去,這樣WinCE在引導的第一階段就把所有的hv扔到RAM中去了,然後開啟boot.hv拿到必要的資料,這其中包括如何載入放置system.hv的磁碟的驅動,所以那些和載入這個磁碟相關的驅動要統統放到boot.hv中,比如FAT檔案系統驅動,mspart分區驅動等等,這裡有一點很重要就是假如你用binfs而且device.exe在NK.bin中,那麼一定在第一階段要保證binfs可用,否則這裡就不可能為system.hv創造條件了。WinCE第一次啟動時候磁碟上沒有東東,這個時候WinCE會將記憶體中的default.hv和user.hv複製到註冊表BootVars指定的地方,default.hv往往會被重新命名為system.hv,第二次啟動會先檢查磁碟上的hv是不是和記憶體中的一致,不一致就載入磁碟上的表項。
整個過程就是這樣子,但要注意一點,HIVE註冊表也是在記憶體中啟動並執行,不同的是啟動的時候會從磁碟上去讀改動的表項,因為這樣才能保證速度,所以你做的的註冊表改動也是在記憶體中做的,這個時候如果你不掉用FlushRegister去將記憶體中的數值儲存到磁碟上那麼這些改動還是會丟失的。兩種方法來避免丟失,一種是認為去調用FlushRegister,令一種就設定一個flag讓WinCE在每次改動註冊表後自動Flush.
最後總結一下:
1.建立一個工程,把該選的組件都選上。
2.添加HIVE支援。
a. 在PB中加入"Hive-based Registry"、“FAT FILE SYSTEM”。
b.開啟platform.reg,完成如下資訊:
;HIVE BOOT SECTION
[HKEY_LOCAL_MACHINE/init/BootVars]
"SYSTEMHIVE"="Documents and Settings//system.hv" ;system.hv會儲存到/HDD/Documents and Settings/system.hv
"PROFILEDIR"="Documents and Settings" ;user.hv會儲存到/HDD/Documents and Settings/default/user.hv
"Start DevMgr"=dword:1 ;這個說是啟動device.exe,但是wince 5.0好像不用這個
"DefaultUser"="default" ;咱們只有一個使用者default,基本上就是決定user.hv的路徑了
"Flags"=dword:3 ;這個應該是wince 5.0下決定在哪個階段啟動device.exe的表項
"RegistryFlags"=dword:1 ;這個就是設定註冊表每次改動後自動flush到system.hv
;"SystemHiveInitialSize"=dword:19000 ; Initial size for hive-registry file
; END HIVE BOOT SECTION
;#####################################################################################################
; HIVE BOOT SECTION
; Add BinFS to partition table
[HKEY_LOCAL_MACHINE/System/StorageManager/PartitionTable]
"21"="BINFS"
[HKEY_LOCAL_MACHINE/System/StorageManager/BINFS]
"Folder"="BINFS"
"FriendlyName"="Bin FileSystem"
"Dll"="binfs.dll"
; MountFlags:
; 0x10 specifies that this file system is to be mounted as an external
; ROM filesystem shadowing the /windows directory
; 0x1 specifies that the mountpoint /BINFS is to be hidden
;
"MountFlags"=dword:10
"BootPhase"=dword:0
[HKEY_LOCAL_MACHINE/System/StorageManager/AutoLoad/SMFlash]
"DriverPath"="Drivers//BlockDevice//SMFlash"
"LoadFlags"=dword:1
"MountFlags"=dword:11
"BootPhase"=dword:0
[HKEY_LOCAL_MACHINE/Drivers/BlockDevice/SMFlash]
"Prefix"="DSK"
"Dll"="BIBDrv.dll"
"Order"=dword:0
"Ioctl"=dword:4
"Profile"="SMFlash"
"FriendlyName"="Samsung Flash Driver"
"MountFlags"=dword:11
"BootPhase"=dword:0
; Bind BINFS to the block driver
[HKEY_LOCAL_MACHINE/System/StorageManager/Profiles/SMFlash]
"DefaultFileSystem"="BINFS"
"PartitionDriver"="mspart.dll"
"AutoMount"=dword:1
"AutoPart"=dword:1
"MountFlags"=dword:11
"Folder"="ResidentFlash"
"Name"="Samsung Flash Disk"
"BootPhase"=dword:0 ;要在第一階段載入binfs
[HKEY_LOCAL_MACHINE/System/StorageManager/Profiles/NANDFLASH/BINFS]
"MountHidden"=dword:1
"MountAsROM"=dword:1
[HKEY_LOCAL_MACHINE/System/StorageManager/AutoLoad/SMFlash/Filters/CacheFilt]
"Dll"="cachefilt.dll"
"LockIOBuffers"=dword:1
; END HIVE BOOT SECTION
;#####################################################################################################
;1st fat area
; HIVE BOOT SECTION
[HKEY_LOCAL_MACHINE/Drivers/BuiltIn/FlashDisk]
"Prefix"="DSK"
"Dll"="ONDisk.dll"
"Order"=dword:1
; "Index"=dword:1
"IClass"=multi_sz:"{A4E7EDDA-E575-4252-9D6B-4195D48BB865}"
"Profile"="FlashDisk"
"BmlVolumeId"=dword:0 ; BML volume ID = 0
"BmlPartitionId"=dword:8 ; BML parition ID = PARTITION_ID_FILESYSTEM
"WMRStartSector"=dword:0
"WMRNumOfSector"=dword:40000 ; 128MByte
; "Flags"=dword:11000 ; do not load again in boot phase 2 ;
IF IMGHIVEREG
"Flags"=dword:1000 ; do not load again in boot phase 2 ;
ENDIF IMGHIVEREG
[HKEY_LOCAL_MACHINE/System/StorageManager/Profiles/FlashDisk]
"DefaultFileSystem"="FATFS"
"PartitionDriver"="mspart.dll"
"Name"="PocketMory MLC Disk"
; "Folder"="Sys"
"AutoMount"=dword:1
"AutoPart"=dword:1
"AutoFormat"=dword:1
; "MountFlags"=dword:0
; "Ioctl"=dword:4
IF IMGHIVEREG
"MountAsBootable"=dword:1 ; for Hive-based registry,這個是wince 5.0下指定這個分區儲存system.hv的關鍵
ENDIF IMGHIVEREG
[HKEY_LOCAL_MACHINE/System/StorageManager/AutoLoad/FlashDisk]
"DriverPath"="Drivers//BuiltIn//FlashDisk"
; LoadFlags 0x01 == load synchronously
"LoadFlags"=dword:1
"BootPhase"=dword:0
[HKEY_LOCAL_MACHINE/System/StorageManager/Profiles/FlashDisk/FATFS]
"FriendlyName"="PocketMory FAT FileSystem"
; "Dll"="fatfsd.dll"
"Flags"=dword:00000014 ; FATFS_ENABLE_BACKUP_FAT | FATFS_DISABLE_AUTOSCAN
"Folder"="Sys"
"FormatExfat"=dword:1
; "EnableCacheWarm"=dword:0
"CheckForFormat"=dword:1
"EnableWriteBack"=dword:1
"EnableCacheWarm"=dword:0
[HKEY_LOCAL_MACHINE/System/StorageManager/AutoLoad/FlashDisk/Filters/CacheFilt]
"Dll"="cachefilt.dll"
"LockIOBuffers"=dword:1
[HKEY_LOCAL_MACHINE/System/StorageManager/Profiles/FlashDisk/FATFS/Filters/CacheFilt]
"Dll"="cachefilt.dll"
"LockIOBuffers"=dword:1
; END HIVE BOOT SECTION
;#####################################################################################################
3.開啟SMDK6410/SMDK6410.bat,開啟xip開關
set IMGMULTIXIP=1
4.對FILES/config.bib進行修改
;下面這個layout可以隨便改,以適應自己的系統。要注意layout的規律哦。
#define CHAIN_ADDRESS 806C0000
#define CHAIN_LENGTH 00004000
;-----------------------------------------------------
; NAME ADDRESS SIZE TYPE
;-----------------------------------------------------
XIPKERNEL 80100000 005c0000 RAMIMAGE
CHAIN $(CHAIN_ADDRESS) $(CHAIN_LENGTH) RESERVED
NK 80700000 03F00000 NANDIMAGE
RAM 80700000 05600000 RAM
FLASH 92000000 00100000 RESERVED
5.對FILES/platform.bib進行修改
把所有的NK都更改為$(XIPKERNEL),為了在xipkernel啟動就把外圍裝置驅動load到記憶體,要不會造成外圍裝置用不了。
6.加入最小系統檔案。要加入的檔案有:
//必須的有
"nk.exe",
"coredll.dll",
"filesys.dll",
"exfat.dll",
"diskcache.dll",
"fatutil.dll",
"binfs.dll",
"fsdmgr.dll",
"mspart.dll",
"ceddk.dll",
"cachefilt.dll",
"kernel.dll",
"k.coredll.dll",
"fpcrt.dll",
"k.fpcrt.dll",
"romfsd.dll",
"device.dll",
"udevice.exe",
"devmgr.dll",
"kitl.dll",
"pm.dll",
"devmgr.dll",
"wince.nls",
"initobj.dat",
"ONDisk.dll",
"initdb.ini",
"boot.hv",
//推薦繼續添加的
"busenum.dll",
"servicesEnum.dll",
"servicesd.exe",
"services.exe",
"servicesStart.exe",
"oalioctl.dll",
添加方法有三種:
1.編譯一次工程,然後修改build下的common.bib,把對應的都改為XIPKERNEL,MAKE IMAGE.(注意:只能用make image)
2.編譯一次工程,然後修改build下的ce.bib,把對應的都改為XIPKERNEL,在VS2005中project->open realease...,運行
romimage ce.bib(注意:只能這樣用)
3.把附件中的processbib.exe,preromimage.bat加入到FILES/下,build 該工程即可,編譯一次後也可以直接make image.推薦這個方法,一勞永逸,而且不容易操作出錯哦。
7.用eboot燒寫xip.bin.