[freeldr] Rework the ramdisk driver to let it be a full device, instead of a deprecat...
authorHervé Poussineau <hpoussin@reactos.org>
Sun, 11 Oct 2009 17:08:33 +0000 (17:08 +0000)
committerHervé Poussineau <hpoussin@reactos.org>
Sun, 11 Oct 2009 17:08:33 +0000 (17:08 +0000)
Add support for /RDPATH switch in WINLDR boot style

svn path=/trunk/; revision=43377

reactos/boot/freeldr/freeldr/arch/arm/macharm.c
reactos/boot/freeldr/freeldr/disk/ramdisk.c
reactos/boot/freeldr/freeldr/include/ramdisk.h
reactos/boot/freeldr/freeldr/reactos/reactos.c
reactos/boot/freeldr/freeldr/windows/winldr.c

index 2dc74fe..c636a0a 100644 (file)
@@ -71,7 +71,6 @@ BOOLEAN
 ArmDiskGetDriveGeometry(IN ULONG DriveNumber,
                         OUT PGEOMETRY Geometry)
 {
-    ASSERT(gRamDiskBase == NULL);
     return FALSE;
 }
 
@@ -81,15 +80,13 @@ ArmDiskReadLogicalSectors(IN ULONG DriveNumber,
                           IN ULONG SectorCount,
                           IN PVOID Buffer)
 {
-    ASSERT(gRamDiskBase == NULL);
     return FALSE;
 }
 
 ULONG
 ArmDiskGetCacheableBlockCount(IN ULONG DriveNumber)
 {
-    ASSERT(gRamDiskBase == NULL);
-    return FALSE;
+    return 0;
 }
 
 PCONFIGURATION_COMPONENT_DATA
@@ -191,12 +188,11 @@ MachInit(IN PCCH CommandLine)
     MachVtbl.HwDetect = ArmHwDetect;
     
     //
-    // Setup disk I/O routines, switch to ramdisk ones for non-NAND boot
+    // Setup disk I/O routines
     //
     MachVtbl.DiskReadLogicalSectors = ArmDiskReadLogicalSectors;
     MachVtbl.DiskGetDriveGeometry = ArmDiskGetDriveGeometry;
     MachVtbl.DiskGetCacheableBlockCount = ArmDiskGetCacheableBlockCount;
-    RamDiskSwitchFromBios();
     
     //
     // Now set default disk handling routines -- we don't need to override
index a5de38a..18397d6 100644 (file)
@@ -1,9 +1,10 @@
 /*
  * PROJECT:         ReactOS Boot Loader
  * LICENSE:         BSD - See COPYING.ARM in the top level directory
- * FILE:            boot/freeldr/arch/i386/ramdisk.c
+ * FILE:            boot/freeldr/freeldr/disk/ramdisk.c
  * PURPOSE:         Implements routines to support booting from a RAM Disk
  * PROGRAMMERS:     ReactOS Portable Systems Group
+ *                  Hervé Poussineau
  */
 
 /* INCLUDES *******************************************************************/
 
 PVOID gRamDiskBase;
 ULONG gRamDiskSize;
+ULONG gRamDiskOffset;
 
 /* FUNCTIONS ******************************************************************/
 
-FORCEINLINE
-PVOID
-RamDiskGetDataAtOffset(IN PVOID Offset)
+static LONG RamDiskClose(ULONG FileId)
 {
     //
-    // Return data from our RAM Disk
+    // Nothing to do
     //
-    ASSERT(((ULONG_PTR)gRamDiskBase + (ULONG_PTR)Offset) <
-           ((ULONG_PTR)gRamDiskBase + (ULONG_PTR)gRamDiskSize));
-    return (PVOID)((ULONG_PTR)gRamDiskBase + (ULONG_PTR)(Offset));
+    return ESUCCESS;
 }
 
-ULONG
-RamDiskGetCacheableBlockCount(IN ULONG Reserved)
+static LONG RamDiskGetFileInformation(ULONG FileId, FILEINFORMATION* Information)
 {
     //
-    // Allow 32KB transfers (64 sectors), emulating BIOS LBA
+    // Give current seek offset and ram disk size to caller
     //
-    ASSERT(Reserved == 0x49);
-    return 64;
+    RtlZeroMemory(Information, sizeof(FILEINFORMATION));
+    Information->EndingAddress.LowPart = gRamDiskSize;
+    Information->CurrentAddress.LowPart = gRamDiskOffset;
+
+    return ESUCCESS;
 }
 
-BOOLEAN
-RamDiskGetDriveGeometry(IN ULONG Reserved,
-                        OUT PGEOMETRY Geometry)
+static LONG RamDiskOpen(CHAR* Path, OPENMODE OpenMode, ULONG* FileId)
 {
     //
-    // Should never be called when the caller expects valid Geometry!
+    // Always return success, as contents are already in memory
     //
-    ASSERT(Reserved == 0x49);
-    return TRUE;
+    return ESUCCESS;
 }
 
-BOOLEAN
-RamDiskReadLogicalSectors(IN ULONG Reserved,
-                          IN ULONGLONG SectorNumber,
-                          IN ULONG SectorCount,
-                          IN PVOID Buffer)
+static LONG RamDiskRead(ULONG FileId, VOID* Buffer, ULONG N, ULONG* Count)
 {
     PVOID StartAddress;
-    ULONG Length;
-    ASSERT(Reserved == 0x49);
 
     //
-    // Get actual pointers and lengths
+    // Get actual pointer
     //
-    StartAddress = (PVOID)((ULONG_PTR)SectorNumber * 512);
-    Length = SectorCount * 512;
-    
+    StartAddress = (PVOID)((ULONG_PTR)gRamDiskBase + gRamDiskOffset);
+
     //
     // Don't allow reads past our image
     //
-    if (((ULONG_PTR)StartAddress + Length) > gRamDiskSize) return FALSE;
+    if (gRamDiskOffset + N > gRamDiskSize)
+    {
+        *Count = 0;
+        return EIO;
+    }
 
     //
     // Do the read
     //
-    RtlCopyMemory(Buffer, RamDiskGetDataAtOffset(StartAddress), Length);
-    return TRUE;
+    RtlCopyMemory(Buffer, StartAddress, N);
+    *Count = N;
+
+    return ESUCCESS;
 }
 
+static LONG RamDiskSeek(ULONG FileId, LARGE_INTEGER* Position, SEEKMODE SeekMode)
+{
+    //
+    // Only accept absolute mode now
+    //
+    if (SeekMode != SeekAbsolute)
+        return EINVAL;
+
+    //
+    // Check if we're in the ramdisk
+    //
+    if (Position->HighPart != 0)
+        return EINVAL;
+    if (Position->LowPart >= gRamDiskSize)
+        return EINVAL;
+
+    //
+    // OK, remember seek position
+    //
+    gRamDiskOffset = Position->LowPart;
+
+    return ESUCCESS;
+}
+
+static const DEVVTBL RamDiskVtbl = {
+    RamDiskClose,
+    RamDiskGetFileInformation,
+    RamDiskOpen,
+    RamDiskRead,
+    RamDiskSeek,
+};
+
 VOID
 NTAPI
 RamDiskLoadVirtualFile(IN PCHAR FileName)
 {
-    PFILE RamFile;
-    ULONG TotalRead, ChunkSize;
-       PCHAR MsgBuffer = "Loading ramdisk...";
+    ULONG RamFile;
+    ULONG TotalRead, ChunkSize, Count;
+    PCHAR MsgBuffer = "Loading ramdisk...";
     ULONG PercentPerChunk, Percent;
+    FILEINFORMATION Information;
+    LARGE_INTEGER Position;
+    LONG ret;
 
     //
     // Display progress
@@ -95,25 +126,45 @@ RamDiskLoadVirtualFile(IN PCHAR FileName)
     UiDrawProgressBarCenter(1, 100, MsgBuffer);
 
     //
-    // Try opening the ramdisk file (this assumes the boot volume was opened)
-    //    
-    RamFile = FsOpenFile(FileName);
-    if (RamFile)
+    // Try opening the ramdisk file
+    //
+    ret = ArcOpen(FileName, OpenReadOnly, &RamFile);
+    if (ret == ESUCCESS)
     {
         //
         // Get the file size
         //
-        gRamDiskSize = FsGetFileSize(RamFile);
-        if (!gRamDiskSize) return;
-        
+        ret = ArcGetFileInformation(RamFile, &Information);
+        if (ret != ESUCCESS)
+        {
+            ArcClose(RamFile);
+            return;
+        }
+
+        //
+        // For now, limit RAM disks to 4GB
+        //
+        if (Information.EndingAddress.HighPart != 0)
+        {
+            UiMessageBox("RAM disk too big\n");
+            ArcClose(RamFile);
+            return;
+        }
+        gRamDiskSize = Information.EndingAddress.LowPart;
+
         //
         // Allocate memory for it
         //
         ChunkSize = 8 * 1024 * 1024;
         Percent = PercentPerChunk = 100 / (gRamDiskSize / ChunkSize);
         gRamDiskBase = MmAllocateMemory(gRamDiskSize);
-        if (!gRamDiskBase) return;
-                
+        if (!gRamDiskBase)
+        {
+            UiMessageBox("Failed to allocate memory for RAM disk\n");
+            ArcClose(RamFile);
+            return;
+        }
+
         //
         // Read it in chunks
         //
@@ -139,43 +190,34 @@ RamDiskLoadVirtualFile(IN PCHAR FileName)
             //
             // Copy the contents
             //
-            
-            if (!FsReadFile(RamFile,
-                            ChunkSize,
-                            NULL,
-                            (PVOID)((ULONG_PTR)gRamDiskBase + TotalRead)))
+            Position.HighPart = 0;
+            Position.LowPart = TotalRead;
+            ret = ArcSeek(RamFile, &Position, SeekAbsolute);
+            if (ret == ESUCCESS)
             {
-                //
-                // Fail
-                //
+                ret = ArcRead(RamFile,
+                              (PVOID)((ULONG_PTR)gRamDiskBase + TotalRead),
+                              ChunkSize,
+                              &Count);
+            }
+
+            //
+            // Check for success
+            //
+            if (ret != ESUCCESS || Count != ChunkSize)
+            {
+                MmFreeMemory(gRamDiskBase);
+                gRamDiskBase = NULL;
+                gRamDiskSize = 0;
+                ArcClose(RamFile);
                 UiMessageBox("Failed to read ramdisk\n");
+                return;
             }
         }
-    }
-}
 
-VOID
-NTAPI
-RamDiskSwitchFromBios(VOID)
-{
-    extern ULONG BootDrive, BootPartition;
+        ArcClose(RamFile);
 
-    //
-    // Check if we have a ramdisk, in which case we need to switch routines
-    //
-    if (gRamDiskBase)
-    {
-        //
-        // Don't use the BIOS for reads anymore
-        //
-        MachVtbl.DiskReadLogicalSectors = RamDiskReadLogicalSectors;
-        MachVtbl.DiskGetDriveGeometry = RamDiskGetDriveGeometry;
-        MachVtbl.DiskGetCacheableBlockCount = RamDiskGetCacheableBlockCount;
-        
-        //
-        // Switch to ramdisk boot partition
-        //
-        BootDrive = 0x49;
-        BootPartition = 0;
+        // Register a new device for the ramdisk
+        FsRegisterDevice("ramdisk(0)", &RamDiskVtbl);
     }
 }
index 08378ad..f8338ee 100644 (file)
 //
 // Ramdisk Routines
 //
-VOID
-NTAPI
-RamDiskSwitchFromBios(
-    VOID
-);
-
 VOID
 NTAPI
 RamDiskLoadVirtualFile(
index 6e52a68..7db4d0e 100644 (file)
@@ -746,15 +746,6 @@ LoadAndBootReactOS(PCSTR OperatingSystemName)
 
     UiDrawStatusText("Loading...");
 
-    //
-    // If we have a ramdisk, this will switch to the ramdisk disk routines
-    // which read from memory instead of using the firmware. This has to be done
-    // after hardware detection, since hardware detection will require using the
-    // real routines in order to perform disk-detection (just because we're on a
-    // ram-boot doesn't mean the user doesn't have actual disks installed too!)
-    //
-    RamDiskSwitchFromBios();
-
     /* Get boot path */
     if (strchr(SystemPath, '\\') != NULL)
         strcpy(szBootPath, strchr(SystemPath, '\\'));
index 1059661..76622ee 100644 (file)
@@ -390,6 +390,7 @@ LoadAndBootWindows(PCSTR OperatingSystemName, USHORT OperatingSystemVersion)
        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;
@@ -445,6 +446,28 @@ LoadAndBootWindows(PCSTR OperatingSystemName, USHORT OperatingSystemVersion)
                strcpy(BootOptions, "");
        }
 
+       //
+       // Check if a ramdisk file was given
+       //
+       File = strstr(BootOptions, "/RDPATH=");
+       if (File)
+       {
+               //
+               // 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...");