WinCE6.0 BootloaderMain源码分析之KernelRelocte

简介:
Eboot启动过程中,在经历了汇编的Startup.s后,跳转到了C语言的main.c文件的main函数中,该函数中实质上就是执行的BootloaderMain函数,那这样写的目的是什么呢?微软这样的设计是为了方便用户在Startup之后和BootloaderMain之前加入一些高级语言的处理代码。
          BootloaderMain 函数的第一个任务就是进行全局变量重定位,即 KernelRelocte 函数的功能。至于为何要进行全局变量重定位,这里进行简单的描述。 Bootloader 通常是在 ROM 存储器重以 XIP 的方式启动运行的,在运行之初自己复制自身的镜像至 RAM 内存中。由于镜像所在的存储区域都是只读而不可写的,所以有必要将镜像中的数据段读到程序内存中来以保证其中的全局变量是可写的。
// 
// 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); 
}
    
    上面是KernelRelocate函数的实现,里面有两个结构体COPYentryROMHDR,它们的定义在文件\WINCE600\PUBLIC\COMMON\OAK\INC\romldr.h中,定义如下:
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; 

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    
                                                                                // 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     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结构体比价简单,就是定义了源数据的地址和长度、目的地址、目的地址的空间大小,从注释中可以看出,如果目的地址空间大于源数据的长度,则多余的空间填0
 
ROMHDR 结构体较为负责,这里主要说一下 KernelRelocate 函数中用到的两个变量, ulCopyEntries 表示的是全局变量重定位时需要搬移的条目数, ulCopyOffset 表示的是全局变量重定位时搬移条目的偏移地址。
现在看 KernelRelocate 函数的实现就很简答了, COPYentry 是对搬移条目的描述,通过从 pTOC 获得到一条一条的 COPYentry ,然后根据描述中的信息进行数据的搬移。
这里值得提到的是 pTOC 参数的定义,在 KernelRelocate 函数所在源文件的前面有如下定义:
ROMHDR * volatile const pTOC = (ROMHDR *)-1;         // Gets replaced by RomLoader with real address                
KernelRelocate 函数的一开始就判断 pTOC 是否等于 -1 ,那么后面的搬移操作还会进行吗?显然要进行全局变量重定位的,要不该函数就没有意义了。那样问题的关键就在于 pTOC 是什么时候赋值的,以便为后面的重定位提供相关信息?
答案 pTOC 是在产生 ROM image 的时候由 WinCE 的编译系统赋值的,并同时为该指针指向的 ROMHDR 类型的内存区域填充数据内容的。具体填充过程的代码请见这篇文章 http://jamsan.blog.hexun.com/58621673_d.html 。那又为何要这样做呢?《 Windows CE 工程实践完全解析》中有这样的介绍,完整的编译过程分为 4 个过程: Compile Sysgen Release Copy MakeRun-Time Image Compile 阶段负责将源代码翻译成二进制目标代码, Sysgen 阶段将 Compile 生成的目标代码链接成可执行文件( .exe .dll ), Release Copy 阶段负责将 Sysgen 生成的可执行文件以及其他系统运行需要的数据文件复制到指定的目录下, MakeRun-Time Image 阶段最后将指定目录中的所有文件打包成操作系统镜像。 pTOC 指向的 ROMHDR 的数据内容依赖于 Sysgen 生成的可执行文件的内容,所以只能放到 MakeRun-Time Image 的阶段了。


本文转自jazka 51CTO博客,原文链接:http://blog.51cto.com/jazka/595261,如需转载请自行联系原作者
相关文章
|
芯片
STM32-FreeRTOS源码下载及移植步骤(基于Keil)
STM32-FreeRTOS源码下载及移植步骤(基于Keil)
739 0
STM32-FreeRTOS源码下载及移植步骤(基于Keil)
|
存储 API 调度
基于STM32移植UCGUI图形界面框架(3.9.0源码版本)
基于STM32移植UCGUI图形界面框架(3.9.0源码版本)
509 0
基于STM32移植UCGUI图形界面框架(3.9.0源码版本)
|
NoSQL 小程序 Linux
开源代码分析技巧之——高效Windows源码分析
引言:项目开发中,我们免不了在已有代码或版本的基础上新增代码。这个时候,如何高效的读懂别人代码逻辑,如何从几十万乃至上百万行代码中找到自己需要的逻辑显得尤为重要。
142 0
开源代码分析技巧之——高效Windows源码分析
|
编解码 自然语言处理 C语言
x264源代码分析-转
相关说明: 1.     使用版本:  x264-cvs-2004-05-11 2.     这次的分析基本上已经将代码中最难理解的部分做了阐释,对代码的主线也做了剖析,如果这个主线理解了,就容易设置几个区间,进行分工阅读,将各个区间击破了.
956 0