Implement ramdisk support for FreeLDR (ramdisk.c and ramdisk.h). The implementation...
authorReactOS Portable Systems Group <ros-arm-bringup@svn.reactos.org>
Tue, 5 Feb 2008 01:29:49 +0000 (01:29 +0000)
committerReactOS Portable Systems Group <ros-arm-bringup@svn.reactos.org>
Tue, 5 Feb 2008 01:29:49 +0000 (01:29 +0000)
We also define a virual ramdisk file (hardcoded name is reactos.img, on the boot volume) for testing ramdisk support on architectures without native ramdisk support (such as x86). This could be $
We introduce two new FreeLDR command-line parameters that should be sent by non-x86 firmware: rdbase and rdsize, and a new freeldr.ini ARC path: ramdisk(0) -- this is compatible with Windows.
For compatibility and status output, we use 8MB chunks for reading virtual ramdisk files (a dot is displayed for each additional 8MB chunk).
Finally, for code-reuse, the ramdisk implementation will "steal" the BIOS support routines in the arch-vtable and replace them with simple memcpy wrappers. To the disk/filesystem routines in Fre$
For now, only FAT ramdisks have been tested, and a sector size of 512 bytes is implied. We also disable the FAT block cache since it wouldn't make much sense to cache RAM.
$lds since the kernel won't get that far for a while.

svn path=/trunk/; revision=32128

reactos/boot/freeldr/freeldr/bootmgr.c
reactos/boot/freeldr/freeldr/disk/ramdisk.c [new file with mode: 0644]
reactos/boot/freeldr/freeldr/freeldr.c
reactos/boot/freeldr/freeldr/freeldr_base.rbuild
reactos/boot/freeldr/freeldr/include/freeldr.h
reactos/boot/freeldr/freeldr/include/ramdisk.h [new file with mode: 0644]
reactos/boot/freeldr/freeldr/reactos/arcname.c
reactos/boot/freeldr/freeldr/reactos/reactos.c

index 878ed85..904f1ef 100644 (file)
@@ -37,6 +37,14 @@ VOID RunLoader(VOID)
                return;
        }
 
+       //
+       // Check if we have a virtual RAM disk
+       // This is for x86 emulation -- on real hardware, the RAM disk will be
+       // located in one of the hardware memory descriptors as well as on the 
+       // freeldr command-line
+       //
+       RamDiskCheckForVirtualFile();
+
        if (!IniFileInitialize())
        {
                UiMessageBoxCritical("Error initializing .ini file");
diff --git a/reactos/boot/freeldr/freeldr/disk/ramdisk.c b/reactos/boot/freeldr/freeldr/disk/ramdisk.c
new file mode 100644 (file)
index 0000000..61f425a
--- /dev/null
@@ -0,0 +1,176 @@
+/*
+ * PROJECT:         ReactOS Boot Loader
+ * LICENSE:         GPL - See COPYING in the top level directory
+ * FILE:            boot/freeldr/arch/i386/ramdisk.c
+ * PURPOSE:         Implements routines to support booting from a RAM Disk
+ * PROGRAMMERS:     alex@winsiderss.com
+ */
+
+/* INCLUDES *******************************************************************/
+
+#include <freeldr.h>
+#define NDEBUG
+#include <debug.h>
+
+/* GLOBALS ********************************************************************/
+
+PVOID gRamDiskBase;
+ULONG gRamDiskSize;
+extern BOOLEAN gCacheEnabled;
+
+/* FUNCTIONS ******************************************************************/
+
+FORCEINLINE
+PVOID
+RamDiskGetDataAtOffset(IN PVOID Offset)
+{
+    //
+    // Return data from our RAM Disk
+    //
+    assert(((ULONG_PTR)gRamDiskBase + (ULONG_PTR)Offset) <
+           ((ULONG_PTR)gRamDiskBase + (ULONG_PTR)gRamDiskSize));
+    return (PVOID)((ULONG_PTR)gRamDiskBase + (ULONG_PTR)(Offset));
+}
+
+ULONG
+RamDiskGetCacheableBlockCount(IN ULONG Reserved)
+{
+    //
+    // Allow 32KB transfers (64 sectors), emulating BIOS LBA
+    //
+    return 64;
+}
+
+BOOLEAN
+RamDiskGetDriveGeometry(IN ULONG Reserved,
+                        OUT PGEOMETRY Geometry)
+{
+    //
+    // Should never be called when the caller expects valid Geometry!
+    //
+    return TRUE;
+}
+
+BOOLEAN
+RamDiskReadLogicalSectors(IN ULONG Reserved,
+                          IN ULONGLONG SectorNumber,
+                          IN ULONG SectorCount,
+                          IN PVOID Buffer)
+{
+    PVOID StartAddress;
+    ULONG Length;
+        
+    //
+    // Get actual pointers and lengths
+    //
+    StartAddress = (PVOID)((ULONG)SectorNumber * 512);
+    Length = SectorCount * 512;
+    
+    //
+    // Don't allow reads past our image
+    //
+    if (((ULONG_PTR)StartAddress + Length) > gRamDiskSize) return FALSE;
+
+    //
+    // Do the read
+    //
+    RtlCopyMemory(Buffer, RamDiskGetDataAtOffset(StartAddress), Length);
+    return TRUE;
+}
+
+VOID
+NTAPI
+RamDiskCheckForVirtualFile(VOID)
+{
+    PFILE RamFile;
+    ULONG TotalRead, ChunkSize;
+    
+    //
+    // Try opening the ramdisk file (this assumes the boot volume was opened)
+    //
+    RamFile = FsOpenFile("reactos.img");
+    if (RamFile)
+    {
+        //
+        // Get the file size
+        //
+        gRamDiskSize = FsGetFileSize(RamFile);
+        TuiPrintf("Found virtual ramdisk (%dKB) \n", gRamDiskSize / 1024);
+        if (!gRamDiskSize) return;
+        
+        //
+        // Allocate memory for it
+        //
+        ChunkSize = 8 * 1024 * 1024;
+        gRamDiskBase = MmAllocateMemory(gRamDiskSize);
+        if (!gRamDiskBase) return;
+        
+        //
+        // Read it in chunks
+        //
+        TuiPrintf("Loading ramdisk @ 0x%x...", gRamDiskBase);
+        for (TotalRead = 0; TotalRead < gRamDiskSize; TotalRead += ChunkSize)
+        {
+            //
+            // Check if we're at the last chunk
+            //
+            if ((gRamDiskSize - TotalRead) < ChunkSize)
+            {
+                //
+                // Only need the actual data required
+                //
+                ChunkSize = gRamDiskSize - TotalRead;
+            }
+            
+            //
+            // Copy the contents
+            //
+            TuiPrintf(".");
+            if (!FsReadFile(RamFile,
+                            ChunkSize,
+                            NULL,
+                            (PVOID)((ULONG_PTR)gRamDiskBase + TotalRead)))
+            {
+                //
+                // Fail
+                //
+                TuiPrintf("Failed to read ramdisk\n");
+            }
+        }
+        TuiPrintf("\n");
+    }
+}
+
+VOID
+NTAPI
+RamDiskSwitchFromBios(VOID)
+{
+    //
+    // 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;
+        
+        //
+        // Also disable cached FAT reads
+        //
+        gCacheEnabled = FALSE;
+    }
+}
+
+VOID
+NTAPI
+RamDiskInit(IN PCHAR CmdLine)
+{
+    //
+    // Get RAM disk parameters
+    //
+    gRamDiskBase = (PVOID)atoi(strstr(CmdLine, "rdbase="));
+    gRamDiskSize = atoi(strstr(CmdLine, "rdsize="));
+}
index 278e31a..2af6cc1 100644 (file)
@@ -26,6 +26,8 @@ VOID BootMain(LPSTR CmdLine)
 
        MachInit(CmdLine);
 
+       RamDiskInit(CmdLine);
+
        DebugInit();
 
        DbgPrint((DPRINT_WARNING, "BootMain() called.\n"));
index cd39dc7..cd20451 100644 (file)
@@ -19,6 +19,7 @@
        <directory name="disk">
                <file>disk.c</file>
                <file>partition.c</file>
+               <file>ramdisk.c</file>
        </directory>
        <directory name="fs">
                <file>ext2.c</file>
index 5ab5417..eadd57b 100644 (file)
@@ -45,6 +45,7 @@
 #include <inffile.h>
 #include <video.h>
 #include <portio.h>
+#include <ramdisk.h>
 /* NDK, needed for ReactOS/Windows loaders */
 #include <ndk/rtlfuncs.h>
 #include <ndk/ldrtypes.h>
diff --git a/reactos/boot/freeldr/freeldr/include/ramdisk.h b/reactos/boot/freeldr/freeldr/include/ramdisk.h
new file mode 100644 (file)
index 0000000..43f6808
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * PROJECT:         ReactOS Boot Loader
+ * LICENSE:         GPL - See COPYING in the top level directory
+ * FILE:            boot/freeldr/include/ramdisk.h
+ * PURPOSE:         Header file for ramdisk support
+ * PROGRAMMERS:     alex@winsiderss.com
+ */
+
+#ifndef _RAMDISK_
+#define _RAMDISK_
+
+//
+// Ramdisk Routines
+//
+VOID
+NTAPI
+RamDiskInit(
+    IN PCHAR CmdLine
+);
+
+VOID
+NTAPI
+RamDiskSwitchFromBios(
+    VOID
+);
+
+VOID
+NTAPI
+RamDiskCheckForVirtualFile(
+    VOID
+);
+
+#endif
index dee2202..789d1c5 100644 (file)
@@ -25,6 +25,25 @@ BOOLEAN DissectArcPath(CHAR *ArcPath, CHAR *BootPath, ULONG* BootDrive, ULONG* B
 {
        char *p;
 
+       //
+       // Detect ramdisk path
+       //
+       if (_strnicmp(ArcPath, "ramdisk(0)", 10) == 0)
+       {
+               //
+               // Magic value for ramdisks
+               //
+               *BootDrive = 0x49;
+               *BootPartition = 1;
+
+               //
+               // Get the path
+               //
+               p = ArcPath + 11;
+               strcpy(BootPath, p);
+               return TRUE;
+       }
+
        if (_strnicmp(ArcPath, "multi(0)disk(0)", 15) != 0)
                return FALSE;
 
index 2df4c98..abc4604 100644 (file)
@@ -707,6 +707,15 @@ 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();
+
        /*
         * Try to open system drive
         */