2 * COPYRIGHT: See COPYING.ARM in the top level directory
3 * PROJECT: ReactOS UEFI Boot Library
4 * FILE: boot/environ/lib/mm/pagealloc.c
5 * PURPOSE: Boot Library Memory Manager Page Allocator
6 * PROGRAMMER: Alex Ionescu (alex.ionescu@reactos.org)
9 /* INCLUDES ******************************************************************/
14 typedef struct _BL_PA_REQUEST
16 BL_ADDRESS_RANGE BaseRange
;
17 BL_ADDRESS_RANGE VirtualRange
;
23 } BL_PA_REQUEST
, *PBL_PA_REQUEST
;
25 /* DATA VARIABLES ************************************************************/
27 ULONGLONG PapMaximumPhysicalPage
, PapMinimumPhysicalPage
;
29 ULONG PapMinimumAllocationCount
;
31 BOOLEAN PapInitializationStatus
;
33 BL_MEMORY_DESCRIPTOR_LIST MmMdlMappedAllocated
;
34 BL_MEMORY_DESCRIPTOR_LIST MmMdlMappedUnallocated
;
35 BL_MEMORY_DESCRIPTOR_LIST MmMdlFwAllocationTracker
;
36 BL_MEMORY_DESCRIPTOR_LIST MmMdlUnmappedAllocated
;
37 BL_MEMORY_DESCRIPTOR_LIST MmMdlUnmappedUnallocated
;
38 BL_MEMORY_DESCRIPTOR_LIST MmMdlReservedAllocated
;
39 BL_MEMORY_DESCRIPTOR_LIST MmMdlBadMemory
;
40 BL_MEMORY_DESCRIPTOR_LIST MmMdlTruncatedMemory
;
41 BL_MEMORY_DESCRIPTOR_LIST MmMdlPersistentMemory
;
42 BL_MEMORY_DESCRIPTOR_LIST MmMdlCompleteBadMemory
;
43 BL_MEMORY_DESCRIPTOR_LIST MmMdlFreeVirtual
;
44 BL_MEMORY_DESCRIPTOR_LIST MmMdlMappingTrackers
;
46 /* FUNCTIONS *****************************************************************/
49 BlpMmInitializeConstraints (
54 ULONGLONG LowestAddressValid
, HighestAddressValid
;
56 /* Check for LOWMEM */
57 Status
= BlGetBootOptionInteger(BlpApplicationEntry
.BcdData
,
58 BcdLibraryInteger_AvoidLowPhysicalMemory
,
60 if (NT_SUCCESS(Status
))
62 EfiPrintf(L
"/LOWMEM not supported\r\n");
63 return STATUS_NOT_IMPLEMENTED
;
66 /* Check for MAXMEM */
67 Status
= BlGetBootOptionInteger(BlpApplicationEntry
.BcdData
,
68 BcdLibraryInteger_TruncatePhysicalMemory
,
69 &HighestAddressValid
);
70 if (NT_SUCCESS(Status
))
72 EfiPrintf(L
"/MAXMEM not supported\r\n");
73 return STATUS_NOT_IMPLEMENTED
;
76 /* Return back to the caller */
77 return STATUS_SUCCESS
;
81 MmPapAllocateRegionFromMdl (
82 _In_ PBL_MEMORY_DESCRIPTOR_LIST NewList
,
83 _Out_opt_ PBL_MEMORY_DESCRIPTOR Descriptor
,
84 _In_ PBL_MEMORY_DESCRIPTOR_LIST CurrentList
,
85 _In_ PBL_PA_REQUEST Request
,
86 _In_ BL_MEMORY_TYPE Type
90 BL_MEMORY_DESCRIPTOR LocalDescriptor
= {{0}};
91 PBL_MEMORY_DESCRIPTOR FoundDescriptor
, TempDescriptor
;
92 PLIST_ENTRY ListHead
, NextEntry
;
93 BOOLEAN TopDown
, GotFwPages
;
94 EFI_PHYSICAL_ADDRESS EfiAddress
;
95 ULONGLONG LocalEndPage
, FoundEndPage
, LocalVirtualEndPage
;
97 /* Check if any parameters were not passed in correctly */
98 if ( !(CurrentList
) || !(Request
) || (!(NewList
) && !(Descriptor
)))
100 return STATUS_INVALID_PARAMETER
;
103 /* Set failure by default */
104 Status
= STATUS_NO_MEMORY
;
106 /* Take the head and next entry in the list, as appropriate */
107 ListHead
= CurrentList
->First
;
108 if (Request
->Type
& BL_MM_REQUEST_TOP_DOWN_TYPE
)
110 NextEntry
= ListHead
->Blink
;
115 NextEntry
= ListHead
->Flink
;
119 /* Loop through the list */
121 while (NextEntry
!= ListHead
)
123 /* Grab a descriptor */
124 FoundDescriptor
= CONTAINING_RECORD(NextEntry
,
125 BL_MEMORY_DESCRIPTOR
,
128 /* See if it matches the request */
129 if (MmMdFindSatisfyingRegion(FoundDescriptor
,
133 &Request
->VirtualRange
,
139 /* It does, get out */
143 /* It doesn't, move to the next appropriate entry */
146 NextEntry
= NextEntry
->Blink
;
150 NextEntry
= NextEntry
->Flink
;
154 /* Check if we exhausted the list */
155 if (NextEntry
== ListHead
)
157 EfiPrintf(L
"No matching memory found\r\n");
161 /* Copy all the flags that are not request flag */
162 LocalDescriptor
.Flags
= (Request
->Flags
& 0xFFFF0000) |
163 (LocalDescriptor
.Flags
& 0x0000FFFF);
165 /* Are we using the physical memory list, and are we OK with using firmware? */
166 if ((CurrentList
== &MmMdlUnmappedUnallocated
) &&
167 !((Request
->Flags
& BlMemoryNonFirmware
) ||
168 (LocalDescriptor
.Flags
& BlMemoryNonFirmware
)))
170 /* Allocate the requested address from EFI */
171 EfiAddress
= LocalDescriptor
.BasePage
<< PAGE_SHIFT
;
172 Status
= EfiAllocatePages(AllocateAddress
,
173 (ULONG
)LocalDescriptor
.PageCount
,
175 if (!NT_SUCCESS(Status
))
177 EfiPrintf(L
"EFI memory allocation failure\r\n");
181 /* Remember we got memory from EFI */
185 /* Remove the descriptor from the original list it was on */
186 MmMdRemoveDescriptorFromList(CurrentList
, FoundDescriptor
);
188 /* Are we allocating from the virtual memory list? */
189 if (CurrentList
== &MmMdlMappedUnallocated
)
191 EfiPrintf(L
"Virtual memory not yet supported\r\n");
192 return STATUS_NOT_IMPLEMENTED
;
195 /* Does the memory we received not exactly fall onto the beginning of its descriptor? */
196 if (LocalDescriptor
.BasePage
!= FoundDescriptor
->BasePage
)
198 EfiPrintf(L
"Local Page: %08I64X Found Page: %08I64X\r\n", LocalDescriptor
.BasePage
, FoundDescriptor
->BasePage
);
199 TempDescriptor
= MmMdInitByteGranularDescriptor(FoundDescriptor
->Flags
,
200 FoundDescriptor
->Type
,
201 FoundDescriptor
->BasePage
,
202 FoundDescriptor
->VirtualPage
,
203 LocalDescriptor
.BasePage
-
204 FoundDescriptor
->BasePage
);
205 Status
= MmMdAddDescriptorToList(CurrentList
, TempDescriptor
, 0);
206 if (!NT_SUCCESS(Status
))
212 /* Does the memory we received not exactly fall onto the end of its descriptor? */
213 LocalEndPage
= LocalDescriptor
.PageCount
+ LocalDescriptor
.BasePage
;
214 FoundEndPage
= FoundDescriptor
->PageCount
+ FoundDescriptor
->BasePage
;
215 LocalVirtualEndPage
= LocalDescriptor
.VirtualPage
?
216 LocalDescriptor
.VirtualPage
+ LocalDescriptor
.PageCount
: 0;
217 if (LocalEndPage
!= FoundEndPage
)
219 EfiPrintf(L
"Local Page: %08I64X Found Page: %08I64X\r\n", LocalEndPage
, FoundEndPage
);
220 TempDescriptor
= MmMdInitByteGranularDescriptor(FoundDescriptor
->Flags
,
221 FoundDescriptor
->Type
,
224 FoundEndPage
- LocalEndPage
);
225 Status
= MmMdAddDescriptorToList(CurrentList
, TempDescriptor
, 0);
226 if (!NT_SUCCESS(Status
))
232 /* We got the memory we needed */
233 Status
= STATUS_SUCCESS
;
235 /* Are we supposed to insert it into a new list? */
238 /* Copy the allocated region descriptor into the one we found */
239 FoundDescriptor
->BaseAddress
= LocalDescriptor
.BaseAddress
;
240 FoundDescriptor
->VirtualPage
= LocalDescriptor
.VirtualPage
;
241 FoundDescriptor
->PageCount
= LocalDescriptor
.PageCount
;
242 FoundDescriptor
->Type
= Type
;
243 FoundDescriptor
->Flags
= LocalDescriptor
.Flags
;
245 /* Remember if it came from EFI */
248 FoundDescriptor
->Flags
|= BlMemoryFirmware
;
251 /* Add the descriptor to the requested list */
252 Status
= MmMdAddDescriptorToList(NewList
, FoundDescriptor
, 0);
256 /* Free the descriptor, nobody wants to know about it anymore */
257 MmMdFreeDescriptor(FoundDescriptor
);
260 /* Return the allocation region back */
261 RtlCopyMemory(Descriptor
, &LocalDescriptor
, sizeof(LocalDescriptor
));
267 _In_ PBL_MEMORY_DESCRIPTOR_LIST NewList
,
268 _In_ PBL_MEMORY_DESCRIPTOR Descriptor
,
269 _In_ PBL_MEMORY_DESCRIPTOR_LIST CurrentList
,
270 _In_ PBL_PA_REQUEST Request
,
271 _In_ BL_MEMORY_TYPE MemoryType
276 /* Heap and page directory/table pages have a special flag */
277 if ((MemoryType
>= BlLoaderHeap
) && (MemoryType
<= BlLoaderReferencePage
))
279 Request
->Flags
|= BlMemorySpecial
;
282 /* Try to find a free region of RAM matching this range and request */
283 Request
->MemoryType
= BlConventionalMemory
;
284 Status
= MmPapAllocateRegionFromMdl(NewList
,
289 if (Status
== STATUS_NOT_FOUND
)
291 /* Need to re-synchronize the memory map and check other lists */
292 EfiPrintf(L
"No RAM found -- backup plan not yet implemented\r\n");
295 /* Did we get the region we wanted? */
296 if (NT_SUCCESS(Status
))
298 /* All good, return back */
302 /* Nope, we have to hunt for it elsewhere */
303 EfiPrintf(L
"TODO\r\n");
308 MmPapAllocatePhysicalPagesInRange (
309 _Inout_ PPHYSICAL_ADDRESS BaseAddress
,
310 _In_ BL_MEMORY_TYPE MemoryType
,
311 _In_ ULONGLONG Pages
,
312 _In_ ULONG Attributes
,
313 _In_ ULONG Alignment
,
314 _In_ PBL_MEMORY_DESCRIPTOR_LIST NewList
,
315 _In_opt_ PBL_ADDRESS_RANGE Range
,
320 BL_PA_REQUEST Request
;
321 BL_MEMORY_DESCRIPTOR Descriptor
;
323 /* Increase nesting depth */
324 ++MmDescriptorCallTreeCount
;
326 /* Bail out if no address was specified */
329 Status
= STATUS_INVALID_PARAMETER
;
333 /* Bail out if no page count was passed in, or a bad list was specified */
335 ((NewList
!= &MmMdlUnmappedAllocated
) &&
336 (NewList
!= &MmMdlPersistentMemory
)))
338 Status
= STATUS_INVALID_PARAMETER
;
342 /* Bail out if the passed in range is invalid */
343 if ((Range
) && (Range
->Minimum
>= Range
->Maximum
))
345 Status
= STATUS_INVALID_PARAMETER
;
349 /* Adjust alignment as needed */
355 /* Clear the virtual range */
356 Request
.VirtualRange
.Minimum
= 0;
357 Request
.VirtualRange
.Maximum
= 0;
359 /* Check if a fixed allocation was requested*/
360 if (Attributes
& BlMemoryFixed
)
362 /* Force the only available range to be the passed in address */
363 Request
.BaseRange
.Minimum
= BaseAddress
->QuadPart
>> PAGE_SHIFT
;
364 Request
.BaseRange
.Maximum
= Request
.BaseRange
.Minimum
+ Pages
- 1;
368 /* Otherwise, a manual range was specified, use it */
369 Request
.BaseRange
.Minimum
= Range
->Minimum
>> PAGE_SHIFT
;
370 Request
.BaseRange
.Maximum
= Request
.BaseRange
.Minimum
+
371 (Range
->Maximum
>> PAGE_SHIFT
) - 1;
375 /* Otherwise, use any possible range of pages */
376 Request
.BaseRange
.Minimum
= PapMinimumPhysicalPage
;
377 Request
.BaseRange
.Maximum
= MAXULONG
>> PAGE_SHIFT
;
380 /* Check if no type was specified, or if it was invalid */
382 (RangeType
& ~(BL_MM_REQUEST_TOP_DOWN_TYPE
| BL_MM_REQUEST_DEFAULT_TYPE
)))
384 /* Use default type */
385 Request
.Type
= BL_MM_REQUEST_DEFAULT_TYPE
;
389 /* Use the requested type */
390 Request
.Type
= RangeType
;
393 /* Capture the other request parameters */
394 Request
.Alignment
= Alignment
;
395 Request
.Pages
= Pages
;
396 Request
.Flags
= Attributes
;
397 Status
= MmPaAllocatePages(NewList
,
399 &MmMdlUnmappedUnallocated
,
402 if (NT_SUCCESS(Status
))
404 /* We got a descriptor back, return its address */
405 BaseAddress
->QuadPart
= Descriptor
.BasePage
<< PAGE_SHIFT
;
409 /* Restore the nesting depth */
410 MmMdFreeGlobalDescriptors();
411 --MmDescriptorCallTreeCount
;
416 MmPapAllocatePagesInRange (
417 _Inout_ PVOID
* PhysicalAddress
,
418 _In_ BL_MEMORY_TYPE MemoryType
,
419 _In_ ULONGLONG Pages
,
420 _In_ ULONG Attributes
,
421 _In_ ULONG Alignment
,
422 _In_opt_ PBL_ADDRESS_RANGE Range
,
427 PHYSICAL_ADDRESS BaseAddress
;
429 /* Increment nesting depth */
430 ++MmDescriptorCallTreeCount
;
432 /* Check for missing parameters or invalid range */
433 if (!(PhysicalAddress
) ||
435 ((Range
) && (Range
->Minimum
>= Range
->Maximum
)))
437 Status
= STATUS_INVALID_PARAMETER
;
441 /* What translation mode are we using? */
442 if (MmTranslationType
!= BlNone
)
444 /* We don't support virtual memory yet */
445 Status
= STATUS_NOT_IMPLEMENTED
;
450 /* Check if this is a fixed allocation */
451 BaseAddress
.QuadPart
= (Attributes
& BlMemoryFixed
) ? (ULONG_PTR
)*PhysicalAddress
: 0;
453 /* Allocate the pages */
454 Status
= MmPapAllocatePhysicalPagesInRange(&BaseAddress
,
459 (&MmMdlMappedAllocated
!=
460 &MmMdlPersistentMemory
) ?
461 &MmMdlUnmappedAllocated
:
462 &MmMdlMappedAllocated
,
466 /* Return the allocated address */
467 *PhysicalAddress
= (PVOID
)BaseAddress
.LowPart
;
471 /* Restore the nesting depth */
472 MmMdFreeGlobalDescriptors();
473 --MmDescriptorCallTreeCount
;
479 __in PBL_MEMORY_DATA BootMemoryData
,
480 __in ULONG MinimumAllocationCount
484 ULONG ExistingDescriptors
, FinalOffset
;
485 PBL_MEMORY_DESCRIPTOR Descriptor
, NewDescriptor
;
487 /* Initialize physical allocator variables */
488 PapMaximumPhysicalPage
= 0xFFFFFFFFFFFFF;
489 PapMinimumAllocationCount
= MinimumAllocationCount
;
490 PapMinimumPhysicalPage
= 0;
492 /* Initialize all the lists */
493 MmMdInitializeListHead(&MmMdlMappedAllocated
);
494 MmMdInitializeListHead(&MmMdlMappedUnallocated
);
495 MmMdInitializeListHead(&MmMdlFwAllocationTracker
);
496 MmMdInitializeListHead(&MmMdlUnmappedAllocated
);
497 MmMdInitializeListHead(&MmMdlReservedAllocated
);
498 MmMdInitializeListHead(&MmMdlBadMemory
);
499 MmMdInitializeListHead(&MmMdlTruncatedMemory
);
500 MmMdInitializeListHead(&MmMdlPersistentMemory
);
501 MmMdInitializeListHead(&MmMdlUnmappedUnallocated
);
502 MmMdInitializeListHead(&MmMdlCompleteBadMemory
);
504 /* Get the BIOS memory map */
505 Status
= MmFwGetMemoryMap(&MmMdlUnmappedUnallocated
,
506 BL_MM_FLAG_USE_FIRMWARE_FOR_MEMORY_MAP_BUFFERS
|
507 BL_MM_FLAG_REQUEST_COALESCING
);
508 if (NT_SUCCESS(Status
))
511 PLIST_ENTRY listHead
, nextEntry
;
513 /* Loop the NT firmware memory list */
514 EfiPrintf(L
"NT MEMORY MAP\n\r\n");
515 listHead
= &MmMdlUnmappedUnallocated
.ListHead
;
516 nextEntry
= listHead
->Flink
;
517 while (listHead
!= nextEntry
)
519 Descriptor
= CONTAINING_RECORD(nextEntry
, BL_MEMORY_DESCRIPTOR
, ListEntry
);
521 EfiPrintf(L
"Type: %08lX Flags: %08lX Base: 0x%016I64X End: 0x%016I64X\r\n",
524 Descriptor
->BasePage
<< PAGE_SHIFT
,
525 (Descriptor
->BasePage
+ Descriptor
->PageCount
) << PAGE_SHIFT
);
527 nextEntry
= nextEntry
->Flink
;
532 * Because BL supports cross x86-x64 application launches and a LIST_ENTRY
533 * is of variable size, care must be taken here to ensure that we see a
534 * consistent view of descriptors. BL uses some offset magic to figure out
535 * where the data actually starts, since everything is ULONGLONG past the
538 FinalOffset
= BootMemoryData
->MdListOffset
+ BootMemoryData
->DescriptorOffset
;
539 Descriptor
= (PBL_MEMORY_DESCRIPTOR
)((ULONG_PTR
)BootMemoryData
+ FinalOffset
-
540 FIELD_OFFSET(BL_MEMORY_DESCRIPTOR
, BasePage
));
542 /* Scan all of them */
543 ExistingDescriptors
= BootMemoryData
->DescriptorCount
;
544 while (ExistingDescriptors
!= 0)
546 /* Remove this region from our free memory MDL */
547 Status
= MmMdRemoveRegionFromMdlEx(&MmMdlUnmappedUnallocated
,
549 Descriptor
->BasePage
,
550 Descriptor
->PageCount
,
552 if (!NT_SUCCESS(Status
))
554 return STATUS_INVALID_PARAMETER
;
557 /* Build a descriptor for it */
558 NewDescriptor
= MmMdInitByteGranularDescriptor(Descriptor
->Flags
,
560 Descriptor
->BasePage
,
561 Descriptor
->VirtualPage
,
562 Descriptor
->PageCount
);
565 return STATUS_NO_MEMORY
;
568 /* And add this region to the reserved & allocated MDL */
569 Status
= MmMdAddDescriptorToList(&MmMdlReservedAllocated
, NewDescriptor
, 0);
570 if (!NT_SUCCESS(Status
))
575 /* Move on to the next descriptor */
576 ExistingDescriptors
--;
577 Descriptor
= (PBL_MEMORY_DESCRIPTOR
)((ULONG_PTR
)Descriptor
+ BootMemoryData
->DescriptorSize
);
580 /* We are done, so check for any RAM constraints which will make us truncate memory */
581 Status
= BlpMmInitializeConstraints();
582 if (NT_SUCCESS(Status
))
584 /* The Page Allocator has initialized */
585 PapInitializationStatus
= TRUE
;
586 Status
= STATUS_SUCCESS
;
595 BlMmAllocatePhysicalPages(
596 _In_ PPHYSICAL_ADDRESS Address
,
597 _In_ BL_MEMORY_TYPE MemoryType
,
598 _In_ ULONGLONG PageCount
,
599 _In_ ULONG Attributes
,
603 /* Call the physical allocator */
604 return MmPapAllocatePhysicalPagesInRange(Address
,
609 &MmMdlUnmappedAllocated
,
615 BlMmFreePhysicalPages (
616 _In_ PHYSICAL_ADDRESS Address
619 /* Call the physical allocator */
620 EfiPrintf(L
"Leaking memory!\r\n");
621 return STATUS_SUCCESS
;
622 //return MmPapFreePhysicalPages(4, 0, Address);
627 _In_ PLIST_ENTRY MemoryMap
,
628 _In_ PBL_IMAGE_PARAMETERS MemoryParameters
,
629 _In_ ULONG WhichTypes
,
633 BL_MEMORY_DESCRIPTOR_LIST FirmwareMdList
, FullMdList
;
634 BOOLEAN DoFirmware
, DoPersistent
, DoTruncated
, DoBad
;
635 BOOLEAN DoReserved
, DoUnmapUnalloc
, DoUnmapAlloc
;
636 BOOLEAN DoMapAlloc
, DoMapUnalloc
, DoFirmware2
;
637 ULONG LoopCount
, MdListCount
, MdListSize
, Used
;
640 /* Initialize the firmware list if we use it */
641 MmMdInitializeListHead(&FirmwareMdList
);
643 /* Make sure we got our input parameters */
644 if (!(MemoryMap
) || !(MemoryParameters
))
646 return STATUS_INVALID_PARAMETER
;
649 /* Either ask for firmware memory, or don't. Not neither */
650 if ((WhichTypes
& ~BL_MM_INCLUDE_NO_FIRMWARE_MEMORY
) &&
651 (WhichTypes
& ~BL_MM_INCLUDE_ONLY_FIRMWARE_MEMORY
))
653 return STATUS_INVALID_PARAMETER
;
656 /* Either ask for firmware memory, or don't. Not both */
657 if ((WhichTypes
& BL_MM_INCLUDE_NO_FIRMWARE_MEMORY
) &&
658 (WhichTypes
& BL_MM_INCLUDE_ONLY_FIRMWARE_MEMORY
))
660 return STATUS_INVALID_PARAMETER
;
663 /* Initialize the memory map list */
664 InitializeListHead(MemoryMap
);
666 /* Check which types of memory to dump */
667 DoFirmware
= WhichTypes
& BL_MM_INCLUDE_FIRMWARE_MEMORY
;
668 DoPersistent
= WhichTypes
& BL_MM_INCLUDE_PERSISTENT_MEMORY
;
669 DoTruncated
= WhichTypes
& BL_MM_INCLUDE_TRUNCATED_MEMORY
;
670 DoBad
= WhichTypes
& BL_MM_INCLUDE_BAD_MEMORY
;
671 DoReserved
= WhichTypes
& BL_MM_INCLUDE_RESERVED_ALLOCATED
;
672 DoUnmapUnalloc
= WhichTypes
& BL_MM_INCLUDE_UNMAPPED_UNALLOCATED
;
673 DoUnmapAlloc
= WhichTypes
& BL_MM_INCLUDE_UNMAPPED_ALLOCATED
;
674 DoMapAlloc
= WhichTypes
& BL_MM_INCLUDE_MAPPED_ALLOCATED
;
675 DoMapUnalloc
= WhichTypes
& BL_MM_INCLUDE_MAPPED_UNALLOCATED
;
676 DoFirmware2
= WhichTypes
& BL_MM_INCLUDE_FIRMWARE_MEMORY_2
;
678 /* Begin the attempt loop */
682 /* Count how many entries we will need */
684 if (DoMapAlloc
) MdListCount
= MmMdCountList(&MmMdlMappedAllocated
);
685 if (DoMapUnalloc
) MdListCount
+= MmMdCountList(&MmMdlMappedUnallocated
);
686 if (DoUnmapAlloc
) MdListCount
+= MmMdCountList(&MmMdlUnmappedAllocated
);
687 if (DoUnmapUnalloc
) MdListCount
+= MmMdCountList(&MmMdlUnmappedUnallocated
);
688 if (DoReserved
) MdListCount
+= MmMdCountList(&MmMdlReservedAllocated
);
689 if (DoBad
) MdListCount
+= MmMdCountList(&MmMdlBadMemory
);
690 if (DoTruncated
) MdListCount
+= MmMdCountList(&MmMdlTruncatedMemory
);
691 if (DoPersistent
) MdListCount
+= MmMdCountList(&MmMdlPersistentMemory
);
693 /* Plus firmware entries */
696 /* Free the previous entries, if any */
697 MmMdFreeList(&FirmwareMdList
);
699 /* Get the firmware map */
700 Status
= MmFwGetMemoryMap(&FirmwareMdList
, 2);
701 if (!NT_SUCCESS(Status
))
706 /* We overwrite, since this type is exclusive */
707 MdListCount
= MmMdCountList(&FirmwareMdList
);
710 /* Plus firmware entries-2 */
713 /* Free the previous entries, if any */
714 MmMdFreeList(&FirmwareMdList
);
716 /* Get the firmware map */
717 Status
= MmFwGetMemoryMap(&FirmwareMdList
, 0);
718 if (!NT_SUCCESS(Status
))
723 /* We overwrite, since this type is exclusive */
724 MdListCount
= MmMdCountList(&FirmwareMdList
);
727 /* If there's no descriptors, we're done */
730 Status
= STATUS_SUCCESS
;
734 /* Check if the buffer we have is big enough */
735 if (MemoryParameters
->BufferSize
>=
736 (sizeof(BL_MEMORY_DESCRIPTOR
) * MdListCount
))
741 /* It's not, allocate it, with a slack of 4 extra descriptors */
742 MdListSize
= sizeof(BL_MEMORY_DESCRIPTOR
) * (MdListCount
+ 4);
744 /* Except if we weren't asked to */
745 if (!(Flags
& BL_MM_ADD_DESCRIPTOR_ALLOCATE_FLAG
))
747 MemoryParameters
->BufferSize
= MdListSize
;
748 Status
= STATUS_BUFFER_TOO_SMALL
;
752 /* Has it been less than 4 times we've tried this? */
753 if (++LoopCount
<= 4)
755 /* Free the previous attempt, if any */
756 if (MemoryParameters
->BufferSize
)
758 BlMmFreeHeap(MemoryParameters
->Buffer
);
761 /* Allocate a new buffer */
762 MemoryParameters
->BufferSize
= MdListSize
;
763 MemoryParameters
->Buffer
= BlMmAllocateHeap(MdListSize
);
764 if (MemoryParameters
->Buffer
)
771 /* If we got here, we're out of memory after 4 attempts */
772 Status
= STATUS_NO_MEMORY
;
776 /* We should have a buffer by now... */
777 if (MemoryParameters
->Buffer
)
780 RtlZeroMemory(MemoryParameters
->Buffer
,
781 MdListCount
* sizeof(BL_MEMORY_DESCRIPTOR
));
784 /* Initialize our list of descriptors */
785 MmMdInitializeList(&FullMdList
, 0, MemoryMap
);
788 /* Handle mapped, allocated */
791 Status
= MmMdCopyList(&FullMdList
,
792 &MmMdlMappedAllocated
,
793 MemoryParameters
->Buffer
,
799 /* Handle mapped, unallocated */
802 Status
= MmMdCopyList(&FullMdList
,
803 &MmMdlMappedUnallocated
,
804 MemoryParameters
->Buffer
,
810 /* Handle unmapped, allocated */
813 Status
= MmMdCopyList(&FullMdList
,
814 &MmMdlUnmappedAllocated
,
815 MemoryParameters
->Buffer
,
821 /* Handle unmapped, unallocated */
824 Status
= MmMdCopyList(&FullMdList
,
825 &MmMdlUnmappedUnallocated
,
826 MemoryParameters
->Buffer
,
832 /* Handle reserved, allocated */
835 Status
= MmMdCopyList(&FullMdList
,
836 &MmMdlReservedAllocated
,
837 MemoryParameters
->Buffer
,
846 Status
= MmMdCopyList(&FullMdList
,
848 MemoryParameters
->Buffer
,
854 /* Handle truncated */
857 Status
= MmMdCopyList(&FullMdList
,
858 &MmMdlTruncatedMemory
,
859 MemoryParameters
->Buffer
,
865 /* Handle persistent */
868 Status
= MmMdCopyList(&FullMdList
,
869 &MmMdlPersistentMemory
,
870 MemoryParameters
->Buffer
,
876 /* Handle firmware */
879 Status
= MmMdCopyList(&FullMdList
,
881 MemoryParameters
->Buffer
,
887 /* Handle firmware2 */
890 Status
= MmMdCopyList(&FullMdList
,
892 MemoryParameters
->Buffer
,
898 /* Add up the final size */
899 Status
= RtlULongLongToULong(Used
* sizeof(BL_MEMORY_DESCRIPTOR
),
900 &MemoryParameters
->ActualSize
);
903 MmMdFreeList(&FirmwareMdList
);