[freeldr] Rework the ramdisk driver to let it be a full device, instead of a deprecated harddisk which was only available once real harddisks were disabled

Add support for /RDPATH switch in WINLDR boot style

svn path=/trunk/; revision=43377
This commit is contained in:
Hervé Poussineau 2009-10-11 17:08:33 +00:00
parent 84625e3ee4
commit 02db465a10
5 changed files with 146 additions and 100 deletions

View file

@ -71,7 +71,6 @@ BOOLEAN
ArmDiskGetDriveGeometry(IN ULONG DriveNumber, ArmDiskGetDriveGeometry(IN ULONG DriveNumber,
OUT PGEOMETRY Geometry) OUT PGEOMETRY Geometry)
{ {
ASSERT(gRamDiskBase == NULL);
return FALSE; return FALSE;
} }
@ -81,15 +80,13 @@ ArmDiskReadLogicalSectors(IN ULONG DriveNumber,
IN ULONG SectorCount, IN ULONG SectorCount,
IN PVOID Buffer) IN PVOID Buffer)
{ {
ASSERT(gRamDiskBase == NULL);
return FALSE; return FALSE;
} }
ULONG ULONG
ArmDiskGetCacheableBlockCount(IN ULONG DriveNumber) ArmDiskGetCacheableBlockCount(IN ULONG DriveNumber)
{ {
ASSERT(gRamDiskBase == NULL); return 0;
return FALSE;
} }
PCONFIGURATION_COMPONENT_DATA PCONFIGURATION_COMPONENT_DATA
@ -191,12 +188,11 @@ MachInit(IN PCCH CommandLine)
MachVtbl.HwDetect = ArmHwDetect; 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.DiskReadLogicalSectors = ArmDiskReadLogicalSectors;
MachVtbl.DiskGetDriveGeometry = ArmDiskGetDriveGeometry; MachVtbl.DiskGetDriveGeometry = ArmDiskGetDriveGeometry;
MachVtbl.DiskGetCacheableBlockCount = ArmDiskGetCacheableBlockCount; MachVtbl.DiskGetCacheableBlockCount = ArmDiskGetCacheableBlockCount;
RamDiskSwitchFromBios();
// //
// Now set default disk handling routines -- we don't need to override // Now set default disk handling routines -- we don't need to override

View file

@ -1,9 +1,10 @@
/* /*
* PROJECT: ReactOS Boot Loader * PROJECT: ReactOS Boot Loader
* LICENSE: BSD - See COPYING.ARM in the top level directory * 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 * PURPOSE: Implements routines to support booting from a RAM Disk
* PROGRAMMERS: ReactOS Portable Systems Group * PROGRAMMERS: ReactOS Portable Systems Group
* Hervé Poussineau
*/ */
/* INCLUDES *******************************************************************/ /* INCLUDES *******************************************************************/
@ -16,78 +17,108 @@
PVOID gRamDiskBase; PVOID gRamDiskBase;
ULONG gRamDiskSize; ULONG gRamDiskSize;
ULONG gRamDiskOffset;
/* FUNCTIONS ******************************************************************/ /* FUNCTIONS ******************************************************************/
FORCEINLINE static LONG RamDiskClose(ULONG FileId)
PVOID
RamDiskGetDataAtOffset(IN PVOID Offset)
{ {
// //
// Return data from our RAM Disk // Nothing to do
// //
ASSERT(((ULONG_PTR)gRamDiskBase + (ULONG_PTR)Offset) < return ESUCCESS;
((ULONG_PTR)gRamDiskBase + (ULONG_PTR)gRamDiskSize));
return (PVOID)((ULONG_PTR)gRamDiskBase + (ULONG_PTR)(Offset));
} }
ULONG static LONG RamDiskGetFileInformation(ULONG FileId, FILEINFORMATION* Information)
RamDiskGetCacheableBlockCount(IN ULONG Reserved)
{ {
// //
// Allow 32KB transfers (64 sectors), emulating BIOS LBA // Give current seek offset and ram disk size to caller
// //
ASSERT(Reserved == 0x49); RtlZeroMemory(Information, sizeof(FILEINFORMATION));
return 64; Information->EndingAddress.LowPart = gRamDiskSize;
Information->CurrentAddress.LowPart = gRamDiskOffset;
return ESUCCESS;
} }
BOOLEAN static LONG RamDiskOpen(CHAR* Path, OPENMODE OpenMode, ULONG* FileId)
RamDiskGetDriveGeometry(IN ULONG Reserved,
OUT PGEOMETRY Geometry)
{ {
// //
// Should never be called when the caller expects valid Geometry! // Always return success, as contents are already in memory
// //
ASSERT(Reserved == 0x49); return ESUCCESS;
return TRUE;
} }
BOOLEAN static LONG RamDiskRead(ULONG FileId, VOID* Buffer, ULONG N, ULONG* Count)
RamDiskReadLogicalSectors(IN ULONG Reserved,
IN ULONGLONG SectorNumber,
IN ULONG SectorCount,
IN PVOID Buffer)
{ {
PVOID StartAddress; PVOID StartAddress;
ULONG Length;
ASSERT(Reserved == 0x49);
// //
// Get actual pointers and lengths // Get actual pointer
// //
StartAddress = (PVOID)((ULONG_PTR)SectorNumber * 512); StartAddress = (PVOID)((ULONG_PTR)gRamDiskBase + gRamDiskOffset);
Length = SectorCount * 512;
// //
// Don't allow reads past our image // 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 // Do the read
// //
RtlCopyMemory(Buffer, RamDiskGetDataAtOffset(StartAddress), Length); RtlCopyMemory(Buffer, StartAddress, N);
return TRUE; *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 VOID
NTAPI NTAPI
RamDiskLoadVirtualFile(IN PCHAR FileName) RamDiskLoadVirtualFile(IN PCHAR FileName)
{ {
PFILE RamFile; ULONG RamFile;
ULONG TotalRead, ChunkSize; ULONG TotalRead, ChunkSize, Count;
PCHAR MsgBuffer = "Loading ramdisk..."; PCHAR MsgBuffer = "Loading ramdisk...";
ULONG PercentPerChunk, Percent; ULONG PercentPerChunk, Percent;
FILEINFORMATION Information;
LARGE_INTEGER Position;
LONG ret;
// //
// Display progress // Display progress
@ -95,25 +126,45 @@ RamDiskLoadVirtualFile(IN PCHAR FileName)
UiDrawProgressBarCenter(1, 100, MsgBuffer); UiDrawProgressBarCenter(1, 100, MsgBuffer);
// //
// Try opening the ramdisk file (this assumes the boot volume was opened) // Try opening the ramdisk file
// //
RamFile = FsOpenFile(FileName); ret = ArcOpen(FileName, OpenReadOnly, &RamFile);
if (RamFile) if (ret == ESUCCESS)
{ {
// //
// Get the file size // Get the file size
// //
gRamDiskSize = FsGetFileSize(RamFile); ret = ArcGetFileInformation(RamFile, &Information);
if (!gRamDiskSize) return; 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 // Allocate memory for it
// //
ChunkSize = 8 * 1024 * 1024; ChunkSize = 8 * 1024 * 1024;
Percent = PercentPerChunk = 100 / (gRamDiskSize / ChunkSize); Percent = PercentPerChunk = 100 / (gRamDiskSize / ChunkSize);
gRamDiskBase = MmAllocateMemory(gRamDiskSize); gRamDiskBase = MmAllocateMemory(gRamDiskSize);
if (!gRamDiskBase) return; if (!gRamDiskBase)
{
UiMessageBox("Failed to allocate memory for RAM disk\n");
ArcClose(RamFile);
return;
}
// //
// Read it in chunks // Read it in chunks
// //
@ -139,43 +190,34 @@ RamDiskLoadVirtualFile(IN PCHAR FileName)
// //
// Copy the contents // Copy the contents
// //
Position.HighPart = 0;
if (!FsReadFile(RamFile, Position.LowPart = TotalRead;
ChunkSize, ret = ArcSeek(RamFile, &Position, SeekAbsolute);
NULL, if (ret == ESUCCESS)
(PVOID)((ULONG_PTR)gRamDiskBase + TotalRead)))
{ {
// ret = ArcRead(RamFile,
// Fail (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"); UiMessageBox("Failed to read ramdisk\n");
return;
} }
} }
}
} ArcClose(RamFile);
VOID // Register a new device for the ramdisk
NTAPI FsRegisterDevice("ramdisk(0)", &RamDiskVtbl);
RamDiskSwitchFromBios(VOID)
{
extern ULONG BootDrive, BootPartition;
//
// 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;
} }
} }

View file

@ -12,12 +12,6 @@
// //
// Ramdisk Routines // Ramdisk Routines
// //
VOID
NTAPI
RamDiskSwitchFromBios(
VOID
);
VOID VOID
NTAPI NTAPI
RamDiskLoadVirtualFile( RamDiskLoadVirtualFile(

View file

@ -746,15 +746,6 @@ LoadAndBootReactOS(PCSTR OperatingSystemName)
UiDrawStatusText("Loading..."); 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 */ /* Get boot path */
if (strchr(SystemPath, '\\') != NULL) if (strchr(SystemPath, '\\') != NULL)
strcpy(szBootPath, strchr(SystemPath, '\\')); strcpy(szBootPath, strchr(SystemPath, '\\'));

View file

@ -390,6 +390,7 @@ LoadAndBootWindows(PCSTR OperatingSystemName, USHORT OperatingSystemVersion)
CHAR FullPath[MAX_PATH], SystemRoot[MAX_PATH], BootPath[MAX_PATH]; CHAR FullPath[MAX_PATH], SystemRoot[MAX_PATH], BootPath[MAX_PATH];
CHAR FileName[MAX_PATH]; CHAR FileName[MAX_PATH];
CHAR BootOptions[256]; CHAR BootOptions[256];
PCHAR File;
PCHAR PathSeparator; PCHAR PathSeparator;
PVOID NtosBase = NULL, HalBase = NULL, KdComBase = NULL; PVOID NtosBase = NULL, HalBase = NULL, KdComBase = NULL;
BOOLEAN Status; BOOLEAN Status;
@ -445,6 +446,28 @@ LoadAndBootWindows(PCSTR OperatingSystemName, USHORT OperatingSystemVersion)
strcpy(BootOptions, ""); 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 */ /* Let user know we started loading */
UiDrawStatusText("Loading..."); UiDrawStatusText("Loading...");