1.需要用到的两个概念:
ROMIMAGE.exe: 生成系统镜像文件的程序。
TOC: Table Of Contents, 保存了系统的指针和数据。在镜像文件开头附近,有一个标志,内容是CECE(0x44424442)。这个标志后面就存放着TOC的偏移值,那么bootloader和其他程序可以通过TOC找到镜像相关的信息。
2.需要用到的的两个结构体:
ROMHDR结构体:
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
ULONG ulFSRamPercent; // Percentage of RAM used for filesystem
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;
ulCopyOffset:全局变量存放的起始地址。
全局变量描述结构体:
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;
ulDest:全局变量被存放的RAM起始地址
ulSource:全局变量被存放的ROM中的起始地址
ulCopyLen:全局变量真实个数长度
ulDestLen:为期望全局变量长度
3.代码如下:
//这是该文件中TOC的全局指针变量,拷贝到这里方便分析
ROMHDR * volatile const pTOC = (ROMHDR *)-1;
//
// 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!
}
//这里把镜像中的数据拷贝到Ram中。
// 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));
//全部拷贝到RAM中
if (cptr->ulCopyLen)
memcpy((LPVOID)cptr->ulDest,(LPVOID)cptr->ulSource,cptr->ulCopyLen);
//如果大小不相等的话,需要把剩余部分置0
if (cptr->ulCopyLen != cptr->ulDestLen)
memset((LPVOID)(cptr->ulDest+cptr->ulCopyLen),
0,cptr->ulDestLen-cptr->ulCopyLen);
}
return (TRUE);
}
问题来咯:
如果你仔细去阅读该代码,你就会发现一个问题,pTOC是被赋值为(ROMHDR *)-1,那么在KernelRelocate()函数中:
if (pTOC == (ROMHDR *const) -1)
{
return (FALSE); // spin forever!
}
这个判断一直为真,直接就退出了。这个问题查了一下资料,其实在Romimage.exe中初始化了C代码定义的非0值全局变量。(我靠,感觉好奇怪!)
pTOC == (ROMHDR *const) -1
在这里完成了对pTOC的初始化。具体的流程需要去看Romimage的代码。我没有仔细去看。有兴趣的可以查看:
C:/WINCE500/PRIVATE/WINCEOS/COREOS/NK/TOOLS/ROMIMAGE/ROM
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/luocan1986/archive/2009/12/30/5107364.aspx