Windows CE 6.0 启动过程分析1

来源:互联网 发布:数据分析师考试报名费 编辑:程序博客网 时间:2024/05/16 13:07

在Windows CE 6.0中,内核(Kenerl)和OEM代码被分成oal.exe、kernel.dll和kitl.dll三个部分,其中启动代码(startup)和 OAL层的实现部分不再与内核链接生成NK.exe,取而代之的是启动代码(startup)和硬件相关且独立于内核的OAL层的实现部分编译成 oal.exe,而与内核相关且独立于硬件的OAL层代码包含在kernel.dll中;内核无关传输层(KITL)的支持代码从OAL层分离出来编译成 kitl.dll。

    从表面上看,好像只是代码重新组合了一下,从帮助文档中BSP的移植过程看好像也是这么一回事,实际上,整个Windows CE 6.0内核布局发生了很大的改变。Windows CE 6.0的启动过程也是如此,如果你想按照Windows CE 5.0的启动顺序去分析Windows CE 6.0的启动顺序,可能会走到一个死胡同。主要是因为Windows CE 6.0在启动过程中调用了kernel.dll和kitl.dll两个动态链接库的原因,而且Windows CE6.0不再编译生成KernKitlProf.exe内核文件。
    从Windows CE 6.0的帮助文档可以看出,WinCE6.0的启动只与oal.exe和kernel.dll有关,至于kitl.dll,只有将操作系统编译成具有 KITL功能时才用到。分析Windows CE 6.0的启动过程实际上找到编译oal.exe和kernel.dll的源码位置。
    首先看一下将WinCE6.0编译成诸如WinCE5.0所说的基本内核情况,即kern.exe。对于oal.exe源码位置比较容易找到,因为 oal.exe是启动代码与硬件相关的OAL层实现文件编译而成,所以只需在BSP的OAL目录中便能找到。而对于kernel.dll,在BSP目录结构中,基本上无法找到kernel.dll的编译文件,所以必须从其他方面着手。
    下面为WinCE 6.0的编译日志输出文件:makeimg.out在文件复制过程的一部分:
Copying E:/WINCE600/OSDesigns/xsbase270/xsbase270/RelDir/XSBase270_ARMV4I_Release/oal.exe   to
E:/WINCE600/OSDesigns/xsbase270/xsbase270/RelDir/XSBase270_ARMV4I_Release/nk.exe for debugger
Copying E:/WINCE600/OSDesigns/xsbase270/xsbase270/RelDir/XSBase270_ARMV4I_Release/kern.dll   to
E:/WINCE600/OSDesigns/xsbase270/xsbase270/RelDir/XSBase270_ARMV4I_Release/kernel.dll for debugger
    从日志输出文件可以看出,在文件复制过程中,WinCE6.0编译器将oal.exe更名为nk.exe,而将kern.dll文件更名为 kernel.dll,也就是说,kern.dll文件的实现部分就是kernel.dll的实现体。根据前面的分析,oal.exe是与硬件相关独立于内核的OAL层的实现部分,而kernel.dll为内核相关独立于硬件的OAL层的实现部分。同样可以从最后整合后的二进制配置文件ce.bib文件中看出端倪。
; @CESYSGEN IF CE_MODULES_NK
nk.exe E:/WINCE600/OSDesigns/xsbase270/xsbase270/RelDir/XSBase270_ARMV4I_Release/oal.exe NK SHZ
kitl.dll E:/WINCE600/OSDesigns/xsbase270/xsbase270/RelDir/XSBase270_ARMV4I_Release/kitl.dll NK SHZ
kernel.dll E:/WINCE600/OSDesigns/xsbase270/xsbase270/RelDir/XSBase270_ARMV4I_Release/kern.dll NK SHZ
; @CESYSGEN ENDIF
    而kern.dll动态库在整个Windows CE6.0中没有显式编译过程,即没有一个sources文件有kern.dll的编译过程,所以只能从操作系统的编译文件Makefile中寻找其编译过程。下面看一下$(_PUBLICROOT)/common/CESYSGEN/makefile中的部分内容:
nk::$(NK_COMPONENTS) $(NK_REPLACE_COMPONENTS)
@copy $(SG_INPUT_LIB)/oemstub.pdb $(SG_OUTPUT_OAKLIB)
@copy $(SG_INPUT_LIB)/oemstub.lib $(SG_OUTPUT_OAKLIB)
set TARGETTYPE=DYNLINK
set TARGETNAME=kern
set RELEASETYPE=OAK
set DLLENTRY=NKStartup
set DEFFILE=NO_DEF_FILE
set TARGETLIBS=
set SOURCELIBS=%%NKLIBS%% $(SG_INPUT_LIB)/nkmain.lib $(SG_INPUT_LIB)/fulllibc.lib
$(MAKECMD) /NOLOGO NOLIBC=1 kern.dll
    从上述代码中可以发现,原来kern.dll动态库是从oemstub.lib编译而来,而且与nkmain.lib有关。
    在理顺了上述文件的相互之间的关系之后,再来分析Windows CE 6.0的启动过程可能就比较容易啦。
    在理清了上述文件的关系之后,便可以分析任意一款基于ARM微处理器的Windows CE 6.0的启动过程,现在以深圳亿道电子技术有限公司开发的基于PXA270 ARM开发平台为例,分析Windows CE 6.0操作系统启动过程。
1、Startup函数:
    从Windows CE 6.0的帮助文档可以看出,WinCE6.0的启动只与oal.exe和kernel.dll有关,至于kitl.dll,只有将操作系统编译成具有 KITL功能时才用到。分析Windows CE 6.0的启动过程实际上找到编译oal.exe和kernel.dll的源码位置。
oal.exe的通过Startup函数完成硬件的初始化。Startup.s代码与该硬件平台的Bootloader启动代码共用,其中PreInit 函数主要完成将ARM处理器工作模式切换到管理员模式、同时关闭MMU,并检测系统启动原因,如果是热启动、即在该函数调用之前已经启动了 Bootloader程序,相当基本硬件初始化已经完成,则直接跳转到OALStartUp函数中;否则需要进行硬件中断屏蔽、内存、系统时钟频率、电源管理等硬件的基本初始化过程。(具体过程见代码的分析)
$(_PLATFORMROOT)/xsbase270/src/common/Startup/Startup.s
LEAF_ENTRY StartUp
    bl PreInit
    tst r10, #RCSR_HARD_RESET
    beq OALStartUp
    tst r10, #RCSR_GPIO_RESET
    bne Continue_StartUp
    bl xlli_mem_init ;初始化内存控制器
    ldr r0, =xlli_PMRCREGS_PHYSICAL_BASE;
    ldr r0, [r0, #xlli_PSPR_offset];
    mov r1, r10;
    bl XllpPmValidateResumeFromSleep;
    cmp r0, #0;
    bne Failed_Sleep_Resume;
    Sleep_Reset
    ldr r0, =xlli_PMRCREGS_PHYSICAL_BASE;
    ldr r0, [r0, #xlli_PSPR_offset];
    mov r1, r10;
    b XllpPmGoToContextRestoration;
    Failed_Sleep_Resume
    ldr r1, =xlli_RCSR_SMR
    bic r10, r10, r1
    Continue_StartUp
    bl xlli_intr_init; ;初始化中断控制器
    bl EnableClks; ;使能内核时钟(内存/OS定时器/FFART时钟之需)
    bl OALXScaleSetFrequencies ;设置系统频率
    bl xlli_mem_Topt
    bl xlli_mem_restart ;复位内存,使其处于工作模式
    bl xlli_ost_init ;初始化操作系统定时器
    bl xlli_pwrmgr_init ;初始化电源管理
    bl xlli_IMpwr_init ;初始化内部存储器
   b
ENTRY_END
 
2、OALStartUp函数:
    在系统硬件初始化完毕之后,Startup调用OALStartUp函数,OALStartUp函数主要完成将OEMAddressTable表传递给内核;然后调用KernelStart函数跳转到内核OEMAddressTable表的主要作用表的每一个入口都定义了一个内存中的物理位置、内存的大小以及映射这物理地址的静态虚拟地址;
◆静态虚拟内存地址被定义在缓冲存储器的范围之内;
◆内核可以创建非缓冲的内存地址指向到相同的物理地址;
◆对于同一物理地址,既有一个缓冲的虚拟内存地址,也有一个非缓冲的虚拟内存地址;
◆OEMAddressTable最后必须以0结尾;
◆对于MIPS和SHx类型的CPU,物理地址与虚拟地址的映射由CPU完成,无需创建OEMAddressTable
$(_PLATFORMROOT)/xsbase270/src/Inc/ Oemaddrtab_cfg.inc):
ALIGN g_oalAddressTable
    DCD 0x80000000, 0xA0000000,64; XSBASE270: SDRAM (64MB).
    DCD 0x84000000, 0x5C000000,1; BULVERDE: Internal SRAM (64KB bank 0).
    DCD 0x84100000, 0x58000000,1; BULVERDE: Internal memory PM registers.
    DCD 0x84200000, 0x4C000000,1; BULVERDE: USB host controller.
    DCD 0x84300000, 0x48000000,1; BULVERDE: Memory controller.
    DCD 0x84400000, 0x44000000,1; BULVERDE: LCD controller.
    DCD 0x84500000, 0x40000000,32; BULVERDE: Memory-mapped registers
    DCD 0x86500000, 0x00000000,64; XSBASE270: nCS0: Boot Flash (64MB).
    DCD 0x96600000, 0x3C000000,64; BULVERDE: PCMCIA S1 common memory space.
    DCD 0x8A600000, 0x38000000,32; BULVERDE: PCMCIA S1 attribute memory space.
    DCD 0x8C600000, 0x30000000,32; BULVERDE: PCMCIA S1 I/O space.
    DCD 0x8E500000, 0x2C000000,64; BULVERDE: PCMCIA S0 common memory space.
    DCD 0x92500000, 0x28000000,32; BULVERDE: PCMCIA S0 attribute memory space.
    DCD 0x94500000, 0x20000000,32; BULVERDE: PCMCIA S0 I/O space.
    DCD 0x96500000, 0xE0000000,1; XSBASE270: Zero-bank .
    DCD 0x96600000, 0x14000000,1; XSBASE270: nCS5: eXpansion board header.
    DCD 0x96600000, 0x10000000,64; XSBASE270: nCS4: USB2.0/IDE controller.
    DCD 0x9A700000, 0x0C000000,1; XSBASE270: nCS3: SMSC 91C111 Ethernet controller.
    DCD 0x9A800000, 0x0A000000,1; XSBASE270: nCS2 : Board registers (CPLD).
    DCD 0x9A900000, 0x04000000,32; XSBASE270: nCS1: Secondary flash (32MB).
    DCD 0x9F900000, 0x50000000,1; BULVERDE: Camera peripheral interface.
    DCD 0x9FA00000, 0x14700000,1
    DCD 0x00000000, 0x00000000,0;end of table
END
 
 
$(_PLATFORMROOT)/xsbase270/src/oal/OalLib/Startup.s
ALIGN
LEAF_ENTRY OALStartUp
    add r0, pc, #g_oalAddressTable - (. + 8)
    mov r11, r0
    b KernelStart
    nop
    nop
    nop
    nop
    nop
    nop
    STALL
    b STALL ;Spin forever.
原创粉丝点击