Merge from amd64 branch:

[NTOSKRNL]
44415 Move architecture specific inline functions in into the respective headers.

[FREELDR]
39639 Fix 2 small typos.
40247 Fix a number of ULONG / ULONG_PTR issues, remove LoadReactOSSetup2 for non-x86 builds.
40324 Fix switching from long mode to real mode, by jumping into a compatibility segment first.
43566 move wlmemory.c into arch specific folder. add wlmemory.c and ntsetup.c for amd64 (stubbed)
43574 Enable winldr style boot for amd64
43598 Split wlmemory into portable and arch specific code. Partly implement amd64 version.
43600 Fix a bug.
43601 Move definition of KIP0PCRADDRESS into arch specific header. Implement WinLdrSetupForNt for amd64. Fix mapping of PCR and KI_USER_SHARED_DATA. Don't enable paging again on amd64. Fix WinLdrSetProcessorContext to take a ULONG_PTR not ULONG for Pcr and Tss
43602 Round up to pages when updating LoaderPagesSpanned to avoid a bug when the last memory region is not mapped.
43604 Add MempIsPageMapped for debugging puposes. Map pages for kernel, too in amd64 version of MempSetupPaging.
43605 Include the intrinsics from the kernel. Set segement selectors
43757 Pass pointer to debugprint function to the kernel in LoaderBlock->u.I386.CommonDataArea. Comment out __lldt
43775 Fixed build with MinGW-w64 4.4.3
44065 Use LoaderMemoryData instead of LoaderSpecialMemory for page tables
44095 Use the kernel mode address for the gdt/idt
44123 Fix a typo
44144 Share some more inline functions between the kernel and freeldr. Use __ltr instead of Ke386SetTr. refactor KiInitializeTss. Update some Mm constants. Halfplement KeFlushEntireTb. Clean the mapping of page 0 in KiSystemStartup, as long as we don't clean mappings in freeldr. Fix a bug in KiPageFault, where ebp was used instead of rbp. Refactor MmArmInitSystem and related.
44205 Improve the code in wlmemory.c, no real functional change.
44426 remove unused variables.
44530 Don't include i386/ke.h from ntoskrnl.
44540 Detect if this is a amd64 CPU before attempting to boot. (Basil Gello)

svn path=/trunk/; revision=44669
This commit is contained in:
Timo Kreuzer 2009-12-20 13:30:35 +00:00
commit 114bcb2c56
20 changed files with 1312 additions and 651 deletions

View file

@ -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
///////////////////////////////////////////////////////////////////////////////

View file

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

View file

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

View file

@ -108,6 +108,13 @@
<if property="ARCH" value="i386">
<directory name="i386">
<file>ntsetup.c</file>
<file>wlmemory.c</file>
</directory>
</if>
<if property="ARCH" value="amd64">
<directory name="amd64">
<file>ntsetup.c</file>
<file>wlmemory.c</file>
</directory>
</if>
</directory>

View file

@ -77,6 +77,15 @@
<file>wlregistry.c</file>
</directory>
</if>
<if property="ARCH" value="amd64">
<directory name="windows">
<file>conversion.c</file>
<file>peloader.c</file>
<file>winldr.c</file>
<file>wlmemory.c</file>
<file>wlregistry.c</file>
</directory>
</if>
<file>freeldr.c</file>
<file>debug.c</file>
<file>version.c</file>

View file

@ -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();

View file

@ -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_ */

View file

@ -80,7 +80,6 @@
#include <arch/i386/machxbox.h>
#include <arch/i386/miscboot.h>
#include <internal/i386/intrin_i.h>
#include <internal/i386/ke.h>
#elif defined(_M_PPC)
#include <arch/powerpc/hardware.h>
#elif defined(_M_ARM)
@ -90,6 +89,7 @@
#elif defined(_M_AMD64)
#include <arch/amd64/hardware.h>
#include <arch/amd64/machpc.h>
#include <internal/amd64/intrin_i.h>
#endif
/* misc files */
#include <keycodes.h>

View file

@ -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;

View file

@ -20,8 +20,13 @@
<file>setupldr.c</file>
</directory>
<if property="ARCH" value="i386">
<directory name="windows">
<file>setupldr2.c</file>
</directory>
</if>
<directory name="windows">
<file>setupldr2.c</file>
</directory>
</if>
<if property="ARCH" value="amd64">
<directory name="windows">
<file>setupldr2.c</file>
</directory>
</if>
</module>

View file

@ -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 <freeldr.h>
#include <debug.h>
// this is needed for new IDT filling
#if 0
extern ULONG_PTR i386DivideByZero;
extern ULONG_PTR i386DebugException;
extern ULONG_PTR i386NMIException;
extern ULONG_PTR i386Breakpoint;
extern ULONG_PTR i386Overflow;
extern ULONG_PTR i386BoundException;
extern ULONG_PTR i386InvalidOpcode;
extern ULONG_PTR i386FPUNotAvailable;
extern ULONG_PTR i386DoubleFault;
extern ULONG_PTR i386CoprocessorSegment;
extern ULONG_PTR i386InvalidTSS;
extern ULONG_PTR i386SegmentNotPresent;
extern ULONG_PTR i386StackException;
extern ULONG_PTR i386GeneralProtectionFault;
extern ULONG_PTR i386PageFault; // exc 14
extern ULONG_PTR i386CoprocessorError; // exc 16
extern ULONG_PTR i386AlignmentCheck; // exc 17
#endif
/* FUNCTIONS **************************************************************/
// Last step before going virtual
void WinLdrSetupForNt(PLOADER_PARAMETER_BLOCK LoaderBlock,
PVOID *GdtIdt,
ULONG *PcrBasePage,
ULONG *TssBasePage)
{
ULONG TssSize;
ULONG TssPages;
ULONG_PTR Pcr = 0;
ULONG_PTR Tss = 0;
ULONG BlockSize, NumPages;
LoaderBlock->u.I386.CommonDataArea = (PVOID)DbgPrint; // HACK
LoaderBlock->u.I386.MachineType = MACHINE_TYPE_ISA;
/* Allocate 2 pages for PCR */
Pcr = (ULONG_PTR)MmAllocateMemoryWithType(2 * MM_PAGE_SIZE, LoaderStartupPcrPage);
*PcrBasePage = Pcr >> MM_PAGE_SHIFT;
RtlZeroMemory((PVOID)Pcr, 2 * MM_PAGE_SIZE);
if (Pcr == 0)
{
UiMessageBox("Can't allocate PCR\n");
return;
}
/* Allocate TSS */
TssSize = (sizeof(KTSS) + MM_PAGE_SIZE) & ~(MM_PAGE_SIZE - 1);
TssPages = TssSize / MM_PAGE_SIZE;
Tss = (ULONG_PTR)MmAllocateMemoryWithType(TssSize, LoaderMemoryData);
*TssBasePage = Tss >> MM_PAGE_SHIFT;
/* Allocate space for new GDT + IDT */
BlockSize = NUM_GDT*sizeof(KGDTENTRY) + NUM_IDT*sizeof(KIDTENTRY);//FIXME: Use GDT/IDT limits here?
NumPages = (BlockSize + MM_PAGE_SIZE - 1) >> MM_PAGE_SHIFT;
*GdtIdt = (PKGDTENTRY)MmAllocateMemoryWithType(NumPages * MM_PAGE_SIZE, LoaderMemoryData);
if (*GdtIdt == NULL)
{
UiMessageBox("Can't allocate pages for GDT+IDT!\n");
return;
}
/* Zero newly prepared GDT+IDT */
RtlZeroMemory(*GdtIdt, NumPages << MM_PAGE_SHIFT);
}

View file

@ -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 <freeldr.h>
#include <ndk/asm.h>
#include <debug.h>
//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()
{
}

View file

@ -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 <freeldr.h>
#include <ndk/asm.h>
#include <debug.h>
extern ULONG TotalNLSSize;
extern ULONG LoaderPagesSpanned;
// This is needed because headers define wrong one for ReactOS
#undef KIP0PCRADDRESS
#define KIP0PCRADDRESS 0xffdff000
#define HYPER_SPACE_ENTRY 0x300
// 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");
}
}

View file

@ -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(

View file

@ -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;

View file

@ -13,15 +13,8 @@
#include <ndk/asm.h>
#include <debug.h>
extern ULONG TotalNLSSize;
extern ULONG LoaderPagesSpanned;
// This is needed because headers define wrong one for ReactOS
#undef KIP0PCRADDRESS
#define KIP0PCRADDRESS 0xffdff000
#define HYPER_SPACE_ENTRY 0x300
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
*/
}

View file

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

View file

@ -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(

View file

@ -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,

View file

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