********************************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中定义,如下图:

 

我们通过viewbin –r eboot.bin和viewbin –r nk.bin获取的信息如下图:

 

由图2可知eboot.bin的pTOC指向的起始地址为0x80070e7c,大小为0x00000054的内存区域,也就是说eboot.bin的TOC信息保存在这块内存区域。这块内存区域的内容可以通过viewbin –d eboot.bin de.txt获取到的相关内容如下:

 

通过同样的方式,我们也把nk.bin中的TOC相关信息贴出来:

 

下面就结合图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中定义,如下图所示:

 

也可以看出nk.bin中此值为0x80100000,通过下图的命令

 

可知此值等于nk.bin的image start,此值由config.bib中的内容来决定的

 

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中包含一个模块,这个模块是什么呢?见下图:

 

可知此模块是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的值。结合下图可以更好理解:

 

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,那么这个地址处对应的内容是什么呢?

 

可知eboot.bin中的全局变量重定位时的复制入口的偏移地址就是上图淡蓝色部分,这些值在后面的学习中再来看其作用。Nk.bin中该值为0x81759D78,我们知道nk.bin重定位时要复制的TOC入口数是2个,通过同样的方式下面就来看0x81759D78对应的地址处的内容:

 

也就是对应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包含的文件如下图所示:

 

我们再把FILES最后的文件贴出来:

 

结合图12和图13可知nk.bin包含的文件个数=417-301+1=117个。

14)   ulKernelFlags

记录的是操作系统内核可选属性的标志位掩码,因为这个标志位对于eboot.bin没有意义,所以该值为0,而nk.bin的该位可能包含的标志位掩码值如下图:

 

这个值是由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,见下图:

 

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的函数体如下:

 

可以结合对ROMHDR结构体的介绍更容易理解。

2.1.2         eboot更新NK的时候,会调用WriteOSImageToBootMedia()->GetKernelExtPointerH

函数来判断nk.bin中是否包含nk.exe及其扩展指针,下面就来看这个函数:

 

 

图19也就是ROMHDR结构的内容。

 

2.2   NK中用到TOC的地方

2.1.1 ARMInit函数中

在系统启动过程中会调用ARMInit函数,此函数体如下:

 

下面来看FindKernelEntry的函数体

 

 

系统中还有其他地方用到TOC信息,从上面的描述可知道TOC信息的重要性,到此也进一步学习和理解了TOC。