diff --git a/reactos/boot/freeldr/freeldr/debug.c b/reactos/boot/freeldr/freeldr/debug.c
index 073f6128ec9..4e9e4e1e076 100644
--- a/reactos/boot/freeldr/freeldr/debug.c
+++ b/reactos/boot/freeldr/freeldr/debug.c
@@ -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');
diff --git a/reactos/boot/freeldr/freeldr/freeldr_base.rbuild b/reactos/boot/freeldr/freeldr/freeldr_base.rbuild
index 15094f34202..654eb398025 100644
--- a/reactos/boot/freeldr/freeldr/freeldr_base.rbuild
+++ b/reactos/boot/freeldr/freeldr/freeldr_base.rbuild
@@ -8,6 +8,7 @@
-->
+
-ffreestanding
-fno-builtin
-fno-inline
@@ -67,7 +68,10 @@
video.c
+ conversion.c
+ peloader.c
winldr.c
+ wlmemory.c
freeldr.c
debug.c
diff --git a/reactos/boot/freeldr/freeldr/include/debug.h b/reactos/boot/freeldr/freeldr/include/debug.h
index 07371aa32aa..848c9dd74f0 100644
--- a/reactos/boot/freeldr/freeldr/include/debug.h
+++ b/reactos/boot/freeldr/freeldr/include/debug.h
@@ -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, ...);
diff --git a/reactos/boot/freeldr/freeldr/include/winldr.h b/reactos/boot/freeldr/freeldr/include/winldr.h
index f3607fd29ba..c4c973ba59c 100644
--- a/reactos/boot/freeldr/freeldr/include/winldr.h
+++ b/reactos/boot/freeldr/freeldr/include/winldr.h
@@ -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
diff --git a/reactos/boot/freeldr/freeldr/windows/conversion.c b/reactos/boot/freeldr/freeldr/windows/conversion.c
new file mode 100644
index 00000000000..8d29c1eeba7
--- /dev/null
+++ b/reactos/boot/freeldr/freeldr/windows/conversion.c
@@ -0,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@reactos.org)
+ */
+
+/* INCLUDES ***************************************************************/
+
+#include
+
+//#include
+
+#define NDEBUG
+#include
+
+/* 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);
+ }
+}
diff --git a/reactos/boot/freeldr/freeldr/windows/peloader.c b/reactos/boot/freeldr/freeldr/windows/peloader.c
new file mode 100644
index 00000000000..c8f58f32141
--- /dev/null
+++ b/reactos/boot/freeldr/freeldr/windows/peloader.c
@@ -0,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@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
+
+#define NDEBUG
+#include
+
+/* 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 *******************************************************/
diff --git a/reactos/boot/freeldr/freeldr/windows/winldr.c b/reactos/boot/freeldr/freeldr/windows/winldr.c
index 6f20403b21f..45c86f4ee8c 100644
--- a/reactos/boot/freeldr/freeldr/windows/winldr.c
+++ b/reactos/boot/freeldr/freeldr/windows/winldr.c
@@ -24,13 +24,178 @@
#define NDEBUG
#include
+VOID DumpMemoryAllocMap(VOID);
+VOID WinLdrpDumpMemoryDescriptors(PLOADER_PARAMETER_BLOCK LoaderBlock);
+
VOID
LoadAndBootWindows(PCSTR OperatingSystemName, WORD OperatingSystemVersion)
{
CHAR MsgBuffer[256];
+ 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);
+ //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;
+ }
+}
diff --git a/reactos/boot/freeldr/freeldr/windows/wlmemory.c b/reactos/boot/freeldr/freeldr/windows/wlmemory.c
new file mode 100644
index 00000000000..a9393a6e98f
--- /dev/null
+++ b/reactos/boot/freeldr/freeldr/windows/wlmemory.c
@@ -0,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@reactos.org)
+ */
+
+/* INCLUDES ***************************************************************/
+
+#include
+
+#include
+
+#define NDEBUG
+#include
+
+// 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;
+}