2 * COPYRIGHT: See COPYING.ARM in the top level directory
3 * PROJECT: ReactOS UEFI Boot Library
4 * FILE: boot/environ/lib/mm/descriptor.c
5 * PURPOSE: Boot Library Memory Manager Descriptor Manager
6 * PROGRAMMER: Alex Ionescu (alex.ionescu@reactos.org)
9 /* INCLUDES ******************************************************************/
13 /* DATA VARIABLES ************************************************************/
15 BL_MEMORY_DESCRIPTOR MmStaticMemoryDescriptors
[512];
16 ULONG MmGlobalMemoryDescriptorCount
;
17 PBL_MEMORY_DESCRIPTOR MmGlobalMemoryDescriptors
;
18 ULONG MmGlobalMemoryDescriptorsUsed
;
19 PBL_MEMORY_DESCRIPTOR MmDynamicMemoryDescriptors
;
20 ULONG MmDynamicMemoryDescriptorCount
;
22 BL_MEMORY_TYPE MmPlatformMemoryTypePrecedence
[] =
29 BlEfiRuntimeCodeMemory
,
30 BlEfiRuntimeDataMemory
,
35 BlConventionalZeroedMemory
38 /* FUNCTIONS *****************************************************************/
41 MmMdpLookupTypePrecedenceIndex (
42 _In_ BL_MEMORY_TYPE Type
47 /* Check the precedence array */
48 for (i
= 0; i
< RTL_NUMBER_OF(MmPlatformMemoryTypePrecedence
); i
++)
50 /* Check for a match */
51 if (MmPlatformMemoryTypePrecedence
[i
] == Type
)
53 /* Return the index */
58 /* Invalid index type */
62 /* The order is Conventional > Other > System > Loader > Application */
65 _In_ BL_MEMORY_TYPE Type1
,
66 _In_ BL_MEMORY_TYPE Type2
69 BL_MEMORY_CLASS Class1
, Class2
;
72 /* It isn't free RAM, but the comparator is -- it succeeds it */
73 if (Type2
== BlConventionalMemory
)
78 /* Descriptor is free RAM -- it precedes */
79 if (Type1
== BlConventionalMemory
)
84 /* Descriptor is not system, application, or loader class -- it precedes */
85 Class1
= Type1
>> BL_MEMORY_CLASS_SHIFT
;
86 if ((Class1
!= BlSystemClass
) &&
87 (Class1
!= BlApplicationClass
) &&
88 (Class1
!= BlLoaderClass
))
93 /* It isn't one of those classes, but the comparator it -- it succeeds it */
94 Class2
= Type2
>> BL_MEMORY_CLASS_SHIFT
;
95 if ((Class2
!= BlSystemClass
) &&
96 (Class2
!= BlApplicationClass
) &&
97 (Class2
!= BlLoaderClass
))
102 /* Descriptor is system class */
103 if (Class1
== BlSystemClass
)
105 /* If the other guy isn't, system wins */
106 if (Class2
!= BlSystemClass
)
111 /* Scan for the descriptor's system precedence index */
112 i
= MmMdpLookupTypePrecedenceIndex(Type1
);
113 j
= MmMdpLookupTypePrecedenceIndex(Type2
);
115 /* Does the current have a valid index? */
121 /* Yes, what about the comparator? */
127 /* Let the indexes fight! */
131 /* Descriptor is not system class, but comparator is -- it succeeds it */
132 if (Class2
== BlSystemClass
)
137 /* Descriptor is loader class -- it preceedes */
138 if (Class1
== BlLoaderClass
)
143 /* It isn't loader class -- if the other guy is, succeed it */
144 return Class2
!= BlLoaderClass
;
148 MmMdpSwitchToDynamicDescriptors (
152 EfiPrintf(L
"Dynamic switch NOT SUPPORTED!!!\r\n");
158 _In_ PBL_MEMORY_DESCRIPTOR MemoryDescriptor
163 /* Check if this is a valid static descriptor */
164 if (((MmDynamicMemoryDescriptors
) &&
165 (MemoryDescriptor
>= MmDynamicMemoryDescriptors
) &&
166 (MemoryDescriptor
< &MmDynamicMemoryDescriptors
[MmDynamicMemoryDescriptorCount
])) ||
167 ((MemoryDescriptor
>= MmStaticMemoryDescriptors
) &&
168 (MemoryDescriptor
< &MmStaticMemoryDescriptors
[RTL_NUMBER_OF(MmStaticMemoryDescriptors
)])))
170 /* It's a global/static descriptor, so just zero it */
171 RtlZeroMemory(MemoryDescriptor
, sizeof(BL_MEMORY_DESCRIPTOR
));
172 Status
= STATUS_SUCCESS
;
176 /* It's a dynamic descriptor, so free it */
177 EfiPrintf(L
"Freeing dynamic descriptors not yet supported\r\n");
179 Status
= STATUS_NOT_IMPLEMENTED
;
187 MmMdpSaveCurrentListPointer (
188 _In_ PBL_MEMORY_DESCRIPTOR_LIST MdList
,
189 _In_ PLIST_ENTRY Current
192 PBL_MEMORY_DESCRIPTOR FirstEntry
, LastEntry
;
194 /* Make sure that this is not a global descriptor and not the first one */
195 FirstEntry
= &MmGlobalMemoryDescriptors
[0];
196 LastEntry
= &MmGlobalMemoryDescriptors
[MmGlobalMemoryDescriptorCount
];
197 if ((((ULONG_PTR
)Current
< (ULONG_PTR
)FirstEntry
) ||
198 ((ULONG_PTR
)Current
>= (ULONG_PTR
)LastEntry
)) &&
199 (Current
!= MdList
->First
))
201 /* Save this as the current pointer */
202 MdList
->This
= Current
;
208 _In_ PBL_MEMORY_DESCRIPTOR_LIST MdList
211 PLIST_ENTRY First
, NextEntry
;
214 /* Iterate the list */
215 for (Count
= 0, First
= MdList
->First
, NextEntry
= First
->Flink
;
217 NextEntry
= NextEntry
->Flink
, Count
++);
219 /* Return the count */
225 _In_ PBL_MEMORY_DESCRIPTOR_LIST MdList
,
227 _In_ PLIST_ENTRY ListHead
230 /* Check if a list was specified */
234 MdList
->First
= ListHead
;
238 /* Otherwise, use the internal, built-in list */
239 InitializeListHead(&MdList
->ListHead
);
240 MdList
->First
= &MdList
->ListHead
;
246 /* Initialize current iterator to nothing */
252 _In_ PBL_MEMORY_DESCRIPTOR_LIST DestinationList
,
253 _In_ PBL_MEMORY_DESCRIPTOR_LIST SourceList
,
254 _In_opt_ PBL_MEMORY_DESCRIPTOR ListDescriptor
,
255 _Out_ PULONG ActualCount
,
262 PLIST_ENTRY First
, NextEntry
;
263 PBL_MEMORY_DESCRIPTOR Descriptor
;
265 /* Both parameters must be present */
266 if (!(DestinationList
) || !(SourceList
))
268 return STATUS_INVALID_PARAMETER
;
272 Status
= STATUS_SUCCESS
;
274 /* Check if a descriptor is being used to store the list */
277 /* See how big it is */
278 Flags
|= BL_MM_ADD_DESCRIPTOR_NEVER_COALESCE_FLAG
;
283 /* We are using our internal descriptors instead */
284 Used
= &MmGlobalMemoryDescriptorsUsed
;
285 ++MmDescriptorCallTreeCount
;
287 /* Use as many as are available */
288 Count
= MmGlobalMemoryDescriptorCount
;
289 ListDescriptor
= MmGlobalMemoryDescriptors
;
292 /* Never truncate descriptors during a list copy */
293 Flags
|= BL_MM_ADD_DESCRIPTOR_NEVER_TRUNCATE_FLAG
;
295 /* Iterate through the list */
296 First
= SourceList
->First
;
297 NextEntry
= First
->Flink
;
298 while ((NextEntry
!= First
) && (NT_SUCCESS(Status
)))
300 /* Make sure there's still space */
303 Status
= STATUS_NO_MEMORY
;
307 /* Get the current descriptor */
308 Descriptor
= CONTAINING_RECORD(NextEntry
,
309 BL_MEMORY_DESCRIPTOR
,
312 /* Copy it into one of the descriptors we have */
313 RtlCopyMemory(&ListDescriptor
[*Used
],
315 sizeof(*Descriptor
));
317 /* Add it to the list we have */
318 Status
= MmMdAddDescriptorToList(DestinationList
,
319 &ListDescriptor
[*Used
],
323 /* Move to the next entry */
324 NextEntry
= NextEntry
->Flink
;
327 /* Check if the global descriptors were used */
328 if (ListDescriptor
== MmGlobalMemoryDescriptors
)
330 /* Unwind our usage */
331 MmMdFreeGlobalDescriptors();
332 --MmDescriptorCallTreeCount
;
335 /* Return back to caller */
340 MmMdRemoveDescriptorFromList (
341 _In_ PBL_MEMORY_DESCRIPTOR_LIST MdList
,
342 _In_ PBL_MEMORY_DESCRIPTOR Entry
345 /* Remove the entry */
346 RemoveEntryList(&Entry
->ListEntry
);
348 /* Check if this was the current link */
349 if (MdList
->This
== &Entry
->ListEntry
)
351 /* Remove the current link and set the next one */
353 MmMdpSaveCurrentListPointer(MdList
, Entry
->ListEntry
.Blink
);
359 _In_ PBL_MEMORY_DESCRIPTOR_LIST MdList
362 PLIST_ENTRY FirstEntry
, NextEntry
;
363 PBL_MEMORY_DESCRIPTOR Entry
;
365 /* Go over every descriptor from the top */
366 FirstEntry
= MdList
->First
;
367 NextEntry
= FirstEntry
->Flink
;
368 while (NextEntry
!= FirstEntry
)
370 /* Remove and free each one */
371 Entry
= CONTAINING_RECORD(NextEntry
, BL_MEMORY_DESCRIPTOR
, ListEntry
);
372 NextEntry
= NextEntry
->Flink
;
373 MmMdRemoveDescriptorFromList(MdList
, Entry
);
374 MmMdFreeDescriptor(Entry
);
378 PBL_MEMORY_DESCRIPTOR
379 MmMdInitByteGranularDescriptor (
381 _In_ BL_MEMORY_TYPE Type
,
382 _In_ ULONGLONG BasePage
,
383 _In_ ULONGLONG VirtualPage
,
384 _In_ ULONGLONG PageCount
387 PBL_MEMORY_DESCRIPTOR MemoryDescriptor
;
389 /* If we're out of descriptors, bail out */
390 if (MmGlobalMemoryDescriptorsUsed
>= MmGlobalMemoryDescriptorCount
)
392 EfiPrintf(L
"Out of descriptors!\r\n");
397 /* Take one of the available descriptors and fill it out */
398 MemoryDescriptor
= &MmGlobalMemoryDescriptors
[MmGlobalMemoryDescriptorsUsed
];
399 MemoryDescriptor
->BasePage
= BasePage
;
400 MemoryDescriptor
->VirtualPage
= VirtualPage
;
401 MemoryDescriptor
->PageCount
= PageCount
;
402 MemoryDescriptor
->Flags
= Flags
;
403 MemoryDescriptor
->Type
= Type
;
404 InitializeListHead(&MemoryDescriptor
->ListEntry
);
406 /* Increment the count and return the descriptor */
407 MmGlobalMemoryDescriptorsUsed
++;
408 return MemoryDescriptor
;
412 MmMdTruncateDescriptors (
413 _In_ PBL_MEMORY_DESCRIPTOR_LIST MdList
,
414 _In_ PBL_MEMORY_DESCRIPTOR_LIST NewList
,
415 _In_ ULONGLONG BasePage
418 PLIST_ENTRY ListHead
, NextEntry
;
419 PBL_MEMORY_DESCRIPTOR Descriptor
, NewDescriptor
;
420 ULONGLONG FoundEndPage
;
422 /* Search the descriptor list */
423 ListHead
= MdList
->First
;
424 NextEntry
= ListHead
->Flink
;
425 while (NextEntry
!= ListHead
)
427 /* Get the current descriptor */
428 Descriptor
= CONTAINING_RECORD(NextEntry
,
429 BL_MEMORY_DESCRIPTOR
,
432 /* Go to the next entry in case we have to remove */
433 NextEntry
= NextEntry
->Flink
;
435 /* Don't touch anything else but free RAM */
436 if (((Descriptor
->Type
>> BL_MEMORY_CLASS_SHIFT
) == BlSystemClass
) &&
437 (Descriptor
->Type
!= BlConventionalMemory
))
442 /* Check if this page is within the descriptor's region */
443 FoundEndPage
= Descriptor
->BasePage
+ Descriptor
->PageCount
;
444 if (BasePage
> Descriptor
->BasePage
)
446 /* Check if it doesn't go beyond the descriptor */
447 if (BasePage
< FoundEndPage
)
449 /* Create a new descriptor to describe this region */
450 EfiPrintf(L
"Truncating descriptor type %lx base: %llx end: %llx\r\n",
451 Descriptor
->Type
, Descriptor
->BasePage
, FoundEndPage
);
452 NewDescriptor
= MmMdInitByteGranularDescriptor(Descriptor
->Flags
,
456 FoundEndPage
- BasePage
);
459 return STATUS_NO_MEMORY
;
462 /* Cut off this descriptor to make it shorter */
463 Descriptor
->PageCount
= BasePage
- Descriptor
->BasePage
;
465 /* Add the region to the new list */
466 MmMdAddDescriptorToList(NewList
,
468 BL_MM_ADD_DESCRIPTOR_COALESCE_FLAG
);
473 /* This whole descriptor covers the truncated area */
474 EfiPrintf(L
"Truncating descriptor type %lx base: %llx end: %llx\r\n",
475 Descriptor
->Type
, Descriptor
->BasePage
, FoundEndPage
);
476 MmMdRemoveDescriptorFromList(MdList
, Descriptor
);
477 MmMdAddDescriptorToList(NewList
,
479 BL_MM_ADD_DESCRIPTOR_COALESCE_FLAG
);
483 /* All good if we got here */
484 return STATUS_SUCCESS
;
488 MmMdpTruncateDescriptor (
489 _In_ PBL_MEMORY_DESCRIPTOR_LIST MdList
,
490 _In_ PBL_MEMORY_DESCRIPTOR MemoryDescriptor
,
494 PBL_MEMORY_DESCRIPTOR NextDescriptor
, PreviousDescriptor
;
495 PLIST_ENTRY NextEntry
, PreviousEntry
;
496 ULONGLONG EndPage
, PreviousEndPage
;// , NextEndPage;
498 /* Get the next descriptor */
499 NextEntry
= MemoryDescriptor
->ListEntry
.Flink
;
500 NextDescriptor
= CONTAINING_RECORD(NextEntry
, BL_MEMORY_DESCRIPTOR
, ListEntry
);
502 /* Get the previous descriptor */
503 PreviousEntry
= MemoryDescriptor
->ListEntry
.Blink
;
504 PreviousDescriptor
= CONTAINING_RECORD(PreviousEntry
, BL_MEMORY_DESCRIPTOR
, ListEntry
);
506 /* Calculate end pages */
507 EndPage
= MemoryDescriptor
->BasePage
+ MemoryDescriptor
->PageCount
;
508 //NextEndPage = NextDescriptor->BasePage + NextDescriptor->PageCount;
509 PreviousEndPage
= PreviousDescriptor
->BasePage
+ PreviousDescriptor
->PageCount
;
511 /* Check for backward overlap */
512 if ((PreviousEntry
!= MdList
->First
) && (MemoryDescriptor
->BasePage
< PreviousEndPage
))
514 EfiPrintf(L
"Overlap detected -- this is unexpected on x86/x64 platforms\r\n");
518 /* Check for forward overlap */
519 if ((NextEntry
!= MdList
->First
) && (NextDescriptor
->BasePage
< EndPage
))
521 EfiPrintf(L
"Overlap detected -- this is unexpected on x86/x64 platforms\r\n");
530 MmMdpCoalesceDescriptor (
531 _In_ PBL_MEMORY_DESCRIPTOR_LIST MdList
,
532 _In_ PBL_MEMORY_DESCRIPTOR MemoryDescriptor
,
536 PBL_MEMORY_DESCRIPTOR NextDescriptor
, PreviousDescriptor
;
537 PLIST_ENTRY NextEntry
, PreviousEntry
;
538 ULONGLONG EndPage
, PreviousEndPage
, PreviousMappedEndPage
, MappedEndPage
;
540 /* Get the next descriptor */
541 NextEntry
= MemoryDescriptor
->ListEntry
.Flink
;
542 NextDescriptor
= CONTAINING_RECORD(NextEntry
, BL_MEMORY_DESCRIPTOR
, ListEntry
);
544 /* Get the previous descriptor */
545 PreviousEntry
= MemoryDescriptor
->ListEntry
.Blink
;
546 PreviousDescriptor
= CONTAINING_RECORD(PreviousEntry
, BL_MEMORY_DESCRIPTOR
, ListEntry
);
548 /* Calculate end pages */
549 EndPage
= MemoryDescriptor
->BasePage
+ MemoryDescriptor
->PageCount
;
550 MappedEndPage
= MemoryDescriptor
->BasePage
+ MemoryDescriptor
->PageCount
;
551 PreviousMappedEndPage
= PreviousDescriptor
->VirtualPage
+ PreviousDescriptor
->PageCount
;
552 PreviousEndPage
= PreviousDescriptor
->BasePage
+ PreviousDescriptor
->PageCount
;
553 PreviousMappedEndPage
= PreviousDescriptor
->VirtualPage
+ PreviousDescriptor
->PageCount
;
555 /* Check if the previous entry touches the current entry, and is compatible */
556 if ((PreviousEntry
!= MdList
->First
) &&
557 (PreviousDescriptor
->Type
== MemoryDescriptor
->Type
) &&
558 ((PreviousDescriptor
->Flags
^ MemoryDescriptor
->Flags
) & 0x1B19FFFF) &&
559 (PreviousEndPage
== MemoryDescriptor
->BasePage
) &&
560 ((!(MemoryDescriptor
->VirtualPage
) && !(PreviousDescriptor
->VirtualPage
)) ||
561 ((MemoryDescriptor
->VirtualPage
) && (PreviousDescriptor
->VirtualPage
) &&
562 (PreviousMappedEndPage
== MemoryDescriptor
->VirtualPage
))))
564 EfiPrintf(L
"Previous descriptor coalescable!\r\n");
567 /* CHeck if the current entry touches the next entry, and is compatible */
568 if ((NextEntry
!= MdList
->First
) &&
569 (NextDescriptor
->Type
== MemoryDescriptor
->Type
) &&
570 ((NextDescriptor
->Flags
^ MemoryDescriptor
->Flags
) & 0x1B19FFFF) &&
571 (EndPage
== NextDescriptor
->BasePage
) &&
572 ((!(MemoryDescriptor
->VirtualPage
) && !(NextDescriptor
->VirtualPage
)) ||
573 ((MemoryDescriptor
->VirtualPage
) && (NextDescriptor
->VirtualPage
) &&
574 (MappedEndPage
== NextDescriptor
->VirtualPage
))))
576 EfiPrintf(L
"Next descriptor coalescable!\r\n");
584 MmMdAddDescriptorToList (
585 _In_ PBL_MEMORY_DESCRIPTOR_LIST MdList
,
586 _In_ PBL_MEMORY_DESCRIPTOR MemoryDescriptor
,
590 PLIST_ENTRY ThisEntry
, FirstEntry
;
591 PBL_MEMORY_DESCRIPTOR ThisDescriptor
;
593 /* Arguments must be present */
594 if (!(MdList
) || !(MemoryDescriptor
))
596 return STATUS_INVALID_PARAMETER
;
599 /* Check if coalescing is forcefully disabled */
600 if (Flags
& BL_MM_ADD_DESCRIPTOR_NEVER_COALESCE_FLAG
)
602 /* Then we won't be coalescing */
603 Flags
&= ~BL_MM_ADD_DESCRIPTOR_COALESCE_FLAG
;
605 else if (MemoryDescriptor
->Flags
& BlMemoryCoalesced
)
607 /* Coalesce if the descriptor requires it */
608 Flags
|= BL_MM_ADD_DESCRIPTOR_COALESCE_FLAG
;
611 /* Check if truncation is forcefully disabled */
612 if (Flags
& BL_MM_ADD_DESCRIPTOR_NEVER_TRUNCATE_FLAG
)
614 Flags
&= ~BL_MM_ADD_DESCRIPTOR_TRUNCATE_FLAG
;
617 /* Update the current list pointer if the descriptor requires it */
618 if (MemoryDescriptor
->Flags
& BlMemoryUpdate
)
620 Flags
|= BL_MM_ADD_DESCRIPTOR_UPDATE_LIST_POINTER_FLAG
;
623 /* Get the current descriptor */
624 ThisEntry
= MdList
->This
;
625 ThisDescriptor
= CONTAINING_RECORD(ThisEntry
, BL_MEMORY_DESCRIPTOR
, ListEntry
);
627 /* Also get the first descriptor */
628 FirstEntry
= MdList
->First
;
630 /* Check if there's no current pointer, or if it's higher than the new one */
632 (MemoryDescriptor
->BasePage
<= ThisDescriptor
->BasePage
))
634 /* Start at the first descriptor instead, since current is past us */
635 ThisEntry
= FirstEntry
->Flink
;
638 /* Loop until we find the right location to insert */
639 while (ThisEntry
!= FirstEntry
)
641 /* Get the descriptor part of this entry */
642 ThisDescriptor
= CONTAINING_RECORD(ThisEntry
, BL_MEMORY_DESCRIPTOR
, ListEntry
);
644 /* Is the address smaller, or equal but more important? */
645 if ((MemoryDescriptor
->BasePage
< ThisDescriptor
->BasePage
) ||
646 ((MemoryDescriptor
->BasePage
== ThisDescriptor
->BasePage
) &&
647 (MmMdpHasPrecedence(MemoryDescriptor
->Type
, ThisDescriptor
->Type
))))
649 /* Then insert right here */
650 InsertTailList(ThisEntry
, &MemoryDescriptor
->ListEntry
);
654 /* Try the next entry */
655 ThisEntry
= ThisEntry
->Flink
;
658 /* Then we didn't find a good match, so insert it right here */
659 InsertTailList(FirstEntry
, &MemoryDescriptor
->ListEntry
);
662 /* Do we have to truncate? */
663 if (Flags
& BL_MM_ADD_DESCRIPTOR_TRUNCATE_FLAG
)
665 /* Do it and then exit */
666 if (MmMdpTruncateDescriptor(MdList
, MemoryDescriptor
, Flags
))
668 return STATUS_SUCCESS
;
672 /* Do we have to coalesce? */
673 if (Flags
& BL_MM_ADD_DESCRIPTOR_COALESCE_FLAG
)
675 /* Do it and then exit */
676 if (MmMdpCoalesceDescriptor(MdList
, MemoryDescriptor
, Flags
))
678 return STATUS_SUCCESS
;
682 /* Do we have to update the current pointer? */
683 if (Flags
& BL_MM_ADD_DESCRIPTOR_UPDATE_LIST_POINTER_FLAG
)
686 MmMdpSaveCurrentListPointer(MdList
, &MemoryDescriptor
->ListEntry
);
690 return STATUS_SUCCESS
;
694 MmMdRemoveRegionFromMdlEx (
695 _In_ PBL_MEMORY_DESCRIPTOR_LIST MdList
,
697 _In_ ULONGLONG BasePage
,
698 _In_ ULONGLONG PageCount
,
699 _Out_opt_ PBL_MEMORY_DESCRIPTOR_LIST NewMdList
702 BOOLEAN HaveNewList
, UseVirtualPage
;
704 PLIST_ENTRY ListHead
, NextEntry
;
705 PBL_MEMORY_DESCRIPTOR Descriptor
, NewDescriptor
, ListDescriptor
;
706 BL_MEMORY_DESCRIPTOR OldDescriptor
;
707 ULONGLONG RegionSize
;
708 ULONGLONG FoundBasePage
, FoundEndPage
, FoundPageCount
, EndPage
, VirtualPage
;
710 /* Set initial status */
711 Status
= STATUS_SUCCESS
;
712 ListDescriptor
= NULL
;
713 NewDescriptor
= NULL
;
716 /* Check if removed descriptors should go into a new list */
717 if (NewMdList
!= NULL
)
720 MmMdInitializeList(NewMdList
, MdList
->Type
, NULL
);
722 /* Remember for later */
726 /* Is the region being removed physical? */
727 UseVirtualPage
= FALSE
;
728 if (!(Flags
& BL_MM_REMOVE_VIRTUAL_REGION_FLAG
))
730 /* Is this a list of virtual descriptors? */
731 if (MdList
->Type
== BlMdVirtual
)
733 /* Request is nonsensical, fail */
734 Status
= STATUS_INVALID_PARAMETER
;
740 /* Is this a list of physical descriptors? */
741 if (MdList
->Type
== BlMdPhysical
)
743 /* We'll have to use the virtual page instead */
744 UseVirtualPage
= TRUE
;
749 ListHead
= MdList
->First
;
750 NextEntry
= ListHead
->Flink
;
751 while (NextEntry
!= ListHead
)
753 /* Get the descriptor */
754 Descriptor
= CONTAINING_RECORD(NextEntry
, BL_MEMORY_DESCRIPTOR
, ListEntry
);
756 /* Extract range details */
757 FoundBasePage
= UseVirtualPage
? Descriptor
->VirtualPage
: Descriptor
->BasePage
;
758 FoundPageCount
= Descriptor
->PageCount
;
759 FoundEndPage
= FoundBasePage
+ FoundPageCount
;
760 EndPage
= PageCount
+ BasePage
;
762 /* Make a copy of the original descriptor */
763 OldDescriptor
= *Descriptor
;
765 /* Check if the region to be removed starts after the found region starts */
766 if ((BasePage
> FoundBasePage
) || (FoundBasePage
>= EndPage
))
768 /* Check if the region ends after the found region */
769 if ((BasePage
>= FoundEndPage
) || (FoundEndPage
> EndPage
))
771 /* Check if the found region starts after the region or ends before the region */
772 if ((FoundBasePage
>= BasePage
) || (EndPage
>= FoundEndPage
))
774 /* This is a fully-mapped descriptor -- change nothing */
775 OldDescriptor
.PageCount
= 0;
779 /* This descriptor fully covers the entire allocation */
780 FoundBasePage
= Descriptor
->BasePage
;
781 VirtualPage
= Descriptor
->VirtualPage
;
782 FoundPageCount
= BasePage
- FoundBasePage
;
784 /* This is how many pages we will eat away from the descriptor */
785 RegionSize
= FoundPageCount
+ PageCount
;
787 /* Update the descriptor to account for the consumed pages */
788 Descriptor
->BasePage
+= RegionSize
;
789 Descriptor
->PageCount
-= RegionSize
;
792 Descriptor
->VirtualPage
+= RegionSize
;
795 /* Initialize a descriptor for the start of the region */
796 NewDescriptor
= MmMdInitByteGranularDescriptor(Descriptor
->Flags
,
803 Status
= STATUS_NO_MEMORY
;
807 /* Add it into the list */
808 Status
= MmMdAddDescriptorToList(MdList
, NewDescriptor
, Flags
);
809 if (!NT_SUCCESS(Status
))
811 Status
= STATUS_NO_MEMORY
;
815 /* Don't free it on exit path */
816 NewDescriptor
= NULL
;
818 /* Adjust the leftover descriptor */
819 OldDescriptor
.BasePage
+= FoundPageCount
;
820 OldDescriptor
.PageCount
= PageCount
;
821 if (OldDescriptor
.VirtualPage
)
823 OldDescriptor
.VirtualPage
+= FoundPageCount
;
829 /* This descriptor contains the entire allocation */
830 RegionSize
= FoundEndPage
- BasePage
;
831 Descriptor
->PageCount
-= RegionSize
;
833 /* Adjust the leftover descriptor */
834 OldDescriptor
.BasePage
+= Descriptor
->PageCount
;
835 OldDescriptor
.PageCount
= RegionSize
;
836 if (OldDescriptor
.VirtualPage
)
838 OldDescriptor
.VirtualPage
+= FoundPageCount
;
842 /* Go to the next entry */
843 NextEntry
= NextEntry
->Flink
;
848 * This descriptor contains the end of the allocation. It may:
850 * - Contain the full allocation (i.e.: the start is aligned)
851 * - Contain parts of the end of the allocation (i.e.: the end is beyond)
852 * - Contain the entire tail end of the allocation (i..e:the end is within)
854 * So first, figure out if we cover the entire end or not
856 if (EndPage
< FoundEndPage
)
858 /* The allocation goes past the end of this descriptor */
859 FoundEndPage
= EndPage
;
862 /* This is how many pages we will eat away from the descriptor */
863 FoundPageCount
= FoundEndPage
- FoundBasePage
;
865 /* Update the descriptor to account for the consumed pages */
866 Descriptor
->BasePage
+= FoundPageCount
;
867 Descriptor
->PageCount
-= FoundPageCount
;
868 if (Descriptor
->VirtualPage
)
870 Descriptor
->VirtualPage
+= FoundPageCount
;
873 /* Go to the next entry */
874 NextEntry
= NextEntry
->Flink
;
876 /* Check if the descriptor is now empty */
877 if (!Descriptor
->PageCount
)
880 MmMdRemoveDescriptorFromList(MdList
, Descriptor
);
882 /* Check if we're supposed to insert it into a new list */
885 /* This is the one to add */
886 ListDescriptor
= Descriptor
;
890 /* Nope -- just get rid of it */
891 MmMdFreeDescriptor(Descriptor
);
896 /* Is there a remainder descriptor, and do we have a list for it */
897 if ((OldDescriptor
.PageCount
) && (HaveNewList
))
899 /* Did we already chop off the descriptor? */
902 /* Use what we previously chopped */
903 *ListDescriptor
= OldDescriptor
;
907 /* First time, so build a descriptor to describe the leftover */
908 ListDescriptor
= MmMdInitByteGranularDescriptor(OldDescriptor
.Flags
,
910 OldDescriptor
.BasePage
,
911 OldDescriptor
.VirtualPage
,
912 OldDescriptor
.PageCount
);
915 Status
= STATUS_NO_MEMORY
;
919 /* Add it into the list */
920 Status
= MmMdAddDescriptorToList(NewMdList
, ListDescriptor
, 0);
921 if (!NT_SUCCESS(Status
))
926 /* Don't free on exit path */
927 ListDescriptor
= NULL
;
933 /* Check for failure cleanup */
934 if (!NT_SUCCESS(Status
))
936 /* Did we have to build a new list? */
939 /* Free and re-initialize it */
940 MmMdFreeList(NewMdList
);
941 MmMdInitializeList(NewMdList
, MdList
->Type
, NULL
);
944 /* Check if we had a list descriptor, and free it */
947 MmMdFreeDescriptor(ListDescriptor
);
950 /* Check if we had a new descriptor, and free it */
953 MmMdFreeDescriptor(NewDescriptor
);
961 PBL_MEMORY_DESCRIPTOR
962 MmMdFindDescriptorFromMdl (
963 _In_ PBL_MEMORY_DESCRIPTOR_LIST MdList
,
969 PLIST_ENTRY NextEntry
, ListHead
;
970 PBL_MEMORY_DESCRIPTOR Current
;
973 /* Assume physical */
976 /* Check if the caller wants physical memory */
977 if (!(Flags
& BL_MM_REMOVE_VIRTUAL_REGION_FLAG
))
979 /* Check if this is a virtual memory list */
980 if (MdList
->Type
== BlMdVirtual
)
982 /* We won't find anything */
986 else if (MdList
->Type
== BlMdPhysical
)
988 /* Otherwise, caller wants virtual, but this is a physical list */
990 NextEntry
= MdList
->First
->Flink
;
993 /* Check if this is a physical search */
996 /* Check if we can use the current pointer */
997 NextEntry
= MdList
->This
;
1000 /* We can't -- start at the beginning */
1001 NextEntry
= MdList
->First
->Flink
;
1005 /* If the page is below the current pointer, restart */
1006 Current
= CONTAINING_RECORD(NextEntry
, BL_MEMORY_DESCRIPTOR
, ListEntry
);
1007 if (Page
< Current
->BasePage
)
1009 NextEntry
= MdList
->First
->Flink
;
1014 /* Loop the list of descriptors */
1015 ListHead
= MdList
->First
;
1016 while (NextEntry
!= ListHead
)
1018 /* Get the current one */
1019 Current
= CONTAINING_RECORD(NextEntry
, BL_MEMORY_DESCRIPTOR
, ListEntry
);
1021 /* Check if we are looking for virtual memory */
1024 /* Use the base address */
1025 BasePage
= Current
->VirtualPage
;
1030 BasePage
= Current
->BasePage
;
1033 /* If this is a virtual descriptor, make sure it has a base address */
1034 if ((!(IsVirtual
) || (BasePage
)) &&
1035 (BasePage
<= Page
) &&
1036 (Page
< (BasePage
+ Current
->PageCount
)))
1038 /* The descriptor fits the page being requested */
1042 /* Try the next one */
1043 NextEntry
= NextEntry
->Flink
;
1046 /* Nothing found if we're here */
1050 PBL_MEMORY_DESCRIPTOR
1051 MmMdFindDescriptor (
1052 _In_ ULONG WhichList
,
1057 PBL_MEMORY_DESCRIPTOR FoundDescriptor
;
1059 /* Check if the caller is looking for mapped, allocated memory */
1060 if (WhichList
& BL_MM_INCLUDE_MAPPED_ALLOCATED
)
1062 /* Find a descriptor in that list */
1063 FoundDescriptor
= MmMdFindDescriptorFromMdl(&MmMdlMappedAllocated
, Flags
, Page
);
1064 if (FoundDescriptor
)
1067 return FoundDescriptor
;
1071 /* Check if the caller is looking for mapped, unallocated memory */
1072 if (WhichList
& BL_MM_INCLUDE_MAPPED_UNALLOCATED
)
1074 /* Find a descriptor in that list */
1075 FoundDescriptor
= MmMdFindDescriptorFromMdl(&MmMdlMappedUnallocated
, Flags
, Page
);
1076 if (FoundDescriptor
)
1079 return FoundDescriptor
;
1083 /* Check if the caller is looking for unmapped, allocated memory */
1084 if (WhichList
& BL_MM_INCLUDE_UNMAPPED_ALLOCATED
)
1086 /* Find a descriptor in that list */
1087 FoundDescriptor
= MmMdFindDescriptorFromMdl(&MmMdlUnmappedAllocated
, Flags
, Page
);
1088 if (FoundDescriptor
)
1091 return FoundDescriptor
;
1095 /* Check if the caller is looking for unmapped, unallocated memory */
1096 if (WhichList
& BL_MM_INCLUDE_UNMAPPED_UNALLOCATED
)
1098 /* Find a descriptor in that list */
1099 FoundDescriptor
= MmMdFindDescriptorFromMdl(&MmMdlUnmappedUnallocated
, Flags
, Page
);
1100 if (FoundDescriptor
)
1103 return FoundDescriptor
;
1107 /* Check if the caller is looking for reserved, allocated memory */
1108 if (WhichList
& BL_MM_INCLUDE_RESERVED_ALLOCATED
)
1110 /* Find a descriptor in that list */
1111 FoundDescriptor
= MmMdFindDescriptorFromMdl(&MmMdlReservedAllocated
, Flags
, Page
);
1112 if (FoundDescriptor
)
1115 return FoundDescriptor
;
1119 /* Check if the caller is looking for bad memory */
1120 if (WhichList
& BL_MM_INCLUDE_BAD_MEMORY
)
1122 /* Find a descriptor in that list */
1123 FoundDescriptor
= MmMdFindDescriptorFromMdl(&MmMdlBadMemory
, Flags
, Page
);
1124 if (FoundDescriptor
)
1127 return FoundDescriptor
;
1131 /* Check if the caller is looking for truncated memory */
1132 if (WhichList
& BL_MM_INCLUDE_TRUNCATED_MEMORY
)
1134 /* Find a descriptor in that list */
1135 FoundDescriptor
= MmMdFindDescriptorFromMdl(&MmMdlTruncatedMemory
, Flags
, Page
);
1136 if (FoundDescriptor
)
1139 return FoundDescriptor
;
1143 /* Check if the caller is looking for persistent memory */
1144 if (WhichList
& BL_MM_INCLUDE_PERSISTENT_MEMORY
)
1146 /* Find a descriptor in that list */
1147 FoundDescriptor
= MmMdFindDescriptorFromMdl(&MmMdlPersistentMemory
, Flags
, Page
);
1148 if (FoundDescriptor
)
1151 return FoundDescriptor
;
1155 /* Nothing if we got here */
1160 MmMdFindSatisfyingRegion (
1161 _In_ PBL_MEMORY_DESCRIPTOR Descriptor
,
1162 _Out_ PBL_MEMORY_DESCRIPTOR NewDescriptor
,
1163 _In_ ULONGLONG Pages
,
1164 _In_ PBL_ADDRESS_RANGE BaseRange
,
1165 _In_ PBL_ADDRESS_RANGE VirtualRange
,
1166 _In_ BOOLEAN TopDown
,
1167 _In_ BL_MEMORY_TYPE MemoryType
,
1169 _In_ ULONG Alignment
1172 ULONGLONG BaseMin
, BaseMax
, AlignedMin
;
1173 ULONGLONG VirtualPage
, BasePage
;
1174 ULONGLONG BaseDelta
, AlignedBase
;
1175 ULONGLONG VirtualMin
, VirtualMax
;
1177 /* Extract the minimum and maximum range */
1178 BaseMin
= BaseRange
->Minimum
;
1179 BaseMax
= BaseRange
->Maximum
;
1181 /* Don't go below where the descriptor starts */
1182 if (BaseMin
< Descriptor
->BasePage
)
1184 BaseMin
= Descriptor
->BasePage
;
1187 /* Don't go beyond where the descriptor ends */
1188 if (BaseMax
> (Descriptor
->BasePage
+ Descriptor
->PageCount
- 1))
1190 BaseMax
= (Descriptor
->BasePage
+ Descriptor
->PageCount
- 1);
1193 /* Check for start overflow */
1194 if (BaseMin
> BaseMax
)
1199 /* Align the base as required */
1202 AlignedMin
= ALIGN_UP_BY(BaseMin
, Alignment
);
1206 AlignedMin
= BaseMin
;
1209 /* Check for range overflow */
1210 if (((AlignedMin
+ Pages
- 1) < AlignedMin
) || ((AlignedMin
+ Pages
- 1) > BaseMax
))
1215 /* Check if this was a top-down request */
1218 /* Then get the highest page possible */
1219 BasePage
= BaseMax
- Pages
+ 1;
1222 /* Align it as needed */
1223 AlignedBase
= ALIGN_DOWN_BY(BasePage
, Alignment
);
1227 AlignedBase
= BasePage
;
1230 /* Calculate the delta between max address and our aligned base */
1231 BaseDelta
= BasePage
- AlignedBase
;
1232 BasePage
-= BaseDelta
;
1236 /* Otherwise, get the lowest page possible */
1237 BasePage
= AlignedMin
;
1241 /* If a virtual address range was passed in, this must be a virtual descriptor */
1242 if (((VirtualRange
->Minimum
) || (VirtualRange
->Maximum
)) &&
1243 !(Descriptor
->VirtualPage
))
1248 /* Any mapped page already? */
1249 if (Descriptor
->VirtualPage
)
1251 /* Get virtual min/max */
1252 VirtualMin
= VirtualRange
->Minimum
;
1253 VirtualMax
= VirtualRange
->Maximum
;
1255 /* Don't go below where the descriptor maps */
1256 if (VirtualMin
<= Descriptor
->VirtualPage
)
1258 VirtualMin
= Descriptor
->VirtualPage
;
1261 /* Don't go above where the descriptor maps */
1262 if (VirtualMax
>= (Descriptor
->VirtualPage
+ Descriptor
->PageCount
- 1))
1264 VirtualMax
= Descriptor
->VirtualPage
+ Descriptor
->PageCount
- 1;
1267 /* Don't let the base overflow */
1268 if (VirtualMin
> VirtualMax
)
1273 /* Adjust the base by the alignment delta */
1274 VirtualMin
+= AlignedMin
- BaseMin
;
1276 /* Check that the bounds don't overflow or underflow */
1277 if (((VirtualMin
+ Pages
- 1) < VirtualMin
) ||
1278 ((VirtualMin
+ Pages
- 1) > VirtualMax
))
1283 /* Finally, pick the correct address based on direction */
1286 /* Highest possible base address, aligned */
1287 VirtualPage
= VirtualMax
- Pages
+ 1 - BaseDelta
;
1291 /* Lowest possible base address, aligned */
1292 VirtualPage
= VirtualMin
;
1297 /* Nothing to worry about */
1301 /* Bail out if the memory type attributes don't match */
1302 if ((((Flags
& 0xFF) & (Descriptor
->Flags
& 0xFF)) != (Flags
& 0xFF)) ||
1303 (((Flags
& 0xFF00) & (Descriptor
->Flags
& 0xFF00)) != (Flags
& 0xFF00)))
1305 EfiPrintf(L
"Incorrect memory attributes\r\n");
1309 /* Bail out if the allocation flags don't match */
1310 if (((Flags
^ Descriptor
->Flags
) & (BlMemoryRuntime
| BlMemoryBelow1MB
| BlMemoryLargePages
)))
1312 //EfiPrintf(L"Incorrect memory allocation flags\r\n");
1316 /* Bail out if the type doesn't match */
1317 if (Descriptor
->Type
!= MemoryType
)
1319 //EfiPrintf(L"Incorrect descriptor type: %lx %lx\r\n", Descriptor->Type, MemoryType);
1323 /* We have a matching region, fill out the descriptor for it */
1324 NewDescriptor
->BasePage
= BasePage
;
1325 NewDescriptor
->PageCount
= Pages
;
1326 NewDescriptor
->Type
= Descriptor
->Type
;
1327 NewDescriptor
->VirtualPage
= VirtualPage
;
1328 NewDescriptor
->Flags
= Descriptor
->Flags
;
1329 //EfiPrintf(L"Found a matching descriptor: %08I64X with %08I64X pages\r\n", BasePage, Pages);
1334 MmMdFreeGlobalDescriptors (
1338 PBL_MEMORY_DESCRIPTOR Descriptor
, OldDescriptor
;
1340 PLIST_ENTRY OldFlink
, OldBlink
;
1342 /* Make sure we're not int middle of a call using a descriptor */
1343 if (MmDescriptorCallTreeCount
!= 1)
1348 /* Loop every current global descriptor */
1349 while (Index
< MmGlobalMemoryDescriptorsUsed
)
1351 /* Does it have any valid pages? */
1352 OldDescriptor
= &MmGlobalMemoryDescriptors
[Index
];
1353 if (OldDescriptor
->PageCount
)
1355 /* Allocate a copy of it */
1356 Descriptor
= BlMmAllocateHeap(sizeof(*Descriptor
));
1362 /* Save the links */
1363 OldBlink
= OldDescriptor
->ListEntry
.Blink
;
1364 OldFlink
= OldDescriptor
->ListEntry
.Flink
;
1367 *Descriptor
= *OldDescriptor
;
1370 OldBlink
->Flink
= &Descriptor
->ListEntry
;
1371 OldFlink
->Blink
= &Descriptor
->ListEntry
;
1373 /* Zero the descriptor */
1374 RtlZeroMemory(OldDescriptor
, sizeof(*OldDescriptor
));
1381 /* All global descriptors freed */
1382 MmGlobalMemoryDescriptorsUsed
= 0;
1388 _In_ PBL_LIBRARY_PARAMETERS LibraryParameters
1391 /* Are we in phase 1? */
1394 /* Switch to dynamic descriptors if we have too many */
1395 if (LibraryParameters
->DescriptorCount
> RTL_NUMBER_OF(MmStaticMemoryDescriptors
))
1397 MmMdpSwitchToDynamicDescriptors(LibraryParameters
->DescriptorCount
);
1402 /* In phase 0, start with a pool of 512 static descriptors */
1403 MmGlobalMemoryDescriptorCount
= RTL_NUMBER_OF(MmStaticMemoryDescriptors
);
1404 MmGlobalMemoryDescriptors
= MmStaticMemoryDescriptors
;
1405 RtlZeroMemory(MmStaticMemoryDescriptors
, sizeof(MmStaticMemoryDescriptors
));
1406 MmGlobalMemoryDescriptorsUsed
= 0;