⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sysinit.c

📁 WinCE5.0部分核心源码
💻 C
📖 第 1 页 / 共 2 页
字号:



//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
BOOL 
HookInterrupt(
    int hwInterruptNumber,
    FARPROC pfnHandler
    ) 
{
    if (hwInterruptNumber < ARRAY_SIZE(g_aIntDescTable)) {
        PKIDTENTRY pIDTEntry = &g_aIntDescTable[hwInterruptNumber];
        if (pIDTEntry->Offset == 0 && pIDTEntry->Selector == 0) {
            PINTHOOKSTUB pStub = &g_aIntHookStubs[0];
            for (pStub = &g_aIntHookStubs[0]; pStub <= LAST_ELEMENT(g_aIntHookStubs); pStub++) {
                if (pStub->pfnHandler == NULL) {
                    pStub->PushEax   = 0x50;
                    pStub->Pushad    = 0x60;
                    pStub->MovEsi    = 0xBE;
                    pStub->pfnHandler= pfnHandler;
                    pStub->JmpNear   = 0xE9;
                    pStub->JmpOffset = ((DWORD)&CommonIntDispatch) - ((DWORD)(&pStub->JmpOffset) + 4);
                    InitIDTEntry(hwInterruptNumber, KGDT_R0_CODE, pStub, INTERRUPT_GATE);
                    return(TRUE);
                }
            }
        }
    }
    return(FALSE);
}



//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
BOOL 
UnhookInterrupt(
    int hwInterruptNumber,
    FARPROC pfnHandler
    ) 
{
    if (hwInterruptNumber < ARRAY_SIZE(g_aIntDescTable)) {
        PKIDTENTRY pIDTEntry = &g_aIntDescTable[hwInterruptNumber];
        PINTHOOKSTUB pStub = (PINTHOOKSTUB)(pIDTEntry->Offset + (pIDTEntry->ExtendedOffset << 16));
        if (pStub >= &g_aIntHookStubs[0] && pStub <= LAST_ELEMENT(g_aIntHookStubs)) {
            InitIDTEntry(hwInterruptNumber, 0, 0, 0);
            pStub->pfnHandler = NULL;
            return(TRUE);
        }
    }
    return(FALSE);
}

PPTE        g_pOEMAddressTable;
PPAGETABLE  g_pPageDir;

DWORD       g_dwRAMOfstVA2PA = 0x80000000;

static int FindRAMEntry (PPTE pOEMAddressTable)
{
    int i;
    DWORD dwRAMAddr = pTOC->ulRAMFree;
    for (i = 0; pOEMAddressTable[i].dwSize; i ++) {
        if ((dwRAMAddr >= pOEMAddressTable[i].dwVA)
            && (dwRAMAddr < (pOEMAddressTable[i].dwVA + pOEMAddressTable[i].dwSize))) {
            g_dwRAMOfstVA2PA = pOEMAddressTable[i].dwPA - pOEMAddressTable[i].dwVA;
            break;
        }
    }
    return i;
}

//
// mapping extra ram using 4M pages
//
static void MapExtraRAM4M (DWORD dwRamStart, DWORD dwRamEnd)
{
    DWORD idxPDE   = dwRamStart >> 22;                // index to 1st cached PDE entry
    DWORD idxUCPDE = idxPDE + 0x80;                   // index to 1st uncached PDE entry
    DWORD nEntries = (dwRamEnd - dwRamStart) >> 22;   // # of PDE entries needed

    DEBUGCHK (idxPDE > 0);

    for ( ; nEntries --; idxPDE ++, idxUCPDE ++) {
        g_pPageDir->PTE[idxPDE] = g_pPageDir->PTE[idxPDE-1] + 0x400000;     // cached entry
        g_pPageDir->PTE[idxUCPDE] = g_pPageDir->PTE[idxUCPDE-1] + 0x400000; // uncached entry
    }
}

//
// mapping extra ram using 4K pages
//
static void MapExtraRAM4K (DWORD dwRamStart, DWORD dwRamEnd)
{
    DWORD idxPDE   = dwRamStart >> 22;                // index to 1st cached PDE entry
    DWORD idxUCPDE = idxPDE + 0x80;                   // index to 1st uncached PDE entry
    DWORD nEntries = (dwRamEnd - dwRamStart) >> 22;   // # of PDE entries needed
    PPAGETABLE ppte = (PPAGETABLE) (pTOC->ulRAMFree + MemForPT);    // 2nd Level Page table for cached address
    PPAGETABLE ppteUC = ppte+1;                         // 2nd level page table for uncached address
    PPAGETABLE pptePrev = (PPAGETABLE) Phys2Virt (GetPFN (g_pPageDir->PTE[idxPDE-1] & -PAGE_SIZE));     // previous PDE for cached address
    PPAGETABLE ppteUCPrev = (PPAGETABLE) Phys2Virt (GetPFN (g_pPageDir->PTE[idxUCPDE-1] & -PAGE_SIZE)); // previous PDE for uncached address
    const DWORD pdeAttrib = g_pPageDir->PTE[idxPDE-1] & (PAGE_SIZE-1);      // attribute bits for cached PDE
    const DWORD pdeUCAttrib = g_pPageDir->PTE[idxUCPDE-1] & (PAGE_SIZE-1);  // attribute bits for uncached PDE
    int i;

    // reserver memroy for 2nd level page tables (*2 == 1 for cached and 1 for uncached)
    MemForPT += nEntries * PAGE_SIZE * 2;

    // fill PDE/PTE in 4M chunks.
    for ( ; nEntries --; idxPDE ++, idxUCPDE ++) {

        // file the page table entries. 
        for (i = 0; i < 1024; i ++) {
            ppte->PTE[i] = pptePrev->PTE[i] + 0x400000;
            ppteUC->PTE[i] = ppteUCPrev->PTE[i] + 0x400000;
        }

        // update page directory entries
        g_pPageDir->PTE[idxPDE] = LIN_TO_PHYS (ppte) | pdeAttrib;
        g_pPageDir->PTE[idxUCPDE] = LIN_TO_PHYS (ppteUC) | pdeUCAttrib;

        // update 'prev' page table pointers.
        ppteUCPrev = ppteUC;
        pptePrev = ppte;

        // advance to the next page table.
        // NOTE: we use 2 pages at a time (1 cached, 1 uncached)
        ppte += 2;
        ppteUC += 2;
    }
}

//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void 
SystemInitialization (PPTE pOEMAddressTable, LPDWORD pSysPages) 
{
    int i, idxRam;
    DWORD dwCpuCap;
    DWORD dwMappedRamEnd;

    /* Zero out kernel data page. */
    /* NOTE: need to preserve the number of pages used by Page Tables */
    i = KData.nMemForPT;                // save MemForPT
    dwCpuCap = KData.dwCpuCap;          // save dwCpuCap
    memset(&KData, 0, sizeof(KData));
    KData.nMemForPT = i;                // resotre MemForPT
    KData.dwCpuCap = dwCpuCap;          // restore dwCpuCap
    KData.handleBase = 0x80000000;

    /* Initialize SectionTable in KPage */
    for (i = 1 ; i <= SECTION_MASK ; ++i)
        SectionTable[i] = NULL_SECTION;

    /* Copy kernel data to RAM & zero out BSS */
    KernelRelocate(pTOC);

    /* save the address of OEMAddressTable */
    g_pOEMAddressTable = pOEMAddressTable;
    g_pPageDir = (PPAGETABLE) pSysPages;

    idxRam = FindRAMEntry (pOEMAddressTable);
    dwMappedRamEnd = pOEMAddressTable[idxRam].dwVA + pOEMAddressTable[idxRam].dwSize;
    
    OEMInitDebugSerial();           // initialize serial port

    OEMWriteDebugString(TEXT("\r\nSysInit: "));

    // if config.bib specify more RAM than OEMAddressTable, map extra ram and keep a 
    // copy of the OEMAddressTable, with adjusted size.
    // NOTE: OEMAddress is considered to be in ROM and we cannot modify it directly.

    if (dwMappedRamEnd && (dwMappedRamEnd < pTOC->ulRAMEnd)) {
        // we have more RAM than we've mapped.

        // Round up end address to next 4M. 
        DWORD dwEndAddr = (pTOC->ulRAMEnd + 0x3fffff) & ~0x3fffff;

        NKDbgPrintfW(L"Mapping Extra RAM from 0x%8.8lx to 0x%8.8lx\r\n", dwMappedRamEnd, dwEndAddr);
        // make a copy of OEMAddressTable. we have a full page reserved for this purpose,
        // which can hold more than 300 entries. 
        g_pOEMAddressTable = (PPTE) ((DWORD)pSysPages + PAGE_SIZE);
        for (i = 0; (g_pOEMAddressTable[i] = pOEMAddressTable[i]).dwSize; i ++) {
            // empty loop body
        }

        // update the size of RAM in OEMAddressTable
        g_pOEMAddressTable[idxRam].dwSize = dwEndAddr - g_pOEMAddressTable[idxRam].dwVA;

#ifdef DEBUG
        for (i = 0; g_pOEMAddressTable[i].dwSize; i ++) {
            // empty loop body
            NKDbgPrintfW(L"%d: %8.8lx %8.8lx %8.8lx\r\n", i, 
                g_pOEMAddressTable[i].dwVA, g_pOEMAddressTable[i].dwPA, g_pOEMAddressTable[i].dwSize);
        }
#endif
        // map extra ram.
        if (dwCpuCap & CPUID_PSE) {
            // map extra RAM using 4M pages
            MapExtraRAM4M (dwMappedRamEnd, dwEndAddr); 
        } else {
            // map extra ram using 4K pages
            MapExtraRAM4K (dwMappedRamEnd, dwEndAddr); 
        }
    }
    
    NKDbgPrintfW(L"GDTBase=%8.8lx IDTBase=%8.8lx KData=%8.8lx\r\n", &g_aGlobalDescriptorTable, &g_aIntDescTable, &KData);

    /* Switch to our GDT now that kernel relocation is done */
    __asm {
        lgdt    [g_KernelGDTBase]
        push    KGDT_R0_CODE
        push    offset OurCSIsLoadedNow
        retf
OurCSIsLoadedNow:
        mov     eax, KGDT_R0_DATA
        mov     ss, ax
        mov     eax, KGDT_R3_DATA
        mov     ds, ax
        mov     es, ax
    }

    // Initialize the interrupt dispatch tables
    InitializeTaskStates();
    InitializeIDT();

    OEMWriteDebugString(TEXT("Windows CE Kernel for i486 Built on ") TEXT(__DATE__) TEXT(" at ") TEXT(__TIME__) TEXT("\r\n"));

    //  Initialize the page tables and the floating point unit
    InitializePageTables();
    OEMInit();          // initialize firmware
    KernelFindMemory();
    NKDbgPrintfW (TEXT("X86Init done, OEMAddressTable = %8.8lx.\r\n"), g_pOEMAddressTable);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -