- 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).

svn path=/trunk/; revision=24350
This commit is contained in:
Aleksey Bragin 2006-10-01 19:39:49 +00:00
parent 71e329a125
commit 3d9d36ccff
8 changed files with 441 additions and 3 deletions

View 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');

View 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>
@ -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>

View 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, ...);

View file

@ -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

View file

@ -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 <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);
}
}

View file

@ -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 <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 *******************************************************/

View file

@ -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];
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;
}
}

View file

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