ReactOS  0.4.14-dev-57-g333b8f1
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 
14 /* GLOBALS ********************************************************************/
15 
18 
21 static ULONGLONG RamDiskFileSize; // FIXME: RAM disks currently limited to 4GB.
22 static ULONGLONG RamDiskImageLength; // Size of valid data in the Ramdisk (usually == RamDiskFileSize - RamDiskImageOffset)
23 static ULONG RamDiskImageOffset; // Starting offset from the Ramdisk base.
24 static ULONGLONG RamDiskOffset; // Current position in the Ramdisk.
25 
26 /* FUNCTIONS ******************************************************************/
27 
29 {
30  /* Nothing to do */
31  return ESUCCESS;
32 }
33 
35 {
37  Information->EndingAddress.QuadPart = RamDiskImageLength;
38  Information->CurrentAddress.QuadPart = RamDiskOffset;
39 
40  return ESUCCESS;
41 }
42 
43 static ARC_STATUS RamDiskOpen(CHAR* Path, OPENMODE OpenMode, ULONG* FileId)
44 {
45  /* Always return success, as contents are already in memory */
46  return ESUCCESS;
47 }
48 
50 {
51  PVOID StartAddress;
52 
53  /* Don't allow reads past our image */
55  {
56  *Count = 0;
57  return EIO;
58  }
59  // N = min(N, RamdiskImageLength - RamDiskOffset);
60 
61  /* Get actual pointer */
63 
64  /* Do the read */
65  RtlCopyMemory(Buffer, StartAddress, N);
66  RamDiskOffset += N;
67  *Count = N;
68 
69  return ESUCCESS;
70 }
71 
73 {
74  LARGE_INTEGER NewPosition = *Position;
75 
76  switch (SeekMode)
77  {
78  case SeekAbsolute:
79  break;
80  case SeekRelative:
81  NewPosition.QuadPart += RamDiskOffset;
82  break;
83  default:
84  ASSERT(FALSE);
85  return EINVAL;
86  }
87 
88  if (NewPosition.QuadPart >= RamDiskImageLength)
89  return EINVAL;
90 
91  RamDiskOffset = NewPosition.QuadPart;
92  return ESUCCESS;
93 }
94 
95 static const DEVVTBL RamDiskVtbl =
96 {
100  RamDiskRead,
101  RamDiskSeek,
102 };
103 
104 static ARC_STATUS
106  IN PCSTR FileName,
107  IN PCSTR DefaultPath OPTIONAL)
108 {
110  ULONG RamFileId;
112  ULONGLONG TotalRead;
113  PCHAR MsgBuffer = "Loading RamDisk...";
114  ULONG PercentPerChunk, Percent;
117 
118  /* Display progress */
119  UiDrawBackdrop();
120  UiDrawProgressBarCenter(1, 100, MsgBuffer);
121 
122  /* Try opening the Ramdisk file */
123  Status = FsOpenFile(FileName, DefaultPath, OpenReadOnly, &RamFileId);
124  if (Status != ESUCCESS)
125  return Status;
126 
127  /* Get the file size */
129  if (Status != ESUCCESS)
130  {
131  ArcClose(RamFileId);
132  return Status;
133  }
134 
135  /* FIXME: For now, limit RAM disks to 4GB */
136  if (Information.EndingAddress.HighPart != 0)
137  {
138  UiMessageBox("RAM disk too big.");
139  ArcClose(RamFileId);
140  return ENOMEM;
141  }
142  RamDiskFileSize = Information.EndingAddress.QuadPart;
143  ASSERT(RamDiskFileSize < 0x100000000); // See FIXME above.
144 
145  /* Allocate memory for it */
146  ChunkSize = 8 * 1024 * 1024;
148  Percent = PercentPerChunk = 0;
149  else
150  Percent = PercentPerChunk = 100 / (RamDiskFileSize / ChunkSize);
152  if (!RamDiskBase)
153  {
154  UiMessageBox("Failed to allocate memory for RAM disk.");
155  ArcClose(RamFileId);
156  return ENOMEM;
157  }
158 
159  /*
160  * Read it in chunks
161  */
162  for (TotalRead = 0; TotalRead < RamDiskFileSize; TotalRead += ChunkSize)
163  {
164  /* Check if we're at the last chunk */
165  if ((RamDiskFileSize - TotalRead) < ChunkSize)
166  {
167  /* Only need the actual data required */
168  ChunkSize = (ULONG)(RamDiskFileSize - TotalRead);
169  }
170 
171  /* Draw progress */
172  UiDrawProgressBarCenter(Percent, 100, MsgBuffer);
173  Percent += PercentPerChunk;
174 
175  /* Copy the contents */
176  Position.QuadPart = TotalRead;
177  Status = ArcSeek(RamFileId, &Position, SeekAbsolute);
178  if (Status == ESUCCESS)
179  {
180  Status = ArcRead(RamFileId,
181  (PVOID)((ULONG_PTR)RamDiskBase + (ULONG_PTR)TotalRead),
182  ChunkSize,
183  &Count);
184  }
185 
186  /* Check for success */
187  if ((Status != ESUCCESS) || (Count != ChunkSize))
188  {
190  RamDiskBase = NULL;
191  RamDiskFileSize = 0;
192  ArcClose(RamFileId);
193  UiMessageBox("Failed to read RAM disk.");
194  return ((Status != ESUCCESS) ? Status : EIO);
195  }
196  }
197 
198  ArcClose(RamFileId);
199 
200  return ESUCCESS;
201 }
202 
205  IN BOOLEAN InitRamDisk,
206  IN PCSTR LoadOptions OPTIONAL,
207  IN PCSTR DefaultPath OPTIONAL)
208 {
209  /* Reset the RAMDISK device */
210  if ((RamDiskBase != gInitRamDiskBase) &&
212  (gInitRamDiskSize != 0))
213  {
214  /* This is not the initial Ramdisk, so we can free the allocated memory */
216  }
217  RamDiskBase = NULL;
218  RamDiskFileSize = 0;
219  RamDiskImageLength = 0;
220  RamDiskImageOffset = 0;
221  RamDiskOffset = 0;
222 
223  if (InitRamDisk)
224  {
225  /* We initialize the initial Ramdisk: it should be present in memory */
226  if (!gInitRamDiskBase || gInitRamDiskSize == 0)
227  return ENODEV;
228 
229  // TODO: Handle SDI image.
230 
233  ASSERT(RamDiskFileSize < 0x100000000); // See FIXME about 4GB support in RamDiskLoadVirtualFile().
234  }
235  else
236  {
237  /* We initialize the Ramdisk from the load options */
239  CHAR FileName[MAX_PATH] = "";
240 
241  /* If we don't have any load options, initialize an empty Ramdisk */
242  if (LoadOptions)
243  {
244  PCHAR Option;
245 
246  /* Ramdisk image file name */
247  Option = strstr(LoadOptions, "/RDPATH=");
248  if (Option)
249  {
250  /* Copy the file name - everything until the next separator */
251  Option += 8;
253  Option, strcspn(Option, " \t") * sizeof(CHAR));
254  }
255 
256  /* Ramdisk image length */
257  Option = strstr(LoadOptions, "/RDIMAGELENGTH=");
258  if (Option)
259  {
260  RamDiskImageLength = _atoi64(Option + 15);
261  }
262 
263  /* Ramdisk image offset */
264  Option = strstr(LoadOptions, "/RDIMAGEOFFSET=");
265  if (Option)
266  {
267  RamDiskImageOffset = atol(Option + 15);
268  }
269  }
270 
271  if (*FileName)
272  {
273  Status = RamDiskLoadVirtualFile(FileName, DefaultPath);
274  if (Status != ESUCCESS)
275  return Status;
276  }
277  }
278 
279  /* Adjust the Ramdisk image length if needed */
282 
283  /* Register the RAMDISK device */
285  {
286  FsRegisterDevice("ramdisk(0)", &RamDiskVtbl);
288  }
289 
290  return ESUCCESS;
291 }
signed char * PCHAR
Definition: retypes.h:7
static ULONG RamDiskImageOffset
Definition: ramdisk.c:23
#define IN
Definition: typedefs.h:38
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:204
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
static ARC_STATUS RamDiskClose(ULONG FileId)
Definition: ramdisk.c:28
Definition: arc.h:32
static BOOLEAN RamDiskDeviceRegistered
Definition: ramdisk.c:19
char * strstr(char *String1, char *String2)
Definition: utclib.c:653
_Check_return_ _CRTIMP size_t __cdecl strcspn(_In_z_ const char *_Str, _In_z_ const char *_Control)
Definition: arc.h:39
static COORD Position
Definition: mouse.c:34
char CHAR
Definition: xmlstorage.h:175
Definition: fs.h:24
_Inout_ __drv_aliasesMem PSLIST_ENTRY _Inout_ PSLIST_ENTRY _In_ ULONG Count
Definition: exfuncs.h:1015
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:95
Definition: arc.h:48
uint32_t ULONG_PTR
Definition: typedefs.h:63
static ULONGLONG RamDiskOffset
Definition: ramdisk.c:24
_Inout_ PUCHAR _In_ PUCHAR _Out_ PUCHAR _Out_ PULONG ChunkSize
Definition: rtlfuncs.h:2276
VOID UiMessageBox(PCSTR Format,...)
Definition: ui.c:320
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
enum _SEEKMODE SEEKMODE
Definition: bufpool.h:45
void * PVOID
Definition: retypes.h:9
static ARC_STATUS RamDiskGetFileInformation(ULONG FileId, FILEINFORMATION *Information)
Definition: ramdisk.c:34
static ARC_STATUS RamDiskOpen(CHAR *Path, OPENMODE OpenMode, ULONG *FileId)
Definition: ramdisk.c:43
uint64_t ULONGLONG
Definition: typedefs.h:65
static ARC_STATUS RamDiskRead(ULONG FileId, VOID *Buffer, ULONG N, ULONG *Count)
Definition: ramdisk.c:49
#define MAX_PATH
Definition: compat.h:26
ULONG gInitRamDiskSize
Definition: ramdisk.c:17
_Check_return_ long __cdecl atol(_In_z_ const char *_Str)
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
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
Status
Definition: gdiplustypes.h:24
VOID MmFreeMemory(PVOID MemoryPointer)
Definition: mm.c:215
static ULONGLONG RamDiskImageLength
Definition: ramdisk.c:22
Definition: arc.h:45
PRTL_UNICODE_STRING_BUFFER Path
static ARC_STATUS RamDiskSeek(ULONG FileId, LARGE_INTEGER *Position, SEEKMODE SeekMode)
Definition: ramdisk.c:72
_Check_return_ __MINGW_EXTENSION _CRTIMP __int64 __cdecl _atoi64(_In_z_ const char *_String)
Definition: arc.h:40
static ULONGLONG RamDiskFileSize
Definition: ramdisk.c:21
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:261
#define ULONG_PTR
Definition: config.h:101
static ARC_STATUS RamDiskLoadVirtualFile(IN PCSTR FileName, IN PCSTR DefaultPath OPTIONAL)
Definition: ramdisk.c:105
const char * PCSTR
Definition: typedefs.h:51
PVOID gInitRamDiskBase
Definition: ramdisk.c:16
enum _OPENMODE OPENMODE
static PVOID RamDiskBase
Definition: ramdisk.c:20
Iosb Information
Definition: create.c:4377
LONGLONG QuadPart
Definition: typedefs.h:112
VOID UiDrawProgressBarCenter(ULONG Position, ULONG Range, PCHAR ProgressText)
Definition: ui.c:346
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68