S3C2410下WinCE6.0的启动过程详解(3)

Code
//
// NKStartup - entry point of kernel.dll.
//
// NK Loader setup only the minimal mappings, which includes ARMHigh area, and the cached static mapping area,
// with *EVERYTHING UNCACHED*. Interrupt vectors are not setup either. So, the init sequence reqiures:
// (1) pickup data passed from nk loader
// (2) Find entry point of oal, exchange globals, find out the cache mode.
// (3) fill in the rest of static mapped area (0xa0000000 - 0xbfffffff), PSL faulting address, interrupt vectors,
//     mod stacks, etc. Then, change the 'cached' static mapping area to use cache, and flush I&D TLB.
// (4) continue normal loading of kernel (find KITLdll, call OEMInitDebugSerial, etc.)
//
void NKStartup (struct KDataStruct * pKData)
{
    PFN_OEMInitGlobals pfnInitGlob;
    PFN_DllMain pfnKitlEntry;
    DWORD dwCpuId = GetCpuId ();

    // (1) pickup arguments from the nk loader
    g_pKData            = pKData;
    pTOC                = (const ROMHDR *) pKData->dwTOCAddr;
    g_pOEMAddressTable  = (PADDRMAP) pKData->pAddrMap;

    /* get architecture id and update page protection attributes */
    pKData->dwArchitectureId = (dwCpuId >> 16) & 0xf;
    if (pKData->dwArchitectureId >= ARMArchitectureV6) {
        // v6 or later
        pKData->dwProtMask = PG_V6_PROTECTION;
        pKData->dwRead     = PG_V6_PROT_READ;
        pKData->dwWrite    = PG_V6_PROT_WRITE;
        pKData->dwKrwUro   = PG_V6_PROT_URO_KRW;
        pKData->dwKrwUno   = PG_V6_PROT_UNO_KRW;

    } else {
        // pre-v6
        pKData->dwProtMask = PG_V4_PROTECTION;
        pKData->dwRead     = PG_V4_PROT_READ;
        pKData->dwWrite    = PG_V4_PROT_WRITE;
        pKData->dwKrwUro   = PG_V4_PROT_URO_KRW;
        pKData->dwKrwUno   = PG_V4_PROT_UNO_KRW;
    }

    // initialize nk globals
    FirstROM.pTOC       = (ROMHDR *) pTOC;
    FirstROM.pNext      = 0;
    ROMChain            = &FirstROM;
    KInfoTable[KINX_PTOC] = (long)pTOC;
    KInfoTable[KINX_PAGESIZE] = VM_PAGE_SIZE;

    g_ppdirNK = (PPAGEDIRECTORY) &ArmHigh->firstPT[0];
    pKData->pNk  = g_pNKGlobal;

    // (2) find entry of oal
    pfnInitGlob = (PFN_OEMInitGlobals) pKData->dwOEMInitGlobalsAddr;

    // no checking here, if OAL entry point doesn't exist, we can't continue
    g_pOemGlobal = pfnInitGlob (g_pNKGlobal);
    g_pOemGlobal->dwMainMemoryEndAddress = pTOC->ulRAMEnd;
    pKData->pOem = g_pOemGlobal;

    // setup globals
    pVMProc         = g_pprcNK;
    pActvProc       = g_pprcNK;

    g_pNKGlobal->pfnWriteDebugString = g_pOemGlobal->pfnWriteDebugString;

    // (3) setup vectors, UC mappings, mode stacks, etc.
    ARMSetup ();

    //
    // cache is enabled from here on
    //

    // (4) common startup code.

    // try to load KITL if exist
    if ((pfnKitlEntry = (PFN_DllMain) g_pOemGlobal->pfnKITLGlobalInit) ||
        (pfnKitlEntry = (PFN_DllMain) FindROMDllEntry (pTOC, KITLDLL))) {
        (* pfnKitlEntry) (NULL, DLL_PROCESS_ATTACH, (DWORD) NKKernelLibIoControl);
    }

#ifdef DEBUG
    CurMSec = dwPrevReschedTime = (DWORD) -200000;      // ~3 minutes before wrap
#endif

    OEMInitDebugSerial ();

    // debugchk only works after we have something to print to.
    DEBUGCHK (pKData == (struct KDataStruct *) PUserKData);
    DEBUGCHK (pKData == &ArmHigh->kdata);

    OEMWriteDebugString ((LPWSTR)NKSignon);

    /* Copy interlocked api code into the kpage */
    DEBUGCHK(sizeof(struct KDataStruct) <= FIRST_INTERLOCK);
    DEBUGCHK((InterlockedEnd-InterlockedAPIs)+FIRST_INTERLOCK <= 0x400);
    memcpy((char *)g_pKData+FIRST_INTERLOCK, InterlockedAPIs, InterlockedEnd-InterlockedAPIs);

    /* setup processor version information */
    CEProcessorType     = (dwCpuId >> 4) & 0xFFF;
    CEProcessorLevel    = 4;
    CEProcessorRevision = (WORD) dwCpuId & 0x0f;
    CEInstructionSet    = PROCESSOR_ARM_V4I_INSTRUCTION;

    RETAILMSG (1, (L"ProcessorType=%4.4x  Revision=%d\r\n", CEProcessorType, CEProcessorRevision));
    RETAILMSG (1, (L"OEMAddressTable = %8.8lx\r\n", g_pOEMAddressTable));

    OEMInit();          // initialize firmware

    // flush I&D TLB
    OEMCacheRangeFlush (NULL, 0, CACHE_SYNC_FLUSH_TLB);

    KernelFindMemory();

    DEBUGMSG (1, (TEXT("NKStartup done, starting up kernel.\r\n")));

    KernelStart ();

    // never returned
    DEBUGCHK (0);
}

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/392d14ee7c46bd4a232f80e3976d6e8b.html