[BOOTLIB]: Make the EfiPrintf with __FUNCTION__ work also on GCC. Also, on MSVC ...
[reactos.git] / reactos / boot / environ / lib / mm / mm.c
1 /*
2 * COPYRIGHT: See COPYING.ARM in the top level directory
3 * PROJECT: ReactOS UEFI Boot Library
4 * FILE: boot/environ/lib/mm/mm.c
5 * PURPOSE: Boot Library Memory Manager Core
6 * PROGRAMMER: Alex Ionescu (alex.ionescu@reactos.org)
7 */
8
9 /* INCLUDES ******************************************************************/
10
11 #include "bl.h"
12 #include "bcd.h"
13
14 /* DATA VARIABLES ************************************************************/
15
16 /* This is a bug in Windows, but is required for MmTrInitialize to load */
17 BL_TRANSLATION_TYPE MmTranslationType = BlMax;
18 BL_TRANSLATION_TYPE MmOriginalTranslationType;
19 ULONG MmDescriptorCallTreeCount;
20
21 /* FUNCTIONS *****************************************************************/
22
23 NTSTATUS
24 MmTrInitialize (
25 VOID
26 )
27 {
28 PBL_MEMORY_DESCRIPTOR Descriptor;
29 NTSTATUS Status;
30 PLIST_ENTRY NextEntry;
31
32 /* Nothing to track if we're using physical memory */
33 if (MmTranslationType == BlNone)
34 {
35 return STATUS_SUCCESS;
36 }
37
38 /* Initialize all the virtual lists */
39 MmMdInitializeListHead(&MmMdlMappingTrackers);
40 MmMdlMappingTrackers.Type = BlMdTracker;
41 MmMdInitializeListHead(&MmMdlFreeVirtual);
42 MmMdlFreeVirtual.Type = BlMdVirtual;
43
44 /* Initialize a 4GB free descriptor */
45 Descriptor = MmMdInitByteGranularDescriptor(0,
46 BlConventionalMemory,
47 0,
48 0,
49 ((ULONGLONG)4 * 1024 * 1024 * 1024) >>
50 PAGE_SHIFT);
51 if (!Descriptor)
52 {
53 Status = STATUS_NO_MEMORY;
54 goto Quickie;
55 }
56
57 /* Add this 4GB region to the free virtual address space list */
58 Status = MmMdAddDescriptorToList(&MmMdlFreeVirtual,
59 Descriptor,
60 BL_MM_ADD_DESCRIPTOR_COALESCE_FLAG);
61 if (!NT_SUCCESS(Status))
62 {
63 RtlZeroMemory(Descriptor, sizeof(*Descriptor));
64 goto Quickie;
65 }
66
67 /* Remove any reserved regions of virtual address space */
68 NextEntry = MmMdlReservedAllocated.First->Flink;
69 while (NextEntry != MmMdlReservedAllocated.First)
70 {
71 /* Grab the descriptor and see if it's mapped */
72 Descriptor = CONTAINING_RECORD(NextEntry, BL_MEMORY_DESCRIPTOR, ListEntry);
73 if (Descriptor->VirtualPage)
74 {
75 EfiPrintf(L"Need to handle reserved allocation: %llx %llx\r\n",
76 Descriptor->VirtualPage, Descriptor->PageCount);
77 EfiStall(100000);
78 Status = STATUS_NOT_IMPLEMENTED;
79 goto Quickie;
80 }
81
82 /* Next entry */
83 NextEntry = NextEntry->Flink;
84 }
85
86 /* Set success if we made it */
87 Status = STATUS_SUCCESS;
88
89 Quickie:
90 /* Return back to caller */
91 return Status;
92 }
93
94 NTSTATUS
95 BlMmRemoveBadMemory (
96 VOID
97 )
98 {
99 BOOLEAN AllowBad;
100 NTSTATUS Status;
101 PULONGLONG BadPages;
102 ULONGLONG BadPageCount;
103
104 /* First check if bad memory access is allowed */
105 AllowBad = FALSE;
106 Status = BlGetBootOptionBoolean(BlpApplicationEntry.BcdData,
107 BcdLibraryBoolean_AllowBadMemoryAccess,
108 &AllowBad);
109 if ((NT_SUCCESS(Status)) && (AllowBad))
110 {
111 /* No point checking the list if it is */
112 return STATUS_SUCCESS;
113 }
114
115 /* Otherwise, check if there's a persisted bad page list */
116 Status = BlpGetBootOptionIntegerList(BlpApplicationEntry.BcdData,
117 BcdLibraryIntegerList_BadMemoryList,
118 &BadPages,
119 &BadPageCount,
120 TRUE);
121 if (NT_SUCCESS(Status))
122 {
123 EfiPrintf(L"Persistent bad page list not supported\r\n");
124 return STATUS_NOT_IMPLEMENTED;
125 }
126
127 /* All done here */
128 return STATUS_SUCCESS;
129 }
130
131 NTSTATUS
132 MmSelectMappingAddress (
133 _Out_ PVOID* MappingAddress,
134 _In_ ULONGLONG Size,
135 _In_ ULONG AllocationAttributes,
136 _In_ ULONG Flags,
137 _In_ PHYSICAL_ADDRESS PhysicalAddress
138 )
139 {
140 /* Are we in physical mode? */
141 if (MmTranslationType == BlNone)
142 {
143 /* Just return the physical address as the mapping address */
144 *MappingAddress = (PVOID)PhysicalAddress.LowPart;
145 return STATUS_SUCCESS;
146 }
147
148 /* We don't support virtual memory yet @TODO */
149 EfiPrintf(L"not yet implemented in %S\r\n", __FUNCTION__);
150 EfiStall(1000000);
151 return STATUS_NOT_IMPLEMENTED;
152 }
153
154 NTSTATUS
155 MmMapPhysicalAddress (
156 _Inout_ PPHYSICAL_ADDRESS PhysicalAddress,
157 _Out_ PVOID VirtualAddress,
158 _Inout_ PULONGLONG Size,
159 _In_ ULONG CacheAttributes
160 )
161 {
162 ULONGLONG MappingSize;
163
164 /* Fail if any parameters are missing */
165 if (!(PhysicalAddress) || !(VirtualAddress) || !(Size))
166 {
167 return STATUS_INVALID_PARAMETER;
168 }
169
170 /* Fail if the size is over 32-bits */
171 MappingSize = *Size;
172 if (MappingSize > 0xFFFFFFFF)
173 {
174 return STATUS_INVALID_PARAMETER;
175 }
176
177 /* Nothing to do if we're in physical mode */
178 if (MmTranslationType == BlNone)
179 {
180 return STATUS_SUCCESS;
181 }
182
183 /* Can't use virtual memory in real mode */
184 if (CurrentExecutionContext->Mode == BlRealMode)
185 {
186 return STATUS_UNSUCCESSFUL;
187 }
188
189 /* We don't support virtual memory yet @TODO */
190 EfiPrintf(L"not yet implemented in %S\r\n", __FUNCTION__);
191 EfiStall(1000000);
192 return STATUS_NOT_IMPLEMENTED;
193 }
194
195 NTSTATUS
196 BlMmMapPhysicalAddressEx (
197 _In_ PVOID* VirtualAddress,
198 _In_ ULONG Flags,
199 _In_ ULONGLONG Size,
200 _In_ PHYSICAL_ADDRESS PhysicalAddress
201 )
202 {
203 NTSTATUS Status;
204 PVOID MappingAddress;
205 PHYSICAL_ADDRESS MappedAddress;
206 PVOID MappedBase;
207 ULONGLONG MapSize;
208 UCHAR CacheAttributes;
209
210 /* Increase call depth */
211 ++MmDescriptorCallTreeCount;
212
213 /* Check if any parameters are missing */
214 if (!(VirtualAddress) || !(Size))
215 {
216 Status = STATUS_INVALID_PARAMETER;
217 goto Quickie;
218 }
219
220 /* Check for fixed allocation without an actual address */
221 if ((Flags & BlMemoryFixed) &&
222 (PhysicalAddress.QuadPart == -1) &&
223 !(*VirtualAddress))
224 {
225 Status = STATUS_INVALID_PARAMETER;
226 goto Quickie;
227 }
228
229 /* Check for invalid requirement flag, if one is present */
230 if (((Flags & BlMemoryValidAllocationAttributes) != BlMemoryFixed) &&
231 ((Flags & BlMemoryValidAllocationAttributes) != BlMemoryNonFixed) &&
232 (Flags & BlMemoryValidAllocationAttributes))
233 {
234 Status = STATUS_INVALID_PARAMETER;
235 goto Quickie;
236 }
237
238 /* Check for invalid cache attribute flags */
239 if (((Flags & BlMemoryValidCacheAttributeMask) - 1) &
240 (Flags & BlMemoryValidCacheAttributeMask))
241 {
242 Status = STATUS_INVALID_PARAMETER;
243 goto Quickie;
244 }
245
246 /* Select an address to map this at */
247 Status = MmSelectMappingAddress(&MappingAddress,
248 Size,
249 Flags & BlMemoryValidAllocationAttributes,
250 Flags,
251 PhysicalAddress);
252 if (!NT_SUCCESS(Status))
253 {
254 goto Quickie;
255 }
256
257 /* Map the selected address, using the appropriate caching attributes */
258 MappedAddress = PhysicalAddress;
259 MapSize = Size;
260 CacheAttributes = ((Flags & BlMemoryValidCacheAttributeMask) != 0x20) ?
261 (Flags & BlMemoryValidCacheAttributeMask) : 0;
262 Status = MmMapPhysicalAddress(&MappedAddress,
263 &MappingAddress,
264 &MapSize,
265 CacheAttributes);
266 if (!NT_SUCCESS(Status))
267 {
268 goto Quickie;
269 }
270
271 /* Compute the final address where the mapping was made */
272 MappedBase = (PVOID)((ULONG_PTR)MappingAddress +
273 PhysicalAddress.LowPart -
274 MappedAddress.LowPart);
275
276 /* Check if we're in physical or virtual mode */
277 if (MmTranslationType != BlNone)
278 {
279 /* We don't support virtual memory yet @TODO */
280 EfiPrintf(L"not yet implemented in %S\r\n", __FUNCTION__);
281 EfiStall(1000000);
282 Status = STATUS_NOT_IMPLEMENTED;
283 goto Quickie;
284 }
285
286 /* Return the mapped virtual address */
287 Status = STATUS_SUCCESS;
288 *VirtualAddress = MappedBase;
289
290 Quickie:
291 /* Cleanup descriptors and reduce depth */
292 MmMdFreeGlobalDescriptors();
293 --MmDescriptorCallTreeCount;
294 return Status;
295 }
296
297 NTSTATUS
298 MmUnmapVirtualAddress (
299 _Inout_ PVOID* VirtualAddress,
300 _Inout_ PULONGLONG Size
301 )
302 {
303 NTSTATUS Status;
304
305 /* Make sure parameters were passed in and are valid */
306 if ((VirtualAddress) && (Size) && (*Size <= 0xFFFFFFFF))
307 {
308 /* Nothing to do if translation isn't active */
309 if (MmTranslationType == BlNone)
310 {
311 Status = STATUS_SUCCESS;
312 }
313 else
314 {
315 /* We don't support virtual memory yet @TODO */
316 EfiPrintf(L"not yet implemented in %S\r\n", __FUNCTION__);
317 EfiStall(1000000);
318 Status = STATUS_NOT_IMPLEMENTED;
319 }
320 }
321 else
322 {
323 /* Fail */
324 Status = STATUS_INVALID_PARAMETER;
325 }
326
327 /* All done */
328 return Status;
329 }
330
331 NTSTATUS
332 BlMmUnmapVirtualAddressEx (
333 _In_ PVOID VirtualAddress,
334 _In_ ULONGLONG Size
335 )
336 {
337 NTSTATUS Status;
338
339 /* Increment call depth */
340 ++MmDescriptorCallTreeCount;
341
342 /* Make sure all parameters are there */
343 if ((VirtualAddress) && (Size))
344 {
345 /* Unmap the virtual address */
346 Status = MmUnmapVirtualAddress(&VirtualAddress, &Size);
347
348 /* Check if we actually had a virtual mapping active */
349 if ((NT_SUCCESS(Status)) && (MmTranslationType != BlNone))
350 {
351 /* We don't support virtual memory yet @TODO */
352 EfiPrintf(L"not yet implemented in %S\r\n", __FUNCTION__);
353 EfiStall(1000000);
354 Status = STATUS_NOT_IMPLEMENTED;
355 }
356 }
357 else
358 {
359 /* Fail */
360 Status = STATUS_INVALID_PARAMETER;
361 }
362
363 /* Cleanup descriptors and reduce depth */
364 MmMdFreeGlobalDescriptors();
365 --MmDescriptorCallTreeCount;
366 return Status;
367 }
368
369 BOOLEAN
370 BlMmTranslateVirtualAddress (
371 _In_ PVOID VirtualAddress,
372 _Out_ PPHYSICAL_ADDRESS PhysicalAddress
373 )
374 {
375 /* Make sure arguments are present */
376 if (!(VirtualAddress) || !(PhysicalAddress))
377 {
378 return FALSE;
379 }
380
381 /* Do the architecture-specific translation */
382 return MmArchTranslateVirtualAddress(VirtualAddress, PhysicalAddress, NULL);
383 }
384
385 NTSTATUS
386 BlpMmInitialize (
387 _In_ PBL_MEMORY_DATA MemoryData,
388 _In_ BL_TRANSLATION_TYPE TranslationType,
389 _In_ PBL_LIBRARY_PARAMETERS LibraryParameters
390 )
391 {
392 NTSTATUS Status;
393
394 /* Take a reference */
395 MmDescriptorCallTreeCount = 1;
396
397 /* Only support valid translation types */
398 if ((TranslationType > BlPae) || (LibraryParameters->TranslationType > BlPae))
399 {
400 /* Bail out */
401 EfiPrintf(L"Invalid translation types present\r\n");
402 Status = STATUS_INVALID_PARAMETER;
403 goto Quickie;
404 }
405
406 /* Initialize memory descriptors */
407 MmMdInitialize(0, LibraryParameters);
408
409 /* Remember the page type we came in with */
410 MmOriginalTranslationType = TranslationType;
411
412 /* Initialize the physical page allocator */
413 Status = MmPaInitialize(MemoryData,
414 LibraryParameters->MinimumAllocationCount);
415 if (!NT_SUCCESS(Status))
416 {
417 goto Quickie;
418 }
419
420 /* Initialize the memory tracker */
421 Status = MmTrInitialize();
422 if (!NT_SUCCESS(Status))
423 {
424 EfiPrintf(L"TR Mm init failed: %lx\r\n", Status);
425 //MmArchDestroy();
426 //MmPaDestroy(1);
427 goto Quickie;
428 }
429
430 /* Initialize paging, large pages, self-mapping, PAE, if needed */
431 Status = MmArchInitialize(1,
432 MemoryData,
433 TranslationType,
434 LibraryParameters->TranslationType);
435 if (NT_SUCCESS(Status))
436 {
437 /* Save the newly active transation type */
438 MmTranslationType = LibraryParameters->TranslationType;
439
440 /* Initialize the heap allocator now */
441 Status = MmHaInitialize(LibraryParameters->MinimumHeapSize,
442 LibraryParameters->HeapAllocationAttributes);
443 }
444
445 /* If Phase 1 init failed, bail out */
446 if (!NT_SUCCESS(Status))
447 {
448 /* Kill everything set setup so far */
449 EfiPrintf(L"Phase 1 Mm init failed: %lx\r\n", Status);
450 //MmPaDestroy(0);
451 //MmTrDestroy();
452 //MmArchDestroy();
453 //MmPaDestroy(1);
454 goto Quickie;
455 }
456
457 /* Do we have too many descriptors? */
458 if (LibraryParameters->DescriptorCount > 512)
459 {
460 /* Switch to using a dynamic buffer instead */
461 EfiPrintf(L"Warning: too many descriptors\r\n");
462 Status = STATUS_NOT_IMPLEMENTED;
463 goto Quickie;
464 //MmMdpSwitchToDynamicDescriptors(LibraryParameters->DescriptorCount);
465 }
466
467 /* Remove memory that the BCD says is bad */
468 BlMmRemoveBadMemory();
469
470 /* Now map all the memory regions as needed */
471 Status = MmArchInitialize(2,
472 MemoryData,
473 TranslationType,
474 LibraryParameters->TranslationType);
475 if (NT_SUCCESS(Status))
476 {
477 /* Initialize the block allocator */
478 Status = MmBaInitialize();
479 }
480
481 /* Check if anything in phase 2 failed */
482 if (!NT_SUCCESS(Status))
483 {
484 /* Go back to static descriptors and kill the heap */
485 EfiPrintf(L"Phase 2 Mm init failed: %lx\r\n", Status);
486 //MmMdpSwitchToStaticDescriptors();
487 //HapInitializationStatus = 0;
488 //++MmDescriptorCallTreeCount;
489
490 /* Destroy the Phase 1 initialization */
491 //MmPaDestroy(0);
492 //MmTrDestroy();
493 //MmArchDestroy();
494 //MmPaDestroy(1);
495 }
496
497 Quickie:
498 /* Free the memory descriptors and return the initialization state */
499 MmMdFreeGlobalDescriptors();
500 --MmDescriptorCallTreeCount;
501 return Status;
502 }