关于wince6.0 的TOC讨论
2012-08-30 09:24
381 查看
INCE TOC解析
********************************LoongEmbedded************************
作者:LoongEmbedded(kandi)
时间:2009.10.20
类别:WINCE 驱动开发
********************************LoongEmbedded************************
1. TOC是什么
TOC: Table Of Contents, OEM on disk structure.
2. 为什么要进行全局变量重定位
Bootloader的主控制函数BootloaderMain()调用的第一个函数是KernelRelocate (pTOC),WINCE操作系统OAL模块的启动过程中调用的ARMInit()函数页调用了KernelRelocate (pTOC)。这两次对KernelRelocate函数的调用把全局变量重定位到RAM中,只不过它们操作的对象不同。OAL模块的ARMInit函数调用的KernelRelocate函数是对WINCE操作系统镜像的全局变量进行重定位,而BootloaderMain函数调用KernelRelocate函数是对Bootloader的全局变量重定位。
那么为什么要对bootloader及操作系统的全局变量进行重定位呢? bootloader及WINCE操作系统的源代码中,需要定义一些全局变量,当这两者的源代码分别编译链接成可执行的二进制文件后,这些全局变量被放在可执行文件的一个数据段中。此二进制代码被烧写到目标设备上,包括全局变量所在的数据段,而很多种情况下,bootloader是在只读的目标设备(比如nor flash)上运行,如果是这种情况,那么bootloader的代码要对全局变量进行写操作就会失败。因此,需要把bootloader的全局变量所在的数据段移到RAM中,来确保全局变量可写。而在操作系统启动过程中,需要把镜像的数据从目标设备(比如nand
flash)读入到config.bib文件中定义的RAMIMAGE的区域内,这块区域是SDRAM
我们知道boot的方式一般有nand boot和nor boot这两种,其中nor flash支持XIP执行的方式,但因为nor flash价格相对nand flash高许多,所以现在很多系统采用的boot方式是nand boot方式,但不管使用哪种方式,保存着bootloader的镜像和WINCE镜像的nand flash或是nor flash
3. 如何实现全局变量重定位
相关的代码如下:
// Gets replaced by RomLoader with real address
ROMHDR * volatile const pTOC = (ROMHDR *)-1;
/**********************************************/
可知它是一个指向ROMHDR结构体的指针。此指针描述了整个ROM的几乎所有信息。但是也可看到在变量声明时,此变量被赋予了一个非法值-1.那么这个变量到底是在什么时候、什么地方被初始化的呢?
此指针指向包含ROM信息的结构体,在编写代码时,代码本身不可能知道自己将会被烧写到什么样的ROM里。因此代码本身是不包含ROM信息的,那么唯一可以确定ROM信息的就是ROM的制作工具—RomImage.exe(MakeImage.exe调用RomImage.exe来打包所有的文件,RomImage.exe接受BIB文件作为参数,根据BIB(eboot.bib,config.bib,platform.bib)文件的内容打包,在该步中,MakeImage.exe会调用命令:romimage config.bib(这个文件是我的理解),从而根据config.bib的内容来把EBOOT打包为ROM文件(eboot.nb0)时初始化的。)。
RomImage.exe把文件打包为ROM文件时,读取一些特殊的全局变量或函数的符号表,然后对这些符号表进行一些操作。pTOC全局变量就是这些特殊的全局符号之一。RomImage.exe保证代码在ROM运行时,pTOC指针已经指向了正确的位置。
/************************************************/
void BootloaderMain (void)
{
……………………
// relocate globals to RAM
if (!KernelRelocate (pTOC))
{
// spin forever
HALT (BLERR_KERNELRELOCATE);
}
……………………
}
KernelRelocate的函数体如下所示:
KernelRelocate
// KernelRelocate: move global variables to RAM
static BOOL KernelRelocate (ROMHDR *const pTOC)
{
ULONG loop;
COPYentry *cptr;
if (pTOC == (ROMHDR *const) -1)
{
return (FALSE); // spin forever!
}
// This is where the data sections become valid... don't read globals until after //this
for (loop = 0; loop < pTOC->ulCopyEntries; loop++)
{
cptr = (COPYentry *)(pTOC->ulCopyOffset + loop*sizeof(COPYentry));
if (cptr->ulCopyLen)
memcpy((LPVOID)cptr->ulDest,(LPVOID)cptr->ulSource,cptr->ulCopyLen);
if (cptr->ulCopyLen != cptr->ulDestLen)
memset((LPVOID)(cptr->ulDest+cptr->ulCopyLen),0,
cptr->ulDestLen-cptr->ulCopyLen);
}
return (TRUE);
}
4. ROMHDR结构体
我们知道pTOC是一个指向ROMHDR结构体的指针,这个结构体在xxx:\WINCE500\PUBLIC\COMMON\OAK\INC的romldr.h下定义,内容如下
typedef struct ROMHDR {
ULONG dllfirst; // first DLL address
ULONG dlllast; // last DLL address
ULONG physfirst; // first physical address
ULONG physlast; // highest physical address
ULONG nummods; // number of TOCentry's
ULONG ulRAMStart; // start of RAM
ULONG ulRAMFree; // start of RAM free space
ULONG ulRAMEnd; // end of RAM
ULONG ulCopyEntries; // number of copy section entries
ULONG ulCopyOffset; // offset to copy section
ULONG ulProfileLen; // length of PROFentries RAM
ULONG ulProfileOffset; // offset to PROFentries
ULONG numfiles; // number of FILES
ULONG ulKernelFlags; // optional kernel flags from ROMFLAGS .bib config option
/************************************************************/
Percentage of RAM used for filesystem from FSRAMPERCENT .bib config option
byte 0 = #4K chunks/Mbyte of RAM for filesystem 0-2Mbytes 0-255
byte 1 = #4K chunks/Mbyte of RAM for filesystem 2-4Mbytes 0-255
byte 2 = #4K chunks/Mbyte of RAM for filesystem 4-6Mbytes 0-255
byte 3 = #4K chunks/Mbyte of RAM for filesystem > 6Mbytes 0-255
/************************************************************/
ULONG ulFSRamPercent; //
ULONG ulDrivglobStart; // device driver global starting address
ULONG ulDrivglobLen; // device driver global length
USHORT usCPUType; // CPU (machine) Type
USHORT usMiscFlags; // Miscellaneous flags
PVOID pExtensions; // pointer to ROM Header extensions
ULONG ulTrackingStart; // tracking memory starting address
ULONG ulTrackingLen; // tracking memory ending address
} ROMHDR;
所用的结构体COPYentry的内容如下:
typedef struct COPYentry {
ULONG ulSource; // copy source address
ULONG ulDest; // copy destination address
ULONG ulCopyLen; // copy length
ULONG ulDestLen; // copy destination length
// (zero fill to end if > ulCopyLen)
} COPYentry;
但Romimage.exe如何去初始化这些结构体的呢?首先我们通过下图的命令所得到的文本文件内容如下:
图1
所得到的文本文件的部分内容:
图2
打包工具Romimage.exe根据config.bib
图3
根据“NK 8C200000 01B00000 RAMIMAGE”,Romimage.exe在编译的时候初始化ROMHDR结构体的成员physfirst=0x8C200000,也就是图2中的“Physical First : 0x8C200000 ”,但是操作系统镜像的实际大小是图2的“length = 0x0158537C”,所以可以得出0x8C200000+0x0158537C=图2的“Physical Last : 0x8D78537C ”,这就初始化了成员physlast=0x8D758537C,其他的成员的初始化可以根据.bib文件来推导。
5. 深入认识TOC数据
WINCE操作系统nk.bin文件是最常用的记录格式类型的操作系统镜像文件(还有nk.nb0)。镜像数据nk.bin格式:最开始是7个字节的文件头,内容为42 30 30 30 46 46 0A,即“B000FF\x0A”,我用记事本打开时看到的内容如下:
图4
接下来的4字节是操作系统镜像数据的目的起始地址(Image Start),再4字节是以字节为单位的镜像数据长度(length),再接下来就是nk.bin的逐条记录(Record),也就是操作系统镜像的数据正文,其中每一条记录由4字节起始地址(Start)、4字节数据长度(Length)、4字节校验码(Chksum)和Length个字节的记录数据(RecordData)组成,见下图:
图5
接下来,我们通过图6可知pTOC=0x8d783764,它所指向的内存区域的操作系统镜像数据保存在Record[144]中,这条记录的长度为0x54(=84个字节),正好是ROMHDR类型的大小 (19*4+2*2+4=84)吻合
6.
********************************LoongEmbedded************************
作者:LoongEmbedded(kandi)
时间:2009.10.20
类别:WINCE 驱动开发
********************************LoongEmbedded************************
1. TOC是什么
TOC: Table Of Contents, OEM on disk structure.
2. 为什么要进行全局变量重定位
Bootloader的主控制函数BootloaderMain()调用的第一个函数是KernelRelocate (pTOC),WINCE操作系统OAL模块的启动过程中调用的ARMInit()函数页调用了KernelRelocate (pTOC)。这两次对KernelRelocate函数的调用把全局变量重定位到RAM中,只不过它们操作的对象不同。OAL模块的ARMInit函数调用的KernelRelocate函数是对WINCE操作系统镜像的全局变量进行重定位,而BootloaderMain函数调用KernelRelocate函数是对Bootloader的全局变量重定位。
那么为什么要对bootloader及操作系统的全局变量进行重定位呢? bootloader及WINCE操作系统的源代码中,需要定义一些全局变量,当这两者的源代码分别编译链接成可执行的二进制文件后,这些全局变量被放在可执行文件的一个数据段中。此二进制代码被烧写到目标设备上,包括全局变量所在的数据段,而很多种情况下,bootloader是在只读的目标设备(比如nor flash)上运行,如果是这种情况,那么bootloader的代码要对全局变量进行写操作就会失败。因此,需要把bootloader的全局变量所在的数据段移到RAM中,来确保全局变量可写。而在操作系统启动过程中,需要把镜像的数据从目标设备(比如nand
flash)读入到config.bib文件中定义的RAMIMAGE的区域内,这块区域是SDRAM
我们知道boot的方式一般有nand boot和nor boot这两种,其中nor flash支持XIP执行的方式,但因为nor flash价格相对nand flash高许多,所以现在很多系统采用的boot方式是nand boot方式,但不管使用哪种方式,保存着bootloader的镜像和WINCE镜像的nand flash或是nor flash
3. 如何实现全局变量重定位
相关的代码如下:
// Gets replaced by RomLoader with real address
ROMHDR * volatile const pTOC = (ROMHDR *)-1;
/**********************************************/
可知它是一个指向ROMHDR结构体的指针。此指针描述了整个ROM的几乎所有信息。但是也可看到在变量声明时,此变量被赋予了一个非法值-1.那么这个变量到底是在什么时候、什么地方被初始化的呢?
此指针指向包含ROM信息的结构体,在编写代码时,代码本身不可能知道自己将会被烧写到什么样的ROM里。因此代码本身是不包含ROM信息的,那么唯一可以确定ROM信息的就是ROM的制作工具—RomImage.exe(MakeImage.exe调用RomImage.exe来打包所有的文件,RomImage.exe接受BIB文件作为参数,根据BIB(eboot.bib,config.bib,platform.bib)文件的内容打包,在该步中,MakeImage.exe会调用命令:romimage config.bib(这个文件是我的理解),从而根据config.bib的内容来把EBOOT打包为ROM文件(eboot.nb0)时初始化的。)。
RomImage.exe把文件打包为ROM文件时,读取一些特殊的全局变量或函数的符号表,然后对这些符号表进行一些操作。pTOC全局变量就是这些特殊的全局符号之一。RomImage.exe保证代码在ROM运行时,pTOC指针已经指向了正确的位置。
/************************************************/
void BootloaderMain (void)
{
……………………
// relocate globals to RAM
if (!KernelRelocate (pTOC))
{
// spin forever
HALT (BLERR_KERNELRELOCATE);
}
……………………
}
KernelRelocate的函数体如下所示:
KernelRelocate
// KernelRelocate: move global variables to RAM
static BOOL KernelRelocate (ROMHDR *const pTOC)
{
ULONG loop;
COPYentry *cptr;
if (pTOC == (ROMHDR *const) -1)
{
return (FALSE); // spin forever!
}
// This is where the data sections become valid... don't read globals until after //this
for (loop = 0; loop < pTOC->ulCopyEntries; loop++)
{
cptr = (COPYentry *)(pTOC->ulCopyOffset + loop*sizeof(COPYentry));
if (cptr->ulCopyLen)
memcpy((LPVOID)cptr->ulDest,(LPVOID)cptr->ulSource,cptr->ulCopyLen);
if (cptr->ulCopyLen != cptr->ulDestLen)
memset((LPVOID)(cptr->ulDest+cptr->ulCopyLen),0,
cptr->ulDestLen-cptr->ulCopyLen);
}
return (TRUE);
}
4. ROMHDR结构体
我们知道pTOC是一个指向ROMHDR结构体的指针,这个结构体在xxx:\WINCE500\PUBLIC\COMMON\OAK\INC的romldr.h下定义,内容如下
typedef struct ROMHDR {
ULONG dllfirst; // first DLL address
ULONG dlllast; // last DLL address
ULONG physfirst; // first physical address
ULONG physlast; // highest physical address
ULONG nummods; // number of TOCentry's
ULONG ulRAMStart; // start of RAM
ULONG ulRAMFree; // start of RAM free space
ULONG ulRAMEnd; // end of RAM
ULONG ulCopyEntries; // number of copy section entries
ULONG ulCopyOffset; // offset to copy section
ULONG ulProfileLen; // length of PROFentries RAM
ULONG ulProfileOffset; // offset to PROFentries
ULONG numfiles; // number of FILES
ULONG ulKernelFlags; // optional kernel flags from ROMFLAGS .bib config option
/************************************************************/
Percentage of RAM used for filesystem from FSRAMPERCENT .bib config option
byte 0 = #4K chunks/Mbyte of RAM for filesystem 0-2Mbytes 0-255
byte 1 = #4K chunks/Mbyte of RAM for filesystem 2-4Mbytes 0-255
byte 2 = #4K chunks/Mbyte of RAM for filesystem 4-6Mbytes 0-255
byte 3 = #4K chunks/Mbyte of RAM for filesystem > 6Mbytes 0-255
/************************************************************/
ULONG ulFSRamPercent; //
ULONG ulDrivglobStart; // device driver global starting address
ULONG ulDrivglobLen; // device driver global length
USHORT usCPUType; // CPU (machine) Type
USHORT usMiscFlags; // Miscellaneous flags
PVOID pExtensions; // pointer to ROM Header extensions
ULONG ulTrackingStart; // tracking memory starting address
ULONG ulTrackingLen; // tracking memory ending address
} ROMHDR;
所用的结构体COPYentry的内容如下:
typedef struct COPYentry {
ULONG ulSource; // copy source address
ULONG ulDest; // copy destination address
ULONG ulCopyLen; // copy length
ULONG ulDestLen; // copy destination length
// (zero fill to end if > ulCopyLen)
} COPYentry;
但Romimage.exe如何去初始化这些结构体的呢?首先我们通过下图的命令所得到的文本文件内容如下:
图1
所得到的文本文件的部分内容:
图2
打包工具Romimage.exe根据config.bib
图3
根据“NK 8C200000 01B00000 RAMIMAGE”,Romimage.exe在编译的时候初始化ROMHDR结构体的成员physfirst=0x8C200000,也就是图2中的“Physical First : 0x8C200000 ”,但是操作系统镜像的实际大小是图2的“length = 0x0158537C”,所以可以得出0x8C200000+0x0158537C=图2的“Physical Last : 0x8D78537C ”,这就初始化了成员physlast=0x8D758537C,其他的成员的初始化可以根据.bib文件来推导。
5. 深入认识TOC数据
WINCE操作系统nk.bin文件是最常用的记录格式类型的操作系统镜像文件(还有nk.nb0)。镜像数据nk.bin格式:最开始是7个字节的文件头,内容为42 30 30 30 46 46 0A,即“B000FF\x0A”,我用记事本打开时看到的内容如下:
图4
接下来的4字节是操作系统镜像数据的目的起始地址(Image Start),再4字节是以字节为单位的镜像数据长度(length),再接下来就是nk.bin的逐条记录(Record),也就是操作系统镜像的数据正文,其中每一条记录由4字节起始地址(Start)、4字节数据长度(Length)、4字节校验码(Chksum)和Length个字节的记录数据(RecordData)组成,见下图:
图5
接下来,我们通过图6可知pTOC=0x8d783764,它所指向的内存区域的操作系统镜像数据保存在Record[144]中,这条记录的长度为0x54(=84个字节),正好是ROMHDR类型的大小 (19*4+2*2+4=84)吻合
6.
相关文章推荐
- 关于实现S5PV210同时跑wince 和android双系统实现的可能性讨方法讨论
- 【求助】关于wince6.0 机器在某些XP电脑下同步软件驱动安装不上的奇怪问题
- 【原创】回答网友关于ARM9 S3C2440 wince6.0 内存 128M的使用问题
- 关于WINCE 6.0 下用MFC编程使用Invalidate()导致的4KB内存泄漏
- 近期关于“WINCE驱动开发之DMA的使用”讨论
- 关于MAVEN和ANT的讨论(整理)
- 关于核空间与像空间的专题讨论
- 关于简单的JVM实现的讨论,记录备忘。
- 很好的关于Bitmap内存讨论的文章
- WINCE6.0在应用程序中调用控制面板的应用
- 关于ext的讨论,ajax不应该只是ext,此时的我可能更倾向于jquery了,可是jquery的插件做的实在不漂亮啊,尤其是grid
- 关于tomcat服务器部署,页面报404/500错误,myeclipse异常关闭 导致tomcat 6.0 无法重启 的问题
- WinCE6.0的批量编译
- 关于扁平化界面风格的设计美学讨论
- Ajax关于readyState和status的讨论
- 关于数据建模(面向ER)和领域模型建模(面向OO)在企业应用中的作用的讨论
- 关于计算机启动流程的讨论总结
- 关于异或的速算公式讨论(备忘)
- 关于百度地图SDK v3.6.0以上版本找不到PoiOverlay类(开源代码)的解决方法.
- 关于模态和振型的初步讨论