WinCE上BINFS实现详解
網上不少介紹三星24x0系列的BINFS啟動方式實現,有些內容上描述的不是非常全面
下面就WinCE6上的BINFS實現,從基本原理到修改BSP,再到如何燒錄啟動做一個較全面的講解
一 BINFS到底是什么?
其實BINFS就是MS給CE做的一種存放系統鏡像的一個文件系統。
一說文件系統,大家可能比較頭大。那么這么說,其實就是一個結構體(說是文件系統確實比較勉強,結構體可能更合適),里面有記錄各模塊的起始地址,大小等的信息,你要找模塊可以根據這個信息到后面找。
二 為什么要用BINFS?有什么好處?
其實我覺得最大的好處是“按需加載系統模塊到內存”,這里衍生出兩個優點:
1 開機需要加載的核心部分很少,大大減少開機讀取系統的時間
2 不需要為操作系統預留全尺寸的內存大小,只需預留最小開機核心的大小,剩下的作為通用內存空間,所以使系統內存使用有了很大靈活性,可用系統內存大大增加
三 BINFS的實現基礎
這里不得不說WinCE的燒寫和引導方式
在默認情況下,大家都知道WinCE會生成nk.bin和nk.nb0
bin其實就是nb0的壓縮形式
nb0怎么可以壓縮?
因為nb0中有很多空白區域
bin是如何壓縮的?
很簡單的描述下,就是用一個結構體記錄一下,起始地址,大小,校驗和,然后后面就是實際的內容
這樣的一個一個結構體順序排在一起就組成了bin這個簡單的壓縮格式,實際上只是壓縮了nb0里面不必要的0,而不是對數據做了算法壓縮,所以很好理解,所以你用winrar等去壓縮bin,發現可以更小,呵呵
最簡單最簡單的燒寫和啟動WinCE的方法是:
直接把nk.bin燒到存儲設備上,比如NAND上
假設nk.bin是30MB,那么就在NAND上順序留下30MB給NK.bin
啟動的時候把nk.bin按照那個結構體,解壓到內存中,跳轉到起始地址,就可以運行了
但是我發現有趣的是,很多開發板廠家并不是這么做的
他們實際上是用了BINFS來存放解壓出來的系統鏡像
這里大家可能比較疑惑一個問題,明明很多開發板都沒有用“BINFS”,你怎么說他們用了BINFS?
實際上這里有一個重要的誤會
BINFS是一個文件系統,但是大家關注BINFS是因為想實現上面說的加快開機和節省內存的好處,實際上需要完成這種好處,BINFS是一個文件系統基礎,真正做到將系統鏡像分為兩個部分還需要用到multi-bin技術
所以這個就是誤會所在,很多開發板確實用了BINFS文件系統,但是他們只是把系統鏡像全部寫入到BINFS分區,啟動時再全部讀出來,這樣就沒有達到前面說的“好處”
怎么確定我的系統現在有沒有用BINFS?
看看自己的燒寫代碼,如果用了bootpart的庫進行分區,寫入,比如
BP_OpenPartition(NEXT_FREE_LOC, dwNumSectors, PART_BINFS, TRUE, PART_OPEN_ALWAYS);
這里就是典型的建立了一個BINFS分區
然后使用BP_WriteData將鏡像內容寫入到這個分區
如果你的程序沒有使用這么一套機制,那么說明你的系統沒有使用BINFS
前面說到除了BINFS作為文件系統的支持,還需要multi-bin技術,那么這個multi-bin技術是做什么的呢
實際上,我們想到,系統可以分為多塊,我們只需要把核心啟動的內容放到內存中,然后其它用到的從固態存儲器中(使用了BINFS文件系統)讀出來就可以了,這個就是我們前面說到的“好處”的實現原理
那么如何將系統鏡像分開來,這個就是需要一些BSP里面的修改了,后面在實現方法中介紹
那么最簡單的分配就是將系統鏡像分為兩塊
一塊用來存放系統啟動時候需要在內存中運行的“最小內核”
一塊用來存放系統后續需要“按需加載”的模塊文件
我們一般也都是這么做的
編譯的時候我們會通過配置文件告訴系統什么地址范圍是在內存中運行的內核,什么地址范圍是在存儲器(使用BINFS存放鏡像)上的系統其它模塊,然后啟動時候只需要加載最小內核,然后由最小內核使用BINFS文件系統驅動來讀取存儲器BINFS分區上的其它所需模塊
系統怎么知道那些文件在什么地址?怎么知道哪些文件是在最小內核里還是存儲器BINFS分區上的?
系統有記錄各文件地址的結構體,有了文件地址就自然知道是放在什么地方的了,別忘了前面說的配置文件,里面已經告訴了各塊的起止地址,很容易就可以判斷到。關于結構體是如何記錄模塊地址等內容,不是本文討論范圍,這里就先放下,大家知道系統有方法知道文件的地址和大小就可以了。
所以為什么一些開發板系統用了BINFS,卻沒有那些“好處”,就是因為雖然用了BINFS文件系統,但是把全部內容都放進了最小內核,所以沒有達到任何的優勢效果。
就是說我們在實現了BINFS文件系統之后需要做的就是將“最小內核”和“系統其它文件”分離開來
四 BINFS的實現
前面已經較詳細的說明了原理,其實說到這里文章題目已經需要有些改變了,我們實際上討論的是“使用BINFS實現multi-bin來節省系統內存”,而不只是實現BINFS文件系統。因為我怕標題太長,大家有些費解,而且很多人把這個就稱為BINFS,所以才取了這個題目。實際上將這種技術單單叫做BINFS是不準確的。
1 首先說說如何實現BINFS文件系統
前面說了,BINFS文件系統是基礎,為什么?因為分離系統鏡像之后,系統“最小內核”會使用BINFS去讀系統其它模塊,所以我們必須將系統鏡像使用BINFS文件系統寫入固態存取器(后面無特別說明,所有"存儲器"均指“固態存儲器”,內存指"SDRAM"或"DDR"等程序運行介質)
那么我們可不可以不用BINFS,用FAT?理論上應該是可以的,不過需要修改MS的系統加載模塊的程序,我不知道是不是所有涉及到的模塊都有開源,所以這個我們不討論
其實MS對WinCE設備的存儲器分區啟動管理有點像PC的
在WinCE中首先在存儲器一開始,存放的是MBR(master boot record,我沒記錯的話...),熟悉文件系統的朋友一看就明白了MBR是干什么的。MBR在CE中主要是記錄后面的存儲器空間是如何分區的,這個記錄應該和PC上是一樣的,起始sector號碼,總共有幾個Sectors,分區使用什么文件系統。但是不同的是,MBR不需要承擔引導代碼的功能
在MBR之后,按照分區記錄中的起始地址,就是各個分區,大家不妨想象為PC上的分區,只不過我們現在C盤不用FAT或者NTFS,而是使用一種叫做BINFS的文件系統。
我們需要創建,修改MBR,增加刪除,查詢,讀取分區信息和內容。這些功能都是bootpart庫里面的,大家可以查詢相關內容,這里不詳細說明bootpart庫是如何使用的。
只要了解過磁盤分區概念的朋友,應該很快就可以操作bootpart函數,而且一般的EBoot在燒寫這里都是有例子的。大家可以參考,這里只是列出基本步驟
a) BP_LowLevelFormat 用來格式化所有存儲空間
b) BP_OpenPartition 打開某個分區,如果不存在可以創建該分區,比如BINFS
c) BP_WriteData 往分區里寫數據
d) BP_ReadData 讀取分區里的數據
這些是一些基本的操作函數,具體實現細節大家需要多參考EBoot里面的代碼,實際需要考慮的問題還可能包括整個存儲器的布局
2 往BINFS分區中寫入鏡像
如果創建好了BINFS分區,那么下面要做的就是把鏡像寫入BINFS分區
如果大家下載的是BIN文件,首先需要把BIN文件解壓縮出來,解壓縮代碼可以參考EBoot里面的代碼
然后調用BP_WriteData可以寫入BINFS分區
詳細步驟大家還是多看示例代碼,過程并不復雜
3 如何將系統鏡像分成多個部分
這里就是說的multi-bin的,把鏡像分為“最小內核”與“系統其它文件”
MS幫助文件里面有How to Implement BinFS ,這里將大致流程介紹了一下
首先就是需要修改config.bib文件,對CE比較了解的朋友知道,CE的地址等配置都是在config.bib里面修改的,所以我們要去改config.bib文件
這里可以看到現在系統對于鏡像的劃分,例如
Name??????? Address???? Size??????? Type
NK????????? 88200000??? 03000000??? RAMIMAGE
RAM???????? 8B200000??? 04E00000??? RAM
這個很容易理解,NK是唯一的一個bin文件,存放RAMIMAGE
這里面RAMIMAGE是關鍵字,告訴系統這個是需要啟動的“最小內核”,現在是48MB...
RAM是告訴系統可用的內存起始地址和大小
首先我們需要把NK給分開成為兩部分,即“最小內核”與“系統其它文件”
修改如下
我們好好看下這個配置,這里完成的是將系統鏡像內容分為兩部分
XIPKERNEL,就是我們的“最小內核”,就是RAMIMAGE
NK,就是“系統其它文件”,就是NANDIMAGE(關鍵字,不可改)
好了,這里有些問題大家可能要問。CHAIN是什么?CHAIN是實現multi-bin的必須部分,是告訴系統各bin文件位置的信息。一定需要了解CHAIN的內容?
其實CHAIN也是結構體...,大家如果把chain.bin解壓出來,會發現是這個結構體
這里說的bin就是把系統鏡像拆分開的子區塊,我們這里就是2個,分別是XIPKERNEL和NK
信息描述會記錄各個bin的起始位置,實際大小和最大大小,分區名稱等
實際大小就是編譯出來的實際大小,最大大小就是我們在config.bib里面指定的大小
還有一些其它的配置也需要修改
AUTOSIZE=ON
COMPRESSION=ON
DLLADDR_AUTOSIZE=ON
KERNELFIXUPS=ON
PROFILE=OFF
RAM_AUTOSIZE=OFF
ROMFLAGS=0
ROM_AUTOSIZE=OFF
ROMSIZE=03000000
ROMSTART=88000000
ROMWIDTH=32
XIPSCHAIN=88600000
這里你能訂制的就是后面4項,我這里ROMSTART=88000000,因為前面還有一些地址配置因為與系統鏡像生成無關,所以我就沒有貼上來,不過為了防止大家搞不清這個88000000是怎么來的,還是貼一下
Name??????? Address???? Size??????? Type
ARGS??????? 88000000??? 00001000??? RESERVED
VPU???????? 88001000??? 000FF000??? RESERVED
FRAMEBUFFER 88100000??? 00100000??? RESERVED
88000000就是我內存映射到的起始地址
這里需要注意XIPSCHAIN,這個一定要設置為CHAIN的起始地址
帶了XIPSCHAIN,才會生成后面需要的xip.bin
MS的幫助文件里面的例子是用的NK作為RAMIMAGE的名字,EXT作為NANDIMAGE的名字
當然名字不是最重要的,但是實際使用中,大家會發現使用NK作為RAMIMAGE的名字虧大了
為什么呢?
這就是我們下面需要做的把各分區都配置好之后,下面需要決定把哪些內容放到什么分區下了
如前面所述,我們需要把啟動需要的“最小內核”放到RAMIMAGE里面
首先定義一下哪些是“最小內核”
其實說白了就是系統可以使用BINFS讀取在存儲器上文件所需要的最小系統文件
這里其實需要了解WinCE的啟動過程,但是我們并不深入到函數,只是模塊級的系統啟動后需要初始化,所以關于初始化的OAL層都需要放進來,然后我們需要使用device.exe來加載我們的存儲器驅動,這樣才能訪問存儲器,所以關于設備驅動加載,總線枚舉的模塊都要加上,還有我們需要的BINFS驅動模塊,還有
mspart分區模塊,不然無法找到BINFS分區的位置。這些都是較通用的模塊,還有一些模塊你一定要注意,就是你的存儲器驅動所依賴的驅動模塊,比如ceddk?你的bsp里的gpio驅動?dma驅動?等等。如果沒有加入全的話就會出現加載不了存儲器驅動,也就沒法找到分區,沒法訪問BINFS...
有人說如果需要用HIVE的話,還要加載FAT驅動,實際上并不需要,因為我們的目的是要完成“可以訪問BINFS”,
boot.hv一定是要放到RAMIMAGE里的,所以基礎注冊表都是有的,可以讓你完成對存儲器驅動的加載,而這之后都可以用BINFS訪問“系統其它文件”了,所以FAT驅動是不需要放到RAMIMAGE里面的,在用到FAT時,BINFS已經好用了
同時default.hv,user.hv也都是不需要放到RAMIMAGE里面的
如果你使用非英文的系統,還有一個文件不要忘記
wince.nls,少了這個你也會啟動不了
下面給出例子,我相信可以涵蓋大部分平臺應用了
MODULES
??? nk.exe????????? $(_FLATRELEASEDIR)\oal.exe????????????????? XIPKERNEL SHZ
??? kernel.dll????? $(_FLATRELEASEDIR)\kern.dll???????????????? XIPKERNEL SHZ
??? coredll.dll???? $(_FLATRELEASEDIR)\coredll.dll????????????? XIPKERNEL SH
???? k.coredll.dll?? $(_FLATRELEASEDIR)\k.coredll.dll??????????? XIPKERNEL SHMK
???? oalioctl.dll??? $(_FLATRELEASEDIR)\oalioctl.dll???????????? XIPKERNEL SHK
???? filesys.dll???? $(_FLATRELEASEDIR)\filesys.dll????????????? XIPKERNEL SHK
???? fsdmgr.dll???? $(_FLATRELEASEDIR)\fsdmgr.dll??????????????? XIPKERNEL SHMK
???? mspart.dll???? $(_FLATRELEASEDIR)\mspart.dll??????????????? XIPKERNEL SHK
???? romfsd.dll???? $(_FLATRELEASEDIR)\romfsd.dll????????????? XIPKERNEL SHK
???? binfs.dll???? $(_FLATRELEASEDIR)\binfs.dll????????????????????? XIPKERNEL SHK
???? fpcrt.dll?????? $(_FLATRELEASEDIR)\fpcrt.dll??????????????? XIPKERNEL SH
???? k.fpcrt.dll???? $(_FLATRELEASEDIR)\fpcrt.dll??????????????? XIPKERNEL SHMK
???? ceddk.dll?????? $(_FLATRELEASEDIR)\ceddk.dll??????????????? XIPKERNEL SHQ
???? device.dll????? $(_FLATRELEASEDIR)\device.dll?????????????? XIPKERNEL SHMK
?? udevice.exe???? $(_FLATRELEASEDIR)\udevice.exe????????????? XIPKERNEL SHM
?? devmgr.dll????? $(_FLATRELEASEDIR)\devmgr.dll?????????????? XIPKERNEL SHMK
?? regenum.dll???? $(_FLATRELEASEDIR)\regenum.dll????????????? XIPKERNEL SHK
?? busenum.dll???? $(_FLATRELEASEDIR)\busenum.dll????????????? XIPKERNEL SHK
??? pm.dll?????? $(_FLATRELEASEDIR)\pm.dll????????????????????? XIPKERNEL SHMK
??? nandfmd.dll???????? $(_FLATRELEASEDIR)\nandfmd.dll????????????? XIPKERNEL SHK
FILES
??? boot.hv???????? $(_FLATRELEASEDIR)\boot.hv????????????????? XIPKERNEL SH
?? wince.nls????? $(_FLATRELEASEDIR)\wince.nls??????????????? XIPKERNEL SHU
這里的nandfmd.dll是我的NAND驅動,可以改成你自己的
可能有一些還是可以優化掉的,但是我還沒有嘗試,大家可以給出意見
上面這段代碼放到哪里?
放到config.bib最后!沒錯,是config.bib,不是platform.bib
這里再回頭來說說使用NK當作RAMIMAGE名稱的缺點
大家看到,我們只要把需要的模塊改成XIPKERNEL就好了,但是系統默認的都是用的NK這個名字,如果我們使用NK當作RAMIMAGE的名字的話,我們要把其他所有不要加進來的改名字...這個工作量太大了,所以我們把NK當作了NANDIMAGE的名字
4 配置注冊表
到了這一步還沒有完成,我們需要配置些注冊表
其實我默認的注冊表還真沒有什么需要改的
大家看看MS的幫助文件里面關于注冊表的配置,這里列出一些設置
[HKEY_LOCAL_MACHINE\System\StorageManager\PartitionTable]
??? "21"="BINFS"
[HKEY_LOCAL_MACHINE\System\StorageManager\Profiles\FlashDisk\BINFS]
??? "MountHidden"=dword:1
??? "MountAsROM"=dword:1
這里不得不說一下RAM and ROM file system和ROM-Only file system
很多帖子都說用BINFS一定要用RAM and ROM file system,實際上并不是這樣
使用ROM-Only file system一樣可以,但是大家需要記住,在使用ROM-Only file system時,把FAT mount為根目錄
五 BINFS的燒寫和啟動
上面把BSP那里該修改的都修改了,只要編譯就可以了,關于如何編譯系統,其實是一個非常非常重要的問題,一定要重視,參考http://www.armce.com/bbs/thread-804-1-1.html
不正確的編譯,會影響你本來應該正確的結果!
下面又是一個問題,現在生成了4個可以用的bin,分別是
XIKERNEL.bin,nk.bin,chain.bin,xip.bin
那么到底該怎么燒寫呢?
實際上大家從大小就可以看出XIP包含了所有其他bin的內容,所以大家直接把XIP.bin下載解壓,然后用bootpart的函數燒寫到存儲器上就可以了
啟動的時候怎么引導?和原來啟動系統一樣,但是記住,不需要把全部的xip.bin里面指定的大小都讀取出來了,最多只要讀你在config.bib里面指定的RAMIMAGE大小就可以了
RAMIMAGE大小怎么確定的?這個你可以先放的比較大,比如10MB,然后看編譯出來的RAMIMAGE分區有多大,再調整,一般都是3MB以內吧,我這里保守的用4MB
六 調試技巧
調試BINFS的multi-bin啟動,需要反復的燒寫,設置有一點不正確經常就是卡在某個地方,對于我們用中文鏡像的就更痛苦了,release版都有30-40MB,debug版不改存儲布局,燒都燒不進去
我建議大家新建一個項目,然后選擇thin client,不妨將顯示驅動也加入,其他驅動都不要,然后一定選擇debug版
本,debug版本的調試信息非常重要
花這點時間去編譯一個thin client是非常值得的,調試速度很快
下面給一些調試建議
1 引導之后就死機,什么消息都沒有
估計是內存配置有問題,或者燒寫的有問題,或者沒有把需要的內核模塊加進去
2 死在OEMInit之后
后面應該開始加載NAND驅動了,看看你的關于設備管理,驅動加載和總線枚舉的模塊有沒有加全
如果已經有NAND驅動的信息出來了,看看NAND驅動是不是因為什么原因沒有加載起來,比如缺少某個dll支持
3 其他
如果NAND正常了,BINFS沒問題了,大家需要根據自己的BSP來看看其他的問題
?
轉自:http://apps.hi.baidu.com/share/detail/877159#content
總結
以上是生活随笔為你收集整理的WinCE上BINFS实现详解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: S3c2440A WINCE平台HIVE
- 下一篇: uboot环境变量实现分析