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 Status
= BlMmFreeHeap(MemoryDescriptor
);
185 MmMdpSaveCurrentListPointer (
186 _In_ PBL_MEMORY_DESCRIPTOR_LIST MdList
,
187 _In_ PLIST_ENTRY Current
190 PBL_MEMORY_DESCRIPTOR FirstEntry
, LastEntry
;
192 /* Make sure that this is not a global descriptor and not the first one */
193 FirstEntry
= &MmGlobalMemoryDescriptors
[0];
194 LastEntry
= &MmGlobalMemoryDescriptors
[MmGlobalMemoryDescriptorCount
];
195 if ((((ULONG_PTR
)Current
< (ULONG_PTR
)FirstEntry
) ||
196 ((ULONG_PTR
)Current
>= (ULONG_PTR
)LastEntry
)) &&
197 (Current
!= MdList
->First
))
199 /* Save this as the current pointer */
200 MdList
->This
= Current
;
206 _In_ PBL_MEMORY_DESCRIPTOR_LIST MdList
209 PLIST_ENTRY First
, NextEntry
;
212 /* Iterate the list */
213 for (Count
= 0, First
= MdList
->First
, NextEntry
= First
->Flink
;
215 NextEntry
= NextEntry
->Flink
, Count
++);
217 /* Return the count */
223 _In_ PBL_MEMORY_DESCRIPTOR_LIST MdList
,
225 _In_ PLIST_ENTRY ListHead
228 /* Check if a list was specified */
232 MdList
->First
= ListHead
;
236 /* Otherwise, use the internal, built-in list */
237 InitializeListHead(&MdList
->ListHead
);
238 MdList
->First
= &MdList
->ListHead
;
244 /* Initialize current iterator to nothing */
250 _In_ PBL_MEMORY_DESCRIPTOR_LIST DestinationList
,
251 _In_ PBL_MEMORY_DESCRIPTOR_LIST SourceList
,
252 _In_opt_ PBL_MEMORY_DESCRIPTOR ListDescriptor
,
253 _Out_ PULONG ActualCount
,
260 PLIST_ENTRY First
, NextEntry
;
261 PBL_MEMORY_DESCRIPTOR Descriptor
;
263 /* Both parameters must be present */
264 if (!(DestinationList
) || !(SourceList
))
266 return STATUS_INVALID_PARAMETER
;
270 Status
= STATUS_SUCCESS
;
272 /* Check if a descriptor is being used to store the list */
275 /* See how big it is */
276 Flags
|= BL_MM_ADD_DESCRIPTOR_NEVER_COALESCE_FLAG
;
281 /* We are using our internal descriptors instead */
282 Used
= &MmGlobalMemoryDescriptorsUsed
;
283 ++MmDescriptorCallTreeCount
;
285 /* Use as many as are available */
286 Count
= MmGlobalMemoryDescriptorCount
;
287 ListDescriptor
= MmGlobalMemoryDescriptors
;
290 /* Never truncate descriptors during a list copy */
291 Flags
|= BL_MM_ADD_DESCRIPTOR_NEVER_TRUNCATE_FLAG
;
293 /* Iterate through the list */
294 First
= SourceList
->First
;
295 NextEntry
= First
->Flink
;
296 while ((NextEntry
!= First
) && (NT_SUCCESS(Status
)))
298 /* Make sure there's still space */
301 Status
= STATUS_NO_MEMORY
;
305 /* Get the current descriptor */
306 Descriptor
= CONTAINING_RECORD(NextEntry
,
307 BL_MEMORY_DESCRIPTOR
,
310 /* Copy it into one of the descriptors we have */
311 RtlCopyMemory(&ListDescriptor
[*Used
],
313 sizeof(*Descriptor
));
315 /* Add it to the list we have */
316 Status
= MmMdAddDescriptorToList(DestinationList
,
317 &ListDescriptor
[*Used
],
321 /* Move to the next entry */
322 NextEntry
= NextEntry
->Flink
;
325 /* Check if the global descriptors were used */
326 if (ListDescriptor
== MmGlobalMemoryDescriptors
)
328 /* Unwind our usage */
329 MmMdFreeGlobalDescriptors();
330 --MmDescriptorCallTreeCount
;
333 /* Return back to caller */
338 MmMdRemoveDescriptorFromList (
339 _In_ PBL_MEMORY_DESCRIPTOR_LIST MdList
,
340 _In_ PBL_MEMORY_DESCRIPTOR Entry
343 /* Remove the entry */
344 RemoveEntryList(&Entry
->ListEntry
);
346 /* Check if this was the current link */
347 if (MdList
->This
== &Entry
->ListEntry
)
349 /* Remove the current link and set the next one */
351 MmMdpSaveCurrentListPointer(MdList
, Entry
->ListEntry
.Blink
);
357 _In_ PBL_MEMORY_DESCRIPTOR_LIST MdList
360 PLIST_ENTRY FirstEntry
, NextEntry
;
361 PBL_MEMORY_DESCRIPTOR Entry
;
363 /* Go over every descriptor from the top */
364 FirstEntry
= MdList
->First
;
365 NextEntry
= FirstEntry
->Flink
;
366 while (NextEntry
!= FirstEntry
)
368 /* Remove and free each one */
369 Entry
= CONTAINING_RECORD(NextEntry
, BL_MEMORY_DESCRIPTOR
, ListEntry
);
370 NextEntry
= NextEntry
->Flink
;
371 MmMdRemoveDescriptorFromList(MdList
, Entry
);
372 MmMdFreeDescriptor(Entry
);
376 PBL_MEMORY_DESCRIPTOR
377 MmMdInitByteGranularDescriptor (
379 _In_ BL_MEMORY_TYPE Type
,
380 _In_ ULONGLONG BasePage
,
381 _In_ ULONGLONG VirtualPage
,
382 _In_ ULONGLONG PageCount
385 PBL_MEMORY_DESCRIPTOR MemoryDescriptor
;
387 /* If we're out of descriptors, bail out */
388 if (MmGlobalMemoryDescriptorsUsed
>= MmGlobalMemoryDescriptorCount
)
390 EfiPrintf(L
"Out of descriptors!\r\n");
395 /* Take one of the available descriptors and fill it out */
396 MemoryDescriptor
= &MmGlobalMemoryDescriptors
[MmGlobalMemoryDescriptorsUsed
];
397 MemoryDescriptor
->BasePage
= BasePage
;
398 MemoryDescriptor
->VirtualPage
= VirtualPage
;
399 MemoryDescriptor
->PageCount
= PageCount
;
400 MemoryDescriptor
->Flags
= Flags
;
401 MemoryDescriptor
->Type
= Type
;
402 InitializeListHead(&MemoryDescriptor
->ListEntry
);
404 /* Increment the count and return the descriptor */
405 MmGlobalMemoryDescriptorsUsed
++;
406 return MemoryDescriptor
;
410 MmMdTruncateDescriptors (
411 _In_ PBL_MEMORY_DESCRIPTOR_LIST MdList
,
412 _In_ PBL_MEMORY_DESCRIPTOR_LIST NewList
,
413 _In_ ULONGLONG BasePage
416 PLIST_ENTRY ListHead
, NextEntry
;
417 PBL_MEMORY_DESCRIPTOR Descriptor
, NewDescriptor
;
418 ULONGLONG FoundEndPage
;
420 /* Search the descriptor list */
421 ListHead
= MdList
->First
;
422 NextEntry
= ListHead
->Flink
;
423 while (NextEntry
!= ListHead
)
425 /* Get the current descriptor */
426 Descriptor
= CONTAINING_RECORD(NextEntry
,
427 BL_MEMORY_DESCRIPTOR
,
430 /* Go to the next entry in case we have to remove */
431 NextEntry
= NextEntry
->Flink
;
433 /* Don't touch anything else but free RAM */
434 if (((Descriptor
->Type
>> BL_MEMORY_CLASS_SHIFT
) == BlSystemClass
) &&
435 (Descriptor
->Type
!= BlConventionalMemory
))
440 /* Check if this page is within the descriptor's region */
441 FoundEndPage
= Descriptor
->BasePage
+ Descriptor
->PageCount
;
442 if (BasePage
> Descriptor
->BasePage
)
444 /* Check if it doesn't go beyond the descriptor */
445 if (BasePage
< FoundEndPage
)
447 /* Create a new descriptor to describe this region */
448 EfiPrintf(L
"Truncating descriptor type %lx base: %llx end: %llx\r\n",
449 Descriptor
->Type
, Descriptor
->BasePage
, FoundEndPage
);
450 NewDescriptor
= MmMdInitByteGranularDescriptor(Descriptor
->Flags
,
454 FoundEndPage
- BasePage
);
457 return STATUS_NO_MEMORY
;
460 /* Cut off this descriptor to make it shorter */
461 Descriptor
->PageCount
= BasePage
- Descriptor
->BasePage
;
463 /* Add the region to the new list */
464 MmMdAddDescriptorToList(NewList
,
466 BL_MM_ADD_DESCRIPTOR_COALESCE_FLAG
);
471 /* This whole descriptor covers the truncated area */
472 EfiPrintf(L
"Truncating descriptor type %lx base: %llx end: %llx\r\n",
473 Descriptor
->Type
, Descriptor
->BasePage
, FoundEndPage
);
474 MmMdRemoveDescriptorFromList(MdList
, Descriptor
);
475 MmMdAddDescriptorToList(NewList
,
477 BL_MM_ADD_DESCRIPTOR_COALESCE_FLAG
);
481 /* All good if we got here */
482 return STATUS_SUCCESS
;
486 MmMdpTruncateDescriptor (
487 _In_ PBL_MEMORY_DESCRIPTOR_LIST MdList
,
488 _In_ PBL_MEMORY_DESCRIPTOR MemoryDescriptor
,
492 PBL_MEMORY_DESCRIPTOR NextDescriptor
, PreviousDescriptor
;
493 PLIST_ENTRY NextEntry
, PreviousEntry
;
494 ULONGLONG EndPage
, PreviousEndPage
;// , NextEndPage;
496 /* Get the next descriptor */
497 NextEntry
= MemoryDescriptor
->ListEntry
.Flink
;
498 NextDescriptor
= CONTAINING_RECORD(NextEntry
, BL_MEMORY_DESCRIPTOR
, ListEntry
);
500 /* Get the previous descriptor */
501 PreviousEntry
= MemoryDescriptor
->ListEntry
.Blink
;
502 PreviousDescriptor
= CONTAINING_RECORD(PreviousEntry
, BL_MEMORY_DESCRIPTOR
, ListEntry
);
504 /* Calculate end pages */
505 EndPage
= MemoryDescriptor
->BasePage
+ MemoryDescriptor
->PageCount
;
506 //NextEndPage = NextDescriptor->BasePage + NextDescriptor->PageCount;
507 PreviousEndPage
= PreviousDescriptor
->BasePage
+ PreviousDescriptor
->PageCount
;
509 /* Check for backward overlap */
510 if ((PreviousEntry
!= MdList
->First
) && (MemoryDescriptor
->BasePage
< PreviousEndPage
))
512 EfiPrintf(L
"Overlap detected -- this is unexpected on x86/x64 platforms\r\n");
516 /* Check for forward overlap */
517 if ((NextEntry
!= MdList
->First
) && (NextDescriptor
->BasePage
< EndPage
))
519 EfiPrintf(L
"Overlap detected -- this is unexpected on x86/x64 platforms\r\n");
528 MmMdpCoalesceDescriptor (
529 _In_ PBL_MEMORY_DESCRIPTOR_LIST MdList
,
530 _In_ PBL_MEMORY_DESCRIPTOR MemoryDescriptor
,
534 PBL_MEMORY_DESCRIPTOR NextDescriptor
, PreviousDescriptor
;
535 PLIST_ENTRY NextEntry
, PreviousEntry
;
536 ULONGLONG EndPage
, PreviousEndPage
, PreviousMappedEndPage
, MappedEndPage
;
538 /* Get the next descriptor */
539 NextEntry
= MemoryDescriptor
->ListEntry
.Flink
;
540 NextDescriptor
= CONTAINING_RECORD(NextEntry
, BL_MEMORY_DESCRIPTOR
, ListEntry
);
542 /* Get the previous descriptor */
543 PreviousEntry
= MemoryDescriptor
->ListEntry
.Blink
;
544 PreviousDescriptor
= CONTAINING_RECORD(PreviousEntry
, BL_MEMORY_DESCRIPTOR
, ListEntry
);
546 /* Calculate end pages */
547 EndPage
= MemoryDescriptor
->BasePage
+ MemoryDescriptor
->PageCount
;
548 MappedEndPage
= MemoryDescriptor
->BasePage
+ MemoryDescriptor
->PageCount
;
549 PreviousMappedEndPage
= PreviousDescriptor
->VirtualPage
+ PreviousDescriptor
->PageCount
;
550 PreviousEndPage
= PreviousDescriptor
->BasePage
+ PreviousDescriptor
->PageCount
;
551 PreviousMappedEndPage
= PreviousDescriptor
->VirtualPage
+ PreviousDescriptor
->PageCount
;
553 /* Check if the previous entry touches the current entry, and is compatible */
554 if ((PreviousEntry
!= MdList
->First
) &&
555 (PreviousDescriptor
->Type
== MemoryDescriptor
->Type
) &&
556 ((PreviousDescriptor
->Flags
^ MemoryDescriptor
->Flags
) & 0x1B19FFFF) &&
557 (PreviousEndPage
== MemoryDescriptor
->BasePage
) &&
558 ((!(MemoryDescriptor
->VirtualPage
) && !(PreviousDescriptor
->VirtualPage
)) ||
559 ((MemoryDescriptor
->VirtualPage
) && (PreviousDescriptor
->VirtualPage
) &&
560 (PreviousMappedEndPage
== MemoryDescriptor
->VirtualPage
))))
562 EfiPrintf(L
"Previous descriptor coalescable!\r\n");
565 /* CHeck if the current entry touches the next entry, and is compatible */
566 if ((NextEntry
!= MdList
->First
) &&
567 (NextDescriptor
->Type
== MemoryDescriptor
->Type
) &&
568 ((NextDescriptor
->Flags
^ MemoryDescriptor
->Flags
) & 0x1B19FFFF) &&
569 (EndPage
== NextDescriptor
->BasePage
) &&
570 ((!(MemoryDescriptor
->VirtualPage
) && !(NextDescriptor
->VirtualPage
)) ||
571 ((MemoryDescriptor
->VirtualPage
) && (NextDescriptor
->VirtualPage
) &&
572 (MappedEndPage
== NextDescriptor
->VirtualPage
))))
574 EfiPrintf(L
"Next descriptor coalescable!\r\n");
582 MmMdAddDescriptorToList (
583 _In_ PBL_MEMORY_DESCRIPTOR_LIST MdList
,
584 _In_ PBL_MEMORY_DESCRIPTOR MemoryDescriptor
,
588 PLIST_ENTRY ThisEntry
, FirstEntry
;
589 PBL_MEMORY_DESCRIPTOR ThisDescriptor
;
591 /* Arguments must be present */
592 if (!(MdList
) || !(MemoryDescriptor
))
594 return STATUS_INVALID_PARAMETER
;
597 /* Check if coalescing is forcefully disabled */
598 if (Flags
& BL_MM_ADD_DESCRIPTOR_NEVER_COALESCE_FLAG
)
600 /* Then we won't be coalescing */
601 Flags
&= ~BL_MM_ADD_DESCRIPTOR_COALESCE_FLAG
;
603 else if (MemoryDescriptor
->Flags
& BlMemoryCoalesced
)
605 /* Coalesce if the descriptor requires it */
606 Flags
|= BL_MM_ADD_DESCRIPTOR_COALESCE_FLAG
;
609 /* Check if truncation is forcefully disabled */
610 if (Flags
& BL_MM_ADD_DESCRIPTOR_NEVER_TRUNCATE_FLAG
)
612 Flags
&= ~BL_MM_ADD_DESCRIPTOR_TRUNCATE_FLAG
;
615 /* Update the current list pointer if the descriptor requires it */
616 if (MemoryDescriptor
->Flags
& BlMemoryUpdate
)
618 Flags
|= BL_MM_ADD_DESCRIPTOR_UPDATE_LIST_POINTER_FLAG
;
621 /* Get the current descriptor */
622 ThisEntry
= MdList
->This
;
623 ThisDescriptor
= CONTAINING_RECORD(ThisEntry
, BL_MEMORY_DESCRIPTOR
, ListEntry
);
625 /* Also get the first descriptor */
626 FirstEntry
= MdList
->First
;
628 /* Check if there's no current pointer, or if it's higher than the new one */
630 (MemoryDescriptor
->BasePage
<= ThisDescriptor
->BasePage
))
632 /* Start at the first descriptor instead, since current is past us */
633 ThisEntry
= FirstEntry
->Flink
;
636 /* Loop until we find the right location to insert */
637 while (ThisEntry
!= FirstEntry
)
639 /* Get the descriptor part of this entry */
640 ThisDescriptor
= CONTAINING_RECORD(ThisEntry
, BL_MEMORY_DESCRIPTOR
, ListEntry
);
642 /* Is the address smaller, or equal but more important? */
643 if ((MemoryDescriptor
->BasePage
< ThisDescriptor
->BasePage
) ||
644 ((MemoryDescriptor
->BasePage
== ThisDescriptor
->BasePage
) &&
645 (MmMdpHasPrecedence(MemoryDescriptor
->Type
, ThisDescriptor
->Type
))))
647 /* Then insert right here */
648 InsertTailList(ThisEntry
, &MemoryDescriptor
->ListEntry
);
652 /* Try the next entry */
653 ThisEntry
= ThisEntry
->Flink
;
656 /* Then we didn't find a good match, so insert it right here */
657 InsertTailList(FirstEntry
, &MemoryDescriptor
->ListEntry
);
660 /* Do we have to truncate? */
661 if (Flags
& BL_MM_ADD_DESCRIPTOR_TRUNCATE_FLAG
)
663 /* Do it and then exit */
664 if (MmMdpTruncateDescriptor(MdList
, MemoryDescriptor
, Flags
))
666 return STATUS_SUCCESS
;
670 /* Do we have to coalesce? */
671 if (Flags
& BL_MM_ADD_DESCRIPTOR_COALESCE_FLAG
)
673 /* Do it and then exit */
674 if (MmMdpCoalesceDescriptor(MdList
, MemoryDescriptor
, Flags
))
676 return STATUS_SUCCESS
;
680 /* Do we have to update the current pointer? */
681 if (Flags
& BL_MM_ADD_DESCRIPTOR_UPDATE_LIST_POINTER_FLAG
)
684 MmMdpSaveCurrentListPointer(MdList
, &MemoryDescriptor
->ListEntry
);
688 return STATUS_SUCCESS
;
692 MmMdRemoveRegionFromMdlEx (
693 _In_ PBL_MEMORY_DESCRIPTOR_LIST MdList
,
695 _In_ ULONGLONG BasePage
,
696 _In_ ULONGLONG PageCount
,
697 _Out_opt_ PBL_MEMORY_DESCRIPTOR_LIST NewMdList
700 BOOLEAN HaveNewList
, UseVirtualPage
;
702 PLIST_ENTRY ListHead
, NextEntry
;
703 PBL_MEMORY_DESCRIPTOR Descriptor
, NewDescriptor
, ListDescriptor
;
704 BL_MEMORY_DESCRIPTOR OldDescriptor
;
705 ULONGLONG RegionSize
;
706 ULONGLONG FoundBasePage
, FoundEndPage
, FoundPageCount
, EndPage
, VirtualPage
;
708 /* Set initial status */
709 Status
= STATUS_SUCCESS
;
710 ListDescriptor
= NULL
;
711 NewDescriptor
= NULL
;
714 /* Check if removed descriptors should go into a new list */
715 if (NewMdList
!= NULL
)
718 MmMdInitializeList(NewMdList
, MdList
->Type
, NULL
);
720 /* Remember for later */
724 /* Is the region being removed physical? */
725 UseVirtualPage
= FALSE
;
726 if (!(Flags
& BL_MM_REMOVE_VIRTUAL_REGION_FLAG
))
728 /* Is this a list of virtual descriptors? */
729 if (MdList
->Type
== BlMdVirtual
)
731 /* Request is nonsensical, fail */
732 Status
= STATUS_INVALID_PARAMETER
;
738 /* Is this a list of physical descriptors? */
739 if (MdList
->Type
== BlMdPhysical
)
741 /* We'll have to use the virtual page instead */
742 UseVirtualPage
= TRUE
;
747 ListHead
= MdList
->First
;
748 NextEntry
= ListHead
->Flink
;
749 while (NextEntry
!= ListHead
)
751 /* Get the descriptor */
752 Descriptor
= CONTAINING_RECORD(NextEntry
, BL_MEMORY_DESCRIPTOR
, ListEntry
);
754 /* Extract range details */
755 FoundBasePage
= UseVirtualPage
? Descriptor
->VirtualPage
: Descriptor
->BasePage
;
756 FoundPageCount
= Descriptor
->PageCount
;
757 FoundEndPage
= FoundBasePage
+ FoundPageCount
;
758 EndPage
= PageCount
+ BasePage
;
760 /* Make a copy of the original descriptor */
761 OldDescriptor
= *Descriptor
;
763 /* Check if the region to be removed starts after the found region starts */
764 if ((BasePage
> FoundBasePage
) || (FoundBasePage
>= EndPage
))
766 /* Check if the region ends after the found region */
767 if ((BasePage
>= FoundEndPage
) || (FoundEndPage
> EndPage
))
769 /* Check if the found region starts after the region or ends before the region */
770 if ((FoundBasePage
>= BasePage
) || (EndPage
>= FoundEndPage
))
772 /* This is a fully-mapped descriptor -- change nothing */
773 OldDescriptor
.PageCount
= 0;
777 /* This descriptor fully covers the entire allocation */
778 FoundBasePage
= Descriptor
->BasePage
;
779 VirtualPage
= Descriptor
->VirtualPage
;
780 FoundPageCount
= BasePage
- FoundBasePage
;
782 /* This is how many pages we will eat away from the descriptor */
783 RegionSize
= FoundPageCount
+ PageCount
;
785 /* Update the descriptor to account for the consumed pages */
786 Descriptor
->BasePage
+= RegionSize
;
787 Descriptor
->PageCount
-= RegionSize
;
790 Descriptor
->VirtualPage
+= RegionSize
;
793 /* Initialize a descriptor for the start of the region */
794 NewDescriptor
= MmMdInitByteGranularDescriptor(Descriptor
->Flags
,
801 Status
= STATUS_NO_MEMORY
;
805 /* Add it into the list */
806 Status
= MmMdAddDescriptorToList(MdList
, NewDescriptor
, Flags
);
807 if (!NT_SUCCESS(Status
))
809 Status
= STATUS_NO_MEMORY
;
813 /* Don't free it on exit path */
814 NewDescriptor
= NULL
;
816 /* Adjust the leftover descriptor */
817 OldDescriptor
.BasePage
+= FoundPageCount
;
818 OldDescriptor
.PageCount
= PageCount
;
819 if (OldDescriptor
.VirtualPage
)
821 OldDescriptor
.VirtualPage
+= FoundPageCount
;
827 /* This descriptor contains the entire allocation */
828 RegionSize
= FoundEndPage
- BasePage
;
829 Descriptor
->PageCount
-= RegionSize
;
831 /* Adjust the leftover descriptor */
832 OldDescriptor
.BasePage
+= Descriptor
->PageCount
;
833 OldDescriptor
.PageCount
= RegionSize
;
834 if (OldDescriptor
.VirtualPage
)
836 OldDescriptor
.VirtualPage
+= FoundPageCount
;
840 /* Go to the next entry */
841 NextEntry
= NextEntry
->Flink
;
846 * This descriptor contains the end of the allocation. It may:
848 * - Contain the full allocation (i.e.: the start is aligned)
849 * - Contain parts of the end of the allocation (i.e.: the end is beyond)
850 * - Contain the entire tail end of the allocation (i..e:the end is within)
852 * So first, figure out if we cover the entire end or not
854 if (EndPage
< FoundEndPage
)
856 /* The allocation goes past the end of this descriptor */
857 FoundEndPage
= EndPage
;
860 /* This is how many pages we will eat away from the descriptor */
861 FoundPageCount
= FoundEndPage
- FoundBasePage
;
863 /* Update the descriptor to account for the consumed pages */
864 Descriptor
->BasePage
+= FoundPageCount
;
865 Descriptor
->PageCount
-= FoundPageCount
;
866 if (Descriptor
->VirtualPage
)
868 Descriptor
->VirtualPage
+= FoundPageCount
;
871 /* Go to the next entry */
872 NextEntry
= NextEntry
->Flink
;
874 /* Check if the descriptor is now empty */
875 if (!Descriptor
->PageCount
)
878 MmMdRemoveDescriptorFromList(MdList
, Descriptor
);
880 /* Check if we're supposed to insert it into a new list */
883 /* This is the one to add */
884 ListDescriptor
= Descriptor
;
888 /* Nope -- just get rid of it */
889 MmMdFreeDescriptor(Descriptor
);
894 /* Is there a remainder descriptor, and do we have a list for it */
895 if ((OldDescriptor
.PageCount
) && (HaveNewList
))
897 /* Did we already chop off the descriptor? */
900 /* Use what we previously chopped */
901 *ListDescriptor
= OldDescriptor
;
905 /* First time, so build a descriptor to describe the leftover */
906 ListDescriptor
= MmMdInitByteGranularDescriptor(OldDescriptor
.Flags
,
908 OldDescriptor
.BasePage
,
909 OldDescriptor
.VirtualPage
,
910 OldDescriptor
.PageCount
);
913 Status
= STATUS_NO_MEMORY
;
917 /* Add it into the list */
918 Status
= MmMdAddDescriptorToList(NewMdList
, ListDescriptor
, 0);
919 if (!NT_SUCCESS(Status
))
924 /* Don't free on exit path */
925 ListDescriptor
= NULL
;
931 /* Check for failure cleanup */
932 if (!NT_SUCCESS(Status
))
934 /* Did we have to build a new list? */
937 /* Free and re-initialize it */
938 MmMdFreeList(NewMdList
);
939 MmMdInitializeList(NewMdList
, MdList
->Type
, NULL
);
942 /* Check if we had a list descriptor, and free it */
945 MmMdFreeDescriptor(ListDescriptor
);
948 /* Check if we had a new descriptor, and free it */
951 MmMdFreeDescriptor(NewDescriptor
);
959 PBL_MEMORY_DESCRIPTOR
960 MmMdFindDescriptorFromMdl (
961 _In_ PBL_MEMORY_DESCRIPTOR_LIST MdList
,
967 PLIST_ENTRY NextEntry
, ListHead
;
968 PBL_MEMORY_DESCRIPTOR Current
;
971 /* Assume physical */
974 /* Check if the caller wants physical memory */
975 if (!(Flags
& BL_MM_REMOVE_VIRTUAL_REGION_FLAG
))
977 /* Check if this is a virtual memory list */
978 if (MdList
->Type
== BlMdVirtual
)
980 /* We won't find anything */
984 else if (MdList
->Type
== BlMdPhysical
)
986 /* Otherwise, caller wants virtual, but this is a physical list */
988 NextEntry
= MdList
->First
->Flink
;
991 /* Check if this is a physical search */
994 /* Check if we can use the current pointer */
995 NextEntry
= MdList
->This
;
998 /* We can't -- start at the beginning */
999 NextEntry
= MdList
->First
->Flink
;
1003 /* If the page is below the current pointer, restart */
1004 Current
= CONTAINING_RECORD(NextEntry
, BL_MEMORY_DESCRIPTOR
, ListEntry
);
1005 if (Page
< Current
->BasePage
)
1007 NextEntry
= MdList
->First
->Flink
;
1012 /* Loop the list of descriptors */
1013 ListHead
= MdList
->First
;
1014 while (NextEntry
!= ListHead
)
1016 /* Get the current one */
1017 Current
= CONTAINING_RECORD(NextEntry
, BL_MEMORY_DESCRIPTOR
, ListEntry
);
1019 /* Check if we are looking for virtual memory */
1022 /* Use the base address */
1023 BasePage
= Current
->VirtualPage
;
1028 BasePage
= Current
->BasePage
;
1031 /* If this is a virtual descriptor, make sure it has a base address */
1032 if ((!(IsVirtual
) || (BasePage
)) &&
1033 (BasePage
<= Page
) &&
1034 (Page
< (BasePage
+ Current
->PageCount
)))
1036 /* The descriptor fits the page being requested */
1040 /* Try the next one */
1041 NextEntry
= NextEntry
->Flink
;
1044 /* Nothing found if we're here */
1048 PBL_MEMORY_DESCRIPTOR
1049 MmMdFindDescriptor (
1050 _In_ ULONG WhichList
,
1055 PBL_MEMORY_DESCRIPTOR FoundDescriptor
;
1057 /* Check if the caller is looking for mapped, allocated memory */
1058 if (WhichList
& BL_MM_INCLUDE_MAPPED_ALLOCATED
)
1060 /* Find a descriptor in that list */
1061 FoundDescriptor
= MmMdFindDescriptorFromMdl(&MmMdlMappedAllocated
, Flags
, Page
);
1062 if (FoundDescriptor
)
1065 return FoundDescriptor
;
1069 /* Check if the caller is looking for mapped, unallocated memory */
1070 if (WhichList
& BL_MM_INCLUDE_MAPPED_UNALLOCATED
)
1072 /* Find a descriptor in that list */
1073 FoundDescriptor
= MmMdFindDescriptorFromMdl(&MmMdlMappedUnallocated
, Flags
, Page
);
1074 if (FoundDescriptor
)
1077 return FoundDescriptor
;
1081 /* Check if the caller is looking for unmapped, allocated memory */
1082 if (WhichList
& BL_MM_INCLUDE_UNMAPPED_ALLOCATED
)
1084 /* Find a descriptor in that list */
1085 FoundDescriptor
= MmMdFindDescriptorFromMdl(&MmMdlUnmappedAllocated
, Flags
, Page
);
1086 if (FoundDescriptor
)
1089 return FoundDescriptor
;
1093 /* Check if the caller is looking for unmapped, unallocated memory */
1094 if (WhichList
& BL_MM_INCLUDE_UNMAPPED_UNALLOCATED
)
1096 /* Find a descriptor in that list */
1097 FoundDescriptor
= MmMdFindDescriptorFromMdl(&MmMdlUnmappedUnallocated
, Flags
, Page
);
1098 if (FoundDescriptor
)
1101 return FoundDescriptor
;
1105 /* Check if the caller is looking for reserved, allocated memory */
1106 if (WhichList
& BL_MM_INCLUDE_RESERVED_ALLOCATED
)
1108 /* Find a descriptor in that list */
1109 FoundDescriptor
= MmMdFindDescriptorFromMdl(&MmMdlReservedAllocated
, Flags
, Page
);
1110 if (FoundDescriptor
)
1113 return FoundDescriptor
;
1117 /* Check if the caller is looking for bad memory */
1118 if (WhichList
& BL_MM_INCLUDE_BAD_MEMORY
)
1120 /* Find a descriptor in that list */
1121 FoundDescriptor
= MmMdFindDescriptorFromMdl(&MmMdlBadMemory
, Flags
, Page
);
1122 if (FoundDescriptor
)
1125 return FoundDescriptor
;
1129 /* Check if the caller is looking for truncated memory */
1130 if (WhichList
& BL_MM_INCLUDE_TRUNCATED_MEMORY
)
1132 /* Find a descriptor in that list */
1133 FoundDescriptor
= MmMdFindDescriptorFromMdl(&MmMdlTruncatedMemory
, Flags
, Page
);
1134 if (FoundDescriptor
)
1137 return FoundDescriptor
;
1141 /* Check if the caller is looking for persistent memory */
1142 if (WhichList
& BL_MM_INCLUDE_PERSISTENT_MEMORY
)
1144 /* Find a descriptor in that list */
1145 FoundDescriptor
= MmMdFindDescriptorFromMdl(&MmMdlPersistentMemory
, Flags
, Page
);
1146 if (FoundDescriptor
)
1149 return FoundDescriptor
;
1153 /* Nothing if we got here */
1158 MmMdFindSatisfyingRegion (
1159 _In_ PBL_MEMORY_DESCRIPTOR Descriptor
,
1160 _Out_ PBL_MEMORY_DESCRIPTOR NewDescriptor
,
1161 _In_ ULONGLONG Pages
,
1162 _In_ PBL_ADDRESS_RANGE BaseRange
,
1163 _In_ PBL_ADDRESS_RANGE VirtualRange
,
1164 _In_ BOOLEAN TopDown
,
1165 _In_ BL_MEMORY_TYPE MemoryType
,
1167 _In_ ULONG Alignment
1170 ULONGLONG BaseMin
, BaseMax
, AlignedMin
;
1171 ULONGLONG VirtualPage
, BasePage
;
1172 ULONGLONG BaseDelta
, AlignedBase
;
1173 ULONGLONG VirtualMin
, VirtualMax
;
1175 /* Extract the minimum and maximum range */
1176 BaseMin
= BaseRange
->Minimum
;
1177 BaseMax
= BaseRange
->Maximum
;
1179 /* Don't go below where the descriptor starts */
1180 if (BaseMin
< Descriptor
->BasePage
)
1182 BaseMin
= Descriptor
->BasePage
;
1185 /* Don't go beyond where the descriptor ends */
1186 if (BaseMax
> (Descriptor
->BasePage
+ Descriptor
->PageCount
- 1))
1188 BaseMax
= (Descriptor
->BasePage
+ Descriptor
->PageCount
- 1);
1191 /* Check for start overflow */
1192 if (BaseMin
> BaseMax
)
1197 /* Align the base as required */
1200 AlignedMin
= ALIGN_UP_BY(BaseMin
, Alignment
);
1204 AlignedMin
= BaseMin
;
1207 /* Check for range overflow */
1208 if (((AlignedMin
+ Pages
- 1) < AlignedMin
) || ((AlignedMin
+ Pages
- 1) > BaseMax
))
1213 /* Check if this was a top-down request */
1216 /* Then get the highest page possible */
1217 BasePage
= BaseMax
- Pages
+ 1;
1220 /* Align it as needed */
1221 AlignedBase
= ALIGN_DOWN_BY(BasePage
, Alignment
);
1225 AlignedBase
= BasePage
;
1228 /* Calculate the delta between max address and our aligned base */
1229 BaseDelta
= BasePage
- AlignedBase
;
1230 BasePage
-= BaseDelta
;
1234 /* Otherwise, get the lowest page possible */
1235 BasePage
= AlignedMin
;
1239 /* If a virtual address range was passed in, this must be a virtual descriptor */
1240 if (((VirtualRange
->Minimum
) || (VirtualRange
->Maximum
)) &&
1241 !(Descriptor
->VirtualPage
))
1246 /* Any mapped page already? */
1247 if (Descriptor
->VirtualPage
)
1249 /* Get virtual min/max */
1250 VirtualMin
= VirtualRange
->Minimum
;
1251 VirtualMax
= VirtualRange
->Maximum
;
1253 /* Don't go below where the descriptor maps */
1254 if (VirtualMin
<= Descriptor
->VirtualPage
)
1256 VirtualMin
= Descriptor
->VirtualPage
;
1259 /* Don't go above where the descriptor maps */
1260 if (VirtualMax
>= (Descriptor
->VirtualPage
+ Descriptor
->PageCount
- 1))
1262 VirtualMax
= Descriptor
->VirtualPage
+ Descriptor
->PageCount
- 1;
1265 /* Don't let the base overflow */
1266 if (VirtualMin
> VirtualMax
)
1271 /* Adjust the base by the alignment delta */
1272 VirtualMin
+= AlignedMin
- BaseMin
;
1274 /* Check that the bounds don't overflow or underflow */
1275 if (((VirtualMin
+ Pages
- 1) < VirtualMin
) ||
1276 ((VirtualMin
+ Pages
- 1) > VirtualMax
))
1281 /* Finally, pick the correct address based on direction */
1284 /* Highest possible base address, aligned */
1285 VirtualPage
= VirtualMax
- Pages
+ 1 - BaseDelta
;
1289 /* Lowest possible base address, aligned */
1290 VirtualPage
= VirtualMin
;
1295 /* Nothing to worry about */
1299 /* Bail out if the memory type attributes don't match */
1300 if ((((Flags
& 0xFF) & (Descriptor
->Flags
& 0xFF)) != (Flags
& 0xFF)) ||
1301 (((Flags
& 0xFF00) & (Descriptor
->Flags
& 0xFF00)) != (Flags
& 0xFF00)))
1303 //EfiPrintf(L"Incorrect memory attributes\r\n");
1307 /* Bail out if the allocation flags don't match */
1308 if (((Flags
^ Descriptor
->Flags
) & (BlMemoryRuntime
| BlMemoryBelow1MB
| BlMemoryLargePages
)))
1310 //EfiPrintf(L"Incorrect memory allocation flags\r\n");
1314 /* Bail out if the type doesn't match */
1315 if (Descriptor
->Type
!= MemoryType
)
1317 //EfiPrintf(L"Incorrect descriptor type: %lx %lx\r\n", Descriptor->Type, MemoryType);
1321 /* We have a matching region, fill out the descriptor for it */
1322 NewDescriptor
->BasePage
= BasePage
;
1323 NewDescriptor
->PageCount
= Pages
;
1324 NewDescriptor
->Type
= Descriptor
->Type
;
1325 NewDescriptor
->VirtualPage
= VirtualPage
;
1326 NewDescriptor
->Flags
= Descriptor
->Flags
;
1327 //EfiPrintf(L"Found a matching descriptor: %08I64X with %08I64X pages\r\n", BasePage, Pages);
1332 MmMdFreeGlobalDescriptors (
1336 PBL_MEMORY_DESCRIPTOR Descriptor
, OldDescriptor
;
1338 PLIST_ENTRY OldFlink
, OldBlink
;
1340 /* Make sure we're not int middle of a call using a descriptor */
1341 if (MmDescriptorCallTreeCount
!= 1)
1346 /* Loop every current global descriptor */
1347 while (Index
< MmGlobalMemoryDescriptorsUsed
)
1349 /* Does it have any valid pages? */
1350 OldDescriptor
= &MmGlobalMemoryDescriptors
[Index
];
1351 if (OldDescriptor
->PageCount
)
1353 /* Allocate a copy of it */
1354 Descriptor
= BlMmAllocateHeap(sizeof(*Descriptor
));
1360 /* Save the links */
1361 OldBlink
= OldDescriptor
->ListEntry
.Blink
;
1362 OldFlink
= OldDescriptor
->ListEntry
.Flink
;
1365 *Descriptor
= *OldDescriptor
;
1368 OldBlink
->Flink
= &Descriptor
->ListEntry
;
1369 OldFlink
->Blink
= &Descriptor
->ListEntry
;
1371 /* Zero the descriptor */
1372 RtlZeroMemory(OldDescriptor
, sizeof(*OldDescriptor
));
1379 /* All global descriptors freed */
1380 MmGlobalMemoryDescriptorsUsed
= 0;
1386 _In_ PBL_LIBRARY_PARAMETERS LibraryParameters
1389 /* Are we in phase 1? */
1392 /* Switch to dynamic descriptors if we have too many */
1393 if (LibraryParameters
->DescriptorCount
> RTL_NUMBER_OF(MmStaticMemoryDescriptors
))
1395 MmMdpSwitchToDynamicDescriptors(LibraryParameters
->DescriptorCount
);
1400 /* In phase 0, start with a pool of 512 static descriptors */
1401 MmGlobalMemoryDescriptorCount
= RTL_NUMBER_OF(MmStaticMemoryDescriptors
);
1402 MmGlobalMemoryDescriptors
= MmStaticMemoryDescriptors
;
1403 RtlZeroMemory(MmStaticMemoryDescriptors
, sizeof(MmStaticMemoryDescriptors
));
1404 MmGlobalMemoryDescriptorsUsed
= 0;