mirror of
https://github.com/reactos/reactos.git
synced 2025-04-25 16:10:29 +00:00
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:
commit
114bcb2c56
20 changed files with 1312 additions and 651 deletions
|
@ -20,6 +20,10 @@ RealEntryPoint:
|
||||||
mov gs, ax
|
mov gs, ax
|
||||||
mov ss, ax
|
mov ss, ax
|
||||||
|
|
||||||
|
/* checkPoint Charlie - where it all began... */
|
||||||
|
mov si, offset _CheckPoint0
|
||||||
|
call writestr
|
||||||
|
|
||||||
/* Setup a real mode stack */
|
/* Setup a real mode stack */
|
||||||
mov sp, stack16
|
mov sp, stack16
|
||||||
|
|
||||||
|
@ -41,17 +45,88 @@ RealEntryPoint:
|
||||||
|
|
||||||
call x86_16_EnableA20
|
call x86_16_EnableA20
|
||||||
|
|
||||||
|
/* checkPoint Charlie - where it all began... */
|
||||||
|
mov si, offset _CheckPoint1
|
||||||
|
call writestr
|
||||||
|
|
||||||
call x86_16_BuildPageTables
|
call x86_16_BuildPageTables
|
||||||
|
|
||||||
/* Switch to long mode */
|
/* checkPoint Charlie - where it all began... */
|
||||||
|
mov si, offset _CheckPoint2
|
||||||
|
call writestr
|
||||||
|
|
||||||
|
/* Check if CPU supports CPUID */
|
||||||
|
|
||||||
|
pushfd
|
||||||
|
pop eax
|
||||||
|
mov ebx, eax
|
||||||
|
xor eax, 0x00200000
|
||||||
|
push eax
|
||||||
|
popfd
|
||||||
|
pushfd
|
||||||
|
pop eax
|
||||||
|
cmp eax,ebx
|
||||||
|
jz NO_CPUID_SUPPORT_DETECTED
|
||||||
|
|
||||||
|
/* CPUID support detected - getting the PAE/PGE */
|
||||||
|
|
||||||
|
mov eax,1 // Fn0000_0001 - PAE in EDX[6]
|
||||||
|
cpuid
|
||||||
|
xor eax,eax
|
||||||
|
and edx,0x00a0
|
||||||
|
test edx,edx // are PAE and PGE bits set?
|
||||||
|
jz NO_X64_SUPPORT_DETECTED
|
||||||
|
|
||||||
|
/* PAE and PGE are here */
|
||||||
|
|
||||||
|
xor edx, edx
|
||||||
|
mov eax, 0x80000001
|
||||||
|
cpuid
|
||||||
|
and edx, 0x20000000
|
||||||
|
test edx,edx
|
||||||
|
jz NO_X64_SUPPORT_DETECTED
|
||||||
|
|
||||||
|
/* X64 Processor */
|
||||||
|
|
||||||
|
/* checkPoint Charlie - where it all began... */
|
||||||
|
mov si, offset _CheckPoint3
|
||||||
|
call writestr
|
||||||
|
|
||||||
|
jmp _switch64
|
||||||
|
|
||||||
|
NO_X64_SUPPORT_DETECTED:
|
||||||
|
mov si, offset _NotAnX64Processor // Loading message
|
||||||
|
call writestr
|
||||||
|
jmp _fail
|
||||||
|
|
||||||
|
NO_CPUID_SUPPORT_DETECTED:
|
||||||
|
mov si, offset _NoCPUIDSupport // Loading message
|
||||||
|
call writestr
|
||||||
|
|
||||||
|
_fail:
|
||||||
|
jmp _fail
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
|
||||||
|
_switch64:
|
||||||
call x86_16_SwitchToLong
|
call x86_16_SwitchToLong
|
||||||
|
|
||||||
.code64
|
.code64
|
||||||
|
|
||||||
|
// mov ax, LMODE_DS
|
||||||
|
// mov ds, ax
|
||||||
|
// mov word ptr ds:[0xb8000], 0x0e00 + '1'
|
||||||
|
|
||||||
/* GO! */
|
/* GO! */
|
||||||
xor rcx, rcx
|
xor rcx, rcx
|
||||||
call _BootMain
|
call _BootMain
|
||||||
|
|
||||||
|
/* Checkpoint */
|
||||||
|
// mov ax, LMODE_DS
|
||||||
|
// mov ds, ax
|
||||||
|
// mov word ptr ds:[0xb8002], 0x0e02 + '2'
|
||||||
|
|
||||||
|
|
||||||
/* Return into real mode */
|
/* Return into real mode */
|
||||||
call x86_64_SwitchToReal
|
call x86_64_SwitchToReal
|
||||||
.code16
|
.code16
|
||||||
|
@ -90,7 +165,6 @@ x86_16_EnableA20:
|
||||||
popa
|
popa
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We define 512 2MB pages at the start of memory, so we can access the first
|
* We define 512 2MB pages at the start of memory, so we can access the first
|
||||||
* 1 GB as if paging was disabled
|
* 1 GB as if paging was disabled
|
||||||
|
@ -143,9 +217,39 @@ Bpt2:
|
||||||
popa
|
popa
|
||||||
ret
|
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
|
//.global x86_16_SwitchToLong
|
||||||
x86_16_SwitchToLong:
|
x86_16_SwitchToLong:
|
||||||
|
|
||||||
cli
|
cli
|
||||||
|
|
||||||
xor ax,ax
|
xor ax,ax
|
||||||
|
@ -190,8 +294,7 @@ LongCat:
|
||||||
/* Now return in long mode! */
|
/* Now return in long mode! */
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
/** 64 Bit functions **********************************************************/
|
||||||
/** 64 But functions **********************************************************/
|
|
||||||
.code64
|
.code64
|
||||||
|
|
||||||
.global x86_64_SwitchToReal
|
.global x86_64_SwitchToReal
|
||||||
|
@ -203,25 +306,40 @@ x86_64_SwitchToReal:
|
||||||
/* Save 64-bit stack pointer */
|
/* Save 64-bit stack pointer */
|
||||||
mov stack64, rsp
|
mov stack64, rsp
|
||||||
|
|
||||||
/* Step 1 - deactivate long mode, by disabling paging */
|
// mov ax, LMODE_DS
|
||||||
mov rax, cr0
|
// mov ds, ax
|
||||||
and rax, 0x000000007fffffff //~0x80000000
|
// mov word ptr ds:[0xb8004], 0x0e00 + '3'
|
||||||
mov cr0, rax
|
|
||||||
|
/* 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 */
|
/* Step 2 - disable long mode in EFER MSR */
|
||||||
mov rcx, 0xC0000080 // Specify EFER MSR
|
// mov ecx, 0xC0000080 // Specify EFER MSR
|
||||||
rdmsr
|
// rdmsr
|
||||||
and eax, ~0x00000100 // Disable EFER.LME
|
// and eax, ~0x00000100 // Disable EFER.LME
|
||||||
wrmsr
|
// wrmsr
|
||||||
|
|
||||||
.code32
|
/* Step 3 - jump to 16-bit segment to set the limit correctly */
|
||||||
/* jmp to 16-bit segment to set the limit correctly */
|
|
||||||
jmp RMODE_CS: offset SwitchToReal2
|
jmp RMODE_CS: offset SwitchToReal2
|
||||||
|
|
||||||
SwitchToReal2:
|
SwitchToReal2:
|
||||||
.code16
|
.code16
|
||||||
|
|
||||||
/* Step 3 - Disable Protected Mode */
|
/* Step 4 - Disable Protected Mode */
|
||||||
mov eax, cr0
|
mov eax, cr0
|
||||||
and eax, ~0x00000001
|
and eax, ~0x00000001
|
||||||
mov cr0, eax
|
mov cr0, eax
|
||||||
|
@ -230,6 +348,11 @@ SwitchToReal2:
|
||||||
jmp 0:offset BeReal
|
jmp 0:offset BeReal
|
||||||
|
|
||||||
BeReal:
|
BeReal:
|
||||||
|
/* Checkpoint */
|
||||||
|
// mov ax, 0xb800
|
||||||
|
// mov fs, ax
|
||||||
|
// mov word ptr fs:[0x0C], 0x0e00 + '7'
|
||||||
|
|
||||||
/* Restore segment registers */
|
/* Restore segment registers */
|
||||||
mov ax, 0
|
mov ax, 0
|
||||||
mov ds, ax
|
mov ds, ax
|
||||||
|
@ -238,7 +361,7 @@ BeReal:
|
||||||
mov gs, ax
|
mov gs, ax
|
||||||
mov ss, ax
|
mov ss, ax
|
||||||
|
|
||||||
/* Rstore 16 bit stack */
|
/* Restore 16 bit stack */
|
||||||
mov sp, stack16
|
mov sp, stack16
|
||||||
|
|
||||||
// lidt rmode_idtptr /* Load IDTR with real mode value */
|
// lidt rmode_idtptr /* Load IDTR with real mode value */
|
||||||
|
@ -266,17 +389,19 @@ stack64:
|
||||||
code64ret:
|
code64ret:
|
||||||
.quad 0
|
.quad 0
|
||||||
|
|
||||||
|
.p2align 2
|
||||||
gdt:
|
gdt:
|
||||||
.quad 0x0000000000000000 /* 00: NULL descriptor */
|
.quad 0x0000000000000000 /* 00: NULL descriptor */
|
||||||
.quad 0x0000000000000000 /* 08: */
|
.quad 0x0000000000000000 /* 08: */
|
||||||
.quad 0x0020980000000000 /* 10: long mode cs */
|
.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, 0x9E00, 0x0000 /* 16-bit real mode CS */
|
||||||
.word 0xFFFF, 0x0000, 0x9200, 0x0000 /* 16-bit real mode DS */
|
.word 0xFFFF, 0x0000, 0x9200, 0x0000 /* 16-bit real mode DS */
|
||||||
|
.quad 0x00CF9B000000FFFF /* 30: compat mode cs */
|
||||||
|
|
||||||
/* GDT table pointer */
|
/* GDT table pointer */
|
||||||
gdtptr:
|
gdtptr:
|
||||||
.word 0x2f /* Limit */
|
.word 0x37 /* Limit */
|
||||||
.long gdt /* Base Address */
|
.long gdt /* Base Address */
|
||||||
|
|
||||||
|
|
||||||
|
@ -288,6 +413,36 @@ _BootDrive:
|
||||||
_BootPartition:
|
_BootPartition:
|
||||||
.long 0
|
.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
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
|
@ -155,7 +155,7 @@ GetFatEntry16:
|
||||||
add bx,dx
|
add bx,dx
|
||||||
mov es,bx
|
mov es,bx
|
||||||
mov bx,ax // Restore FAT entry offset
|
mov bx,ax // Restore FAT entry offset
|
||||||
mov ax, [es:bx] // Get FAT entry
|
mov ax, es:[bx] // Get FAT entry
|
||||||
|
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
@ -173,7 +173,7 @@ GetFatEntry12:
|
||||||
mov bx,0x7000
|
mov bx,0x7000
|
||||||
mov es,bx
|
mov es,bx
|
||||||
mov bx,ax // Put FAT entry offset into 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
|
pop cx // Get cluster number from stack
|
||||||
and cx,1
|
and cx,1
|
||||||
jz UseLow12Bits
|
jz UseLow12Bits
|
||||||
|
|
|
@ -233,7 +233,7 @@ VOID RunLoader(VOID)
|
||||||
// to have different install methods, etc.
|
// to have different install methods, etc.
|
||||||
LoadReactOSSetup();
|
LoadReactOSSetup();
|
||||||
}
|
}
|
||||||
#ifdef __i386__
|
#if defined(__i386__) || defined(__x86_64__)
|
||||||
else if (_stricmp(BootType, "ReactOSSetup2") == 0)
|
else if (_stricmp(BootType, "ReactOSSetup2") == 0)
|
||||||
{
|
{
|
||||||
// WinLdr-style boot
|
// WinLdr-style boot
|
||||||
|
|
|
@ -108,6 +108,13 @@
|
||||||
<if property="ARCH" value="i386">
|
<if property="ARCH" value="i386">
|
||||||
<directory name="i386">
|
<directory name="i386">
|
||||||
<file>ntsetup.c</file>
|
<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>
|
</directory>
|
||||||
</if>
|
</if>
|
||||||
</directory>
|
</directory>
|
||||||
|
|
|
@ -77,6 +77,15 @@
|
||||||
<file>wlregistry.c</file>
|
<file>wlregistry.c</file>
|
||||||
</directory>
|
</directory>
|
||||||
</if>
|
</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>freeldr.c</file>
|
||||||
<file>debug.c</file>
|
<file>debug.c</file>
|
||||||
<file>version.c</file>
|
<file>version.c</file>
|
||||||
|
|
|
@ -21,6 +21,10 @@
|
||||||
#ifndef __AMD64_AMD64_H_
|
#ifndef __AMD64_AMD64_H_
|
||||||
#define __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 */
|
#define STACK64ADDR 0x74000 /* The 64-bit stack top will be at 0x74000 */
|
||||||
|
|
||||||
/* Long mode selectors */
|
/* Long mode selectors */
|
||||||
|
@ -28,6 +32,7 @@
|
||||||
#define LMODE_DS 0x18
|
#define LMODE_DS 0x18
|
||||||
#define RMODE_CS 0x20 /* RMode code selector, base 0 limit 64k */
|
#define RMODE_CS 0x20 /* RMode code selector, base 0 limit 64k */
|
||||||
#define RMODE_DS 0x28 /* RMode data selector, base 0 limit 64k */
|
#define RMODE_DS 0x28 /* RMode data selector, base 0 limit 64k */
|
||||||
|
#define CMODE_CS 0x30
|
||||||
|
|
||||||
#define VA_MASK 0x0000FFFFFFFFFFFFUL
|
#define VA_MASK 0x0000FFFFFFFFFFFFUL
|
||||||
|
|
||||||
|
@ -53,35 +58,6 @@ typedef struct _PAGE_DIRECTORY_AMD64
|
||||||
HARDWARE_PTE Pde[512];
|
HARDWARE_PTE Pde[512];
|
||||||
} PAGE_DIRECTORY_AMD64, *PPAGE_DIRECTORY_AMD64;
|
} 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();
|
VOID FrLdrSetupGdtIdt();
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,9 @@
|
||||||
#ifndef __I386_I386_H_
|
#ifndef __I386_I386_H_
|
||||||
#define __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_ */
|
#endif /* __I386_I386_H_ */
|
||||||
|
|
|
@ -80,7 +80,6 @@
|
||||||
#include <arch/i386/machxbox.h>
|
#include <arch/i386/machxbox.h>
|
||||||
#include <arch/i386/miscboot.h>
|
#include <arch/i386/miscboot.h>
|
||||||
#include <internal/i386/intrin_i.h>
|
#include <internal/i386/intrin_i.h>
|
||||||
#include <internal/i386/ke.h>
|
|
||||||
#elif defined(_M_PPC)
|
#elif defined(_M_PPC)
|
||||||
#include <arch/powerpc/hardware.h>
|
#include <arch/powerpc/hardware.h>
|
||||||
#elif defined(_M_ARM)
|
#elif defined(_M_ARM)
|
||||||
|
@ -90,6 +89,7 @@
|
||||||
#elif defined(_M_AMD64)
|
#elif defined(_M_AMD64)
|
||||||
#include <arch/amd64/hardware.h>
|
#include <arch/amd64/hardware.h>
|
||||||
#include <arch/amd64/machpc.h>
|
#include <arch/amd64/machpc.h>
|
||||||
|
#include <internal/amd64/intrin_i.h>
|
||||||
#endif
|
#endif
|
||||||
/* misc files */
|
/* misc files */
|
||||||
#include <keycodes.h>
|
#include <keycodes.h>
|
||||||
|
|
|
@ -75,8 +75,8 @@ PVOID MmAllocateMemoryWithType(ULONG MemorySize, TYPE_OF_MEMORY MemoryType)
|
||||||
#endif // DBG
|
#endif // DBG
|
||||||
|
|
||||||
// Update LoaderPagesSpanned count
|
// Update LoaderPagesSpanned count
|
||||||
if ((((ULONG_PTR)MemPointer + MemorySize) >> PAGE_SHIFT) > LoaderPagesSpanned)
|
if ((((ULONG_PTR)MemPointer + MemorySize + PAGE_SIZE - 1) >> PAGE_SHIFT) > LoaderPagesSpanned)
|
||||||
LoaderPagesSpanned = (((ULONG_PTR)MemPointer + MemorySize) >> PAGE_SHIFT);
|
LoaderPagesSpanned = (((ULONG_PTR)MemPointer + MemorySize + PAGE_SIZE - 1) >> PAGE_SHIFT);
|
||||||
|
|
||||||
// Now return the pointer
|
// Now return the pointer
|
||||||
return MemPointer;
|
return MemPointer;
|
||||||
|
@ -175,8 +175,8 @@ PVOID MmAllocateMemoryAtAddress(ULONG MemorySize, PVOID DesiredAddress, TYPE_OF_
|
||||||
#endif // DBG
|
#endif // DBG
|
||||||
|
|
||||||
// Update LoaderPagesSpanned count
|
// Update LoaderPagesSpanned count
|
||||||
if ((((ULONG_PTR)MemPointer + MemorySize) >> PAGE_SHIFT) > LoaderPagesSpanned)
|
if ((((ULONG_PTR)MemPointer + MemorySize + PAGE_SIZE - 1) >> PAGE_SHIFT) > LoaderPagesSpanned)
|
||||||
LoaderPagesSpanned = (((ULONG_PTR)MemPointer + MemorySize) >> PAGE_SHIFT);
|
LoaderPagesSpanned = (((ULONG_PTR)MemPointer + MemorySize + PAGE_SIZE - 1) >> PAGE_SHIFT);
|
||||||
|
|
||||||
// Now return the pointer
|
// Now return the pointer
|
||||||
return MemPointer;
|
return MemPointer;
|
||||||
|
|
|
@ -20,8 +20,13 @@
|
||||||
<file>setupldr.c</file>
|
<file>setupldr.c</file>
|
||||||
</directory>
|
</directory>
|
||||||
<if property="ARCH" value="i386">
|
<if property="ARCH" value="i386">
|
||||||
<directory name="windows">
|
<directory name="windows">
|
||||||
<file>setupldr2.c</file>
|
<file>setupldr2.c</file>
|
||||||
</directory>
|
</directory>
|
||||||
</if>
|
</if>
|
||||||
|
<if property="ARCH" value="amd64">
|
||||||
|
<directory name="windows">
|
||||||
|
<file>setupldr2.c</file>
|
||||||
|
</directory>
|
||||||
|
</if>
|
||||||
</module>
|
</module>
|
||||||
|
|
84
reactos/boot/freeldr/freeldr/windows/amd64/ntsetup.c
Normal file
84
reactos/boot/freeldr/freeldr/windows/amd64/ntsetup.c
Normal 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);
|
||||||
|
}
|
353
reactos/boot/freeldr/freeldr/windows/amd64/wlmemory.c
Normal file
353
reactos/boot/freeldr/freeldr/windows/amd64/wlmemory.c
Normal 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()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
560
reactos/boot/freeldr/freeldr/windows/i386/wlmemory.c
Normal file
560
reactos/boot/freeldr/freeldr/windows/i386/wlmemory.c
Normal 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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -413,7 +413,7 @@ WinLdrLoadImage(IN PCHAR FileName,
|
||||||
if (SizeOfRawData < VirtualSize)
|
if (SizeOfRawData < VirtualSize)
|
||||||
{
|
{
|
||||||
DPRINTM(DPRINT_PELOADER, "WinLdrLoadImage(): SORD %d < VS %d\n", 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++;
|
SectionHeader++;
|
||||||
|
@ -428,7 +428,7 @@ WinLdrLoadImage(IN PCHAR FileName,
|
||||||
|
|
||||||
|
|
||||||
/* Relocate the image, if it needs it */
|
/* 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",
|
DPRINTM(DPRINT_PELOADER, "Relocating %p -> %p\n",
|
||||||
NtHeaders->OptionalHeader.ImageBase, VirtualBase);
|
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) */
|
/* AddressOfData in thunk entry will become a virtual address (from relative) */
|
||||||
//DPRINTM(DPRINT_PELOADER, "WinLdrpBindImportName(): ThunkData->u1.AOD was %p\n", ThunkData->u1.AddressOfData);
|
//DPRINTM(DPRINT_PELOADER, "WinLdrpBindImportName(): ThunkData->u1.AOD was %p\n", ThunkData->u1.AddressOfData);
|
||||||
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);
|
//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));
|
FunctionTable = (PULONG)VaToPa(RVA(DllBase, ExportDirectory->AddressOfFunctions));
|
||||||
|
|
||||||
/* Save a pointer to the function */
|
/* 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) */
|
/* Is it a forwarder? (function pointer isn't within the export directory) */
|
||||||
if (((ULONG)VaToPa((PVOID)ThunkData->u1.Function) > (ULONG)ExportDirectory) &&
|
if (((ULONG_PTR)VaToPa((PVOID)ThunkData->u1.Function) > (ULONG_PTR)ExportDirectory) &&
|
||||||
((ULONG)VaToPa((PVOID)ThunkData->u1.Function) < ((ULONG)ExportDirectory + ExportSize)))
|
((ULONG_PTR)VaToPa((PVOID)ThunkData->u1.Function) < ((ULONG_PTR)ExportDirectory + ExportSize)))
|
||||||
{
|
{
|
||||||
PLDR_DATA_TABLE_ENTRY DataTableEntry;
|
PLDR_DATA_TABLE_ENTRY DataTableEntry;
|
||||||
CHAR ForwardDllName[255];
|
CHAR ForwardDllName[255];
|
||||||
|
@ -692,7 +692,7 @@ WinLdrpBindImportName(IN OUT PLOADER_PARAMETER_BLOCK WinLdrBlock,
|
||||||
ImportByName->Hint = 0;
|
ImportByName->Hint = 0;
|
||||||
|
|
||||||
/* And finally point ThunkData's AddressOfData to that structure */
|
/* And finally point ThunkData's AddressOfData to that structure */
|
||||||
RefThunkData.u1.AddressOfData = (ULONG)ImportByName;
|
RefThunkData.u1.AddressOfData = (ULONG_PTR)ImportByName;
|
||||||
|
|
||||||
/* And recursively call ourselves */
|
/* And recursively call ourselves */
|
||||||
Status = WinLdrpBindImportName(
|
Status = WinLdrpBindImportName(
|
||||||
|
|
|
@ -417,7 +417,7 @@ LoadAndBootWindows(PCSTR OperatingSystemName,
|
||||||
PCHAR PathSeparator;
|
PCHAR PathSeparator;
|
||||||
PVOID NtosBase = NULL, HalBase = NULL, KdComBase = NULL;
|
PVOID NtosBase = NULL, HalBase = NULL, KdComBase = NULL;
|
||||||
BOOLEAN Status;
|
BOOLEAN Status;
|
||||||
ULONG SectionId;
|
ULONG_PTR SectionId;
|
||||||
PLOADER_PARAMETER_BLOCK LoaderBlock, LoaderBlockVA;
|
PLOADER_PARAMETER_BLOCK LoaderBlock, LoaderBlockVA;
|
||||||
KERNEL_ENTRY_POINT KiSystemStartup;
|
KERNEL_ENTRY_POINT KiSystemStartup;
|
||||||
PLDR_DATA_TABLE_ENTRY KernelDTE, HalDTE, KdComDTE = NULL;
|
PLDR_DATA_TABLE_ENTRY KernelDTE, HalDTE, KdComDTE = NULL;
|
||||||
|
|
|
@ -13,15 +13,8 @@
|
||||||
#include <ndk/asm.h>
|
#include <ndk/asm.h>
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
|
||||||
extern ULONG TotalNLSSize;
|
|
||||||
extern ULONG LoaderPagesSpanned;
|
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[] = {
|
PCHAR MemTypeDesc[] = {
|
||||||
"ExceptionBlock ", // ?
|
"ExceptionBlock ", // ?
|
||||||
"SystemBlock ", // ?
|
"SystemBlock ", // ?
|
||||||
|
@ -66,192 +59,31 @@ VOID
|
||||||
WinLdrRemoveDescriptor(IN PMEMORY_ALLOCATION_DESCRIPTOR Descriptor);
|
WinLdrRemoveDescriptor(IN PMEMORY_ALLOCATION_DESCRIPTOR Descriptor);
|
||||||
|
|
||||||
VOID
|
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
|
BOOLEAN
|
||||||
#pragma pack(2)
|
MempAllocatePageTables();
|
||||||
typedef struct
|
|
||||||
{
|
BOOLEAN
|
||||||
USHORT Limit;
|
MempSetupPaging(IN ULONG StartPage,
|
||||||
ULONG Base;
|
IN ULONG NumberOfPages);
|
||||||
} GDTIDT;
|
|
||||||
#pragma pack(4)
|
BOOLEAN
|
||||||
|
WinLdrMapSpecialPages(ULONG PcrBasePage);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
MempUnmapPage(ULONG Page);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
MempDump();
|
||||||
|
|
||||||
/* GLOBALS ***************************************************************/
|
/* GLOBALS ***************************************************************/
|
||||||
|
|
||||||
PHARDWARE_PTE PDE;
|
|
||||||
PHARDWARE_PTE HalPageTable;
|
|
||||||
|
|
||||||
PUCHAR PhysicalPageTablesBuffer;
|
|
||||||
PUCHAR KernelPageTablesBuffer;
|
|
||||||
ULONG PhysicalPageTables;
|
|
||||||
ULONG KernelPageTables;
|
|
||||||
|
|
||||||
MEMORY_ALLOCATION_DESCRIPTOR *Mad;
|
MEMORY_ALLOCATION_DESCRIPTOR *Mad;
|
||||||
ULONG MadCount = 0;
|
ULONG MadCount = 0;
|
||||||
|
|
||||||
|
|
||||||
/* FUNCTIONS **************************************************************/
|
/* 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
|
VOID
|
||||||
MempDisablePages()
|
MempDisablePages()
|
||||||
{
|
{
|
||||||
|
@ -292,20 +124,7 @@ MempDisablePages()
|
||||||
|
|
||||||
for (Page = StartPage; Page < EndPage; Page++)
|
for (Page = StartPage; Page < EndPage; Page++)
|
||||||
{
|
{
|
||||||
PHARDWARE_PTE KernelPT;
|
MempUnmapPage(Page);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
BOOLEAN
|
||||||
WinLdrTurnOnPaging(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
|
WinLdrTurnOnPaging(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
|
||||||
ULONG PcrBasePage,
|
ULONG PcrBasePage,
|
||||||
|
@ -554,25 +334,8 @@ WinLdrTurnOnPaging(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
|
||||||
return;
|
return;
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
//VideoDisplayString(L"Hello from VGA, going into the kernel\n");
|
/* Map stuff like PCR, KI_USER_SHARED_DATA and Apic */
|
||||||
DPRINTM(DPRINT_WINDOWS, "HalPageTable: 0x%X\n", HalPageTable);
|
WinLdrMapSpecialPages(PcrBasePage);
|
||||||
|
|
||||||
// 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);
|
|
||||||
|
|
||||||
Tss = (PKTSS)(KSEG0_BASE | (TssBasePage << MM_PAGE_SHIFT));
|
Tss = (PKTSS)(KSEG0_BASE | (TssBasePage << MM_PAGE_SHIFT));
|
||||||
|
|
||||||
|
@ -585,42 +348,9 @@ WinLdrTurnOnPaging(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
|
||||||
List_PaToVa(&LoaderBlock->MemoryDescriptorListHead);
|
List_PaToVa(&LoaderBlock->MemoryDescriptorListHead);
|
||||||
|
|
||||||
#if DBG
|
#if DBG
|
||||||
{
|
MempDump();
|
||||||
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");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
#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
|
// Set processor context
|
||||||
WinLdrSetProcessorContext(GdtIdt, KIP0PCRADDRESS, KSEG0_BASE | (TssBasePage << MM_PAGE_SHIFT));
|
WinLdrSetProcessorContext(GdtIdt, KIP0PCRADDRESS, KSEG0_BASE | (TssBasePage << MM_PAGE_SHIFT));
|
||||||
|
|
||||||
|
@ -696,244 +426,3 @@ WinLdrInsertDescriptor(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
|
||||||
return;
|
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
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
|
@ -71,6 +71,23 @@ KeInvalidateTlbEntry(IN PVOID Address)
|
||||||
KeArmInvalidateTlbEntry(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
|
VOID
|
||||||
KiPassiveRelease(
|
KiPassiveRelease(
|
||||||
VOID
|
VOID
|
||||||
|
|
|
@ -77,6 +77,39 @@ KeInvalidateTlbEntry(IN PVOID Address)
|
||||||
__invlpg(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
|
VOID
|
||||||
FASTCALL
|
FASTCALL
|
||||||
Ki386InitializeTss(
|
Ki386InitializeTss(
|
||||||
|
|
|
@ -7,19 +7,6 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _M_ARM
|
#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
|
FORCEINLINE
|
||||||
UCHAR
|
UCHAR
|
||||||
KeGetPreviousMode(VOID)
|
KeGetPreviousMode(VOID)
|
||||||
|
@ -29,23 +16,6 @@ KeGetPreviousMode(VOID)
|
||||||
}
|
}
|
||||||
#endif
|
#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
|
// Enters a Guarded Region
|
||||||
//
|
//
|
||||||
|
@ -300,21 +270,6 @@ KiCheckDeferredReadyList(IN PKPRCB Prcb)
|
||||||
UNREFERENCED_PARAMETER(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
|
FORCEINLINE
|
||||||
VOID
|
VOID
|
||||||
KiRequestApcInterrupt(IN BOOLEAN NeedApc,
|
KiRequestApcInterrupt(IN BOOLEAN NeedApc,
|
||||||
|
@ -657,14 +612,6 @@ KiCheckDeferredReadyList(IN PKPRCB Prcb)
|
||||||
if (Prcb->DeferredReadyListHead.Next) KiProcessDeferredReadyList(Prcb);
|
if (Prcb->DeferredReadyListHead.Next) KiProcessDeferredReadyList(Prcb);
|
||||||
}
|
}
|
||||||
|
|
||||||
FORCEINLINE
|
|
||||||
VOID
|
|
||||||
KiRundownThread(IN PKTHREAD Thread)
|
|
||||||
{
|
|
||||||
/* Nothing to do */
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
FORCEINLINE
|
FORCEINLINE
|
||||||
VOID
|
VOID
|
||||||
KiRequestApcInterrupt(IN BOOLEAN NeedApc,
|
KiRequestApcInterrupt(IN BOOLEAN NeedApc,
|
||||||
|
|
|
@ -77,6 +77,29 @@ FORCEINLINE struct _KPCR * NTHALAPI KeGetCurrentKPCR(
|
||||||
return (struct _KPCR *)__readfsdword(0x1c);
|
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 */
|
#ifdef _NTOSKRNL_ /* FIXME: Move flags above to NDK instead of here */
|
||||||
VOID
|
VOID
|
||||||
NTAPI
|
NTAPI
|
||||||
|
|
Loading…
Reference in a new issue