ReactOS  0.4.15-dev-4871-g4471ee4
ramdisk.c
Go to the documentation of this file.
1 /*
2  * PROJECT: FreeLoader
3  * LICENSE: BSD - See COPYING.ARM in the top level directory
4  * PURPOSE: Implements routines to support booting from a RAM Disk.
5  * COPYRIGHT: Copyright 2008 ReactOS Portable Systems Group
6  * Copyright 2009 HervĂ© Poussineau
7  * Copyright 2019 Hermes Belusca-Maito
8  */
9 
10 /* INCLUDES *******************************************************************/
11 
12 #include <freeldr.h>
13 #include "../ntldr/ntldropts.h"
14 
15 /* GLOBALS ********************************************************************/
16 
19 
22 static ULONGLONG RamDiskFileSize; // FIXME: RAM disks currently limited to 4GB.
23 static ULONGLONG RamDiskImageLength; // Size of valid data in the Ramdisk (usually == RamDiskFileSize - RamDiskImageOffset)
24 static ULONG RamDiskImageOffset; // Starting offset from the Ramdisk base.
25 static ULONGLONG RamDiskOffset; // Current position in the Ramdisk.
26 
27 /* FUNCTIONS ******************************************************************/
28 
30 {
31  /* Nothing to do */
32  return ESUCCESS;
33 }
34 
36 {
38  Information->EndingAddress.QuadPart = RamDiskImageLength;
39  Information->CurrentAddress.QuadPart = RamDiskOffset;
40 
41  return ESUCCESS;
42 }
43 
44 static ARC_STATUS RamDiskOpen(CHAR* Path, OPENMODE OpenMode, ULONG* FileId)
45 {
46  /* Always return success, as contents are already in memory */
47  return ESUCCESS;
48 }
49 
51 {
52  PVOID StartAddress;
53 
54  /* Don't allow reads past our image */
56  {
57  *Count = 0;
58  return EIO;
59  }
60  // N = min(N, RamdiskImageLength - RamDiskOffset);
61 
62  /* Get actual pointer */
64 
65  /* Do the read */
66  RtlCopyMemory(Buffer, StartAddress, N);
67  RamDiskOffset += N;
68  *Count = N;
69 
70  return ESUCCESS;
71 }
72 
74 {
75  LARGE_INTEGER NewPosition = *Position;
76 
77  switch (SeekMode)
78  {
79  case SeekAbsolute:
80  break;
81  case SeekRelative:
82  NewPosition.QuadPart += RamDiskOffset;
83  break;
84  default:
85  ASSERT(FALSE);
86  return EINVAL;
87  }
88 
89  if (NewPosition.QuadPart >= RamDiskImageLength)
90  return EINVAL;
91 
92  RamDiskOffset = NewPosition.QuadPart;
93  return ESUCCESS;
94 }
95 
96 static const DEVVTBL RamDiskVtbl =
97 {
100  RamDiskOpen,
101  RamDiskRead,
102  RamDiskSeek,
103 };
104 
105 static ARC_STATUS
107  IN PCSTR FileName,
108  IN PCSTR DefaultPath OPTIONAL)
109 {
111  ULONG RamFileId;
113  ULONGLONG TotalRead;
114  ULONG PercentPerChunk, Percent;
117 
118  /* Display progress */
119  UiDrawProgressBarCenter("Loading RamDisk...");
120 
121  /* Try opening the Ramdisk file */
122  Status = FsOpenFile(FileName, DefaultPath, OpenReadOnly, &RamFileId);
123  if (Status != ESUCCESS)
124  return Status;
125 
126  /* Get the file size */
128  if (Status != ESUCCESS)
129  {
130  ArcClose(RamFileId);
131  return Status;
132  }
133 
134  /* FIXME: For now, limit RAM disks to 4GB */
135  if (Information.EndingAddress.HighPart != 0)
136  {
137  ArcClose(RamFileId);
138  UiMessageBox("RAM disk too big.");
139  return ENOMEM;
140  }
141  RamDiskFileSize = Information.EndingAddress.QuadPart;
142  ASSERT(RamDiskFileSize < 0x100000000); // See FIXME above.
143 
144  /* Allocate memory for it */
145  ChunkSize = 8 * 1024 * 1024;
147  PercentPerChunk = 0;
148  else
149  PercentPerChunk = 100 * ChunkSize / RamDiskFileSize;
151  if (!RamDiskBase)
152  {
153  RamDiskFileSize = 0;
154  ArcClose(RamFileId);
155  UiMessageBox("Failed to allocate memory for RAM disk.");
156  return ENOMEM;
157  }
158 
159  /*
160  * Read it in chunks
161  */
162  Percent = 0;
163  for (TotalRead = 0; TotalRead < RamDiskFileSize; TotalRead += ChunkSize)
164  {
165  /* Check if we're at the last chunk */
166  if ((RamDiskFileSize - TotalRead) < ChunkSize)
167  {
168  /* Only need the actual data required */
169  ChunkSize = (ULONG)(RamDiskFileSize - TotalRead);
170  }
171 
172  /* Update progress */
173  UiUpdateProgressBar(Percent, NULL);
174  Percent += PercentPerChunk;
175 
176  /* Copy the contents */
177  Position.QuadPart = TotalRead;
178  Status = ArcSeek(RamFileId, &Position, SeekAbsolute);
179  if (Status == ESUCCESS)
180  {
181  Status = ArcRead(RamFileId,
182  (PVOID)((ULONG_PTR)RamDiskBase + (ULONG_PTR)TotalRead),
183  ChunkSize,
184  &Count);
185  }
186 
187  /* Check for success */
188  if ((Status != ESUCCESS) || (Count != ChunkSize))
189  {
191  RamDiskBase = NULL;
192  RamDiskFileSize = 0;
193  ArcClose(RamFileId);
194  UiMessageBox("Failed to read RAM disk.");
195  return ((Status != ESUCCESS) ? Status : EIO);
196  }
197  }
199 
200  ArcClose(RamFileId);
201 
202  return ESUCCESS;
203 }
204 
207  IN BOOLEAN InitRamDisk,
208  IN PCSTR LoadOptions OPTIONAL,
209  IN PCSTR DefaultPath OPTIONAL)
210 {
211  /* Reset the RAMDISK device */
212  if ((RamDiskBase != gInitRamDiskBase) &&
214  (gInitRamDiskSize != 0))
215  {
216  /* This is not the initial Ramdisk, so we can free the allocated memory */
218  }
219  RamDiskBase = NULL;
220  RamDiskFileSize = 0;
221  RamDiskImageLength = 0;
222  RamDiskImageOffset = 0;
223  RamDiskOffset = 0;
224 
225  if (InitRamDisk)
226  {
227  /* We initialize the initial Ramdisk: it should be present in memory */
228  if (!gInitRamDiskBase || gInitRamDiskSize == 0)
229  return ENODEV;
230 
231  // TODO: Handle SDI image.
232 
235  ASSERT(RamDiskFileSize < 0x100000000); // See FIXME about 4GB support in RamDiskLoadVirtualFile().
236  }
237  else
238  {
239  /* We initialize the Ramdisk from the load options */
241  CHAR FileName[MAX_PATH] = "";
242 
243  /* If we don't have any load options, initialize an empty Ramdisk */
244  if (LoadOptions)
245  {
246  PCSTR Option;
248 
249  /* Ramdisk image file name */
250  Option = NtLdrGetOptionEx(LoadOptions, "RDPATH=", &FileNameLength);
251  if (Option && (FileNameLength > 7))
252  {
253  /* Copy the file name */
254  Option += 7; FileNameLength -= 7;
256  Option, FileNameLength * sizeof(CHAR));
257  }
258 
259  /* Ramdisk image length */
260  Option = NtLdrGetOption(LoadOptions, "RDIMAGELENGTH=");
261  if (Option)
262  {
263  RamDiskImageLength = _atoi64(Option + 14);
264  }
265 
266  /* Ramdisk image offset */
267  Option = NtLdrGetOption(LoadOptions, "RDIMAGEOFFSET=");
268  if (Option)
269  {
270  RamDiskImageOffset = atol(Option + 14);
271  }
272  }
273 
274  if (*FileName)
275  {
276  Status = RamDiskLoadVirtualFile(FileName, DefaultPath);
277  if (Status != ESUCCESS)
278  return Status;
279  }
280  }
281 
282  /* Adjust the Ramdisk image length if needed */
285 
286  /* Register the RAMDISK device */
288  {
289  FsRegisterDevice("ramdisk(0)", &RamDiskVtbl);
291  }
292 
293  return ESUCCESS;
294 }
VOID UiUpdateProgressBar(_In_ ULONG Percentage, _In_opt_ PCSTR ProgressText)
Definition: ui.c:462
static ULONG RamDiskImageOffset
Definition: ramdisk.c:24
#define IN
Definition: typedefs.h:39
NTSTRSAFEAPI RtlStringCbCopyNA(_Out_writes_bytes_(cbDest) NTSTRSAFE_PSTR pszDest, _In_ size_t cbDest, _In_reads_bytes_(cbToCopy) STRSAFE_LPCSTR pszSrc, _In_ size_t cbToCopy)
Definition: ntstrsafe.h:395
ARC_STATUS RamDiskInitialize(IN BOOLEAN InitRamDisk, IN PCSTR LoadOptions OPTIONAL, IN PCSTR DefaultPath OPTIONAL)
Definition: ramdisk.c:206
static ARC_STATUS RamDiskClose(ULONG FileId)
Definition: ramdisk.c:29
Definition: arc.h:32
static BOOLEAN RamDiskDeviceRegistered
Definition: ramdisk.c:20
__MINGW_EXTENSION _Check_return_ _CRTIMP __int64 __cdecl _atoi64(_In_z_ const char *_String)
#define TRUE
Definition: types.h:120
Definition: arc.h:39
static COORD Position
Definition: mouse.c:34
char CHAR
Definition: xmlstorage.h:175
Definition: fs.h:24
ULONG ARC_STATUS
Definition: arc.h:4
ARC_STATUS FsOpenFile(IN PCSTR FileName, IN PCSTR DefaultPath OPTIONAL, IN OPENMODE OpenMode, OUT PULONG FileId)
Definition: fs.c:266
static const DEVVTBL RamDiskVtbl
Definition: ramdisk.c:96
_In_ WDFREQUEST _In_ NTSTATUS _In_ ULONG_PTR Information
Definition: wdfrequest.h:1044
Definition: arc.h:48
uint32_t ULONG_PTR
Definition: typedefs.h:65
static ULONGLONG RamDiskOffset
Definition: ramdisk.c:25
#define FALSE
Definition: types.h:117
_Inout_ PUCHAR _In_ PUCHAR _Out_ PUCHAR _Out_ PULONG ChunkSize
Definition: rtlfuncs.h:2274
VOID UiMessageBox(PCSTR Format,...)
Definition: ui.c:363
unsigned char BOOLEAN
VOID UiDrawProgressBarCenter(_In_ PCSTR ProgressText)
Definition: ui.c:503
enum _SEEKMODE SEEKMODE
Definition: bufpool.h:45
void * PVOID
Definition: retypes.h:9
static ARC_STATUS RamDiskGetFileInformation(ULONG FileId, FILEINFORMATION *Information)
Definition: ramdisk.c:35
Status
Definition: gdiplustypes.h:24
int Count
Definition: noreturn.cpp:7
static ARC_STATUS RamDiskOpen(CHAR *Path, OPENMODE OpenMode, ULONG *FileId)
Definition: ramdisk.c:44
#define ASSERT(a)
Definition: mode.c:44
uint64_t ULONGLONG
Definition: typedefs.h:67
static ARC_STATUS RamDiskRead(ULONG FileId, VOID *Buffer, ULONG N, ULONG *Count)
Definition: ramdisk.c:50
#define MAX_PATH
Definition: compat.h:34
ULONG gInitRamDiskSize
Definition: ramdisk.c:18
_Check_return_ long __cdecl atol(_In_z_ const char *_Str)
ARC_STATUS ArcRead(ULONG FileId, VOID *Buffer, ULONG N, ULONG *Count)
Definition: fs.c:236
VOID FsRegisterDevice(CHAR *Prefix, const DEVVTBL *FuncTable)
Definition: fs.c:383
PVOID MmAllocateMemoryWithType(SIZE_T MemorySize, TYPE_OF_MEMORY MemoryType)
Definition: mm.c:31
ARC_STATUS ArcSeek(ULONG FileId, LARGE_INTEGER *Position, SEEKMODE SeekMode)
Definition: fs.c:243
_Must_inspect_result_ _In_ PFILE_OBJECT _In_opt_ HANDLE _In_ ULONG FileNameLength
Definition: fltkernel.h:1129
VOID MmFreeMemory(PVOID MemoryPointer)
Definition: mm.c:215
static ULONGLONG RamDiskImageLength
Definition: ramdisk.c:23
Definition: arc.h:45
PCSTR NtLdrGetOption(IN PCSTR Options, IN PCSTR OptionName)
Definition: ntldropts.c:128
PRTL_UNICODE_STRING_BUFFER Path
static ARC_STATUS RamDiskSeek(ULONG FileId, LARGE_INTEGER *Position, SEEKMODE SeekMode)
Definition: ramdisk.c:73
#define NULL
Definition: types.h:112
Definition: arc.h:40
static ULONGLONG RamDiskFileSize
Definition: ramdisk.c:22
ARC_STATUS ArcClose(ULONG FileId)
Definition: fs.c:218
ARC_STATUS ArcGetFileInformation(ULONG FileId, FILEINFORMATION *Information)
Definition: fs.c:250
unsigned int ULONG
Definition: retypes.h:1
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define ULONG_PTR
Definition: config.h:101
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
static ARC_STATUS RamDiskLoadVirtualFile(IN PCSTR FileName, IN PCSTR DefaultPath OPTIONAL)
Definition: ramdisk.c:106
const char * PCSTR
Definition: typedefs.h:52
PVOID gInitRamDiskBase
Definition: ramdisk.c:17
enum _OPENMODE OPENMODE
PCSTR NtLdrGetOptionEx(IN PCSTR Options, IN PCSTR OptionName, OUT PULONG OptionLength OPTIONAL)
Definition: ntldropts.c:117
static PVOID RamDiskBase
Definition: ramdisk.c:21
LONGLONG QuadPart
Definition: typedefs.h:114
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68