WINCE TOC解析
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的方式一般有nandboot和nor boot这两种,其中nor flash支持XIP执行的方式,但因为nor flash价格相对nand flash高许多,所以现在很多系统采用的boot方式是nand boot方式,但不管使用哪种方式,保存着bootloader的镜像和WINCE镜像的nand flash或是norflash 3.? 如何实现全局变量重定位 相关的代码如下: // Gets replaced by RomLoader with realaddress 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 datasections 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), cptr->ulDestLen-cptr->ulCopyLen); ??? } ??? return (TRUE); } ? 4.? ROMHDR结构体 我们知道pTOC是一个指向ROMHDR结构体的指针,这个结构体在xxx:WINCE500PUBLICCOMMONOAKINC的romldr.h下定义,内容如下 typedefstruct ROMHDR { ??? ULONG??dllfirst;?????????????? // firstDLL address ??? ULONG??dlllast;??????????????? // lastDLL address ??? ULONG??physfirst;? ????????????// first physical address ??? ULONG??physlast;?????????????? // highestphysical address ??? ULONG??nummods;??????????????? // numberof TOCentry's ??? ULONG??ulRAMStart;???????????? // startof RAM ??? ULONG??ulRAMFree;????????????? // startof RAM free space ??? ULONG??ulRAMEnd;?????????????? // end ofRAM ??? ULONG??ulCopyEntries;????????? // numberof copy section entries ??? ULONG??ulCopyOffset;?????????? // offsetto copy section ??? ULONG??ulProfileLen;?????????? // lengthof PROFentries RAM ??? ULONG??ulProfileOffset;??????? // offsetto PROFentries ??? ULONG??numfiles;?????????????? // numberof FILES ULONG??ulKernelFlags;????????? //optional kernel flags from ROMFLAGS .bib config option /************************************************************/ Percentageof RAM used for filesystem ?fromFSRAMPERCENT .bib config option byte0 = #4K chunks/Mbyte of RAM for filesystem 0-2Mbytes 0-255 byte1 = #4K chunks/Mbyte of RAM for filesystem 2-4Mbytes 0-255 byte2 = #4K chunks/Mbyte of RAM for filesystem 4-6Mbytes 0-255 byte3 = #4K chunks/Mbyte of RAM for filesystem > 6Mbytes 0-255 /************************************************************/ ??? ULONG??ulFSRamPercent;???????? // ? ??? ULONG??ulDrivglobStart;??????? // devicedriver global starting address ??? ULONG??ulDrivglobLen;????????? // devicedriver global length ??? USHORT?usCPUType;????????????? // CPU(machine) Type ??? USHORT?usMiscFlags;??????????? //Miscellaneous flags ??? PVOID??pExtensions;??????????? // pointerto ROM Header extensions ??? ULONG??ulTrackingStart;??????? //tracking memory starting address ??? ULONG??ulTrackingLen;????????? //tracking memory ending address }ROMHDR; ? ??? 所用的结构体COPYentry的内容如下: typedefstruct COPYentry { ??? ULONG??ulSource;?????????????? // copysource address ??? ULONG??ulDest;???????????????? // copydestination address ??? ULONG??ulCopyLen;????????????? // copylength ??? ULONG??ulDestLen;????????????? // copydestination length ??????? ????????????????????????????// (zero fill toend 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,即“B000FFx0A”,我用记事本打开时看到的内容如下: ??????????????????????????????? 图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.? ? (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |