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

📄 wlmemory.c

📁 ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机理和API函数调用几乎相同。甚至可以兼容XP的程序。喜欢研究系统内核的人可以看一看。
💻 C
📖 第 1 页 / 共 2 页
字号:
		}
	}

	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 + -