第四课、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.