📄 wlmemory.c
字号:
}
}
DbgPrint((DPRINT_WINDOWS, "MadCount: %d\n", MadCount));
WinLdrpDumpMemoryDescriptors(LoaderBlock); //FIXME: Delete!
// Map our loader image, so we can continue running
/*Status = MempSetupPaging(OsLoaderBase >> MM_PAGE_SHIFT, OsLoaderSize >> MM_PAGE_SHIFT);
if (!Status)
{
UiMessageBox("Error during MempSetupPaging");
return;
}*/
//VideoDisplayString(L"Hello from VGA, going into the kernel\n");
DbgPrint((DPRINT_WINDOWS, "HalPT: 0x%X\n", HalPT));
// Page Tables have been setup, make special handling for PCR and TSS
// (which is done in BlSetupFotNt in usual ntldr)
HalPT[(KI_USER_SHARED_DATA - 0xFFC00000) >> MM_PAGE_SHIFT].PageFrameNumber = PcrBasePage+1;
HalPT[(KI_USER_SHARED_DATA - 0xFFC00000) >> MM_PAGE_SHIFT].Valid = 1;
HalPT[(KI_USER_SHARED_DATA - 0xFFC00000) >> MM_PAGE_SHIFT].Write = 1;
HalPT[(KIP0PCRADDRESS - 0xFFC00000) >> MM_PAGE_SHIFT].PageFrameNumber = PcrBasePage;
HalPT[(KIP0PCRADDRESS - 0xFFC00000) >> MM_PAGE_SHIFT].Valid = 1;
HalPT[(KIP0PCRADDRESS - 0xFFC00000) >> MM_PAGE_SHIFT].Write = 1;
// Map VGA memory
//VideoMemoryBase = MmMapIoSpace(0xb8000, 4000, MmNonCached);
//DbgPrint((DPRINT_WINDOWS, "VideoMemoryBase: 0x%X\n", VideoMemoryBase));
Tss = (PKTSS)(KSEG0_BASE | (TssBasePage << MM_PAGE_SHIFT));
// Fill the memory descriptor list and
//PrepareMemoryDescriptorList();
DbgPrint((DPRINT_WINDOWS, "Memory Descriptor List prepared, printing PDE\n"));
List_PaToVa(&LoaderBlock->MemoryDescriptorListHead);
#ifdef DBG
{
ULONG *PDE_Addr=(ULONG *)PDE;//0xC0300000;
int j;
DbgPrint((DPRINT_WINDOWS, "\nPDE\n"));
for (i=0; i<128; i++)
{
DbgPrint((DPRINT_WINDOWS, "0x%04X | ", i*8));
for (j=0; j<8; j++)
{
DbgPrint((DPRINT_WINDOWS, "0x%08X ", PDE_Addr[i*8+j]));
}
DbgPrint((DPRINT_WINDOWS, "\n"));
}
}
#endif
// Enable paging
//BS->ExitBootServices(ImageHandle,MapKey);
// Disable Interrupts
_disable();
// Re-initalize EFLAGS
Ke386EraseFlags();
// Set the PDBR
__writecr3((ULONG_PTR)PDE);
// Enable paging by modifying CR0
__writecr0(__readcr0() | CR0_PG);
// Set processor context
WinLdrSetProcessorContext(GdtIdt, KIP0PCRADDRESS, KSEG0_BASE | (TssBasePage << MM_PAGE_SHIFT));
// Zero KI_USER_SHARED_DATA page
memset((PVOID)KI_USER_SHARED_DATA, 0, MM_PAGE_SIZE);
return TRUE;
}
// Two special things this func does: it sorts descriptors,
// and it merges free ones
VOID
WinLdrInsertDescriptor(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
IN PMEMORY_ALLOCATION_DESCRIPTOR NewDescriptor)
{
PLIST_ENTRY ListHead = &LoaderBlock->MemoryDescriptorListHead;
PLIST_ENTRY PreviousEntry, NextEntry;
PMEMORY_ALLOCATION_DESCRIPTOR PreviousDescriptor = NULL, NextDescriptor = NULL;
DbgPrint((DPRINT_WINDOWS, "BP=0x%X PC=0x%X %s\n", NewDescriptor->BasePage,
NewDescriptor->PageCount, MemTypeDesc[NewDescriptor->MemoryType]));
/* Find a place where to insert the new descriptor to */
PreviousEntry = ListHead;
NextEntry = ListHead->Flink;
while (NextEntry != ListHead)
{
NextDescriptor = CONTAINING_RECORD(NextEntry,
MEMORY_ALLOCATION_DESCRIPTOR,
ListEntry);
if (NewDescriptor->BasePage < NextDescriptor->BasePage)
break;
PreviousEntry = NextEntry;
PreviousDescriptor = NextDescriptor;
NextEntry = NextEntry->Flink;
}
/* Don't forget about merging free areas */
if (NewDescriptor->MemoryType != LoaderFree)
{
/* Just insert, nothing to merge */
InsertHeadList(PreviousEntry, &NewDescriptor->ListEntry);
}
else
{
/* Previous block also free? */
if ((PreviousEntry != ListHead) && (PreviousDescriptor->MemoryType == LoaderFree) &&
((PreviousDescriptor->BasePage + PreviousDescriptor->PageCount) ==
NewDescriptor->BasePage))
{
/* Just enlarge previous descriptor's PageCount */
PreviousDescriptor->PageCount += NewDescriptor->PageCount;
NewDescriptor = PreviousDescriptor;
}
else
{
/* Nope, just insert */
InsertHeadList(PreviousEntry, &NewDescriptor->ListEntry);
}
/* Next block is free ?*/
if ((NextEntry != ListHead) &&
(NextDescriptor->MemoryType == LoaderFree) &&
((NewDescriptor->BasePage + NewDescriptor->PageCount) == NextDescriptor->BasePage))
{
/* Enlarge next descriptor's PageCount */
NewDescriptor->PageCount += NextDescriptor->PageCount;
RemoveEntryList(&NextDescriptor->ListEntry);
}
}
return;
}
VOID
WinLdrSetProcessorContext(PVOID GdtIdt, IN ULONG Pcr, IN ULONG Tss)
{
GDTIDT GdtDesc, IdtDesc, OldIdt;
PKGDTENTRY pGdt;
PKIDTENTRY pIdt;
ULONG Ldt = 0;
//ULONG i;
DbgPrint((DPRINT_WINDOWS, "GDtIdt %p, Pcr %p, Tss 0x%08X\n",
GdtIdt, Pcr, Tss));
// Kernel expects the PCR to be zero-filled on startup
// FIXME: Why zero it here when we can zero it right after allocation?
RtlZeroMemory((PVOID)Pcr, MM_PAGE_SIZE); //FIXME: Why zero only 1 page when we allocate 2?
// Get old values of GDT and IDT
Ke386GetGlobalDescriptorTable(GdtDesc);
Ke386GetInterruptDescriptorTable(IdtDesc);
// Save old IDT
OldIdt.Base = IdtDesc.Base;
OldIdt.Limit = IdtDesc.Limit;
// Prepare new IDT+GDT
GdtDesc.Base = KSEG0_BASE | (ULONG_PTR)GdtIdt;
GdtDesc.Limit = NUM_GDT * sizeof(KGDTENTRY) - 1;
IdtDesc.Base = (ULONG)((PUCHAR)GdtDesc.Base + GdtDesc.Limit + 1);
IdtDesc.Limit = NUM_IDT * sizeof(KIDTENTRY) - 1;
// ========================
// Fill all descriptors now
// ========================
pGdt = (PKGDTENTRY)GdtDesc.Base;
pIdt = (PKIDTENTRY)IdtDesc.Base;
//
// Code selector (0x8)
// Flat 4Gb
//
pGdt[1].LimitLow = 0xFFFF;
pGdt[1].BaseLow = 0;
pGdt[1].HighWord.Bytes.BaseMid = 0;
pGdt[1].HighWord.Bytes.Flags1 = 0x9A;
pGdt[1].HighWord.Bytes.Flags2 = 0xCF;
pGdt[1].HighWord.Bytes.BaseHi = 0;
//
// Data selector (0x10)
// Flat 4Gb
//
pGdt[2].LimitLow = 0xFFFF;
pGdt[2].BaseLow = 0;
pGdt[2].HighWord.Bytes.BaseMid = 0;
pGdt[2].HighWord.Bytes.Flags1 = 0x92;
pGdt[2].HighWord.Bytes.Flags2 = 0xCF;
pGdt[2].HighWord.Bytes.BaseHi = 0;
//
// Selector (0x18)
// Flat 2Gb
//
pGdt[3].LimitLow = 0xFFFF;
pGdt[3].BaseLow = 0;
pGdt[3].HighWord.Bytes.BaseMid = 0;
pGdt[3].HighWord.Bytes.Flags1 = 0xFA;
pGdt[3].HighWord.Bytes.Flags2 = 0xCF;
pGdt[3].HighWord.Bytes.BaseHi = 0;
//
// Selector (0x20)
// Flat 2Gb
//
pGdt[4].LimitLow = 0xFFFF;
pGdt[4].BaseLow = 0;
pGdt[4].HighWord.Bytes.BaseMid = 0;
pGdt[4].HighWord.Bytes.Flags1 = 0xF2;
pGdt[4].HighWord.Bytes.Flags2 = 0xCF;
pGdt[4].HighWord.Bytes.BaseHi = 0;
//
// TSS Selector (0x28)
//
pGdt[5].LimitLow = 0x78-1; // 60 dwords
pGdt[5].BaseLow = (USHORT)(Tss & 0xffff);
pGdt[5].HighWord.Bytes.BaseMid = (UCHAR)((Tss >> 16) & 0xff);
pGdt[5].HighWord.Bytes.Flags1 = 0x89;
pGdt[5].HighWord.Bytes.Flags2 = 0x00;
pGdt[5].HighWord.Bytes.BaseHi = (UCHAR)((Tss >> 24) & 0xff);
//
// PCR Selector (0x30)
//
pGdt[6].LimitLow = 0x01;
pGdt[6].BaseLow = (USHORT)(Pcr & 0xffff);
pGdt[6].HighWord.Bytes.BaseMid = (UCHAR)((Pcr >> 16) & 0xff);
pGdt[6].HighWord.Bytes.Flags1 = 0x92;
pGdt[6].HighWord.Bytes.Flags2 = 0xC0;
pGdt[6].HighWord.Bytes.BaseHi = (UCHAR)((Pcr >> 24) & 0xff);
//
// Selector (0x38)
//
pGdt[7].LimitLow = 0xFFFF;
pGdt[7].BaseLow = 0;
pGdt[7].HighWord.Bytes.BaseMid = 0;
pGdt[7].HighWord.Bytes.Flags1 = 0xF3;
pGdt[7].HighWord.Bytes.Flags2 = 0x40;
pGdt[7].HighWord.Bytes.BaseHi = 0;
//
// Some BIOS fuck (0x40)
//
pGdt[8].LimitLow = 0xFFFF;
pGdt[8].BaseLow = 0x400;
pGdt[8].HighWord.Bytes.BaseMid = 0;
pGdt[8].HighWord.Bytes.Flags1 = 0xF2;
pGdt[8].HighWord.Bytes.Flags2 = 0x0;
pGdt[8].HighWord.Bytes.BaseHi = 0;
//
// Selector (0x48)
//
pGdt[9].LimitLow = 0;
pGdt[9].BaseLow = 0;
pGdt[9].HighWord.Bytes.BaseMid = 0;
pGdt[9].HighWord.Bytes.Flags1 = 0;
pGdt[9].HighWord.Bytes.Flags2 = 0;
pGdt[9].HighWord.Bytes.BaseHi = 0;
//
// Selector (0x50)
//
pGdt[10].LimitLow = 0xFFFF; //FIXME: Not correct!
pGdt[10].BaseLow = 0;
pGdt[10].HighWord.Bytes.BaseMid = 0x2;
pGdt[10].HighWord.Bytes.Flags1 = 0x89;
pGdt[10].HighWord.Bytes.Flags2 = 0;
pGdt[10].HighWord.Bytes.BaseHi = 0;
//
// Selector (0x58)
//
pGdt[11].LimitLow = 0xFFFF;
pGdt[11].BaseLow = 0;
pGdt[11].HighWord.Bytes.BaseMid = 0x2;
pGdt[11].HighWord.Bytes.Flags1 = 0x9A;
pGdt[11].HighWord.Bytes.Flags2 = 0;
pGdt[11].HighWord.Bytes.BaseHi = 0;
//
// Selector (0x60)
//
pGdt[12].LimitLow = 0xFFFF;
pGdt[12].BaseLow = 0; //FIXME: Maybe not correct, but noone cares
pGdt[12].HighWord.Bytes.BaseMid = 0x2;
pGdt[12].HighWord.Bytes.Flags1 = 0x92;
pGdt[12].HighWord.Bytes.Flags2 = 0;
pGdt[12].HighWord.Bytes.BaseHi = 0;
//
// Video buffer Selector (0x68)
//
pGdt[13].LimitLow = 0x3FFF;
pGdt[13].BaseLow = 0x8000; //FIXME: I guess not correct for UGA
pGdt[13].HighWord.Bytes.BaseMid = 0x0B;
pGdt[13].HighWord.Bytes.Flags1 = 0x92;
pGdt[13].HighWord.Bytes.Flags2 = 0;
pGdt[13].HighWord.Bytes.BaseHi = 0;
//
// Points to GDT (0x70)
//
pGdt[14].LimitLow = NUM_GDT*sizeof(KGDTENTRY) - 1;
pGdt[14].BaseLow = 0x7000;
pGdt[14].HighWord.Bytes.BaseMid = 0xFF;
pGdt[14].HighWord.Bytes.Flags1 = 0x92;
pGdt[14].HighWord.Bytes.Flags2 = 0;
pGdt[14].HighWord.Bytes.BaseHi = 0xFF;
//
// Some unused descriptors should go here
// ...
//
// Fill IDT with Traps
//
#if 0
pIdt[0].Offset = (i386DivideByZero | KSEG0_BASE) & 0xFFFF;
pIdt[0].ExtendedOffset = 0x8; // Selector
pIdt[0].Access = 0x8F00;
pIdt[0].Selector = (i386DivideByZero | KSEG0_BASE) >> 16; // Extended Offset
pIdt[1].Offset = (i386DebugException | KSEG0_BASE) & 0xFFFF;
pIdt[1].ExtendedOffset = 0x8; // Selector
pIdt[1].Access = 0x8F00;
pIdt[1].Selector = (i386DebugException | KSEG0_BASE) >> 16; // Extended Offset
pIdt[2].Offset = (i386NMIException | KSEG0_BASE) & 0xFFFF;
pIdt[2].ExtendedOffset = 0x8; // Selector
pIdt[2].Access = 0x8F00;
pIdt[2].Selector = (i386NMIException | KSEG0_BASE) >> 16; // Extended Offset
pIdt[3].Offset = (i386Breakpoint | KSEG0_BASE) & 0xFFFF;
pIdt[3].ExtendedOffset = 0x8; // Selector
pIdt[3].Access = 0x8F00;
pIdt[3].Selector = (i386Breakpoint | KSEG0_BASE) >> 16; // Extended Offset
pIdt[4].Offset = (i386Overflow | KSEG0_BASE) & 0xFFFF;
pIdt[4].ExtendedOffset = 0x8; // Selector
pIdt[4].Access = 0x8F00;
pIdt[4].Selector = (i386Overflow | KSEG0_BASE) >> 16; // Extended Offset
pIdt[5].Selector = (i386BoundException | KSEG0_BASE) >> 16; // Extended Offset
pIdt[5].Offset = (i386BoundException | KSEG0_BASE) & 0xFFFF;
pIdt[5].ExtendedOffset = 0x8; // Selector
pIdt[5].Access = 0x8F00;
pIdt[6].Selector = (i386InvalidOpcode | KSEG0_BASE) >> 16; // Extended Offset
pIdt[6].Offset = (i386InvalidOpcode | KSEG0_BASE) & 0xFFFF;
pIdt[6].ExtendedOffset = 0x8; // Selector
pIdt[6].Access = 0x8F00;
pIdt[7].Selector = (i386FPUNotAvailable | KSEG0_BASE) >> 16; // Extended Offset
pIdt[7].Offset = (i386FPUNotAvailable | KSEG0_BASE) & 0xFFFF;
pIdt[7].ExtendedOffset = 0x8; // Selector
pIdt[7].Access = 0x8F00;
pIdt[8].Selector = (i386DoubleFault | KSEG0_BASE) >> 16; // Extended Offset
pIdt[8].Offset = (i386DoubleFault | KSEG0_BASE) & 0xFFFF;
pIdt[8].ExtendedOffset = 0x8; // Selector
pIdt[8].Access = 0x8F00;
pIdt[9].Selector = (i386CoprocessorSegment | KSEG0_BASE) >> 16; // Extended Offset
pIdt[9].Offset = (i386CoprocessorSegment | KSEG0_BASE) & 0xFFFF;
pIdt[9].ExtendedOffset = 0x8; // Selector
pIdt[9].Access = 0x8F00;
pIdt[10].Selector = (i386InvalidTSS | KSEG0_BASE) >> 16; // Extended Offset
pIdt[10].Offset = (i386InvalidTSS | KSEG0_BASE) & 0xFFFF;
pIdt[10].ExtendedOffset = 0x8; // Selector
pIdt[10].Access = 0x8F00;
pIdt[11].Selector = (i386SegmentNotPresent | KSEG0_BASE) >> 16; // Extended Offset
pIdt[11].Offset = (i386SegmentNotPresent | KSEG0_BASE) & 0xFFFF;
pIdt[11].ExtendedOffset = 0x8; // Selector
pIdt[11].Access = 0x8F00;
pIdt[12].Selector = (i386StackException | KSEG0_BASE) >> 16; // Extended Offset
pIdt[12].Offset = (i386StackException | KSEG0_BASE) & 0xFFFF;
pIdt[12].ExtendedOffset = 0x8; // Selector
pIdt[12].Access = 0x8F00;
pIdt[13].Selector = (i386GeneralProtectionFault | KSEG0_BASE) >> 16; // Extended Offset
pIdt[13].Offset = (i386GeneralProtectionFault | KSEG0_BASE) & 0xFFFF;
pIdt[13].ExtendedOffset = 0x8; // Selector
pIdt[13].Access = 0x8F00;
pIdt[14].Selector = (i386PageFault | KSEG0_BASE) >> 16; // Extended Offset
pIdt[14].Offset = (i386PageFault | KSEG0_BASE) & 0xFFFF;
pIdt[14].ExtendedOffset = 0x8; // Selector
pIdt[14].Access = 0x8F00;
pIdt[15].Selector = 0; // Extended Offset
pIdt[15].Offset = 0;
pIdt[15].ExtendedOffset = 0; // Selector
pIdt[15].Access = 0;
pIdt[16].Selector = (i386CoprocessorError | KSEG0_BASE) >> 16; // Extended Offset
pIdt[16].Offset = (i386CoprocessorError | KSEG0_BASE) & 0xFFFF;
pIdt[16].ExtendedOffset = 0x8; // Selector
pIdt[16].Access = 0x8F00;
pIdt[17].Selector = (i386AlignmentCheck | KSEG0_BASE) >> 16; // Extended Offset
pIdt[17].Offset = (i386AlignmentCheck | KSEG0_BASE) & 0xFFFF;
pIdt[17].ExtendedOffset = 0x8; // Selector
pIdt[17].Access = 0x8F00;
#endif
/*for (i=0; i<16; i++)
{
//pIdt[i].Offset = ((ULONG_PTR)i386GeneralProtectionFault | KSEG0_BASE) & 0xFFFF;
//pIdt[i].ExtendedOffset = 0x8; // Selector
//pIdt[i].Access = 0x8F00;
//pIdt[i].Selector = ((ULONG_PTR)i386GeneralProtectionFault | KSEG0_BASE) >> 16; // Extended Offset
pIdt[i].Offset = ((ULONG_PTR)i386GeneralProtectionFault | KSEG0_BASE) & 0xFFFF;
pIdt[i].ExtendedOffset = ((ULONG_PTR)i386GeneralProtectionFault | KSEG0_BASE) >> 16; // Extended Offset
pIdt[i].Access = 0x8F00;
pIdt[i].Selector = 0x8;
}*/
// Copy the old IDT
RtlCopyMemory(pIdt, (PVOID)OldIdt.Base, OldIdt.Limit);
// Mask interrupts
//asm("cli\n"); // they are already masked before enabling paged mode
// Load GDT+IDT
Ke386SetGlobalDescriptorTable(GdtDesc);
Ke386SetInterruptDescriptorTable(IdtDesc);
// Jump to proper CS and clear prefetch queue
asm("ljmp $0x08, $mb1\n"
"mb1:\n");
// Set SS selector
asm(".intel_syntax noprefix\n");
asm("mov ax, 0x10\n"); // DataSelector=0x10
asm("mov ss, ax\n");
asm(".att_syntax\n");
// Set DS and ES selectors
Ke386SetDs(0x10);
Ke386SetEs(0x10); // this is vital for rep stosd
// LDT = not used ever, thus set to 0
Ke386SetLocalDescriptorTable(Ldt);
// Load TSR
Ke386SetTr(0x28);
// Clear GS
asm(".intel_syntax noprefix\n");
asm("push 0\n");
asm("pop gs\n");
asm(".att_syntax\n");
// Set FS to PCR
Ke386SetFs(0x30);
// Real end of the function, just for information
/* do not uncomment!
pop edi;
pop esi;
pop ebx;
mov esp, ebp;
pop ebp;
ret
*/
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -