ReactOS 0.4.15-dev-7889-g76290a6
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
22static ULONGLONG RamDiskFileSize; // FIXME: RAM disks currently limited to 4GB.
23static ULONGLONG RamDiskImageLength; // Size of valid data in the Ramdisk (usually == RamDiskFileSize - RamDiskImageOffset)
24static ULONG RamDiskImageOffset; // Starting offset from the Ramdisk base.
25static 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
44static 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);
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:
86 return EINVAL;
87 }
88
89 if (NewPosition.QuadPart >= RamDiskImageLength)
90 return EINVAL;
91
92 RamDiskOffset = NewPosition.QuadPart;
93 return ESUCCESS;
94}
95
96static const DEVVTBL RamDiskVtbl =
97{
103};
104
105static ARC_STATUS
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 {
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 }
220 RamDiskFileSize = 0;
223 RamDiskOffset = 0;
224
225 if (InitRamDisk)
226 {
227 /* We initialize the initial Ramdisk: it should be present in memory */
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}
#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
__int64 CDECL _atoi64(const char *nptr)
Definition: atoi64.c:18
static ARC_STATUS RamDiskOpen(CHAR *Path, OPENMODE OpenMode, ULONG *FileId)
Definition: ramdisk.c:44
static ARC_STATUS RamDiskRead(ULONG FileId, VOID *Buffer, ULONG N, ULONG *Count)
Definition: ramdisk.c:50
static ARC_STATUS RamDiskSeek(ULONG FileId, LARGE_INTEGER *Position, SEEKMODE SeekMode)
Definition: ramdisk.c:73
static ARC_STATUS RamDiskClose(ULONG FileId)
Definition: ramdisk.c:29
static ARC_STATUS RamDiskGetFileInformation(ULONG FileId, FILEINFORMATION *Information)
Definition: ramdisk.c:35
static BOOLEAN RamDiskDeviceRegistered
Definition: ramdisk.c:20
static ULONGLONG RamDiskFileSize
Definition: ramdisk.c:22
static PVOID RamDiskBase
Definition: ramdisk.c:21
static ULONG RamDiskImageOffset
Definition: ramdisk.c:24
ARC_STATUS RamDiskInitialize(IN BOOLEAN InitRamDisk, IN PCSTR LoadOptions OPTIONAL, IN PCSTR DefaultPath OPTIONAL)
Definition: ramdisk.c:206
static ARC_STATUS RamDiskLoadVirtualFile(IN PCSTR FileName, IN PCSTR DefaultPath OPTIONAL)
Definition: ramdisk.c:106
static const DEVVTBL RamDiskVtbl
Definition: ramdisk.c:96
PVOID gInitRamDiskBase
Definition: ramdisk.c:17
static ULONGLONG RamDiskOffset
Definition: ramdisk.c:25
static ULONGLONG RamDiskImageLength
Definition: ramdisk.c:23
ULONG gInitRamDiskSize
Definition: ramdisk.c:18
ARC_STATUS ArcClose(ULONG FileId)
Definition: fs.c:220
ARC_STATUS ArcGetFileInformation(ULONG FileId, FILEINFORMATION *Information)
Definition: fs.c:252
ARC_STATUS ArcSeek(ULONG FileId, LARGE_INTEGER *Position, SEEKMODE SeekMode)
Definition: fs.c:245
ARC_STATUS FsOpenFile(IN PCSTR FileName, IN PCSTR DefaultPath OPTIONAL, IN OPENMODE OpenMode, OUT PULONG FileId)
Definition: fs.c:268
ARC_STATUS ArcRead(ULONG FileId, VOID *Buffer, ULONG N, ULONG *Count)
Definition: fs.c:238
VOID FsRegisterDevice(CHAR *Prefix, const DEVVTBL *FuncTable)
Definition: fs.c:385
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
_Check_return_ long __cdecl atol(_In_z_ const char *_Str)
#define ASSERT(a)
Definition: mode.c:44
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
@ ESUCCESS
Definition: arc.h:32
@ LoaderXIPRom
Definition: arc.h:199
ULONG ARC_STATUS
Definition: arc.h:4
@ SeekRelative
Definition: arc.h:60
@ SeekAbsolute
Definition: arc.h:59
enum _OPENMODE OPENMODE
enum _SEEKMODE SEEKMODE
@ OpenReadOnly
Definition: arc.h:65
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:2277
char CHAR
Definition: xmlstorage.h:175