[freeldr] Rework the ramdisk driver to let it be a full device, instead of a deprecat...
[reactos.git] / reactos / boot / freeldr / freeldr / windows / winldr.c
index c8c6f50..76622ee 100644 (file)
 #include <ndk/ldrtypes.h>
 #include <debug.h>
 
+// TODO: Move to .h
+void WinLdrSetupForNt(PLOADER_PARAMETER_BLOCK LoaderBlock,
+                      PVOID *GdtIdt,
+                      ULONG *PcrBasePage,
+                      ULONG *TssBasePage);
+
 //FIXME: Do a better way to retrieve Arc disk information
 extern ULONG reactos_disk_count;
 extern ARC_DISK_SIGNATURE reactos_arc_disk_info[];
@@ -75,7 +81,7 @@ AllocateAndInitLPB(PLOADER_PARAMETER_BLOCK *OutLoaderBlock)
 VOID
 WinLdrInitializePhase1(PLOADER_PARAMETER_BLOCK LoaderBlock,
                        PCHAR Options,
-                       PCHAR SystemPath,
+                       PCHAR SystemRoot,
                        PCHAR BootPath,
                        USHORT VersionToBoot)
 {
@@ -86,20 +92,15 @@ WinLdrInitializePhase1(PLOADER_PARAMETER_BLOCK LoaderBlock,
        //CHAR  ArcBoot[] = "multi(0)disk(0)rdisk(0)partition(1)";
 
        CHAR    HalPath[] = "\\";
-       CHAR    SystemRoot[256];
        CHAR    ArcBoot[256];
        CHAR    MiscFiles[256];
        ULONG i, PathSeparator;
        PLOADER_PARAMETER_EXTENSION Extension;
 
-       LoaderBlock->u.I386.CommonDataArea = NULL; // Force No ABIOS support
-
        /* Construct SystemRoot and ArcBoot from SystemPath */
-       PathSeparator = strstr(SystemPath, "\\") - SystemPath;
-       strncpy(ArcBoot, SystemPath, PathSeparator);
+       PathSeparator = strstr(BootPath, "\\") - BootPath;
+       strncpy(ArcBoot, BootPath, PathSeparator);
        ArcBoot[PathSeparator] = 0;
-       strcpy(SystemRoot, &SystemPath[PathSeparator]);
-       strcat(SystemRoot, "\\");
 
        DPRINTM(DPRINT_WINDOWS, "ArcBoot: %s\n", ArcBoot);
        DPRINTM(DPRINT_WINDOWS, "SystemRoot: %s\n", SystemRoot);
@@ -208,54 +209,6 @@ WinLdrInitializePhase1(PLOADER_PARAMETER_BLOCK LoaderBlock,
                LoaderBlock->SetupLdrBlock = PaToVa(LoaderBlock->SetupLdrBlock);
 }
 
-// Last step before going virtual
-void WinLdrSetupForNt(PLOADER_PARAMETER_BLOCK LoaderBlock,
-                      PVOID *GdtIdt,
-                      ULONG *PcrBasePage,
-                      ULONG *TssBasePage)
-{
-       ULONG TssSize;
-       ULONG TssPages;
-       ULONG_PTR Pcr = 0;
-       ULONG_PTR Tss = 0;
-       ULONG BlockSize, NumPages;
-
-       LoaderBlock->u.I386.CommonDataArea = NULL; //CommonDataArea;
-       LoaderBlock->u.I386.MachineType = 0; // ntldr sets this to 0
-
-       /* Allocate 2 pages for PCR */
-       Pcr = (ULONG_PTR)MmAllocateMemoryWithType(2 * MM_PAGE_SIZE, LoaderStartupPcrPage);
-       *PcrBasePage = Pcr >> MM_PAGE_SHIFT;
-
-       if (Pcr == 0)
-       {
-               UiMessageBox("Can't allocate PCR\n");
-               return;
-       }
-
-       /* Allocate TSS */
-       TssSize = (sizeof(KTSS) + MM_PAGE_SIZE) & ~(MM_PAGE_SIZE - 1);
-       TssPages = TssSize / MM_PAGE_SIZE;
-
-       Tss = (ULONG_PTR)MmAllocateMemoryWithType(TssSize, LoaderMemoryData);
-
-       *TssBasePage = Tss >> MM_PAGE_SHIFT;
-
-       /* Allocate space for new GDT + IDT */
-       BlockSize = NUM_GDT*sizeof(KGDTENTRY) + NUM_IDT*sizeof(KIDTENTRY);//FIXME: Use GDT/IDT limits here?
-       NumPages = (BlockSize + MM_PAGE_SIZE - 1) >> MM_PAGE_SHIFT;
-       *GdtIdt = (PKGDTENTRY)MmAllocateMemoryWithType(NumPages * MM_PAGE_SIZE, LoaderMemoryData);
-
-       if (*GdtIdt == NULL)
-       {
-               UiMessageBox("Can't allocate pages for GDT+IDT!\n");
-               return;
-       }
-
-       /* Zero newly prepared GDT+IDT */
-       RtlZeroMemory(*GdtIdt, NumPages << MM_PAGE_SHIFT);
-}
-
 BOOLEAN
 WinLdrLoadDeviceDriver(PLOADER_PARAMETER_BLOCK LoaderBlock,
                        LPSTR BootPath,
@@ -374,10 +327,12 @@ WinLdrLoadBootDrivers(PLOADER_PARAMETER_BLOCK LoaderBlock,
 PVOID WinLdrLoadModule(PCSTR ModuleName, ULONG *Size,
                                           TYPE_OF_MEMORY MemoryType)
 {
-       PFILE FileHandle;
+       ULONG FileId;
        PVOID PhysicalBase;
+       FILEINFORMATION FileInfo;
        ULONG FileSize;
-       BOOLEAN Status;
+       ULONG Status;
+       ULONG BytesRead;
 
        //CHAR ProgressString[256];
 
@@ -389,39 +344,41 @@ PVOID WinLdrLoadModule(PCSTR ModuleName, ULONG *Size,
        *Size = 0;
 
        /* Open the image file */
-       FileHandle = FsOpenFile(ModuleName);
-
-       if (FileHandle == NULL)
+       Status = ArcOpen((PCHAR)ModuleName, OpenReadOnly, &FileId);
+       if (Status != ESUCCESS)
        {
                /* In case of errors, we just return, without complaining to the user */
                return NULL;
        }
 
        /* Get this file's size */
-       FileSize = FsGetFileSize(FileHandle);
+       Status = ArcGetFileInformation(FileId, &FileInfo);
+       if (Status != ESUCCESS)
+       {
+               ArcClose(FileId);
+               return NULL;
+       }
+       FileSize = FileInfo.EndingAddress.LowPart;
        *Size = FileSize;
 
        /* Allocate memory */
        PhysicalBase = MmAllocateMemoryWithType(FileSize, MemoryType);
        if (PhysicalBase == NULL)
        {
-               FsCloseFile(FileHandle);
+               ArcClose(FileId);
                return NULL;
        }
 
        /* Load whole file */
-       Status = FsReadFile(FileHandle, FileSize, NULL, PhysicalBase);
-       if (!Status)
+       Status = ArcRead(FileId, PhysicalBase, FileSize, &BytesRead);
+       ArcClose(FileId);
+       if (Status != ESUCCESS)
        {
-               FsCloseFile(FileHandle);
                return NULL;
        }
 
        DPRINTM(DPRINT_WINDOWS, "Loaded %s at 0x%x with size 0x%x\n", ModuleName, PhysicalBase, FileSize);
 
-       /* We are done with the file - close it */
-       FsCloseFile(FileHandle);
-
        return PhysicalBase;
 }
 
@@ -430,14 +387,14 @@ VOID
 LoadAndBootWindows(PCSTR OperatingSystemName, USHORT OperatingSystemVersion)
 {
        CHAR  MsgBuffer[256];
-       CHAR  SystemPath[512], SearchPath[512];
-       CHAR  FileName[512];
-       CHAR  BootPath[512];
+       CHAR  FullPath[MAX_PATH], SystemRoot[MAX_PATH], BootPath[MAX_PATH];
+       CHAR  FileName[MAX_PATH];
        CHAR  BootOptions[256];
+       PCHAR File;
+       PCHAR PathSeparator;
        PVOID NtosBase = NULL, HalBase = NULL, KdComBase = NULL;
        BOOLEAN Status;
-       ULONG_PTR SectionId;
-       ULONG BootDevice;
+       ULONG SectionId;
        PLOADER_PARAMETER_BLOCK LoaderBlock, LoaderBlockVA;
        KERNEL_ENTRY_POINT KiSystemStartup;
        PLDR_DATA_TABLE_ENTRY KernelDTE, HalDTE, KdComDTE = NULL;
@@ -463,12 +420,25 @@ LoadAndBootWindows(PCSTR OperatingSystemName, USHORT OperatingSystemVersion)
        UiDrawProgressBarCenter(1, 100, "Loading Windows...");
 
        /* Make sure the system path is set in the .ini file */
-       if (!IniReadSettingByName(SectionId, "SystemPath", SystemPath, sizeof(SystemPath)))
+       if (!IniReadSettingByName(SectionId, "SystemPath", FullPath, sizeof(FullPath)))
        {
                UiMessageBox("System path not specified for selected operating system.");
                return;
        }
 
+       /* Special case for LiveCD */
+       if (!_strnicmp(FullPath, "LiveCD", strlen("LiveCD")))
+       {
+               strcpy(BootPath, FullPath + strlen("LiveCD"));
+               MachDiskGetBootPath(FullPath, sizeof(FullPath));
+               strcat(FullPath, BootPath);
+       }
+
+       /* Convert FullPath to SystemRoot */
+       PathSeparator = strstr(FullPath, "\\");
+       strcpy(SystemRoot, PathSeparator);
+       strcat(SystemRoot, "\\");
+
        /* Read booting options */
        if (!IniReadSettingByName(SectionId, "Options", BootOptions, sizeof(BootOptions)))
        {
@@ -476,30 +446,38 @@ LoadAndBootWindows(PCSTR OperatingSystemName, USHORT OperatingSystemVersion)
                strcpy(BootOptions, "");
        }
 
-       /* Normalize system path */
-       if (!MachDiskNormalizeSystemPath(SystemPath, sizeof(SystemPath)))
+       //
+       // Check if a ramdisk file was given
+       //
+       File = strstr(BootOptions, "/RDPATH=");
+       if (File)
        {
-               UiMessageBox("Invalid system path");
-               return;
+               //
+               // Copy the file name and everything else after it
+               //
+               strcpy(FileName, File + 8);
+
+               //
+               // Null-terminate
+               //
+               *strstr(FileName, " ") = ANSI_NULL;
+
+               //
+               // Load the ramdisk
+               //
+               RamDiskLoadVirtualFile(FileName);
        }
 
        /* Let user know we started loading */
        UiDrawStatusText("Loading...");
 
-       /* Try to open system drive */
-       BootDevice = 0xffffffff;
-       if (!FsOpenSystemVolume(SystemPath, BootPath, &BootDevice))
-       {
-               UiMessageBox("Failed to open boot drive.");
-               return;
-       }
-
        /* append a backslash */
+       strcpy(BootPath, FullPath);
        if ((strlen(BootPath)==0) ||
            BootPath[strlen(BootPath)] != '\\')
                strcat(BootPath, "\\");
 
-       DPRINTM(DPRINT_WINDOWS,"SystemRoot: '%s'\n", BootPath);
+       DPRINTM(DPRINT_WINDOWS,"BootPath: '%s'\n", BootPath);
 
        /* Allocate and minimalistic-initialize LPB */
        AllocateAndInitLPB(&LoaderBlock);
@@ -541,12 +519,12 @@ LoadAndBootWindows(PCSTR OperatingSystemName, USHORT OperatingSystemVersion)
        }
 
        /* Load all referenced DLLs for kernel, HAL and kdcom.dll */
-       strcpy(SearchPath, BootPath);
-       strcat(SearchPath, "SYSTEM32\\");
-       WinLdrScanImportDescriptorTable(LoaderBlock, SearchPath, KernelDTE);
-       WinLdrScanImportDescriptorTable(LoaderBlock, SearchPath, HalDTE);
+       strcpy(FileName, BootPath);
+       strcat(FileName, "SYSTEM32\\");
+       WinLdrScanImportDescriptorTable(LoaderBlock, FileName, KernelDTE);
+       WinLdrScanImportDescriptorTable(LoaderBlock, FileName, HalDTE);
        if (KdComDTE)
-               WinLdrScanImportDescriptorTable(LoaderBlock, SearchPath, KdComDTE);
+               WinLdrScanImportDescriptorTable(LoaderBlock, FileName, KdComDTE);
 
        /* Load Hive, and then NLS data, OEM font, and prepare boot drivers list */
        Status = WinLdrLoadAndScanSystemHive(LoaderBlock, BootPath);
@@ -560,7 +538,7 @@ LoadAndBootWindows(PCSTR OperatingSystemName, USHORT OperatingSystemVersion)
        WinLdrSetupForNt(LoaderBlock, &GdtIdt, &PcrBasePage, &TssBasePage);
 
        /* Initialize Phase 1 - no drivers loading anymore */
-       WinLdrInitializePhase1(LoaderBlock, BootOptions, SystemPath, BootPath, OperatingSystemVersion);
+       WinLdrInitializePhase1(LoaderBlock, BootOptions, SystemRoot, BootPath, OperatingSystemVersion);
 
        /* Save entry-point pointer and Loader block VAs */
        KiSystemStartup = (KERNEL_ENTRY_POINT)KernelDTE->EntryPoint;