您的位置:首页 > 其它

关于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.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: