- Add new type of debug print for windows loader
authorAleksey Bragin <aleksey@reactos.org>
Sun, 1 Oct 2006 19:39:49 +0000 (19:39 +0000)
committerAleksey Bragin <aleksey@reactos.org>
Sun, 1 Oct 2006 19:39:49 +0000 (19:39 +0000)
- 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).

svn path=/trunk/; revision=24350

reactos/boot/freeldr/freeldr/debug.c
reactos/boot/freeldr/freeldr/freeldr_base.rbuild
reactos/boot/freeldr/freeldr/include/debug.h
reactos/boot/freeldr/freeldr/include/winldr.h
reactos/boot/freeldr/freeldr/windows/conversion.c [new file with mode: 0644]
reactos/boot/freeldr/freeldr/windows/peloader.c [new file with mode: 0644]
reactos/boot/freeldr/freeldr/windows/winldr.c
reactos/boot/freeldr/freeldr/windows/wlmemory.c [new file with mode: 0644]

index 073f612..4e9e4e1 100644 (file)
@@ -38,7 +38,8 @@ ULONG         DebugPrintMask = DPRINT_INIFILE;
 #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 @@ VOID DebugPrintHeader(ULONG Mask)
                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');
index 15094f3..654eb39 100644 (file)
@@ -8,6 +8,7 @@
        <define name="DEBUG" />
 -->
        <define name="_NTHAL_" />
+       <define name="_NTSYSTEM_" />
        <compilerflag>-ffreestanding</compilerflag>
        <compilerflag>-fno-builtin</compilerflag>
        <compilerflag>-fno-inline</compilerflag>
                <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>
index 07371aa..848c9dd 100644 (file)
@@ -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, ...);
index f3607fd..c4c973b 100644 (file)
 ///////////////////////////////////////////////////////////////////////////////////////\r
 VOID LoadAndBootWindows(PCSTR OperatingSystemName, WORD OperatingSystemVersion);\r
 \r
+/* Entry-point to kernel */\r
+typedef\r
+VOID\r
+NTAPI\r
+(*KERNEL_ENTRY_POINT) (PLOADER_PARAMETER_BLOCK LoaderBlock);\r
+\r
+\r
+// Some definitions\r
+#define SECTOR_SIZE 512\r
+\r
+// Descriptors\r
+#define NUM_GDT 28 //15. The kernel wants 0xD8 as a last GDT entry offset\r
+#define NUM_IDT 0x100 // only 16 are used though\r
+\r
+// conversion.c\r
+PVOID VaToPa(PVOID Va);\r
+PVOID PaToVa(PVOID Pa);\r
+VOID List_PaToVa(LIST_ENTRY *ListEntry);\r
+VOID ConvertConfigToVA(PCONFIGURATION_COMPONENT_DATA Start);\r
+\r
+// peloader.c\r
+BOOLEAN\r
+WinLdrLoadImage(IN PCHAR FileName,\r
+                OUT PVOID *ImageBasePA);\r
+\r
+\r
+BOOLEAN\r
+WinLdrAllocateDataTableEntry(IN OUT PLOADER_PARAMETER_BLOCK WinLdrBlock,\r
+                             IN PCCH BaseDllName,\r
+                             IN PCCH FullDllName,\r
+                             IN PVOID BasePA,\r
+                             OUT PLDR_DATA_TABLE_ENTRY *NewEntry);\r
+\r
+BOOLEAN\r
+WinLdrScanImportDescriptorTable(IN OUT PLOADER_PARAMETER_BLOCK WinLdrBlock,\r
+                                IN PCCH DirectoryPath,\r
+                                IN PLDR_DATA_TABLE_ENTRY ScanDTE);\r
+\r
+// wlmemory.c\r
+BOOLEAN\r
+WinLdrTurnOnPaging(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,\r
+                   ULONG PcrBasePage,\r
+                   ULONG TssBasePage,\r
+                   PVOID GdtIdt);\r
 \r
 #endif // defined __WINLDR_H\r
diff --git a/reactos/boot/freeldr/freeldr/windows/conversion.c b/reactos/boot/freeldr/freeldr/windows/conversion.c
new file mode 100644 (file)
index 0000000..8d29c1e
--- /dev/null
@@ -0,0 +1,123 @@
+/*\r
+ * PROJECT:         EFI Windows Loader\r
+ * LICENSE:         GPL - See COPYING in the top level directory\r
+ * FILE:            freeldr/winldr/conversion.c\r
+ * PURPOSE:         Physical <-> Virtual addressing mode conversions\r
+ * PROGRAMMERS:     Aleksey Bragin (aleksey@reactos.org)\r
+ */\r
+\r
+/* INCLUDES ***************************************************************/\r
+\r
+#include <freeldr.h>\r
+\r
+//#include <ndk/ldrtypes.h>\r
+\r
+#define NDEBUG\r
+#include <debug.h>\r
+\r
+/* FUNCTIONS **************************************************************/\r
+\r
+/* Arch-specific addresses translation implementation */\r
+PVOID\r
+VaToPa(PVOID Va)\r
+{\r
+       return (PVOID)((ULONG_PTR)Va & ~KSEG0_BASE);\r
+}\r
+\r
+PVOID\r
+PaToVa(PVOID Pa)\r
+{\r
+       return (PVOID)((ULONG_PTR)Pa | KSEG0_BASE);\r
+}\r
+\r
+VOID\r
+List_PaToVa(LIST_ENTRY *ListEntry)\r
+{\r
+       LIST_ENTRY *ListHead = ListEntry;\r
+       LIST_ENTRY *Next = ListEntry->Flink;\r
+       LIST_ENTRY *NextPA;\r
+\r
+       //Print(L"\n\nList_Entry: %X, First Next: %X\n", ListEntry, Next);\r
+       //\r
+       // Walk through the whole list\r
+       //\r
+       if (Next != NULL)\r
+       {\r
+               while (Next != PaToVa(ListHead))\r
+               {\r
+                       NextPA = VaToPa(Next);\r
+                       //Print(L"Current: %X, Flink: %X, Blink: %X\n", Next, NextPA->Flink, NextPA->Blink);\r
+\r
+                       NextPA->Flink = PaToVa((PVOID)NextPA->Flink);\r
+                       NextPA->Blink = PaToVa((PVOID)NextPA->Blink);\r
+\r
+                       //Print(L"After converting Flink: %X, Blink: %X\n", NextPA->Flink, NextPA->Blink);\r
+\r
+                       Next = NextPA->Flink;\r
+               }\r
+\r
+               //\r
+               // Finally convert first Flink/Blink\r
+               //\r
+               ListEntry->Flink = PaToVa((PVOID)ListEntry->Flink);\r
+               if (ListEntry->Blink)\r
+                       ListEntry->Blink = PaToVa((PVOID)ListEntry->Blink);\r
+       }\r
+}\r
+\r
+// This function converts only Child->Child, and calls itself for each Sibling\r
+VOID\r
+ConvertConfigToVA(PCONFIGURATION_COMPONENT_DATA Start)\r
+{\r
+       PCONFIGURATION_COMPONENT_DATA Child;\r
+       PCONFIGURATION_COMPONENT_DATA Sibling;\r
+\r
+       DbgPrint((DPRINT_WINDOWS, "ConvertConfigToVA(Start 0x%X)", Start));\r
+       Child = Start;\r
+\r
+       while (Child != NULL)\r
+       {\r
+               if (Child->ConfigurationData)\r
+                       Child->ConfigurationData = PaToVa(Child->ConfigurationData);\r
+\r
+               if (Child->Child)\r
+                       Child->Child = PaToVa(Child->Child);\r
+\r
+               if (Child->Parent)\r
+                       Child->Parent = PaToVa(Child->Parent);\r
+\r
+               if (Child->Sibling)\r
+                       Child->Sibling = PaToVa(Child->Sibling);\r
+\r
+               DbgPrint((DPRINT_WINDOWS, "Device 0x%X class %d", Child, Child->ComponentEntry.Class));\r
+\r
+               // If the child has a sibling list, then search the sibling list\r
+               // for an entry that matches the specified class, type, and key.\r
+               Sibling = Child->Sibling;\r
+               while (Sibling != NULL)\r
+               {\r
+                       if (Sibling->ConfigurationData)\r
+                               Sibling->ConfigurationData = PaToVa(Sibling->ConfigurationData);\r
+\r
+                       if (Sibling->Child)\r
+                               Sibling->Child = PaToVa(Sibling->Child);\r
+\r
+                       if (Sibling->Parent)\r
+                               Sibling->Parent = PaToVa(Sibling->Parent);\r
+\r
+                       if (Sibling->Sibling)\r
+                               Sibling->Sibling = PaToVa(Sibling->Sibling);\r
+\r
+                       DbgPrint((DPRINT_WINDOWS, "Device 0x%X class %d", Sibling, Sibling->ComponentEntry.Class));\r
+\r
+                       // If the sibling has a child tree, then search the child tree\r
+                       // for an entry that matches the specified class, type, and key.\r
+                       if (VaToPa(Sibling->Child) != NULL)\r
+                               ConvertConfigToVA(VaToPa(Sibling->Child));\r
+\r
+                       Sibling = VaToPa(Sibling->Sibling);\r
+               }\r
+\r
+               Child = VaToPa(Child->Child);\r
+       }\r
+}\r
diff --git a/reactos/boot/freeldr/freeldr/windows/peloader.c b/reactos/boot/freeldr/freeldr/windows/peloader.c
new file mode 100644 (file)
index 0000000..c8f58f3
--- /dev/null
@@ -0,0 +1,55 @@
+/*\r
+ * PROJECT:         WinLoader\r
+ * LICENSE:         GPL - See COPYING in the top level directory\r
+ * FILE:            freeldr/winldr/peloader.c\r
+ * PURPOSE:         Provides routines for loading PE files. To be merged with\r
+ *                  arch/i386/loader.c in future\r
+ *                  This article was very handy during development:\r
+ *                  http://msdn.microsoft.com/msdnmag/issues/02/03/PE2/\r
+ * PROGRAMMERS:     Aleksey Bragin (aleksey@reactos.org)\r
+ *                  The source code in this file is based on the work of respective\r
+ *                  authors of PE loading code in ReactOS and Brian Palmer and\r
+ *                  Alex Ionescu's arch/i386/loader.c, and my research project\r
+ *                  (creating a native EFI loader for Windows)\r
+ */\r
+\r
+/* INCLUDES ***************************************************************/\r
+#include <freeldr.h>\r
+\r
+#define NDEBUG\r
+#include <debug.h>\r
+\r
+/* FUNCTIONS **************************************************************/\r
+\r
+BOOLEAN\r
+WinLdrScanImportDescriptorTable(IN OUT PLOADER_PARAMETER_BLOCK WinLdrBlock,\r
+                                IN PCCH DirectoryPath,\r
+                                IN PLDR_DATA_TABLE_ENTRY ScanDTE)\r
+{\r
+       return FALSE;\r
+}\r
+\r
+BOOLEAN\r
+WinLdrAllocateDataTableEntry(IN OUT PLOADER_PARAMETER_BLOCK WinLdrBlock,\r
+                             IN PCCH BaseDllName,\r
+                             IN PCCH FullDllName,\r
+                             IN PVOID BasePA,\r
+                             OUT PLDR_DATA_TABLE_ENTRY *NewEntry)\r
+{\r
+       return FALSE;\r
+}\r
+\r
+/* WinLdrLoadImage loads the specified image from the file (it doesn't\r
+   perform any additional operations on the filename, just directly\r
+   calls the file I/O routines), and relocates it so that it's ready\r
+   to be used when paging is enabled.\r
+   Addressing mode: physical\r
+ */\r
+BOOLEAN\r
+WinLdrLoadImage(IN PCHAR FileName,\r
+                OUT PVOID *ImageBasePA)\r
+{\r
+       return FALSE;\r
+}\r
+\r
+/* PRIVATE FUNCTIONS *******************************************************/\r
index 6f20403..45c86f4 100644 (file)
 #define NDEBUG\r
 #include <debug.h>\r
 \r
+VOID DumpMemoryAllocMap(VOID);\r
+VOID WinLdrpDumpMemoryDescriptors(PLOADER_PARAMETER_BLOCK LoaderBlock);\r
+\r
 VOID\r
 LoadAndBootWindows(PCSTR OperatingSystemName, WORD OperatingSystemVersion)\r
 {\r
        CHAR  MsgBuffer[256];\r
+       CHAR  SystemPath[1024], SearchPath[1024];\r
+       CHAR  FileName[1024];\r
+       CHAR  BootPath[256];\r
+       PVOID NtosBase = NULL, HalBase = NULL;\r
+       BOOLEAN Status;\r
+       ULONG SectionId;\r
+       ULONG BootDevice;\r
+       PLOADER_PARAMETER_BLOCK LoaderBlock=NULL, LoaderBlockVA;\r
+       PLDR_DATA_TABLE_ENTRY KernelDTE, HalDTE;\r
+       KERNEL_ENTRY_POINT KiSystemStartup;\r
+       // Mm-related things\r
+       PVOID GdtIdt=NULL;\r
+       ULONG PcrBasePage=0;\r
+       ULONG TssBasePage=0;\r
+\r
+       //sprintf(MsgBuffer,"Booting Microsoft(R) Windows(R) OS version '%04x' is not implemented yet", OperatingSystemVersion);\r
+       //UiMessageBox(MsgBuffer);\r
+\r
+       //\r
+       // Open the operating system section\r
+       // specified in the .ini file\r
+       //\r
+       if (!IniOpenSection(OperatingSystemName, &SectionId))\r
+       {\r
+               sprintf(MsgBuffer,"Operating System section '%s' not found in freeldr.ini", OperatingSystemName);\r
+               UiMessageBox(MsgBuffer);\r
+               return;\r
+       }\r
+\r
+       /*\r
+        * Make sure the system path is set in the .ini file\r
+        */\r
+       if (!IniReadSettingByName(SectionId, "SystemPath", SystemPath, sizeof(SystemPath)))\r
+       {\r
+               UiMessageBox("System path not specified for selected operating system.");\r
+               return;\r
+       }\r
+\r
+       if (!MachDiskNormalizeSystemPath(SystemPath,\r
+                                        sizeof(SystemPath)))\r
+       {\r
+               UiMessageBox("Invalid system path");\r
+               return;\r
+       }\r
+\r
+       UiDrawStatusText("Loading...");\r
+\r
+       /*\r
+        * Try to open system drive\r
+        */\r
+       BootDevice = 0xffffffff;\r
+       if (!FsOpenSystemVolume(SystemPath, BootPath, &BootDevice))\r
+       {\r
+               UiMessageBox("Failed to open boot drive.");\r
+               return;\r
+       }\r
+\r
+       /* append a backslash */\r
+       if ((strlen(BootPath)==0) ||\r
+           BootPath[strlen(BootPath)] != '\\')\r
+               strcat(BootPath, "\\");\r
+\r
+       DbgPrint((DPRINT_WINDOWS,"SystemRoot: '%s'\n", BootPath));\r
+\r
+       /* Allocate and minimalistic-initialize LPB */\r
+       //AllocateAndInitLPB(&LoaderBlock);\r
+\r
+       // Load kernel\r
+       strcpy(FileName, BootPath);\r
+       strcat(FileName, "SYSTEM32\\NTOSKRNL.EXE");\r
+       Status = WinLdrLoadImage(FileName, &NtosBase);\r
+       DbgPrint((DPRINT_WINDOWS, "Ntos loaded with status %d\n", Status));\r
+\r
+       // Load HAL\r
+       strcpy(FileName, BootPath);\r
+       strcat(FileName, "SYSTEM32\\HAL.DLL");\r
+       Status = WinLdrLoadImage(FileName, &HalBase);\r
+       DbgPrint((DPRINT_WINDOWS, "HAL loaded with status %d\n", Status));\r
+\r
+       WinLdrAllocateDataTableEntry(LoaderBlock, "ntoskrnl.exe",\r
+               "WINNT\\SYSTEM32\\NTOSKRNL.EXE", NtosBase, &KernelDTE);\r
+       WinLdrAllocateDataTableEntry(LoaderBlock, "hal.dll",\r
+               "WINNT\\SYSTEM32\\HAL.EXE", HalBase, &HalDTE);\r
+\r
+       /* Load all referenced DLLs for kernel and HAL */\r
+       strcpy(SearchPath, BootPath);\r
+       strcat(SearchPath, "SYSTEM32\\");\r
+       WinLdrScanImportDescriptorTable(LoaderBlock, SearchPath, KernelDTE);\r
+       WinLdrScanImportDescriptorTable(LoaderBlock, SearchPath, HalDTE);\r
+\r
+       /* Initialize Phase 1 - before NLS */\r
+       //WinLdrInitializePhase1(LoaderBlock);\r
+\r
+       /* Load SYSTEM hive and its LOG file */\r
+       strcpy(SearchPath, BootPath);\r
+       strcat(SearchPath, "SYSTEM32\\CONFIG\\");\r
+       //Status = WinLdrLoadSystemHive(LoaderBlock, SearchPath, "SYSTEM");\r
+       DbgPrint((DPRINT_WINDOWS, "SYSTEM hive loaded with status %d\n", Status));\r
+\r
+       /* Load NLS data */\r
+       strcpy(SearchPath, BootPath);\r
+       strcat(SearchPath, "SYSTEM32\\");\r
+       //Status = WinLdrLoadNLSData(LoaderBlock, SearchPath,\r
+       //      "c_1252.nls", "c_437.nls", "l_intl.nls");\r
+       DbgPrint((DPRINT_WINDOWS, "NLS data loaded with status %d\n", Status));\r
+\r
+       /* Load OEM HAL font */\r
+\r
+       /* Load boot drivers */\r
 \r
-       sprintf(MsgBuffer,"Booting Microsoft(R) Windows(R) OS version '%04x' is not implemented yet", OperatingSystemVersion);\r
-       UiMessageBox(MsgBuffer);\r
+       /* Alloc PCR, TSS, do magic things with the GDT/IDT */\r
+       //WinLdrSetupForNt(LoaderBlock, &GdtIdt, &PcrBasePage, &TssBasePage);\r
+\r
+       /* Save entry-point pointer (VA) */\r
+       KiSystemStartup = (KERNEL_ENTRY_POINT)KernelDTE->EntryPoint;\r
+       LoaderBlockVA = PaToVa(LoaderBlock);\r
+\r
+       /* Debugging... */\r
+       //DumpMemoryAllocMap();\r
+\r
+       /* Turn on paging mode of CPU*/\r
+       WinLdrTurnOnPaging(LoaderBlock, PcrBasePage, TssBasePage, GdtIdt);\r
+\r
+       DbgPrint((DPRINT_WINDOWS, "Hello from paged mode, KiSystemStartup %p, LoaderBlockVA %p!\n",\r
+               KiSystemStartup, LoaderBlockVA));\r
+\r
+       WinLdrpDumpMemoryDescriptors(LoaderBlockVA);\r
+\r
+       /*__asm\r
+       {\r
+               or esp, KSEG0_BASE;\r
+               or ebp, KSEG0_BASE;\r
+       }*/\r
+\r
+       /*\r
+       {\r
+               ULONG *trrr = (ULONG *)(512*1024*1024);\r
+\r
+               *trrr = 0x13131414;\r
+       }\r
+\r
+       //FIXME!\r
+       while (1) {};*/\r
+\r
+       (KiSystemStartup)(LoaderBlockVA);\r
 \r
        return;\r
 }\r
+\r
+VOID\r
+WinLdrpDumpMemoryDescriptors(PLOADER_PARAMETER_BLOCK LoaderBlock)\r
+{\r
+       PLIST_ENTRY NextMd;\r
+       PMEMORY_ALLOCATION_DESCRIPTOR MemoryDescriptor;\r
+\r
+       NextMd = LoaderBlock->MemoryDescriptorListHead.Flink;\r
+\r
+       while (NextMd != &LoaderBlock->MemoryDescriptorListHead)\r
+       {\r
+               MemoryDescriptor = CONTAINING_RECORD(NextMd, MEMORY_ALLOCATION_DESCRIPTOR, ListEntry);\r
+\r
+\r
+               DbgPrint((DPRINT_WINDOWS, "BP %08X PC %04X MT %d\n", MemoryDescriptor->BasePage,\r
+                       MemoryDescriptor->PageCount, MemoryDescriptor->MemoryType));\r
+\r
+               NextMd = MemoryDescriptor->ListEntry.Flink;\r
+       }\r
+}\r
diff --git a/reactos/boot/freeldr/freeldr/windows/wlmemory.c b/reactos/boot/freeldr/freeldr/windows/wlmemory.c
new file mode 100644 (file)
index 0000000..a9393a6
--- /dev/null
@@ -0,0 +1,35 @@
+/*\r
+ * PROJECT:         EFI Windows Loader\r
+ * LICENSE:         GPL - See COPYING in the top level directory\r
+ * FILE:            freeldr/winldr/wlmemory.c\r
+ * PURPOSE:         Memory related routines\r
+ * PROGRAMMERS:     Aleksey Bragin (aleksey@reactos.org)\r
+ */\r
+\r
+/* INCLUDES ***************************************************************/\r
+\r
+#include <freeldr.h>\r
+\r
+#include <ndk/asm.h>\r
+\r
+#define NDEBUG\r
+#include <debug.h>\r
+\r
+// This is needed because headers define wrong one for ReactOS\r
+#undef KIP0PCRADDRESS\r
+#define KIP0PCRADDRESS                      0xffdff000\r
+\r
+#define HYPER_SPACE_ENTRY       0x300\r
+\r
+/* GLOBALS ***************************************************************/\r
+\r
+/* FUNCTIONS **************************************************************/\r
+\r
+BOOLEAN\r
+WinLdrTurnOnPaging(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,\r
+                   ULONG PcrBasePage,\r
+                   ULONG TssBasePage,\r
+                   PVOID GdtIdt)\r
+{\r
+       return FALSE;\r
+}\r