1
0
Fork 0
mirror of https://github.com/reactos/reactos.git synced 2025-05-18 00:31:27 +00:00

[FREELDR] Improvements for the RamDisk support.

- Implement support for the "RDIMAGELENGTH" and "RDIMAGEOFFSET" boot
  options. Fixes CORE-15432.

- Separate the initialization of the global gInitRamDiskBase /
  gInitRamDiskSize variables from the FreeLdr command-line, and the
  actual initialization of the internal variables of the RamDisk.
  The latter are initialized via calls to RamDiskInitialize().

- Implement 'SeekRelative' mode in RamDiskSeek().

- Make RamDiskLoadVirtualFile() internal function that gets called by
  RamDiskInitialize(), and we use the latter in the NT loader instead.
This commit is contained in:
Hermès Bélusca-Maïto 2019-09-13 19:04:06 +02:00
parent 034820ca55
commit db15c921e8
No known key found for this signature in database
GPG key ID: 3B2539C65E7B93D0
6 changed files with 183 additions and 121 deletions
boot/freeldr/freeldr

View file

@ -120,8 +120,8 @@ ArmHwDetect(VOID)
SecondLevelIcacheSize = SecondLevelIcacheSize =
SecondLevelIcacheFillSize = 0; SecondLevelIcacheFillSize = 0;
/* Register RAMDISK Device */ /* Initialize the RAMDISK Device */
RamDiskInitialize(); RamDiskInitialize(TRUE, NULL, NULL);
/* Fill out the ARC disk block */ /* Fill out the ARC disk block */
AddReactOSArcDiskInfo("ramdisk(0)", 0xBADAB00F, 0xDEADBABE, TRUE); AddReactOSArcDiskInfo("ramdisk(0)", 0xBADAB00F, 0xDEADBABE, TRUE);

View file

@ -91,7 +91,7 @@ CmdLineParse(IN PCSTR CmdLine)
Setting = strstr(CmdLine, "rdbase="); Setting = strstr(CmdLine, "rdbase=");
if (Setting) if (Setting)
{ {
gRamDiskBase = gInitRamDiskBase =
(PVOID)(ULONG_PTR)strtoull(Setting + (PVOID)(ULONG_PTR)strtoull(Setting +
sizeof("rdbase=") - sizeof(ANSI_NULL), sizeof("rdbase=") - sizeof(ANSI_NULL),
NULL, 0); NULL, 0);
@ -101,9 +101,9 @@ CmdLineParse(IN PCSTR CmdLine)
Setting = strstr(CmdLine, "rdsize="); Setting = strstr(CmdLine, "rdsize=");
if (Setting) if (Setting)
{ {
gRamDiskSize = strtoul(Setting + gInitRamDiskSize = strtoul(Setting +
sizeof("rdsize=") - sizeof(ANSI_NULL), sizeof("rdsize=") - sizeof(ANSI_NULL),
NULL, 0); NULL, 0);
} }
/* Get ramdisk offset */ /* Get ramdisk offset */
@ -116,7 +116,7 @@ CmdLineParse(IN PCSTR CmdLine)
} }
/* Fix it up */ /* Fix it up */
gRamDiskBase = (PVOID)((ULONG_PTR)gRamDiskBase + Offset); gInitRamDiskBase = (PVOID)((ULONG_PTR)gInitRamDiskBase + Offset);
} }
PCSTR PCSTR

View file

@ -1,51 +1,48 @@
/* /*
* PROJECT: ReactOS Boot Loader * PROJECT: FreeLoader
* LICENSE: BSD - See COPYING.ARM in the top level directory * LICENSE: BSD - See COPYING.ARM in the top level directory
* 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 * COPYRIGHT: Copyright 2008 ReactOS Portable Systems Group
* PROGRAMMERS: ReactOS Portable Systems Group * Copyright 2009 Hervé Poussineau
* Hervé Poussineau * Copyright 2019 Hermes Belusca-Maito
*/ */
/* INCLUDES *******************************************************************/ /* INCLUDES *******************************************************************/
#include <freeldr.h> #include <freeldr.h>
#include <debug.h>
/* GLOBALS ********************************************************************/ /* GLOBALS ********************************************************************/
PVOID gRamDiskBase; PVOID gInitRamDiskBase = NULL;
ULONG gRamDiskSize; ULONG gInitRamDiskSize = 0;
ULONG gRamDiskOffset;
static BOOLEAN RamDiskDeviceRegistered = FALSE;
static PVOID RamDiskBase;
static ULONGLONG RamDiskFileSize; // FIXME: RAM disks currently limited to 4GB.
static ULONGLONG RamDiskImageLength; // Size of valid data in the Ramdisk (usually == RamDiskFileSize - RamDiskImageOffset)
static ULONG RamDiskImageOffset; // Starting offset from the Ramdisk base.
static ULONGLONG RamDiskOffset; // Current position in the Ramdisk.
/* FUNCTIONS ******************************************************************/ /* FUNCTIONS ******************************************************************/
static ARC_STATUS RamDiskClose(ULONG FileId) static ARC_STATUS RamDiskClose(ULONG FileId)
{ {
// /* Nothing to do */
// Nothing to do
//
return ESUCCESS; return ESUCCESS;
} }
static ARC_STATUS RamDiskGetFileInformation(ULONG FileId, FILEINFORMATION* Information) static ARC_STATUS RamDiskGetFileInformation(ULONG FileId, FILEINFORMATION* Information)
{ {
//
// Give current seek offset and ram disk size to caller
//
RtlZeroMemory(Information, sizeof(*Information)); RtlZeroMemory(Information, sizeof(*Information));
Information->EndingAddress.LowPart = gRamDiskSize; Information->EndingAddress.QuadPart = RamDiskImageLength;
Information->CurrentAddress.LowPart = gRamDiskOffset; Information->CurrentAddress.QuadPart = RamDiskOffset;
return ESUCCESS; return ESUCCESS;
} }
static ARC_STATUS RamDiskOpen(CHAR* Path, OPENMODE OpenMode, ULONG* FileId) static ARC_STATUS RamDiskOpen(CHAR* Path, OPENMODE OpenMode, ULONG* FileId)
{ {
// /* Always return success, as contents are already in memory */
// Always return success, as contents are already in memory
//
return ESUCCESS; return ESUCCESS;
} }
@ -53,24 +50,20 @@ static ARC_STATUS RamDiskRead(ULONG FileId, VOID* Buffer, ULONG N, ULONG* Count)
{ {
PVOID StartAddress; PVOID StartAddress;
// /* Don't allow reads past our image */
// Get actual pointer if (RamDiskOffset >= RamDiskImageLength || RamDiskOffset + N > RamDiskImageLength)
//
StartAddress = (PVOID)((ULONG_PTR)gRamDiskBase + gRamDiskOffset);
//
// Don't allow reads past our image
//
if (gRamDiskOffset + N > gRamDiskSize)
{ {
*Count = 0; *Count = 0;
return EIO; return EIO;
} }
// N = min(N, RamdiskImageLength - RamDiskOffset);
// /* Get actual pointer */
// Do the read StartAddress = (PVOID)((ULONG_PTR)RamDiskBase + RamDiskImageOffset + (ULONG_PTR)RamDiskOffset);
//
/* Do the read */
RtlCopyMemory(Buffer, StartAddress, N); RtlCopyMemory(Buffer, StartAddress, N);
RamDiskOffset += N;
*Count = N; *Count = N;
return ESUCCESS; return ESUCCESS;
@ -78,29 +71,29 @@ static ARC_STATUS RamDiskRead(ULONG FileId, VOID* Buffer, ULONG N, ULONG* Count)
static ARC_STATUS RamDiskSeek(ULONG FileId, LARGE_INTEGER* Position, SEEKMODE SeekMode) static ARC_STATUS RamDiskSeek(ULONG FileId, LARGE_INTEGER* Position, SEEKMODE SeekMode)
{ {
// LARGE_INTEGER NewPosition = *Position;
// Only accept absolute mode now
// switch (SeekMode)
if (SeekMode != SeekAbsolute) {
case SeekAbsolute:
break;
case SeekRelative:
NewPosition.QuadPart += RamDiskOffset;
break;
default:
ASSERT(FALSE);
return EINVAL;
}
if (NewPosition.QuadPart >= RamDiskImageLength)
return EINVAL; return EINVAL;
// RamDiskOffset = NewPosition.QuadPart;
// 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; return ESUCCESS;
} }
static const DEVVTBL RamDiskVtbl = { static const DEVVTBL RamDiskVtbl =
{
RamDiskClose, RamDiskClose,
RamDiskGetFileInformation, RamDiskGetFileInformation,
RamDiskOpen, RamDiskOpen,
@ -108,21 +101,15 @@ static const DEVVTBL RamDiskVtbl = {
RamDiskSeek, RamDiskSeek,
}; };
VOID static ARC_STATUS
RamDiskInitialize(VOID)
{
/* Register the RAMDISK device */
FsRegisterDevice("ramdisk(0)", &RamDiskVtbl);
}
ARC_STATUS
RamDiskLoadVirtualFile( RamDiskLoadVirtualFile(
IN PCSTR FileName, IN PCSTR FileName,
IN PCSTR DefaultPath OPTIONAL) IN PCSTR DefaultPath OPTIONAL)
{ {
ARC_STATUS Status; ARC_STATUS Status;
ULONG RamFileId; ULONG RamFileId;
ULONG TotalRead, ChunkSize, Count; ULONG ChunkSize, Count;
ULONGLONG TotalRead;
PCHAR MsgBuffer = "Loading RamDisk..."; PCHAR MsgBuffer = "Loading RamDisk...";
ULONG PercentPerChunk, Percent; ULONG PercentPerChunk, Percent;
FILEINFORMATION Information; FILEINFORMATION Information;
@ -132,7 +119,7 @@ RamDiskLoadVirtualFile(
UiDrawBackdrop(); UiDrawBackdrop();
UiDrawProgressBarCenter(1, 100, MsgBuffer); UiDrawProgressBarCenter(1, 100, MsgBuffer);
/* Try opening the ramdisk file */ /* Try opening the Ramdisk file */
Status = FsOpenFile(FileName, DefaultPath, OpenReadOnly, &RamFileId); Status = FsOpenFile(FileName, DefaultPath, OpenReadOnly, &RamFileId);
if (Status != ESUCCESS) if (Status != ESUCCESS)
return Status; return Status;
@ -145,23 +132,24 @@ RamDiskLoadVirtualFile(
return Status; return Status;
} }
/* For now, limit RAM disks to 4GB */ /* FIXME: For now, limit RAM disks to 4GB */
if (Information.EndingAddress.HighPart != 0) if (Information.EndingAddress.HighPart != 0)
{ {
UiMessageBox("RAM disk too big."); UiMessageBox("RAM disk too big.");
ArcClose(RamFileId); ArcClose(RamFileId);
return ENOMEM; return ENOMEM;
} }
gRamDiskSize = Information.EndingAddress.LowPart; RamDiskFileSize = Information.EndingAddress.QuadPart;
ASSERT(RamDiskFileSize < 0x100000000); // See FIXME above.
/* Allocate memory for it */ /* Allocate memory for it */
ChunkSize = 8 * 1024 * 1024; ChunkSize = 8 * 1024 * 1024;
if (gRamDiskSize < ChunkSize) if (RamDiskFileSize < ChunkSize)
Percent = PercentPerChunk = 0; Percent = PercentPerChunk = 0;
else else
Percent = PercentPerChunk = 100 / (gRamDiskSize / ChunkSize); Percent = PercentPerChunk = 100 / (RamDiskFileSize / ChunkSize);
gRamDiskBase = MmAllocateMemoryWithType(gRamDiskSize, LoaderXIPRom); RamDiskBase = MmAllocateMemoryWithType(RamDiskFileSize, LoaderXIPRom);
if (!gRamDiskBase) if (!RamDiskBase)
{ {
UiMessageBox("Failed to allocate memory for RAM disk."); UiMessageBox("Failed to allocate memory for RAM disk.");
ArcClose(RamFileId); ArcClose(RamFileId);
@ -171,13 +159,13 @@ RamDiskLoadVirtualFile(
/* /*
* Read it in chunks * Read it in chunks
*/ */
for (TotalRead = 0; TotalRead < gRamDiskSize; TotalRead += ChunkSize) for (TotalRead = 0; TotalRead < RamDiskFileSize; TotalRead += ChunkSize)
{ {
/* Check if we're at the last chunk */ /* Check if we're at the last chunk */
if ((gRamDiskSize - TotalRead) < ChunkSize) if ((RamDiskFileSize - TotalRead) < ChunkSize)
{ {
/* Only need the actual data required */ /* Only need the actual data required */
ChunkSize = gRamDiskSize - TotalRead; ChunkSize = (ULONG)(RamDiskFileSize - TotalRead);
} }
/* Draw progress */ /* Draw progress */
@ -185,13 +173,12 @@ RamDiskLoadVirtualFile(
Percent += PercentPerChunk; Percent += PercentPerChunk;
/* Copy the contents */ /* Copy the contents */
Position.HighPart = 0; Position.QuadPart = TotalRead;
Position.LowPart = TotalRead;
Status = ArcSeek(RamFileId, &Position, SeekAbsolute); Status = ArcSeek(RamFileId, &Position, SeekAbsolute);
if (Status == ESUCCESS) if (Status == ESUCCESS)
{ {
Status = ArcRead(RamFileId, Status = ArcRead(RamFileId,
(PVOID)((ULONG_PTR)gRamDiskBase + TotalRead), (PVOID)((ULONG_PTR)RamDiskBase + (ULONG_PTR)TotalRead),
ChunkSize, ChunkSize,
&Count); &Count);
} }
@ -199,9 +186,9 @@ RamDiskLoadVirtualFile(
/* Check for success */ /* Check for success */
if ((Status != ESUCCESS) || (Count != ChunkSize)) if ((Status != ESUCCESS) || (Count != ChunkSize))
{ {
MmFreeMemory(gRamDiskBase); MmFreeMemory(RamDiskBase);
gRamDiskBase = NULL; RamDiskBase = NULL;
gRamDiskSize = 0; RamDiskFileSize = 0;
ArcClose(RamFileId); ArcClose(RamFileId);
UiMessageBox("Failed to read RAM disk."); UiMessageBox("Failed to read RAM disk.");
return ((Status != ESUCCESS) ? Status : EIO); return ((Status != ESUCCESS) ? Status : EIO);
@ -210,8 +197,95 @@ RamDiskLoadVirtualFile(
ArcClose(RamFileId); ArcClose(RamFileId);
/* Setup the RAMDISK device */ return ESUCCESS;
RamDiskInitialize(); }
ARC_STATUS
RamDiskInitialize(
IN BOOLEAN InitRamDisk,
IN PCSTR LoadOptions OPTIONAL,
IN PCSTR DefaultPath OPTIONAL)
{
/* Reset the RAMDISK device */
if ((RamDiskBase != gInitRamDiskBase) &&
(RamDiskFileSize != gInitRamDiskSize) &&
(gInitRamDiskSize != 0))
{
/* This is not the initial Ramdisk, so we can free the allocated memory */
MmFreeMemory(RamDiskBase);
}
RamDiskBase = NULL;
RamDiskFileSize = 0;
RamDiskImageLength = 0;
RamDiskImageOffset = 0;
RamDiskOffset = 0;
if (InitRamDisk)
{
/* We initialize the initial Ramdisk: it should be present in memory */
if (!gInitRamDiskBase || gInitRamDiskSize == 0)
return ENODEV;
// TODO: Handle SDI image.
RamDiskBase = gInitRamDiskBase;
RamDiskFileSize = gInitRamDiskSize;
ASSERT(RamDiskFileSize < 0x100000000); // See FIXME about 4GB support in RamDiskLoadVirtualFile().
}
else
{
/* We initialize the Ramdisk from the load options */
ARC_STATUS Status;
CHAR FileName[MAX_PATH] = "";
/* If we don't have any load options, initialize an empty Ramdisk */
if (LoadOptions)
{
PCHAR Option;
/* Ramdisk image file name */
Option = strstr(LoadOptions, "/RDPATH=");
if (Option)
{
/* Copy the file name - everything until the next separator */
Option += 8;
RtlStringCbCopyNA(FileName, sizeof(FileName),
Option, strcspn(Option, " \t") * sizeof(CHAR));
}
/* Ramdisk image length */
Option = strstr(LoadOptions, "/RDIMAGELENGTH=");
if (Option)
{
RamDiskImageLength = _atoi64(Option + 15);
}
/* Ramdisk image offset */
Option = strstr(LoadOptions, "/RDIMAGEOFFSET=");
if (Option)
{
RamDiskImageOffset = atol(Option + 15);
}
}
if (*FileName)
{
Status = RamDiskLoadVirtualFile(FileName, DefaultPath);
if (Status != ESUCCESS)
return Status;
}
}
/* Adjust the Ramdisk image length if needed */
if (!RamDiskImageLength || (RamDiskImageLength > RamDiskFileSize - RamDiskImageOffset))
RamDiskImageLength = RamDiskFileSize - RamDiskImageOffset;
/* Register the RAMDISK device */
if (!RamDiskDeviceRegistered)
{
FsRegisterDevice("ramdisk(0)", &RamDiskVtbl);
RamDiskDeviceRegistered = TRUE;
}
return ESUCCESS; return ESUCCESS;
} }

View file

@ -1,23 +1,19 @@
/* /*
* PROJECT: ReactOS Boot Loader * PROJECT: FreeLoader
* LICENSE: BSD - See COPYING.ARM in the top level directory * LICENSE: BSD - See COPYING.ARM in the top level directory
* FILE: boot/freeldr/freeldr/include/ramdisk.h * PURPOSE: Header file for ramdisk support.
* PURPOSE: Header file for ramdisk support * COPYRIGHT: Copyright 2008 ReactOS Portable Systems Group
* PROGRAMMERS: ReactOS Portable Systems Group * Copyright 2009 Hervé Poussineau
* Copyright 2019 Hermes Belusca-Maito
*/ */
#pragma once #pragma once
//
// Ramdisk Routines
//
ARC_STATUS ARC_STATUS
RamDiskLoadVirtualFile( RamDiskInitialize(
IN PCSTR FileName, IN BOOLEAN InitRamDisk,
IN PCSTR LoadOptions OPTIONAL,
IN PCSTR DefaultPath OPTIONAL); IN PCSTR DefaultPath OPTIONAL);
VOID extern PVOID gInitRamDiskBase;
RamDiskInitialize(VOID); extern ULONG gInitRamDiskSize;
extern PVOID gRamDiskBase;
extern ULONG gRamDiskSize;

View file

@ -284,17 +284,13 @@ LoadReactOSSetup(
File = strstr(BootOptions2, "/RDPATH="); File = strstr(BootOptions2, "/RDPATH=");
if (File) if (File)
{ {
/* Copy the file name and everything else after it */
RtlStringCbCopyA(FileName, sizeof(FileName), File + 8);
/* Null-terminate */
*strstr(FileName, " ") = ANSI_NULL;
/* Load the ramdisk */ /* Load the ramdisk */
Status = RamDiskLoadVirtualFile(FileName, SystemPartition); Status = RamDiskInitialize(FALSE, BootOptions2, SystemPartition);
if (Status != ESUCCESS) if (Status != ESUCCESS)
{ {
UiMessageBox("Failed to load RAM disk file %s", FileName); File += 8;
UiMessageBox("Failed to load RAM disk file '%.*s'",
strcspn(File, " \t"), File);
return Status; return Status;
} }
} }
@ -323,7 +319,7 @@ LoadReactOSSetup(
TRACE("BootPath: '%s', SystemPath: '%s'\n", BootPath, SystemPath); TRACE("BootPath: '%s', SystemPath: '%s'\n", BootPath, SystemPath);
/* Get Load options - debug and non-debug */ /* Get load options - debug and non-debug */
if (!InfFindFirstLine(InfHandle, "SetupData", "OsLoadOptions", &InfContext)) if (!InfFindFirstLine(InfHandle, "SetupData", "OsLoadOptions", &InfContext))
{ {
ERR("Failed to find 'SetupData/OsLoadOptions'\n"); ERR("Failed to find 'SetupData/OsLoadOptions'\n");

View file

@ -731,9 +731,9 @@ LoadAndBootWindows(
BOOLEAN Success; BOOLEAN Success;
USHORT OperatingSystemVersion; USHORT OperatingSystemVersion;
PLOADER_PARAMETER_BLOCK LoaderBlock; PLOADER_PARAMETER_BLOCK LoaderBlock;
CHAR BootPath[MAX_PATH]; CHAR BootPath[MAX_PATH];
CHAR FileName[MAX_PATH]; CHAR FileName[MAX_PATH];
CHAR BootOptions[256]; CHAR BootOptions[256];
/* Retrieve the (mandatory) boot type */ /* Retrieve the (mandatory) boot type */
ArgValue = GetArgumentValue(Argc, Argv, "BootType"); ArgValue = GetArgumentValue(Argc, Argv, "BootType");
@ -852,17 +852,13 @@ LoadAndBootWindows(
File = strstr(BootOptions, "/RDPATH="); File = strstr(BootOptions, "/RDPATH=");
if (File) if (File)
{ {
/* Copy the file name and everything else after it */
RtlStringCbCopyA(FileName, sizeof(FileName), File + 8);
/* Null-terminate */
*strstr(FileName, " ") = ANSI_NULL;
/* Load the ramdisk */ /* Load the ramdisk */
Status = RamDiskLoadVirtualFile(FileName, SystemPartition); Status = RamDiskInitialize(FALSE, BootOptions, SystemPartition);
if (Status != ESUCCESS) if (Status != ESUCCESS)
{ {
UiMessageBox("Failed to load RAM disk file %s", FileName); File += 8;
UiMessageBox("Failed to load RAM disk file '%.*s'",
strcspn(File, " \t"), File);
return Status; return Status;
} }
} }