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; +}