For Xen, setup paging the way the kernel wants it and
transfer control to the kernel
Modified: branches/xen/reactos/boot/freeldr/freeldr/arch/i386/i386boot.c
Modified: branches/xen/reactos/boot/freeldr/freeldr/arch/i386/i386boot.h
Added: branches/xen/reactos/boot/freeldr/freeldr/arch/i386/i386mem.h
Modified: branches/xen/reactos/boot/freeldr/freeldr/arch/i386/machxen.h
Modified: branches/xen/reactos/boot/freeldr/freeldr/arch/i386/mb.S
Modified: branches/xen/reactos/boot/freeldr/freeldr/arch/i386/xenboot.c
Modified: branches/xen/reactos/boot/freeldr/freeldr/arch/i386/xenmem.c

Modified: branches/xen/reactos/boot/freeldr/freeldr/arch/i386/i386boot.c
--- branches/xen/reactos/boot/freeldr/freeldr/arch/i386/i386boot.c	2005-05-20 08:06:27 UTC (rev 15429)
+++ branches/xen/reactos/boot/freeldr/freeldr/arch/i386/i386boot.c	2005-05-20 10:33:27 UTC (rev 15430)
@@ -14,33 +14,22 @@
 #include <debug.h>
 
 #include "i386boot.h"
+#include "i386mem.h"
 
-/* Bits to shift to convert a Virtual Address into an Offset in the Page Table */
-#define PFN_SHIFT 12
-
-/* Bits to shift to convert a Virtual Address into an Offset in the Page Directory */
-#define PDE_SHIFT 20
-#define PDE_SHIFT_PAE 18
-
-
-/* Converts a Phsyical Address Pointer into a Page Frame Number */
-#define PaPtrToPfn(p) \
-    (((ULONG_PTR)&p) >> PFN_SHIFT)
-
-/* Converts a Phsyical Address into a Page Frame Number */
-#define PaToPfn(p) \
-    ((p) >> PFN_SHIFT)
-
 #define STARTUP_BASE                0xF0000000
 #define HYPERSPACE_BASE             0xF0800000
 #define APIC_BASE                   0xFEC00000
+#ifdef XEN_VER
+#define KPCR_BASE                   0xFB000000
+#else
 #define KPCR_BASE                   0xFF000000
+#endif
 
 #define LowMemPageTableIndex        0
-#define StartupPageTableIndex       (STARTUP_BASE >> 20)    / sizeof(HARDWARE_PTE_X86)
-#define HyperspacePageTableIndex    (HYPERSPACE_BASE >> 20) / sizeof(HARDWARE_PTE_X86)
-#define KpcrPageTableIndex          (KPCR_BASE >> 20)       / sizeof(HARDWARE_PTE_X86)
-#define ApicPageTableIndex          (APIC_BASE >> 20)       / sizeof(HARDWARE_PTE_X86)
+#define StartupPageTableIndex       (STARTUP_BASE >> PDN_SHIFT)
+#define HyperspacePageTableIndex    (HYPERSPACE_BASE >> PDN_SHIFT)
+#define KpcrPageTableIndex          (KPCR_BASE >> PDN_SHIFT)
+#define ApicPageTableIndex          (APIC_BASE >> PDN_SHIFT)
 
 #define LowMemPageTableIndexPae     0
 #define StartupPageTableIndexPae    (STARTUP_BASE >> 21)
@@ -48,83 +37,32 @@
 #define KpcrPageTableIndexPae       (KPCR_BASE >> 21)
 #define ApicPageTableIndexPae       (APIC_BASE >> 21)
 
-
-#define KernelEntryPoint            (KernelEntry - KERNEL_BASE_PHYS) + KernelBase
-
-/* Unrelocated Kernel Base in Virtual Memory */
-extern ULONG_PTR KernelBase;
-
-/* Kernel Entrypoint in Physical Memory */
-extern ULONG_PTR KernelEntry;
-
-/* Page Directory and Tables for non-PAE Systems */
-extern ULONG_PTR startup_pagedirectory;
-extern ULONG_PTR lowmem_pagetable;
-extern ULONG_PTR kernel_pagetable;
-extern ULONG_PTR hyperspace_pagetable;
-extern ULONG_PTR _pae_pagedirtable;
-extern ULONG_PTR apic_pagetable;
-extern ULONG_PTR kpcr_pagetable;
-
-/* Page Directory and Tables for PAE Systems */
-extern ULONG_PTR startup_pagedirectorytable_pae;
-extern ULONG_PTR startup_pagedirectory_pae;
-extern ULONG_PTR lowmem_pagetable_pae;
-extern ULONG_PTR kernel_pagetable_pae;
-extern ULONG_PTR hyperspace_pagetable_pae;
-extern ULONG_PTR pagedirtable_pae;
-extern ULONG_PTR apic_pagetable_pae;
-extern ULONG_PTR kpcr_pagetable_pae;
-
-typedef struct _HARDWARE_PTE_X86 {
-    ULONG Valid             : 1;
-    ULONG Write             : 1;
-    ULONG Owner             : 1;
-    ULONG WriteThrough      : 1;
-    ULONG CacheDisable      : 1;
-    ULONG Accessed          : 1;
-    ULONG Dirty             : 1;
-    ULONG LargePage         : 1;
-    ULONG Global            : 1;
-    ULONG CopyOnWrite       : 1;
-    ULONG Prototype         : 1;
-    ULONG reserved          : 1;
-    ULONG PageFrameNumber   : 20;
-} HARDWARE_PTE_X86, *PHARDWARE_PTE_X86;
-
-typedef struct _HARDWARE_PTE_X64 {
-    ULONG Valid             : 1;
-    ULONG Write             : 1;
-    ULONG Owner             : 1;
-    ULONG WriteThrough      : 1;
-    ULONG CacheDisable      : 1;
-    ULONG Accessed          : 1;
-    ULONG Dirty             : 1;
-    ULONG LargePage         : 1;
-    ULONG Global            : 1;
-    ULONG CopyOnWrite       : 1;
-    ULONG Prototype         : 1;
-    ULONG reserved          : 1;
-    ULONG PageFrameNumber   : 20;
-    ULONG reserved2         : 31;
-    ULONG NoExecute         : 1;
-} HARDWARE_PTE_X64, *PHARDWARE_PTE_X64;
-
-typedef struct _PAGE_DIRECTORY_X86 {
-    HARDWARE_PTE_X86 Pde[1024];
-} PAGE_DIRECTORY_x86, *PPAGE_DIRECTORY_X86;
-
-typedef struct _PAGE_DIRECTORY_X64 {
-    HARDWARE_PTE_X64 Pde[2048];
-} PAGE_DIRECTORY_X64, *PPAGE_DIRECTORY_X64;
-
-typedef struct _PAGE_DIRECTORY_TABLE_X64 {
-    HARDWARE_PTE_X64 Pde[4];
-} PAGE_DIRECTORY_TABLE_X64, *PPAGE_DIRECTORY_TABLE_X64;
-
 /* FUNCTIONS *****************************************************************/
 
 /*++
+ * i386BootAddrToPfn
+ * INTERNAL
+ *
+ *     Translate an address to a page frame number
+ *
+ * Params:
+ *     Addr - address to translate
+ *
+ * Returns:
+ *     Frame number.
+ *
+ * Remarks:
+ *     None.
+ *
+ *--*/
+ULONG
+STDCALL
+i386BootAddrToPfn(ULONG_PTR Addr)
+{
+  return PaToPfn(Addr);
+}
+
+/*++
  * i386BootStartup
  * INTERNAL
  *
@@ -156,7 +94,7 @@
     PaeModeEnabled = i386BootGetPaeMode();
 
     /* Initialize the page directory */
-    i386BootSetupPageDirectory(PaeModeEnabled);
+    i386BootSetupPageDirectory(PaeModeEnabled, TRUE, i386BootAddrToPfn);
 
     /* Initialize Paging, Write-Protection and Load NTOSKRNL */
     i386BootSetupPae(PaeModeEnabled, Magic);
@@ -257,7 +195,8 @@
  *--*/
 VOID
 FASTCALL
-i386BootSetupPageDirectory(BOOLEAN PaeModeEnabled)
+i386BootSetupPageDirectory(BOOLEAN PaeModeEnabled, BOOLEAN SetupApic,
+                           ULONG (STDCALL *AddrToPfn)(ULONG_PTR Addr))
 {
     PPAGE_DIRECTORY_X86 PageDir;
     PPAGE_DIRECTORY_TABLE_X64 PageDirTablePae;
@@ -369,7 +308,7 @@
     } else {
 
         /* Get the Kernel Table Index */
-        KernelPageTableIndex = (KernelBase >> PDE_SHIFT) / sizeof(HARDWARE_PTE_X86);
+        KernelPageTableIndex = KernelBase >> PDN_SHIFT;
 
         /* Get the Startup Page Directory */
         PageDir = (PPAGE_DIRECTORY_X86)&startup_pagedirectory;
@@ -377,35 +316,37 @@
         /* Set up the Low Memory PDE */
         PageDir->Pde[LowMemPageTableIndex].Valid = 1;
         PageDir->Pde[LowMemPageTableIndex].Write = 1;
-        PageDir->Pde[LowMemPageTableIndex].PageFrameNumber = PaPtrToPfn(lowmem_pagetable);
+        PageDir->Pde[LowMemPageTableIndex].PageFrameNumber = (*AddrToPfn)((ULONG_PTR) &lowmem_pagetable);
 
         /* Set up the Kernel PDEs */
         PageDir->Pde[KernelPageTableIndex].Valid = 1;
         PageDir->Pde[KernelPageTableIndex].Write = 1;
-        PageDir->Pde[KernelPageTableIndex].PageFrameNumber = PaPtrToPfn(kernel_pagetable);
+        PageDir->Pde[KernelPageTableIndex].PageFrameNumber = (*AddrToPfn)((ULONG_PTR) &kernel_pagetable);
         PageDir->Pde[KernelPageTableIndex + 1].Valid = 1;
         PageDir->Pde[KernelPageTableIndex + 1].Write = 1;
-        PageDir->Pde[KernelPageTableIndex + 1].PageFrameNumber = PaPtrToPfn(kernel_pagetable + 4096);
+        PageDir->Pde[KernelPageTableIndex + 1].PageFrameNumber = (*AddrToPfn)((ULONG_PTR) &kernel_pagetable + 4096);
 
         /* Set up the Startup PDE */
         PageDir->Pde[StartupPageTableIndex].Valid = 1;
         PageDir->Pde[StartupPageTableIndex].Write = 1;
-        PageDir->Pde[StartupPageTableIndex].PageFrameNumber = PaPtrToPfn(startup_pagedirectory);
+        PageDir->Pde[StartupPageTableIndex].PageFrameNumber = (*AddrToPfn)((LONG_PTR) &startup_pagedirectory);
 
         /* Set up the Hyperspace PDE */
         PageDir->Pde[HyperspacePageTableIndex].Valid = 1;
         PageDir->Pde[HyperspacePageTableIndex].Write = 1;
-        PageDir->Pde[HyperspacePageTableIndex].PageFrameNumber = PaPtrToPfn(hyperspace_pagetable);
+        PageDir->Pde[HyperspacePageTableIndex].PageFrameNumber = (*AddrToPfn)((LONG_PTR) &hyperspace_pagetable);
 
         /* Set up the Apic PDE */
-        PageDir->Pde[ApicPageTableIndex].Valid = 1;
-        PageDir->Pde[ApicPageTableIndex].Write = 1;
-        PageDir->Pde[ApicPageTableIndex].PageFrameNumber = PaPtrToPfn(apic_pagetable);
+        if (SetupApic) {
+            PageDir->Pde[ApicPageTableIndex].Valid = 1;
+            PageDir->Pde[ApicPageTableIndex].Write = 1;
+            PageDir->Pde[ApicPageTableIndex].PageFrameNumber = (*AddrToPfn)((LONG_PTR) &apic_pagetable);
+        }
 
         /* Set up the KPCR PDE */
         PageDir->Pde[KpcrPageTableIndex].Valid = 1;
         PageDir->Pde[KpcrPageTableIndex].Write = 1;
-        PageDir->Pde[KpcrPageTableIndex].PageFrameNumber = PaPtrToPfn(kpcr_pagetable);
+        PageDir->Pde[KpcrPageTableIndex].PageFrameNumber = (*AddrToPfn)((LONG_PTR) &kpcr_pagetable);
 
         /* Set up Low Memory PTEs */
         PageDir = (PPAGE_DIRECTORY_X86)&lowmem_pagetable;
@@ -414,7 +355,7 @@
             PageDir->Pde[i].Valid = 1;
             PageDir->Pde[i].Write = 1;
             PageDir->Pde[i].Owner = 1;
-            PageDir->Pde[i].PageFrameNumber = PaToPfn(i * PAGE_SIZE);
+            PageDir->Pde[i].PageFrameNumber = (*AddrToPfn)(i * PAGE_SIZE);
         }
 
         /* Set up Kernel PTEs */
@@ -423,27 +364,29 @@
 
             PageDir->Pde[i].Valid = 1;
             PageDir->Pde[i].Write = 1;
-            PageDir->Pde[i].PageFrameNumber = PaToPfn(KERNEL_BASE_PHYS + i * PAGE_SIZE);
+            PageDir->Pde[i].PageFrameNumber = (*AddrToPfn)(KERNEL_BASE_PHYS + i * PAGE_SIZE);
         }
 
         /* Set up APIC PTEs */
-        PageDir = (PPAGE_DIRECTORY_X86)&apic_pagetable;
-        PageDir->Pde[0].Valid = 1;
-        PageDir->Pde[0].Write = 1;
-        PageDir->Pde[0].CacheDisable = 1;
-        PageDir->Pde[0].WriteThrough = 1;
-        PageDir->Pde[0].PageFrameNumber = PaToPfn(APIC_BASE);
-        PageDir->Pde[0x200].Valid = 1;
-        PageDir->Pde[0x200].Write = 1;
-        PageDir->Pde[0x200].CacheDisable = 1;
-        PageDir->Pde[0x200].WriteThrough = 1;
-        PageDir->Pde[0x200].PageFrameNumber = PaToPfn(APIC_BASE + KERNEL_BASE_PHYS);
+        if (SetupApic) {
+            PageDir = (PPAGE_DIRECTORY_X86)&apic_pagetable;
+            PageDir->Pde[0].Valid = 1;
+            PageDir->Pde[0].Write = 1;
+            PageDir->Pde[0].CacheDisable = 1;
+            PageDir->Pde[0].WriteThrough = 1;
+            PageDir->Pde[0].PageFrameNumber = (*AddrToPfn)(APIC_BASE);
+            PageDir->Pde[0x200].Valid = 1;
+            PageDir->Pde[0x200].Write = 1;
+            PageDir->Pde[0x200].CacheDisable = 1;
+            PageDir->Pde[0x200].WriteThrough = 1;
+            PageDir->Pde[0x200].PageFrameNumber = (*AddrToPfn)(APIC_BASE + KERNEL_BASE_PHYS);
+        }
 
         /* Set up KPCR PTEs */
         PageDir = (PPAGE_DIRECTORY_X86)&kpcr_pagetable;
         PageDir->Pde[0].Valid = 1;
         PageDir->Pde[0].Write = 1;
-        PageDir->Pde[0].PageFrameNumber = 1;
+        PageDir->Pde[0].PageFrameNumber = (*AddrToPfn)(PAGE_SIZE);
     }
     return;
 }

Modified: branches/xen/reactos/boot/freeldr/freeldr/arch/i386/i386boot.h
--- branches/xen/reactos/boot/freeldr/freeldr/arch/i386/i386boot.h	2005-05-20 08:06:27 UTC (rev 15429)
+++ branches/xen/reactos/boot/freeldr/freeldr/arch/i386/i386boot.h	2005-05-20 10:33:27 UTC (rev 15430)
@@ -1,6 +1,33 @@
 #ifndef I386BOOT_H_INCLUDED
 #define I386BOOT_H_INCLUDED
 
+#define KernelEntryPoint            (KernelEntry - KERNEL_BASE_PHYS) + KernelBase
+
+/* Unrelocated Kernel Base in Virtual Memory */
+extern ULONG_PTR KernelBase;
+
+/* Kernel Entrypoint in Physical Memory */
+extern ULONG_PTR KernelEntry;
+
+/* Page Directory and Tables for non-PAE Systems */
+extern ULONG_PTR startup_pagedirectory;
+extern ULONG_PTR lowmem_pagetable;
+extern ULONG_PTR kernel_pagetable;
+extern ULONG_PTR hyperspace_pagetable;
+extern ULONG_PTR _pae_pagedirtable;
+extern ULONG_PTR apic_pagetable;
+extern ULONG_PTR kpcr_pagetable;
+
+/* Page Directory and Tables for PAE Systems */
+extern ULONG_PTR startup_pagedirectorytable_pae;
+extern ULONG_PTR startup_pagedirectory_pae;
+extern ULONG_PTR lowmem_pagetable_pae;
+extern ULONG_PTR kernel_pagetable_pae;
+extern ULONG_PTR hyperspace_pagetable_pae;
+extern ULONG_PTR pagedirtable_pae;
+extern ULONG_PTR apic_pagetable_pae;
+extern ULONG_PTR kpcr_pagetable_pae;
+
 VOID
 STDCALL
 i386BootStartup(ULONG Magic);
@@ -15,6 +42,7 @@
 
 VOID
 FASTCALL
-i386BootSetupPageDirectory(BOOLEAN PaeModeEnabled);
+i386BootSetupPageDirectory(BOOLEAN PaeModeEnabled, BOOLEAN SetupApic,
+                           ULONG (STDCALL *AddrToPfn)(ULONG_PTR Addr));
 
 #endif /* ! defined I386BOOT_H_INCLUDED */

Copied: branches/xen/reactos/boot/freeldr/freeldr/arch/i386/i386mem.h (from rev 15391, branches/xen/reactos/boot/freeldr/freeldr/arch/i386/i386boot.c)
--- branches/xen/reactos/boot/freeldr/freeldr/arch/i386/i386boot.c	2005-05-17 22:15:18 UTC (rev 15391)
+++ branches/xen/reactos/boot/freeldr/freeldr/arch/i386/i386mem.h	2005-05-20 10:33:27 UTC (rev 15430)
@@ -0,0 +1,84 @@
+#ifndef I386MEM_H_INCLUDED
+#define I386MEM_H_INCLUDED
+
+/* Bits to shift to convert a Virtual Address into an Offset in the Page Table */
+#define PFN_SHIFT 12
+
+/* Bits to shift to convert a Virtual Address into an Offset in the Page Directory */
+#define PDN_SHIFT 22
+
+
+/* Converts a Phsyical Address Pointer into a Page Frame Number */
+#define PaPtrToPfn(p) \
+    (((ULONG_PTR)&p) >> PFN_SHIFT)
+
+/* Converts a Phsyical Address into a Page Frame Number */
+#define PaToPfn(p) \
+    ((p) >> PFN_SHIFT)
+
+typedef struct _HARDWARE_PTE_X86 {
+    union {
+        struct {
+            ULONG Valid             : 1;
+            ULONG Write             : 1;
+            ULONG Owner             : 1;
+            ULONG WriteThrough      : 1;
+            ULONG CacheDisable      : 1;
+            ULONG Accessed          : 1;
+            ULONG Dirty             : 1;
+            ULONG LargePage         : 1;
+            ULONG Global            : 1;
+            ULONG CopyOnWrite       : 1;
+            ULONG Prototype         : 1;
+            ULONG reserved          : 1;
+            ULONG PageFrameNumber   : 20;
+        };
+        ULONG Val;
+    };
+} HARDWARE_PTE_X86, *PHARDWARE_PTE_X86, HARDWARE_PDE_X86, *PHARDWARE_PDE_X86;
+
+typedef struct _HARDWARE_PTE_X64 {
+    ULONG Valid             : 1;
+    ULONG Write             : 1;
+    ULONG Owner             : 1;
+    ULONG WriteThrough      : 1;
+    ULONG CacheDisable      : 1;
+    ULONG Accessed          : 1;
+    ULONG Dirty             : 1;
+    ULONG LargePage         : 1;
+    ULONG Global            : 1;
+    ULONG CopyOnWrite       : 1;
+    ULONG Prototype         : 1;
+    ULONG reserved          : 1;
+    ULONG PageFrameNumber   : 20;
+    ULONG reserved2         : 31;
+    ULONG NoExecute         : 1;
+} HARDWARE_PTE_X64, *PHARDWARE_PTE_X64;
+
+#define PTRS_PER_PD_X86   (PAGE_SIZE / sizeof(HARDWARE_PDE_X86))
+#define PTRS_PER_PT_X86   (PAGE_SIZE / sizeof(HARDWARE_PTE_X86))
+
+/* Page Directory Index of a given virtual address */
+#define PD_IDX(Va) ((((ULONG_PTR) Va) >> PDN_SHIFT) & (PTRS_PER_PD_X86 - 1))
+/* Page Table Index of a give virtual address */
+#define PT_IDX(Va) ((((ULONG_PTR) Va) >> PFN_SHIFT) & (PTRS_PER_PT_X86 - 1))
+/* Convert a Page Directory or Page Table entry to a (machine) address */
+#define PAGE_MASK  (~(PAGE_SIZE-1))
+
+typedef struct _PAGE_DIRECTORY_X86 {
+    HARDWARE_PDE_X86 Pde[PTRS_PER_PD_X86];
+} PAGE_DIRECTORY_X86, *PPAGE_DIRECTORY_X86;
+
+typedef struct _PAGE_TABLE_X86 {
+    HARDWARE_PTE_X86 Pte[PTRS_PER_PT_X86];
+} PAGE_TABLE_X86, *PPAGE_TABLE_X86;
+
+typedef struct _PAGE_DIRECTORY_X64 {
+    HARDWARE_PTE_X64 Pde[2048];
+} PAGE_DIRECTORY_X64, *PPAGE_DIRECTORY_X64;
+
+typedef struct _PAGE_DIRECTORY_TABLE_X64 {
+    HARDWARE_PTE_X64 Pde[4];
+} PAGE_DIRECTORY_TABLE_X64, *PPAGE_DIRECTORY_TABLE_X64;
+
+#endif /* ! defined I386MEM_H_INCLUDED */

Modified: branches/xen/reactos/boot/freeldr/freeldr/arch/i386/machxen.h
--- branches/xen/reactos/boot/freeldr/freeldr/arch/i386/machxen.h	2005-05-20 08:06:27 UTC (rev 15429)
+++ branches/xen/reactos/boot/freeldr/freeldr/arch/i386/machxen.h	2005-05-20 10:33:27 UTC (rev 15430)
@@ -21,9 +21,8 @@
 #ifndef __I386_MACHXEN_H_
 #define __I386_MACHXEN_H_
 
-#ifndef __MEMORY_H
+#include "i386mem.h"
 #include "mm.h"
-#endif
 
 #include <rosxen.h>
 #include <xen.h>
@@ -74,6 +73,7 @@
 VOID XenMemInit(start_info_t *StartInfo);
 u32 XenMemVirtualToMachine(void *VirtualAddress);
 int XenMemGrantForeignAccess(domid_t DomId, void *VirtAddr, BOOL ReadOnly);
+VOID XenMemInstallPageDir(PPAGE_DIRECTORY_X86 NewPageDir);
 
 BOOL XenDiskReadLogicalSectors(ULONG DriveNumber, ULONGLONG SectorNumber, ULONG SectorCount, PVOID Buffer);
 BOOL XenDiskGetPartitionEntry(ULONG DriveNumber, ULONG PartitionNumber, PPARTITION_TABLE_ENTRY PartitionTableEntry);

Modified: branches/xen/reactos/boot/freeldr/freeldr/arch/i386/mb.S
--- branches/xen/reactos/boot/freeldr/freeldr/arch/i386/mb.S	2005-05-20 08:06:27 UTC (rev 15429)
+++ branches/xen/reactos/boot/freeldr/freeldr/arch/i386/mb.S	2005-05-20 10:33:27 UTC (rev 15430)
@@ -61,6 +61,7 @@
 	.endr
 
 .bss
+	.align 4096
 PageDirectoryStart:
 startup_pagedirectory:
 	.fill 4096, 1, 0

Modified: branches/xen/reactos/boot/freeldr/freeldr/arch/i386/xenboot.c
--- branches/xen/reactos/boot/freeldr/freeldr/arch/i386/xenboot.c	2005-05-20 08:06:27 UTC (rev 15429)
+++ branches/xen/reactos/boot/freeldr/freeldr/arch/i386/xenboot.c	2005-05-20 10:33:27 UTC (rev 15430)
@@ -22,17 +22,24 @@
 #include "machine.h"
 #include "machxen.h"
 
+static ULONG STDCALL
+XenBootAddrToPfn(ULONG_PTR Addr)
+{  
+  return (ULONG) XenMemVirtualToMachine((void *) Addr) >> PAGE_SHIFT;
+}
+
 VOID
 XenBootReactOS(VOID)
-  {
+{
   BOOLEAN PaeModeEnabled;
+  ASMCODE PagedJump;
 
+  /* Clear screen and make sure all console output is written */
   XenVideoClearScreen(0x07);
+  XenConsFlushWait();
 
   /* Disable events */
-#ifdef TODO
   XenEvtchnDisableEvents();
-#endif
 
   /* Re-initalize EFLAGS */
   Ke386EraseFlags();
@@ -41,10 +48,14 @@
   PaeModeEnabled = FALSE;
 
   /* Initialize the page directory */
-  i386BootSetupPageDirectory(PaeModeEnabled);
+  i386BootSetupPageDirectory(PaeModeEnabled, FALSE, XenBootAddrToPfn);
 
-  /* Initialize Paging, Write-Protection and Load NTOSKRNL */
-  i386BootSetupPae(PaeModeEnabled, 0x2badb002);
-  }
+  /* Switch to the new page directory */
+  XenMemInstallPageDir((PPAGE_DIRECTORY_X86) &startup_pagedirectory);
 
+  /* Jump to Kernel */
+  PagedJump = (ASMCODE)KernelEntryPoint;
+  PagedJump(0x2badb002, &LoaderBlock);
+}
+
 /* EOF */

Modified: branches/xen/reactos/boot/freeldr/freeldr/arch/i386/xenmem.c
--- branches/xen/reactos/boot/freeldr/freeldr/arch/i386/xenmem.c	2005-05-20 08:06:27 UTC (rev 15429)
+++ branches/xen/reactos/boot/freeldr/freeldr/arch/i386/xenmem.c	2005-05-20 10:33:27 UTC (rev 15430)
@@ -17,6 +17,8 @@
  */
 
 #include "freeldr.h"
+#include "i386boot.h"
+#include "i386mem.h"
 #include "machxen.h"
 
 #include <rosxen.h>
@@ -27,53 +29,10 @@
 #include <grant_table.h>
 #endif /* CONFIG_XEN_BLKDEV_GRANT */
 
-/* Page Directory Entry */
-typedef struct _PDE
-{
-  u32 Pde;
-} PDE, *PPDE;
-
-/* Page Table Entry */
-typedef struct _PTE
-{
-  u32 Pte;
-} PTE, *PPTE;
-
-#define PGDIR_SHIFT   22
-#define PTRS_PER_PD   (PAGE_SIZE / sizeof(PDE))
-#define PTRS_PER_PT   (PAGE_SIZE / sizeof(PTE))
-
-/* Page Directory Index of a given virtual address */
-#define PD_IDX(Va) ((((ULONG_PTR) Va) >> PGDIR_SHIFT) & (PTRS_PER_PD - 1))
-/* Page Table Index of a give virtual address */
-#define PT_IDX(Va) ((((ULONG_PTR) Va) >> PAGE_SHIFT) & (PTRS_PER_PT - 1))
-/* Convert a Page Directory or Page Table entry to a (machine) address */
-#define PAGE_MASK  (~(PAGE_SIZE-1))
-
-/* The PA_* definitions below were copied from ntoskrnl/mm/i386/page.c, maybe
-   we need a public header for them?? */
-#define PA_BIT_PRESENT   (0)
-#define PA_BIT_READWRITE (1)
-#define PA_BIT_USER      (2)
-#define PA_BIT_WT        (3)
-#define PA_BIT_CD        (4)
-#define PA_BIT_ACCESSED  (5)
-#define PA_BIT_DIRTY     (6)
-#define PA_BIT_GLOBAL    (8)
-
-#define PA_PRESENT   (1 << PA_BIT_PRESENT)
-#define PA_READWRITE (1 << PA_BIT_READWRITE)
-#define PA_USER      (1 << PA_BIT_USER)
-#define PA_DIRTY     (1 << PA_BIT_DIRTY)
-#define PA_WT        (1 << PA_BIT_WT)
-#define PA_CD        (1 << PA_BIT_CD)
-#define PA_ACCESSED  (1 << PA_BIT_ACCESSED)
-#define PA_GLOBAL    (1 << PA_BIT_GLOBAL)
-
 start_info_t *XenStartInfo;
 shared_info_t *XenSharedInfo;
 
-static PPDE XenPageDir;
+static PPAGE_DIRECTORY_X86 XenPageDir;
 
 #if 2 == XEN_VER
 #define XEN_MMU_UPDATE(req, count, success, domid) \
@@ -169,8 +128,8 @@
   static char ErrMsg[] = "XenMemInit failed\n";
   unsigned long StartPfn;           /* (Virtual) page frame number of beginning
                                        of freeldr */
-  PPDE PageDir;                     /* Virtual address of page directory */
-  PPTE PageTableForPageDir;         /* Virtual address of page table which
+  PPAGE_DIRECTORY_X86 PageDir;      /* Virtual address of page directory */
+  PPAGE_TABLE_X86 PageTableForPageDir; /* Virtual address of page table which
                                        contains entry for the page directory */
   unsigned long PageDirMachineAddr; /* Machine address of page directory */
   unsigned PageTablesRequired;      /* Number of page tables we require */
@@ -180,16 +139,18 @@
   unsigned long HighAddr;           /* Virtual address after reloc to high
                                        memory */
   unsigned long PageNumber;         /* Index of current page */
-  PPTE PageTable;                   /* Page table containing current page */
+  PPAGE_TABLE_X86 PageTable;        /* Page table containing current page */
+  HARDWARE_PTE_X86 Pte;             /* Page table entry */
 #ifdef CONFIG_XEN_BLKDEV_GRANT
   gnttab_setup_table_t Setup;       /* Grant table setup request */
   unsigned long Frame;              /* Grant table frame */
 #endif /* CONFIG_XEN_BLKDEV_GRANT */
 
-  PageDir = (PPDE) StartInfo->pt_base;
-  PageTableForPageDir = (PPTE)((char *) StartInfo->pt_base
-                               + PAGE_SIZE * (PD_IDX(StartInfo->pt_base) + 1));
-  PageDirMachineAddr = PageTableForPageDir[PT_IDX(StartInfo->pt_base)].Pte
+  PageDir = (PPAGE_DIRECTORY_X86) StartInfo->pt_base;
+  PageTableForPageDir = (PPAGE_TABLE_X86)((char *) StartInfo->pt_base
+                                          + PAGE_SIZE
+                                            * (PD_IDX(StartInfo->pt_base) + 1));
+  PageDirMachineAddr = PageTableForPageDir->Pte[PT_IDX(StartInfo->pt_base)].Val
                        & PAGE_MASK;
 
   /* Determine pfn of first allocated memory */
@@ -197,20 +158,21 @@
 
   /* First, lets connect all our page tables */
 #ifdef CONFIG_XEN_BLKDEV_GRANT
-  PageTablesRequired = ROUND_UP(StartInfo->nr_pages + 2, PTRS_PER_PT)
-                       / PTRS_PER_PT;
+  PageTablesRequired = ROUND_UP(StartInfo->nr_pages + 2, PTRS_PER_PT_X86)
+                       / PTRS_PER_PT_X86;
 #else /* CONFIG_XEN_BLKDEV_GRANT */
-  PageTablesRequired = ROUND_UP(StartInfo->nr_pages + 1, PTRS_PER_PT)
-                       / PTRS_PER_PT;
+  PageTablesRequired = ROUND_UP(StartInfo->nr_pages + 1, PTRS_PER_PT_X86)
+                       / PTRS_PER_PT_X86;
 #endif /* CONFIG_XEN_BLKDEV_GRANT */
   for (PageTableNumber = 0; PageTableNumber < PageTablesRequired;
        PageTableNumber++)
     {
       MfnIndex = StartInfo->nr_pages - (StartPfn + PageTablesRequired)
                  + PageTableNumber;
-      if (0 == PageDir[PageTableNumber].Pde)
+      if (0 == PageDir->Pde[PageTableNumber].Val)
         {
-          MmuReq.ptr = PageDirMachineAddr + PageTableNumber * sizeof(PTE);
+          MmuReq.ptr = PageDirMachineAddr
+                       + PageTableNumber * sizeof(HARDWARE_PTE_X86);
         }
       else
         {
@@ -218,14 +180,18 @@
            * means that it's also mapped in the area following pt_base. We
            * don't want it there, so let's map another page at that pos.
            * This page table will be mapped near the top of memory later */
-          PageTable = (PPTE)((char *) PageDir
-                             + (PageTableNumber + 1) * PAGE_SIZE);
-          MmuReq.ptr = (PageDir[PD_IDX((unsigned long) PageTable)].Pde
+          PageTable = (PPAGE_TABLE_X86)((char *) PageDir
+                                        + (PageTableNumber + 1) * PAGE_SIZE);
+          MmuReq.ptr = (PageDir->Pde[PD_IDX(PageTable)].Val
                         & PAGE_MASK) +
-                       PT_IDX((unsigned long) PageTable) * sizeof(PTE);
+                       PT_IDX(PageTable) * sizeof(HARDWARE_PTE_X86);
         }
-      MmuReq.val = (((u32*)StartInfo->mfn_list)[MfnIndex] << PAGE_SHIFT)
-                   | (PA_PRESENT | PA_READWRITE | PA_USER);
+      Pte.Val = 0;
+      Pte.PageFrameNumber = ((u32*)StartInfo->mfn_list)[MfnIndex];
+      Pte.Valid = 1;
+      Pte.Write = 1;
+      Pte.Owner = 1;
+      MmuReq.val = Pte.Val;
       if (0 != XEN_MMU_UPDATE(&MmuReq, 1, NULL, DOMID_SELF))
         {
           HYPERVISOR_console_io(CONSOLEIO_write, sizeof(ErrMsg), ErrMsg);
@@ -235,24 +201,31 @@
 
   /* Now, let's make the page directory visible near the top of mem */
   HighAddr = (StartInfo->nr_pages - (PageTablesRequired + 1)) * PAGE_SIZE;
-  MmuReq.ptr = (PageDir[PD_IDX(HighAddr)].Pde & PAGE_MASK)
-               + PT_IDX(HighAddr) * sizeof(PTE);
-  MmuReq.val = PageDirMachineAddr
-               | (PA_PRESENT | PA_USER);
+  MmuReq.ptr = (PageDir->Pde[PD_IDX(HighAddr)].Val & PAGE_MASK)
+               + PT_IDX(HighAddr) * sizeof(HARDWARE_PTE_X86);
+  Pte.Val = 0;
+  Pte.PageFrameNumber = PageDirMachineAddr >> PFN_SHIFT;
+  Pte.Valid = 1;
+  Pte.Owner = 1;
+  MmuReq.val = Pte.Val;
   if (0 != XEN_MMU_UPDATE(&MmuReq, 1, NULL, DOMID_SELF))
     {
       HYPERVISOR_console_io(CONSOLEIO_write, sizeof(ErrMsg), ErrMsg);
       XenDie();
     }
-  XenPageDir = (PPDE) HighAddr;
+  XenPageDir = (PPAGE_DIRECTORY_X86) HighAddr;
 
   /* We don't need the page directory mapped at the low address (pt_base)
    * anymore, so we'll map another page there */
-  MmuReq.ptr = (PageDir[PD_IDX((unsigned long) PageDir)].Pde & PAGE_MASK)
-               + PT_IDX((unsigned long) PageDir) * sizeof(PTE);
+  MmuReq.ptr = (PageDir->Pde[PD_IDX((unsigned long) PageDir)].Val & PAGE_MASK)
+               + PT_IDX((unsigned long) PageDir) * sizeof(HARDWARE_PTE_X86);
   MfnIndex = StartInfo->nr_pages - (StartPfn + PageTablesRequired + 1);
-  MmuReq.val = (((u32*)StartInfo->mfn_list)[MfnIndex] << PAGE_SHIFT)
-               | (PA_PRESENT | PA_READWRITE | PA_USER);
+  Pte.Val = 0;
+  Pte.PageFrameNumber = ((u32*)StartInfo->mfn_list)[MfnIndex];
+  Pte.Valid = 1;
+  Pte.Write = 1;
+  Pte.Owner = 1;
+  MmuReq.val = Pte.Val;
   if (0 != XEN_MMU_UPDATE(&MmuReq, 1, NULL, DOMID_SELF))
     {
       HYPERVISOR_console_io(CONSOLEIO_write, sizeof(ErrMsg), ErrMsg);
@@ -265,10 +238,13 @@
     {
       HighAddr = (StartInfo->nr_pages - PageTablesRequired + PageTableNumber)
                  * PAGE_SIZE;
-      MmuReq.ptr = (XenPageDir[PD_IDX(HighAddr)].Pde & PAGE_MASK)
-                    + PT_IDX(HighAddr) * sizeof(PTE);
-      MmuReq.val = (XenPageDir[PageTableNumber].Pde & PAGE_MASK)
-                   | (PA_PRESENT | PA_USER);
+      MmuReq.ptr = (XenPageDir->Pde[PD_IDX(HighAddr)].Val & PAGE_MASK)
+                    + PT_IDX(HighAddr) * sizeof(HARDWARE_PTE_X86);
+      Pte.Val = 0;
+      Pte.PageFrameNumber = XenPageDir->Pde[PageTableNumber].Val >> PFN_SHIFT;
+      Pte.Valid = 1;
+      Pte.Owner = 1;
+      MmuReq.val = Pte.Val;
       if (0 != XEN_MMU_UPDATE(&MmuReq, 1, NULL, DOMID_SELF))
         {
           HYPERVISOR_console_io(CONSOLEIO_write, sizeof(ErrMsg), ErrMsg);
@@ -281,9 +257,10 @@
        PageNumber < StartInfo->nr_pages - (PageTablesRequired + 1);
        PageNumber++)
     {
-      PageTable = (PPTE)((char *) XenPageDir +
-                         (PD_IDX(PageNumber * PAGE_SIZE) + 1) * PAGE_SIZE);
-      if (0 == PageTable[PT_IDX(PageNumber * PAGE_SIZE)].Pte)
+      PageTable = (PPAGE_TABLE_X86)((char *) XenPageDir
+                                    + (PD_IDX(PageNumber * PAGE_SIZE) + 1)
+                                      * PAGE_SIZE);
+      if (0 == PageTable->Pte[PT_IDX(PageNumber * PAGE_SIZE)].Val)
         {
           if (PageNumber < StartPfn)
             {
@@ -293,11 +270,16 @@
             {
               MfnIndex = PageNumber - StartPfn;
             }
-          MmuReq.ptr = (XenPageDir[PD_IDX(PageNumber * PAGE_SIZE)].Pde
+          MmuReq.ptr = (XenPageDir->Pde[PD_IDX(PageNumber * PAGE_SIZE)].Val
                         & PAGE_MASK)
-                        + PT_IDX(PageNumber * PAGE_SIZE) * sizeof(PTE);
-          MmuReq.val = (((u32 *) StartInfo->mfn_list)[MfnIndex] << PAGE_SHIFT)
-                       | (PA_PRESENT | PA_READWRITE | PA_USER);
+                        + PT_IDX(PageNumber * PAGE_SIZE)
+                          * sizeof(HARDWARE_PTE_X86);
+          Pte.Val = 0;
+          Pte.PageFrameNumber = ((u32 *) StartInfo->mfn_list)[MfnIndex];
+          Pte.Valid = 1;
+          Pte.Write = 1;
+          Pte.Owner = 1;
+          MmuReq.val = Pte.Val;
           if (0 != XEN_MMU_UPDATE(&MmuReq, 1, NULL, DOMID_SELF))
             {
               HYPERVISOR_console_io(CONSOLEIO_write, sizeof(ErrMsg), ErrMsg);
@@ -313,11 +295,16 @@
   /* We don't own the shared_info page, map it as an extra page just after
    * our "normal" memory */
   XenSharedInfo = (shared_info_t *)(XenStartInfo->nr_pages * PAGE_SIZE);
-  MmuReq.ptr = (XenPageDir[PD_IDX(XenStartInfo->nr_pages * PAGE_SIZE)].Pde
+  MmuReq.ptr = (XenPageDir->Pde[PD_IDX(XenStartInfo->nr_pages * PAGE_SIZE)].Val
                 & PAGE_MASK)
-               + PT_IDX(XenStartInfo->nr_pages * PAGE_SIZE) * sizeof(PTE);
-  MmuReq.val = XenStartInfo->shared_info
-               | (PA_PRESENT | PA_READWRITE | PA_USER);
+               + PT_IDX(XenStartInfo->nr_pages * PAGE_SIZE)
+                 * sizeof(HARDWARE_PTE_X86);
+  Pte.Val = 0;
+  Pte.PageFrameNumber = XenStartInfo->shared_info >> PFN_SHIFT;
+  Pte.Valid = 1;
+  Pte.Write = 1;
+  Pte.Owner = 1;
+  MmuReq.val = Pte.Val;
   if (0 != XEN_MMU_UPDATE(&MmuReq, 1, NULL, DOMID_SELF))
     {
       HYPERVISOR_console_io(CONSOLEIO_write, sizeof(ErrMsg), ErrMsg);
@@ -339,11 +326,15 @@
     }
   XenMemBlkdevGrantShared = (grant_entry_t *)((XenStartInfo->nr_pages + 1)
                                               * PAGE_SIZE);
-  MmuReq.ptr = (XenPageDir[PD_IDX(XenMemBlkdevGrantShared)].Pde
+  MmuReq.ptr = (XenPageDir->Pde[PD_IDX(XenMemBlkdevGrantShared)].Val
                 & PAGE_MASK)
-               + PT_IDX(XenMemBlkdevGrantShared) * sizeof(PTE);
-  MmuReq.val = (Frame << PAGE_SHIFT)
-               | (PA_PRESENT | PA_READWRITE | PA_USER);
+               + PT_IDX(XenMemBlkdevGrantShared) * sizeof(HARDWARE_PTE_X86);
+  Pte.Val = 0;
+  Pte.PageFrameNumber = Frame;
+  Pte.Valid = 1;
+  Pte.Write = 1;
+  Pte.Owner = 1;
+  MmuReq.val = Pte.Val;
   if (0 != XEN_MMU_UPDATE(&MmuReq, 1, NULL, DOMID_SELF))
     {
       HYPERVISOR_console_io(CONSOLEIO_write, sizeof(ErrMsg), ErrMsg);
@@ -355,14 +346,32 @@
 u32
 XenMemVirtualToMachine(void *VirtualAddress)
 {
-  PPTE PageTable;
+  PPAGE_TABLE_X86 PageTable;
 
-  PageTable = (PPTE)((char *) XenPageDir +
-                     (PD_IDX((ULONG_PTR) VirtualAddress) + 1) * PAGE_SIZE);
-  return PageTable[PT_IDX((ULONG_PTR) VirtualAddress)].Pte
-         & PAGE_MASK;
+  PageTable = (PPAGE_TABLE_X86)((char *) XenPageDir
+                                + (PD_IDX((ULONG_PTR) VirtualAddress) + 1)
+                                  * PAGE_SIZE);
+  return PageTable->Pte[PT_IDX(VirtualAddress)].Val & PAGE_MASK;
 }
 
+static void *
+XenMemMachineToVirtual(ULONG Mfn)
+{
+  PPAGE_TABLE_X86 PageTable;
+  ULONG Index;
+
+  PageTable = (PPAGE_TABLE_X86)(XenPageDir + 1);
+  Index = 0;
+  while (TRUE)
+    {
+      if ((PageTable->Pte[Index].PageFrameNumber) == Mfn)
+        {
+          return (void *)(Index * PAGE_SIZE);
+        }
+      Index++;
+    }
+}
+
 #ifdef CONFIG_XEN_BLKDEV_GRANT
 int
 XenMemGrantForeignAccess(domid_t DomId, void *VirtualAddress, BOOL ReadOnly)
@@ -370,7 +379,7 @@
   int Ref = 0; /* We only do 1 page at the moment */
 
   XenMemBlkdevGrantShared[Ref].frame = (XenMemVirtualToMachine(VirtualAddress)
-                                        >> PAGE_SHIFT);
+                                        >> PFN_SHIFT);
   XenMemBlkdevGrantShared[Ref].domid = DomId;
   wmb();
   XenMemBlkdevGrantShared[Ref].flags = GTF_permit_access
@@ -380,4 +389,111 @@
 }
 #endif /* CONFIG_XEN_BLKDEV_GRANT */
 
+static VOID
+XenMemSetNewPageReadonly(PPAGE_DIRECTORY_X86 NewPageDir, ULONG Mfn)
+{
+  PPAGE_TABLE_X86 PageTable;
+  unsigned PdIndex;
+  unsigned PtIndex;
+
+  for (PdIndex = 0; PdIndex < PTRS_PER_PD_X86; PdIndex++)
+    {
+      if (NewPageDir->Pde[PdIndex].Valid)
+        {
+          PageTable = (PPAGE_TABLE_X86)
+                      XenMemMachineToVirtual(NewPageDir->Pde[PdIndex].PageFrameNumber);
+          for (PtIndex = 0; PtIndex < PTRS_PER_PT_X86; PtIndex++)
+            {
+              if (PageTable->Pte[PtIndex].PageFrameNumber == Mfn)
+                {
+                  PageTable->Pte[PtIndex].Write = 0;
+                }
+            }
+        }
+    }
+}
+
+static VOID
+XenMemSetOldPageReadonly(ULONG Mfn)
+{
+  PPAGE_TABLE_X86 PageTable;
+  ULONG Index;
+  mmu_update_t MmuReq;
+  ULONG_PTR Address;
+  HARDWARE_PTE_X86 Pte;
+
+  PageTable = (PPAGE_TABLE_X86)(XenPageDir + 1);
+  Index = 0;
+  while (TRUE)
+    {
+      if ((PageTable->Pte[Index].PageFrameNumber) == Mfn)
+        {
+          Address = Index * PAGE_SIZE;
+          MmuReq.ptr = (XenPageDir->Pde[PD_IDX(Address)].Val & PAGE_MASK)
+                       + PT_IDX(Address) * sizeof(HARDWARE_PTE_X86);
+          Pte.Val = PageTable->Pte[Index].Val;
+          Pte.Write = 0;
+          MmuReq.val = Pte.Val;
+          if (0 != XEN_MMU_UPDATE(&MmuReq, 1, NULL, DOMID_SELF))
+            {
+              printf("Failed to map new page dir/table read-only\n");
+              XenDie();
+            }
+          return;
+        }
+      Index++;
+    }
+}
+
+VOID
+XenMemInstallPageDir(PPAGE_DIRECTORY_X86 NewPageDir)
+{
+  struct mmuext_op MmuExtReq;
+  ULONG NewPageDirMfn;
+  ULONG PageIndex;
+
+  NewPageDirMfn = PaToPfn(XenMemVirtualToMachine((void *) NewPageDir));
+
+  for (PageIndex = PTRS_PER_PD_X86; 0 < PageIndex; PageIndex--)
+    {
+      if (NewPageDir->Pde[PageIndex - 1].PageFrameNumber == NewPageDirMfn)
+        {
+        /* A machine page cannot be a page directory and a page table at
+           the same time. We're trying to map the page dir as page table here,
+           undo the mapping and deal with it later. */
+        NewPageDir->Pde[PageIndex - 1].Val = 0;
+        }
+    }
+
+  XenMemSetNewPageReadonly(NewPageDir, NewPageDirMfn);
+  for (PageIndex = PTRS_PER_PD_X86; 0 < PageIndex; PageIndex--)
+    {
+      if (NewPageDir->Pde[PageIndex - 1].Valid)
+        {
+          XenMemSetNewPageReadonly(NewPageDir,
+                                   NewPageDir->Pde[PageIndex - 1].Val
+                                   >> PFN_SHIFT);
+        }
+    }
+
+  XenMemSetOldPageReadonly(NewPageDirMfn);
+  for (PageIndex = PTRS_PER_PD_X86; 0 < PageIndex; PageIndex--)
+    {
+      if (NewPageDir->Pde[PageIndex - 1].Valid)
+        {
+          XenMemSetOldPageReadonly(NewPageDir->Pde[PageIndex - 1].Val
+                                   >> PFN_SHIFT);
+        }
+    }
+
+  /* Set the PDBR */
+  MmuExtReq.cmd = MMUEXT_NEW_BASEPTR;
+  MmuExtReq.mfn = NewPageDirMfn;
+  if (0 != HYPERVISOR_mmuext_op(&MmuExtReq, 1, NULL, DOMID_SELF))
+    {
+      printf("Failed to set new page dir\n");
+      XenDie();
+    }
+}
+
 /* EOF */