[YAROTOWS] Reintegrate the branch. For a brighter future.
[reactos.git] / reactos / boot / freeldr / freeldr / disk / ramdisk.c
1 /*
2 * PROJECT: ReactOS Boot Loader
3 * LICENSE: BSD - See COPYING.ARM in the top level directory
4 * FILE: boot/freeldr/freeldr/disk/ramdisk.c
5 * PURPOSE: Implements routines to support booting from a RAM Disk
6 * PROGRAMMERS: ReactOS Portable Systems Group
7 * Hervé Poussineau
8 */
9
10 /* INCLUDES *******************************************************************/
11
12 #include <freeldr.h>
13 #define NDEBUG
14 #include <debug.h>
15
16 /* GLOBALS ********************************************************************/
17
18 PVOID gRamDiskBase;
19 ULONG gRamDiskSize;
20 ULONG gRamDiskOffset;
21
22 /* FUNCTIONS ******************************************************************/
23
24 static LONG RamDiskClose(ULONG FileId)
25 {
26 //
27 // Nothing to do
28 //
29 return ESUCCESS;
30 }
31
32 static LONG RamDiskGetFileInformation(ULONG FileId, FILEINFORMATION* Information)
33 {
34 //
35 // Give current seek offset and ram disk size to caller
36 //
37 RtlZeroMemory(Information, sizeof(FILEINFORMATION));
38 Information->EndingAddress.LowPart = gRamDiskSize;
39 Information->CurrentAddress.LowPart = gRamDiskOffset;
40
41 return ESUCCESS;
42 }
43
44 static LONG RamDiskOpen(CHAR* Path, OPENMODE OpenMode, ULONG* FileId)
45 {
46 //
47 // Always return success, as contents are already in memory
48 //
49 return ESUCCESS;
50 }
51
52 static LONG RamDiskRead(ULONG FileId, VOID* Buffer, ULONG N, ULONG* Count)
53 {
54 PVOID StartAddress;
55
56 //
57 // Get actual pointer
58 //
59 StartAddress = (PVOID)((ULONG_PTR)gRamDiskBase + gRamDiskOffset);
60
61 //
62 // Don't allow reads past our image
63 //
64 if (gRamDiskOffset + N > gRamDiskSize)
65 {
66 *Count = 0;
67 return EIO;
68 }
69
70 //
71 // Do the read
72 //
73 RtlCopyMemory(Buffer, StartAddress, N);
74 *Count = N;
75
76 return ESUCCESS;
77 }
78
79 static LONG RamDiskSeek(ULONG FileId, LARGE_INTEGER* Position, SEEKMODE SeekMode)
80 {
81 //
82 // Only accept absolute mode now
83 //
84 if (SeekMode != SeekAbsolute)
85 return EINVAL;
86
87 //
88 // Check if we're in the ramdisk
89 //
90 if (Position->HighPart != 0)
91 return EINVAL;
92 if (Position->LowPart >= gRamDiskSize)
93 return EINVAL;
94
95 //
96 // OK, remember seek position
97 //
98 gRamDiskOffset = Position->LowPart;
99
100 return ESUCCESS;
101 }
102
103 static const DEVVTBL RamDiskVtbl = {
104 RamDiskClose,
105 RamDiskGetFileInformation,
106 RamDiskOpen,
107 RamDiskRead,
108 RamDiskSeek,
109 };
110
111 VOID
112 NTAPI
113 RamDiskInitialize(VOID)
114 {
115 /* Setup the RAMDISK device */
116 FsRegisterDevice("ramdisk(0)", &RamDiskVtbl);
117 }
118
119 VOID
120 NTAPI
121 RamDiskLoadVirtualFile(IN PCHAR FileName)
122 {
123 ULONG RamFile;
124 ULONG TotalRead, ChunkSize, Count;
125 PCHAR MsgBuffer = "Loading ramdisk...";
126 ULONG PercentPerChunk, Percent;
127 FILEINFORMATION Information;
128 LARGE_INTEGER Position;
129 LONG ret;
130
131 //
132 // Display progress
133 //
134 UiDrawProgressBarCenter(1, 100, MsgBuffer);
135
136 //
137 // Try opening the ramdisk file
138 //
139 ret = ArcOpen(FileName, OpenReadOnly, &RamFile);
140 if (ret == ESUCCESS)
141 {
142 //
143 // Get the file size
144 //
145 ret = ArcGetFileInformation(RamFile, &Information);
146 if (ret != ESUCCESS)
147 {
148 ArcClose(RamFile);
149 return;
150 }
151
152 //
153 // For now, limit RAM disks to 4GB
154 //
155 if (Information.EndingAddress.HighPart != 0)
156 {
157 UiMessageBox("RAM disk too big\n");
158 ArcClose(RamFile);
159 return;
160 }
161 gRamDiskSize = Information.EndingAddress.LowPart;
162
163 //
164 // Allocate memory for it
165 //
166 ChunkSize = 8 * 1024 * 1024;
167 Percent = PercentPerChunk = 100 / (gRamDiskSize / ChunkSize);
168 gRamDiskBase = MmAllocateMemory(gRamDiskSize);
169 if (!gRamDiskBase)
170 {
171 UiMessageBox("Failed to allocate memory for RAM disk\n");
172 ArcClose(RamFile);
173 return;
174 }
175
176 //
177 // Read it in chunks
178 //
179 for (TotalRead = 0; TotalRead < gRamDiskSize; TotalRead += ChunkSize)
180 {
181 //
182 // Check if we're at the last chunk
183 //
184 if ((gRamDiskSize - TotalRead) < ChunkSize)
185 {
186 //
187 // Only need the actual data required
188 //
189 ChunkSize = gRamDiskSize - TotalRead;
190 }
191
192 //
193 // Draw progress
194 //
195 UiDrawProgressBarCenter(Percent, 100, MsgBuffer);
196 Percent += PercentPerChunk;
197
198 //
199 // Copy the contents
200 //
201 Position.HighPart = 0;
202 Position.LowPart = TotalRead;
203 ret = ArcSeek(RamFile, &Position, SeekAbsolute);
204 if (ret == ESUCCESS)
205 {
206 ret = ArcRead(RamFile,
207 (PVOID)((ULONG_PTR)gRamDiskBase + TotalRead),
208 ChunkSize,
209 &Count);
210 }
211
212 //
213 // Check for success
214 //
215 if (ret != ESUCCESS || Count != ChunkSize)
216 {
217 MmFreeMemory(gRamDiskBase);
218 gRamDiskBase = NULL;
219 gRamDiskSize = 0;
220 ArcClose(RamFile);
221 UiMessageBox("Failed to read ramdisk\n");
222 return;
223 }
224 }
225
226 ArcClose(RamFile);
227
228 // Register a new device for the ramdisk
229 FsRegisterDevice("ramdisk(0)", &RamDiskVtbl);
230 }
231 }