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)
9 /* INCLUDES ******************************************************************/
14 /* DATA VARIABLES ************************************************************/
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
;
21 /* FUNCTIONS *****************************************************************/
28 PBL_MEMORY_DESCRIPTOR Descriptor
;
30 PLIST_ENTRY NextEntry
;
32 /* Nothing to track if we're using physical memory */
33 if (MmTranslationType
== BlNone
)
35 return STATUS_SUCCESS
;
38 /* Initialize all the virtual lists */
39 MmMdInitializeListHead(&MmMdlMappingTrackers
);
40 MmMdlMappingTrackers
.Type
= BlMdTracker
;
41 MmMdInitializeListHead(&MmMdlFreeVirtual
);
42 MmMdlFreeVirtual
.Type
= BlMdVirtual
;
44 /* Initialize a 4GB free descriptor */
45 Descriptor
= MmMdInitByteGranularDescriptor(0,
49 ((ULONGLONG
)4 * 1024 * 1024 * 1024) >>
53 Status
= STATUS_NO_MEMORY
;
57 /* Add this 4GB region to the free virtual address space list */
58 Status
= MmMdAddDescriptorToList(&MmMdlFreeVirtual
,
60 BL_MM_ADD_DESCRIPTOR_COALESCE_FLAG
);
61 if (!NT_SUCCESS(Status
))
63 RtlZeroMemory(Descriptor
, sizeof(*Descriptor
));
67 /* Remove any reserved regions of virtual address space */
68 NextEntry
= MmMdlReservedAllocated
.First
->Flink
;
69 while (NextEntry
!= MmMdlReservedAllocated
.First
)
71 /* Grab the descriptor and see if it's mapped */
72 Descriptor
= CONTAINING_RECORD(NextEntry
, BL_MEMORY_DESCRIPTOR
, ListEntry
);
73 if (Descriptor
->VirtualPage
)
75 EfiPrintf(L
"Need to handle reserved allocation: %llx %llx\r\n",
76 Descriptor
->VirtualPage
, Descriptor
->PageCount
);
78 Status
= STATUS_NOT_IMPLEMENTED
;
83 NextEntry
= NextEntry
->Flink
;
86 /* Set success if we made it */
87 Status
= STATUS_SUCCESS
;
90 /* Return back to caller */
102 ULONGLONG BadPageCount
;
104 /* First check if bad memory access is allowed */
106 Status
= BlGetBootOptionBoolean(BlpApplicationEntry
.BcdData
,
107 BcdLibraryBoolean_AllowBadMemoryAccess
,
109 if ((NT_SUCCESS(Status
)) && (AllowBad
))
111 /* No point checking the list if it is */
112 return STATUS_SUCCESS
;
115 /* Otherwise, check if there's a persisted bad page list */
116 Status
= BlpGetBootOptionIntegerList(BlpApplicationEntry
.BcdData
,
117 BcdLibraryIntegerList_BadMemoryList
,
121 if (NT_SUCCESS(Status
))
123 EfiPrintf(L
"Persistent bad page list not supported\r\n");
124 return STATUS_NOT_IMPLEMENTED
;
128 return STATUS_SUCCESS
;
132 MmSelectMappingAddress (
133 _Out_ PVOID
* MappingAddress
,
135 _In_ ULONG AllocationAttributes
,
137 _In_ PHYSICAL_ADDRESS PhysicalAddress
140 /* Are we in physical mode? */
141 if (MmTranslationType
== BlNone
)
143 /* Just return the physical address as the mapping address */
144 *MappingAddress
= (PVOID
)PhysicalAddress
.LowPart
;
145 return STATUS_SUCCESS
;
148 /* We don't support virtual memory yet @TODO */
149 EfiPrintf(L
"not yet implemented in %S\r\n", __FUNCTION__
);
151 return STATUS_NOT_IMPLEMENTED
;
155 MmMapPhysicalAddress (
156 _Inout_ PPHYSICAL_ADDRESS PhysicalAddress
,
157 _Out_ PVOID VirtualAddress
,
158 _Inout_ PULONGLONG Size
,
159 _In_ ULONG CacheAttributes
162 ULONGLONG MappingSize
;
164 /* Fail if any parameters are missing */
165 if (!(PhysicalAddress
) || !(VirtualAddress
) || !(Size
))
167 return STATUS_INVALID_PARAMETER
;
170 /* Fail if the size is over 32-bits */
172 if (MappingSize
> 0xFFFFFFFF)
174 return STATUS_INVALID_PARAMETER
;
177 /* Nothing to do if we're in physical mode */
178 if (MmTranslationType
== BlNone
)
180 return STATUS_SUCCESS
;
183 /* Can't use virtual memory in real mode */
184 if (CurrentExecutionContext
->Mode
== BlRealMode
)
186 return STATUS_UNSUCCESSFUL
;
189 /* We don't support virtual memory yet @TODO */
190 EfiPrintf(L
"not yet implemented in %S\r\n", __FUNCTION__
);
192 return STATUS_NOT_IMPLEMENTED
;
196 BlMmMapPhysicalAddressEx (
197 _In_ PVOID
* VirtualAddress
,
200 _In_ PHYSICAL_ADDRESS PhysicalAddress
204 PVOID MappingAddress
;
205 PHYSICAL_ADDRESS MappedAddress
;
208 UCHAR CacheAttributes
;
210 /* Increase call depth */
211 ++MmDescriptorCallTreeCount
;
213 /* Check if any parameters are missing */
214 if (!(VirtualAddress
) || !(Size
))
216 Status
= STATUS_INVALID_PARAMETER
;
220 /* Check for fixed allocation without an actual address */
221 if ((Flags
& BlMemoryFixed
) &&
222 (PhysicalAddress
.QuadPart
== -1) &&
225 Status
= STATUS_INVALID_PARAMETER
;
229 /* Check for invalid requirement flag, if one is present */
230 if (((Flags
& BlMemoryValidAllocationAttributes
) != BlMemoryFixed
) &&
231 ((Flags
& BlMemoryValidAllocationAttributes
) != BlMemoryNonFixed
) &&
232 (Flags
& BlMemoryValidAllocationAttributes
))
234 Status
= STATUS_INVALID_PARAMETER
;
238 /* Check for invalid cache attribute flags */
239 if (((Flags
& BlMemoryValidCacheAttributeMask
) - 1) &
240 (Flags
& BlMemoryValidCacheAttributeMask
))
242 Status
= STATUS_INVALID_PARAMETER
;
246 /* Select an address to map this at */
247 Status
= MmSelectMappingAddress(&MappingAddress
,
249 Flags
& BlMemoryValidAllocationAttributes
,
252 if (!NT_SUCCESS(Status
))
257 /* Map the selected address, using the appropriate caching attributes */
258 MappedAddress
= PhysicalAddress
;
260 CacheAttributes
= ((Flags
& BlMemoryValidCacheAttributeMask
) != 0x20) ?
261 (Flags
& BlMemoryValidCacheAttributeMask
) : 0;
262 Status
= MmMapPhysicalAddress(&MappedAddress
,
266 if (!NT_SUCCESS(Status
))
271 /* Compute the final address where the mapping was made */
272 MappedBase
= (PVOID
)((ULONG_PTR
)MappingAddress
+
273 PhysicalAddress
.LowPart
-
274 MappedAddress
.LowPart
);
276 /* Check if we're in physical or virtual mode */
277 if (MmTranslationType
!= BlNone
)
279 /* We don't support virtual memory yet @TODO */
280 EfiPrintf(L
"not yet implemented in %S\r\n", __FUNCTION__
);
282 Status
= STATUS_NOT_IMPLEMENTED
;
286 /* Return the mapped virtual address */
287 Status
= STATUS_SUCCESS
;
288 *VirtualAddress
= MappedBase
;
291 /* Cleanup descriptors and reduce depth */
292 MmMdFreeGlobalDescriptors();
293 --MmDescriptorCallTreeCount
;
298 MmUnmapVirtualAddress (
299 _Inout_ PVOID
* VirtualAddress
,
300 _Inout_ PULONGLONG Size
305 /* Make sure parameters were passed in and are valid */
306 if ((VirtualAddress
) && (Size
) && (*Size
<= 0xFFFFFFFF))
308 /* Nothing to do if translation isn't active */
309 if (MmTranslationType
== BlNone
)
311 Status
= STATUS_SUCCESS
;
315 /* We don't support virtual memory yet @TODO */
316 EfiPrintf(L
"not yet implemented in %S\r\n", __FUNCTION__
);
318 Status
= STATUS_NOT_IMPLEMENTED
;
324 Status
= STATUS_INVALID_PARAMETER
;
332 BlMmUnmapVirtualAddressEx (
333 _In_ PVOID VirtualAddress
,
339 /* Increment call depth */
340 ++MmDescriptorCallTreeCount
;
342 /* Make sure all parameters are there */
343 if ((VirtualAddress
) && (Size
))
345 /* Unmap the virtual address */
346 Status
= MmUnmapVirtualAddress(&VirtualAddress
, &Size
);
348 /* Check if we actually had a virtual mapping active */
349 if ((NT_SUCCESS(Status
)) && (MmTranslationType
!= BlNone
))
351 /* We don't support virtual memory yet @TODO */
352 EfiPrintf(L
"not yet implemented in %S\r\n", __FUNCTION__
);
354 Status
= STATUS_NOT_IMPLEMENTED
;
360 Status
= STATUS_INVALID_PARAMETER
;
363 /* Cleanup descriptors and reduce depth */
364 MmMdFreeGlobalDescriptors();
365 --MmDescriptorCallTreeCount
;
370 BlMmTranslateVirtualAddress (
371 _In_ PVOID VirtualAddress
,
372 _Out_ PPHYSICAL_ADDRESS PhysicalAddress
375 /* Make sure arguments are present */
376 if (!(VirtualAddress
) || !(PhysicalAddress
))
381 /* Do the architecture-specific translation */
382 return MmArchTranslateVirtualAddress(VirtualAddress
, PhysicalAddress
, NULL
);
387 _In_ PBL_MEMORY_DATA MemoryData
,
388 _In_ BL_TRANSLATION_TYPE TranslationType
,
389 _In_ PBL_LIBRARY_PARAMETERS LibraryParameters
394 /* Take a reference */
395 MmDescriptorCallTreeCount
= 1;
397 /* Only support valid translation types */
398 if ((TranslationType
> BlPae
) || (LibraryParameters
->TranslationType
> BlPae
))
401 EfiPrintf(L
"Invalid translation types present\r\n");
402 Status
= STATUS_INVALID_PARAMETER
;
406 /* Initialize memory descriptors */
407 MmMdInitialize(0, LibraryParameters
);
409 /* Remember the page type we came in with */
410 MmOriginalTranslationType
= TranslationType
;
412 /* Initialize the physical page allocator */
413 Status
= MmPaInitialize(MemoryData
,
414 LibraryParameters
->MinimumAllocationCount
);
415 if (!NT_SUCCESS(Status
))
420 /* Initialize the memory tracker */
421 Status
= MmTrInitialize();
422 if (!NT_SUCCESS(Status
))
424 EfiPrintf(L
"TR Mm init failed: %lx\r\n", Status
);
430 /* Initialize paging, large pages, self-mapping, PAE, if needed */
431 Status
= MmArchInitialize(1,
434 LibraryParameters
->TranslationType
);
435 if (NT_SUCCESS(Status
))
437 /* Save the newly active transation type */
438 MmTranslationType
= LibraryParameters
->TranslationType
;
440 /* Initialize the heap allocator now */
441 Status
= MmHaInitialize(LibraryParameters
->MinimumHeapSize
,
442 LibraryParameters
->HeapAllocationAttributes
);
445 /* If Phase 1 init failed, bail out */
446 if (!NT_SUCCESS(Status
))
448 /* Kill everything set setup so far */
449 EfiPrintf(L
"Phase 1 Mm init failed: %lx\r\n", Status
);
457 /* Do we have too many descriptors? */
458 if (LibraryParameters
->DescriptorCount
> 512)
460 /* Switch to using a dynamic buffer instead */
461 EfiPrintf(L
"Warning: too many descriptors\r\n");
462 Status
= STATUS_NOT_IMPLEMENTED
;
464 //MmMdpSwitchToDynamicDescriptors(LibraryParameters->DescriptorCount);
467 /* Remove memory that the BCD says is bad */
468 BlMmRemoveBadMemory();
470 /* Now map all the memory regions as needed */
471 Status
= MmArchInitialize(2,
474 LibraryParameters
->TranslationType
);
475 if (NT_SUCCESS(Status
))
477 /* Initialize the block allocator */
478 Status
= MmBaInitialize();
481 /* Check if anything in phase 2 failed */
482 if (!NT_SUCCESS(Status
))
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;
490 /* Destroy the Phase 1 initialization */
498 /* Free the memory descriptors and return the initialization state */
499 MmMdFreeGlobalDescriptors();
500 --MmDescriptorCallTreeCount
;