WINCE6.0深入理解TOC
********************************LoongEmbedded************************
作者:LoongEmbedded(kandi)
时间:2011.7.17
类别:WINCE 系统开发
********************************LoongEmbedded************************
TOC: Table Of Contents, OEM on disk structure.
1. pTOC指针指向的结构体
pTOC在\WINCE600\PUBLIC\COMMON\OAK\DRIVERS\ETHDBG\BLCOMMON\blcommon.c中定义,如下:
ROMHDR * volatile const pTOC = (ROMHDR *)-1;// Gets replaced by RomLoader with real address
可知pTOC是指向ROMHDR结构体的指针,在\WINCE600\PUBLIC\COMMON\OAK\INC\romldr.h中定义,如下图:
图1
我们通过viewbin –r eboot.bin和viewbin –r nk.bin获取的信息如下图:
图2
由图2可知eboot.bin的pTOC指向的起始地址为0x80070e7c,大小为0x00000054的内存区域,也就是说eboot.bin的TOC信息保存在这块内存区域。这块内存区域的内容可以通过viewbin –d eboot.bin de.txt获取到的相关内容如下:
图3
通过同样的方式,我们也把nk.bin中的TOC相关信息贴出来:
图4
下面就结合图3和图4来学习ROMHDR结构体成员的意义:
1) dllfirst成员
这是分配给NK.bin的动态连接库(dll)使用的虚拟内存的ROM DLL区间的起始地址,在WINCE系统中,0x40000000到0x5FFFFFFF范围的共512MB的虚拟内存空间被定义为ROM DLL区间。从图3和图4可直接看到的值是01C00140,实际是0x4001C001,这是因为ARM采用小端的数据存储格式,也即高字节数据保存在低地址空间处。
我们知道eboot.bin中是不包含dll文件的,这里的值对于eboot.bin来说应该是没有实际的意义的。
2) dlllast
这是分配给NK.bin的动态连接库(dll)使用的虚拟内存的ROM DLL区间的结束地址,eboot.bin中此值为0x4001C001,和dllfirst的值一样,这是意料之中的,因为eboot.bin中没有包含dll;nk.bin中此值是0x416EC101,说明dll实际占用的ROM DLL空间大小为0x416EC101-0x4001C001=0x16D0100,大概22M左右。
3) phyfirst
镜像文件(这里指eboot.bin和nk.bin)的起始存储地址,这个值等于镜像文件的image start,对于eboot.bin来说,此值为0x80030000,通过图2可知就是eboot.bin的image start的值,这个值在eboot.bib中定义,如下图所示:
图5
也可以看出nk.bin中此值为0x80100000,通过下图的命令
图6
可知此值等于nk.bin的image start,此值由config.bib中的内容来决定的
图7
4) physlast
镜像文件的结束存储地址,eboot.bin中此值为0x80071DF4,该值=image start+length=0x80030000+0x00041DF4;nk.bin中此值为0x81CEC494也等于nk.bin中的image start+length。
5) nummods
TOC入口(entry)的数目,eboot.bin中该值为0x00000001,也即eboot.bin中有一个TOC入口,而镜像文件中每个模块(exe或是dll都有一个TOC入口),所以eboot.bin中包含一个模块,这个模块是什么呢?见下图:
图8
可知此模块是NK.exe,这个意思nk.exe实际就是eboot.exe,我们通过eboot.bib下面的内容可知:
MODULES
;Name Path Memory Type
; -------------- ---------------------------------------------- -----------
nk.exe $(_TARGETPLATROOT)\target\$(_TGTCPU)\$(WINCEDEBUG)\eboot.exe EBOOT
nk.bin中为0x000000FB,也即nk.bin中有251TOC入口,也就是总共包含有251个模块(dll或exe)。
6) ulRAMStart
表示镜像文件的RAM的程序内存区域的起始地址,这里RAM的程序内存区域是指没有被系统保留(RESERVED,见config.bib)的,没有被用作对象存储的,也没有被用作加载时存放操作系统镜像的,而是可用于操作系统及应用程序在运行过程中分配的RAM内存空间。
eboot.bin中该值为0x800B0000,是由图5的“RAM”这一项得值来确定的;nk.bin中该值为0x81CF0000,为什么是这个值呢?根据图7“RAM”这一项得值是0x82900000啊?原来和config.bib中的下面的内容有关:
AUTOSIZE=ON
因为为ON表示RAM的空间可以根据具体的情况来调整,我们当前nk.bin的Image Start = 0x80100000,length = 0x01BEC494,那么nk.bin被加载到RAM的结束地址=Image Start+ length=0x81CEC494,因为这个值小于图7中RAMSTART=0x82900000的值,所以程序内存区域会根据nk.bin实际占用的RAM的空间来确定程序内存区域的起始地址。另外我们知道WINCE的内存是基于页式管理的,WINCE操作系统支持两种页大小:1KB和4KB,在WINCE中,虚拟内存的申请分为保留(reserve)和(commit)两个过程,虚拟空间的保留是以64KB(0X00010000),也就是说在任何一次虚拟内存申请都会返回一个64KB的整数倍的地址,而把虚拟内存提交到物理内存是以页(在此是4KB为一页,也就是0x00001000)为粒度的,所以可以得出程序内存区域的起始地址为0x81CF0000。当然了如果AUTOSIZE=OFF,那么就根据图7指定的范围来得到ulRAMStart和下面的ulRAMFree的值。结合下图可以更好理解:
图9
7) ulRAMFree
RAM的程序内存的空闲可用区域的起始地址,eboot.bin中该值为0x800B8000,说明从0x800B0000到0x800B7FFF用于eboot的程序运行时所需要的内存空间,同理可以如此分析nk.bin。
8) ulRAMEnd
程序内存区域的结束地址, eboot.bin中该值为0x800C0000,见图5中队RAM项的描述可以理解,对于nk.bin可以结合config.bib中来理解,见图7。
9) ulCopyEntries(Number of copy section entries)
全局变量重定位时要复制的入口数,eboot.bin中为0x00000001,也就是1个入口,这个就是eboot.exe的入口;nk.bin中为0x00000002,具体是复制哪两个模块的TOC入口呢?希望在后面的学习中可以搞清楚。
10) ulCopyOffset
全局变量重定位时要复制的入口的偏移地址,对于eboot.bin,我们知道加载的时候是保存在0x80030000这起始内存处,大小为0x00041DF4的内存区域处,见图5中EBOOT这项的描述。eboot.bin中该值为0x80070EF0,那么这个地址处对应的内容是什么呢?
图10
可知eboot.bin中的全局变量重定位时的复制入口的偏移地址就是上图淡蓝色部分,这些值在后面的学习中再来看其作用。Nk.bin中该值为0x81759D78,我们知道nk.bin重定位时要复制的TOC入口数是2个,通过同样的方式下面就来看0x81759D78对应的地址处的内容:
图11
也就是对应nk.bin的copy sections的内容。
11) ulProfileLen
用于profile调试功能的入口的字节长度,eboot.bin和nk.bin中该值都为0。
12) ulProfileOffset
用于profile调试功能的入口的偏移地址,eboot.bin和nk.bin中该值都为0。
13) numfiles
镜像文件中包含的文件个数,因为eboot.bin中没有包含文件,所以该值为0,而nk.bin该值为0x00000075,也就是117个,我们通过viewbin –t nk.bin >nt.txt获取到nk.bin包含的文件如下图所示:
图12
我们再把FILES最后的文件贴出来:
图13
结合图12和图13可知nk.bin包含的文件个数=417-301+1=117个。
14) ulKernelFlags
记录的是操作系统内核可选属性的标志位掩码,因为这个标志位对于eboot.bin没有意义,所以该值为0,而nk.bin的该位可能包含的标志位掩码值如下图:
图14
这个值是由config.bib的ROMFLAGS这一项的值来决定的,因为本config.bib的内容如下:
ROMFLAGS=0
所以该值为0。
15) ulFSRamPercent
表示用于文件系统的RAM内存的百分比,因为这个标志位对于eboot.bin没有意义,而nk.bin中该值为0x0D0D0D0D,则表示第一个1MB内存保留了13(0x0D)个4KB页,第二个1MB内存保留了13(0x0D)个4KB页,第三个和第四个字节也如此,所以用作文件系统的内存空间的百分比=(13+13+13+13)*4KB/4MB=5.07%,尽管计算方式如此,但是分配给文件系统使用的RAM内存地址是连续的。
16) ulDrivglobStart
设备启动程序全局变量的起始存储地址,eboot.bin和nk.bin中该值都为0。
17) ulDrivglobLen
设备启动程序全局变量占用存储空间的字节长度,eboot.bin和nk.bin中该值都为0。
18) usCPUType
代表我们WINCE系统运行所在的CPU的类型,eboot.bin和nk.bin中该值都为0x000001C2
19) usMiscFlags
操作系统镜像的混合标记选项,nk.bin该值为0x00000002
。
20) pExtensions
存放ROMHDR扩展数据的内存区域的指针。Eboot.bin该值为0,nk.bin该值为0x80101020,见下图:
图15
0x80101020内存地址处保存的是ROMHDR扩展数据,因为目前的设计中没有使用到这些数据(应该是XIP内核中使用的),所以其值为0。
21) ulTrackingStart
用于Tracking调试功能的内存区域的起始地址,eboot.bin和nk.bin中该值都为0。
22) ulTrackingLen
用于Tracking调试功能的内存区域的字节长度,eboot.bin和nk.bin中该值都为0。
到此ROMHDR结构体已经介绍完毕,下面来看TOC的应用。
2. 用到TOC的地方
2.1 eboot中用到TOC的地方
2.1.1 main函数调用BootloaderMain函数,而此函数开始就调用KernelRelocate函数来重
定位全局变量:
if (!KernelRelocate (pTOC))
{
// spin forever
HALT (BLERR_KERNELRELOCATE);
}
这里的pTOC是指向eboo.bin的TOC数据的,KernelRelocate的函数体如下:
图16
可以结合对ROMHDR结构体的介绍更容易理解。
2.1.2 eboot更新NK的时候,会调用WriteOSImageToBootMedia()->GetKernelExtPointerH
函数来判断nk.bin中是否包含nk.exe及其扩展指针,下面就来看这个函数:
图17
图18
图19
图19也就是ROMHDR结构的内容。
图20
2.2 NK中用到TOC的地方
2.1.1 ARMInit函数中
在系统启动过程中会调用ARMInit函数,此函数体如下:
图21
下面来看FindKernelEntry的函数体
图22
图23
系统中还有其他地方用到TOC信息,从上面的描述可知道TOC信息的重要性,到此也进一步学习和理解了TOC。