2009-03-12 14:42:02 +00:00
|
|
|
/*
|
|
|
|
* FreeLoader
|
|
|
|
*
|
|
|
|
* Copyright (C) 2009 Aleksey Bragin <aleksey@reactos.org>
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <freeldr.h>
|
|
|
|
|
|
|
|
#include <ndk/ldrtypes.h>
|
2009-03-21 11:11:44 +00:00
|
|
|
#include <arc/setupblk.h>
|
|
|
|
|
2009-03-12 14:42:02 +00:00
|
|
|
#include <debug.h>
|
|
|
|
|
2009-03-15 10:46:41 +00:00
|
|
|
// TODO: Move to .h
|
|
|
|
VOID AllocateAndInitLPB(PLOADER_PARAMETER_BLOCK *OutLoaderBlock);
|
|
|
|
BOOLEAN WinLdrLoadBootDrivers(PLOADER_PARAMETER_BLOCK LoaderBlock, LPSTR BootPath);
|
|
|
|
void WinLdrSetupForNt(PLOADER_PARAMETER_BLOCK LoaderBlock,
|
|
|
|
PVOID *GdtIdt,
|
|
|
|
ULONG *PcrBasePage,
|
|
|
|
ULONG *TssBasePage);
|
|
|
|
VOID
|
|
|
|
WinLdrInitializePhase1(PLOADER_PARAMETER_BLOCK LoaderBlock,
|
|
|
|
PCHAR Options,
|
|
|
|
PCHAR SystemPath,
|
|
|
|
PCHAR BootPath,
|
|
|
|
USHORT VersionToBoot);
|
2009-03-15 11:10:52 +00:00
|
|
|
BOOLEAN
|
|
|
|
WinLdrLoadNLSData(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
|
|
|
|
IN LPCSTR DirectoryPath,
|
|
|
|
IN LPCSTR AnsiFileName,
|
|
|
|
IN LPCSTR OemFileName,
|
|
|
|
IN LPCSTR LanguageFileName);
|
2009-03-16 20:56:07 +00:00
|
|
|
BOOLEAN
|
|
|
|
WinLdrAddDriverToList(LIST_ENTRY *BootDriverListHead,
|
|
|
|
LPWSTR RegistryPath,
|
|
|
|
LPWSTR ImagePath,
|
|
|
|
LPWSTR ServiceName);
|
2009-03-15 10:46:41 +00:00
|
|
|
|
|
|
|
|
|
|
|
//FIXME: Do a better way to retrieve Arc disk information
|
|
|
|
extern ULONG reactos_disk_count;
|
|
|
|
extern ARC_DISK_SIGNATURE reactos_arc_disk_info[];
|
|
|
|
extern char reactos_arc_strings[32][256];
|
|
|
|
|
|
|
|
extern BOOLEAN UseRealHeap;
|
|
|
|
extern ULONG LoaderPagesSpanned;
|
|
|
|
|
2009-03-15 11:10:52 +00:00
|
|
|
|
|
|
|
VOID
|
|
|
|
SetupLdrLoadNlsData(PLOADER_PARAMETER_BLOCK LoaderBlock, HINF InfHandle, LPCSTR SearchPath)
|
|
|
|
{
|
|
|
|
INFCONTEXT InfContext;
|
|
|
|
BOOLEAN Status;
|
|
|
|
LPCSTR AnsiName, OemName, LangName;
|
|
|
|
|
|
|
|
/* Get ANSI codepage file */
|
|
|
|
if (!InfFindFirstLine(InfHandle, "NLS", "AnsiCodepage", &InfContext))
|
|
|
|
{
|
|
|
|
printf("Failed to find 'NLS/AnsiCodepage'\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (!InfGetDataField(&InfContext, 1, &AnsiName))
|
|
|
|
{
|
|
|
|
printf("Failed to get load options\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Get OEM codepage file */
|
|
|
|
if (!InfFindFirstLine(InfHandle, "NLS", "OemCodepage", &InfContext))
|
|
|
|
{
|
|
|
|
printf("Failed to find 'NLS/AnsiCodepage'\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (!InfGetDataField(&InfContext, 1, &OemName))
|
|
|
|
{
|
|
|
|
printf("Failed to get load options\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!InfFindFirstLine(InfHandle, "NLS", "UnicodeCasetable", &InfContext))
|
|
|
|
{
|
|
|
|
printf("Failed to find 'NLS/AnsiCodepage'\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (!InfGetDataField(&InfContext, 1, &LangName))
|
|
|
|
{
|
|
|
|
printf("Failed to get load options\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
Status = WinLdrLoadNLSData(LoaderBlock, SearchPath, AnsiName, OemName, LangName);
|
|
|
|
DPRINTM(DPRINT_WINDOWS, "NLS data loaded with status %d\n", Status);
|
|
|
|
}
|
|
|
|
|
2009-03-16 20:56:07 +00:00
|
|
|
VOID
|
|
|
|
SetupLdrScanBootDrivers(PLOADER_PARAMETER_BLOCK LoaderBlock, HINF InfHandle, LPCSTR SearchPath)
|
|
|
|
{
|
|
|
|
INFCONTEXT InfContext;
|
|
|
|
BOOLEAN Status;
|
|
|
|
LPCSTR Media, DriverName;
|
|
|
|
WCHAR ServiceName[256];
|
|
|
|
WCHAR ImagePath[256];
|
|
|
|
|
|
|
|
/* Open inf section */
|
|
|
|
if (!InfFindFirstLine(InfHandle, "SourceDisksFiles", NULL, &InfContext))
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* Load all listed boot drivers */
|
|
|
|
do
|
|
|
|
{
|
|
|
|
if (InfGetDataField(&InfContext, 7, &Media) &&
|
|
|
|
InfGetDataField(&InfContext, 0, &DriverName))
|
|
|
|
{
|
|
|
|
if (strcmp(Media, "x") == 0)
|
|
|
|
{
|
|
|
|
/* Convert name to widechar */
|
|
|
|
swprintf(ServiceName, L"%S", DriverName);
|
|
|
|
|
|
|
|
/* Remove .sys extension */
|
|
|
|
ServiceName[wcslen(ServiceName) - 4] = 0;
|
|
|
|
|
|
|
|
/* Prepare image path */
|
|
|
|
swprintf(ImagePath, L"%S", DriverName);
|
|
|
|
|
|
|
|
/* Add it to the list */
|
|
|
|
Status = WinLdrAddDriverToList(&LoaderBlock->BootDriverListHead,
|
|
|
|
L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\",
|
|
|
|
ImagePath,
|
|
|
|
ServiceName);
|
|
|
|
|
|
|
|
if (!Status)
|
|
|
|
{
|
|
|
|
DPRINTM(DPRINT_WINDOWS, "could not add boot driver %s, %s\n", SearchPath, DriverName);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} while (InfFindNextLine(&InfContext, &InfContext));
|
|
|
|
}
|
|
|
|
|
2009-03-12 14:42:02 +00:00
|
|
|
VOID LoadReactOSSetup2(VOID)
|
|
|
|
{
|
2009-03-15 10:46:41 +00:00
|
|
|
CHAR SystemPath[512], SearchPath[512];
|
|
|
|
CHAR FileName[512];
|
|
|
|
CHAR BootPath[512];
|
2009-09-25 13:03:42 +00:00
|
|
|
LPCSTR LoadOptions, BootOptions;
|
|
|
|
#if DBG
|
|
|
|
LPCSTR DbgOptions;
|
|
|
|
#endif
|
2009-03-15 10:46:41 +00:00
|
|
|
PVOID NtosBase = NULL, HalBase = NULL, KdComBase = NULL;
|
|
|
|
BOOLEAN Status;
|
|
|
|
ULONG i, ErrorLine;
|
|
|
|
HINF InfHandle;
|
|
|
|
INFCONTEXT InfContext;
|
|
|
|
PLOADER_PARAMETER_BLOCK LoaderBlock, LoaderBlockVA;
|
2009-03-21 11:11:44 +00:00
|
|
|
PSETUP_LOADER_BLOCK SetupBlock;
|
2009-03-15 10:46:41 +00:00
|
|
|
KERNEL_ENTRY_POINT KiSystemStartup;
|
|
|
|
PLDR_DATA_TABLE_ENTRY KernelDTE, HalDTE, KdComDTE = NULL;
|
|
|
|
// Mm-related things
|
|
|
|
PVOID GdtIdt;
|
|
|
|
ULONG PcrBasePage=0;
|
|
|
|
ULONG TssBasePage=0;
|
|
|
|
LPCSTR SourcePath;
|
|
|
|
LPCSTR SourcePaths[] =
|
|
|
|
{
|
|
|
|
"", /* Only for floppy boot */
|
|
|
|
#if defined(_M_IX86)
|
|
|
|
"\\I386",
|
|
|
|
#elif defined(_M_MPPC)
|
|
|
|
"\\PPC",
|
|
|
|
#elif defined(_M_MRX000)
|
|
|
|
"\\MIPS",
|
|
|
|
#endif
|
|
|
|
"\\reactos",
|
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
|
|
|
/* Open 'txtsetup.sif' from any of source paths */
|
2009-04-20 20:04:23 +00:00
|
|
|
MachDiskGetBootPath(SystemPath, sizeof(SystemPath));
|
2009-03-15 10:46:41 +00:00
|
|
|
for (i = MachDiskBootingFromFloppy() ? 0 : 1; ; i++)
|
|
|
|
{
|
|
|
|
SourcePath = SourcePaths[i];
|
|
|
|
if (!SourcePath)
|
|
|
|
{
|
|
|
|
printf("Failed to open 'txtsetup.sif'\n");
|
|
|
|
return;
|
|
|
|
}
|
2009-04-20 20:04:23 +00:00
|
|
|
sprintf(FileName, "%s\\txtsetup.sif", SourcePath);
|
2009-03-15 10:46:41 +00:00
|
|
|
if (InfOpenFile (&InfHandle, FileName, &ErrorLine))
|
2009-04-20 20:04:23 +00:00
|
|
|
{
|
|
|
|
sprintf(BootPath, "%s%s\\", SystemPath, SourcePath);
|
2009-03-15 10:46:41 +00:00
|
|
|
break;
|
2009-04-20 20:04:23 +00:00
|
|
|
}
|
2009-03-15 10:46:41 +00:00
|
|
|
}
|
|
|
|
|
2009-09-25 09:28:37 +00:00
|
|
|
/* Get Load options - debug and non-debug */
|
2009-03-15 10:46:41 +00:00
|
|
|
if (!InfFindFirstLine(InfHandle,
|
|
|
|
"SetupData",
|
|
|
|
"OsLoadOptions",
|
|
|
|
&InfContext))
|
|
|
|
{
|
|
|
|
printf("Failed to find 'SetupData/OsLoadOptions'\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-09-25 09:28:37 +00:00
|
|
|
if (!InfGetDataField (&InfContext, 1, &LoadOptions))
|
2009-03-15 10:46:41 +00:00
|
|
|
{
|
|
|
|
printf("Failed to get load options\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-09-25 09:28:37 +00:00
|
|
|
BootOptions = LoadOptions;
|
|
|
|
|
|
|
|
#if DBG
|
|
|
|
/* Get debug load options and use them */
|
|
|
|
if (InfFindFirstLine(InfHandle,
|
|
|
|
"SetupData",
|
|
|
|
"DbgOsLoadOptions",
|
|
|
|
&InfContext))
|
|
|
|
{
|
|
|
|
if (!InfGetDataField(&InfContext, 1, &DbgOptions))
|
|
|
|
DbgOptions = "";
|
|
|
|
else
|
|
|
|
BootOptions = DbgOptions;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
DPRINTM(DPRINT_WINDOWS,"BootOptions: '%s'\n", BootOptions);
|
|
|
|
|
2009-03-15 10:46:41 +00:00
|
|
|
SetupUiInitialize();
|
|
|
|
UiDrawStatusText("");
|
|
|
|
UiDrawStatusText("Detecting Hardware...");
|
|
|
|
|
|
|
|
/* Let user know we started loading */
|
|
|
|
UiDrawStatusText("Loading...");
|
|
|
|
|
|
|
|
/* Construct the system path */
|
2009-04-20 20:04:23 +00:00
|
|
|
sprintf(SystemPath, "%s\\", SourcePath);
|
2009-03-15 10:46:41 +00:00
|
|
|
|
2009-04-24 18:27:34 +00:00
|
|
|
DPRINTM(DPRINT_WINDOWS,"BootPath: '%s', SystemPath: '%s'\n", BootPath, SystemPath);
|
2009-03-15 10:46:41 +00:00
|
|
|
|
|
|
|
/* Allocate and minimalistic-initialize LPB */
|
|
|
|
AllocateAndInitLPB(&LoaderBlock);
|
2009-03-12 14:42:02 +00:00
|
|
|
|
2009-03-21 11:11:44 +00:00
|
|
|
/* Allocate and initialize setup loader block */
|
|
|
|
SetupBlock = MmHeapAlloc(sizeof(SETUP_LOADER_BLOCK));
|
|
|
|
RtlZeroMemory(SetupBlock, sizeof(SETUP_LOADER_BLOCK));
|
|
|
|
LoaderBlock->SetupLdrBlock = SetupBlock;
|
|
|
|
|
|
|
|
/* Set textmode setup flag */
|
|
|
|
SetupBlock->Flags = SETUPLDR_TEXT_MODE;
|
|
|
|
|
2009-03-15 10:46:41 +00:00
|
|
|
/* Detect hardware */
|
|
|
|
UseRealHeap = TRUE;
|
|
|
|
LoaderBlock->ConfigurationRoot = MachHwDetect();
|
|
|
|
|
|
|
|
/* Load kernel */
|
|
|
|
strcpy(FileName, BootPath);
|
|
|
|
strcat(FileName, "NTOSKRNL.EXE");
|
|
|
|
Status = WinLdrLoadImage(FileName, LoaderSystemCode, &NtosBase);
|
|
|
|
DPRINTM(DPRINT_WINDOWS, "Ntos loaded with status %d at %p\n", Status, NtosBase);
|
|
|
|
|
|
|
|
/* Load HAL */
|
|
|
|
strcpy(FileName, BootPath);
|
|
|
|
strcat(FileName, "HAL.DLL");
|
|
|
|
Status = WinLdrLoadImage(FileName, LoaderHalCode, &HalBase);
|
|
|
|
DPRINTM(DPRINT_WINDOWS, "HAL loaded with status %d at %p\n", Status, HalBase);
|
|
|
|
|
|
|
|
/* Load kernel-debugger support dll */
|
|
|
|
strcpy(FileName, BootPath);
|
|
|
|
strcat(FileName, "KDCOM.DLL");
|
|
|
|
Status = WinLdrLoadImage(FileName, LoaderBootDriver, &KdComBase);
|
|
|
|
DPRINTM(DPRINT_WINDOWS, "KdCom loaded with status %d at %p\n", Status, KdComBase);
|
|
|
|
|
|
|
|
/* Allocate data table entries for above-loaded modules */
|
|
|
|
WinLdrAllocateDataTableEntry(LoaderBlock, "ntoskrnl.exe",
|
|
|
|
"NTOSKRNL.EXE", NtosBase, &KernelDTE);
|
|
|
|
WinLdrAllocateDataTableEntry(LoaderBlock, "hal.dll",
|
|
|
|
"HAL.DLL", HalBase, &HalDTE);
|
|
|
|
WinLdrAllocateDataTableEntry(LoaderBlock, "kdcom.dll",
|
|
|
|
"KDCOM.DLL", KdComBase, &KdComDTE);
|
|
|
|
|
|
|
|
/* Load all referenced DLLs for kernel, HAL and kdcom.dll */
|
|
|
|
strcpy(SearchPath, BootPath);
|
|
|
|
WinLdrScanImportDescriptorTable(LoaderBlock, SearchPath, KernelDTE);
|
|
|
|
WinLdrScanImportDescriptorTable(LoaderBlock, SearchPath, HalDTE);
|
|
|
|
if (KdComDTE)
|
|
|
|
WinLdrScanImportDescriptorTable(LoaderBlock, SearchPath, KdComDTE);
|
|
|
|
|
2009-03-15 11:10:52 +00:00
|
|
|
/* Load NLS data */
|
|
|
|
SetupLdrLoadNlsData(LoaderBlock, InfHandle, BootPath);
|
2009-03-15 10:46:41 +00:00
|
|
|
|
2009-03-16 20:56:07 +00:00
|
|
|
/* Get a list of boot drivers */
|
|
|
|
SetupLdrScanBootDrivers(LoaderBlock, InfHandle, BootPath);
|
|
|
|
|
2009-03-15 10:46:41 +00:00
|
|
|
/* Load boot drivers */
|
2009-03-16 20:56:07 +00:00
|
|
|
Status = WinLdrLoadBootDrivers(LoaderBlock, BootPath);
|
2009-03-15 10:46:41 +00:00
|
|
|
DPRINTM(DPRINT_WINDOWS, "Boot drivers loaded with status %d\n", Status);
|
|
|
|
|
|
|
|
/* Alloc PCR, TSS, do magic things with the GDT/IDT */
|
|
|
|
WinLdrSetupForNt(LoaderBlock, &GdtIdt, &PcrBasePage, &TssBasePage);
|
|
|
|
|
|
|
|
/* Initialize Phase 1 - no drivers loading anymore */
|
2009-04-24 18:27:34 +00:00
|
|
|
WinLdrInitializePhase1(LoaderBlock, (PCHAR)BootOptions, SystemPath, BootPath, _WIN32_WINNT_WS03);
|
2009-03-15 10:46:41 +00:00
|
|
|
|
|
|
|
/* Save entry-point pointer and Loader block VAs */
|
|
|
|
KiSystemStartup = (KERNEL_ENTRY_POINT)KernelDTE->EntryPoint;
|
|
|
|
LoaderBlockVA = PaToVa(LoaderBlock);
|
|
|
|
|
|
|
|
/* "Stop all motors", change videomode */
|
2009-04-14 10:36:16 +00:00
|
|
|
MachPrepareForReactOS(TRUE);
|
2009-03-15 10:46:41 +00:00
|
|
|
|
|
|
|
/* Debugging... */
|
|
|
|
//DumpMemoryAllocMap();
|
|
|
|
|
|
|
|
/* Turn on paging mode of CPU*/
|
|
|
|
WinLdrTurnOnPaging(LoaderBlock, PcrBasePage, TssBasePage, GdtIdt);
|
|
|
|
|
|
|
|
/* Save final value of LoaderPagesSpanned */
|
|
|
|
LoaderBlock->Extension->LoaderPagesSpanned = LoaderPagesSpanned;
|
|
|
|
|
|
|
|
DPRINTM(DPRINT_WINDOWS, "Hello from paged mode, KiSystemStartup %p, LoaderBlockVA %p!\n",
|
|
|
|
KiSystemStartup, LoaderBlockVA);
|
|
|
|
|
|
|
|
//WinLdrpDumpMemoryDescriptors(LoaderBlockVA);
|
|
|
|
//WinLdrpDumpBootDriver(LoaderBlockVA);
|
|
|
|
//WinLdrpDumpArcDisks(LoaderBlockVA);
|
|
|
|
|
2009-03-21 11:11:44 +00:00
|
|
|
/*asm(".intel_syntax noprefix\n");
|
|
|
|
asm("test1:\n");
|
|
|
|
asm("jmp test1\n");
|
|
|
|
asm(".att_syntax\n");*/
|
|
|
|
|
2009-03-15 10:46:41 +00:00
|
|
|
/* Pass control */
|
|
|
|
(*KiSystemStartup)(LoaderBlockVA);
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|