您的位置:首页 > 其它

Windows CE 6.0的内核传输无关层(KITL)分析(2)

2011-12-25 22:51 218 查看
 
(3)Windows CE 6.0
的KITL初始化过程分析

在WinCE6.0中,内核调用OEMInit()函数对目标平台进行初始化过程时,需要启动KITL的支持,但由于OEMInit()函数属于oal.exe文件,不能像WinCE5.0那样直接调用初始化KITL的函数,根据Windows CE 6.0中共享变量或函数的互访原则(见Windows CE 6.0启动分析部分),它们只能通过系统定义的OEMGLOBAL和NKGLOBAL两个结构体来实现,当在编译选项(Build
Options)中选中Enable KITL时,编译器就会将kitl.dll动态链接库链接到到内核中,在OEMGLOBAL结构体定义了利用KITLOEM宏将kitl.dll的入口函数KitlDllMain编译到系统中条件,这是系统链接的库为oemmain_statickitl.lib,下面为OEMGLOBAL结构体中KITL的定义部分:

    // Platform specific information passed from OAL to KITL.
    NULL,                                   // LPVOID                  pKitlInfo
#ifdef KITLOEM
    KitlDllMain,                            // KITL entry point (KITL is part of OEM)       

#else
    NULL,                                   // KITL entry point (KITL is in a separate DLL) 

#endif

一旦kitl.dll启动时,在其入口函数KitlDllMain中将KITLIoctl函数地址赋给NKGLOBAL的pfnKITLIoctl指针,同时也从内核启动参数结构体(KDataStruct )g_pKData中获取OEMGLOBAL结构体的指针,这样便可以实现共享变量或函数的互访。即OAL中的OEMInit()函数通过NKGLOBAL结构体间接调用KITLIoctl
函数启动KITL的初始化。

$(_PRIVATEROOT)\WINCEOS\COREOS\NK\KITL\ethdbg.c
BOOL WINAPI KitlDllMain (HINSTANCE DllInstance, DWORD dwReason, LPVOID Reserved)
{
    if (DLL_PROCESS_ATTACH == dwReason) {
        PFN_KLIBIOCTL pfnKLibIoctl = (PFN_KLIBIOCTL) Reserved;
        g_kpriv.pfnExtKITLIoctl = ExtKITLIoctl;               
        (* pfnKLibIoctl) ((HANDLE)KMOD_KITL, IOCTL_KLIB_KITL_INIT, NULL, 0, &g_kpriv, sizeof (g_kpriv), NULL);
        g_pKData        = g_kpriv.pKData;
        g_pprcNK        = g_kpriv.pprcNK;
        g_pNKGlobal     = g_pKData->pNk;
        g_pOemGlobal    = g_pKData->pOem;
        g_pNKGlobal->pfnKITLIoctl = KITLIoctl;
#ifdef DEBUG
        g_pNKGlobal->pKITLDbgZone = &dpCurSettings;
#endif
    }
    return TRUE;
}

 
$(_PRIVATEROOT)\WINCEOS\COREOS\NK\OEMSTUB\oemstub.c
void OEMInit (void)
{
    g_pOemGlobal->pfnInitPlatform ();
}
 
$(_PRIVATEROOT)\WINCEOS\COREOS\NK\NKSTUB\kitlstub.c
BOOL KITLIoctl (DWORD dwCode, LPVOID pInBuf, DWORD nInSize, LPVOID pOutBuf, DWORD nOutSize, LPDWORD pcbRet)
{
    return g_pNKGlobal->pfnKITLIoctl (dwCode, pInBuf, nInSize, pOutBuf, nOutSize, pcbRet);
}
 
$(_PLATFORMROOT)\xsbase270\src\oal\OalLib\Init.c
void OEMInit()
{
    volatile XSBASE270_CPLD_REGS *pCPLDRegs = (volatile XSBASE270_CPLD_REGS *) OALPAtoVA(XSBASE270_BASE_REG_PA_CPLD, FALSE);
    volatile XSBASE270_MEMBCR_REGS *pMEMBCRRegs = (volatile XSBASE270_MEMBCR_REGS *) OALPAtoVA(XSBASE270_BASE_PA_BCR, FALSE);
……
    // Initialize the KITL connection if required.
     KITLIoctl(IOCTL_KITL_STARTUP, NULL, 0, NULL, 0, NULL);
…….
    OALMSG(OAL_FUNC, (L"-OEMInit\r\n"));
}

   

$(_PRIVATEROOT)\WINCEOS\COREOS\NK\KITL\ethdbg.c
BOOL KITLIoctl (DWORD dwIoControlCode, LPVOID lpInBuf, DWORD nInBufSize, LPVOID lpOutBuf, DWORD nOutBufSize, LPDWORD lpBytesReturned)
{
    BOOL retval = FALSE;
    switch (dwIoControlCode) {
    case IOCTL_KITL_STARTUP:
        retval = OEMKitlStartup ();
        break;
……      
    return retval;
}
根据上述分析和上面五段代码,我们再理一下函数的调用顺序。

内核调用$(_PRIVATEROOT)\WINCEOS\COREOS\NK\OEMMAIN\oemstub.c中的OEMInit函数,该函数通过OEMGLOBAL结构体中的函数指针pfnInitPlatform(在oemglobal.c中初始化)调用$(_PLATFORMROOT)\xsbase270\src\oal\OalLib\Init.c中的OEMInit函数,该函数在调用KITLIoctl函数时,实际上调用$(_PRIVATEROOT)\WINCEOS\COREOS\NK\NKSTUB\kitlstub.c中的KITLIoctl,KITLIoctl函数通过NKGLOBAL结构体中的pfnKITLIoctl函数指针再调用$(_PRIVATEROOT)\WINCEOS\COREOS\NK\KITL\ethdbg.c中的KITLIoctl函数。Windows
CE 6.0中函数调用好像是在绕圈子,这也是它的奥妙之处。在理顺上述函数调用顺序之后,后面函数的调用便相当简单啦。
OEMInit 函数中调用KITLIoctl(IOCTL_KITL_STARTUP, NULL, 0, NULL, 0, NULL)函数的第一个参数为IOCTL_KITL_STARTUP,根据上述函数调用顺序关系,该KITLIoctl函数最终被调用的位置为$(_PRIVATEROOT)\WINCEOS\COREOS\NK\KITL\ethdbg.c中的KITLIoctl函数,从源代码可以发现,IOCTL_KITL_STARTUP对于的选择语句为retval = OEMKitlStartup (),即函数调用回到类似Windows
CE 5.0中OALKitlStart()函数,Windows CE 6.0 KITL的移植步骤中提到需要将Windows CE 5.0中OALKitlStart()函数重命名为OEMKitlStartup()函数。如果你对Windows CE 5.0的KITL函数调用顺序比较熟悉的话,后面的内容就可以不用再看啦
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息