Merge from amd64 branch:
authorTimo Kreuzer <timo.kreuzer@reactos.org>
Sun, 20 Dec 2009 13:30:35 +0000 (13:30 +0000)
committerTimo Kreuzer <timo.kreuzer@reactos.org>
Sun, 20 Dec 2009 13:30:35 +0000 (13:30 +0000)
[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

18 files changed:
1  2  3 
reactos/boot/freeldr/freeldr/arch/amd64/arch.S
reactos/boot/freeldr/freeldr/arch/amd64/fathelp.S
reactos/boot/freeldr/freeldr/bootmgr.c
reactos/boot/freeldr/freeldr/freeldr_arch.rbuild
reactos/boot/freeldr/freeldr/freeldr_base.rbuild
reactos/boot/freeldr/freeldr/include/arch/amd64/amd64.h
reactos/boot/freeldr/freeldr/include/arch/i386/i386.h
reactos/boot/freeldr/freeldr/include/freeldr.h
reactos/boot/freeldr/freeldr/mm/mm.c
reactos/boot/freeldr/freeldr/windows/amd64/ntsetup.c
reactos/boot/freeldr/freeldr/windows/amd64/wlmemory.c
reactos/boot/freeldr/freeldr/windows/i386/wlmemory.c
reactos/boot/freeldr/freeldr/windows/winldr.c
reactos/boot/freeldr/freeldr/windows/wlmemory.c
reactos/ntoskrnl/include/internal/arm/ke.h
reactos/ntoskrnl/include/internal/i386/ke.h
reactos/ntoskrnl/include/internal/ke_x.h
reactos/ntoskrnl/include/internal/powerpc/ke.h

@@@@ -20,6 -20,6 -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
   
   
        call x86_16_EnableA20
   
+++     /* checkPoint Charlie - where it all began... */
+++     mov si, offset _CheckPoint1
+++     call writestr   
+++     
        call x86_16_BuildPageTables
+++     
+++     /* checkPoint Charlie - where it all began... */
+++     mov si, offset _CheckPoint2
+++     call writestr   
+++
+++     /* Check if CPU supports CPUID */
+++     
+++     pushfd
+++     pop eax
+++     mov ebx, eax
+++     xor eax, 0x00200000
+++     push eax
+++     popfd
+++     pushfd
+++     pop eax
+++     cmp eax,ebx
+++     jz NO_CPUID_SUPPORT_DETECTED
+++     
+++     /* CPUID support detected - getting the PAE/PGE */      
+++
+++     mov eax,1 // Fn0000_0001 - PAE in EDX[6]
+++     cpuid
+++     xor eax,eax
+++     and edx,0x00a0
+++     test edx,edx // are PAE and PGE bits set?
+++     jz NO_X64_SUPPORT_DETECTED
+++     
+++     /* PAE and PGE are here */
+++     
+++     xor edx, edx
+++     mov eax, 0x80000001
+++     cpuid
+++     and edx, 0x20000000
+++     test edx,edx
+++     jz NO_X64_SUPPORT_DETECTED
+++     
+++     /* X64 Processor */
+++     
+++     /* checkPoint Charlie - where it all began... */
+++     mov si, offset _CheckPoint3
+++     call writestr   
+++
+++     jmp _switch64
+++     
+++NO_X64_SUPPORT_DETECTED:
+++     mov  si, offset _NotAnX64Processor      // Loading message
+++     call writestr
+++     jmp _fail
+++
+++NO_CPUID_SUPPORT_DETECTED:
+++     mov  si, offset _NoCPUIDSupport // Loading message
+++     call writestr
+++
+++_fail:
+++     jmp _fail
+++     nop
+++     nop
   
---     /* Switch to long mode */
+++_switch64:
        call x86_16_SwitchToLong
   
        .code64
   
 --     /* Checkpoint */
+  //   mov ax, LMODE_DS
+  //   mov ds, ax
+  //   mov word ptr ds:[0xb8000], 0x0e00 + '1'
+  
        /* GO! */
        xor rcx, rcx
        call _BootMain
   
 --//   mov word ptr ds:[0xb8002], 0x0e00 + '2'
+       /* Checkpoint */
+  //   mov ax, LMODE_DS
+  //   mov ds, ax
+++//   mov word ptr ds:[0xb8002], 0x0e02 + '2'
+  
+++     
        /* Return into real mode */
        call x86_64_SwitchToReal
        .code16
@@@@ -90,7 -105,7 -105,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 -158,9 -158,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 -205,8 -205,8 +294,7 @@@@ LongCat
        /* Now return in long mode! */
        ret
   
---
---/** 64 But functions **********************************************************/
+++/** 64 Bit functions **********************************************************/
   .code64
   
   .global x86_64_SwitchToReal
@@@@ -288,6 -325,6 -325,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
   
   ///////////////////////////////////////////////////////////////////////////////
   
@@@@ -155,7 -155,7 -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 -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
@@@@ -201,11 -105,21 -105,21 +201,11 @@@@ VOID RunLoader(VOID
                {
                        // Try to infere boot type value
   #ifdef __i386__
 --                     CHAR LastChar;
 --                     LastChar = SectionName[strlen(SectionName) - 1];
 --                     if (LastChar == '\\' ||
 --                         (strstr(SectionName, ")partition(") != NULL &&
 --                          strstr(SectionName, ")partition(0)") == NULL))
  -                     {
  -                             strcpy(SettingValue, "Partition");
  -                     }
  -                     else if (LastChar == ')' || LastChar == ':')
 ++                     ULONG FileId;
 ++                     if (ArcOpen((CHAR*)SectionName, OpenReadOnly, &FileId) == ESUCCESS)
                        {
 -                              strcpy(SettingValue, "Partition");
 -                      }
 -                      else if (LastChar == ')' || LastChar == ':')
 -                      {
 --                             strcpy(SettingValue, "Drive");
 --                     }
 --                     else if (TRUE)
 --                     {
 --                             strcpy(SettingValue, "BootSector");
 ++                             ArcClose(FileId);
 ++                             strcpy(BootType, "BootSector");
                        }
                        else
   #endif
                        // to have different install methods, etc.
                        LoadReactOSSetup();
                }
-- #ifdef __i386__
 -              else if (_stricmp(SettingValue, "ReactOSSetup2") == 0)
++ #if defined(__i386__) || defined(__x86_64__)
  -             else if (_stricmp(SettingValue, "ReactOSSetup2") == 0)
 ++             else if (_stricmp(BootType, "ReactOSSetup2") == 0)
                {
 - #ifdef __i386__
                        // WinLdr-style boot
                        LoadReactOSSetup2();
 - #endif
                }
   #endif
   #endif
   #ifdef __i386__
 --             else if (_stricmp(SettingValue, "WindowsNT40") == 0)
 ++             else if (_stricmp(BootType, "Windows") == 0)
 +              {
  -                     LoadAndBootWindows(SectionName, _WIN32_WINNT_NT4);
 ++                     LoadAndBootWindows(SectionName, SettingValue, 0);
 +              }
  -             else if (_stricmp(SettingValue, "Windows2003") == 0)
 ++             else if (_stricmp(BootType, "WindowsNT40") == 0)
                {
 -                      LoadAndBootWindows(SectionName, _WIN32_WINNT_NT4);
  -                     LoadAndBootWindows(SectionName, _WIN32_WINNT_WS03);
 ++                     LoadAndBootWindows(SectionName, SettingValue, _WIN32_WINNT_NT4);
                }
 -              else if (_stricmp(SettingValue, "Windows2003") == 0)
  -             else if (_stricmp(SettingValue, "Linux") == 0)
 ++             else if (_stricmp(BootType, "Windows2003") == 0)
  +             {
 -                      LoadAndBootWindows(SectionName, _WIN32_WINNT_WS03);
 ++                     LoadAndBootWindows(SectionName, SettingValue, _WIN32_WINNT_WS03);
  +             }
 -              else if (_stricmp(SettingValue, "Linux") == 0)
 ++             else if (_stricmp(BootType, "Linux") == 0)
                {
                        LoadAndBootLinux(SectionName, OperatingSystemDisplayNames[SelectedOperatingSystem]);
                }
                        <file>wlregistry.c</file>
                </directory>
        </if>
+       <if property="ARCH" value="amd64">
+               <directory name="windows">
+                       <file>conversion.c</file>
+                       <file>peloader.c</file>
+                       <file>winldr.c</file>
++                      <file>wlmemory.c</file>
+                       <file>wlregistry.c</file>
+               </directory>
+       </if>
        <file>freeldr.c</file>
        <file>debug.c</file>
        <file>version.c</file>
   #ifndef __AMD64_AMD64_H_
   #define __AMD64_AMD64_H_
   
+++// This is needed because headers define wrong one for ReactOS
+++#undef KIP0PCRADDRESS
+++#define KIP0PCRADDRESS                      0xFFFFF78000001000ULL /* FIXME!!! */
+++
   #define STACK64ADDR  0x74000 /* The 64-bit stack top will be at 0x74000 */
   
   /* Long mode selectors */
@@@@ -53,35 -54,35 -54,35 +58,6 @@@@ typedef struct _PAGE_DIRECTORY_AMD6
       HARDWARE_PTE Pde[512];
   } PAGE_DIRECTORY_AMD64, *PPAGE_DIRECTORY_AMD64;
   
---VOID
---FORCEINLINE
---__lgdt(void *gdt)
---{
---    asm volatile ("lgdt %0\n" : : "m"(*(short*)gdt));
---}
---
---PKGDTENTRY64
---FORCEINLINE
---KiGetGdtEntry(PVOID pGdt, USHORT Index)
---{
---    return (PKGDTENTRY64)((ULONG64)pGdt + (Index & ~RPL_MASK));
---}
---
---VOID
---FORCEINLINE
---KiInitGdtEntry(PKGDTENTRY64 Entry, ULONG64 Base, ULONG Limit, UCHAR Type, UCHAR Dpl)
---{
---    Entry->Bits.Type = Type;
---    Entry->Bits.Present = 1;
---    Entry->Bits.Dpl = Dpl;
---    Entry->BaseLow = (USHORT)(Base & 0xFFFF);
---    Entry->Bytes.BaseMiddle = (UCHAR)(Base >> 16);
---    Entry->Bytes.BaseHigh = (UCHAR)(Base >> 24);
---    Entry->BaseUpper = (ULONG)(Base >> 32);
---    Entry->LimitLow = (USHORT)(Limit & 0xFFFF);
---    Entry->Bits.LimitHigh = (ULONG)((Limit >> 16) & 0xf);
---    Entry->MustBeZero = 0;
---}
   
   VOID FrLdrSetupGdtIdt();
   
   #ifndef __I386_I386_H_
   #define __I386_I386_H_
   
+++// This is needed because headers define wrong one for ReactOS
+++#undef KIP0PCRADDRESS
+++#define KIP0PCRADDRESS                      0xffdff000
   
   
   #endif /* __I386_I386_H_ */
   #include <arch/i386/i386.h>
   #include <arch/i386/machpc.h>
   #include <arch/i386/machxbox.h>
 ++#include <arch/i386/miscboot.h>
   #include <internal/i386/intrin_i.h>
---#include <internal/i386/ke.h>
   #elif defined(_M_PPC)
   #include <arch/powerpc/hardware.h>
   #elif defined(_M_ARM)
   #elif defined(_M_AMD64)
   #include <arch/amd64/hardware.h>
   #include <arch/amd64/machpc.h>
+++#include <internal/amd64/intrin_i.h>
   #endif
   /* misc files */
   #include <keycodes.h>
@@@@ -75,8 -75,8 -75,8 +75,8 @@@@ PVOID MmAllocateMemoryWithType(ULONG Me
   #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 -175,8 +175,8 @@@@ PVOID MmAllocateMemoryAtAddress(ULONG M
   #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;
index 0000000,67d1057,67d1057..b6048e7
mode 000000,100644,100644..100644
--- /dev/null
@@@@ -1,0 -1,44 -1,44 +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);
+  }
index 0000000,bd111ef,ef6a18d..3e3288a
mode 000000,100644,100644..100644
--- /dev/null
@@@@ -1,0 -1,169 -1,315 +1,353 @@@@
 -  * FILE:            freeldr/winldr/wlmemory.c
+  /*
+   * PROJECT:         EFI Windows Loader
+   * LICENSE:         GPL - See COPYING in the top level directory
 -  * PROGRAMMERS:     Aleksey Bragin (aleksey@reactos.org)
++  * FILE:            freeldr/amd64/wlmemory.c
+   * PURPOSE:         Memory related routines
 - extern ULONG TotalNLSSize;
 - extern ULONG LoaderPagesSpanned;
 - 
 - // This is needed because headers define wrong one for ReactOS
 - #undef KIP0PCRADDRESS
 - #define KIP0PCRADDRESS                      0xffdff000
 - 
 - #define HYPER_SPACE_ENTRY       0x300
 - 
 - PCHAR  MemTypeDesc[]  = {
 -     "ExceptionBlock    ", // ?
 -     "SystemBlock       ", // ?
 -     "Free              ",
 -     "Bad               ", // used
 -     "LoadedProgram     ", // == Free
 -     "FirmwareTemporary ", // == Free
 -     "FirmwarePermanent ", // == Bad
 -     "OsloaderHeap      ", // used
 -     "OsloaderStack     ", // == Free
 -     "SystemCode        ",
 -     "HalCode           ",
 -     "BootDriver        ", // not used
 -     "ConsoleInDriver   ", // ?
 -     "ConsoleOutDriver  ", // ?
 -     "StartupDpcStack   ", // ?
 -     "StartupKernelStack", // ?
 -     "StartupPanicStack ", // ?
 -     "StartupPcrPage    ", // ?
 -     "StartupPdrPage    ", // ?
 -     "RegistryData      ", // used
 -     "MemoryData        ", // not used
 -     "NlsData           ", // used
 -     "SpecialMemory     ", // == Bad
 -     "BBTMemory         " // == Bad
 -     };
++  * PROGRAMMERS:     Timo Kreuzer (timo.kreuzer@reactos.org)
+   */
+  
+  /* INCLUDES ***************************************************************/
+  
+  #include <freeldr.h>
+  
+  #include <ndk/asm.h>
+  #include <debug.h>
+  
 - VOID
 - WinLdrpDumpMemoryDescriptors(PLOADER_PARAMETER_BLOCK LoaderBlock);
  -// This is needed because headers define wrong one for ReactOS
  -#undef KIP0PCRADDRESS
  -#define KIP0PCRADDRESS                      0xffdff000
  -
  -#define HYPER_SPACE_ENTRY       0x300
  -
  -// This is needed only for SetProcessorContext routine
  -#pragma pack(2)
  -     typedef struct
  -     {
  -             USHORT Limit;
  -             ULONG Base;
  -     } GDTIDT;
  -#pragma pack(4)
++ //extern ULONG LoaderPagesSpanned;
+  
 - VOID
 - MempAddMemoryBlock(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
 -                    ULONG BasePage,
 -                    ULONG PageCount,
 -                    ULONG Type);
 - VOID
 - WinLdrInsertDescriptor(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
 -                        IN PMEMORY_ALLOCATION_DESCRIPTOR NewDescriptor);
  -//PHARDWARE_PTE PDE;
+++#define HYPER_SPACE_ENTRY       0x1EE
+  
++ /* GLOBALS ***************************************************************/
+  
 - VOID
 - WinLdrRemoveDescriptor(IN PMEMORY_ALLOCATION_DESCRIPTOR Descriptor);
  -PPAGE_DIRECTORY_AMD64 pPML4;
+++PHARDWARE_PTE PxeBase;
++ //PHARDWARE_PTE HalPageTable;
+  
 - VOID
 - WinLdrSetProcessorContext(PVOID GdtIdt, IN ULONG Pcr, IN ULONG Tss);
+  
 - // This is needed only for SetProcessorContext routine
 - #pragma pack(2)
 -      typedef struct
 -      {
 -              USHORT Limit;
 -              ULONG Base;
 -      } GDTIDT;
 - #pragma pack(4)
++ /* FUNCTIONS **************************************************************/
+  
  -     ULONG KernelPages;
  -     PVOID UserSharedData;
  -
++ BOOLEAN
++ MempAllocatePageTables()
++ {
 - /* GLOBALS ***************************************************************/
++     DPRINTM(DPRINT_WINDOWS,">>> MempAllocatePageTables\n");
+  
  -     pPML4 = MmAllocateMemoryWithType(PAGE_SIZE, LoaderMemoryData);
  -    if (!pPML4)
++      /* Allocate a page for the PML4 */
 - PHARDWARE_PTE PDE;
 - PHARDWARE_PTE HalPageTable;
+++     PxeBase = MmAllocateMemoryWithType(PAGE_SIZE, LoaderMemoryData);
+++    if (!PxeBase)
++     {
++         DPRINTM(DPRINT_WINDOWS,"failed to allocate PML4\n");
++         return FALSE;
++     }
+  
 - PUCHAR PhysicalPageTablesBuffer;
 - PUCHAR KernelPageTablesBuffer;
 - ULONG PhysicalPageTables;
 - ULONG KernelPageTables;
++      // FIXME: Physical PTEs = FirmwareTemporary ?
+  
  -     RtlZeroMemory(pPML4, PAGE_SIZE);
++      /* Zero the PML4 */
 - MEMORY_ALLOCATION_DESCRIPTOR *Mad;
 - ULONG MadCount = 0;
+++     RtlZeroMemory(PxeBase, PAGE_SIZE);
+  
  -     pPML4->Pde[VAtoPXI(PXE_BASE)].Valid = 1;
  -     pPML4->Pde[VAtoPXI(PXE_BASE)].Write = 1;
  -     pPML4->Pde[VAtoPXI(PXE_BASE)].PageFrameNumber = PtrToPfn(pPML4);
++      /* The page tables are located at 0xfffff68000000000 
++       * We create a recursive self mapping through all 4 levels at 
++       * virtual address 0xfffff6fb7dbedf68 */
 - /* FUNCTIONS **************************************************************/
+++     PxeBase[VAtoPXI(PXE_BASE)].Valid = 1;
+++     PxeBase[VAtoPXI(PXE_BASE)].Write = 1;
+++     PxeBase[VAtoPXI(PXE_BASE)].PageFrameNumber = PtrToPfn(PxeBase);
+  
++     // FIXME: map PDE's for hals memory mapping
+  
  -PPAGE_DIRECTORY_AMD64
  -MempGetOrCreatePageDir(PPAGE_DIRECTORY_AMD64 pDir, ULONG Index)
++     DPRINTM(DPRINT_WINDOWS,">>> leave MempAllocatePageTables\n");
++ 
++      return TRUE;
++ }
++ 
  -     PPAGE_DIRECTORY_AMD64 pSubDir;
+++PHARDWARE_PTE
+++MempGetOrCreatePageDir(PHARDWARE_PTE PdeBase, ULONG Index)
++ {
  -     if (!pDir)
+++     PHARDWARE_PTE SubDir;
++ 
  -     if (!pDir->Pde[Index].Valid)
+++     if (!PdeBase)
++              return NULL;
++ 
  -             pSubDir = MmAllocateMemoryWithType(PAGE_SIZE, LoaderSpecialMemory);
  -             if (!pSubDir)
+++     if (!PdeBase[Index].Valid)
++      {
  -             RtlZeroMemory(pSubDir, PAGE_SIZE);
  -             pDir->Pde[Index].PageFrameNumber = PtrToPfn(pSubDir);
  -             pDir->Pde[Index].Valid = 1;
  -             pDir->Pde[Index].Write = 1;
+++             SubDir = MmAllocateMemoryWithType(PAGE_SIZE, LoaderMemoryData);
+++             if (!SubDir)
++                      return NULL;
  -             pSubDir = (PPAGE_DIRECTORY_AMD64)((ULONGLONG)(pDir->Pde[Index].PageFrameNumber) * PAGE_SIZE);
+++             RtlZeroMemory(SubDir, PAGE_SIZE);
+++             PdeBase[Index].PageFrameNumber = PtrToPfn(SubDir);
+++             PdeBase[Index].Valid = 1;
+++             PdeBase[Index].Write = 1;
++      }
++      else
++      {
  -     return pSubDir;
+++             SubDir = (PVOID)((ULONG64)(PdeBase[Index].PageFrameNumber) * PAGE_SIZE);
++      }
 - MempAllocatePageTables()
  -MempMapSinglePage(ULONGLONG VirtualAddress, ULONGLONG PhysicalAddress)
+++     return SubDir;
++ }
+  
+  BOOLEAN
  -     PPAGE_DIRECTORY_AMD64 pDir3, pDir2, pDir1;
+++MempMapSinglePage(ULONG64 VirtualAddress, ULONG64 PhysicalAddress)
+  {
  -     pDir3 = MempGetOrCreatePageDir(pPML4, VAtoPXI(VirtualAddress));
  -     pDir2 = MempGetOrCreatePageDir(pDir3, VAtoPPI(VirtualAddress));
  -     pDir1 = MempGetOrCreatePageDir(pDir2, VAtoPDI(VirtualAddress));
+++     PHARDWARE_PTE PpeBase, PdeBase, PteBase;
++      ULONG Index;
++ 
  -     if (!pDir1)
+++     PpeBase = MempGetOrCreatePageDir(PxeBase, VAtoPXI(VirtualAddress));
+++     PdeBase = MempGetOrCreatePageDir(PpeBase, VAtoPPI(VirtualAddress));
+++     PteBase = MempGetOrCreatePageDir(PdeBase, VAtoPDI(VirtualAddress));
++ 
  -     if (pDir1->Pde[Index].Valid)
+++     if (!PteBase)
+++     {
+++        DPRINTM(DPRINT_WINDOWS,"!!!No Dir %p, %p, %p, %p\n", PxeBase, PpeBase, PdeBase, PteBase);
++              return FALSE;
+++     }
++ 
++      Index = VAtoPTI(VirtualAddress);
  -     pDir1->Pde[Index].Valid = 1;
  -     pDir1->Pde[Index].Write = 1;
  -     pDir1->Pde[Index].PageFrameNumber = PhysicalAddress / PAGE_SIZE;
+++     if (PteBase[Index].Valid)
++      {
+++        DPRINTM(DPRINT_WINDOWS,"!!!Already mapped %ld\n", Index);
++              return FALSE;
++      }
++ 
 - VOID
 - MempAllocatePTE(ULONG Entry, PHARDWARE_PTE *PhysicalPT, PHARDWARE_PTE *KernelPT)
+++     PteBase[Index].Valid = 1;
+++     PteBase[Index].Write = 1;
+++     PteBase[Index].PageFrameNumber = PhysicalAddress / PAGE_SIZE;
+  
+       return TRUE;
+  }
+  
  -MempMapRangeOfPages(ULONGLONG VirtualAddress, ULONGLONG PhysicalAddress, ULONG cPages)
+++BOOLEAN
+++MempIsPageMapped(PVOID VirtualAddress)
+ +{
+++     PHARDWARE_PTE PpeBase, PdeBase, PteBase;
+++    ULONG Index;
+++    
+++    Index = VAtoPXI(VirtualAddress);
+++    if (!PxeBase[Index].Valid)
+++        return FALSE;
+++
+++    PpeBase = (PVOID)((ULONG64)(PxeBase[Index].PageFrameNumber) * PAGE_SIZE);
+++    Index = VAtoPPI(VirtualAddress);
+++    if (!PpeBase[Index].Valid)
+++        return FALSE;
+++
+++    PdeBase = (PVOID)((ULONG64)(PpeBase[Index].PageFrameNumber) * PAGE_SIZE);
+++    Index = VAtoPDI(VirtualAddress);
+++    if (!PdeBase[Index].Valid)
+++        return FALSE;
+++
+++    PteBase = (PVOID)((ULONG64)(PdeBase[Index].PageFrameNumber) * PAGE_SIZE);
+++    Index = VAtoPTI(VirtualAddress);
+++    if (!PteBase[Index].Valid)
+++        return FALSE;
+++
+++    return TRUE;
+++}
+ +
++ ULONG
  -             if (!FrLdrMapSinglePage(VirtualAddress, PhysicalAddress))
+++MempMapRangeOfPages(ULONG64 VirtualAddress, ULONG64 PhysicalAddress, ULONG cPages)
++ {
++      ULONG i;
++ 
++      for (i = 0; i < cPages; i++)
++      {
  -    DPRINTM(DPRINT_WINDOWS,">>> MempSetupPaging(0x%lx, %ld)\n", StartPage, NumberOfPages);
+++             if (!MempMapSinglePage(VirtualAddress, PhysicalAddress))
++              {
++                      return i;
++              }
++              VirtualAddress += PAGE_SIZE;
++              PhysicalAddress += PAGE_SIZE;
++      }
++      return i;
+  }
+  
+  BOOLEAN
+  MempSetupPaging(IN ULONG StartPage,
+                               IN ULONG NumberOfPages)
+  {
  -        DPRINTM(DPRINT_WINDOWS,"Failed to map pages\n");
+++    DPRINTM(DPRINT_WINDOWS,">>> MempSetupPaging(0x%lx, %ld, %p)\n", 
+++            StartPage, NumberOfPages, StartPage * PAGE_SIZE + KSEG0_BASE);
++ 
+++    /* Identity mapping */
++     if (MempMapRangeOfPages(StartPage * PAGE_SIZE,
++                             StartPage * PAGE_SIZE,
++                             NumberOfPages) != NumberOfPages)
++     {
 - MempDisablePages()
+++        DPRINTM(DPRINT_WINDOWS,"Failed to map pages 1\n");
+++        return FALSE;
+++    }
+++
+++    /* Kernel mapping */
+++    if (MempMapRangeOfPages(StartPage * PAGE_SIZE + KSEG0_BASE,
+++                            StartPage * PAGE_SIZE,
+++                            NumberOfPages) != NumberOfPages)
+++    {
+++        DPRINTM(DPRINT_WINDOWS,"Failed to map pages 2\n");
++         return FALSE;
++     }
+  
+       return TRUE;
+  }
+  
+  VOID
 - 
++ MempUnmapPage(ULONG Page)
+  {
 - MempAddMemoryBlock(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
 -                    ULONG BasePage,
 -                    ULONG PageCount,
 -                    ULONG Type)
++    // DPRINTM(DPRINT_WINDOWS,">>> MempUnmapPage\n");
+  }
+  
+  VOID
 - #ifdef _M_IX86
 - VOID
 - WinLdrpMapApic()
++ WinLdrpMapApic()
+  {
++      BOOLEAN LocalAPIC;
++      LARGE_INTEGER MsrValue;
++      ULONG CpuInfo[4];
++      ULONG64 APICAddress;
+  
++     DPRINTM(DPRINT_WINDOWS,">>> WinLdrpMapApic\n");
++ 
++      /* Check if we have a local APIC */
++      __cpuid((int*)CpuInfo, 1);
++      LocalAPIC = (((CpuInfo[3] >> 9) & 1) != 0);
++ 
++      /* If there is no APIC, just return */
++      if (!LocalAPIC)
++      {
++         DPRINTM(DPRINT_WINDOWS,"No APIC found.\n");
++              return;
++      }
++ 
++      /* Read the APIC Address */
++      MsrValue.QuadPart = __readmsr(0x1B);
++      APICAddress = (MsrValue.LowPart & 0xFFFFF000);
++ 
++      DPRINTM(DPRINT_WINDOWS, "Local APIC detected at address 0x%x\n",
++              APICAddress);
++ 
++      /* Map it */
++      MempMapSinglePage(APIC_BASE, APICAddress);
+  }
+  
 - 
++ BOOLEAN
++ WinLdrMapSpecialPages(ULONG PcrBasePage)
+  {
  -    if (!MempMapSinglePage(PcrBasePage * PAGE_SIZE, KIP0PCRADDRESS))
++     /* Map the PCR page */
  -    if (!MempMapSinglePage((PcrBasePage+1) * PAGE_SIZE, KI_USER_SHARED_DATA))
+++    if (!MempMapSinglePage(KIP0PCRADDRESS, PcrBasePage * PAGE_SIZE))
++     {
++         DPRINTM(DPRINT_WINDOWS, "Could not map PCR @ %lx\n", PcrBasePage);
++         return FALSE;
++     }
++ 
++     /* Map KI_USER_SHARED_DATA */
 - #else
+++    if (!MempMapSinglePage(KI_USER_SHARED_DATA, (PcrBasePage+1) * PAGE_SIZE))
++     {
++         DPRINTM(DPRINT_WINDOWS, "Could not map KI_USER_SHARED_DATA\n");
++         return FALSE;
++     }
++ 
++      /* Map the APIC page */
++      WinLdrpMapApic();
++ 
++     return TRUE;
+  }
 - WinLdrpMapApic()
++ 
+  VOID
 -      /* Implement it for another arch */
++ WinLdrSetupGdt(PVOID GdtBase, ULONG64 TssBase)
+  {
 - #endif
++      PKGDTENTRY64 Entry;
++      KDESCRIPTOR GdtDesc;
++ 
++      /* Setup KGDT_64_R0_CODE */
++      Entry = KiGetGdtEntry(GdtBase, KGDT_64_R0_CODE);
++      *(PULONG64)Entry = 0x00209b0000000000ULL;
++ 
++      /* Setup KGDT_64_R0_SS */
++      Entry = KiGetGdtEntry(GdtBase, KGDT_64_R0_SS);
++      *(PULONG64)Entry = 0x00cf93000000ffffULL;
++ 
++      /* Setup KGDT_64_DATA */
++      Entry = KiGetGdtEntry(GdtBase, KGDT_64_DATA);
++      *(PULONG64)Entry = 0x00cff3000000ffffULL;
++ 
++      /* Setup KGDT_64_R3_CODE */
++      Entry = KiGetGdtEntry(GdtBase, KGDT_64_R3_CODE);
++      *(PULONG64)Entry = 0x0020fb0000000000ULL;
++ 
++      /* Setup KGDT_32_R3_TEB */
++      Entry = KiGetGdtEntry(GdtBase, KGDT_32_R3_TEB);
++      *(PULONG64)Entry = 0xff40f3fd50003c00ULL;
++ 
++      /* Setup TSS entry */
++      Entry = KiGetGdtEntry(GdtBase, KGDT_TSS);
++      KiInitGdtEntry(Entry, TssBase, sizeof(KTSS), I386_TSS, 0);
++ 
++     /* Setup GDT descriptor */
++      GdtDesc.Base  = GdtBase;
++      GdtDesc.Limit = NUM_GDT * sizeof(KGDTENTRY) - 1;
++ 
++      /* Set the new Gdt */
++      __lgdt(&GdtDesc.Limit);
++      DbgPrint("Gdtr.Base = %p, num = %ld\n", GdtDesc.Base, NUM_GDT);
++ 
+  }
 - BOOLEAN
 - WinLdrTurnOnPaging(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
 -                    ULONG PcrBasePage,
 -                    ULONG TssBasePage,
 -                    PVOID GdtIdt)
+  
 - return 1;
++ VOID
++ WinLdrSetupIdt(PVOID IdtBase)
+  {
 - // Two special things this func does: it sorts descriptors,
 - // and it merges free ones
++      KDESCRIPTOR IdtDesc, OldIdt;
++ 
++     /* Get old IDT */
++      __sidt(&OldIdt);
++ 
++      /* Copy the old IDT */
++      RtlCopyMemory(IdtBase, (PVOID)OldIdt.Base, OldIdt.Limit + 1);
++ 
++      /* Setup the new IDT descriptor */
++      IdtDesc.Base = IdtBase;
++      IdtDesc.Limit = NUM_IDT * sizeof(KIDTENTRY) - 1;
++ 
++      /* Set the new IDT */
++      __lidt(&IdtDesc.Limit);
++      DbgPrint("Idtr.Base = %p\n", IdtDesc.Base);
++ 
+  }
+  
 - WinLdrInsertDescriptor(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
 -                        IN PMEMORY_ALLOCATION_DESCRIPTOR NewDescriptor)
+  VOID
  -     __writecr3((ULONGLONG)pPML4);
++ WinLdrSetProcessorContext(PVOID GdtIdt, IN ULONG64 Pcr, IN ULONG64 Tss)
+  {
+++    DPRINTM(DPRINT_WINDOWS, "WinLdrSetProcessorContext %p\n", Pcr);
+++
++      /* Disable Interrupts */
++      _disable();
+  
++      /* Re-initalize EFLAGS */
++      __writeeflags(0);
++ 
++      /* Set the new PML4 */
  -     // Enable paging by modifying CR0
  -     __writecr0(__readcr0() | CR0_PG);
+++     __writecr3((ULONG64)PxeBase);
++ 
  -     // Kernel expects the PCR to be zero-filled on startup
  -     // FIXME: Why zero it here when we can zero it right after allocation?
  -     RtlZeroMemory((PVOID)Pcr, MM_PAGE_SIZE); //FIXME: Why zero only 1 page when we allocate 2?
+++    /* Get kernel mode address of gdt / idt */
+++     GdtIdt = (PVOID)((ULONG64)GdtIdt + KSEG0_BASE);
++ 
  -     RtlZeroMemory(GdtIdt, PAGE_SIZE);
+++    /* Create gdt entries and load gdtr */
+++    WinLdrSetupGdt(GdtIdt, Tss);
++ 
  -    WinLdrSetupGdt(GdtIdt, Tss);
+++    /* Copy old Idt and set idtr */
+++    WinLdrSetupIdt((PVOID)((ULONG64)GdtIdt + 2048)); // HACK!
++ 
  -    WinLdrSetupIdt(GdtIdt);
+++    /* LDT is unused */
+++//    __lldt(0);
+++
+++    /* Load selectors for DS/ES/FS/GS/SS */
+++    Ke386SetDs(KGDT_64_DATA | RPL_MASK);   // 0x2b
+++    Ke386SetEs(KGDT_64_DATA | RPL_MASK);   // 0x2b
+++    Ke386SetFs(KGDT_32_R3_TEB | RPL_MASK); // 0x53
+++     Ke386SetGs(KGDT_64_DATA | RPL_MASK);   // 0x2b
+++     Ke386SetSs(KGDT_64_R0_SS);             // 0x18
++ 
 - WinLdrSetProcessorContext(PVOID GdtIdt, IN ULONG Pcr, IN ULONG Tss)
+++     /* Load TSR */
+++     __ltr(KGDT_TSS);
++ 
+++    DPRINTM(DPRINT_WINDOWS, "leave WinLdrSetProcessorContext\n");
+  }
+  
+  VOID
 - 
++ MempDump()
+  {
+  }
+  
index 0000000,313413e,6eb8b34..7800f3d
mode 000000,100644,100644..100644
--- /dev/null
@@@@ -1,0 -1,939 -1,560 +1,560 @@@@
 -  * FILE:            freeldr/winldr/wlmemory.c
+  /*
+   * PROJECT:         EFI Windows Loader
+   * LICENSE:         GPL - See COPYING in the top level directory
 - PCHAR  MemTypeDesc[]  = {
 -     "ExceptionBlock    ", // ?
 -     "SystemBlock       ", // ?
 -     "Free              ",
 -     "Bad               ", // used
 -     "LoadedProgram     ", // == Free
 -     "FirmwareTemporary ", // == Free
 -     "FirmwarePermanent ", // == Bad
 -     "OsloaderHeap      ", // used
 -     "OsloaderStack     ", // == Free
 -     "SystemCode        ",
 -     "HalCode           ",
 -     "BootDriver        ", // not used
 -     "ConsoleInDriver   ", // ?
 -     "ConsoleOutDriver  ", // ?
 -     "StartupDpcStack   ", // ?
 -     "StartupKernelStack", // ?
 -     "StartupPanicStack ", // ?
 -     "StartupPcrPage    ", // ?
 -     "StartupPdrPage    ", // ?
 -     "RegistryData      ", // used
 -     "MemoryData        ", // not used
 -     "NlsData           ", // used
 -     "SpecialMemory     ", // == Bad
 -     "BBTMemory         " // == Bad
 -     };
 - 
 - VOID
 - WinLdrpDumpMemoryDescriptors(PLOADER_PARAMETER_BLOCK LoaderBlock);
 - 
 - 
 - VOID
 - MempAddMemoryBlock(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
 -                    ULONG BasePage,
 -                    ULONG PageCount,
 -                    ULONG Type);
 - VOID
 - WinLdrInsertDescriptor(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
 -                        IN PMEMORY_ALLOCATION_DESCRIPTOR NewDescriptor);
 - 
 - VOID
 - WinLdrRemoveDescriptor(IN PMEMORY_ALLOCATION_DESCRIPTOR Descriptor);
 - 
 - VOID
 - WinLdrSetProcessorContext(PVOID GdtIdt, IN ULONG Pcr, IN ULONG Tss);
 - 
++  * FILE:            freeldr/winldr/i386/wlmemory.c
+   * PURPOSE:         Memory related routines
+   * PROGRAMMERS:     Aleksey Bragin (aleksey@reactos.org)
+   */
+  
+  /* INCLUDES ***************************************************************/
+  
+  #include <freeldr.h>
+  
+  #include <ndk/asm.h>
+  #include <debug.h>
+  
+  extern ULONG TotalNLSSize;
+  extern ULONG LoaderPagesSpanned;
+  
+  // This is needed because headers define wrong one for ReactOS
+  #undef KIP0PCRADDRESS
+  #define KIP0PCRADDRESS                      0xffdff000
+  
+  #define HYPER_SPACE_ENTRY       0x300
+  
 - MEMORY_ALLOCATION_DESCRIPTOR *Mad;
 - ULONG MadCount = 0;
 - 
 - 
+  // This is needed only for SetProcessorContext routine
+  #pragma pack(2)
+       typedef struct
+       {
+               USHORT Limit;
+               ULONG Base;
+       } GDTIDT;
+  #pragma pack(4)
+  
+  /* GLOBALS ***************************************************************/
+  
+  PHARDWARE_PTE PDE;
+  PHARDWARE_PTE HalPageTable;
+  
+  PUCHAR PhysicalPageTablesBuffer;
+  PUCHAR KernelPageTablesBuffer;
+  ULONG PhysicalPageTables;
+  ULONG KernelPageTables;
+  
 - MempDisablePages()
 - {
 -      ULONG i;
 - 
 -      //
 -      // We need to delete kernel mapping from memory areas which are
 -      // marked as Special or Permanent memory (thus non-accessible)
 -      //
 - 
 -      for (i=0; i<MadCount; i++)
 -      {
 -              ULONG StartPage, EndPage, Page;
 - 
 -              StartPage = Mad[i].BasePage;
 -              EndPage = Mad[i].BasePage + Mad[i].PageCount;
 - 
 -              if (Mad[i].MemoryType == LoaderFirmwarePermanent ||
 -                      Mad[i].MemoryType == LoaderSpecialMemory ||
 -                      Mad[i].MemoryType == LoaderFree ||
 -                      (Mad[i].MemoryType == LoaderFirmwareTemporary && EndPage <= LoaderPagesSpanned) ||
 -                      Mad[i].MemoryType == LoaderOsloaderStack ||
 -                      Mad[i].MemoryType == LoaderLoadedProgram)
 -              {
 -                      //
 -                      // But, the first megabyte of memory always stays!
 -                      // And, to tell the truth, we don't care about what's higher
 -                      // than LoaderPagesSpanned
 -                      if (Mad[i].MemoryType == LoaderFirmwarePermanent ||
 -                              Mad[i].MemoryType == LoaderSpecialMemory)
 -                      {
 -                              if (StartPage < 0x100)
 -                                      StartPage = 0x100;
 - 
 -                              if (EndPage > LoaderPagesSpanned)
 -                                      EndPage = LoaderPagesSpanned;
 -                      }
 - 
 -                      for (Page = StartPage; Page < EndPage; Page++)
 -                      {
 -                              PHARDWARE_PTE KernelPT;
 -                              ULONG Entry = (Page >> 10) + (KSEG0_BASE >> 22);
 - 
 -                              if (PDE[Entry].Valid)
 -                              {
 -                                      KernelPT = (PHARDWARE_PTE)(PDE[Entry].PageFrameNumber << MM_PAGE_SHIFT);
 - 
 -                                      if (KernelPT)
 -                                      {
 -                                              KernelPT[Page & 0x3ff].PageFrameNumber = 0;
 -                                              KernelPT[Page & 0x3ff].Valid = 0;
 -                                              KernelPT[Page & 0x3ff].Write = 0;
 -                                      }
 -                              }
 -                      }
 -              }
 -      }
 - }
 - 
 - VOID
 - MempAddMemoryBlock(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
 -                    ULONG BasePage,
 -                    ULONG PageCount,
 -                    ULONG Type)
+  /* FUNCTIONS **************************************************************/
+  
+  BOOLEAN
+  MempAllocatePageTables()
+  {
+       ULONG NumPageTables, TotalSize;
+       PUCHAR Buffer;
+       // It's better to allocate PDE + PTEs contigiuos
+  
+       // Max number of entries = MaxPageNum >> 10
+       // FIXME: This is a number to describe ALL physical memory
+       // and windows doesn't expect ALL memory mapped...
+       NumPageTables = (GetSystemMemorySize() >> MM_PAGE_SHIFT) >> 10;
+  
+       DPRINTM(DPRINT_WINDOWS, "NumPageTables = %d\n", NumPageTables);
+  
+       // Allocate memory block for all these things:
+       // PDE, HAL mapping page table, physical mapping, kernel mapping
+       TotalSize = (1+1+NumPageTables*2)*MM_PAGE_SIZE;
+  
+       // PDE+HAL+KernelPTEs == MemoryData
+       Buffer = MmAllocateMemoryWithType(TotalSize, LoaderMemoryData);
+  
+       // Physical PTEs = FirmwareTemporary
+       PhysicalPageTablesBuffer = (PUCHAR)Buffer + TotalSize - NumPageTables*MM_PAGE_SIZE;
+       MmSetMemoryType(PhysicalPageTablesBuffer,
+                       NumPageTables*MM_PAGE_SIZE,
+                       LoaderFirmwareTemporary);
+  
+       // This check is now redundant
+       if (Buffer + (TotalSize - NumPageTables*MM_PAGE_SIZE) !=
+               PhysicalPageTablesBuffer)
+       {
+               DPRINTM(DPRINT_WINDOWS, "There was a problem allocating two adjacent blocks of memory!");
+       }
+  
+       if (Buffer == NULL || PhysicalPageTablesBuffer == NULL)
+       {
+               UiMessageBox("Impossible to allocate memory block for page tables!");
+               return FALSE;
+       }
+  
+       // Zero all this memory block
+       RtlZeroMemory(Buffer, TotalSize);
+  
+       // Set up pointers correctly now
+       PDE = (PHARDWARE_PTE)Buffer;
+  
+       // Map the page directory at 0xC0000000 (maps itself)
+       PDE[HYPER_SPACE_ENTRY].PageFrameNumber = (ULONG)PDE >> MM_PAGE_SHIFT;
+       PDE[HYPER_SPACE_ENTRY].Valid = 1;
+       PDE[HYPER_SPACE_ENTRY].Write = 1;
+  
+       // The last PDE slot is allocated for HAL's memory mapping (Virtual Addresses 0xFFC00000 - 0xFFFFFFFF)
+       HalPageTable = (PHARDWARE_PTE)&Buffer[MM_PAGE_SIZE*1];
+  
+       // Map it
+       PDE[1023].PageFrameNumber = (ULONG)HalPageTable >> MM_PAGE_SHIFT;
+       PDE[1023].Valid = 1;
+       PDE[1023].Write = 1;
+  
+       // Store pointer to the table for easier access
+       KernelPageTablesBuffer = &Buffer[MM_PAGE_SIZE*2];
+  
+       // Zero counters of page tables used
+       PhysicalPageTables = 0;
+       KernelPageTables = 0;
+  
+       return TRUE;
+  }
+  
+  VOID
+  MempAllocatePTE(ULONG Entry, PHARDWARE_PTE *PhysicalPT, PHARDWARE_PTE *KernelPT)
+  {
+       //Print(L"Creating PDE Entry %X\n", Entry);
+  
+       // Identity mapping
+       *PhysicalPT = (PHARDWARE_PTE)&PhysicalPageTablesBuffer[PhysicalPageTables*MM_PAGE_SIZE];
+       PhysicalPageTables++;
+  
+       PDE[Entry].PageFrameNumber = (ULONG)*PhysicalPT >> MM_PAGE_SHIFT;
+       PDE[Entry].Valid = 1;
+       PDE[Entry].Write = 1;
+  
+       if (Entry+(KSEG0_BASE >> 22) > 1023)
+       {
+               DPRINTM(DPRINT_WINDOWS, "WARNING! Entry: %X > 1023\n", Entry+(KSEG0_BASE >> 22));
+       }
+  
+       // Kernel-mode mapping
+       *KernelPT = (PHARDWARE_PTE)&KernelPageTablesBuffer[KernelPageTables*MM_PAGE_SIZE];
+       KernelPageTables++;
+  
+       PDE[Entry+(KSEG0_BASE >> 22)].PageFrameNumber = ((ULONG)*KernelPT >> MM_PAGE_SHIFT);
+       PDE[Entry+(KSEG0_BASE >> 22)].Valid = 1;
+       PDE[Entry+(KSEG0_BASE >> 22)].Write = 1;
+  }
+  
+  BOOLEAN
+  MempSetupPaging(IN ULONG StartPage,
+                               IN ULONG NumberOfPages)
+  {
+       PHARDWARE_PTE PhysicalPT;
+       PHARDWARE_PTE KernelPT;
+       ULONG Entry, Page;
+  
+       //Print(L"MempSetupPaging: SP 0x%X, Number: 0x%X\n", StartPage, NumberOfPages);
+       
+       // HACK
+       if (StartPage+NumberOfPages >= 0x80000)
+       {
+               //
+               // We can't map this as it requires more than 1 PDE
+               // and in fact it's not possible at all ;)
+               //
+               //Print(L"skipping...\n");
+               return TRUE;
+       }
+  
+       //
+       // Now actually set up the page tables for identity mapping
+       //
+       for (Page=StartPage; Page < StartPage+NumberOfPages; Page++)
+       {
+               Entry = Page >> 10;
+  
+               if (((PULONG)PDE)[Entry] == 0)
+               {
+                       MempAllocatePTE(Entry, &PhysicalPT, &KernelPT);
+               }
+               else
+               {
+                       PhysicalPT = (PHARDWARE_PTE)(PDE[Entry].PageFrameNumber << MM_PAGE_SHIFT);
+                       KernelPT = (PHARDWARE_PTE)(PDE[Entry+(KSEG0_BASE >> 22)].PageFrameNumber << MM_PAGE_SHIFT);
+               }
+  
+               if (Page == 0)
+               {
+                       PhysicalPT[Page & 0x3ff].PageFrameNumber = Page;
+                       PhysicalPT[Page & 0x3ff].Valid = 0;
+                       PhysicalPT[Page & 0x3ff].Write = 0;
+  
+                       KernelPT[Page & 0x3ff].PageFrameNumber = Page;
+                       KernelPT[Page & 0x3ff].Valid = 0;
+                       KernelPT[Page & 0x3ff].Write = 0;
+               }
+               else
+               {
+                       PhysicalPT[Page & 0x3ff].PageFrameNumber = Page;
+                       PhysicalPT[Page & 0x3ff].Valid = 1;
+                       PhysicalPT[Page & 0x3ff].Write = 1;
+  
+                       KernelPT[Page & 0x3ff].PageFrameNumber = Page;
+                       KernelPT[Page & 0x3ff].Valid = 1;
+                       KernelPT[Page & 0x3ff].Write = 1;
+               }
+       }
+  
+       return TRUE;
+  }
+  
+  VOID
 -      BOOLEAN Status;
 - 
 -      //
 -      // Check for some weird stuff at the top
 -      //
 -      if (BasePage + PageCount > 0xF0000)
 -      {
 -              //
 -              // Just skip this, without even adding to MAD list
 -              //
 -              return;
 -      }
 - 
 -      //
 -      // Set Base page, page count and type
 -      //
 -      Mad[MadCount].BasePage = BasePage;
 -      Mad[MadCount].PageCount = PageCount;
 -      Mad[MadCount].MemoryType = Type;
 - 
 -      //
 -      // Check if it's more than the allowed for OS loader
 -      // if yes - don't map the pages, just add as FirmwareTemporary
 -      //
 -      if (BasePage + PageCount > LoaderPagesSpanned)
 -      {
 -              if (Mad[MadCount].MemoryType != LoaderSpecialMemory &&
 -                      Mad[MadCount].MemoryType != LoaderFirmwarePermanent &&
 -                      Mad[MadCount].MemoryType != LoaderFree)
 -              {
 -                      DPRINTM(DPRINT_WINDOWS, "Setting page %x %x to Temporary from %d\n",
 -                              BasePage, PageCount, Mad[MadCount].MemoryType);
 -                      Mad[MadCount].MemoryType = LoaderFirmwareTemporary;
 -              }
 - 
 -              WinLdrInsertDescriptor(LoaderBlock, &Mad[MadCount]);
 -              MadCount++;
 - 
 -              return;
 -      }
 -      
 -      //
 -      // Add descriptor
 -      //
 -      WinLdrInsertDescriptor(LoaderBlock, &Mad[MadCount]);
 -      MadCount++;
 - 
 -      //
 -      // Map it (don't map low 1Mb because it was already contigiously
 -      // mapped in WinLdrTurnOnPaging)
 -      //
 -      if (BasePage >= 0x100)
 -      {
 -              Status = MempSetupPaging(BasePage, PageCount);
 -              if (!Status)
 -              {
 -                      DPRINTM(DPRINT_WINDOWS, "Error during MempSetupPaging\n");
 -                      return;
 -              }
 -      }
++ MempUnmapPage(ULONG Page)
+  {
 - #ifdef _M_IX86
++     PHARDWARE_PTE KernelPT;
++     ULONG Entry = (Page >> 10) + (KSEG0_BASE >> 22);
++ 
++     if (PDE[Entry].Valid)
++     {
++         KernelPT = (PHARDWARE_PTE)(PDE[Entry].PageFrameNumber << MM_PAGE_SHIFT);
++ 
++         if (KernelPT)
++         {
++             KernelPT[Page & 0x3ff].PageFrameNumber = 0;
++             KernelPT[Page & 0x3ff].Valid = 0;
++             KernelPT[Page & 0x3ff].Write = 0;
++         }
++     }
+  }
+  
 - #else
 - VOID
 - WinLdrpMapApic()
 - {
 -      /* Implement it for another arch */
 - }
 - #endif
+  VOID
+  WinLdrpMapApic()
+  {
+       BOOLEAN LocalAPIC;
+       LARGE_INTEGER MsrValue;
+       ULONG APICAddress, CpuInfo[4];
+  
+       /* Check if we have a local APIC */
+       __cpuid((int*)CpuInfo, 1);
+       LocalAPIC = (((CpuInfo[3] >> 9) & 1) != 0);
+  
+       /* If there is no APIC, just return */
+       if (!LocalAPIC)
+               return;
+  
+       /* Read the APIC Address */
+       MsrValue.QuadPart = __readmsr(0x1B);
+       APICAddress = (MsrValue.LowPart & 0xFFFFF000);
+  
+       DPRINTM(DPRINT_WINDOWS, "Local APIC detected at address 0x%x\n",
+               APICAddress);
+  
+       /* Map it */
+       HalPageTable[(APIC_BASE - 0xFFC00000) >> MM_PAGE_SHIFT].PageFrameNumber
+               = APICAddress >> MM_PAGE_SHIFT;
+       HalPageTable[(APIC_BASE - 0xFFC00000) >> MM_PAGE_SHIFT].Valid = 1;
+       HalPageTable[(APIC_BASE - 0xFFC00000) >> MM_PAGE_SHIFT].Write = 1;
+       HalPageTable[(APIC_BASE - 0xFFC00000) >> MM_PAGE_SHIFT].WriteThrough = 1;
+       HalPageTable[(APIC_BASE - 0xFFC00000) >> MM_PAGE_SHIFT].CacheDisable = 1;
+  }
 - WinLdrTurnOnPaging(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
 -                    ULONG PcrBasePage,
 -                    ULONG TssBasePage,
 -                    PVOID GdtIdt)
+  
+  BOOLEAN
 -      ULONG i, PagesCount, MemoryMapSizeInPages;
 -      ULONG LastPageIndex, LastPageType, MemoryMapStartPage;
 -      PPAGE_LOOKUP_TABLE_ITEM MemoryMap;
 -      ULONG NoEntries;
 -      PKTSS Tss;
 -      BOOLEAN Status;
 - 
 -      //
 -      // Creating a suitable memory map for the Windows can be tricky, so let's
 -      // give a few advices:
 -      // 1) One must not map the whole available memory pages to PDE!
 -      //    Map only what's needed - 16Mb, 24Mb, 32Mb max I think,
 -      //    thus occupying 4, 6 or 8 PDE entries for identical mapping,
 -      //    the same quantity for KSEG0_BASE mapping, one more entry for
 -      //    hyperspace and one more entry for HAL physical pages mapping.
 -      // 2) Memory descriptors must map *the whole* physical memory
 -      //    showing any memory above 16/24/32 as FirmwareTemporary
 -      //
 -      // 3) Overall memory blocks count must not exceed 30 (?? why?)
 -      //
 - 
 -      //
 -      // During MmInitMachineDependent, the kernel zeroes PDE at the following address
 -      // 0xC0300000 - 0xC03007FC
 -      //
 -      // Then it finds the best place for non-paged pool:
 -      // StartPde C0300F70, EndPde C0300FF8, NumberOfPages C13, NextPhysPage 3AD
 -      //
 - 
 -      // Before we start mapping pages, create a block of memory, which will contain
 -      // PDE and PTEs
 -      if (MempAllocatePageTables() == FALSE)
 -              return FALSE;
 - 
 -      // Allocate memory for memory allocation descriptors
 -      Mad = MmHeapAlloc(sizeof(MEMORY_ALLOCATION_DESCRIPTOR) * 1024);
 - 
 -      // Setup an entry for each descriptor
 -      MemoryMap = MmGetMemoryMap(&NoEntries);
 -      if (MemoryMap == NULL)
 -      {
 -              UiMessageBox("Can not retrieve the current memory map");
 -              return FALSE;
 -      }
 - 
 -      // Calculate parameters of the memory map
 -      MemoryMapStartPage = (ULONG_PTR)MemoryMap >> MM_PAGE_SHIFT;
 -      MemoryMapSizeInPages = NoEntries * sizeof(PAGE_LOOKUP_TABLE_ITEM);
 - 
 -      DPRINTM(DPRINT_WINDOWS, "Got memory map with %d entries\n", NoEntries);
 - 
 -      // Always contigiously map low 1Mb of memory
 -      Status = MempSetupPaging(0, 0x100);
 -      if (!Status)
 -      {
 -              DPRINTM(DPRINT_WINDOWS, "Error during MempSetupPaging of low 1Mb\n");
 -              return FALSE;
 -      }
 - 
 -      // Construct a good memory map from what we've got,
 -      // but mark entries which the memory allocation bitmap takes
 -      // as free entries (this is done in order to have the ability
 -      // to place mem alloc bitmap outside lower 16Mb zone)
 -      PagesCount = 1;
 -      LastPageIndex = 0;
 -      LastPageType = MemoryMap[0].PageAllocated;
 -      for(i=1;i<NoEntries;i++)
 -      {
 -              // Check if its memory map itself
 -              if (i >= MemoryMapStartPage &&
 -                      i < (MemoryMapStartPage+MemoryMapSizeInPages))
 -              {
 -                      // Exclude it if current page belongs to the memory map
 -                      MemoryMap[i].PageAllocated = LoaderFree;
 -              }
 - 
 -              // Process entry
 -              if (MemoryMap[i].PageAllocated == LastPageType &&
 -                      (i != NoEntries-1) )
 -              {
 -                      PagesCount++;
 -              }
 -              else
 -              {
 -                      // Add the resulting region
 -                      MempAddMemoryBlock(LoaderBlock, LastPageIndex, PagesCount, LastPageType);
 - 
 -                      // Reset our counter vars
 -                      LastPageIndex = i;
 -                      LastPageType = MemoryMap[i].PageAllocated;
 -                      PagesCount = 1;
 -              }
 -      }
 - 
 -      // TEMP, DEBUG!
 -      // adding special reserved memory zones for vmware workstation
 - #if 0
 -      {
 -              Mad[MadCount].BasePage = 0xfec00;
 -              Mad[MadCount].PageCount = 0x10;
 -              Mad[MadCount].MemoryType = LoaderSpecialMemory;
 -              WinLdrInsertDescriptor(LoaderBlock, &Mad[MadCount]);
 -              MadCount++;
 - 
 -              Mad[MadCount].BasePage = 0xfee00;
 -              Mad[MadCount].PageCount = 0x1;
 -              Mad[MadCount].MemoryType = LoaderSpecialMemory;
 -              WinLdrInsertDescriptor(LoaderBlock, &Mad[MadCount]);
 -              MadCount++;
 - 
 -              Mad[MadCount].BasePage = 0xfffe0;
 -              Mad[MadCount].PageCount = 0x20;
 -              Mad[MadCount].MemoryType = LoaderSpecialMemory;
 -              WinLdrInsertDescriptor(LoaderBlock, &Mad[MadCount]);
 -              MadCount++;
 -      }
 - #endif
 - 
 -      DPRINTM(DPRINT_WINDOWS, "MadCount: %d\n", MadCount);
 - 
 -      WinLdrpDumpMemoryDescriptors(LoaderBlock); //FIXME: Delete!
 - 
 -      // Map our loader image, so we can continue running
 -      /*Status = MempSetupPaging(OsLoaderBase >> MM_PAGE_SHIFT, OsLoaderSize >> MM_PAGE_SHIFT);
 -      if (!Status)
 -      {
 -              UiMessageBox("Error during MempSetupPaging");
 -              return;
 -      }*/
++ WinLdrMapSpecialPages(ULONG PcrBasePage)
+  {
 -      Tss = (PKTSS)(KSEG0_BASE | (TssBasePage << MM_PAGE_SHIFT));
 - 
 -      // Unmap what is not needed from kernel page table
 -      MempDisablePages();
 - 
 -      // Fill the memory descriptor list and 
 -      //PrepareMemoryDescriptorList();
 -      DPRINTM(DPRINT_WINDOWS, "Memory Descriptor List prepared, printing PDE\n");
 -      List_PaToVa(&LoaderBlock->MemoryDescriptorListHead);
 - 
 - #if DBG
 -      {
 -              ULONG *PDE_Addr=(ULONG *)PDE;//0xC0300000;
 -              int j;
 - 
 -              DPRINTM(DPRINT_WINDOWS, "\nPDE\n");
 - 
 -              for (i=0; i<128; i++)
 -              {
 -                      DPRINTM(DPRINT_WINDOWS, "0x%04X | ", i*8);
+  
+       //VideoDisplayString(L"Hello from VGA, going into the kernel\n");
+       DPRINTM(DPRINT_WINDOWS, "HalPageTable: 0x%X\n", HalPageTable);
+  
+       // Page Tables have been setup, make special handling for PCR and TSS
+       // (which is done in BlSetupFotNt in usual ntldr)
+       HalPageTable[(KI_USER_SHARED_DATA - 0xFFC00000) >> MM_PAGE_SHIFT].PageFrameNumber = PcrBasePage+1;
+       HalPageTable[(KI_USER_SHARED_DATA - 0xFFC00000) >> MM_PAGE_SHIFT].Valid = 1;
+       HalPageTable[(KI_USER_SHARED_DATA - 0xFFC00000) >> MM_PAGE_SHIFT].Write = 1;
+  
+       HalPageTable[(KIP0PCRADDRESS - 0xFFC00000) >> MM_PAGE_SHIFT].PageFrameNumber = PcrBasePage;
+       HalPageTable[(KIP0PCRADDRESS - 0xFFC00000) >> MM_PAGE_SHIFT].Valid = 1;
+       HalPageTable[(KIP0PCRADDRESS - 0xFFC00000) >> MM_PAGE_SHIFT].Write = 1;
+  
+       // Map APIC
+       WinLdrpMapApic();
+  
+       // Map VGA memory
+       //VideoMemoryBase = MmMapIoSpace(0xb8000, 4000, MmNonCached);
+       //DPRINTM(DPRINT_WINDOWS, "VideoMemoryBase: 0x%X\n", VideoMemoryBase);
+  
 -                      for (j=0; j<8; j++)
 -                      {
 -                              DPRINTM(DPRINT_WINDOWS, "0x%08X ", PDE_Addr[i*8+j]);
 -                      }
++     return TRUE;
++ }
+  
 -                      DPRINTM(DPRINT_WINDOWS, "\n");
 -              }
 -      }
 - #endif
+  
 -      // Set processor context
 -      WinLdrSetProcessorContext(GdtIdt, KIP0PCRADDRESS, KSEG0_BASE | (TssBasePage << MM_PAGE_SHIFT));
 - 
 -      // Zero KI_USER_SHARED_DATA page
 -      memset((PVOID)KI_USER_SHARED_DATA, 0, MM_PAGE_SIZE);
 - 
 -      return TRUE;
 - }
 - 
 - // Two special things this func does: it sorts descriptors,
 - // and it merges free ones
 - VOID
 - WinLdrInsertDescriptor(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
 -                        IN PMEMORY_ALLOCATION_DESCRIPTOR NewDescriptor)
 - {
 -      PLIST_ENTRY ListHead = &LoaderBlock->MemoryDescriptorListHead;
 -      PLIST_ENTRY PreviousEntry, NextEntry;
 -      PMEMORY_ALLOCATION_DESCRIPTOR PreviousDescriptor = NULL, NextDescriptor = NULL;
 - 
 -      DPRINTM(DPRINT_WINDOWS, "BP=0x%X PC=0x%X %s\n", NewDescriptor->BasePage,
 -              NewDescriptor->PageCount, MemTypeDesc[NewDescriptor->MemoryType]);
 - 
 -      /* Find a place where to insert the new descriptor to */
 -      PreviousEntry = ListHead;
 -      NextEntry = ListHead->Flink;
 -      while (NextEntry != ListHead)
 -      {
 -              NextDescriptor = CONTAINING_RECORD(NextEntry,
 -                      MEMORY_ALLOCATION_DESCRIPTOR,
 -                      ListEntry);
 -              if (NewDescriptor->BasePage < NextDescriptor->BasePage)
 -                      break;
 - 
 -              PreviousEntry = NextEntry;
 -              PreviousDescriptor = NextDescriptor;
 -              NextEntry = NextEntry->Flink;
 -      }
 - 
 -      /* Don't forget about merging free areas */
 -      if (NewDescriptor->MemoryType != LoaderFree)
 -      {
 -              /* Just insert, nothing to merge */
 -              InsertHeadList(PreviousEntry, &NewDescriptor->ListEntry);
 -      }
 -      else
 -      {
 -              /* Previous block also free? */
 -              if ((PreviousEntry != ListHead) && (PreviousDescriptor->MemoryType == LoaderFree) &&
 -                      ((PreviousDescriptor->BasePage + PreviousDescriptor->PageCount) ==
 -                      NewDescriptor->BasePage))
 -              {
 -                      /* Just enlarge previous descriptor's PageCount */
 -                      PreviousDescriptor->PageCount += NewDescriptor->PageCount;
 -                      NewDescriptor = PreviousDescriptor;
 -              }
 -              else
 -              {
 -                      /* Nope, just insert */
 -                      InsertHeadList(PreviousEntry, &NewDescriptor->ListEntry);
 -              }
 - 
 -              /* Next block is free ?*/
 -              if ((NextEntry != ListHead) &&
 -                      (NextDescriptor->MemoryType == LoaderFree) &&
 -                      ((NewDescriptor->BasePage + NewDescriptor->PageCount) == NextDescriptor->BasePage))
 -              {
 -                      /* Enlarge next descriptor's PageCount */
 -                      NewDescriptor->PageCount += NextDescriptor->PageCount;
 -                      RemoveEntryList(&NextDescriptor->ListEntry);
 -              }
 -      }
 - 
 -      return;
 - }
 - 
 - VOID
 - WinLdrSetProcessorContext(PVOID GdtIdt, IN ULONG Pcr, IN ULONG Tss)
 - {
 -      GDTIDT GdtDesc, IdtDesc, OldIdt;
 -      PKGDTENTRY      pGdt;
 -      PKIDTENTRY      pIdt;
 -      ULONG Ldt = 0;
 -      //ULONG i;
 - 
 -      DPRINTM(DPRINT_WINDOWS, "GDtIdt %p, Pcr %p, Tss 0x%08X\n",
 -              GdtIdt, Pcr, Tss);
 - 
++ VOID
++ WinLdrSetProcessorContext(PVOID GdtIdt, IN ULONG Pcr, IN ULONG Tss)
++ {
++      GDTIDT GdtDesc, IdtDesc, OldIdt;
++      PKGDTENTRY      pGdt;
++      PKIDTENTRY      pIdt;
++      ULONG Ldt = 0;
++      //ULONG i;
+  
++      DPRINTM(DPRINT_WINDOWS, "GDtIdt %p, Pcr %p, Tss 0x%08X\n",
++              GdtIdt, Pcr, Tss);
+  
+       // Enable paging
+       //BS->ExitBootServices(ImageHandle,MapKey);
+  
+       // Disable Interrupts
+       _disable();
+  
+       // Re-initalize EFLAGS
+       __writeeflags(0);
+  
+       // Set the PDBR
+       __writecr3((ULONG_PTR)PDE);
+  
+       // Enable paging by modifying CR0
+       __writecr0(__readcr0() | CR0_PG);
+  
  -    int j;
+       // Kernel expects the PCR to be zero-filled on startup
+       // FIXME: Why zero it here when we can zero it right after allocation?
+       RtlZeroMemory((PVOID)Pcr, MM_PAGE_SIZE); //FIXME: Why zero only 1 page when we allocate 2?
+  
+       // Get old values of GDT and IDT
+       Ke386GetGlobalDescriptorTable(&GdtDesc);
+       __sidt(&IdtDesc);
+  
+       // Save old IDT
+       OldIdt.Base = IdtDesc.Base;
+       OldIdt.Limit = IdtDesc.Limit;
+  
+       // Prepare new IDT+GDT
+       GdtDesc.Base  = KSEG0_BASE | (ULONG_PTR)GdtIdt;
+       GdtDesc.Limit = NUM_GDT * sizeof(KGDTENTRY) - 1;
+       IdtDesc.Base  = (ULONG)((PUCHAR)GdtDesc.Base + GdtDesc.Limit + 1);
+       IdtDesc.Limit = NUM_IDT * sizeof(KIDTENTRY) - 1;
+  
+       // ========================
+       // Fill all descriptors now
+       // ========================
+  
+       pGdt = (PKGDTENTRY)GdtDesc.Base;
+       pIdt = (PKIDTENTRY)IdtDesc.Base;
+  
+       //
+       // Code selector (0x8)
+       // Flat 4Gb
+       //
+       pGdt[1].LimitLow                                = 0xFFFF;
+       pGdt[1].BaseLow                                 = 0;
+       pGdt[1].HighWord.Bytes.BaseMid  = 0;
+       pGdt[1].HighWord.Bytes.Flags1   = 0x9A;
+       pGdt[1].HighWord.Bytes.Flags2   = 0xCF;
+       pGdt[1].HighWord.Bytes.BaseHi   = 0;
+  
+       //
+       // Data selector (0x10)
+       // Flat 4Gb
+       //
+       pGdt[2].LimitLow                                = 0xFFFF;
+       pGdt[2].BaseLow                                 = 0;
+       pGdt[2].HighWord.Bytes.BaseMid  = 0;
+       pGdt[2].HighWord.Bytes.Flags1   = 0x92;
+       pGdt[2].HighWord.Bytes.Flags2   = 0xCF;
+       pGdt[2].HighWord.Bytes.BaseHi   = 0;
+  
+       //
+       // Selector (0x18)
+       // Flat 2Gb
+       //
+       pGdt[3].LimitLow                                = 0xFFFF;
+       pGdt[3].BaseLow                                 = 0;
+       pGdt[3].HighWord.Bytes.BaseMid  = 0;
+       pGdt[3].HighWord.Bytes.Flags1   = 0xFA;
+       pGdt[3].HighWord.Bytes.Flags2   = 0xCF;
+       pGdt[3].HighWord.Bytes.BaseHi   = 0;
+  
+       //
+       // Selector (0x20)
+       // Flat 2Gb
+       //
+       pGdt[4].LimitLow                                = 0xFFFF;
+       pGdt[4].BaseLow                                 = 0;
+       pGdt[4].HighWord.Bytes.BaseMid  = 0;
+       pGdt[4].HighWord.Bytes.Flags1   = 0xF2;
+       pGdt[4].HighWord.Bytes.Flags2   = 0xCF;
+       pGdt[4].HighWord.Bytes.BaseHi   = 0;
+  
+       //
+       // TSS Selector (0x28)
+       //
+       pGdt[5].LimitLow                                = 0x78-1; //FIXME: Check this
+       pGdt[5].BaseLow = (USHORT)(Tss & 0xffff);
+       pGdt[5].HighWord.Bytes.BaseMid = (UCHAR)((Tss >> 16) & 0xff);
+       pGdt[5].HighWord.Bytes.Flags1   = 0x89;
+       pGdt[5].HighWord.Bytes.Flags2   = 0x00;
+       pGdt[5].HighWord.Bytes.BaseHi  = (UCHAR)((Tss >> 24) & 0xff);
+  
+       //
+       // PCR Selector (0x30)
+       //
+       pGdt[6].LimitLow                                = 0x01;
+       pGdt[6].BaseLow  = (USHORT)(Pcr & 0xffff);
+       pGdt[6].HighWord.Bytes.BaseMid = (UCHAR)((Pcr >> 16) & 0xff);
+       pGdt[6].HighWord.Bytes.Flags1   = 0x92;
+       pGdt[6].HighWord.Bytes.Flags2   = 0xC0;
+       pGdt[6].HighWord.Bytes.BaseHi  = (UCHAR)((Pcr >> 24) & 0xff);
+  
+       //
+       // Selector (0x38)
+       //
+       pGdt[7].LimitLow                                = 0xFFFF;
+       pGdt[7].BaseLow                                 = 0;
+       pGdt[7].HighWord.Bytes.BaseMid  = 0;
+       pGdt[7].HighWord.Bytes.Flags1   = 0xF3;
+       pGdt[7].HighWord.Bytes.Flags2   = 0x40;
+       pGdt[7].HighWord.Bytes.BaseHi   = 0;
+  
+       //
+       // Some BIOS stuff (0x40)
+       //
+       pGdt[8].LimitLow                                = 0xFFFF;
+       pGdt[8].BaseLow                                 = 0x400;
+       pGdt[8].HighWord.Bytes.BaseMid  = 0;
+       pGdt[8].HighWord.Bytes.Flags1   = 0xF2;
+       pGdt[8].HighWord.Bytes.Flags2   = 0x0;
+       pGdt[8].HighWord.Bytes.BaseHi   = 0;
+  
+       //
+       // Selector (0x48)
+       //
+       pGdt[9].LimitLow                                = 0;
+       pGdt[9].BaseLow                                 = 0;
+       pGdt[9].HighWord.Bytes.BaseMid  = 0;
+       pGdt[9].HighWord.Bytes.Flags1   = 0;
+       pGdt[9].HighWord.Bytes.Flags2   = 0;
+       pGdt[9].HighWord.Bytes.BaseHi   = 0;
+  
+       //
+       // Selector (0x50)
+       //
+       pGdt[10].LimitLow                               = 0xFFFF; //FIXME: Not correct!
+       pGdt[10].BaseLow                                = 0;
+       pGdt[10].HighWord.Bytes.BaseMid = 0x2;
+       pGdt[10].HighWord.Bytes.Flags1  = 0x89;
+       pGdt[10].HighWord.Bytes.Flags2  = 0;
+       pGdt[10].HighWord.Bytes.BaseHi  = 0;
+  
+       //
+       // Selector (0x58)
+       //
+       pGdt[11].LimitLow                               = 0xFFFF;
+       pGdt[11].BaseLow                                = 0;
+       pGdt[11].HighWord.Bytes.BaseMid = 0x2;
+       pGdt[11].HighWord.Bytes.Flags1  = 0x9A;
+       pGdt[11].HighWord.Bytes.Flags2  = 0;
+       pGdt[11].HighWord.Bytes.BaseHi  = 0;
+  
+       //
+       // Selector (0x60)
+       //
+       pGdt[12].LimitLow                               = 0xFFFF;
+       pGdt[12].BaseLow                                = 0; //FIXME: Maybe not correct, but noone cares
+       pGdt[12].HighWord.Bytes.BaseMid = 0x2;
+       pGdt[12].HighWord.Bytes.Flags1  = 0x92;
+       pGdt[12].HighWord.Bytes.Flags2  = 0;
+       pGdt[12].HighWord.Bytes.BaseHi  = 0;
+  
+       //
+       // Video buffer Selector (0x68)
+       //
+       pGdt[13].LimitLow                               = 0x3FFF;
+       pGdt[13].BaseLow                                = 0x8000;
+       pGdt[13].HighWord.Bytes.BaseMid = 0x0B;
+       pGdt[13].HighWord.Bytes.Flags1  = 0x92;
+       pGdt[13].HighWord.Bytes.Flags2  = 0;
+       pGdt[13].HighWord.Bytes.BaseHi  = 0;
+  
+       //
+       // Points to GDT (0x70)
+       //
+       pGdt[14].LimitLow                               = NUM_GDT*sizeof(KGDTENTRY) - 1;
+       pGdt[14].BaseLow                                = 0x7000;
+       pGdt[14].HighWord.Bytes.BaseMid = 0xFF;
+       pGdt[14].HighWord.Bytes.Flags1  = 0x92;
+       pGdt[14].HighWord.Bytes.Flags2  = 0;
+       pGdt[14].HighWord.Bytes.BaseHi  = 0xFF;
+  
+       //
+       // Some unused descriptors should go here
+       //
+  
+       // Copy the old IDT
+       RtlCopyMemory(pIdt, (PVOID)OldIdt.Base, OldIdt.Limit + 1);
+  
+       // Mask interrupts
+       //asm("cli\n"); // they are already masked before enabling paged mode
+  
+       // Load GDT+IDT
+       Ke386SetGlobalDescriptorTable(&GdtDesc);
+       __lidt(&IdtDesc);
+  
+       // Jump to proper CS and clear prefetch queue
+  #if defined(__GNUC__)
+       asm("ljmp       $0x08, $1f\n"
+               "1:\n");
+  #elif defined(_MSC_VER)
+       /* We can't express the above in MASM so we use this far return instead */
+       DbgPrint("WinLdrSetProcessorContext: Performing untested far-return\n");
+       __asm {
+               push 8
+               push offset resume
+               retf
+               resume:
+               };
+  #else
+  #error
+  #endif
+  
+       // Set SS selector
+       Ke386SetSs(0x10); // DataSelector=0x10
+  
+       // Set DS and ES selectors
+       Ke386SetDs(0x10);
+       Ke386SetEs(0x10); // this is vital for rep stosd
+  
+       // LDT = not used ever, thus set to 0
+       Ke386SetLocalDescriptorTable(Ldt);
+  
+       // Load TSR
+       Ke386SetTr(KGDT_TSS);
+  
+       // Clear GS
+       Ke386SetGs(0);
+  
+       // Set FS to PCR
+       Ke386SetFs(0x30);
+  
+               // Real end of the function, just for information
+               /* do not uncomment!
+               pop edi;
+               pop esi;
+               pop ebx;
+               mov esp, ebp;
+               pop ebp;
+               ret
+               */
+  }
++ 
++ VOID
++ MempDump()
++ {
++     ULONG *PDE_Addr=(ULONG *)PDE;//0xC0300000;
+++    int i, j;
++ 
++     DPRINTM(DPRINT_WINDOWS, "\nPDE\n");
++ 
++     for (i=0; i<128; i++)
++     {
++         DPRINTM(DPRINT_WINDOWS, "0x%04X | ", i*8);
++ 
++         for (j=0; j<8; j++)
++         {
++             DPRINTM(DPRINT_WINDOWS, "0x%08X ", PDE_Addr[i*8+j]);
++         }
++ 
++         DPRINTM(DPRINT_WINDOWS, "\n");
++     }
++ }
++ 
index 313413e,0000000,2ed849a..dd7b19e
mode 100644,000000,100644..100644
--- /dev/null
@@@@ -1,939 -1,0 -1,432 +1,428 @@@@
-  extern ULONG TotalNLSSize;
 + /*
 +  * PROJECT:         EFI Windows Loader
 +  * LICENSE:         GPL - See COPYING in the top level directory
 +  * FILE:            freeldr/winldr/wlmemory.c
 +  * PURPOSE:         Memory related routines
 +  * PROGRAMMERS:     Aleksey Bragin (aleksey@reactos.org)
 +  */
 + 
 + /* INCLUDES ***************************************************************/
 + 
 + #include <freeldr.h>
 + 
 + #include <ndk/asm.h>
 + #include <debug.h>
 + 
- -// This is needed because headers define wrong one for ReactOS
- -#undef KIP0PCRADDRESS
- -#define KIP0PCRADDRESS                      0xffdff000
-  
-  #define HYPER_SPACE_ENTRY       0x300
- -
 + extern ULONG LoaderPagesSpanned;
 + 
- -WinLdrSetProcessorContext(PVOID GdtIdt, IN ULONG Pcr, IN ULONG Tss);
-  
-  // This is needed only for SetProcessorContext routine
-  #pragma pack(2)
-       typedef struct
-       {
-               USHORT Limit;
-               ULONG Base;
-       } GDTIDT;
-  #pragma pack(4)
-  
-  /* GLOBALS ***************************************************************/
-  
-  PHARDWARE_PTE PDE;
-  PHARDWARE_PTE HalPageTable;
-  
-  PUCHAR PhysicalPageTablesBuffer;
-  PUCHAR KernelPageTablesBuffer;
-  ULONG PhysicalPageTables;
-  ULONG KernelPageTables;
-  
-  MEMORY_ALLOCATION_DESCRIPTOR *Mad;
-  ULONG MadCount = 0;
-  
-  
-  /* FUNCTIONS **************************************************************/
 + PCHAR  MemTypeDesc[]  = {
 +     "ExceptionBlock    ", // ?
 +     "SystemBlock       ", // ?
 +     "Free              ",
 +     "Bad               ", // used
 +     "LoadedProgram     ", // == Free
 +     "FirmwareTemporary ", // == Free
 +     "FirmwarePermanent ", // == Bad
 +     "OsloaderHeap      ", // used
 +     "OsloaderStack     ", // == Free
 +     "SystemCode        ",
 +     "HalCode           ",
 +     "BootDriver        ", // not used
 +     "ConsoleInDriver   ", // ?
 +     "ConsoleOutDriver  ", // ?
 +     "StartupDpcStack   ", // ?
 +     "StartupKernelStack", // ?
 +     "StartupPanicStack ", // ?
 +     "StartupPcrPage    ", // ?
 +     "StartupPdrPage    ", // ?
 +     "RegistryData      ", // used
 +     "MemoryData        ", // not used
 +     "NlsData           ", // used
 +     "SpecialMemory     ", // == Bad
 +     "BBTMemory         " // == Bad
 +     };
 + 
 + VOID
 + WinLdrpDumpMemoryDescriptors(PLOADER_PARAMETER_BLOCK LoaderBlock);
 + 
 + 
 + VOID
 + MempAddMemoryBlock(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
 +                    ULONG BasePage,
 +                    ULONG PageCount,
 +                    ULONG Type);
 + VOID
 + WinLdrInsertDescriptor(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
 +                        IN PMEMORY_ALLOCATION_DESCRIPTOR NewDescriptor);
 + 
 + VOID
 + WinLdrRemoveDescriptor(IN PMEMORY_ALLOCATION_DESCRIPTOR Descriptor);
 + 
 + VOID
-  MempAllocatePageTables()
-  {
-       ULONG NumPageTables, TotalSize;
-       PUCHAR Buffer;
-       // It's better to allocate PDE + PTEs contigiuos
-  
-       // Max number of entries = MaxPageNum >> 10
-       // FIXME: This is a number to describe ALL physical memory
-       // and windows doesn't expect ALL memory mapped...
-       NumPageTables = (GetSystemMemorySize() >> MM_PAGE_SHIFT) >> 10;
-  
-       DPRINTM(DPRINT_WINDOWS, "NumPageTables = %d\n", NumPageTables);
-  
-       // Allocate memory block for all these things:
-       // PDE, HAL mapping page table, physical mapping, kernel mapping
-       TotalSize = (1+1+NumPageTables*2)*MM_PAGE_SIZE;
-  
-       // PDE+HAL+KernelPTEs == MemoryData
-       Buffer = MmAllocateMemoryWithType(TotalSize, LoaderMemoryData);
-  
-       // Physical PTEs = FirmwareTemporary
-       PhysicalPageTablesBuffer = (PUCHAR)Buffer + TotalSize - NumPageTables*MM_PAGE_SIZE;
-       MmSetMemoryType(PhysicalPageTablesBuffer,
-                       NumPageTables*MM_PAGE_SIZE,
-                       LoaderFirmwareTemporary);
-  
-       // This check is now redundant
-       if (Buffer + (TotalSize - NumPageTables*MM_PAGE_SIZE) !=
-               PhysicalPageTablesBuffer)
-       {
-               DPRINTM(DPRINT_WINDOWS, "There was a problem allocating two adjacent blocks of memory!");
-       }
-  
-       if (Buffer == NULL || PhysicalPageTablesBuffer == NULL)
-       {
-               UiMessageBox("Impossible to allocate memory block for page tables!");
-               return FALSE;
-       }
-  
-       // Zero all this memory block
-       RtlZeroMemory(Buffer, TotalSize);
-  
-       // Set up pointers correctly now
-       PDE = (PHARDWARE_PTE)Buffer;
-  
-       // Map the page directory at 0xC0000000 (maps itself)
-       PDE[HYPER_SPACE_ENTRY].PageFrameNumber = (ULONG)PDE >> MM_PAGE_SHIFT;
-       PDE[HYPER_SPACE_ENTRY].Valid = 1;
-       PDE[HYPER_SPACE_ENTRY].Write = 1;
-  
-       // The last PDE slot is allocated for HAL's memory mapping (Virtual Addresses 0xFFC00000 - 0xFFFFFFFF)
-       HalPageTable = (PHARDWARE_PTE)&Buffer[MM_PAGE_SIZE*1];
-  
-       // Map it
-       PDE[1023].PageFrameNumber = (ULONG)HalPageTable >> MM_PAGE_SHIFT;
-       PDE[1023].Valid = 1;
-       PDE[1023].Write = 1;
-  
-       // Store pointer to the table for easier access
-       KernelPageTablesBuffer = &Buffer[MM_PAGE_SIZE*2];
-  
-       // Zero counters of page tables used
-       PhysicalPageTables = 0;
-       KernelPageTables = 0;
-  
-       return TRUE;
-  }
-  
-  VOID
-  MempAllocatePTE(ULONG Entry, PHARDWARE_PTE *PhysicalPT, PHARDWARE_PTE *KernelPT)
-  {
-       //Print(L"Creating PDE Entry %X\n", Entry);
-  
-       // Identity mapping
-       *PhysicalPT = (PHARDWARE_PTE)&PhysicalPageTablesBuffer[PhysicalPageTables*MM_PAGE_SIZE];
-       PhysicalPageTables++;
-  
-       PDE[Entry].PageFrameNumber = (ULONG)*PhysicalPT >> MM_PAGE_SHIFT;
-       PDE[Entry].Valid = 1;
-       PDE[Entry].Write = 1;
-  
-       if (Entry+(KSEG0_BASE >> 22) > 1023)
-       {
-               DPRINTM(DPRINT_WINDOWS, "WARNING! Entry: %X > 1023\n", Entry+(KSEG0_BASE >> 22));
-       }
-  
-       // Kernel-mode mapping
-       *KernelPT = (PHARDWARE_PTE)&KernelPageTablesBuffer[KernelPageTables*MM_PAGE_SIZE];
-       KernelPageTables++;
-  
-       PDE[Entry+(KSEG0_BASE >> 22)].PageFrameNumber = ((ULONG)*KernelPT >> MM_PAGE_SHIFT);
-       PDE[Entry+(KSEG0_BASE >> 22)].Valid = 1;
-       PDE[Entry+(KSEG0_BASE >> 22)].Write = 1;
-  }
+++WinLdrSetProcessorContext(PVOID GdtIdt, IN ULONG_PTR Pcr, IN ULONG_PTR Tss);
 + 
 + BOOLEAN
-                               IN ULONG NumberOfPages)
-  {
-       PHARDWARE_PTE PhysicalPT;
-       PHARDWARE_PTE KernelPT;
-       ULONG Entry, Page;
-  
-       //Print(L"MempSetupPaging: SP 0x%X, Number: 0x%X\n", StartPage, NumberOfPages);
-       
-       // HACK
-       if (StartPage+NumberOfPages >= 0x80000)
-       {
-               //
-               // We can't map this as it requires more than 1 PDE
-               // and in fact it's not possible at all ;)
-               //
-               //Print(L"skipping...\n");
-               return TRUE;
-       }
++ MempAllocatePageTables();
 + 
 + BOOLEAN
 + MempSetupPaging(IN ULONG StartPage,
-       //
-       // Now actually set up the page tables for identity mapping
-       //
-       for (Page=StartPage; Page < StartPage+NumberOfPages; Page++)
-       {
-               Entry = Page >> 10;
++                              IN ULONG NumberOfPages);
 + 
-               if (((PULONG)PDE)[Entry] == 0)
-               {
-                       MempAllocatePTE(Entry, &PhysicalPT, &KernelPT);
-               }
-               else
-               {
-                       PhysicalPT = (PHARDWARE_PTE)(PDE[Entry].PageFrameNumber << MM_PAGE_SHIFT);
-                       KernelPT = (PHARDWARE_PTE)(PDE[Entry+(KSEG0_BASE >> 22)].PageFrameNumber << MM_PAGE_SHIFT);
-               }
++ BOOLEAN
++ WinLdrMapSpecialPages(ULONG PcrBasePage);
 + 
-               if (Page == 0)
-               {
-                       PhysicalPT[Page & 0x3ff].PageFrameNumber = Page;
-                       PhysicalPT[Page & 0x3ff].Valid = 0;
-                       PhysicalPT[Page & 0x3ff].Write = 0;
++ VOID
++ MempUnmapPage(ULONG Page);
 + 
-                       KernelPT[Page & 0x3ff].PageFrameNumber = Page;
-                       KernelPT[Page & 0x3ff].Valid = 0;
-                       KernelPT[Page & 0x3ff].Write = 0;
-               }
-               else
-               {
-                       PhysicalPT[Page & 0x3ff].PageFrameNumber = Page;
-                       PhysicalPT[Page & 0x3ff].Valid = 1;
-                       PhysicalPT[Page & 0x3ff].Write = 1;
++ VOID
++ MempDump();
 + 
-                       KernelPT[Page & 0x3ff].PageFrameNumber = Page;
-                       KernelPT[Page & 0x3ff].Valid = 1;
-                       KernelPT[Page & 0x3ff].Write = 1;
-               }
-       }
++ /* GLOBALS ***************************************************************/
 + 
-       return TRUE;
-  }
++ MEMORY_ALLOCATION_DESCRIPTOR *Mad;
++ ULONG MadCount = 0;
 + 
-                               PHARDWARE_PTE KernelPT;
-                               ULONG Entry = (Page >> 10) + (KSEG0_BASE >> 22);
-  
-                               if (PDE[Entry].Valid)
-                               {
-                                       KernelPT = (PHARDWARE_PTE)(PDE[Entry].PageFrameNumber << MM_PAGE_SHIFT);
-  
-                                       if (KernelPT)
-                                       {
-                                               KernelPT[Page & 0x3ff].PageFrameNumber = 0;
-                                               KernelPT[Page & 0x3ff].Valid = 0;
-                                               KernelPT[Page & 0x3ff].Write = 0;
-                                       }
-                               }
++ /* FUNCTIONS **************************************************************/
 + 
 + VOID
 + MempDisablePages()
 + {
 +      ULONG i;
 + 
 +      //
 +      // We need to delete kernel mapping from memory areas which are
 +      // marked as Special or Permanent memory (thus non-accessible)
 +      //
 + 
 +      for (i=0; i<MadCount; i++)
 +      {
 +              ULONG StartPage, EndPage, Page;
 + 
 +              StartPage = Mad[i].BasePage;
 +              EndPage = Mad[i].BasePage + Mad[i].PageCount;
 + 
 +              if (Mad[i].MemoryType == LoaderFirmwarePermanent ||
 +                      Mad[i].MemoryType == LoaderSpecialMemory ||
 +                      Mad[i].MemoryType == LoaderFree ||
 +                      (Mad[i].MemoryType == LoaderFirmwareTemporary && EndPage <= LoaderPagesSpanned) ||
 +                      Mad[i].MemoryType == LoaderOsloaderStack ||
 +                      Mad[i].MemoryType == LoaderLoadedProgram)
 +              {
 +                      //
 +                      // But, the first megabyte of memory always stays!
 +                      // And, to tell the truth, we don't care about what's higher
 +                      // than LoaderPagesSpanned
 +                      if (Mad[i].MemoryType == LoaderFirmwarePermanent ||
 +                              Mad[i].MemoryType == LoaderSpecialMemory)
 +                      {
 +                              if (StartPage < 0x100)
 +                                      StartPage = 0x100;
 + 
 +                              if (EndPage > LoaderPagesSpanned)
 +                                      EndPage = LoaderPagesSpanned;
 +                      }
 + 
 +                      for (Page = StartPage; Page < EndPage; Page++)
 +                      {
-  #ifdef _M_IX86
-  VOID
-  WinLdrpMapApic()
-  {
-       BOOLEAN LocalAPIC;
-       LARGE_INTEGER MsrValue;
-       ULONG APICAddress, CpuInfo[4];
-  
-       /* Check if we have a local APIC */
-       __cpuid((int*)CpuInfo, 1);
-       LocalAPIC = (((CpuInfo[3] >> 9) & 1) != 0);
-  
-       /* If there is no APIC, just return */
-       if (!LocalAPIC)
-               return;
-  
-       /* Read the APIC Address */
-       MsrValue.QuadPart = __readmsr(0x1B);
-       APICAddress = (MsrValue.LowPart & 0xFFFFF000);
-  
-       DPRINTM(DPRINT_WINDOWS, "Local APIC detected at address 0x%x\n",
-               APICAddress);
-  
-       /* Map it */
-       HalPageTable[(APIC_BASE - 0xFFC00000) >> MM_PAGE_SHIFT].PageFrameNumber
-               = APICAddress >> MM_PAGE_SHIFT;
-       HalPageTable[(APIC_BASE - 0xFFC00000) >> MM_PAGE_SHIFT].Valid = 1;
-       HalPageTable[(APIC_BASE - 0xFFC00000) >> MM_PAGE_SHIFT].Write = 1;
-       HalPageTable[(APIC_BASE - 0xFFC00000) >> MM_PAGE_SHIFT].WriteThrough = 1;
-       HalPageTable[(APIC_BASE - 0xFFC00000) >> MM_PAGE_SHIFT].CacheDisable = 1;
-  }
-  #else
-  VOID
-  WinLdrpMapApic()
-  {
-       /* Implement it for another arch */
-  }
-  #endif
-  
++                              MempUnmapPage(Page);
 +                      }
 +              }
 +      }
 + }
 + 
 + VOID
 + MempAddMemoryBlock(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
 +                    ULONG BasePage,
 +                    ULONG PageCount,
 +                    ULONG Type)
 + {
 +      BOOLEAN Status;
 + 
 +      //
 +      // Check for some weird stuff at the top
 +      //
 +      if (BasePage + PageCount > 0xF0000)
 +      {
 +              //
 +              // Just skip this, without even adding to MAD list
 +              //
 +              return;
 +      }
 + 
 +      //
 +      // Set Base page, page count and type
 +      //
 +      Mad[MadCount].BasePage = BasePage;
 +      Mad[MadCount].PageCount = PageCount;
 +      Mad[MadCount].MemoryType = Type;
 + 
 +      //
 +      // Check if it's more than the allowed for OS loader
 +      // if yes - don't map the pages, just add as FirmwareTemporary
 +      //
 +      if (BasePage + PageCount > LoaderPagesSpanned)
 +      {
 +              if (Mad[MadCount].MemoryType != LoaderSpecialMemory &&
 +                      Mad[MadCount].MemoryType != LoaderFirmwarePermanent &&
 +                      Mad[MadCount].MemoryType != LoaderFree)
 +              {
 +                      DPRINTM(DPRINT_WINDOWS, "Setting page %x %x to Temporary from %d\n",
 +                              BasePage, PageCount, Mad[MadCount].MemoryType);
 +                      Mad[MadCount].MemoryType = LoaderFirmwareTemporary;
 +              }
 + 
 +              WinLdrInsertDescriptor(LoaderBlock, &Mad[MadCount]);
 +              MadCount++;
 + 
 +              return;
 +      }
 +      
 +      //
 +      // Add descriptor
 +      //
 +      WinLdrInsertDescriptor(LoaderBlock, &Mad[MadCount]);
 +      MadCount++;
 + 
 +      //
 +      // Map it (don't map low 1Mb because it was already contigiously
 +      // mapped in WinLdrTurnOnPaging)
 +      //
 +      if (BasePage >= 0x100)
 +      {
 +              Status = MempSetupPaging(BasePage, PageCount);
 +              if (!Status)
 +              {
 +                      DPRINTM(DPRINT_WINDOWS, "Error during MempSetupPaging\n");
 +                      return;
 +              }
 +      }
 + }
 + 
-       //VideoDisplayString(L"Hello from VGA, going into the kernel\n");
-       DPRINTM(DPRINT_WINDOWS, "HalPageTable: 0x%X\n", HalPageTable);
-  
-       // Page Tables have been setup, make special handling for PCR and TSS
-       // (which is done in BlSetupFotNt in usual ntldr)
-       HalPageTable[(KI_USER_SHARED_DATA - 0xFFC00000) >> MM_PAGE_SHIFT].PageFrameNumber = PcrBasePage+1;
-       HalPageTable[(KI_USER_SHARED_DATA - 0xFFC00000) >> MM_PAGE_SHIFT].Valid = 1;
-       HalPageTable[(KI_USER_SHARED_DATA - 0xFFC00000) >> MM_PAGE_SHIFT].Write = 1;
-  
-       HalPageTable[(KIP0PCRADDRESS - 0xFFC00000) >> MM_PAGE_SHIFT].PageFrameNumber = PcrBasePage;
-       HalPageTable[(KIP0PCRADDRESS - 0xFFC00000) >> MM_PAGE_SHIFT].Valid = 1;
-       HalPageTable[(KIP0PCRADDRESS - 0xFFC00000) >> MM_PAGE_SHIFT].Write = 1;
-  
-       // Map APIC
-       WinLdrpMapApic();
-  
-       // Map VGA memory
-       //VideoMemoryBase = MmMapIoSpace(0xb8000, 4000, MmNonCached);
-       //DPRINTM(DPRINT_WINDOWS, "VideoMemoryBase: 0x%X\n", VideoMemoryBase);
 + BOOLEAN
 + WinLdrTurnOnPaging(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
 +                    ULONG PcrBasePage,
 +                    ULONG TssBasePage,
 +                    PVOID GdtIdt)
 + {
 +      ULONG i, PagesCount, MemoryMapSizeInPages;
 +      ULONG LastPageIndex, LastPageType, MemoryMapStartPage;
 +      PPAGE_LOOKUP_TABLE_ITEM MemoryMap;
 +      ULONG NoEntries;
 +      PKTSS Tss;
 +      BOOLEAN Status;
 + 
 +      //
 +      // Creating a suitable memory map for the Windows can be tricky, so let's
 +      // give a few advices:
 +      // 1) One must not map the whole available memory pages to PDE!
 +      //    Map only what's needed - 16Mb, 24Mb, 32Mb max I think,
 +      //    thus occupying 4, 6 or 8 PDE entries for identical mapping,
 +      //    the same quantity for KSEG0_BASE mapping, one more entry for
 +      //    hyperspace and one more entry for HAL physical pages mapping.
 +      // 2) Memory descriptors must map *the whole* physical memory
 +      //    showing any memory above 16/24/32 as FirmwareTemporary
 +      //
 +      // 3) Overall memory blocks count must not exceed 30 (?? why?)
 +      //
 + 
 +      //
 +      // During MmInitMachineDependent, the kernel zeroes PDE at the following address
 +      // 0xC0300000 - 0xC03007FC
 +      //
 +      // Then it finds the best place for non-paged pool:
 +      // StartPde C0300F70, EndPde C0300FF8, NumberOfPages C13, NextPhysPage 3AD
 +      //
 + 
 +      // Before we start mapping pages, create a block of memory, which will contain
 +      // PDE and PTEs
 +      if (MempAllocatePageTables() == FALSE)
 +              return FALSE;
 + 
 +      // Allocate memory for memory allocation descriptors
 +      Mad = MmHeapAlloc(sizeof(MEMORY_ALLOCATION_DESCRIPTOR) * 1024);
 + 
 +      // Setup an entry for each descriptor
 +      MemoryMap = MmGetMemoryMap(&NoEntries);
 +      if (MemoryMap == NULL)
 +      {
 +              UiMessageBox("Can not retrieve the current memory map");
 +              return FALSE;
 +      }
 + 
 +      // Calculate parameters of the memory map
 +      MemoryMapStartPage = (ULONG_PTR)MemoryMap >> MM_PAGE_SHIFT;
 +      MemoryMapSizeInPages = NoEntries * sizeof(PAGE_LOOKUP_TABLE_ITEM);
 + 
 +      DPRINTM(DPRINT_WINDOWS, "Got memory map with %d entries\n", NoEntries);
 + 
 +      // Always contigiously map low 1Mb of memory
 +      Status = MempSetupPaging(0, 0x100);
 +      if (!Status)
 +      {
 +              DPRINTM(DPRINT_WINDOWS, "Error during MempSetupPaging of low 1Mb\n");
 +              return FALSE;
 +      }
 + 
 +      // Construct a good memory map from what we've got,
 +      // but mark entries which the memory allocation bitmap takes
 +      // as free entries (this is done in order to have the ability
 +      // to place mem alloc bitmap outside lower 16Mb zone)
 +      PagesCount = 1;
 +      LastPageIndex = 0;
 +      LastPageType = MemoryMap[0].PageAllocated;
 +      for(i=1;i<NoEntries;i++)
 +      {
 +              // Check if its memory map itself
 +              if (i >= MemoryMapStartPage &&
 +                      i < (MemoryMapStartPage+MemoryMapSizeInPages))
 +              {
 +                      // Exclude it if current page belongs to the memory map
 +                      MemoryMap[i].PageAllocated = LoaderFree;
 +              }
 + 
 +              // Process entry
 +              if (MemoryMap[i].PageAllocated == LastPageType &&
 +                      (i != NoEntries-1) )
 +              {
 +                      PagesCount++;
 +              }
 +              else
 +              {
 +                      // Add the resulting region
 +                      MempAddMemoryBlock(LoaderBlock, LastPageIndex, PagesCount, LastPageType);
 + 
 +                      // Reset our counter vars
 +                      LastPageIndex = i;
 +                      LastPageType = MemoryMap[i].PageAllocated;
 +                      PagesCount = 1;
 +              }
 +      }
 + 
 +      // TEMP, DEBUG!
 +      // adding special reserved memory zones for vmware workstation
 + #if 0
 +      {
 +              Mad[MadCount].BasePage = 0xfec00;
 +              Mad[MadCount].PageCount = 0x10;
 +              Mad[MadCount].MemoryType = LoaderSpecialMemory;
 +              WinLdrInsertDescriptor(LoaderBlock, &Mad[MadCount]);
 +              MadCount++;
 + 
 +              Mad[MadCount].BasePage = 0xfee00;
 +              Mad[MadCount].PageCount = 0x1;
 +              Mad[MadCount].MemoryType = LoaderSpecialMemory;
 +              WinLdrInsertDescriptor(LoaderBlock, &Mad[MadCount]);
 +              MadCount++;
 + 
 +              Mad[MadCount].BasePage = 0xfffe0;
 +              Mad[MadCount].PageCount = 0x20;
 +              Mad[MadCount].MemoryType = LoaderSpecialMemory;
 +              WinLdrInsertDescriptor(LoaderBlock, &Mad[MadCount]);
 +              MadCount++;
 +      }
 + #endif
 + 
 +      DPRINTM(DPRINT_WINDOWS, "MadCount: %d\n", MadCount);
 + 
 +      WinLdrpDumpMemoryDescriptors(LoaderBlock); //FIXME: Delete!
 + 
 +      // Map our loader image, so we can continue running
 +      /*Status = MempSetupPaging(OsLoaderBase >> MM_PAGE_SHIFT, OsLoaderSize >> MM_PAGE_SHIFT);
 +      if (!Status)
 +      {
 +              UiMessageBox("Error during MempSetupPaging");
 +              return;
 +      }*/
 + 
-       {
-               ULONG *PDE_Addr=(ULONG *)PDE;//0xC0300000;
-               int j;
-  
-               DPRINTM(DPRINT_WINDOWS, "\nPDE\n");
-  
-               for (i=0; i<128; i++)
-               {
-                       DPRINTM(DPRINT_WINDOWS, "0x%04X | ", i*8);
-  
-                       for (j=0; j<8; j++)
-                       {
-                               DPRINTM(DPRINT_WINDOWS, "0x%08X ", PDE_Addr[i*8+j]);
-                       }
-  
-                       DPRINTM(DPRINT_WINDOWS, "\n");
-               }
-       }
++      /* Map stuff like PCR, KI_USER_SHARED_DATA and Apic */
++      WinLdrMapSpecialPages(PcrBasePage);
 + 
 +      Tss = (PKTSS)(KSEG0_BASE | (TssBasePage << MM_PAGE_SHIFT));
 + 
 +      // Unmap what is not needed from kernel page table
 +      MempDisablePages();
 + 
 +      // Fill the memory descriptor list and 
 +      //PrepareMemoryDescriptorList();
 +      DPRINTM(DPRINT_WINDOWS, "Memory Descriptor List prepared, printing PDE\n");
 +      List_PaToVa(&LoaderBlock->MemoryDescriptorListHead);
 + 
 + #if DBG
-  
-       // Enable paging
-       //BS->ExitBootServices(ImageHandle,MapKey);
-  
-       // Disable Interrupts
-       _disable();
-  
-       // Re-initalize EFLAGS
-       __writeeflags(0);
-  
-       // Set the PDBR
-       __writecr3((ULONG_PTR)PDE);
-  
-       // Enable paging by modifying CR0
-       __writecr0(__readcr0() | CR0_PG);
-  
++     MempDump();
 + #endif
 + 
-  VOID
-  WinLdrSetProcessorContext(PVOID GdtIdt, IN ULONG Pcr, IN ULONG Tss)
-  {
-       GDTIDT GdtDesc, IdtDesc, OldIdt;
-       PKGDTENTRY      pGdt;
-       PKIDTENTRY      pIdt;
-       ULONG Ldt = 0;
-       //ULONG i;
-  
-       DPRINTM(DPRINT_WINDOWS, "GDtIdt %p, Pcr %p, Tss 0x%08X\n",
-               GdtIdt, Pcr, Tss);
-  
-       // Kernel expects the PCR to be zero-filled on startup
-       // FIXME: Why zero it here when we can zero it right after allocation?
-       RtlZeroMemory((PVOID)Pcr, MM_PAGE_SIZE); //FIXME: Why zero only 1 page when we allocate 2?
-  
-       // Get old values of GDT and IDT
-       Ke386GetGlobalDescriptorTable(&GdtDesc);
-       __sidt(&IdtDesc);
-  
-       // Save old IDT
-       OldIdt.Base = IdtDesc.Base;
-       OldIdt.Limit = IdtDesc.Limit;
-  
-       // Prepare new IDT+GDT
-       GdtDesc.Base  = KSEG0_BASE | (ULONG_PTR)GdtIdt;
-       GdtDesc.Limit = NUM_GDT * sizeof(KGDTENTRY) - 1;
-       IdtDesc.Base  = (ULONG)((PUCHAR)GdtDesc.Base + GdtDesc.Limit + 1);
-       IdtDesc.Limit = NUM_IDT * sizeof(KIDTENTRY) - 1;
-  
-       // ========================
-       // Fill all descriptors now
-       // ========================
-  
-       pGdt = (PKGDTENTRY)GdtDesc.Base;
-       pIdt = (PKIDTENTRY)IdtDesc.Base;
-  
-       //
-       // Code selector (0x8)
-       // Flat 4Gb
-       //
-       pGdt[1].LimitLow                                = 0xFFFF;
-       pGdt[1].BaseLow                                 = 0;
-       pGdt[1].HighWord.Bytes.BaseMid  = 0;
-       pGdt[1].HighWord.Bytes.Flags1   = 0x9A;
-       pGdt[1].HighWord.Bytes.Flags2   = 0xCF;
-       pGdt[1].HighWord.Bytes.BaseHi   = 0;
-  
-       //
-       // Data selector (0x10)
-       // Flat 4Gb
-       //
-       pGdt[2].LimitLow                                = 0xFFFF;
-       pGdt[2].BaseLow                                 = 0;
-       pGdt[2].HighWord.Bytes.BaseMid  = 0;
-       pGdt[2].HighWord.Bytes.Flags1   = 0x92;
-       pGdt[2].HighWord.Bytes.Flags2   = 0xCF;
-       pGdt[2].HighWord.Bytes.BaseHi   = 0;
-  
-       //
-       // Selector (0x18)
-       // Flat 2Gb
-       //
-       pGdt[3].LimitLow                                = 0xFFFF;
-       pGdt[3].BaseLow                                 = 0;
-       pGdt[3].HighWord.Bytes.BaseMid  = 0;
-       pGdt[3].HighWord.Bytes.Flags1   = 0xFA;
-       pGdt[3].HighWord.Bytes.Flags2   = 0xCF;
-       pGdt[3].HighWord.Bytes.BaseHi   = 0;
-  
-       //
-       // Selector (0x20)
-       // Flat 2Gb
-       //
-       pGdt[4].LimitLow                                = 0xFFFF;
-       pGdt[4].BaseLow                                 = 0;
-       pGdt[4].HighWord.Bytes.BaseMid  = 0;
-       pGdt[4].HighWord.Bytes.Flags1   = 0xF2;
-       pGdt[4].HighWord.Bytes.Flags2   = 0xCF;
-       pGdt[4].HighWord.Bytes.BaseHi   = 0;
-  
-       //
-       // TSS Selector (0x28)
-       //
-       pGdt[5].LimitLow                                = 0x78-1; //FIXME: Check this
-       pGdt[5].BaseLow = (USHORT)(Tss & 0xffff);
-       pGdt[5].HighWord.Bytes.BaseMid = (UCHAR)((Tss >> 16) & 0xff);
-       pGdt[5].HighWord.Bytes.Flags1   = 0x89;
-       pGdt[5].HighWord.Bytes.Flags2   = 0x00;
-       pGdt[5].HighWord.Bytes.BaseHi  = (UCHAR)((Tss >> 24) & 0xff);
-  
-       //
-       // PCR Selector (0x30)
-       //
-       pGdt[6].LimitLow                                = 0x01;
-       pGdt[6].BaseLow  = (USHORT)(Pcr & 0xffff);
-       pGdt[6].HighWord.Bytes.BaseMid = (UCHAR)((Pcr >> 16) & 0xff);
-       pGdt[6].HighWord.Bytes.Flags1   = 0x92;
-       pGdt[6].HighWord.Bytes.Flags2   = 0xC0;
-       pGdt[6].HighWord.Bytes.BaseHi  = (UCHAR)((Pcr >> 24) & 0xff);
-  
-       //
-       // Selector (0x38)
-       //
-       pGdt[7].LimitLow                                = 0xFFFF;
-       pGdt[7].BaseLow                                 = 0;
-       pGdt[7].HighWord.Bytes.BaseMid  = 0;
-       pGdt[7].HighWord.Bytes.Flags1   = 0xF3;
-       pGdt[7].HighWord.Bytes.Flags2   = 0x40;
-       pGdt[7].HighWord.Bytes.BaseHi   = 0;
-  
-       //
-       // Some BIOS stuff (0x40)
-       //
-       pGdt[8].LimitLow                                = 0xFFFF;
-       pGdt[8].BaseLow                                 = 0x400;
-       pGdt[8].HighWord.Bytes.BaseMid  = 0;
-       pGdt[8].HighWord.Bytes.Flags1   = 0xF2;
-       pGdt[8].HighWord.Bytes.Flags2   = 0x0;
-       pGdt[8].HighWord.Bytes.BaseHi   = 0;
-  
-       //
-       // Selector (0x48)
-       //
-       pGdt[9].LimitLow                                = 0;
-       pGdt[9].BaseLow                                 = 0;
-       pGdt[9].HighWord.Bytes.BaseMid  = 0;
-       pGdt[9].HighWord.Bytes.Flags1   = 0;
-       pGdt[9].HighWord.Bytes.Flags2   = 0;
-       pGdt[9].HighWord.Bytes.BaseHi   = 0;
-  
-       //
-       // Selector (0x50)
-       //
-       pGdt[10].LimitLow                               = 0xFFFF; //FIXME: Not correct!
-       pGdt[10].BaseLow                                = 0;
-       pGdt[10].HighWord.Bytes.BaseMid = 0x2;
-       pGdt[10].HighWord.Bytes.Flags1  = 0x89;
-       pGdt[10].HighWord.Bytes.Flags2  = 0;
-       pGdt[10].HighWord.Bytes.BaseHi  = 0;
-  
-       //
-       // Selector (0x58)
-       //
-       pGdt[11].LimitLow                               = 0xFFFF;
-       pGdt[11].BaseLow                                = 0;
-       pGdt[11].HighWord.Bytes.BaseMid = 0x2;
-       pGdt[11].HighWord.Bytes.Flags1  = 0x9A;
-       pGdt[11].HighWord.Bytes.Flags2  = 0;
-       pGdt[11].HighWord.Bytes.BaseHi  = 0;
-  
-       //
-       // Selector (0x60)
-       //
-       pGdt[12].LimitLow                               = 0xFFFF;
-       pGdt[12].BaseLow                                = 0; //FIXME: Maybe not correct, but noone cares
-       pGdt[12].HighWord.Bytes.BaseMid = 0x2;
-       pGdt[12].HighWord.Bytes.Flags1  = 0x92;
-       pGdt[12].HighWord.Bytes.Flags2  = 0;
-       pGdt[12].HighWord.Bytes.BaseHi  = 0;
-  
-       //
-       // Video buffer Selector (0x68)
-       //
-       pGdt[13].LimitLow                               = 0x3FFF;
-       pGdt[13].BaseLow                                = 0x8000;
-       pGdt[13].HighWord.Bytes.BaseMid = 0x0B;
-       pGdt[13].HighWord.Bytes.Flags1  = 0x92;
-       pGdt[13].HighWord.Bytes.Flags2  = 0;
-       pGdt[13].HighWord.Bytes.BaseHi  = 0;
-  
-       //
-       // Points to GDT (0x70)
-       //
-       pGdt[14].LimitLow                               = NUM_GDT*sizeof(KGDTENTRY) - 1;
-       pGdt[14].BaseLow                                = 0x7000;
-       pGdt[14].HighWord.Bytes.BaseMid = 0xFF;
-       pGdt[14].HighWord.Bytes.Flags1  = 0x92;
-       pGdt[14].HighWord.Bytes.Flags2  = 0;
-       pGdt[14].HighWord.Bytes.BaseHi  = 0xFF;
-  
-       //
-       // Some unused descriptors should go here
-       //
-  
-       // Copy the old IDT
-       RtlCopyMemory(pIdt, (PVOID)OldIdt.Base, OldIdt.Limit + 1);
-  
-       // Mask interrupts
-       //asm("cli\n"); // they are already masked before enabling paged mode
-  
-       // Load GDT+IDT
-       Ke386SetGlobalDescriptorTable(&GdtDesc);
-       __lidt(&IdtDesc);
-  
-       // Jump to proper CS and clear prefetch queue
-  #if defined(__GNUC__)
-       asm("ljmp       $0x08, $1f\n"
-               "1:\n");
-  #elif defined(_MSC_VER)
-       /* We can't express the above in MASM so we use this far return instead */
-       DbgPrint("WinLdrSetProcessorContext: Performing untested far-return\n");
-       __asm {
-               push 8
-               push offset resume
-               retf
-               resume:
-               };
-  #else
-  #error
-  #endif
-  
-       // Set SS selector
-       Ke386SetSs(0x10); // DataSelector=0x10
-  
-       // Set DS and ES selectors
-       Ke386SetDs(0x10);
-       Ke386SetEs(0x10); // this is vital for rep stosd
-  
-       // LDT = not used ever, thus set to 0
-       Ke386SetLocalDescriptorTable(Ldt);
-  
-       // Load TSR
-       Ke386SetTr(KGDT_TSS);
-  
-       // Clear GS
-       Ke386SetGs(0);
-  
-       // Set FS to PCR
-       Ke386SetFs(0x30);
-  
-               // Real end of the function, just for information
-               /* do not uncomment!
-               pop edi;
-               pop esi;
-               pop ebx;
-               mov esp, ebp;
-               pop ebp;
-               ret
-               */
-  }
 +      // Set processor context
 +      WinLdrSetProcessorContext(GdtIdt, KIP0PCRADDRESS, KSEG0_BASE | (TssBasePage << MM_PAGE_SHIFT));
 + 
 +      // Zero KI_USER_SHARED_DATA page
 +      memset((PVOID)KI_USER_SHARED_DATA, 0, MM_PAGE_SIZE);
 + 
 +      return TRUE;
 + }
 + 
 + // Two special things this func does: it sorts descriptors,
 + // and it merges free ones
 + VOID
 + WinLdrInsertDescriptor(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
 +                        IN PMEMORY_ALLOCATION_DESCRIPTOR NewDescriptor)
 + {
 +      PLIST_ENTRY ListHead = &LoaderBlock->MemoryDescriptorListHead;
 +      PLIST_ENTRY PreviousEntry, NextEntry;
 +      PMEMORY_ALLOCATION_DESCRIPTOR PreviousDescriptor = NULL, NextDescriptor = NULL;
 + 
 +      DPRINTM(DPRINT_WINDOWS, "BP=0x%X PC=0x%X %s\n", NewDescriptor->BasePage,
 +              NewDescriptor->PageCount, MemTypeDesc[NewDescriptor->MemoryType]);
 + 
 +      /* Find a place where to insert the new descriptor to */
 +      PreviousEntry = ListHead;
 +      NextEntry = ListHead->Flink;
 +      while (NextEntry != ListHead)
 +      {
 +              NextDescriptor = CONTAINING_RECORD(NextEntry,
 +                      MEMORY_ALLOCATION_DESCRIPTOR,
 +                      ListEntry);
 +              if (NewDescriptor->BasePage < NextDescriptor->BasePage)
 +                      break;
 + 
 +              PreviousEntry = NextEntry;
 +              PreviousDescriptor = NextDescriptor;
 +              NextEntry = NextEntry->Flink;
 +      }
 + 
 +      /* Don't forget about merging free areas */
 +      if (NewDescriptor->MemoryType != LoaderFree)
 +      {
 +              /* Just insert, nothing to merge */
 +              InsertHeadList(PreviousEntry, &NewDescriptor->ListEntry);
 +      }
 +      else
 +      {
 +              /* Previous block also free? */
 +              if ((PreviousEntry != ListHead) && (PreviousDescriptor->MemoryType == LoaderFree) &&
 +                      ((PreviousDescriptor->BasePage + PreviousDescriptor->PageCount) ==
 +                      NewDescriptor->BasePage))
 +              {
 +                      /* Just enlarge previous descriptor's PageCount */
 +                      PreviousDescriptor->PageCount += NewDescriptor->PageCount;
 +                      NewDescriptor = PreviousDescriptor;
 +              }
 +              else
 +              {
 +                      /* Nope, just insert */
 +                      InsertHeadList(PreviousEntry, &NewDescriptor->ListEntry);
 +              }
 + 
 +              /* Next block is free ?*/
 +              if ((NextEntry != ListHead) &&
 +                      (NextDescriptor->MemoryType == LoaderFree) &&
 +                      ((NewDescriptor->BasePage + NewDescriptor->PageCount) == NextDescriptor->BasePage))
 +              {
 +                      /* Enlarge next descriptor's PageCount */
 +                      NewDescriptor->PageCount += NextDescriptor->PageCount;
 +                      RemoveEntryList(&NextDescriptor->ListEntry);
 +              }
 +      }
 + 
 +      return;
 + }
 + 
   // Returns the Interrupt State from a Trap Frame.
   // ON = TRUE, OFF = FALSE
   //
 --//#define KeGetTrapFrameInterruptState(TrapFrame) \
 ++//#define KeGetTrapFrameInterruptState(TrapFrame)
 ++
 ++//
 ++// Invalidates the TLB entry for a specified address
 ++//
 ++FORCEINLINE
 ++VOID
 ++KeInvalidateTlbEntry(IN PVOID Address)
 ++{
 ++    /* Invalidate the TLB entry for this address */
 ++    KeArmInvalidateTlbEntry(Address);
 ++}
 ++
+++FORCEINLINE
+++VOID
+++KeFlushProcessTb(VOID)
+++{
+++    //
+++    // We need to implement this!
+++    //
+++    ASSERTMSG("Need ARM flush routine\n", FALSE);
+++}
+++
+++FORCEINLINE
+++VOID
+++KiRundownThread(IN PKTHREAD Thread)
+++{
+++    /* FIXME */
+++}
+  
   VOID
   KiPassiveRelease(
       VOID
@@@@ -66,17 -42,6 -42,6 +66,50 @@@@ extern ULONG Ke386CacheAlignment
   #define KeGetTrapFrameInterruptState(TrapFrame) \
           BooleanFlagOn((TrapFrame)->EFlags, EFLAGS_INTERRUPT_MASK)
   
 ++//
 ++// Invalidates the TLB entry for a specified address
 ++//
 ++FORCEINLINE
 ++VOID
 ++KeInvalidateTlbEntry(IN PVOID Address)
 ++{
 ++    /* Invalidate the TLB entry for this address */
 ++    __invlpg(Address);
 ++}
 ++
+++FORCEINLINE
+++VOID
+++KeFlushProcessTb(VOID)
+++{
+++    /* Flush the TLB by resetting CR3 */
+++    __writecr3(__readcr3());
+++}
+++
+++FORCEINLINE
+++PRKTHREAD
+++KeGetCurrentThread(VOID)
+++{
+++    /* Return the current thread */
+++    return ((PKIPCR)KeGetPcr())->PrcbData.CurrentThread;
+++}
+++
+++FORCEINLINE
+++VOID
+++KiRundownThread(IN PKTHREAD Thread)
+++{
+++#ifndef CONFIG_SMP
+++    /* Check if this is the NPX Thread */
+++    if (KeGetCurrentPrcb()->NpxThread == Thread)
+++    {
+++        /* Clear it */
+++        KeGetCurrentPrcb()->NpxThread = NULL;
+++        Ke386FnInit();
+++    }
+++#else
+++    /* Nothing to do */
+++#endif
+++}
+++
   VOID
   FASTCALL
   Ki386InitializeTss(
   * PROGRAMMERS:     Alex Ionescu (alex.ionescu@reactos.org)
   */
   
 --//
 --// Thread Dispatcher Header DebugActive Mask
 --//
 --#define DR_MASK(x)                              1 << x
 --#define DR_ACTIVE_MASK                          0x10
 --#define DR_REG_MASK                             0x4F
 --
 --#ifdef _M_IX86
 --//
 --// Sanitizes a selector
 --//
 --FORCEINLINE
 --ULONG
 --Ke386SanitizeSeg(IN ULONG Cs,
 --                IN KPROCESSOR_MODE Mode)
 --{
 --    //
 --    // Check if we're in kernel-mode, and force CPL 0 if so.
 --    // Otherwise, force CPL 3.
 --    //
 --    return ((Mode == KernelMode) ?
 --            (Cs & (0xFFFF & ~RPL_MASK)) :
 --            (RPL_MASK | (Cs & 0xFFFF)));
 --}
 --
 --//
 --// Sanitizes EFLAGS
 --//
 --FORCEINLINE
 --ULONG
 --Ke386SanitizeFlags(IN ULONG Eflags,
 --                   IN KPROCESSOR_MODE Mode)
 --{
 --    //
 --    // Check if we're in kernel-mode, and sanitize EFLAGS if so.
 --    // Otherwise, also force interrupt mask on.
 --    //
 --    return ((Mode == KernelMode) ?
 --            (Eflags & (EFLAGS_USER_SANITIZE | EFLAGS_INTERRUPT_MASK)) :
 --            (EFLAGS_INTERRUPT_MASK | (Eflags & EFLAGS_USER_SANITIZE)));
 --}
 --
 --//
 --// Gets a DR register from a CONTEXT structure
 --//
 --FORCEINLINE
 --PVOID
 --KiDrFromContext(IN ULONG Dr,
 --                IN PCONTEXT Context)
 --{
 --    return *(PVOID*)((ULONG_PTR)Context + KiDebugRegisterContextOffsets[Dr]);
 --}
 --
 --//
 --// Gets a DR register from a KTRAP_FRAME structure
 --//
 --FORCEINLINE
 --PVOID*
 --KiDrFromTrapFrame(IN ULONG Dr,
 --                  IN PKTRAP_FRAME TrapFrame)
 --{
 --    return (PVOID*)((ULONG_PTR)TrapFrame + KiDebugRegisterTrapOffsets[Dr]);
 --}
 --
 --//
 --//
 --//
 --FORCEINLINE
 --PVOID
 --Ke386SanitizeDr(IN PVOID DrAddress,
 --                IN KPROCESSOR_MODE Mode)
 --{
 --    //
 --    // Check if we're in kernel-mode, and return the address directly if so.
 --    // Otherwise, make sure it's not inside the kernel-mode address space.
 --    // If it is, then clear the address.
 --    //
 --    return ((Mode == KernelMode) ? DrAddress :
 --            (DrAddress <= MM_HIGHEST_USER_ADDRESS) ? DrAddress : 0);
 --}
 --#endif /* _M_IX86 */
 --
   #ifndef _M_ARM
---FORCEINLINE
---PRKTHREAD
---KeGetCurrentThread(VOID)
---{
---#ifdef _M_IX86
---    /* Return the current thread */
---    return ((PKIPCR)KeGetPcr())->PrcbData.CurrentThread;
 --#elif defined (_M_AMD64)
 --    return (PRKTHREAD)__readgsqword(FIELD_OFFSET(KIPCR, Prcb.CurrentThread));
---#else
---    PKPRCB Prcb = KeGetCurrentPrcb();
---    return Prcb->CurrentThread;
---#endif
---}
---
   FORCEINLINE
   UCHAR
   KeGetPreviousMode(VOID)
   }
   #endif
   
---FORCEINLINE
---VOID
---KeFlushProcessTb(VOID)
---{
---    /* Flush the TLB by resetting CR3 */
---#ifdef _M_PPC
---    __asm__("sync\n\tisync\n\t");
---#elif _M_ARM
---    //
---    // We need to implement this!
---    //
---    ASSERTMSG("Need ARM flush routine\n", FALSE);
---#else
---    __writecr3(__readcr3());
---#endif
---}
---
   //
   // Enters a Guarded Region
   //
@@@@ -300,21 -384,21 -384,21 +270,6 @@@@ KiCheckDeferredReadyList(IN PKPRCB Prcb
       UNREFERENCED_PARAMETER(Prcb);
   }
   
---FORCEINLINE
---VOID
---KiRundownThread(IN PKTHREAD Thread)
---{
-  #if defined(_M_IX86) || defined(_M_AMD64)
 --#if defined(_M_IX86)
---    /* Check if this is the NPX Thread */
---    if (KeGetCurrentPrcb()->NpxThread == Thread)
---    {
---        /* Clear it */
---        KeGetCurrentPrcb()->NpxThread = NULL;
---        Ke386FnInit();
---    }
---#endif
---}
---
   FORCEINLINE
   VOID
   KiRequestApcInterrupt(IN BOOLEAN NeedApc,
@@@@ -657,14 -741,14 -741,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,
@@@@ -77,6 -77,6 -77,6 +77,29 @@@@ FORCEINLINE struct _KPCR * NTHALAPI KeG
       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