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