ReactOS 0.4.16-dev-1875-g3000d45
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#include <debug.h>
17
18/* GLOBALS ********************************************************************/
19
22
25static ULONGLONG RamDiskFileSize; // FIXME: RAM disks currently limited to 4GB.
26static ULONGLONG RamDiskImageLength; // Size of valid data in the Ramdisk (usually == RamDiskFileSize - RamDiskImageOffset)
27static ULONG RamDiskImageOffset; // Starting offset from the Ramdisk base.
28static ULONGLONG RamDiskOffset; // Current position in the Ramdisk.
29
30/* FUNCTIONS ******************************************************************/
31
33{
34 /* Nothing to do */
35 return ESUCCESS;
36}
37
39{
41 Information->EndingAddress.QuadPart = RamDiskImageLength;
42 Information->CurrentAddress.QuadPart = RamDiskOffset;
44
45 return ESUCCESS;
46}
47
48static ARC_STATUS RamDiskOpen(CHAR* Path, OPENMODE OpenMode, ULONG* FileId)
49{
50 /* Always return success, as contents are already in memory */
51 return ESUCCESS;
52}
53
55{
56 PVOID StartAddress;
57
58 /* Don't allow reads past our image */
60 {
61 *Count = 0;
62 return EIO;
63 }
64 // N = min(N, RamdiskImageLength - RamDiskOffset);
65
66 /* Get actual pointer */
68
69 /* Do the read */
70 RtlCopyMemory(Buffer, StartAddress, N);
72 *Count = N;
73
74 return ESUCCESS;
75}
76
78{
79 LARGE_INTEGER NewPosition = *Position;
80
81 switch (SeekMode)
82 {
83 case SeekAbsolute:
84 break;
85 case SeekRelative:
86 NewPosition.QuadPart += RamDiskOffset;
87 break;
88 default:
90 return EINVAL;
91 }
92
93 if (NewPosition.QuadPart >= RamDiskImageLength)
94 return EINVAL;
95
96 RamDiskOffset = NewPosition.QuadPart;
97 return ESUCCESS;
98}
99
100static const DEVVTBL RamDiskVtbl =
101{
107};
108
109static ARC_STATUS
112 IN PCSTR DefaultPath OPTIONAL)
113{
115 ULONG RamFileId;
117 ULONGLONG TotalRead;
118 ULONG PercentPerChunk, Percent;
121
122 /* Display progress */
123 UiDrawProgressBarCenter("Loading RamDisk...");
124
125 /* Try opening the Ramdisk file */
126 TRACE("RamDiskLoadVirtualFile: Opening '%s', '%s'\n",
127 FileName, DefaultPath ? DefaultPath : "n/a");
128 Status = FsOpenFile(FileName, DefaultPath, OpenReadOnly, &RamFileId);
129 if (Status != ESUCCESS)
130 return Status;
131
132 /* Get the file size */
134 if (Status != ESUCCESS)
135 {
136 ArcClose(RamFileId);
137 return Status;
138 }
139 /* NOTE: For partitions, StartingAddress/EndingAddress are the start/end
140 * positions of the partition as byte offsets from the start of the disk */
141 Information.EndingAddress.QuadPart -= Information.StartingAddress.QuadPart;
142 Information.StartingAddress.QuadPart = 0ULL;
143
144 TRACE("RAMDISK size: %I64u (High: %lu ; Low: %lu)\n",
145 Information.EndingAddress.QuadPart,
146 Information.EndingAddress.HighPart,
147 Information.EndingAddress.LowPart);
148
149 /* FIXME: For now, limit RAM disks to 4GB */
150 if (Information.EndingAddress.HighPart != 0) // (RamDiskFileSize >= 0x100000000ULL)
151 {
152 ArcClose(RamFileId);
153 UiMessageBox("RAM disk too big.");
154 return ENOMEM;
155 }
156 RamDiskFileSize = Information.EndingAddress.QuadPart;
157
158 /* Allocate memory for it */
159 ChunkSize = 8 * 1024 * 1024;
161 PercentPerChunk = 0;
162 else
163 PercentPerChunk = 100 * ChunkSize / RamDiskFileSize;
165 if (!RamDiskBase)
166 {
167 RamDiskFileSize = 0;
168 ArcClose(RamFileId);
169 UiMessageBox("Failed to allocate memory for RAM disk.");
170 return ENOMEM;
171 }
172
173 /*
174 * Read it in chunks, starting at the beginning
175 */
176 Position.QuadPart = 0;
177 Status = ArcSeek(RamFileId, &Position, SeekAbsolute);
178 if (Status != ESUCCESS)
179 goto ReadFailure;
180
181 for (TotalRead = 0, Percent = 0;
182 TotalRead < RamDiskFileSize;
183 TotalRead += ChunkSize, Percent += PercentPerChunk)
184 {
185 /* If we are at the last chunk, read only what's remaining */
186 if ((RamDiskFileSize - TotalRead) < ChunkSize)
187 ChunkSize = (ULONG)(RamDiskFileSize - TotalRead);
188
189 /* Update progress */
190 UiUpdateProgressBar(Percent, NULL);
191
192 /* Copy the data */
193 Status = ArcRead(RamFileId,
194 (PVOID)((ULONG_PTR)RamDiskBase + (ULONG_PTR)TotalRead),
195 ChunkSize,
196 &Count);
197 if ((Status != ESUCCESS) || (Count != ChunkSize))
198 {
199 Status = ((Status != ESUCCESS) ? Status : EIO);
200 goto ReadFailure;
201 }
202 }
204 ArcClose(RamFileId);
205 return ESUCCESS;
206
207ReadFailure:
210 RamDiskFileSize = 0;
211 ArcClose(RamFileId);
212 UiMessageBox("Failed to read RAM disk.");
213 return Status;
214}
215
218 IN BOOLEAN InitRamDisk,
219 IN PCSTR LoadOptions OPTIONAL,
220 IN PCSTR DefaultPath OPTIONAL)
221{
222 TRACE("RamDiskInitialize(%s, '%s', '%s')\n",
223 InitRamDisk ? "INIT" : "REGULAR",
224 LoadOptions ? LoadOptions : "n/a",
225 DefaultPath ? DefaultPath : "n/a");
226
227 /* Reset the RAMDISK device */
228 if ((RamDiskBase != gInitRamDiskBase) &&
230 (gInitRamDiskSize != 0))
231 {
232 /* This is not the initial Ramdisk, so we can free the allocated memory */
234 }
236 RamDiskFileSize = 0;
239 RamDiskOffset = 0;
240
241 if (InitRamDisk)
242 {
243 /* We initialize the initial Ramdisk: it should be present in memory */
245 return ENODEV;
246
247 // TODO: Handle SDI image.
248
251 ASSERT(RamDiskFileSize < 0x100000000); // See FIXME about 4GB support in RamDiskLoadVirtualFile().
252 }
253 else
254 {
255 /* We initialize the Ramdisk from the load options */
257 CHAR FileName[MAX_PATH] = "";
258
259 /* If we don't have any load options, initialize an empty Ramdisk */
260 if (LoadOptions)
261 {
262 PCSTR Option;
264
265 /* Ramdisk image file name */
266 Option = NtLdrGetOptionEx(LoadOptions, "RDPATH=", &FileNameLength);
267 if (Option && (FileNameLength > 7))
268 {
269 /* Copy the file name */
270 Option += 7; FileNameLength -= 7;
272 Option, FileNameLength * sizeof(CHAR));
273 }
274
275 /* Ramdisk image length */
276 Option = NtLdrGetOption(LoadOptions, "RDIMAGELENGTH=");
277 if (Option)
278 {
279 RamDiskImageLength = _atoi64(Option + 14);
280 }
281
282 /* Ramdisk image offset */
283 Option = NtLdrGetOption(LoadOptions, "RDIMAGEOFFSET=");
284 if (Option)
285 {
286 RamDiskImageOffset = atol(Option + 14);
287 }
288 }
289
290 if (*FileName)
291 Status = RamDiskLoadVirtualFile(FileName, DefaultPath);
292 else
293 Status = RamDiskLoadVirtualFile(DefaultPath, NULL);
294 if (Status != ESUCCESS)
295 return Status;
296 }
297
298 /* Adjust the Ramdisk image length if needed */
301
302 /* Register the RAMDISK device */
304 {
305 FsRegisterDevice("ramdisk(0)", &RamDiskVtbl);
307 }
308
309 return ESUCCESS;
310}
#define N
Definition: crc32.c:57
unsigned char BOOLEAN
PRTL_UNICODE_STRING_BUFFER Path
#define EINVAL
Definition: acclib.h:90
#define ENOMEM
Definition: acclib.h:84
#define EIO
Definition: acclib.h:81
#define ENODEV
Definition: acclib.h:89
static ARC_STATUS RamDiskOpen(CHAR *Path, OPENMODE OpenMode, ULONG *FileId)
Definition: ramdisk.c:48
static ARC_STATUS RamDiskRead(ULONG FileId, VOID *Buffer, ULONG N, ULONG *Count)
Definition: ramdisk.c:54
static ARC_STATUS RamDiskSeek(ULONG FileId, LARGE_INTEGER *Position, SEEKMODE SeekMode)
Definition: ramdisk.c:77
static ARC_STATUS RamDiskClose(ULONG FileId)
Definition: ramdisk.c:32
static ARC_STATUS RamDiskGetFileInformation(ULONG FileId, FILEINFORMATION *Information)
Definition: ramdisk.c:38
static BOOLEAN RamDiskDeviceRegistered
Definition: ramdisk.c:23
static ULONGLONG RamDiskFileSize
Definition: ramdisk.c:25
static PVOID RamDiskBase
Definition: ramdisk.c:24
static ULONG RamDiskImageOffset
Definition: ramdisk.c:27
ARC_STATUS RamDiskInitialize(IN BOOLEAN InitRamDisk, IN PCSTR LoadOptions OPTIONAL, IN PCSTR DefaultPath OPTIONAL)
Definition: ramdisk.c:217
static ARC_STATUS RamDiskLoadVirtualFile(IN PCSTR FileName, IN PCSTR DefaultPath OPTIONAL)
Definition: ramdisk.c:110
static const DEVVTBL RamDiskVtbl
Definition: ramdisk.c:100
PVOID gInitRamDiskBase
Definition: ramdisk.c:20
static ULONGLONG RamDiskOffset
Definition: ramdisk.c:28
static ULONGLONG RamDiskImageLength
Definition: ramdisk.c:26
ULONG gInitRamDiskSize
Definition: ramdisk.c:21
#define DBG_DEFAULT_CHANNEL(ch)
Definition: debug.h:106
ARC_STATUS ArcGetFileInformation(ULONG FileId, FILEINFORMATION *Information)
Definition: fs.c:462
ARC_STATUS ArcSeek(ULONG FileId, LARGE_INTEGER *Position, SEEKMODE SeekMode)
Definition: fs.c:455
ARC_STATUS FsOpenFile(IN PCSTR FileName, IN PCSTR DefaultPath OPTIONAL, IN OPENMODE OpenMode, OUT PULONG FileId)
Definition: fs.c:478
ARC_STATUS ArcClose(_In_ ULONG FileId)
Definition: fs.c:409
VOID FsRegisterDevice(_In_ PCSTR DeviceName, _In_ const DEVVTBL *FuncTable)
Definition: fs.c:596
ARC_STATUS ArcRead(ULONG FileId, VOID *Buffer, ULONG N, ULONG *Count)
Definition: fs.c:448
VOID MmFreeMemory(PVOID MemoryPointer)
Definition: mm.c:215
PVOID MmAllocateMemoryWithType(SIZE_T MemorySize, TYPE_OF_MEMORY MemoryType)
Definition: mm.c:31
VOID UiUpdateProgressBar(_In_ ULONG Percentage, _In_opt_ PCSTR ProgressText)
Definition: ui.c:454
VOID UiDrawProgressBarCenter(_In_ PCSTR ProgressText)
Definition: ui.c:487
VOID UiMessageBox(_In_ PCSTR Format,...)
Definition: ui.c:359
Definition: bufpool.h:45
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define MAX_PATH
Definition: compat.h:34
#define ULONG_PTR
Definition: config.h:101
_Must_inspect_result_ _In_ PFILE_OBJECT _In_opt_ HANDLE _In_ ULONG FileNameLength
Definition: fltkernel.h:1129
Status
Definition: gdiplustypes.h:25
#define ASSERT(a)
Definition: mode.c:44
#define ULL(a, b)
Definition: format_msg.c:27
int Count
Definition: noreturn.cpp:7
PCSTR NtLdrGetOption(IN PCSTR Options, IN PCSTR OptionName)
Definition: ntldropts.c:128
PCSTR NtLdrGetOptionEx(IN PCSTR Options, IN PCSTR OptionName, OUT PULONG OptionLength OPTIONAL)
Definition: ntldropts.c:117
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
_Check_return_ long __cdecl atol(_In_z_ const char *_Str)
@ ESUCCESS
Definition: arc.h:32
@ LoaderXIPRom
Definition: arc.h:318
ULONG ARC_STATUS
Definition: arc.h:4
@ DiskPeripheral
Definition: arc.h:138
@ SeekRelative
Definition: arc.h:60
@ SeekAbsolute
Definition: arc.h:59
enum _OPENMODE OPENMODE
enum _SEEKMODE SEEKMODE
@ OpenReadOnly
Definition: arc.h:65
_Check_return_ _ACRTIMP __int64 __cdecl _atoi64(_In_z_ char const *_String)
#define TRACE(s)
Definition: solgame.cpp:4
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68
Definition: fs.h:25
static COORD Position
Definition: mouse.c:34
void * PVOID
Definition: typedefs.h:50
const char * PCSTR
Definition: typedefs.h:52
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define IN
Definition: typedefs.h:39
uint32_t ULONG
Definition: typedefs.h:59
uint64_t ULONGLONG
Definition: typedefs.h:67
LONGLONG QuadPart
Definition: typedefs.h:114
_In_ WDFREQUEST _In_ NTSTATUS _In_ ULONG_PTR Information
Definition: wdfrequest.h:1049
_Inout_ PUCHAR _In_ PUCHAR _Out_ PUCHAR _Out_ PULONG ChunkSize
Definition: rtlfuncs.h:2294
char CHAR
Definition: xmlstorage.h:175