Author: fireball
Date: Sun Oct  1 23:39:49 2006
New Revision: 24350
URL: 
http://svn.reactos.org/svn/reactos?rev=24350&view=rev
Log:
- Add new type of debug print for windows loader
- Add address conversion routines for windows loader
- Add stubs for PE loading, memory operations
- Add some code to the LoadAndBootWindows()
Some notes:
- The windows loader is going to become some kind of a library in future, shared at least
between freeldr and EFI loader.
- The code in windows loader is specific to i386 architecture for now, but I add it to the
"freeldr_base". I better separate it a bit later, after discussion with arty
(because I hardly want compatibility with loading windows on PPC).
Added:
    trunk/reactos/boot/freeldr/freeldr/windows/conversion.c
    trunk/reactos/boot/freeldr/freeldr/windows/peloader.c
    trunk/reactos/boot/freeldr/freeldr/windows/wlmemory.c
Modified:
    trunk/reactos/boot/freeldr/freeldr/debug.c
    trunk/reactos/boot/freeldr/freeldr/freeldr_base.rbuild
    trunk/reactos/boot/freeldr/freeldr/include/debug.h
    trunk/reactos/boot/freeldr/freeldr/include/winldr.h
    trunk/reactos/boot/freeldr/freeldr/windows/winldr.c
Modified: trunk/reactos/boot/freeldr/freeldr/debug.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/boot/freeldr/freeldr/debug…
==============================================================================
--- trunk/reactos/boot/freeldr/freeldr/debug.c (original)
+++ trunk/reactos/boot/freeldr/freeldr/debug.c Sun Oct  1 23:39:49 2006
@@ -38,7 +38,8 @@
 #elif defined (DEBUG_REACTOS)
 ULONG          DebugPrintMask = DPRINT_REACTOS | DPRINT_REGISTRY;
 #elif defined (DEBUG_CUSTOM)
-ULONG          DebugPrintMask =
DPRINT_WARNING|DPRINT_FILESYSTEM|DPRINT_MEMORY|DPRINT_LINUX;
+ULONG          DebugPrintMask = DPRINT_WARNING | DPRINT_MEMORY |
+                                DPRINT_REACTOS | DPRINT_WINDOWS | DPRINT_HWDETECT;
 #else //#elif defined (DEBUG_NONE)
 ULONG          DebugPrintMask = 0;
 #endif
@@ -203,6 +204,16 @@
                DebugPrintChar(':');
                DebugPrintChar(' ');
                break;
+       case DPRINT_WINDOWS:
+               DebugPrintChar('W');
+               DebugPrintChar('I');
+               DebugPrintChar('N');
+               DebugPrintChar('L');
+               DebugPrintChar('D');
+               DebugPrintChar('R');
+               DebugPrintChar(':');
+               DebugPrintChar(' ');
+               break;
        case DPRINT_HWDETECT:
                DebugPrintChar('H');
                DebugPrintChar('W');
Modified: trunk/reactos/boot/freeldr/freeldr/freeldr_base.rbuild
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/boot/freeldr/freeldr/freel…
==============================================================================
--- trunk/reactos/boot/freeldr/freeldr/freeldr_base.rbuild (original)
+++ trunk/reactos/boot/freeldr/freeldr/freeldr_base.rbuild Sun Oct  1 23:39:49 2006
@@ -8,6 +8,7 @@
        <define name="DEBUG" />
 -->
        <define name="_NTHAL_" />
+       <define name="_NTSYSTEM_" />
        <compilerflag>-ffreestanding</compilerflag>
        <compilerflag>-fno-builtin</compilerflag>
        <compilerflag>-fno-inline</compilerflag>
@@ -67,7 +68,10 @@
                <file>video.c</file>
        </directory>
        <directory name="windows">
+               <file>conversion.c</file>
+               <file>peloader.c</file>
                <file>winldr.c</file>
+               <file>wlmemory.c</file>
        </directory>
        <file>freeldr.c</file>
        <file>debug.c</file>
Modified: trunk/reactos/boot/freeldr/freeldr/include/debug.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/boot/freeldr/freeldr/inclu…
==============================================================================
--- trunk/reactos/boot/freeldr/freeldr/include/debug.h (original)
+++ trunk/reactos/boot/freeldr/freeldr/include/debug.h Sun Oct  1 23:39:49 2006
@@ -35,6 +35,7 @@
        #define DPRINT_REACTOS          0x00000100  // OR this with DebugPrintMask to
enable ReactOS messages
        #define DPRINT_LINUX            0x00000200  // OR this with DebugPrintMask to
enable Linux messages
        #define DPRINT_HWDETECT         0x00000400  // OR this with DebugPrintMask to
enable hardware detection messages
+       #define DPRINT_WINDOWS          0x00000800  // OR this with DebugPrintMask to
enable messages from Windows loader
        VOID    DebugInit(VOID);
        VOID    DebugPrint(ULONG Mask, char *format, ...);
Modified: trunk/reactos/boot/freeldr/freeldr/include/winldr.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/boot/freeldr/freeldr/inclu…
==============================================================================
--- trunk/reactos/boot/freeldr/freeldr/include/winldr.h (original)
+++ trunk/reactos/boot/freeldr/freeldr/include/winldr.h Sun Oct  1 23:39:49 2006
@@ -29,5 +29,49 @@
 ///////////////////////////////////////////////////////////////////////////////////////
 VOID LoadAndBootWindows(PCSTR OperatingSystemName, WORD OperatingSystemVersion);
+/* Entry-point to kernel */
+typedef
+VOID
+NTAPI
+(*KERNEL_ENTRY_POINT) (PLOADER_PARAMETER_BLOCK LoaderBlock);
+
+
+// Some definitions
+#define SECTOR_SIZE 512
+
+// Descriptors
+#define NUM_GDT 28 //15. The kernel wants 0xD8 as a last GDT entry offset
+#define NUM_IDT 0x100 // only 16 are used though
+
+// conversion.c
+PVOID VaToPa(PVOID Va);
+PVOID PaToVa(PVOID Pa);
+VOID List_PaToVa(LIST_ENTRY *ListEntry);
+VOID ConvertConfigToVA(PCONFIGURATION_COMPONENT_DATA Start);
+
+// peloader.c
+BOOLEAN
+WinLdrLoadImage(IN PCHAR FileName,
+                OUT PVOID *ImageBasePA);
+
+
+BOOLEAN
+WinLdrAllocateDataTableEntry(IN OUT PLOADER_PARAMETER_BLOCK WinLdrBlock,
+                             IN PCCH BaseDllName,
+                             IN PCCH FullDllName,
+                             IN PVOID BasePA,
+                             OUT PLDR_DATA_TABLE_ENTRY *NewEntry);
+
+BOOLEAN
+WinLdrScanImportDescriptorTable(IN OUT PLOADER_PARAMETER_BLOCK WinLdrBlock,
+                                IN PCCH DirectoryPath,
+                                IN PLDR_DATA_TABLE_ENTRY ScanDTE);
+
+// wlmemory.c
+BOOLEAN
+WinLdrTurnOnPaging(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
+                   ULONG PcrBasePage,
+                   ULONG TssBasePage,
+                   PVOID GdtIdt);
 #endif // defined __WINLDR_H
Added: trunk/reactos/boot/freeldr/freeldr/windows/conversion.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/boot/freeldr/freeldr/windo…
==============================================================================
--- trunk/reactos/boot/freeldr/freeldr/windows/conversion.c (added)
+++ trunk/reactos/boot/freeldr/freeldr/windows/conversion.c Sun Oct  1 23:39:49 2006
@@ -1,0 +1,123 @@
+/*
+ * PROJECT:         EFI Windows Loader
+ * LICENSE:         GPL - See COPYING in the top level directory
+ * FILE:            freeldr/winldr/conversion.c
+ * PURPOSE:         Physical <-> Virtual addressing mode conversions
+ * PROGRAMMERS:     Aleksey Bragin (aleksey(a)reactos.org)
+ */
+
+/* INCLUDES ***************************************************************/
+
+#include <freeldr.h>
+
+//#include <ndk/ldrtypes.h>
+
+#define NDEBUG
+#include <debug.h>
+
+/* FUNCTIONS **************************************************************/
+
+/* Arch-specific addresses translation implementation */
+PVOID
+VaToPa(PVOID Va)
+{
+       return (PVOID)((ULONG_PTR)Va & ~KSEG0_BASE);
+}
+
+PVOID
+PaToVa(PVOID Pa)
+{
+       return (PVOID)((ULONG_PTR)Pa | KSEG0_BASE);
+}
+
+VOID
+List_PaToVa(LIST_ENTRY *ListEntry)
+{
+       LIST_ENTRY *ListHead = ListEntry;
+       LIST_ENTRY *Next = ListEntry->Flink;
+       LIST_ENTRY *NextPA;
+
+       //Print(L"\n\nList_Entry: %X, First Next: %X\n", ListEntry, Next);
+       //
+       // Walk through the whole list
+       //
+       if (Next != NULL)
+       {
+               while (Next != PaToVa(ListHead))
+               {
+                       NextPA = VaToPa(Next);
+                       //Print(L"Current: %X, Flink: %X, Blink: %X\n", Next,
NextPA->Flink, NextPA->Blink);
+
+                       NextPA->Flink = PaToVa((PVOID)NextPA->Flink);
+                       NextPA->Blink = PaToVa((PVOID)NextPA->Blink);
+
+                       //Print(L"After converting Flink: %X, Blink: %X\n",
NextPA->Flink, NextPA->Blink);
+
+                       Next = NextPA->Flink;
+               }
+
+               //
+               // Finally convert first Flink/Blink
+               //
+               ListEntry->Flink = PaToVa((PVOID)ListEntry->Flink);
+               if (ListEntry->Blink)
+                       ListEntry->Blink = PaToVa((PVOID)ListEntry->Blink);
+       }
+}
+
+// This function converts only Child->Child, and calls itself for each Sibling
+VOID
+ConvertConfigToVA(PCONFIGURATION_COMPONENT_DATA Start)
+{
+       PCONFIGURATION_COMPONENT_DATA Child;
+       PCONFIGURATION_COMPONENT_DATA Sibling;
+
+       DbgPrint((DPRINT_WINDOWS, "ConvertConfigToVA(Start 0x%X)", Start));
+       Child = Start;
+
+       while (Child != NULL)
+       {
+               if (Child->ConfigurationData)
+                       Child->ConfigurationData = PaToVa(Child->ConfigurationData);
+
+               if (Child->Child)
+                       Child->Child = PaToVa(Child->Child);
+
+               if (Child->Parent)
+                       Child->Parent = PaToVa(Child->Parent);
+
+               if (Child->Sibling)
+                       Child->Sibling = PaToVa(Child->Sibling);
+
+               DbgPrint((DPRINT_WINDOWS, "Device 0x%X class %d", Child,
Child->ComponentEntry.Class));
+
+               // If the child has a sibling list, then search the sibling list
+               // for an entry that matches the specified class, type, and key.
+               Sibling = Child->Sibling;
+               while (Sibling != NULL)
+               {
+                       if (Sibling->ConfigurationData)
+                               Sibling->ConfigurationData =
PaToVa(Sibling->ConfigurationData);
+
+                       if (Sibling->Child)
+                               Sibling->Child = PaToVa(Sibling->Child);
+
+                       if (Sibling->Parent)
+                               Sibling->Parent = PaToVa(Sibling->Parent);
+
+                       if (Sibling->Sibling)
+                               Sibling->Sibling = PaToVa(Sibling->Sibling);
+
+                       DbgPrint((DPRINT_WINDOWS, "Device 0x%X class %d",
Sibling, Sibling->ComponentEntry.Class));
+
+                       // If the sibling has a child tree, then search the child tree
+                       // for an entry that matches the specified class, type, and key.
+                       if (VaToPa(Sibling->Child) != NULL)
+                               ConvertConfigToVA(VaToPa(Sibling->Child));
+
+                       Sibling = VaToPa(Sibling->Sibling);
+               }
+
+               Child = VaToPa(Child->Child);
+       }
+}
Added: trunk/reactos/boot/freeldr/freeldr/windows/peloader.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/boot/freeldr/freeldr/windo…
==============================================================================
--- trunk/reactos/boot/freeldr/freeldr/windows/peloader.c (added)
+++ trunk/reactos/boot/freeldr/freeldr/windows/peloader.c Sun Oct  1 23:39:49 2006
@@ -1,0 +1,55 @@
+/*
+ * PROJECT:         WinLoader
+ * LICENSE:         GPL - See COPYING in the top level directory
+ * FILE:            freeldr/winldr/peloader.c
+ * PURPOSE:         Provides routines for loading PE files. To be merged with
+ *                  arch/i386/loader.c in future
+ *                  This article was very handy during development:
+ *                  
http://msdn.microsoft.com/msdnmag/issues/02/03/PE2/
+ * PROGRAMMERS:     Aleksey Bragin (aleksey(a)reactos.org)
+ *                  The source code in this file is based on the work of respective
+ *                  authors of PE loading code in ReactOS and Brian Palmer and
+ *                  Alex Ionescu's arch/i386/loader.c, and my research project
+ *                  (creating a native EFI loader for Windows)
+ */
+
+/* INCLUDES ***************************************************************/
+#include <freeldr.h>
+
+#define NDEBUG
+#include <debug.h>
+
+/* FUNCTIONS **************************************************************/
+
+BOOLEAN
+WinLdrScanImportDescriptorTable(IN OUT PLOADER_PARAMETER_BLOCK WinLdrBlock,
+                                IN PCCH DirectoryPath,
+                                IN PLDR_DATA_TABLE_ENTRY ScanDTE)
+{
+       return FALSE;
+}
+
+BOOLEAN
+WinLdrAllocateDataTableEntry(IN OUT PLOADER_PARAMETER_BLOCK WinLdrBlock,
+                             IN PCCH BaseDllName,
+                             IN PCCH FullDllName,
+                             IN PVOID BasePA,
+                             OUT PLDR_DATA_TABLE_ENTRY *NewEntry)
+{
+       return FALSE;
+}
+
+/* WinLdrLoadImage loads the specified image from the file (it doesn't
+   perform any additional operations on the filename, just directly
+   calls the file I/O routines), and relocates it so that it's ready
+   to be used when paging is enabled.
+   Addressing mode: physical
+ */
+BOOLEAN
+WinLdrLoadImage(IN PCHAR FileName,
+                OUT PVOID *ImageBasePA)
+{
+       return FALSE;
+}
+
+/* PRIVATE FUNCTIONS *******************************************************/
Modified: trunk/reactos/boot/freeldr/freeldr/windows/winldr.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/boot/freeldr/freeldr/windo…
==============================================================================
--- trunk/reactos/boot/freeldr/freeldr/windows/winldr.c (original)
+++ trunk/reactos/boot/freeldr/freeldr/windows/winldr.c Sun Oct  1 23:39:49 2006
@@ -24,13 +24,178 @@
 #define NDEBUG
 #include <debug.h>
+VOID DumpMemoryAllocMap(VOID);
+VOID WinLdrpDumpMemoryDescriptors(PLOADER_PARAMETER_BLOCK LoaderBlock);
+
 VOID
 LoadAndBootWindows(PCSTR OperatingSystemName, WORD OperatingSystemVersion)
 {
        CHAR  MsgBuffer[256];
-
-       sprintf(MsgBuffer,"Booting Microsoft(R) Windows(R) OS version '%04x'
is not implemented yet", OperatingSystemVersion);
-       UiMessageBox(MsgBuffer);
+       CHAR  SystemPath[1024], SearchPath[1024];
+       CHAR  FileName[1024];
+       CHAR  BootPath[256];
+       PVOID NtosBase = NULL, HalBase = NULL;
+       BOOLEAN Status;
+       ULONG SectionId;
+       ULONG BootDevice;
+       PLOADER_PARAMETER_BLOCK LoaderBlock=NULL, LoaderBlockVA;
+       PLDR_DATA_TABLE_ENTRY KernelDTE, HalDTE;
+       KERNEL_ENTRY_POINT KiSystemStartup;
+       // Mm-related things
+       PVOID GdtIdt=NULL;
+       ULONG PcrBasePage=0;
+       ULONG TssBasePage=0;
+
+       //sprintf(MsgBuffer,"Booting Microsoft(R) Windows(R) OS version
'%04x' is not implemented yet", OperatingSystemVersion);
+       //UiMessageBox(MsgBuffer);
+
+       //
+       // Open the operating system section
+       // specified in the .ini file
+       //
+       if (!IniOpenSection(OperatingSystemName, &SectionId))
+       {
+               sprintf(MsgBuffer,"Operating System section '%s' not found in
freeldr.ini", OperatingSystemName);
+               UiMessageBox(MsgBuffer);
+               return;
+       }
+
+       /*
+        * Make sure the system path is set in the .ini file
+        */
+       if (!IniReadSettingByName(SectionId, "SystemPath", SystemPath,
sizeof(SystemPath)))
+       {
+               UiMessageBox("System path not specified for selected operating
system.");
+               return;
+       }
+
+       if (!MachDiskNormalizeSystemPath(SystemPath,
+                                        sizeof(SystemPath)))
+       {
+               UiMessageBox("Invalid system path");
+               return;
+       }
+
+       UiDrawStatusText("Loading...");
+
+       /*
+        * Try to open system drive
+        */
+       BootDevice = 0xffffffff;
+       if (!FsOpenSystemVolume(SystemPath, BootPath, &BootDevice))
+       {
+               UiMessageBox("Failed to open boot drive.");
+               return;
+       }
+
+       /* append a backslash */
+       if ((strlen(BootPath)==0) ||
+           BootPath[strlen(BootPath)] != '\\')
+               strcat(BootPath, "\\");
+
+       DbgPrint((DPRINT_WINDOWS,"SystemRoot: '%s'\n", BootPath));
+
+       /* Allocate and minimalistic-initialize LPB */
+       //AllocateAndInitLPB(&LoaderBlock);
+
+       // Load kernel
+       strcpy(FileName, BootPath);
+       strcat(FileName, "SYSTEM32\\NTOSKRNL.EXE");
+       Status = WinLdrLoadImage(FileName, &NtosBase);
+       DbgPrint((DPRINT_WINDOWS, "Ntos loaded with status %d\n", Status));
+
+       // Load HAL
+       strcpy(FileName, BootPath);
+       strcat(FileName, "SYSTEM32\\HAL.DLL");
+       Status = WinLdrLoadImage(FileName, &HalBase);
+       DbgPrint((DPRINT_WINDOWS, "HAL loaded with status %d\n", Status));
+
+       WinLdrAllocateDataTableEntry(LoaderBlock, "ntoskrnl.exe",
+               "WINNT\\SYSTEM32\\NTOSKRNL.EXE", NtosBase, &KernelDTE);
+       WinLdrAllocateDataTableEntry(LoaderBlock, "hal.dll",
+               "WINNT\\SYSTEM32\\HAL.EXE", HalBase, &HalDTE);
+
+       /* Load all referenced DLLs for kernel and HAL */
+       strcpy(SearchPath, BootPath);
+       strcat(SearchPath, "SYSTEM32\\");
+       WinLdrScanImportDescriptorTable(LoaderBlock, SearchPath, KernelDTE);
+       WinLdrScanImportDescriptorTable(LoaderBlock, SearchPath, HalDTE);
+
+       /* Initialize Phase 1 - before NLS */
+       //WinLdrInitializePhase1(LoaderBlock);
+
+       /* Load SYSTEM hive and its LOG file */
+       strcpy(SearchPath, BootPath);
+       strcat(SearchPath, "SYSTEM32\\CONFIG\\");
+       //Status = WinLdrLoadSystemHive(LoaderBlock, SearchPath, "SYSTEM");
+       DbgPrint((DPRINT_WINDOWS, "SYSTEM hive loaded with status %d\n",
Status));
+
+       /* Load NLS data */
+       strcpy(SearchPath, BootPath);
+       strcat(SearchPath, "SYSTEM32\\");
+       //Status = WinLdrLoadNLSData(LoaderBlock, SearchPath,
+       //      "c_1252.nls", "c_437.nls", "l_intl.nls");
+       DbgPrint((DPRINT_WINDOWS, "NLS data loaded with status %d\n", Status));
+
+       /* Load OEM HAL font */
+
+       /* Load boot drivers */
+
+       /* Alloc PCR, TSS, do magic things with the GDT/IDT */
+       //WinLdrSetupForNt(LoaderBlock, &GdtIdt, &PcrBasePage, &TssBasePage);
+
+       /* Save entry-point pointer (VA) */
+       KiSystemStartup = (KERNEL_ENTRY_POINT)KernelDTE->EntryPoint;
+       LoaderBlockVA = PaToVa(LoaderBlock);
+
+       /* Debugging... */
+       //DumpMemoryAllocMap();
+
+       /* Turn on paging mode of CPU*/
+       WinLdrTurnOnPaging(LoaderBlock, PcrBasePage, TssBasePage, GdtIdt);
+
+       DbgPrint((DPRINT_WINDOWS, "Hello from paged mode, KiSystemStartup %p,
LoaderBlockVA %p!\n",
+               KiSystemStartup, LoaderBlockVA));
+
+       WinLdrpDumpMemoryDescriptors(LoaderBlockVA);
+
+       /*__asm
+       {
+               or esp, KSEG0_BASE;
+               or ebp, KSEG0_BASE;
+       }*/
+
+       /*
+       {
+               ULONG *trrr = (ULONG *)(512*1024*1024);
+
+               *trrr = 0x13131414;
+       }
+
+       //FIXME!
+       while (1) {};*/
+
+       (KiSystemStartup)(LoaderBlockVA);
        return;
 }
+
+VOID
+WinLdrpDumpMemoryDescriptors(PLOADER_PARAMETER_BLOCK LoaderBlock)
+{
+       PLIST_ENTRY NextMd;
+       PMEMORY_ALLOCATION_DESCRIPTOR MemoryDescriptor;
+
+       NextMd = LoaderBlock->MemoryDescriptorListHead.Flink;
+
+       while (NextMd != &LoaderBlock->MemoryDescriptorListHead)
+       {
+               MemoryDescriptor = CONTAINING_RECORD(NextMd, MEMORY_ALLOCATION_DESCRIPTOR,
ListEntry);
+
+
+               DbgPrint((DPRINT_WINDOWS, "BP %08X PC %04X MT %d\n",
MemoryDescriptor->BasePage,
+                       MemoryDescriptor->PageCount, MemoryDescriptor->MemoryType));
+
+               NextMd = MemoryDescriptor->ListEntry.Flink;
+       }
+}
Added: trunk/reactos/boot/freeldr/freeldr/windows/wlmemory.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/boot/freeldr/freeldr/windo…
==============================================================================
--- trunk/reactos/boot/freeldr/freeldr/windows/wlmemory.c (added)
+++ trunk/reactos/boot/freeldr/freeldr/windows/wlmemory.c Sun Oct  1 23:39:49 2006
@@ -1,0 +1,35 @@
+/*
+ * 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(a)reactos.org)
+ */
+
+/* INCLUDES ***************************************************************/
+
+#include <freeldr.h>
+
+#include <ndk/asm.h>
+
+#define NDEBUG
+#include <debug.h>
+
+// This is needed because headers define wrong one for ReactOS
+#undef KIP0PCRADDRESS
+#define KIP0PCRADDRESS                      0xffdff000
+
+#define HYPER_SPACE_ENTRY       0x300
+
+/* GLOBALS ***************************************************************/
+
+/* FUNCTIONS **************************************************************/
+
+BOOLEAN
+WinLdrTurnOnPaging(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
+                   ULONG PcrBasePage,
+                   ULONG TssBasePage,
+                   PVOID GdtIdt)
+{
+       return FALSE;
+}