https://git.reactos.org/?p=reactos.git;a=commitdiff;h=db15c921e8f92b7bad319…
commit db15c921e8f92b7bad319df4962e255087a8ca94
Author: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org>
AuthorDate: Fri Sep 13 19:04:06 2019 +0200
Commit: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org>
CommitDate: Wed Oct 9 03:26:41 2019 +0200
[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.
---
boot/freeldr/freeldr/arch/arm/macharm.c | 4 +-
boot/freeldr/freeldr/cmdline.c | 10 +-
boot/freeldr/freeldr/disk/ramdisk.c | 230 +++++++++++++++++++++-----------
boot/freeldr/freeldr/include/ramdisk.h | 26 ++--
boot/freeldr/freeldr/ntldr/setupldr.c | 14 +-
boot/freeldr/freeldr/ntldr/winldr.c | 18 +--
6 files changed, 182 insertions(+), 120 deletions(-)
diff --git a/boot/freeldr/freeldr/arch/arm/macharm.c
b/boot/freeldr/freeldr/arch/arm/macharm.c
index d38a38924f7..cfca3b17169 100644
--- a/boot/freeldr/freeldr/arch/arm/macharm.c
+++ b/boot/freeldr/freeldr/arch/arm/macharm.c
@@ -120,8 +120,8 @@ ArmHwDetect(VOID)
SecondLevelIcacheSize =
SecondLevelIcacheFillSize = 0;
- /* Register RAMDISK Device */
- RamDiskInitialize();
+ /* Initialize the RAMDISK Device */
+ RamDiskInitialize(TRUE, NULL, NULL);
/* Fill out the ARC disk block */
AddReactOSArcDiskInfo("ramdisk(0)", 0xBADAB00F, 0xDEADBABE, TRUE);
diff --git a/boot/freeldr/freeldr/cmdline.c b/boot/freeldr/freeldr/cmdline.c
index b7ac90dd274..c41466e6163 100644
--- a/boot/freeldr/freeldr/cmdline.c
+++ b/boot/freeldr/freeldr/cmdline.c
@@ -91,7 +91,7 @@ CmdLineParse(IN PCSTR CmdLine)
Setting = strstr(CmdLine, "rdbase=");
if (Setting)
{
- gRamDiskBase =
+ gInitRamDiskBase =
(PVOID)(ULONG_PTR)strtoull(Setting +
sizeof("rdbase=") - sizeof(ANSI_NULL),
NULL, 0);
@@ -101,9 +101,9 @@ CmdLineParse(IN PCSTR CmdLine)
Setting = strstr(CmdLine, "rdsize=");
if (Setting)
{
- gRamDiskSize = strtoul(Setting +
- sizeof("rdsize=") - sizeof(ANSI_NULL),
- NULL, 0);
+ gInitRamDiskSize = strtoul(Setting +
+ sizeof("rdsize=") - sizeof(ANSI_NULL),
+ NULL, 0);
}
/* Get ramdisk offset */
@@ -116,7 +116,7 @@ CmdLineParse(IN PCSTR CmdLine)
}
/* Fix it up */
- gRamDiskBase = (PVOID)((ULONG_PTR)gRamDiskBase + Offset);
+ gInitRamDiskBase = (PVOID)((ULONG_PTR)gInitRamDiskBase + Offset);
}
PCSTR
diff --git a/boot/freeldr/freeldr/disk/ramdisk.c b/boot/freeldr/freeldr/disk/ramdisk.c
index 905c40941fa..78503649a49 100644
--- a/boot/freeldr/freeldr/disk/ramdisk.c
+++ b/boot/freeldr/freeldr/disk/ramdisk.c
@@ -1,51 +1,48 @@
/*
- * PROJECT: ReactOS Boot Loader
- * 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
- * PROGRAMMERS: ReactOS Portable Systems Group
- * Herv� Poussineau
+ * PROJECT: FreeLoader
+ * LICENSE: BSD - See COPYING.ARM in the top level directory
+ * PURPOSE: Implements routines to support booting from a RAM Disk.
+ * COPYRIGHT: Copyright 2008 ReactOS Portable Systems Group
+ * Copyright 2009 Hervé Poussineau
+ * Copyright 2019 Hermes Belusca-Maito
*/
/* INCLUDES *******************************************************************/
#include <freeldr.h>
-#include <debug.h>
-
/* GLOBALS ********************************************************************/
-PVOID gRamDiskBase;
-ULONG gRamDiskSize;
-ULONG gRamDiskOffset;
+PVOID gInitRamDiskBase = NULL;
+ULONG gInitRamDiskSize = 0;
+
+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 ******************************************************************/
static ARC_STATUS RamDiskClose(ULONG FileId)
{
- //
- // Nothing to do
- //
+ /* Nothing to do */
return ESUCCESS;
}
static ARC_STATUS RamDiskGetFileInformation(ULONG FileId, FILEINFORMATION* Information)
{
- //
- // Give current seek offset and ram disk size to caller
- //
RtlZeroMemory(Information, sizeof(*Information));
- Information->EndingAddress.LowPart = gRamDiskSize;
- Information->CurrentAddress.LowPart = gRamDiskOffset;
+ Information->EndingAddress.QuadPart = RamDiskImageLength;
+ Information->CurrentAddress.QuadPart = RamDiskOffset;
return ESUCCESS;
}
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;
}
@@ -53,24 +50,20 @@ static ARC_STATUS RamDiskRead(ULONG FileId, VOID* Buffer, ULONG N,
ULONG* Count)
{
PVOID StartAddress;
- //
- // Get actual pointer
- //
- StartAddress = (PVOID)((ULONG_PTR)gRamDiskBase + gRamDiskOffset);
-
- //
- // Don't allow reads past our image
- //
- if (gRamDiskOffset + N > gRamDiskSize)
+ /* Don't allow reads past our image */
+ if (RamDiskOffset >= RamDiskImageLength || RamDiskOffset + N >
RamDiskImageLength)
{
*Count = 0;
return EIO;
}
+ // N = min(N, RamdiskImageLength - RamDiskOffset);
- //
- // Do the read
- //
+ /* Get actual pointer */
+ StartAddress = (PVOID)((ULONG_PTR)RamDiskBase + RamDiskImageOffset +
(ULONG_PTR)RamDiskOffset);
+
+ /* Do the read */
RtlCopyMemory(Buffer, StartAddress, N);
+ RamDiskOffset += N;
*Count = N;
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)
{
- //
- // Only accept absolute mode now
- //
- if (SeekMode != SeekAbsolute)
- return EINVAL;
+ LARGE_INTEGER NewPosition = *Position;
- //
- // Check if we're in the ramdisk
- //
- if (Position->HighPart != 0)
- return EINVAL;
- if (Position->LowPart >= gRamDiskSize)
- return EINVAL;
+ switch (SeekMode)
+ {
+ case SeekAbsolute:
+ break;
+ case SeekRelative:
+ NewPosition.QuadPart += RamDiskOffset;
+ break;
+ default:
+ ASSERT(FALSE);
+ return EINVAL;
+ }
- //
- // OK, remember seek position
- //
- gRamDiskOffset = Position->LowPart;
+ if (NewPosition.QuadPart >= RamDiskImageLength)
+ return EINVAL;
+ RamDiskOffset = NewPosition.QuadPart;
return ESUCCESS;
}
-static const DEVVTBL RamDiskVtbl = {
+static const DEVVTBL RamDiskVtbl =
+{
RamDiskClose,
RamDiskGetFileInformation,
RamDiskOpen,
@@ -108,21 +101,15 @@ static const DEVVTBL RamDiskVtbl = {
RamDiskSeek,
};
-VOID
-RamDiskInitialize(VOID)
-{
- /* Register the RAMDISK device */
- FsRegisterDevice("ramdisk(0)", &RamDiskVtbl);
-}
-
-ARC_STATUS
+static ARC_STATUS
RamDiskLoadVirtualFile(
IN PCSTR FileName,
IN PCSTR DefaultPath OPTIONAL)
{
ARC_STATUS Status;
ULONG RamFileId;
- ULONG TotalRead, ChunkSize, Count;
+ ULONG ChunkSize, Count;
+ ULONGLONG TotalRead;
PCHAR MsgBuffer = "Loading RamDisk...";
ULONG PercentPerChunk, Percent;
FILEINFORMATION Information;
@@ -132,7 +119,7 @@ RamDiskLoadVirtualFile(
UiDrawBackdrop();
UiDrawProgressBarCenter(1, 100, MsgBuffer);
- /* Try opening the ramdisk file */
+ /* Try opening the Ramdisk file */
Status = FsOpenFile(FileName, DefaultPath, OpenReadOnly, &RamFileId);
if (Status != ESUCCESS)
return Status;
@@ -145,23 +132,24 @@ RamDiskLoadVirtualFile(
return Status;
}
- /* For now, limit RAM disks to 4GB */
+ /* FIXME: For now, limit RAM disks to 4GB */
if (Information.EndingAddress.HighPart != 0)
{
UiMessageBox("RAM disk too big.");
ArcClose(RamFileId);
return ENOMEM;
}
- gRamDiskSize = Information.EndingAddress.LowPart;
+ RamDiskFileSize = Information.EndingAddress.QuadPart;
+ ASSERT(RamDiskFileSize < 0x100000000); // See FIXME above.
/* Allocate memory for it */
ChunkSize = 8 * 1024 * 1024;
- if (gRamDiskSize < ChunkSize)
+ if (RamDiskFileSize < ChunkSize)
Percent = PercentPerChunk = 0;
else
- Percent = PercentPerChunk = 100 / (gRamDiskSize / ChunkSize);
- gRamDiskBase = MmAllocateMemoryWithType(gRamDiskSize, LoaderXIPRom);
- if (!gRamDiskBase)
+ Percent = PercentPerChunk = 100 / (RamDiskFileSize / ChunkSize);
+ RamDiskBase = MmAllocateMemoryWithType(RamDiskFileSize, LoaderXIPRom);
+ if (!RamDiskBase)
{
UiMessageBox("Failed to allocate memory for RAM disk.");
ArcClose(RamFileId);
@@ -171,13 +159,13 @@ RamDiskLoadVirtualFile(
/*
* 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 */
- if ((gRamDiskSize - TotalRead) < ChunkSize)
+ if ((RamDiskFileSize - TotalRead) < ChunkSize)
{
/* Only need the actual data required */
- ChunkSize = gRamDiskSize - TotalRead;
+ ChunkSize = (ULONG)(RamDiskFileSize - TotalRead);
}
/* Draw progress */
@@ -185,13 +173,12 @@ RamDiskLoadVirtualFile(
Percent += PercentPerChunk;
/* Copy the contents */
- Position.HighPart = 0;
- Position.LowPart = TotalRead;
+ Position.QuadPart = TotalRead;
Status = ArcSeek(RamFileId, &Position, SeekAbsolute);
if (Status == ESUCCESS)
{
Status = ArcRead(RamFileId,
- (PVOID)((ULONG_PTR)gRamDiskBase + TotalRead),
+ (PVOID)((ULONG_PTR)RamDiskBase + (ULONG_PTR)TotalRead),
ChunkSize,
&Count);
}
@@ -199,9 +186,9 @@ RamDiskLoadVirtualFile(
/* Check for success */
if ((Status != ESUCCESS) || (Count != ChunkSize))
{
- MmFreeMemory(gRamDiskBase);
- gRamDiskBase = NULL;
- gRamDiskSize = 0;
+ MmFreeMemory(RamDiskBase);
+ RamDiskBase = NULL;
+ RamDiskFileSize = 0;
ArcClose(RamFileId);
UiMessageBox("Failed to read RAM disk.");
return ((Status != ESUCCESS) ? Status : EIO);
@@ -210,8 +197,95 @@ RamDiskLoadVirtualFile(
ArcClose(RamFileId);
- /* Setup the RAMDISK device */
- RamDiskInitialize();
+ return ESUCCESS;
+}
+
+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;
}
diff --git a/boot/freeldr/freeldr/include/ramdisk.h
b/boot/freeldr/freeldr/include/ramdisk.h
index a9dd199feb2..c3d9740aa7f 100644
--- a/boot/freeldr/freeldr/include/ramdisk.h
+++ b/boot/freeldr/freeldr/include/ramdisk.h
@@ -1,23 +1,19 @@
/*
- * PROJECT: ReactOS Boot Loader
- * LICENSE: BSD - See COPYING.ARM in the top level directory
- * FILE: boot/freeldr/freeldr/include/ramdisk.h
- * PURPOSE: Header file for ramdisk support
- * PROGRAMMERS: ReactOS Portable Systems Group
+ * PROJECT: FreeLoader
+ * LICENSE: BSD - See COPYING.ARM in the top level directory
+ * PURPOSE: Header file for ramdisk support.
+ * COPYRIGHT: Copyright 2008 ReactOS Portable Systems Group
+ * Copyright 2009 Hervé Poussineau
+ * Copyright 2019 Hermes Belusca-Maito
*/
#pragma once
-//
-// Ramdisk Routines
-//
ARC_STATUS
-RamDiskLoadVirtualFile(
- IN PCSTR FileName,
+RamDiskInitialize(
+ IN BOOLEAN InitRamDisk,
+ IN PCSTR LoadOptions OPTIONAL,
IN PCSTR DefaultPath OPTIONAL);
-VOID
-RamDiskInitialize(VOID);
-
-extern PVOID gRamDiskBase;
-extern ULONG gRamDiskSize;
+extern PVOID gInitRamDiskBase;
+extern ULONG gInitRamDiskSize;
diff --git a/boot/freeldr/freeldr/ntldr/setupldr.c
b/boot/freeldr/freeldr/ntldr/setupldr.c
index 1d87f082b57..2010a2718db 100644
--- a/boot/freeldr/freeldr/ntldr/setupldr.c
+++ b/boot/freeldr/freeldr/ntldr/setupldr.c
@@ -284,17 +284,13 @@ LoadReactOSSetup(
File = strstr(BootOptions2, "/RDPATH=");
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 */
- Status = RamDiskLoadVirtualFile(FileName, SystemPartition);
+ Status = RamDiskInitialize(FALSE, BootOptions2, SystemPartition);
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;
}
}
@@ -323,7 +319,7 @@ LoadReactOSSetup(
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))
{
ERR("Failed to find 'SetupData/OsLoadOptions'\n");
diff --git a/boot/freeldr/freeldr/ntldr/winldr.c b/boot/freeldr/freeldr/ntldr/winldr.c
index 5eeff108e55..bf1d0658f45 100644
--- a/boot/freeldr/freeldr/ntldr/winldr.c
+++ b/boot/freeldr/freeldr/ntldr/winldr.c
@@ -731,9 +731,9 @@ LoadAndBootWindows(
BOOLEAN Success;
USHORT OperatingSystemVersion;
PLOADER_PARAMETER_BLOCK LoaderBlock;
- CHAR BootPath[MAX_PATH];
- CHAR FileName[MAX_PATH];
- CHAR BootOptions[256];
+ CHAR BootPath[MAX_PATH];
+ CHAR FileName[MAX_PATH];
+ CHAR BootOptions[256];
/* Retrieve the (mandatory) boot type */
ArgValue = GetArgumentValue(Argc, Argv, "BootType");
@@ -852,17 +852,13 @@ LoadAndBootWindows(
File = strstr(BootOptions, "/RDPATH=");
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 */
- Status = RamDiskLoadVirtualFile(FileName, SystemPartition);
+ Status = RamDiskInitialize(FALSE, BootOptions, SystemPartition);
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;
}
}