其实所有的工作都是改注册表,但是怎么改,为什么这么改要搞懂就蛮费一番心思了,好在俺是喜欢钻研的动物,
我们的案子是基于 samsung S 3C 2440A + samsung ONENAND+WinCE5.0 的,开发平台是 platform builder 5.0 ,首先我们基于 RAM register 的 image 已经可以正常跑起来了, Flash 除了放置 image 外其他的空间为用户提供文件系统,这部分的驱动程序是用三星的 PocetStoreII15 。先来回味一下底层的东东,我们的 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 的建立工作是在用 UT ( OEM 自己的一种底层的工具集)实现的, UT 在烧 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 牵到一起搞得很多问题都走错了方向,本来一天就能搞定结果搞了四五天, NND 。这么说吧, 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 )在 PB 中将 HIVEbased Registers 拉到项目的 WorkSpaces 中来。
2 )把 Platform.reg 中的下列表项加到 boot.hv 中
3 ) Build Image 了
附上我的注册表设置做参考:
;-----------------------------------------------------------------------------------------
;ALL these entries below will be add to boot.hv when hive register is enabled!
;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
;###########################################################################
; 这个部分是 binfs 的注册表项,如果你不是用的 binfs 那么不用将它们拉到 boot.hv 中
[HKEY_LOCAL_MACHINE/System/StorageManager/AutoLoad/SMFlash]
"DriverPath"="Drivers//BlockDevice//SMFlash"
"LoadFlags"=dword:1
"MountFlags"=dword:11
"BootPhase"=dword:0
"Flags"=dword:1000
[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
"Flags"=dword:1000
; Bind BINFS to the block driver
[HKEY_LOCAL_MACHINE/System/StorageManager/Profiles/SMFlash]
"DefaultFileSystem"="BINFS" ;binfs 的路径为 /BINFS
"PartitionDriver"="mspart.dll"
"AutoMount"=dword:1
"AutoPart"=dword:1
"MountFlags"=dword:11
"Folder"="ResidentFlash"
"Name"="Samsung Flash Disk"
"BootPhase"=dword:0
"Flags"=dword:1000
"MountHidden"=dword:0 ; 有了这个你就可以在 /BINFS 目录下看到所有的 NK.bin 的东东了
;###########################################################################
;###########################################################################
; 这个部分是设置保存 system.hv 的磁盘的驱动程序,每个人不一样了 , 但是大同小异
; 我这里用的是 PoketStroeII15 的 Flash 驱动, system.hv 保存在第一个 Flash 分区上
IF BSP_POCKETSTORE
[HKEY_LOCAL_MACHINE/Drivers/BuiltIn/PocketStore]
"Prefix"="DSK"
"Dll"="ONDisk.dll"
"Order"=dword:1
"Profile"="PocketStore"
"IClass"=multi_sz:"{A4E7EDDA-E575-4252-9D6B-4195D48BB865}"
"BmlVolumeId"=dword:0 ; BML volume ID = 0
"BmlPartitionId"=dword:8 ; BML parition ID = PARTITION_ID_FILESYSTEM
"Index"=dword:2
"Flags"=dword:1000 ; 这个 flag 指定这个驱动只在 boot.hv 中加载一次
[HKEY_LOCAL_MACHINE/System/StorageManager/Profiles/PocketStore]
"DefaultFileSystem"="FATFS"
"PartitionDriver"="mspart.dll"
"AutoMount"=dword:1
"AutoPart"=dword:1
"AutoFormat"=dword:1
"MountAsBootable"=dword:1 ; 这个是 wince 5.0 下指定这个分区保存 system.hv 的关键
"Folder"="HDD"
"Name"="NAND Drive"
"Ioctl"=dword:4
[HKEY_LOCAL_MACHINE/System/StorageManager/Profiles/PocketStore/FATFS]
"EnableCacheWarm"=dword:0
ENDIF