ReactOS  0.4.15-dev-3163-gf17c2c0
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  PCHAR MsgBuffer = "Loading RamDisk...";
115  ULONG PercentPerChunk, Percent;
118 
119  /* Display progress */
120  UiDrawBackdrop();
121  UiDrawProgressBarCenter(1, 100, MsgBuffer);
122 
123  /* Try opening the Ramdisk file */
124  Status = FsOpenFile(FileName, DefaultPath, OpenReadOnly, &RamFileId);
125  if (Status != ESUCCESS)
126  return Status;
127 
128  /* Get the file size */
130  if (Status != ESUCCESS)
131  {
132  ArcClose(RamFileId);
133  return Status;
134  }
135 
136  /* FIXME: For now, limit RAM disks to 4GB */
137  if (Information.EndingAddress.HighPart != 0)
138  {
139  UiMessageBox("RAM disk too big.");
140  ArcClose(RamFileId);
141  return ENOMEM;
142  }
143  RamDiskFileSize = Information.EndingAddress.QuadPart;
144  ASSERT(RamDiskFileSize < 0x100000000); // See FIXME above.
145 
146  /* Allocate memory for it */
147  ChunkSize = 8 * 1024 * 1024;
149  Percent = PercentPerChunk = 0;
150  else
151  Percent = PercentPerChunk = 100 / (RamDiskFileSize / ChunkSize);
153  if (!RamDiskBase)
154  {
155  UiMessageBox("Failed to allocate memory for RAM disk.");
156  ArcClose(RamFileId);
157  return ENOMEM;
158  }
159 
160  /*
161  * Read it in chunks
162  */
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  /* Draw progress */
173  UiDrawProgressBarCenter(Percent, 100, MsgBuffer);
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  }
198 
199  ArcClose(RamFileId);
200 
201  return ESUCCESS;
202 }
203 
206  IN BOOLEAN InitRamDisk,
207  IN PCSTR LoadOptions OPTIONAL,
208  IN PCSTR DefaultPath OPTIONAL)
209 {
210  /* Reset the RAMDISK device */
211  if ((RamDiskBase != gInitRamDiskBase) &&
213  (gInitRamDiskSize != 0))
214  {
215  /* This is not the initial Ramdisk, so we can free the allocated memory */
217  }
218  RamDiskBase = NULL;
219  RamDiskFileSize = 0;
220  RamDiskImageLength = 0;
221  RamDiskImageOffset = 0;
222  RamDiskOffset = 0;
223 
224  if (InitRamDisk)
225  {
226  /* We initialize the initial Ramdisk: it should be present in memory */
227  if (!gInitRamDiskBase || gInitRamDiskSize == 0)
228  return ENODEV;
229 
230  // TODO: Handle SDI image.
231 
234  ASSERT(RamDiskFileSize < 0x100000000); // See FIXME about 4GB support in RamDiskLoadVirtualFile().
235  }
236  else
237  {
238  /* We initialize the Ramdisk from the load options */
240  CHAR FileName[MAX_PATH] = "";
241 
242  /* If we don't have any load options, initialize an empty Ramdisk */
243  if (LoadOptions)
244  {
245  PCSTR Option;
247 
248  /* Ramdisk image file name */
249  Option = NtLdrGetOptionEx(LoadOptions, "RDPATH=", &FileNameLength);
250  if (Option && (FileNameLength > 7))
251  {
252  /* Copy the file name */
253  Option += 7; FileNameLength -= 7;
255  Option, FileNameLength * sizeof(CHAR));
256  }
257 
258  /* Ramdisk image length */
259  Option = NtLdrGetOption(LoadOptions, "RDIMAGELENGTH=");
260  if (Option)
261  {
262  RamDiskImageLength = _atoi64(Option + 14);
263  }
264 
265  /* Ramdisk image offset */
266  Option = NtLdrGetOption(LoadOptions, "RDIMAGEOFFSET=");
267  if (Option)
268  {
269  RamDiskImageOffset = atol(Option + 14);
270  }
271  }
272 
273  if (*FileName)
274  {
275  Status = RamDiskLoadVirtualFile(FileName, DefaultPath);
276  if (Status != ESUCCESS)
277  return Status;
278  }
279  }
280 
281  /* Adjust the Ramdisk image length if needed */
284 
285  /* Register the RAMDISK device */
287  {
288  FsRegisterDevice("ramdisk(0)", &RamDiskVtbl);
290  }
291 
292  return ESUCCESS;
293 }
signed char * PCHAR
Definition: retypes.h:7
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:205
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:320
unsigned char BOOLEAN
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
VOID UiDrawBackdrop(VOID)
Definition: ui.c:214
_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
VOID UiDrawProgressBarCenter(ULONG Position, ULONG Range, PCHAR ProgressText)
Definition: ui.c:346
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68