diff --git a/reactos/boot/freeldr/freeldr/arch/amd64/arch.S b/reactos/boot/freeldr/freeldr/arch/amd64/arch.S
index 33910ffeb6c..0f6c257e34a 100644
--- a/reactos/boot/freeldr/freeldr/arch/amd64/arch.S
+++ b/reactos/boot/freeldr/freeldr/arch/amd64/arch.S
@@ -20,6 +20,10 @@ RealEntryPoint:
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
@@ -41,17 +45,88 @@ RealEntryPoint:
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
- /* Switch to long mode */
+ /* 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
+
+_switch64:
call x86_16_SwitchToLong
.code64
+// mov ax, LMODE_DS
+// mov ds, ax
+// mov word ptr ds:[0xb8000], 0x0e00 + '1'
+
/* GO! */
xor rcx, rcx
call _BootMain
+ /* Checkpoint */
+// mov ax, LMODE_DS
+// mov ds, ax
+// mov word ptr ds:[0xb8002], 0x0e02 + '2'
+
+
/* Return into real mode */
call x86_64_SwitchToReal
.code16
@@ -90,7 +165,6 @@ x86_16_EnableA20:
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
@@ -143,9 +217,39 @@ Bpt2:
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
@@ -190,8 +294,7 @@ LongCat:
/* Now return in long mode! */
ret
-
-/** 64 But functions **********************************************************/
+/** 64 Bit functions **********************************************************/
.code64
.global x86_64_SwitchToReal
@@ -203,25 +306,40 @@ x86_64_SwitchToReal:
/* Save 64-bit stack pointer */
mov stack64, rsp
- /* Step 1 - deactivate long mode, by disabling paging */
- mov rax, cr0
- and rax, 0x000000007fffffff //~0x80000000
- mov cr0, rax
+// mov ax, LMODE_DS
+// mov ds, ax
+// mov word ptr ds:[0xb8004], 0x0e00 + '3'
+
+ /* Step 1 - jump to compatibility segment */
+ ljmp jumpvector
+
+jumpvector:
+ .long SwitchToReal1
+ .word CMODE_CS
+
+SwitchToReal1:
+.code32
+
+// mov word ptr ds:[0xb8006], 0x0e00 + '4'
+
+ /* Step 2 - deactivate long mode, by disabling paging */
+ mov eax, cr0
+ and eax, 0x000000007fffffff //~0x80000000
+ mov cr0, eax
/* Step 2 - disable long mode in EFER MSR */
- mov rcx, 0xC0000080 // Specify EFER MSR
- rdmsr
- and eax, ~0x00000100 // Disable EFER.LME
- wrmsr
+// mov ecx, 0xC0000080 // Specify EFER MSR
+// rdmsr
+// and eax, ~0x00000100 // Disable EFER.LME
+// wrmsr
- .code32
- /* jmp to 16-bit segment to set the limit correctly */
+ /* Step 3 - jump to 16-bit segment to set the limit correctly */
jmp RMODE_CS: offset SwitchToReal2
SwitchToReal2:
.code16
- /* Step 3 - Disable Protected Mode */
+ /* Step 4 - Disable Protected Mode */
mov eax, cr0
and eax, ~0x00000001
mov cr0, eax
@@ -230,6 +348,11 @@ SwitchToReal2:
jmp 0:offset BeReal
BeReal:
+ /* Checkpoint */
+// mov ax, 0xb800
+// mov fs, ax
+// mov word ptr fs:[0x0C], 0x0e00 + '7'
+
/* Restore segment registers */
mov ax, 0
mov ds, ax
@@ -238,7 +361,7 @@ BeReal:
mov gs, ax
mov ss, ax
- /* Rstore 16 bit stack */
+ /* Restore 16 bit stack */
mov sp, stack16
// lidt rmode_idtptr /* Load IDTR with real mode value */
@@ -266,17 +389,19 @@ stack64:
code64ret:
.quad 0
+.p2align 2
gdt:
.quad 0x0000000000000000 /* 00: NULL descriptor */
.quad 0x0000000000000000 /* 08: */
.quad 0x0020980000000000 /* 10: long mode cs */
- .quad 0x0000900000000000 /* 18: long mode ds */
+ .quad 0x00cff3000000ffff /* 18: long mode ds */
.word 0xFFFF, 0x0000, 0x9E00, 0x0000 /* 16-bit real mode CS */
.word 0xFFFF, 0x0000, 0x9200, 0x0000 /* 16-bit real mode DS */
+ .quad 0x00CF9B000000FFFF /* 30: compat mode cs */
/* GDT table pointer */
gdtptr:
- .word 0x2f /* Limit */
+ .word 0x37 /* Limit */
.long gdt /* Base Address */
@@ -288,6 +413,36 @@ _BootDrive:
_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
///////////////////////////////////////////////////////////////////////////////
diff --git a/reactos/boot/freeldr/freeldr/arch/amd64/fathelp.S b/reactos/boot/freeldr/freeldr/arch/amd64/fathelp.S
index 94d4eb6f90a..f799cb9978a 100644
--- a/reactos/boot/freeldr/freeldr/arch/amd64/fathelp.S
+++ b/reactos/boot/freeldr/freeldr/arch/amd64/fathelp.S
@@ -155,7 +155,7 @@ GetFatEntry16:
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
@@ -173,7 +173,7 @@ GetFatEntry12:
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
diff --git a/reactos/boot/freeldr/freeldr/bootmgr.c b/reactos/boot/freeldr/freeldr/bootmgr.c
index 9fa910354cc..a83f294cef3 100644
--- a/reactos/boot/freeldr/freeldr/bootmgr.c
+++ b/reactos/boot/freeldr/freeldr/bootmgr.c
@@ -233,7 +233,7 @@ VOID RunLoader(VOID)
// to have different install methods, etc.
LoadReactOSSetup();
}
-#ifdef __i386__
+#if defined(__i386__) || defined(__x86_64__)
else if (_stricmp(BootType, "ReactOSSetup2") == 0)
{
// WinLdr-style boot
diff --git a/reactos/boot/freeldr/freeldr/freeldr_arch.rbuild b/reactos/boot/freeldr/freeldr/freeldr_arch.rbuild
index 3eaee52f364..b08d2585e9e 100644
--- a/reactos/boot/freeldr/freeldr/freeldr_arch.rbuild
+++ b/reactos/boot/freeldr/freeldr/freeldr_arch.rbuild
@@ -108,6 +108,13 @@
ntsetup.c
+ wlmemory.c
+
+
+
+
+ ntsetup.c
+ wlmemory.c
diff --git a/reactos/boot/freeldr/freeldr/freeldr_base.rbuild b/reactos/boot/freeldr/freeldr/freeldr_base.rbuild
index 2607147e067..16076bf18f4 100644
--- a/reactos/boot/freeldr/freeldr/freeldr_base.rbuild
+++ b/reactos/boot/freeldr/freeldr/freeldr_base.rbuild
@@ -77,6 +77,15 @@
wlregistry.c
+
+
+ conversion.c
+ peloader.c
+ winldr.c
+ wlmemory.c
+ wlregistry.c
+
+
freeldr.c
debug.c
version.c
diff --git a/reactos/boot/freeldr/freeldr/include/arch/amd64/amd64.h b/reactos/boot/freeldr/freeldr/include/arch/amd64/amd64.h
index 44554a1debb..ea7e3800742 100644
--- a/reactos/boot/freeldr/freeldr/include/arch/amd64/amd64.h
+++ b/reactos/boot/freeldr/freeldr/include/arch/amd64/amd64.h
@@ -21,6 +21,10 @@
#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 */
@@ -28,6 +32,7 @@
#define LMODE_DS 0x18
#define RMODE_CS 0x20 /* RMode code selector, base 0 limit 64k */
#define RMODE_DS 0x28 /* RMode data selector, base 0 limit 64k */
+#define CMODE_CS 0x30
#define VA_MASK 0x0000FFFFFFFFFFFFUL
@@ -53,35 +58,6 @@ typedef struct _PAGE_DIRECTORY_AMD64
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();
diff --git a/reactos/boot/freeldr/freeldr/include/arch/i386/i386.h b/reactos/boot/freeldr/freeldr/include/arch/i386/i386.h
index 96ecd7272e6..c58f5953848 100644
--- a/reactos/boot/freeldr/freeldr/include/arch/i386/i386.h
+++ b/reactos/boot/freeldr/freeldr/include/arch/i386/i386.h
@@ -21,6 +21,9 @@
#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_ */
diff --git a/reactos/boot/freeldr/freeldr/include/freeldr.h b/reactos/boot/freeldr/freeldr/include/freeldr.h
index 761af015769..ca8788da288 100644
--- a/reactos/boot/freeldr/freeldr/include/freeldr.h
+++ b/reactos/boot/freeldr/freeldr/include/freeldr.h
@@ -80,7 +80,6 @@
#include
#include
#include
-#include
#elif defined(_M_PPC)
#include
#elif defined(_M_ARM)
@@ -90,6 +89,7 @@
#elif defined(_M_AMD64)
#include
#include
+#include
#endif
/* misc files */
#include
diff --git a/reactos/boot/freeldr/freeldr/mm/mm.c b/reactos/boot/freeldr/freeldr/mm/mm.c
index 344ffe425be..36a04cc64f7 100644
--- a/reactos/boot/freeldr/freeldr/mm/mm.c
+++ b/reactos/boot/freeldr/freeldr/mm/mm.c
@@ -75,8 +75,8 @@ PVOID MmAllocateMemoryWithType(ULONG MemorySize, TYPE_OF_MEMORY MemoryType)
#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;
@@ -175,8 +175,8 @@ PVOID MmAllocateMemoryAtAddress(ULONG MemorySize, PVOID DesiredAddress, TYPE_OF_
#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;
diff --git a/reactos/boot/freeldr/freeldr/setupldr_main.rbuild b/reactos/boot/freeldr/freeldr/setupldr_main.rbuild
index 4d7e5714544..c89e46ba0c5 100644
--- a/reactos/boot/freeldr/freeldr/setupldr_main.rbuild
+++ b/reactos/boot/freeldr/freeldr/setupldr_main.rbuild
@@ -20,8 +20,13 @@
setupldr.c
-
- setupldr2.c
-
-
+
+ setupldr2.c
+
+
+
+
+ setupldr2.c
+
+
diff --git a/reactos/boot/freeldr/freeldr/windows/amd64/ntsetup.c b/reactos/boot/freeldr/freeldr/windows/amd64/ntsetup.c
new file mode 100644
index 00000000000..b6048e792d6
--- /dev/null
+++ b/reactos/boot/freeldr/freeldr/windows/amd64/ntsetup.c
@@ -0,0 +1,84 @@
+/*
+ * 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
+#include
+
+// 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);
+}
diff --git a/reactos/boot/freeldr/freeldr/windows/amd64/wlmemory.c b/reactos/boot/freeldr/freeldr/windows/amd64/wlmemory.c
new file mode 100644
index 00000000000..3e3288a682a
--- /dev/null
+++ b/reactos/boot/freeldr/freeldr/windows/amd64/wlmemory.c
@@ -0,0 +1,353 @@
+/*
+ * PROJECT: EFI Windows Loader
+ * LICENSE: GPL - See COPYING in the top level directory
+ * FILE: freeldr/amd64/wlmemory.c
+ * PURPOSE: Memory related routines
+ * PROGRAMMERS: Timo Kreuzer (timo.kreuzer@reactos.org)
+ */
+
+/* INCLUDES ***************************************************************/
+
+#include
+
+#include
+#include
+
+//extern ULONG LoaderPagesSpanned;
+
+#define HYPER_SPACE_ENTRY 0x1EE
+
+/* GLOBALS ***************************************************************/
+
+PHARDWARE_PTE PxeBase;
+//PHARDWARE_PTE HalPageTable;
+
+
+/* FUNCTIONS **************************************************************/
+
+BOOLEAN
+MempAllocatePageTables()
+{
+ DPRINTM(DPRINT_WINDOWS,">>> MempAllocatePageTables\n");
+
+ /* Allocate a page for the PML4 */
+ PxeBase = MmAllocateMemoryWithType(PAGE_SIZE, LoaderMemoryData);
+ if (!PxeBase)
+ {
+ DPRINTM(DPRINT_WINDOWS,"failed to allocate PML4\n");
+ return FALSE;
+ }
+
+ // FIXME: Physical PTEs = FirmwareTemporary ?
+
+ /* Zero the PML4 */
+ RtlZeroMemory(PxeBase, PAGE_SIZE);
+
+ /* The page tables are located at 0xfffff68000000000
+ * We create a recursive self mapping through all 4 levels at
+ * virtual address 0xfffff6fb7dbedf68 */
+ 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
+
+ DPRINTM(DPRINT_WINDOWS,">>> leave MempAllocatePageTables\n");
+
+ return TRUE;
+}
+
+PHARDWARE_PTE
+MempGetOrCreatePageDir(PHARDWARE_PTE PdeBase, ULONG Index)
+{
+ PHARDWARE_PTE SubDir;
+
+ if (!PdeBase)
+ return NULL;
+
+ if (!PdeBase[Index].Valid)
+ {
+ SubDir = MmAllocateMemoryWithType(PAGE_SIZE, LoaderMemoryData);
+ if (!SubDir)
+ return NULL;
+ RtlZeroMemory(SubDir, PAGE_SIZE);
+ PdeBase[Index].PageFrameNumber = PtrToPfn(SubDir);
+ PdeBase[Index].Valid = 1;
+ PdeBase[Index].Write = 1;
+ }
+ else
+ {
+ SubDir = (PVOID)((ULONG64)(PdeBase[Index].PageFrameNumber) * PAGE_SIZE);
+ }
+ return SubDir;
+}
+
+BOOLEAN
+MempMapSinglePage(ULONG64 VirtualAddress, ULONG64 PhysicalAddress)
+{
+ PHARDWARE_PTE PpeBase, PdeBase, PteBase;
+ ULONG Index;
+
+ PpeBase = MempGetOrCreatePageDir(PxeBase, VAtoPXI(VirtualAddress));
+ PdeBase = MempGetOrCreatePageDir(PpeBase, VAtoPPI(VirtualAddress));
+ PteBase = MempGetOrCreatePageDir(PdeBase, VAtoPDI(VirtualAddress));
+
+ if (!PteBase)
+ {
+ DPRINTM(DPRINT_WINDOWS,"!!!No Dir %p, %p, %p, %p\n", PxeBase, PpeBase, PdeBase, PteBase);
+ return FALSE;
+ }
+
+ Index = VAtoPTI(VirtualAddress);
+ if (PteBase[Index].Valid)
+ {
+ DPRINTM(DPRINT_WINDOWS,"!!!Already mapped %ld\n", Index);
+ return FALSE;
+ }
+
+ PteBase[Index].Valid = 1;
+ PteBase[Index].Write = 1;
+ PteBase[Index].PageFrameNumber = PhysicalAddress / PAGE_SIZE;
+
+ return TRUE;
+}
+
+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
+MempMapRangeOfPages(ULONG64 VirtualAddress, ULONG64 PhysicalAddress, ULONG cPages)
+{
+ ULONG i;
+
+ for (i = 0; i < cPages; i++)
+ {
+ 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,">>> 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)
+ {
+ 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)
+{
+ // DPRINTM(DPRINT_WINDOWS,">>> MempUnmapPage\n");
+}
+
+VOID
+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)
+{
+ /* Map the PCR page */
+ if (!MempMapSinglePage(KIP0PCRADDRESS, PcrBasePage * PAGE_SIZE))
+ {
+ DPRINTM(DPRINT_WINDOWS, "Could not map PCR @ %lx\n", PcrBasePage);
+ return FALSE;
+ }
+
+ /* Map KI_USER_SHARED_DATA */
+ 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;
+}
+
+VOID
+WinLdrSetupGdt(PVOID GdtBase, ULONG64 TssBase)
+{
+ 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);
+
+}
+
+VOID
+WinLdrSetupIdt(PVOID IdtBase)
+{
+ 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);
+
+}
+
+VOID
+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 */
+ __writecr3((ULONG64)PxeBase);
+
+ /* Get kernel mode address of gdt / idt */
+ GdtIdt = (PVOID)((ULONG64)GdtIdt + KSEG0_BASE);
+
+ /* Create gdt entries and load gdtr */
+ WinLdrSetupGdt(GdtIdt, Tss);
+
+ /* Copy old Idt and set idtr */
+ WinLdrSetupIdt((PVOID)((ULONG64)GdtIdt + 2048)); // HACK!
+
+ /* 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
+
+ /* Load TSR */
+ __ltr(KGDT_TSS);
+
+ DPRINTM(DPRINT_WINDOWS, "leave WinLdrSetProcessorContext\n");
+}
+
+VOID
+MempDump()
+{
+}
+
diff --git a/reactos/boot/freeldr/freeldr/windows/i386/wlmemory.c b/reactos/boot/freeldr/freeldr/windows/i386/wlmemory.c
new file mode 100644
index 00000000000..7800f3dd7f8
--- /dev/null
+++ b/reactos/boot/freeldr/freeldr/windows/i386/wlmemory.c
@@ -0,0 +1,560 @@
+/*
+ * PROJECT: EFI Windows Loader
+ * LICENSE: GPL - See COPYING in the top level directory
+ * FILE: freeldr/winldr/i386/wlmemory.c
+ * PURPOSE: Memory related routines
+ * PROGRAMMERS: Aleksey Bragin (aleksey@reactos.org)
+ */
+
+/* INCLUDES ***************************************************************/
+
+#include
+
+#include
+#include
+
+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
+
+// 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;
+
+/* 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
+MempUnmapPage(ULONG 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
+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;
+}
+
+BOOLEAN
+WinLdrMapSpecialPages(ULONG PcrBasePage)
+{
+
+ //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);
+
+ return TRUE;
+}
+
+
+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);
+
+ // 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");
+ }
+}
+
diff --git a/reactos/boot/freeldr/freeldr/windows/peloader.c b/reactos/boot/freeldr/freeldr/windows/peloader.c
index 912e53e476e..f4c731e7254 100644
--- a/reactos/boot/freeldr/freeldr/windows/peloader.c
+++ b/reactos/boot/freeldr/freeldr/windows/peloader.c
@@ -413,7 +413,7 @@ WinLdrLoadImage(IN PCHAR FileName,
if (SizeOfRawData < VirtualSize)
{
DPRINTM(DPRINT_PELOADER, "WinLdrLoadImage(): SORD %d < VS %d\n", SizeOfRawData, VirtualSize);
- RtlZeroMemory((PVOID)(SectionHeader->VirtualAddress + (ULONG)PhysicalBase + SizeOfRawData), VirtualSize - SizeOfRawData);
+ RtlZeroMemory((PVOID)(SectionHeader->VirtualAddress + (ULONG_PTR)PhysicalBase + SizeOfRawData), VirtualSize - SizeOfRawData);
}
SectionHeader++;
@@ -428,7 +428,7 @@ WinLdrLoadImage(IN PCHAR FileName,
/* Relocate the image, if it needs it */
- if (NtHeaders->OptionalHeader.ImageBase != (ULONG)VirtualBase)
+ if (NtHeaders->OptionalHeader.ImageBase != (ULONG_PTR)VirtualBase)
{
DPRINTM(DPRINT_PELOADER, "Relocating %p -> %p\n",
NtHeaders->OptionalHeader.ImageBase, VirtualBase);
@@ -535,7 +535,7 @@ WinLdrpBindImportName(IN OUT PLOADER_PARAMETER_BLOCK WinLdrBlock,
/* AddressOfData in thunk entry will become a virtual address (from relative) */
//DPRINTM(DPRINT_PELOADER, "WinLdrpBindImportName(): ThunkData->u1.AOD was %p\n", ThunkData->u1.AddressOfData);
ThunkData->u1.AddressOfData =
- (ULONG)RVA(ImageBase, ThunkData->u1.AddressOfData);
+ (ULONG_PTR)RVA(ImageBase, ThunkData->u1.AddressOfData);
//DPRINTM(DPRINT_PELOADER, "WinLdrpBindImportName(): ThunkData->u1.AOD became %p\n", ThunkData->u1.AddressOfData);
}
@@ -637,11 +637,11 @@ WinLdrpBindImportName(IN OUT PLOADER_PARAMETER_BLOCK WinLdrBlock,
FunctionTable = (PULONG)VaToPa(RVA(DllBase, ExportDirectory->AddressOfFunctions));
/* Save a pointer to the function */
- ThunkData->u1.Function = (ULONG)RVA(DllBase, FunctionTable[Ordinal]);
+ ThunkData->u1.Function = (ULONG_PTR)RVA(DllBase, FunctionTable[Ordinal]);
/* Is it a forwarder? (function pointer isn't within the export directory) */
- if (((ULONG)VaToPa((PVOID)ThunkData->u1.Function) > (ULONG)ExportDirectory) &&
- ((ULONG)VaToPa((PVOID)ThunkData->u1.Function) < ((ULONG)ExportDirectory + ExportSize)))
+ if (((ULONG_PTR)VaToPa((PVOID)ThunkData->u1.Function) > (ULONG_PTR)ExportDirectory) &&
+ ((ULONG_PTR)VaToPa((PVOID)ThunkData->u1.Function) < ((ULONG_PTR)ExportDirectory + ExportSize)))
{
PLDR_DATA_TABLE_ENTRY DataTableEntry;
CHAR ForwardDllName[255];
@@ -692,7 +692,7 @@ WinLdrpBindImportName(IN OUT PLOADER_PARAMETER_BLOCK WinLdrBlock,
ImportByName->Hint = 0;
/* And finally point ThunkData's AddressOfData to that structure */
- RefThunkData.u1.AddressOfData = (ULONG)ImportByName;
+ RefThunkData.u1.AddressOfData = (ULONG_PTR)ImportByName;
/* And recursively call ourselves */
Status = WinLdrpBindImportName(
diff --git a/reactos/boot/freeldr/freeldr/windows/winldr.c b/reactos/boot/freeldr/freeldr/windows/winldr.c
index c464a192a29..704035a4420 100644
--- a/reactos/boot/freeldr/freeldr/windows/winldr.c
+++ b/reactos/boot/freeldr/freeldr/windows/winldr.c
@@ -417,7 +417,7 @@ LoadAndBootWindows(PCSTR OperatingSystemName,
PCHAR PathSeparator;
PVOID NtosBase = NULL, HalBase = NULL, KdComBase = NULL;
BOOLEAN Status;
- ULONG SectionId;
+ ULONG_PTR SectionId;
PLOADER_PARAMETER_BLOCK LoaderBlock, LoaderBlockVA;
KERNEL_ENTRY_POINT KiSystemStartup;
PLDR_DATA_TABLE_ENTRY KernelDTE, HalDTE, KdComDTE = NULL;
diff --git a/reactos/boot/freeldr/freeldr/windows/wlmemory.c b/reactos/boot/freeldr/freeldr/windows/wlmemory.c
index 313413e5451..dd7b19ee208 100644
--- a/reactos/boot/freeldr/freeldr/windows/wlmemory.c
+++ b/reactos/boot/freeldr/freeldr/windows/wlmemory.c
@@ -13,15 +13,8 @@
#include
#include
-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 ", // ?
@@ -66,192 +59,31 @@ VOID
WinLdrRemoveDescriptor(IN PMEMORY_ALLOCATION_DESCRIPTOR Descriptor);
VOID
-WinLdrSetProcessorContext(PVOID GdtIdt, IN ULONG Pcr, IN ULONG Tss);
+WinLdrSetProcessorContext(PVOID GdtIdt, IN ULONG_PTR Pcr, IN ULONG_PTR Tss);
-// This is needed only for SetProcessorContext routine
-#pragma pack(2)
- typedef struct
- {
- USHORT Limit;
- ULONG Base;
- } GDTIDT;
-#pragma pack(4)
+BOOLEAN
+MempAllocatePageTables();
+
+BOOLEAN
+MempSetupPaging(IN ULONG StartPage,
+ IN ULONG NumberOfPages);
+
+BOOLEAN
+WinLdrMapSpecialPages(ULONG PcrBasePage);
+
+VOID
+MempUnmapPage(ULONG Page);
+
+VOID
+MempDump();
/* GLOBALS ***************************************************************/
-PHARDWARE_PTE PDE;
-PHARDWARE_PTE HalPageTable;
-
-PUCHAR PhysicalPageTablesBuffer;
-PUCHAR KernelPageTablesBuffer;
-ULONG PhysicalPageTables;
-ULONG KernelPageTables;
-
MEMORY_ALLOCATION_DESCRIPTOR *Mad;
ULONG MadCount = 0;
-
/* 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
MempDisablePages()
{
@@ -292,20 +124,7 @@ MempDisablePages()
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;
- }
- }
+ MempUnmapPage(Page);
}
}
}
@@ -379,45 +198,6 @@ MempAddMemoryBlock(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
}
}
-#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
-
BOOLEAN
WinLdrTurnOnPaging(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
ULONG PcrBasePage,
@@ -554,25 +334,8 @@ WinLdrTurnOnPaging(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
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);
+ /* Map stuff like PCR, KI_USER_SHARED_DATA and Apic */
+ WinLdrMapSpecialPages(PcrBasePage);
Tss = (PKTSS)(KSEG0_BASE | (TssBasePage << MM_PAGE_SHIFT));
@@ -585,42 +348,9 @@ WinLdrTurnOnPaging(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
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);
-
- for (j=0; j<8; j++)
- {
- DPRINTM(DPRINT_WINDOWS, "0x%08X ", PDE_Addr[i*8+j]);
- }
-
- DPRINTM(DPRINT_WINDOWS, "\n");
- }
- }
+ MempDump();
#endif
-
- // 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);
-
// Set processor context
WinLdrSetProcessorContext(GdtIdt, KIP0PCRADDRESS, KSEG0_BASE | (TssBasePage << MM_PAGE_SHIFT));
@@ -696,244 +426,3 @@ WinLdrInsertDescriptor(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
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);
-
- // 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
- */
-}
diff --git a/reactos/ntoskrnl/include/internal/arm/ke.h b/reactos/ntoskrnl/include/internal/arm/ke.h
index 8dace742c0d..14ab98e2e95 100644
--- a/reactos/ntoskrnl/include/internal/arm/ke.h
+++ b/reactos/ntoskrnl/include/internal/arm/ke.h
@@ -71,6 +71,23 @@ KeInvalidateTlbEntry(IN PVOID 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
diff --git a/reactos/ntoskrnl/include/internal/i386/ke.h b/reactos/ntoskrnl/include/internal/i386/ke.h
index 753ebbcc912..d7d8b72e206 100644
--- a/reactos/ntoskrnl/include/internal/i386/ke.h
+++ b/reactos/ntoskrnl/include/internal/i386/ke.h
@@ -77,6 +77,39 @@ KeInvalidateTlbEntry(IN PVOID 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(
diff --git a/reactos/ntoskrnl/include/internal/ke_x.h b/reactos/ntoskrnl/include/internal/ke_x.h
index b6f37e15548..e8945ff3b59 100644
--- a/reactos/ntoskrnl/include/internal/ke_x.h
+++ b/reactos/ntoskrnl/include/internal/ke_x.h
@@ -7,19 +7,6 @@
*/
#ifndef _M_ARM
-FORCEINLINE
-PRKTHREAD
-KeGetCurrentThread(VOID)
-{
-#ifdef _M_IX86
- /* Return the current thread */
- return ((PKIPCR)KeGetPcr())->PrcbData.CurrentThread;
-#else
- PKPRCB Prcb = KeGetCurrentPrcb();
- return Prcb->CurrentThread;
-#endif
-}
-
FORCEINLINE
UCHAR
KeGetPreviousMode(VOID)
@@ -29,23 +16,6 @@ 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
//
@@ -300,21 +270,6 @@ KiCheckDeferredReadyList(IN PKPRCB Prcb)
UNREFERENCED_PARAMETER(Prcb);
}
-FORCEINLINE
-VOID
-KiRundownThread(IN PKTHREAD Thread)
-{
-#if defined(_M_IX86) || defined(_M_AMD64)
- /* Check if this is the NPX Thread */
- if (KeGetCurrentPrcb()->NpxThread == Thread)
- {
- /* Clear it */
- KeGetCurrentPrcb()->NpxThread = NULL;
- Ke386FnInit();
- }
-#endif
-}
-
FORCEINLINE
VOID
KiRequestApcInterrupt(IN BOOLEAN NeedApc,
@@ -657,14 +612,6 @@ KiCheckDeferredReadyList(IN PKPRCB Prcb)
if (Prcb->DeferredReadyListHead.Next) KiProcessDeferredReadyList(Prcb);
}
-FORCEINLINE
-VOID
-KiRundownThread(IN PKTHREAD Thread)
-{
- /* Nothing to do */
- return;
-}
-
FORCEINLINE
VOID
KiRequestApcInterrupt(IN BOOLEAN NeedApc,
diff --git a/reactos/ntoskrnl/include/internal/powerpc/ke.h b/reactos/ntoskrnl/include/internal/powerpc/ke.h
index 578590e2914..ba47ffcbf02 100644
--- a/reactos/ntoskrnl/include/internal/powerpc/ke.h
+++ b/reactos/ntoskrnl/include/internal/powerpc/ke.h
@@ -77,6 +77,29 @@ FORCEINLINE struct _KPCR * NTHALAPI KeGetCurrentKPCR(
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