mov gs, ax
mov ss, ax
+++ /* checkPoint Charlie - where it all began... */
+++ mov si, offset _CheckPoint0
+++ call writestr
+++
/* Setup a real mode stack */
mov sp, stack16
call x86_16_EnableA20
+++ /* checkPoint Charlie - where it all began... */
+++ mov si, offset _CheckPoint1
+++ call writestr
+++
call x86_16_BuildPageTables
+++
+++ /* checkPoint Charlie - where it all began... */
+++ mov si, offset _CheckPoint2
+++ call writestr
+++
+++ /* Check if CPU supports CPUID */
+++
+++ pushfd
+++ pop eax
+++ mov ebx, eax
+++ xor eax, 0x00200000
+++ push eax
+++ popfd
+++ pushfd
+++ pop eax
+++ cmp eax,ebx
+++ jz NO_CPUID_SUPPORT_DETECTED
+++
+++ /* CPUID support detected - getting the PAE/PGE */
+++
+++ mov eax,1 // Fn0000_0001 - PAE in EDX[6]
+++ cpuid
+++ xor eax,eax
+++ and edx,0x00a0
+++ test edx,edx // are PAE and PGE bits set?
+++ jz NO_X64_SUPPORT_DETECTED
+++
+++ /* PAE and PGE are here */
+++
+++ xor edx, edx
+++ mov eax, 0x80000001
+++ cpuid
+++ and edx, 0x20000000
+++ test edx,edx
+++ jz NO_X64_SUPPORT_DETECTED
+++
+++ /* X64 Processor */
+++
+++ /* checkPoint Charlie - where it all began... */
+++ mov si, offset _CheckPoint3
+++ call writestr
+++
+++ jmp _switch64
+++
+++NO_X64_SUPPORT_DETECTED:
+++ mov si, offset _NotAnX64Processor // Loading message
+++ call writestr
+++ jmp _fail
+++
+++NO_CPUID_SUPPORT_DETECTED:
+++ mov si, offset _NoCPUIDSupport // Loading message
+++ call writestr
+++
+++_fail:
+++ jmp _fail
+++ nop
+++ nop
--- /* Switch to long mode */
+++_switch64:
call x86_16_SwitchToLong
.code64
-- /* Checkpoint */
+ // mov ax, LMODE_DS
+ // mov ds, ax
+ // mov word ptr ds:[0xb8000], 0x0e00 + '1'
+
/* GO! */
xor rcx, rcx
call _BootMain
--// mov word ptr ds:[0xb8002], 0x0e00 + '2'
+ /* Checkpoint */
+ // mov ax, LMODE_DS
+ // mov ds, ax
+++// mov word ptr ds:[0xb8002], 0x0e02 + '2'
+
+++
/* Return into real mode */
call x86_64_SwitchToReal
.code16
popa
ret
---
/*
* We define 512 2MB pages at the start of memory, so we can access the first
* 1 GB as if paging was disabled
popa
ret
+++/*
+++ * writechr,writestr
+++ *
+++ *
+++ */
+++writestr:
+++ pushfd
+++ pushad
+++.top:
+++ lodsb
+++ and al, al
+++ jz .end
+++ call writechr
+++ jmp short .top
+++.end:
+++ popad
+++ popfd
+++ ret
+++
+++
+++writechr:
+++ pushf
+++ pusha
+++ mov ah, 0x0E
+++ xor bx, bx
+++ int 0x10
+++ popa
+++ popf
+++ ret
//.global x86_16_SwitchToLong
x86_16_SwitchToLong:
+++
cli
xor ax,ax
/* Now return in long mode! */
ret
---
---/** 64 But functions **********************************************************/
+++/** 64 Bit functions **********************************************************/
.code64
.global x86_64_SwitchToReal
_BootPartition:
.long 0
+++.global _NotAnX64Processor
+++_NotAnX64Processor:
+++ .ascii "FreeLoader: No x64-compatible CPU detected! Exiting..."
+++ .byte 0x0d, 0x0a, 0
+++
+++.global _NoCPUIDSupport
+++_NoCPUIDSupport:
+++ .ascii "FreeLoader: No CPUID instruction support detected! Exiting..."
+++ .byte 0x0d, 0x0a, 0
+++
+++/////////////////////////// Checkpoint messages ///////////////////////////////
+++.global _CheckPoint0
+++_CheckPoint0:
+++ .ascii "Starting FreeLoader..."
+++ .byte 0x0d, 0x0a, 0
+++
+++.global _CheckPoint1
+++_CheckPoint1:
+++ .ascii "FreeLoader[16-bit]: building page tables..."
+++ .byte 0x0d, 0x0a, 0
+++
+++.global _CheckPoint2
+++_CheckPoint2:
+++ .ascii "FreeLoader[16-bit]: checking CPU for x64 long mode..."
+++ .byte 0x0d, 0x0a, 0
+++
+++.global _CheckPoint3
+++_CheckPoint3:
+++ .ascii "FreeLoader: Switching to x64 long mode..."
+++ .byte 0x0d, 0x0a, 0
///////////////////////////////////////////////////////////////////////////////
add bx,dx
mov es,bx
mov bx,ax // Restore FAT entry offset
--- mov ax, [es:bx] // Get FAT entry
+++ mov ax, es:[bx] // Get FAT entry
ret
mov bx,0x7000
mov es,bx
mov bx,ax // Put FAT entry offset into BX
--- mov ax, [es:bx] // Get FAT entry
+++ mov ax, es:[bx] // Get FAT entry
pop cx // Get cluster number from stack
and cx,1
jz UseLow12Bits
{
// Try to infere boot type value
#ifdef __i386__
-- CHAR LastChar;
-- LastChar = SectionName[strlen(SectionName) - 1];
-- if (LastChar == '\\' ||
-- (strstr(SectionName, ")partition(") != NULL &&
-- strstr(SectionName, ")partition(0)") == NULL))
- {
- strcpy(SettingValue, "Partition");
- }
- else if (LastChar == ')' || LastChar == ':')
++ ULONG FileId;
++ if (ArcOpen((CHAR*)SectionName, OpenReadOnly, &FileId) == ESUCCESS)
{
- strcpy(SettingValue, "Partition");
- }
- else if (LastChar == ')' || LastChar == ':')
- {
-- strcpy(SettingValue, "Drive");
-- }
-- else if (TRUE)
-- {
-- strcpy(SettingValue, "BootSector");
++ ArcClose(FileId);
++ strcpy(BootType, "BootSector");
}
else
#endif
// to have different install methods, etc.
LoadReactOSSetup();
}
-- #ifdef __i386__
- else if (_stricmp(SettingValue, "ReactOSSetup2") == 0)
++ #if defined(__i386__) || defined(__x86_64__)
- else if (_stricmp(SettingValue, "ReactOSSetup2") == 0)
++ else if (_stricmp(BootType, "ReactOSSetup2") == 0)
{
- #ifdef __i386__
// WinLdr-style boot
LoadReactOSSetup2();
- #endif
}
#endif
#endif
#ifdef __i386__
-- else if (_stricmp(SettingValue, "WindowsNT40") == 0)
++ else if (_stricmp(BootType, "Windows") == 0)
+ {
- LoadAndBootWindows(SectionName, _WIN32_WINNT_NT4);
++ LoadAndBootWindows(SectionName, SettingValue, 0);
+ }
- else if (_stricmp(SettingValue, "Windows2003") == 0)
++ else if (_stricmp(BootType, "WindowsNT40") == 0)
{
- LoadAndBootWindows(SectionName, _WIN32_WINNT_NT4);
- LoadAndBootWindows(SectionName, _WIN32_WINNT_WS03);
++ LoadAndBootWindows(SectionName, SettingValue, _WIN32_WINNT_NT4);
}
- else if (_stricmp(SettingValue, "Windows2003") == 0)
- else if (_stricmp(SettingValue, "Linux") == 0)
++ else if (_stricmp(BootType, "Windows2003") == 0)
+ {
- LoadAndBootWindows(SectionName, _WIN32_WINNT_WS03);
++ LoadAndBootWindows(SectionName, SettingValue, _WIN32_WINNT_WS03);
+ }
- else if (_stricmp(SettingValue, "Linux") == 0)
++ else if (_stricmp(BootType, "Linux") == 0)
{
LoadAndBootLinux(SectionName, OperatingSystemDisplayNames[SelectedOperatingSystem]);
}
<file>wlregistry.c</file>
</directory>
</if>
+ <if property="ARCH" value="amd64">
+ <directory name="windows">
+ <file>conversion.c</file>
+ <file>peloader.c</file>
+ <file>winldr.c</file>
++ <file>wlmemory.c</file>
+ <file>wlregistry.c</file>
+ </directory>
+ </if>
<file>freeldr.c</file>
<file>debug.c</file>
<file>version.c</file>
#ifndef __AMD64_AMD64_H_
#define __AMD64_AMD64_H_
+++// This is needed because headers define wrong one for ReactOS
+++#undef KIP0PCRADDRESS
+++#define KIP0PCRADDRESS 0xFFFFF78000001000ULL /* FIXME!!! */
+++
#define STACK64ADDR 0x74000 /* The 64-bit stack top will be at 0x74000 */
/* Long mode selectors */
HARDWARE_PTE Pde[512];
} PAGE_DIRECTORY_AMD64, *PPAGE_DIRECTORY_AMD64;
---VOID
---FORCEINLINE
---__lgdt(void *gdt)
---{
--- asm volatile ("lgdt %0\n" : : "m"(*(short*)gdt));
---}
---
---PKGDTENTRY64
---FORCEINLINE
---KiGetGdtEntry(PVOID pGdt, USHORT Index)
---{
--- return (PKGDTENTRY64)((ULONG64)pGdt + (Index & ~RPL_MASK));
---}
---
---VOID
---FORCEINLINE
---KiInitGdtEntry(PKGDTENTRY64 Entry, ULONG64 Base, ULONG Limit, UCHAR Type, UCHAR Dpl)
---{
--- Entry->Bits.Type = Type;
--- Entry->Bits.Present = 1;
--- Entry->Bits.Dpl = Dpl;
--- Entry->BaseLow = (USHORT)(Base & 0xFFFF);
--- Entry->Bytes.BaseMiddle = (UCHAR)(Base >> 16);
--- Entry->Bytes.BaseHigh = (UCHAR)(Base >> 24);
--- Entry->BaseUpper = (ULONG)(Base >> 32);
--- Entry->LimitLow = (USHORT)(Limit & 0xFFFF);
--- Entry->Bits.LimitHigh = (ULONG)((Limit >> 16) & 0xf);
--- Entry->MustBeZero = 0;
---}
VOID FrLdrSetupGdtIdt();
#ifndef __I386_I386_H_
#define __I386_I386_H_
+++// This is needed because headers define wrong one for ReactOS
+++#undef KIP0PCRADDRESS
+++#define KIP0PCRADDRESS 0xffdff000
#endif /* __I386_I386_H_ */
#include <arch/i386/i386.h>
#include <arch/i386/machpc.h>
#include <arch/i386/machxbox.h>
++#include <arch/i386/miscboot.h>
#include <internal/i386/intrin_i.h>
---#include <internal/i386/ke.h>
#elif defined(_M_PPC)
#include <arch/powerpc/hardware.h>
#elif defined(_M_ARM)
#elif defined(_M_AMD64)
#include <arch/amd64/hardware.h>
#include <arch/amd64/machpc.h>
+++#include <internal/amd64/intrin_i.h>
#endif
/* misc files */
#include <keycodes.h>
#endif // DBG
// Update LoaderPagesSpanned count
--- if ((((ULONG_PTR)MemPointer + MemorySize) >> PAGE_SHIFT) > LoaderPagesSpanned)
--- LoaderPagesSpanned = (((ULONG_PTR)MemPointer + MemorySize) >> PAGE_SHIFT);
+++ if ((((ULONG_PTR)MemPointer + MemorySize + PAGE_SIZE - 1) >> PAGE_SHIFT) > LoaderPagesSpanned)
+++ LoaderPagesSpanned = (((ULONG_PTR)MemPointer + MemorySize + PAGE_SIZE - 1) >> PAGE_SHIFT);
// Now return the pointer
return MemPointer;
#endif // DBG
// Update LoaderPagesSpanned count
--- if ((((ULONG_PTR)MemPointer + MemorySize) >> PAGE_SHIFT) > LoaderPagesSpanned)
--- LoaderPagesSpanned = (((ULONG_PTR)MemPointer + MemorySize) >> PAGE_SHIFT);
+++ if ((((ULONG_PTR)MemPointer + MemorySize + PAGE_SIZE - 1) >> PAGE_SHIFT) > LoaderPagesSpanned)
+++ LoaderPagesSpanned = (((ULONG_PTR)MemPointer + MemorySize + PAGE_SIZE - 1) >> PAGE_SHIFT);
// Now return the pointer
return MemPointer;
--- /dev/null
+ /*
+ * PROJECT: EFI Windows Loader
+ * LICENSE: GPL - See COPYING in the top level directory
+ * FILE: freeldr/windows/i386/ntsetup.c
+ * PURPOSE: i386-specific setup for Windows boot
+ * PROGRAMMERS: Aleksey Bragin (aleksey@reactos.org)
+ */
+
+ /* INCLUDES ***************************************************************/
+
+ #include <freeldr.h>
+ #include <debug.h>
+
+ // this is needed for new IDT filling
+ #if 0
+ extern ULONG_PTR i386DivideByZero;
+ extern ULONG_PTR i386DebugException;
+ extern ULONG_PTR i386NMIException;
+ extern ULONG_PTR i386Breakpoint;
+ extern ULONG_PTR i386Overflow;
+ extern ULONG_PTR i386BoundException;
+ extern ULONG_PTR i386InvalidOpcode;
+ extern ULONG_PTR i386FPUNotAvailable;
+ extern ULONG_PTR i386DoubleFault;
+ extern ULONG_PTR i386CoprocessorSegment;
+ extern ULONG_PTR i386InvalidTSS;
+ extern ULONG_PTR i386SegmentNotPresent;
+ extern ULONG_PTR i386StackException;
+ extern ULONG_PTR i386GeneralProtectionFault;
+ extern ULONG_PTR i386PageFault; // exc 14
+ extern ULONG_PTR i386CoprocessorError; // exc 16
+ extern ULONG_PTR i386AlignmentCheck; // exc 17
+ #endif
+
+ /* FUNCTIONS **************************************************************/
+
+ // Last step before going virtual
+ void WinLdrSetupForNt(PLOADER_PARAMETER_BLOCK LoaderBlock,
+ PVOID *GdtIdt,
+ ULONG *PcrBasePage,
+ ULONG *TssBasePage)
+ {
+++ ULONG TssSize;
+++ ULONG TssPages;
+++ ULONG_PTR Pcr = 0;
+++ ULONG_PTR Tss = 0;
+++ ULONG BlockSize, NumPages;
+
+++ LoaderBlock->u.I386.CommonDataArea = (PVOID)DbgPrint; // HACK
+++ LoaderBlock->u.I386.MachineType = MACHINE_TYPE_ISA;
+++
+++ /* Allocate 2 pages for PCR */
+++ Pcr = (ULONG_PTR)MmAllocateMemoryWithType(2 * MM_PAGE_SIZE, LoaderStartupPcrPage);
+++ *PcrBasePage = Pcr >> MM_PAGE_SHIFT;
+++ RtlZeroMemory((PVOID)Pcr, 2 * MM_PAGE_SIZE);
+++
+++ if (Pcr == 0)
+++ {
+++ UiMessageBox("Can't allocate PCR\n");
+++ return;
+++ }
+++
+++ /* Allocate TSS */
+++ TssSize = (sizeof(KTSS) + MM_PAGE_SIZE) & ~(MM_PAGE_SIZE - 1);
+++ TssPages = TssSize / MM_PAGE_SIZE;
+++
+++ Tss = (ULONG_PTR)MmAllocateMemoryWithType(TssSize, LoaderMemoryData);
+++
+++ *TssBasePage = Tss >> MM_PAGE_SHIFT;
+++
+++ /* Allocate space for new GDT + IDT */
+++ BlockSize = NUM_GDT*sizeof(KGDTENTRY) + NUM_IDT*sizeof(KIDTENTRY);//FIXME: Use GDT/IDT limits here?
+++ NumPages = (BlockSize + MM_PAGE_SIZE - 1) >> MM_PAGE_SHIFT;
+++ *GdtIdt = (PKGDTENTRY)MmAllocateMemoryWithType(NumPages * MM_PAGE_SIZE, LoaderMemoryData);
+++
+++ if (*GdtIdt == NULL)
+++ {
+++ UiMessageBox("Can't allocate pages for GDT+IDT!\n");
+++ return;
+++ }
+++
+++ /* Zero newly prepared GDT+IDT */
+++ RtlZeroMemory(*GdtIdt, NumPages << MM_PAGE_SHIFT);
+ }
--- /dev/null
- * FILE: freeldr/winldr/wlmemory.c
+ /*
+ * PROJECT: EFI Windows Loader
+ * LICENSE: GPL - See COPYING in the top level directory
- * PROGRAMMERS: Aleksey Bragin (aleksey@reactos.org)
++ * FILE: freeldr/amd64/wlmemory.c
+ * PURPOSE: Memory related routines
- extern ULONG TotalNLSSize;
- extern ULONG LoaderPagesSpanned;
-
- // This is needed because headers define wrong one for ReactOS
- #undef KIP0PCRADDRESS
- #define KIP0PCRADDRESS 0xffdff000
-
- #define HYPER_SPACE_ENTRY 0x300
-
- PCHAR MemTypeDesc[] = {
- "ExceptionBlock ", // ?
- "SystemBlock ", // ?
- "Free ",
- "Bad ", // used
- "LoadedProgram ", // == Free
- "FirmwareTemporary ", // == Free
- "FirmwarePermanent ", // == Bad
- "OsloaderHeap ", // used
- "OsloaderStack ", // == Free
- "SystemCode ",
- "HalCode ",
- "BootDriver ", // not used
- "ConsoleInDriver ", // ?
- "ConsoleOutDriver ", // ?
- "StartupDpcStack ", // ?
- "StartupKernelStack", // ?
- "StartupPanicStack ", // ?
- "StartupPcrPage ", // ?
- "StartupPdrPage ", // ?
- "RegistryData ", // used
- "MemoryData ", // not used
- "NlsData ", // used
- "SpecialMemory ", // == Bad
- "BBTMemory " // == Bad
- };
++ * PROGRAMMERS: Timo Kreuzer (timo.kreuzer@reactos.org)
+ */
+
+ /* INCLUDES ***************************************************************/
+
+ #include <freeldr.h>
+
+ #include <ndk/asm.h>
+ #include <debug.h>
+
- VOID
- WinLdrpDumpMemoryDescriptors(PLOADER_PARAMETER_BLOCK LoaderBlock);
-// This is needed because headers define wrong one for ReactOS
-#undef KIP0PCRADDRESS
-#define KIP0PCRADDRESS 0xffdff000
-
-#define HYPER_SPACE_ENTRY 0x300
-
-// This is needed only for SetProcessorContext routine
-#pragma pack(2)
- typedef struct
- {
- USHORT Limit;
- ULONG Base;
- } GDTIDT;
-#pragma pack(4)
++ //extern ULONG LoaderPagesSpanned;
+
- VOID
- MempAddMemoryBlock(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
- ULONG BasePage,
- ULONG PageCount,
- ULONG Type);
- VOID
- WinLdrInsertDescriptor(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
- IN PMEMORY_ALLOCATION_DESCRIPTOR NewDescriptor);
-//PHARDWARE_PTE PDE;
+++#define HYPER_SPACE_ENTRY 0x1EE
+
++ /* GLOBALS ***************************************************************/
+
- VOID
- WinLdrRemoveDescriptor(IN PMEMORY_ALLOCATION_DESCRIPTOR Descriptor);
-PPAGE_DIRECTORY_AMD64 pPML4;
+++PHARDWARE_PTE PxeBase;
++ //PHARDWARE_PTE HalPageTable;
+
- VOID
- WinLdrSetProcessorContext(PVOID GdtIdt, IN ULONG Pcr, IN ULONG Tss);
+
- // This is needed only for SetProcessorContext routine
- #pragma pack(2)
- typedef struct
- {
- USHORT Limit;
- ULONG Base;
- } GDTIDT;
- #pragma pack(4)
++ /* FUNCTIONS **************************************************************/
+
- ULONG KernelPages;
- PVOID UserSharedData;
-
++ BOOLEAN
++ MempAllocatePageTables()
++ {
- /* GLOBALS ***************************************************************/
++ DPRINTM(DPRINT_WINDOWS,">>> MempAllocatePageTables\n");
+
- pPML4 = MmAllocateMemoryWithType(PAGE_SIZE, LoaderMemoryData);
- if (!pPML4)
++ /* Allocate a page for the PML4 */
- PHARDWARE_PTE PDE;
- PHARDWARE_PTE HalPageTable;
+++ PxeBase = MmAllocateMemoryWithType(PAGE_SIZE, LoaderMemoryData);
+++ if (!PxeBase)
++ {
++ DPRINTM(DPRINT_WINDOWS,"failed to allocate PML4\n");
++ return FALSE;
++ }
+
- PUCHAR PhysicalPageTablesBuffer;
- PUCHAR KernelPageTablesBuffer;
- ULONG PhysicalPageTables;
- ULONG KernelPageTables;
++ // FIXME: Physical PTEs = FirmwareTemporary ?
+
- RtlZeroMemory(pPML4, PAGE_SIZE);
++ /* Zero the PML4 */
- MEMORY_ALLOCATION_DESCRIPTOR *Mad;
- ULONG MadCount = 0;
+++ RtlZeroMemory(PxeBase, PAGE_SIZE);
+
- pPML4->Pde[VAtoPXI(PXE_BASE)].Valid = 1;
- pPML4->Pde[VAtoPXI(PXE_BASE)].Write = 1;
- pPML4->Pde[VAtoPXI(PXE_BASE)].PageFrameNumber = PtrToPfn(pPML4);
++ /* The page tables are located at 0xfffff68000000000
++ * We create a recursive self mapping through all 4 levels at
++ * virtual address 0xfffff6fb7dbedf68 */
- /* FUNCTIONS **************************************************************/
+++ PxeBase[VAtoPXI(PXE_BASE)].Valid = 1;
+++ PxeBase[VAtoPXI(PXE_BASE)].Write = 1;
+++ PxeBase[VAtoPXI(PXE_BASE)].PageFrameNumber = PtrToPfn(PxeBase);
+
++ // FIXME: map PDE's for hals memory mapping
+
-PPAGE_DIRECTORY_AMD64
-MempGetOrCreatePageDir(PPAGE_DIRECTORY_AMD64 pDir, ULONG Index)
++ DPRINTM(DPRINT_WINDOWS,">>> leave MempAllocatePageTables\n");
++
++ return TRUE;
++ }
++
- PPAGE_DIRECTORY_AMD64 pSubDir;
+++PHARDWARE_PTE
+++MempGetOrCreatePageDir(PHARDWARE_PTE PdeBase, ULONG Index)
++ {
- if (!pDir)
+++ PHARDWARE_PTE SubDir;
++
- if (!pDir->Pde[Index].Valid)
+++ if (!PdeBase)
++ return NULL;
++
- pSubDir = MmAllocateMemoryWithType(PAGE_SIZE, LoaderSpecialMemory);
- if (!pSubDir)
+++ if (!PdeBase[Index].Valid)
++ {
- RtlZeroMemory(pSubDir, PAGE_SIZE);
- pDir->Pde[Index].PageFrameNumber = PtrToPfn(pSubDir);
- pDir->Pde[Index].Valid = 1;
- pDir->Pde[Index].Write = 1;
+++ SubDir = MmAllocateMemoryWithType(PAGE_SIZE, LoaderMemoryData);
+++ if (!SubDir)
++ return NULL;
- pSubDir = (PPAGE_DIRECTORY_AMD64)((ULONGLONG)(pDir->Pde[Index].PageFrameNumber) * PAGE_SIZE);
+++ RtlZeroMemory(SubDir, PAGE_SIZE);
+++ PdeBase[Index].PageFrameNumber = PtrToPfn(SubDir);
+++ PdeBase[Index].Valid = 1;
+++ PdeBase[Index].Write = 1;
++ }
++ else
++ {
- return pSubDir;
+++ SubDir = (PVOID)((ULONG64)(PdeBase[Index].PageFrameNumber) * PAGE_SIZE);
++ }
- MempAllocatePageTables()
-MempMapSinglePage(ULONGLONG VirtualAddress, ULONGLONG PhysicalAddress)
+++ return SubDir;
++ }
+
+ BOOLEAN
- PPAGE_DIRECTORY_AMD64 pDir3, pDir2, pDir1;
+++MempMapSinglePage(ULONG64 VirtualAddress, ULONG64 PhysicalAddress)
+ {
- pDir3 = MempGetOrCreatePageDir(pPML4, VAtoPXI(VirtualAddress));
- pDir2 = MempGetOrCreatePageDir(pDir3, VAtoPPI(VirtualAddress));
- pDir1 = MempGetOrCreatePageDir(pDir2, VAtoPDI(VirtualAddress));
+++ PHARDWARE_PTE PpeBase, PdeBase, PteBase;
++ ULONG Index;
++
- if (!pDir1)
+++ PpeBase = MempGetOrCreatePageDir(PxeBase, VAtoPXI(VirtualAddress));
+++ PdeBase = MempGetOrCreatePageDir(PpeBase, VAtoPPI(VirtualAddress));
+++ PteBase = MempGetOrCreatePageDir(PdeBase, VAtoPDI(VirtualAddress));
++
- if (pDir1->Pde[Index].Valid)
+++ if (!PteBase)
+++ {
+++ DPRINTM(DPRINT_WINDOWS,"!!!No Dir %p, %p, %p, %p\n", PxeBase, PpeBase, PdeBase, PteBase);
++ return FALSE;
+++ }
++
++ Index = VAtoPTI(VirtualAddress);
- pDir1->Pde[Index].Valid = 1;
- pDir1->Pde[Index].Write = 1;
- pDir1->Pde[Index].PageFrameNumber = PhysicalAddress / PAGE_SIZE;
+++ if (PteBase[Index].Valid)
++ {
+++ DPRINTM(DPRINT_WINDOWS,"!!!Already mapped %ld\n", Index);
++ return FALSE;
++ }
++
- VOID
- MempAllocatePTE(ULONG Entry, PHARDWARE_PTE *PhysicalPT, PHARDWARE_PTE *KernelPT)
+++ PteBase[Index].Valid = 1;
+++ PteBase[Index].Write = 1;
+++ PteBase[Index].PageFrameNumber = PhysicalAddress / PAGE_SIZE;
+
+ return TRUE;
+ }
+
-MempMapRangeOfPages(ULONGLONG VirtualAddress, ULONGLONG PhysicalAddress, ULONG cPages)
+++BOOLEAN
+++MempIsPageMapped(PVOID VirtualAddress)
+ +{
+++ PHARDWARE_PTE PpeBase, PdeBase, PteBase;
+++ ULONG Index;
+++
+++ Index = VAtoPXI(VirtualAddress);
+++ if (!PxeBase[Index].Valid)
+++ return FALSE;
+++
+++ PpeBase = (PVOID)((ULONG64)(PxeBase[Index].PageFrameNumber) * PAGE_SIZE);
+++ Index = VAtoPPI(VirtualAddress);
+++ if (!PpeBase[Index].Valid)
+++ return FALSE;
+++
+++ PdeBase = (PVOID)((ULONG64)(PpeBase[Index].PageFrameNumber) * PAGE_SIZE);
+++ Index = VAtoPDI(VirtualAddress);
+++ if (!PdeBase[Index].Valid)
+++ return FALSE;
+++
+++ PteBase = (PVOID)((ULONG64)(PdeBase[Index].PageFrameNumber) * PAGE_SIZE);
+++ Index = VAtoPTI(VirtualAddress);
+++ if (!PteBase[Index].Valid)
+++ return FALSE;
+++
+++ return TRUE;
+++}
+ +
++ ULONG
- if (!FrLdrMapSinglePage(VirtualAddress, PhysicalAddress))
+++MempMapRangeOfPages(ULONG64 VirtualAddress, ULONG64 PhysicalAddress, ULONG cPages)
++ {
++ ULONG i;
++
++ for (i = 0; i < cPages; i++)
++ {
- DPRINTM(DPRINT_WINDOWS,">>> MempSetupPaging(0x%lx, %ld)\n", StartPage, NumberOfPages);
+++ if (!MempMapSinglePage(VirtualAddress, PhysicalAddress))
++ {
++ return i;
++ }
++ VirtualAddress += PAGE_SIZE;
++ PhysicalAddress += PAGE_SIZE;
++ }
++ return i;
+ }
+
+ BOOLEAN
+ MempSetupPaging(IN ULONG StartPage,
+ IN ULONG NumberOfPages)
+ {
- DPRINTM(DPRINT_WINDOWS,"Failed to map pages\n");
+++ DPRINTM(DPRINT_WINDOWS,">>> MempSetupPaging(0x%lx, %ld, %p)\n",
+++ StartPage, NumberOfPages, StartPage * PAGE_SIZE + KSEG0_BASE);
++
+++ /* Identity mapping */
++ if (MempMapRangeOfPages(StartPage * PAGE_SIZE,
++ StartPage * PAGE_SIZE,
++ NumberOfPages) != NumberOfPages)
++ {
- MempDisablePages()
+++ DPRINTM(DPRINT_WINDOWS,"Failed to map pages 1\n");
+++ return FALSE;
+++ }
+++
+++ /* Kernel mapping */
+++ if (MempMapRangeOfPages(StartPage * PAGE_SIZE + KSEG0_BASE,
+++ StartPage * PAGE_SIZE,
+++ NumberOfPages) != NumberOfPages)
+++ {
+++ DPRINTM(DPRINT_WINDOWS,"Failed to map pages 2\n");
++ return FALSE;
++ }
+
+ return TRUE;
+ }
+
+ VOID
-
++ MempUnmapPage(ULONG Page)
+ {
- MempAddMemoryBlock(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
- ULONG BasePage,
- ULONG PageCount,
- ULONG Type)
++ // DPRINTM(DPRINT_WINDOWS,">>> MempUnmapPage\n");
+ }
+
+ VOID
- #ifdef _M_IX86
- VOID
- WinLdrpMapApic()
++ WinLdrpMapApic()
+ {
++ BOOLEAN LocalAPIC;
++ LARGE_INTEGER MsrValue;
++ ULONG CpuInfo[4];
++ ULONG64 APICAddress;
+
++ DPRINTM(DPRINT_WINDOWS,">>> WinLdrpMapApic\n");
++
++ /* Check if we have a local APIC */
++ __cpuid((int*)CpuInfo, 1);
++ LocalAPIC = (((CpuInfo[3] >> 9) & 1) != 0);
++
++ /* If there is no APIC, just return */
++ if (!LocalAPIC)
++ {
++ DPRINTM(DPRINT_WINDOWS,"No APIC found.\n");
++ return;
++ }
++
++ /* Read the APIC Address */
++ MsrValue.QuadPart = __readmsr(0x1B);
++ APICAddress = (MsrValue.LowPart & 0xFFFFF000);
++
++ DPRINTM(DPRINT_WINDOWS, "Local APIC detected at address 0x%x\n",
++ APICAddress);
++
++ /* Map it */
++ MempMapSinglePage(APIC_BASE, APICAddress);
+ }
+
-
++ BOOLEAN
++ WinLdrMapSpecialPages(ULONG PcrBasePage)
+ {
- if (!MempMapSinglePage(PcrBasePage * PAGE_SIZE, KIP0PCRADDRESS))
++ /* Map the PCR page */
- if (!MempMapSinglePage((PcrBasePage+1) * PAGE_SIZE, KI_USER_SHARED_DATA))
+++ if (!MempMapSinglePage(KIP0PCRADDRESS, PcrBasePage * PAGE_SIZE))
++ {
++ DPRINTM(DPRINT_WINDOWS, "Could not map PCR @ %lx\n", PcrBasePage);
++ return FALSE;
++ }
++
++ /* Map KI_USER_SHARED_DATA */
- #else
+++ if (!MempMapSinglePage(KI_USER_SHARED_DATA, (PcrBasePage+1) * PAGE_SIZE))
++ {
++ DPRINTM(DPRINT_WINDOWS, "Could not map KI_USER_SHARED_DATA\n");
++ return FALSE;
++ }
++
++ /* Map the APIC page */
++ WinLdrpMapApic();
++
++ return TRUE;
+ }
- WinLdrpMapApic()
++
+ VOID
- /* Implement it for another arch */
++ WinLdrSetupGdt(PVOID GdtBase, ULONG64 TssBase)
+ {
- #endif
++ PKGDTENTRY64 Entry;
++ KDESCRIPTOR GdtDesc;
++
++ /* Setup KGDT_64_R0_CODE */
++ Entry = KiGetGdtEntry(GdtBase, KGDT_64_R0_CODE);
++ *(PULONG64)Entry = 0x00209b0000000000ULL;
++
++ /* Setup KGDT_64_R0_SS */
++ Entry = KiGetGdtEntry(GdtBase, KGDT_64_R0_SS);
++ *(PULONG64)Entry = 0x00cf93000000ffffULL;
++
++ /* Setup KGDT_64_DATA */
++ Entry = KiGetGdtEntry(GdtBase, KGDT_64_DATA);
++ *(PULONG64)Entry = 0x00cff3000000ffffULL;
++
++ /* Setup KGDT_64_R3_CODE */
++ Entry = KiGetGdtEntry(GdtBase, KGDT_64_R3_CODE);
++ *(PULONG64)Entry = 0x0020fb0000000000ULL;
++
++ /* Setup KGDT_32_R3_TEB */
++ Entry = KiGetGdtEntry(GdtBase, KGDT_32_R3_TEB);
++ *(PULONG64)Entry = 0xff40f3fd50003c00ULL;
++
++ /* Setup TSS entry */
++ Entry = KiGetGdtEntry(GdtBase, KGDT_TSS);
++ KiInitGdtEntry(Entry, TssBase, sizeof(KTSS), I386_TSS, 0);
++
++ /* Setup GDT descriptor */
++ GdtDesc.Base = GdtBase;
++ GdtDesc.Limit = NUM_GDT * sizeof(KGDTENTRY) - 1;
++
++ /* Set the new Gdt */
++ __lgdt(&GdtDesc.Limit);
++ DbgPrint("Gdtr.Base = %p, num = %ld\n", GdtDesc.Base, NUM_GDT);
++
+ }
- BOOLEAN
- WinLdrTurnOnPaging(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
- ULONG PcrBasePage,
- ULONG TssBasePage,
- PVOID GdtIdt)
+
- return 1;
++ VOID
++ WinLdrSetupIdt(PVOID IdtBase)
+ {
- // Two special things this func does: it sorts descriptors,
- // and it merges free ones
++ KDESCRIPTOR IdtDesc, OldIdt;
++
++ /* Get old IDT */
++ __sidt(&OldIdt);
++
++ /* Copy the old IDT */
++ RtlCopyMemory(IdtBase, (PVOID)OldIdt.Base, OldIdt.Limit + 1);
++
++ /* Setup the new IDT descriptor */
++ IdtDesc.Base = IdtBase;
++ IdtDesc.Limit = NUM_IDT * sizeof(KIDTENTRY) - 1;
++
++ /* Set the new IDT */
++ __lidt(&IdtDesc.Limit);
++ DbgPrint("Idtr.Base = %p\n", IdtDesc.Base);
++
+ }
+
- WinLdrInsertDescriptor(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
- IN PMEMORY_ALLOCATION_DESCRIPTOR NewDescriptor)
+ VOID
- __writecr3((ULONGLONG)pPML4);
++ WinLdrSetProcessorContext(PVOID GdtIdt, IN ULONG64 Pcr, IN ULONG64 Tss)
+ {
+++ DPRINTM(DPRINT_WINDOWS, "WinLdrSetProcessorContext %p\n", Pcr);
+++
++ /* Disable Interrupts */
++ _disable();
+
++ /* Re-initalize EFLAGS */
++ __writeeflags(0);
++
++ /* Set the new PML4 */
- // Enable paging by modifying CR0
- __writecr0(__readcr0() | CR0_PG);
+++ __writecr3((ULONG64)PxeBase);
++
- // 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 kernel mode address of gdt / idt */
+++ GdtIdt = (PVOID)((ULONG64)GdtIdt + KSEG0_BASE);
++
- RtlZeroMemory(GdtIdt, PAGE_SIZE);
+++ /* Create gdt entries and load gdtr */
+++ WinLdrSetupGdt(GdtIdt, Tss);
++
- WinLdrSetupGdt(GdtIdt, Tss);
+++ /* Copy old Idt and set idtr */
+++ WinLdrSetupIdt((PVOID)((ULONG64)GdtIdt + 2048)); // HACK!
++
- WinLdrSetupIdt(GdtIdt);
+++ /* LDT is unused */
+++// __lldt(0);
+++
+++ /* Load selectors for DS/ES/FS/GS/SS */
+++ Ke386SetDs(KGDT_64_DATA | RPL_MASK); // 0x2b
+++ Ke386SetEs(KGDT_64_DATA | RPL_MASK); // 0x2b
+++ Ke386SetFs(KGDT_32_R3_TEB | RPL_MASK); // 0x53
+++ Ke386SetGs(KGDT_64_DATA | RPL_MASK); // 0x2b
+++ Ke386SetSs(KGDT_64_R0_SS); // 0x18
++
- WinLdrSetProcessorContext(PVOID GdtIdt, IN ULONG Pcr, IN ULONG Tss)
+++ /* Load TSR */
+++ __ltr(KGDT_TSS);
++
+++ DPRINTM(DPRINT_WINDOWS, "leave WinLdrSetProcessorContext\n");
+ }
+
+ VOID
-
++ MempDump()
+ {
+ }
+
--- /dev/null
- * FILE: freeldr/winldr/wlmemory.c
+ /*
+ * PROJECT: EFI Windows Loader
+ * LICENSE: GPL - See COPYING in the top level directory
- PCHAR MemTypeDesc[] = {
- "ExceptionBlock ", // ?
- "SystemBlock ", // ?
- "Free ",
- "Bad ", // used
- "LoadedProgram ", // == Free
- "FirmwareTemporary ", // == Free
- "FirmwarePermanent ", // == Bad
- "OsloaderHeap ", // used
- "OsloaderStack ", // == Free
- "SystemCode ",
- "HalCode ",
- "BootDriver ", // not used
- "ConsoleInDriver ", // ?
- "ConsoleOutDriver ", // ?
- "StartupDpcStack ", // ?
- "StartupKernelStack", // ?
- "StartupPanicStack ", // ?
- "StartupPcrPage ", // ?
- "StartupPdrPage ", // ?
- "RegistryData ", // used
- "MemoryData ", // not used
- "NlsData ", // used
- "SpecialMemory ", // == Bad
- "BBTMemory " // == Bad
- };
-
- VOID
- WinLdrpDumpMemoryDescriptors(PLOADER_PARAMETER_BLOCK LoaderBlock);
-
-
- VOID
- MempAddMemoryBlock(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
- ULONG BasePage,
- ULONG PageCount,
- ULONG Type);
- VOID
- WinLdrInsertDescriptor(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
- IN PMEMORY_ALLOCATION_DESCRIPTOR NewDescriptor);
-
- VOID
- WinLdrRemoveDescriptor(IN PMEMORY_ALLOCATION_DESCRIPTOR Descriptor);
-
- VOID
- WinLdrSetProcessorContext(PVOID GdtIdt, IN ULONG Pcr, IN ULONG Tss);
-
++ * FILE: freeldr/winldr/i386/wlmemory.c
+ * PURPOSE: Memory related routines
+ * PROGRAMMERS: Aleksey Bragin (aleksey@reactos.org)
+ */
+
+ /* INCLUDES ***************************************************************/
+
+ #include <freeldr.h>
+
+ #include <ndk/asm.h>
+ #include <debug.h>
+
+ extern ULONG TotalNLSSize;
+ extern ULONG LoaderPagesSpanned;
+
+ // This is needed because headers define wrong one for ReactOS
+ #undef KIP0PCRADDRESS
+ #define KIP0PCRADDRESS 0xffdff000
+
+ #define HYPER_SPACE_ENTRY 0x300
+
- MEMORY_ALLOCATION_DESCRIPTOR *Mad;
- ULONG MadCount = 0;
-
-
+ // This is needed only for SetProcessorContext routine
+ #pragma pack(2)
+ typedef struct
+ {
+ USHORT Limit;
+ ULONG Base;
+ } GDTIDT;
+ #pragma pack(4)
+
+ /* GLOBALS ***************************************************************/
+
+ PHARDWARE_PTE PDE;
+ PHARDWARE_PTE HalPageTable;
+
+ PUCHAR PhysicalPageTablesBuffer;
+ PUCHAR KernelPageTablesBuffer;
+ ULONG PhysicalPageTables;
+ ULONG KernelPageTables;
+
- MempDisablePages()
- {
- ULONG i;
-
- //
- // We need to delete kernel mapping from memory areas which are
- // marked as Special or Permanent memory (thus non-accessible)
- //
-
- for (i=0; i<MadCount; i++)
- {
- ULONG StartPage, EndPage, Page;
-
- StartPage = Mad[i].BasePage;
- EndPage = Mad[i].BasePage + Mad[i].PageCount;
-
- if (Mad[i].MemoryType == LoaderFirmwarePermanent ||
- Mad[i].MemoryType == LoaderSpecialMemory ||
- Mad[i].MemoryType == LoaderFree ||
- (Mad[i].MemoryType == LoaderFirmwareTemporary && EndPage <= LoaderPagesSpanned) ||
- Mad[i].MemoryType == LoaderOsloaderStack ||
- Mad[i].MemoryType == LoaderLoadedProgram)
- {
- //
- // But, the first megabyte of memory always stays!
- // And, to tell the truth, we don't care about what's higher
- // than LoaderPagesSpanned
- if (Mad[i].MemoryType == LoaderFirmwarePermanent ||
- Mad[i].MemoryType == LoaderSpecialMemory)
- {
- if (StartPage < 0x100)
- StartPage = 0x100;
-
- if (EndPage > LoaderPagesSpanned)
- EndPage = LoaderPagesSpanned;
- }
-
- for (Page = StartPage; Page < EndPage; Page++)
- {
- PHARDWARE_PTE KernelPT;
- ULONG Entry = (Page >> 10) + (KSEG0_BASE >> 22);
-
- if (PDE[Entry].Valid)
- {
- KernelPT = (PHARDWARE_PTE)(PDE[Entry].PageFrameNumber << MM_PAGE_SHIFT);
-
- if (KernelPT)
- {
- KernelPT[Page & 0x3ff].PageFrameNumber = 0;
- KernelPT[Page & 0x3ff].Valid = 0;
- KernelPT[Page & 0x3ff].Write = 0;
- }
- }
- }
- }
- }
- }
-
- VOID
- MempAddMemoryBlock(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
- ULONG BasePage,
- ULONG PageCount,
- ULONG Type)
+ /* FUNCTIONS **************************************************************/
+
+ BOOLEAN
+ MempAllocatePageTables()
+ {
+ ULONG NumPageTables, TotalSize;
+ PUCHAR Buffer;
+ // It's better to allocate PDE + PTEs contigiuos
+
+ // Max number of entries = MaxPageNum >> 10
+ // FIXME: This is a number to describe ALL physical memory
+ // and windows doesn't expect ALL memory mapped...
+ NumPageTables = (GetSystemMemorySize() >> MM_PAGE_SHIFT) >> 10;
+
+ DPRINTM(DPRINT_WINDOWS, "NumPageTables = %d\n", NumPageTables);
+
+ // Allocate memory block for all these things:
+ // PDE, HAL mapping page table, physical mapping, kernel mapping
+ TotalSize = (1+1+NumPageTables*2)*MM_PAGE_SIZE;
+
+ // PDE+HAL+KernelPTEs == MemoryData
+ Buffer = MmAllocateMemoryWithType(TotalSize, LoaderMemoryData);
+
+ // Physical PTEs = FirmwareTemporary
+ PhysicalPageTablesBuffer = (PUCHAR)Buffer + TotalSize - NumPageTables*MM_PAGE_SIZE;
+ MmSetMemoryType(PhysicalPageTablesBuffer,
+ NumPageTables*MM_PAGE_SIZE,
+ LoaderFirmwareTemporary);
+
+ // This check is now redundant
+ if (Buffer + (TotalSize - NumPageTables*MM_PAGE_SIZE) !=
+ PhysicalPageTablesBuffer)
+ {
+ DPRINTM(DPRINT_WINDOWS, "There was a problem allocating two adjacent blocks of memory!");
+ }
+
+ if (Buffer == NULL || PhysicalPageTablesBuffer == NULL)
+ {
+ UiMessageBox("Impossible to allocate memory block for page tables!");
+ return FALSE;
+ }
+
+ // Zero all this memory block
+ RtlZeroMemory(Buffer, TotalSize);
+
+ // Set up pointers correctly now
+ PDE = (PHARDWARE_PTE)Buffer;
+
+ // Map the page directory at 0xC0000000 (maps itself)
+ PDE[HYPER_SPACE_ENTRY].PageFrameNumber = (ULONG)PDE >> MM_PAGE_SHIFT;
+ PDE[HYPER_SPACE_ENTRY].Valid = 1;
+ PDE[HYPER_SPACE_ENTRY].Write = 1;
+
+ // The last PDE slot is allocated for HAL's memory mapping (Virtual Addresses 0xFFC00000 - 0xFFFFFFFF)
+ HalPageTable = (PHARDWARE_PTE)&Buffer[MM_PAGE_SIZE*1];
+
+ // Map it
+ PDE[1023].PageFrameNumber = (ULONG)HalPageTable >> MM_PAGE_SHIFT;
+ PDE[1023].Valid = 1;
+ PDE[1023].Write = 1;
+
+ // Store pointer to the table for easier access
+ KernelPageTablesBuffer = &Buffer[MM_PAGE_SIZE*2];
+
+ // Zero counters of page tables used
+ PhysicalPageTables = 0;
+ KernelPageTables = 0;
+
+ return TRUE;
+ }
+
+ VOID
+ MempAllocatePTE(ULONG Entry, PHARDWARE_PTE *PhysicalPT, PHARDWARE_PTE *KernelPT)
+ {
+ //Print(L"Creating PDE Entry %X\n", Entry);
+
+ // Identity mapping
+ *PhysicalPT = (PHARDWARE_PTE)&PhysicalPageTablesBuffer[PhysicalPageTables*MM_PAGE_SIZE];
+ PhysicalPageTables++;
+
+ PDE[Entry].PageFrameNumber = (ULONG)*PhysicalPT >> MM_PAGE_SHIFT;
+ PDE[Entry].Valid = 1;
+ PDE[Entry].Write = 1;
+
+ if (Entry+(KSEG0_BASE >> 22) > 1023)
+ {
+ DPRINTM(DPRINT_WINDOWS, "WARNING! Entry: %X > 1023\n", Entry+(KSEG0_BASE >> 22));
+ }
+
+ // Kernel-mode mapping
+ *KernelPT = (PHARDWARE_PTE)&KernelPageTablesBuffer[KernelPageTables*MM_PAGE_SIZE];
+ KernelPageTables++;
+
+ PDE[Entry+(KSEG0_BASE >> 22)].PageFrameNumber = ((ULONG)*KernelPT >> MM_PAGE_SHIFT);
+ PDE[Entry+(KSEG0_BASE >> 22)].Valid = 1;
+ PDE[Entry+(KSEG0_BASE >> 22)].Write = 1;
+ }
+
+ BOOLEAN
+ MempSetupPaging(IN ULONG StartPage,
+ IN ULONG NumberOfPages)
+ {
+ PHARDWARE_PTE PhysicalPT;
+ PHARDWARE_PTE KernelPT;
+ ULONG Entry, Page;
+
+ //Print(L"MempSetupPaging: SP 0x%X, Number: 0x%X\n", StartPage, NumberOfPages);
+
+ // HACK
+ if (StartPage+NumberOfPages >= 0x80000)
+ {
+ //
+ // We can't map this as it requires more than 1 PDE
+ // and in fact it's not possible at all ;)
+ //
+ //Print(L"skipping...\n");
+ return TRUE;
+ }
+
+ //
+ // Now actually set up the page tables for identity mapping
+ //
+ for (Page=StartPage; Page < StartPage+NumberOfPages; Page++)
+ {
+ Entry = Page >> 10;
+
+ if (((PULONG)PDE)[Entry] == 0)
+ {
+ MempAllocatePTE(Entry, &PhysicalPT, &KernelPT);
+ }
+ else
+ {
+ PhysicalPT = (PHARDWARE_PTE)(PDE[Entry].PageFrameNumber << MM_PAGE_SHIFT);
+ KernelPT = (PHARDWARE_PTE)(PDE[Entry+(KSEG0_BASE >> 22)].PageFrameNumber << MM_PAGE_SHIFT);
+ }
+
+ if (Page == 0)
+ {
+ PhysicalPT[Page & 0x3ff].PageFrameNumber = Page;
+ PhysicalPT[Page & 0x3ff].Valid = 0;
+ PhysicalPT[Page & 0x3ff].Write = 0;
+
+ KernelPT[Page & 0x3ff].PageFrameNumber = Page;
+ KernelPT[Page & 0x3ff].Valid = 0;
+ KernelPT[Page & 0x3ff].Write = 0;
+ }
+ else
+ {
+ PhysicalPT[Page & 0x3ff].PageFrameNumber = Page;
+ PhysicalPT[Page & 0x3ff].Valid = 1;
+ PhysicalPT[Page & 0x3ff].Write = 1;
+
+ KernelPT[Page & 0x3ff].PageFrameNumber = Page;
+ KernelPT[Page & 0x3ff].Valid = 1;
+ KernelPT[Page & 0x3ff].Write = 1;
+ }
+ }
+
+ return TRUE;
+ }
+
+ VOID
- BOOLEAN Status;
-
- //
- // Check for some weird stuff at the top
- //
- if (BasePage + PageCount > 0xF0000)
- {
- //
- // Just skip this, without even adding to MAD list
- //
- return;
- }
-
- //
- // Set Base page, page count and type
- //
- Mad[MadCount].BasePage = BasePage;
- Mad[MadCount].PageCount = PageCount;
- Mad[MadCount].MemoryType = Type;
-
- //
- // Check if it's more than the allowed for OS loader
- // if yes - don't map the pages, just add as FirmwareTemporary
- //
- if (BasePage + PageCount > LoaderPagesSpanned)
- {
- if (Mad[MadCount].MemoryType != LoaderSpecialMemory &&
- Mad[MadCount].MemoryType != LoaderFirmwarePermanent &&
- Mad[MadCount].MemoryType != LoaderFree)
- {
- DPRINTM(DPRINT_WINDOWS, "Setting page %x %x to Temporary from %d\n",
- BasePage, PageCount, Mad[MadCount].MemoryType);
- Mad[MadCount].MemoryType = LoaderFirmwareTemporary;
- }
-
- WinLdrInsertDescriptor(LoaderBlock, &Mad[MadCount]);
- MadCount++;
-
- return;
- }
-
- //
- // Add descriptor
- //
- WinLdrInsertDescriptor(LoaderBlock, &Mad[MadCount]);
- MadCount++;
-
- //
- // Map it (don't map low 1Mb because it was already contigiously
- // mapped in WinLdrTurnOnPaging)
- //
- if (BasePage >= 0x100)
- {
- Status = MempSetupPaging(BasePage, PageCount);
- if (!Status)
- {
- DPRINTM(DPRINT_WINDOWS, "Error during MempSetupPaging\n");
- return;
- }
- }
++ MempUnmapPage(ULONG Page)
+ {
- #ifdef _M_IX86
++ PHARDWARE_PTE KernelPT;
++ ULONG Entry = (Page >> 10) + (KSEG0_BASE >> 22);
++
++ if (PDE[Entry].Valid)
++ {
++ KernelPT = (PHARDWARE_PTE)(PDE[Entry].PageFrameNumber << MM_PAGE_SHIFT);
++
++ if (KernelPT)
++ {
++ KernelPT[Page & 0x3ff].PageFrameNumber = 0;
++ KernelPT[Page & 0x3ff].Valid = 0;
++ KernelPT[Page & 0x3ff].Write = 0;
++ }
++ }
+ }
+
- #else
- VOID
- WinLdrpMapApic()
- {
- /* Implement it for another arch */
- }
- #endif
+ VOID
+ WinLdrpMapApic()
+ {
+ BOOLEAN LocalAPIC;
+ LARGE_INTEGER MsrValue;
+ ULONG APICAddress, CpuInfo[4];
+
+ /* Check if we have a local APIC */
+ __cpuid((int*)CpuInfo, 1);
+ LocalAPIC = (((CpuInfo[3] >> 9) & 1) != 0);
+
+ /* If there is no APIC, just return */
+ if (!LocalAPIC)
+ return;
+
+ /* Read the APIC Address */
+ MsrValue.QuadPart = __readmsr(0x1B);
+ APICAddress = (MsrValue.LowPart & 0xFFFFF000);
+
+ DPRINTM(DPRINT_WINDOWS, "Local APIC detected at address 0x%x\n",
+ APICAddress);
+
+ /* Map it */
+ HalPageTable[(APIC_BASE - 0xFFC00000) >> MM_PAGE_SHIFT].PageFrameNumber
+ = APICAddress >> MM_PAGE_SHIFT;
+ HalPageTable[(APIC_BASE - 0xFFC00000) >> MM_PAGE_SHIFT].Valid = 1;
+ HalPageTable[(APIC_BASE - 0xFFC00000) >> MM_PAGE_SHIFT].Write = 1;
+ HalPageTable[(APIC_BASE - 0xFFC00000) >> MM_PAGE_SHIFT].WriteThrough = 1;
+ HalPageTable[(APIC_BASE - 0xFFC00000) >> MM_PAGE_SHIFT].CacheDisable = 1;
+ }
- WinLdrTurnOnPaging(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
- ULONG PcrBasePage,
- ULONG TssBasePage,
- PVOID GdtIdt)
+
+ BOOLEAN
- ULONG i, PagesCount, MemoryMapSizeInPages;
- ULONG LastPageIndex, LastPageType, MemoryMapStartPage;
- PPAGE_LOOKUP_TABLE_ITEM MemoryMap;
- ULONG NoEntries;
- PKTSS Tss;
- BOOLEAN Status;
-
- //
- // Creating a suitable memory map for the Windows can be tricky, so let's
- // give a few advices:
- // 1) One must not map the whole available memory pages to PDE!
- // Map only what's needed - 16Mb, 24Mb, 32Mb max I think,
- // thus occupying 4, 6 or 8 PDE entries for identical mapping,
- // the same quantity for KSEG0_BASE mapping, one more entry for
- // hyperspace and one more entry for HAL physical pages mapping.
- // 2) Memory descriptors must map *the whole* physical memory
- // showing any memory above 16/24/32 as FirmwareTemporary
- //
- // 3) Overall memory blocks count must not exceed 30 (?? why?)
- //
-
- //
- // During MmInitMachineDependent, the kernel zeroes PDE at the following address
- // 0xC0300000 - 0xC03007FC
- //
- // Then it finds the best place for non-paged pool:
- // StartPde C0300F70, EndPde C0300FF8, NumberOfPages C13, NextPhysPage 3AD
- //
-
- // Before we start mapping pages, create a block of memory, which will contain
- // PDE and PTEs
- if (MempAllocatePageTables() == FALSE)
- return FALSE;
-
- // Allocate memory for memory allocation descriptors
- Mad = MmHeapAlloc(sizeof(MEMORY_ALLOCATION_DESCRIPTOR) * 1024);
-
- // Setup an entry for each descriptor
- MemoryMap = MmGetMemoryMap(&NoEntries);
- if (MemoryMap == NULL)
- {
- UiMessageBox("Can not retrieve the current memory map");
- return FALSE;
- }
-
- // Calculate parameters of the memory map
- MemoryMapStartPage = (ULONG_PTR)MemoryMap >> MM_PAGE_SHIFT;
- MemoryMapSizeInPages = NoEntries * sizeof(PAGE_LOOKUP_TABLE_ITEM);
-
- DPRINTM(DPRINT_WINDOWS, "Got memory map with %d entries\n", NoEntries);
-
- // Always contigiously map low 1Mb of memory
- Status = MempSetupPaging(0, 0x100);
- if (!Status)
- {
- DPRINTM(DPRINT_WINDOWS, "Error during MempSetupPaging of low 1Mb\n");
- return FALSE;
- }
-
- // Construct a good memory map from what we've got,
- // but mark entries which the memory allocation bitmap takes
- // as free entries (this is done in order to have the ability
- // to place mem alloc bitmap outside lower 16Mb zone)
- PagesCount = 1;
- LastPageIndex = 0;
- LastPageType = MemoryMap[0].PageAllocated;
- for(i=1;i<NoEntries;i++)
- {
- // Check if its memory map itself
- if (i >= MemoryMapStartPage &&
- i < (MemoryMapStartPage+MemoryMapSizeInPages))
- {
- // Exclude it if current page belongs to the memory map
- MemoryMap[i].PageAllocated = LoaderFree;
- }
-
- // Process entry
- if (MemoryMap[i].PageAllocated == LastPageType &&
- (i != NoEntries-1) )
- {
- PagesCount++;
- }
- else
- {
- // Add the resulting region
- MempAddMemoryBlock(LoaderBlock, LastPageIndex, PagesCount, LastPageType);
-
- // Reset our counter vars
- LastPageIndex = i;
- LastPageType = MemoryMap[i].PageAllocated;
- PagesCount = 1;
- }
- }
-
- // TEMP, DEBUG!
- // adding special reserved memory zones for vmware workstation
- #if 0
- {
- Mad[MadCount].BasePage = 0xfec00;
- Mad[MadCount].PageCount = 0x10;
- Mad[MadCount].MemoryType = LoaderSpecialMemory;
- WinLdrInsertDescriptor(LoaderBlock, &Mad[MadCount]);
- MadCount++;
-
- Mad[MadCount].BasePage = 0xfee00;
- Mad[MadCount].PageCount = 0x1;
- Mad[MadCount].MemoryType = LoaderSpecialMemory;
- WinLdrInsertDescriptor(LoaderBlock, &Mad[MadCount]);
- MadCount++;
-
- Mad[MadCount].BasePage = 0xfffe0;
- Mad[MadCount].PageCount = 0x20;
- Mad[MadCount].MemoryType = LoaderSpecialMemory;
- WinLdrInsertDescriptor(LoaderBlock, &Mad[MadCount]);
- MadCount++;
- }
- #endif
-
- DPRINTM(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;
- }*/
++ WinLdrMapSpecialPages(ULONG PcrBasePage)
+ {
- Tss = (PKTSS)(KSEG0_BASE | (TssBasePage << MM_PAGE_SHIFT));
-
- // Unmap what is not needed from kernel page table
- MempDisablePages();
-
- // Fill the memory descriptor list and
- //PrepareMemoryDescriptorList();
- DPRINTM(DPRINT_WINDOWS, "Memory Descriptor List prepared, printing PDE\n");
- List_PaToVa(&LoaderBlock->MemoryDescriptorListHead);
-
- #if DBG
- {
- ULONG *PDE_Addr=(ULONG *)PDE;//0xC0300000;
- int j;
-
- DPRINTM(DPRINT_WINDOWS, "\nPDE\n");
-
- for (i=0; i<128; i++)
- {
- DPRINTM(DPRINT_WINDOWS, "0x%04X | ", i*8);
+
+ //VideoDisplayString(L"Hello from VGA, going into the kernel\n");
+ DPRINTM(DPRINT_WINDOWS, "HalPageTable: 0x%X\n", HalPageTable);
+
+ // Page Tables have been setup, make special handling for PCR and TSS
+ // (which is done in BlSetupFotNt in usual ntldr)
+ HalPageTable[(KI_USER_SHARED_DATA - 0xFFC00000) >> MM_PAGE_SHIFT].PageFrameNumber = PcrBasePage+1;
+ HalPageTable[(KI_USER_SHARED_DATA - 0xFFC00000) >> MM_PAGE_SHIFT].Valid = 1;
+ HalPageTable[(KI_USER_SHARED_DATA - 0xFFC00000) >> MM_PAGE_SHIFT].Write = 1;
+
+ HalPageTable[(KIP0PCRADDRESS - 0xFFC00000) >> MM_PAGE_SHIFT].PageFrameNumber = PcrBasePage;
+ HalPageTable[(KIP0PCRADDRESS - 0xFFC00000) >> MM_PAGE_SHIFT].Valid = 1;
+ HalPageTable[(KIP0PCRADDRESS - 0xFFC00000) >> MM_PAGE_SHIFT].Write = 1;
+
+ // Map APIC
+ WinLdrpMapApic();
+
+ // Map VGA memory
+ //VideoMemoryBase = MmMapIoSpace(0xb8000, 4000, MmNonCached);
+ //DPRINTM(DPRINT_WINDOWS, "VideoMemoryBase: 0x%X\n", VideoMemoryBase);
+
- for (j=0; j<8; j++)
- {
- DPRINTM(DPRINT_WINDOWS, "0x%08X ", PDE_Addr[i*8+j]);
- }
++ return TRUE;
++ }
+
- DPRINTM(DPRINT_WINDOWS, "\n");
- }
- }
- #endif
+
- // 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;
-
- DPRINTM(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;
-
- DPRINTM(DPRINT_WINDOWS, "GDtIdt %p, Pcr %p, Tss 0x%08X\n",
- GdtIdt, Pcr, Tss);
-
++ VOID
++ WinLdrSetProcessorContext(PVOID GdtIdt, IN ULONG Pcr, IN ULONG Tss)
++ {
++ GDTIDT GdtDesc, IdtDesc, OldIdt;
++ PKGDTENTRY pGdt;
++ PKIDTENTRY pIdt;
++ ULONG Ldt = 0;
++ //ULONG i;
+
++ DPRINTM(DPRINT_WINDOWS, "GDtIdt %p, Pcr %p, Tss 0x%08X\n",
++ GdtIdt, Pcr, Tss);
+
+ // Enable paging
+ //BS->ExitBootServices(ImageHandle,MapKey);
+
+ // Disable Interrupts
+ _disable();
+
+ // Re-initalize EFLAGS
+ __writeeflags(0);
+
+ // Set the PDBR
+ __writecr3((ULONG_PTR)PDE);
+
+ // Enable paging by modifying CR0
+ __writecr0(__readcr0() | CR0_PG);
+
- int j;
+ // 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);
+ __sidt(&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; //FIXME: Check this
+ 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 stuff (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;
+ 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
+ //
+
+ // Copy the old IDT
+ RtlCopyMemory(pIdt, (PVOID)OldIdt.Base, OldIdt.Limit + 1);
+
+ // Mask interrupts
+ //asm("cli\n"); // they are already masked before enabling paged mode
+
+ // Load GDT+IDT
+ Ke386SetGlobalDescriptorTable(&GdtDesc);
+ __lidt(&IdtDesc);
+
+ // Jump to proper CS and clear prefetch queue
+ #if defined(__GNUC__)
+ asm("ljmp $0x08, $1f\n"
+ "1:\n");
+ #elif defined(_MSC_VER)
+ /* We can't express the above in MASM so we use this far return instead */
+ DbgPrint("WinLdrSetProcessorContext: Performing untested far-return\n");
+ __asm {
+ push 8
+ push offset resume
+ retf
+ resume:
+ };
+ #else
+ #error
+ #endif
+
+ // Set SS selector
+ Ke386SetSs(0x10); // DataSelector=0x10
+
+ // 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(KGDT_TSS);
+
+ // Clear GS
+ Ke386SetGs(0);
+
+ // 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
+ */
+ }
++
++ VOID
++ MempDump()
++ {
++ ULONG *PDE_Addr=(ULONG *)PDE;//0xC0300000;
+++ int i, j;
++
++ DPRINTM(DPRINT_WINDOWS, "\nPDE\n");
++
++ for (i=0; i<128; i++)
++ {
++ DPRINTM(DPRINT_WINDOWS, "0x%04X | ", i*8);
++
++ for (j=0; j<8; j++)
++ {
++ DPRINTM(DPRINT_WINDOWS, "0x%08X ", PDE_Addr[i*8+j]);
++ }
++
++ DPRINTM(DPRINT_WINDOWS, "\n");
++ }
++ }
++
--- /dev/null
- extern ULONG TotalNLSSize;
+ /*
+ * PROJECT: EFI Windows Loader
+ * LICENSE: GPL - See COPYING in the top level directory
+ * FILE: freeldr/winldr/wlmemory.c
+ * PURPOSE: Memory related routines
+ * PROGRAMMERS: Aleksey Bragin (aleksey@reactos.org)
+ */
+
+ /* INCLUDES ***************************************************************/
+
+ #include <freeldr.h>
+
+ #include <ndk/asm.h>
+ #include <debug.h>
+
- -// This is needed because headers define wrong one for ReactOS
- -#undef KIP0PCRADDRESS
- -#define KIP0PCRADDRESS 0xffdff000
-
- #define HYPER_SPACE_ENTRY 0x300
- -
+ extern ULONG LoaderPagesSpanned;
+
- -WinLdrSetProcessorContext(PVOID GdtIdt, IN ULONG Pcr, IN ULONG Tss);
-
- // This is needed only for SetProcessorContext routine
- #pragma pack(2)
- typedef struct
- {
- USHORT Limit;
- ULONG Base;
- } GDTIDT;
- #pragma pack(4)
-
- /* GLOBALS ***************************************************************/
-
- PHARDWARE_PTE PDE;
- PHARDWARE_PTE HalPageTable;
-
- PUCHAR PhysicalPageTablesBuffer;
- PUCHAR KernelPageTablesBuffer;
- ULONG PhysicalPageTables;
- ULONG KernelPageTables;
-
- MEMORY_ALLOCATION_DESCRIPTOR *Mad;
- ULONG MadCount = 0;
-
-
- /* FUNCTIONS **************************************************************/
+ PCHAR MemTypeDesc[] = {
+ "ExceptionBlock ", // ?
+ "SystemBlock ", // ?
+ "Free ",
+ "Bad ", // used
+ "LoadedProgram ", // == Free
+ "FirmwareTemporary ", // == Free
+ "FirmwarePermanent ", // == Bad
+ "OsloaderHeap ", // used
+ "OsloaderStack ", // == Free
+ "SystemCode ",
+ "HalCode ",
+ "BootDriver ", // not used
+ "ConsoleInDriver ", // ?
+ "ConsoleOutDriver ", // ?
+ "StartupDpcStack ", // ?
+ "StartupKernelStack", // ?
+ "StartupPanicStack ", // ?
+ "StartupPcrPage ", // ?
+ "StartupPdrPage ", // ?
+ "RegistryData ", // used
+ "MemoryData ", // not used
+ "NlsData ", // used
+ "SpecialMemory ", // == Bad
+ "BBTMemory " // == Bad
+ };
+
+ VOID
+ WinLdrpDumpMemoryDescriptors(PLOADER_PARAMETER_BLOCK LoaderBlock);
+
+
+ VOID
+ MempAddMemoryBlock(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
+ ULONG BasePage,
+ ULONG PageCount,
+ ULONG Type);
+ VOID
+ WinLdrInsertDescriptor(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
+ IN PMEMORY_ALLOCATION_DESCRIPTOR NewDescriptor);
+
+ VOID
+ WinLdrRemoveDescriptor(IN PMEMORY_ALLOCATION_DESCRIPTOR Descriptor);
+
+ VOID
- MempAllocatePageTables()
- {
- ULONG NumPageTables, TotalSize;
- PUCHAR Buffer;
- // It's better to allocate PDE + PTEs contigiuos
-
- // Max number of entries = MaxPageNum >> 10
- // FIXME: This is a number to describe ALL physical memory
- // and windows doesn't expect ALL memory mapped...
- NumPageTables = (GetSystemMemorySize() >> MM_PAGE_SHIFT) >> 10;
-
- DPRINTM(DPRINT_WINDOWS, "NumPageTables = %d\n", NumPageTables);
-
- // Allocate memory block for all these things:
- // PDE, HAL mapping page table, physical mapping, kernel mapping
- TotalSize = (1+1+NumPageTables*2)*MM_PAGE_SIZE;
-
- // PDE+HAL+KernelPTEs == MemoryData
- Buffer = MmAllocateMemoryWithType(TotalSize, LoaderMemoryData);
-
- // Physical PTEs = FirmwareTemporary
- PhysicalPageTablesBuffer = (PUCHAR)Buffer + TotalSize - NumPageTables*MM_PAGE_SIZE;
- MmSetMemoryType(PhysicalPageTablesBuffer,
- NumPageTables*MM_PAGE_SIZE,
- LoaderFirmwareTemporary);
-
- // This check is now redundant
- if (Buffer + (TotalSize - NumPageTables*MM_PAGE_SIZE) !=
- PhysicalPageTablesBuffer)
- {
- DPRINTM(DPRINT_WINDOWS, "There was a problem allocating two adjacent blocks of memory!");
- }
-
- if (Buffer == NULL || PhysicalPageTablesBuffer == NULL)
- {
- UiMessageBox("Impossible to allocate memory block for page tables!");
- return FALSE;
- }
-
- // Zero all this memory block
- RtlZeroMemory(Buffer, TotalSize);
-
- // Set up pointers correctly now
- PDE = (PHARDWARE_PTE)Buffer;
-
- // Map the page directory at 0xC0000000 (maps itself)
- PDE[HYPER_SPACE_ENTRY].PageFrameNumber = (ULONG)PDE >> MM_PAGE_SHIFT;
- PDE[HYPER_SPACE_ENTRY].Valid = 1;
- PDE[HYPER_SPACE_ENTRY].Write = 1;
-
- // The last PDE slot is allocated for HAL's memory mapping (Virtual Addresses 0xFFC00000 - 0xFFFFFFFF)
- HalPageTable = (PHARDWARE_PTE)&Buffer[MM_PAGE_SIZE*1];
-
- // Map it
- PDE[1023].PageFrameNumber = (ULONG)HalPageTable >> MM_PAGE_SHIFT;
- PDE[1023].Valid = 1;
- PDE[1023].Write = 1;
-
- // Store pointer to the table for easier access
- KernelPageTablesBuffer = &Buffer[MM_PAGE_SIZE*2];
-
- // Zero counters of page tables used
- PhysicalPageTables = 0;
- KernelPageTables = 0;
-
- return TRUE;
- }
-
- VOID
- MempAllocatePTE(ULONG Entry, PHARDWARE_PTE *PhysicalPT, PHARDWARE_PTE *KernelPT)
- {
- //Print(L"Creating PDE Entry %X\n", Entry);
-
- // Identity mapping
- *PhysicalPT = (PHARDWARE_PTE)&PhysicalPageTablesBuffer[PhysicalPageTables*MM_PAGE_SIZE];
- PhysicalPageTables++;
-
- PDE[Entry].PageFrameNumber = (ULONG)*PhysicalPT >> MM_PAGE_SHIFT;
- PDE[Entry].Valid = 1;
- PDE[Entry].Write = 1;
-
- if (Entry+(KSEG0_BASE >> 22) > 1023)
- {
- DPRINTM(DPRINT_WINDOWS, "WARNING! Entry: %X > 1023\n", Entry+(KSEG0_BASE >> 22));
- }
-
- // Kernel-mode mapping
- *KernelPT = (PHARDWARE_PTE)&KernelPageTablesBuffer[KernelPageTables*MM_PAGE_SIZE];
- KernelPageTables++;
-
- PDE[Entry+(KSEG0_BASE >> 22)].PageFrameNumber = ((ULONG)*KernelPT >> MM_PAGE_SHIFT);
- PDE[Entry+(KSEG0_BASE >> 22)].Valid = 1;
- PDE[Entry+(KSEG0_BASE >> 22)].Write = 1;
- }
+++WinLdrSetProcessorContext(PVOID GdtIdt, IN ULONG_PTR Pcr, IN ULONG_PTR Tss);
+
+ BOOLEAN
- IN ULONG NumberOfPages)
- {
- PHARDWARE_PTE PhysicalPT;
- PHARDWARE_PTE KernelPT;
- ULONG Entry, Page;
-
- //Print(L"MempSetupPaging: SP 0x%X, Number: 0x%X\n", StartPage, NumberOfPages);
-
- // HACK
- if (StartPage+NumberOfPages >= 0x80000)
- {
- //
- // We can't map this as it requires more than 1 PDE
- // and in fact it's not possible at all ;)
- //
- //Print(L"skipping...\n");
- return TRUE;
- }
++ MempAllocatePageTables();
+
+ BOOLEAN
+ MempSetupPaging(IN ULONG StartPage,
- //
- // Now actually set up the page tables for identity mapping
- //
- for (Page=StartPage; Page < StartPage+NumberOfPages; Page++)
- {
- Entry = Page >> 10;
++ IN ULONG NumberOfPages);
+
- if (((PULONG)PDE)[Entry] == 0)
- {
- MempAllocatePTE(Entry, &PhysicalPT, &KernelPT);
- }
- else
- {
- PhysicalPT = (PHARDWARE_PTE)(PDE[Entry].PageFrameNumber << MM_PAGE_SHIFT);
- KernelPT = (PHARDWARE_PTE)(PDE[Entry+(KSEG0_BASE >> 22)].PageFrameNumber << MM_PAGE_SHIFT);
- }
++ BOOLEAN
++ WinLdrMapSpecialPages(ULONG PcrBasePage);
+
- if (Page == 0)
- {
- PhysicalPT[Page & 0x3ff].PageFrameNumber = Page;
- PhysicalPT[Page & 0x3ff].Valid = 0;
- PhysicalPT[Page & 0x3ff].Write = 0;
++ VOID
++ MempUnmapPage(ULONG Page);
+
- KernelPT[Page & 0x3ff].PageFrameNumber = Page;
- KernelPT[Page & 0x3ff].Valid = 0;
- KernelPT[Page & 0x3ff].Write = 0;
- }
- else
- {
- PhysicalPT[Page & 0x3ff].PageFrameNumber = Page;
- PhysicalPT[Page & 0x3ff].Valid = 1;
- PhysicalPT[Page & 0x3ff].Write = 1;
++ VOID
++ MempDump();
+
- KernelPT[Page & 0x3ff].PageFrameNumber = Page;
- KernelPT[Page & 0x3ff].Valid = 1;
- KernelPT[Page & 0x3ff].Write = 1;
- }
- }
++ /* GLOBALS ***************************************************************/
+
- return TRUE;
- }
++ MEMORY_ALLOCATION_DESCRIPTOR *Mad;
++ ULONG MadCount = 0;
+
- PHARDWARE_PTE KernelPT;
- ULONG Entry = (Page >> 10) + (KSEG0_BASE >> 22);
-
- if (PDE[Entry].Valid)
- {
- KernelPT = (PHARDWARE_PTE)(PDE[Entry].PageFrameNumber << MM_PAGE_SHIFT);
-
- if (KernelPT)
- {
- KernelPT[Page & 0x3ff].PageFrameNumber = 0;
- KernelPT[Page & 0x3ff].Valid = 0;
- KernelPT[Page & 0x3ff].Write = 0;
- }
- }
++ /* FUNCTIONS **************************************************************/
+
+ VOID
+ MempDisablePages()
+ {
+ ULONG i;
+
+ //
+ // We need to delete kernel mapping from memory areas which are
+ // marked as Special or Permanent memory (thus non-accessible)
+ //
+
+ for (i=0; i<MadCount; i++)
+ {
+ ULONG StartPage, EndPage, Page;
+
+ StartPage = Mad[i].BasePage;
+ EndPage = Mad[i].BasePage + Mad[i].PageCount;
+
+ if (Mad[i].MemoryType == LoaderFirmwarePermanent ||
+ Mad[i].MemoryType == LoaderSpecialMemory ||
+ Mad[i].MemoryType == LoaderFree ||
+ (Mad[i].MemoryType == LoaderFirmwareTemporary && EndPage <= LoaderPagesSpanned) ||
+ Mad[i].MemoryType == LoaderOsloaderStack ||
+ Mad[i].MemoryType == LoaderLoadedProgram)
+ {
+ //
+ // But, the first megabyte of memory always stays!
+ // And, to tell the truth, we don't care about what's higher
+ // than LoaderPagesSpanned
+ if (Mad[i].MemoryType == LoaderFirmwarePermanent ||
+ Mad[i].MemoryType == LoaderSpecialMemory)
+ {
+ if (StartPage < 0x100)
+ StartPage = 0x100;
+
+ if (EndPage > LoaderPagesSpanned)
+ EndPage = LoaderPagesSpanned;
+ }
+
+ for (Page = StartPage; Page < EndPage; Page++)
+ {
- #ifdef _M_IX86
- VOID
- WinLdrpMapApic()
- {
- BOOLEAN LocalAPIC;
- LARGE_INTEGER MsrValue;
- ULONG APICAddress, CpuInfo[4];
-
- /* Check if we have a local APIC */
- __cpuid((int*)CpuInfo, 1);
- LocalAPIC = (((CpuInfo[3] >> 9) & 1) != 0);
-
- /* If there is no APIC, just return */
- if (!LocalAPIC)
- return;
-
- /* Read the APIC Address */
- MsrValue.QuadPart = __readmsr(0x1B);
- APICAddress = (MsrValue.LowPart & 0xFFFFF000);
-
- DPRINTM(DPRINT_WINDOWS, "Local APIC detected at address 0x%x\n",
- APICAddress);
-
- /* Map it */
- HalPageTable[(APIC_BASE - 0xFFC00000) >> MM_PAGE_SHIFT].PageFrameNumber
- = APICAddress >> MM_PAGE_SHIFT;
- HalPageTable[(APIC_BASE - 0xFFC00000) >> MM_PAGE_SHIFT].Valid = 1;
- HalPageTable[(APIC_BASE - 0xFFC00000) >> MM_PAGE_SHIFT].Write = 1;
- HalPageTable[(APIC_BASE - 0xFFC00000) >> MM_PAGE_SHIFT].WriteThrough = 1;
- HalPageTable[(APIC_BASE - 0xFFC00000) >> MM_PAGE_SHIFT].CacheDisable = 1;
- }
- #else
- VOID
- WinLdrpMapApic()
- {
- /* Implement it for another arch */
- }
- #endif
-
++ MempUnmapPage(Page);
+ }
+ }
+ }
+ }
+
+ VOID
+ MempAddMemoryBlock(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
+ ULONG BasePage,
+ ULONG PageCount,
+ ULONG Type)
+ {
+ BOOLEAN Status;
+
+ //
+ // Check for some weird stuff at the top
+ //
+ if (BasePage + PageCount > 0xF0000)
+ {
+ //
+ // Just skip this, without even adding to MAD list
+ //
+ return;
+ }
+
+ //
+ // Set Base page, page count and type
+ //
+ Mad[MadCount].BasePage = BasePage;
+ Mad[MadCount].PageCount = PageCount;
+ Mad[MadCount].MemoryType = Type;
+
+ //
+ // Check if it's more than the allowed for OS loader
+ // if yes - don't map the pages, just add as FirmwareTemporary
+ //
+ if (BasePage + PageCount > LoaderPagesSpanned)
+ {
+ if (Mad[MadCount].MemoryType != LoaderSpecialMemory &&
+ Mad[MadCount].MemoryType != LoaderFirmwarePermanent &&
+ Mad[MadCount].MemoryType != LoaderFree)
+ {
+ DPRINTM(DPRINT_WINDOWS, "Setting page %x %x to Temporary from %d\n",
+ BasePage, PageCount, Mad[MadCount].MemoryType);
+ Mad[MadCount].MemoryType = LoaderFirmwareTemporary;
+ }
+
+ WinLdrInsertDescriptor(LoaderBlock, &Mad[MadCount]);
+ MadCount++;
+
+ return;
+ }
+
+ //
+ // Add descriptor
+ //
+ WinLdrInsertDescriptor(LoaderBlock, &Mad[MadCount]);
+ MadCount++;
+
+ //
+ // Map it (don't map low 1Mb because it was already contigiously
+ // mapped in WinLdrTurnOnPaging)
+ //
+ if (BasePage >= 0x100)
+ {
+ Status = MempSetupPaging(BasePage, PageCount);
+ if (!Status)
+ {
+ DPRINTM(DPRINT_WINDOWS, "Error during MempSetupPaging\n");
+ return;
+ }
+ }
+ }
+
- //VideoDisplayString(L"Hello from VGA, going into the kernel\n");
- DPRINTM(DPRINT_WINDOWS, "HalPageTable: 0x%X\n", HalPageTable);
-
- // Page Tables have been setup, make special handling for PCR and TSS
- // (which is done in BlSetupFotNt in usual ntldr)
- HalPageTable[(KI_USER_SHARED_DATA - 0xFFC00000) >> MM_PAGE_SHIFT].PageFrameNumber = PcrBasePage+1;
- HalPageTable[(KI_USER_SHARED_DATA - 0xFFC00000) >> MM_PAGE_SHIFT].Valid = 1;
- HalPageTable[(KI_USER_SHARED_DATA - 0xFFC00000) >> MM_PAGE_SHIFT].Write = 1;
-
- HalPageTable[(KIP0PCRADDRESS - 0xFFC00000) >> MM_PAGE_SHIFT].PageFrameNumber = PcrBasePage;
- HalPageTable[(KIP0PCRADDRESS - 0xFFC00000) >> MM_PAGE_SHIFT].Valid = 1;
- HalPageTable[(KIP0PCRADDRESS - 0xFFC00000) >> MM_PAGE_SHIFT].Write = 1;
-
- // Map APIC
- WinLdrpMapApic();
-
- // Map VGA memory
- //VideoMemoryBase = MmMapIoSpace(0xb8000, 4000, MmNonCached);
- //DPRINTM(DPRINT_WINDOWS, "VideoMemoryBase: 0x%X\n", VideoMemoryBase);
+ BOOLEAN
+ WinLdrTurnOnPaging(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
+ ULONG PcrBasePage,
+ ULONG TssBasePage,
+ PVOID GdtIdt)
+ {
+ ULONG i, PagesCount, MemoryMapSizeInPages;
+ ULONG LastPageIndex, LastPageType, MemoryMapStartPage;
+ PPAGE_LOOKUP_TABLE_ITEM MemoryMap;
+ ULONG NoEntries;
+ PKTSS Tss;
+ BOOLEAN Status;
+
+ //
+ // Creating a suitable memory map for the Windows can be tricky, so let's
+ // give a few advices:
+ // 1) One must not map the whole available memory pages to PDE!
+ // Map only what's needed - 16Mb, 24Mb, 32Mb max I think,
+ // thus occupying 4, 6 or 8 PDE entries for identical mapping,
+ // the same quantity for KSEG0_BASE mapping, one more entry for
+ // hyperspace and one more entry for HAL physical pages mapping.
+ // 2) Memory descriptors must map *the whole* physical memory
+ // showing any memory above 16/24/32 as FirmwareTemporary
+ //
+ // 3) Overall memory blocks count must not exceed 30 (?? why?)
+ //
+
+ //
+ // During MmInitMachineDependent, the kernel zeroes PDE at the following address
+ // 0xC0300000 - 0xC03007FC
+ //
+ // Then it finds the best place for non-paged pool:
+ // StartPde C0300F70, EndPde C0300FF8, NumberOfPages C13, NextPhysPage 3AD
+ //
+
+ // Before we start mapping pages, create a block of memory, which will contain
+ // PDE and PTEs
+ if (MempAllocatePageTables() == FALSE)
+ return FALSE;
+
+ // Allocate memory for memory allocation descriptors
+ Mad = MmHeapAlloc(sizeof(MEMORY_ALLOCATION_DESCRIPTOR) * 1024);
+
+ // Setup an entry for each descriptor
+ MemoryMap = MmGetMemoryMap(&NoEntries);
+ if (MemoryMap == NULL)
+ {
+ UiMessageBox("Can not retrieve the current memory map");
+ return FALSE;
+ }
+
+ // Calculate parameters of the memory map
+ MemoryMapStartPage = (ULONG_PTR)MemoryMap >> MM_PAGE_SHIFT;
+ MemoryMapSizeInPages = NoEntries * sizeof(PAGE_LOOKUP_TABLE_ITEM);
+
+ DPRINTM(DPRINT_WINDOWS, "Got memory map with %d entries\n", NoEntries);
+
+ // Always contigiously map low 1Mb of memory
+ Status = MempSetupPaging(0, 0x100);
+ if (!Status)
+ {
+ DPRINTM(DPRINT_WINDOWS, "Error during MempSetupPaging of low 1Mb\n");
+ return FALSE;
+ }
+
+ // Construct a good memory map from what we've got,
+ // but mark entries which the memory allocation bitmap takes
+ // as free entries (this is done in order to have the ability
+ // to place mem alloc bitmap outside lower 16Mb zone)
+ PagesCount = 1;
+ LastPageIndex = 0;
+ LastPageType = MemoryMap[0].PageAllocated;
+ for(i=1;i<NoEntries;i++)
+ {
+ // Check if its memory map itself
+ if (i >= MemoryMapStartPage &&
+ i < (MemoryMapStartPage+MemoryMapSizeInPages))
+ {
+ // Exclude it if current page belongs to the memory map
+ MemoryMap[i].PageAllocated = LoaderFree;
+ }
+
+ // Process entry
+ if (MemoryMap[i].PageAllocated == LastPageType &&
+ (i != NoEntries-1) )
+ {
+ PagesCount++;
+ }
+ else
+ {
+ // Add the resulting region
+ MempAddMemoryBlock(LoaderBlock, LastPageIndex, PagesCount, LastPageType);
+
+ // Reset our counter vars
+ LastPageIndex = i;
+ LastPageType = MemoryMap[i].PageAllocated;
+ PagesCount = 1;
+ }
+ }
+
+ // TEMP, DEBUG!
+ // adding special reserved memory zones for vmware workstation
+ #if 0
+ {
+ Mad[MadCount].BasePage = 0xfec00;
+ Mad[MadCount].PageCount = 0x10;
+ Mad[MadCount].MemoryType = LoaderSpecialMemory;
+ WinLdrInsertDescriptor(LoaderBlock, &Mad[MadCount]);
+ MadCount++;
+
+ Mad[MadCount].BasePage = 0xfee00;
+ Mad[MadCount].PageCount = 0x1;
+ Mad[MadCount].MemoryType = LoaderSpecialMemory;
+ WinLdrInsertDescriptor(LoaderBlock, &Mad[MadCount]);
+ MadCount++;
+
+ Mad[MadCount].BasePage = 0xfffe0;
+ Mad[MadCount].PageCount = 0x20;
+ Mad[MadCount].MemoryType = LoaderSpecialMemory;
+ WinLdrInsertDescriptor(LoaderBlock, &Mad[MadCount]);
+ MadCount++;
+ }
+ #endif
+
+ DPRINTM(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;
+ }*/
+
- {
- ULONG *PDE_Addr=(ULONG *)PDE;//0xC0300000;
- int j;
-
- DPRINTM(DPRINT_WINDOWS, "\nPDE\n");
-
- for (i=0; i<128; i++)
- {
- DPRINTM(DPRINT_WINDOWS, "0x%04X | ", i*8);
-
- for (j=0; j<8; j++)
- {
- DPRINTM(DPRINT_WINDOWS, "0x%08X ", PDE_Addr[i*8+j]);
- }
-
- DPRINTM(DPRINT_WINDOWS, "\n");
- }
- }
++ /* Map stuff like PCR, KI_USER_SHARED_DATA and Apic */
++ WinLdrMapSpecialPages(PcrBasePage);
+
+ Tss = (PKTSS)(KSEG0_BASE | (TssBasePage << MM_PAGE_SHIFT));
+
+ // Unmap what is not needed from kernel page table
+ MempDisablePages();
+
+ // Fill the memory descriptor list and
+ //PrepareMemoryDescriptorList();
+ DPRINTM(DPRINT_WINDOWS, "Memory Descriptor List prepared, printing PDE\n");
+ List_PaToVa(&LoaderBlock->MemoryDescriptorListHead);
+
+ #if DBG
-
- // Enable paging
- //BS->ExitBootServices(ImageHandle,MapKey);
-
- // Disable Interrupts
- _disable();
-
- // Re-initalize EFLAGS
- __writeeflags(0);
-
- // Set the PDBR
- __writecr3((ULONG_PTR)PDE);
-
- // Enable paging by modifying CR0
- __writecr0(__readcr0() | CR0_PG);
-
++ MempDump();
+ #endif
+
- VOID
- WinLdrSetProcessorContext(PVOID GdtIdt, IN ULONG Pcr, IN ULONG Tss)
- {
- GDTIDT GdtDesc, IdtDesc, OldIdt;
- PKGDTENTRY pGdt;
- PKIDTENTRY pIdt;
- ULONG Ldt = 0;
- //ULONG i;
-
- DPRINTM(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);
- __sidt(&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; //FIXME: Check this
- 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 stuff (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;
- 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
- //
-
- // Copy the old IDT
- RtlCopyMemory(pIdt, (PVOID)OldIdt.Base, OldIdt.Limit + 1);
-
- // Mask interrupts
- //asm("cli\n"); // they are already masked before enabling paged mode
-
- // Load GDT+IDT
- Ke386SetGlobalDescriptorTable(&GdtDesc);
- __lidt(&IdtDesc);
-
- // Jump to proper CS and clear prefetch queue
- #if defined(__GNUC__)
- asm("ljmp $0x08, $1f\n"
- "1:\n");
- #elif defined(_MSC_VER)
- /* We can't express the above in MASM so we use this far return instead */
- DbgPrint("WinLdrSetProcessorContext: Performing untested far-return\n");
- __asm {
- push 8
- push offset resume
- retf
- resume:
- };
- #else
- #error
- #endif
-
- // Set SS selector
- Ke386SetSs(0x10); // DataSelector=0x10
-
- // 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(KGDT_TSS);
-
- // Clear GS
- Ke386SetGs(0);
-
- // 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
- */
- }
+ // 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;
+
+ DPRINTM(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;
+ }
+
// Returns the Interrupt State from a Trap Frame.
// ON = TRUE, OFF = FALSE
//
--//#define KeGetTrapFrameInterruptState(TrapFrame) \
++//#define KeGetTrapFrameInterruptState(TrapFrame)
++
++//
++// Invalidates the TLB entry for a specified address
++//
++FORCEINLINE
++VOID
++KeInvalidateTlbEntry(IN PVOID Address)
++{
++ /* Invalidate the TLB entry for this address */
++ KeArmInvalidateTlbEntry(Address);
++}
++
+++FORCEINLINE
+++VOID
+++KeFlushProcessTb(VOID)
+++{
+++ //
+++ // We need to implement this!
+++ //
+++ ASSERTMSG("Need ARM flush routine\n", FALSE);
+++}
+++
+++FORCEINLINE
+++VOID
+++KiRundownThread(IN PKTHREAD Thread)
+++{
+++ /* FIXME */
+++}
+
VOID
KiPassiveRelease(
VOID
#define KeGetTrapFrameInterruptState(TrapFrame) \
BooleanFlagOn((TrapFrame)->EFlags, EFLAGS_INTERRUPT_MASK)
++//
++// Invalidates the TLB entry for a specified address
++//
++FORCEINLINE
++VOID
++KeInvalidateTlbEntry(IN PVOID Address)
++{
++ /* Invalidate the TLB entry for this address */
++ __invlpg(Address);
++}
++
+++FORCEINLINE
+++VOID
+++KeFlushProcessTb(VOID)
+++{
+++ /* Flush the TLB by resetting CR3 */
+++ __writecr3(__readcr3());
+++}
+++
+++FORCEINLINE
+++PRKTHREAD
+++KeGetCurrentThread(VOID)
+++{
+++ /* Return the current thread */
+++ return ((PKIPCR)KeGetPcr())->PrcbData.CurrentThread;
+++}
+++
+++FORCEINLINE
+++VOID
+++KiRundownThread(IN PKTHREAD Thread)
+++{
+++#ifndef CONFIG_SMP
+++ /* Check if this is the NPX Thread */
+++ if (KeGetCurrentPrcb()->NpxThread == Thread)
+++ {
+++ /* Clear it */
+++ KeGetCurrentPrcb()->NpxThread = NULL;
+++ Ke386FnInit();
+++ }
+++#else
+++ /* Nothing to do */
+++#endif
+++}
+++
VOID
FASTCALL
Ki386InitializeTss(
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
*/
--//
--// Thread Dispatcher Header DebugActive Mask
--//
--#define DR_MASK(x) 1 << x
--#define DR_ACTIVE_MASK 0x10
--#define DR_REG_MASK 0x4F
--
--#ifdef _M_IX86
--//
--// Sanitizes a selector
--//
--FORCEINLINE
--ULONG
--Ke386SanitizeSeg(IN ULONG Cs,
-- IN KPROCESSOR_MODE Mode)
--{
-- //
-- // Check if we're in kernel-mode, and force CPL 0 if so.
-- // Otherwise, force CPL 3.
-- //
-- return ((Mode == KernelMode) ?
-- (Cs & (0xFFFF & ~RPL_MASK)) :
-- (RPL_MASK | (Cs & 0xFFFF)));
--}
--
--//
--// Sanitizes EFLAGS
--//
--FORCEINLINE
--ULONG
--Ke386SanitizeFlags(IN ULONG Eflags,
-- IN KPROCESSOR_MODE Mode)
--{
-- //
-- // Check if we're in kernel-mode, and sanitize EFLAGS if so.
-- // Otherwise, also force interrupt mask on.
-- //
-- return ((Mode == KernelMode) ?
-- (Eflags & (EFLAGS_USER_SANITIZE | EFLAGS_INTERRUPT_MASK)) :
-- (EFLAGS_INTERRUPT_MASK | (Eflags & EFLAGS_USER_SANITIZE)));
--}
--
--//
--// Gets a DR register from a CONTEXT structure
--//
--FORCEINLINE
--PVOID
--KiDrFromContext(IN ULONG Dr,
-- IN PCONTEXT Context)
--{
-- return *(PVOID*)((ULONG_PTR)Context + KiDebugRegisterContextOffsets[Dr]);
--}
--
--//
--// Gets a DR register from a KTRAP_FRAME structure
--//
--FORCEINLINE
--PVOID*
--KiDrFromTrapFrame(IN ULONG Dr,
-- IN PKTRAP_FRAME TrapFrame)
--{
-- return (PVOID*)((ULONG_PTR)TrapFrame + KiDebugRegisterTrapOffsets[Dr]);
--}
--
--//
--//
--//
--FORCEINLINE
--PVOID
--Ke386SanitizeDr(IN PVOID DrAddress,
-- IN KPROCESSOR_MODE Mode)
--{
-- //
-- // Check if we're in kernel-mode, and return the address directly if so.
-- // Otherwise, make sure it's not inside the kernel-mode address space.
-- // If it is, then clear the address.
-- //
-- return ((Mode == KernelMode) ? DrAddress :
-- (DrAddress <= MM_HIGHEST_USER_ADDRESS) ? DrAddress : 0);
--}
--#endif /* _M_IX86 */
--
#ifndef _M_ARM
---FORCEINLINE
---PRKTHREAD
---KeGetCurrentThread(VOID)
---{
---#ifdef _M_IX86
--- /* Return the current thread */
--- return ((PKIPCR)KeGetPcr())->PrcbData.CurrentThread;
--#elif defined (_M_AMD64)
-- return (PRKTHREAD)__readgsqword(FIELD_OFFSET(KIPCR, Prcb.CurrentThread));
---#else
--- PKPRCB Prcb = KeGetCurrentPrcb();
--- return Prcb->CurrentThread;
---#endif
---}
---
FORCEINLINE
UCHAR
KeGetPreviousMode(VOID)
}
#endif
---FORCEINLINE
---VOID
---KeFlushProcessTb(VOID)
---{
--- /* Flush the TLB by resetting CR3 */
---#ifdef _M_PPC
--- __asm__("sync\n\tisync\n\t");
---#elif _M_ARM
--- //
--- // We need to implement this!
--- //
--- ASSERTMSG("Need ARM flush routine\n", FALSE);
---#else
--- __writecr3(__readcr3());
---#endif
---}
---
//
// Enters a Guarded Region
//
UNREFERENCED_PARAMETER(Prcb);
}
---FORCEINLINE
---VOID
---KiRundownThread(IN PKTHREAD Thread)
---{
- #if defined(_M_IX86) || defined(_M_AMD64)
--#if defined(_M_IX86)
--- /* Check if this is the NPX Thread */
--- if (KeGetCurrentPrcb()->NpxThread == Thread)
--- {
--- /* Clear it */
--- KeGetCurrentPrcb()->NpxThread = NULL;
--- Ke386FnInit();
--- }
---#endif
---}
---
FORCEINLINE
VOID
KiRequestApcInterrupt(IN BOOLEAN NeedApc,
if (Prcb->DeferredReadyListHead.Next) KiProcessDeferredReadyList(Prcb);
}
---FORCEINLINE
---VOID
---KiRundownThread(IN PKTHREAD Thread)
---{
--- /* Nothing to do */
--- return;
---}
---
FORCEINLINE
VOID
KiRequestApcInterrupt(IN BOOLEAN NeedApc,
return (struct _KPCR *)__readfsdword(0x1c);
}
+++FORCEINLINE
+++VOID
+++KeFlushProcessTb(VOID)
+++{
+++ /* Flush the TLB */
+++ __asm__("sync\n\tisync\n\t");
+++}
+++
+++FORCEINLINE
+++PRKTHREAD
+++KeGetCurrentThread(VOID)
+++{
+++ /* Return the current thread */
+++ return KeGetCurrentPrcb()->CurrentThread;
+++}
+++
+++FORCEINLINE
+++VOID
+++KiRundownThread(IN PKTHREAD Thread)
+++{
+++ /* FIXME */
+++}
+++
#ifdef _NTOSKRNL_ /* FIXME: Move flags above to NDK instead of here */
VOID
NTAPI