📄 sysinit.c
字号:
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
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 + -