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
[] =
35 /* FUNCTIONS *****************************************************************/
37 /* The order is Conventional > Other > System > Loader > Application */
40 _In_ BL_MEMORY_TYPE Type1
,
41 _In_ BL_MEMORY_TYPE Type2
44 BL_MEMORY_CLASS Class1
, Class2
;
47 /* Descriptor is free RAM -- it precedes */
48 if (Type1
== BlConventionalMemory
)
53 /* It isn't free RAM, but the comparator is -- it succeeds it */
54 if (Type2
== BlConventionalMemory
)
59 /* Descriptor is not system, application, or loader class -- it precedes */
60 Class1
= Type1
>> BL_MEMORY_CLASS_SHIFT
;
61 if ((Class1
!= BlSystemClass
) &&
62 (Class1
!= BlApplicationClass
) &&
63 (Class1
!= BlLoaderClass
))
68 /* It isn't one of those classes, but the comparator it -- it succeeds it */
69 Class2
= Type2
>> BL_MEMORY_CLASS_SHIFT
;
70 if ((Class2
!= BlSystemClass
) &&
71 (Class2
!= BlApplicationClass
) &&
72 (Class2
!= BlLoaderClass
))
77 /* Descriptor is system class */
78 if (Class1
== BlSystemClass
)
80 /* And so is the other guy... */
81 if (Class2
== BlSystemClass
)
86 /* Scan for the descriptor's system precedence index */
89 if (MmPlatformMemoryTypePrecedence
[j
] == Type1
)
93 } while (++j
< RTL_NUMBER_OF(MmPlatformMemoryTypePrecedence
));
95 /* Use an invalid index if one wasn't found */
96 if (j
== RTL_NUMBER_OF(MmPlatformMemoryTypePrecedence
))
101 /* Now scan for the comparator's system precedence index */
102 while (MmPlatformMemoryTypePrecedence
[i
] != Type2
)
104 /* Use an invalid index if one wasn't found */
105 if (++i
>= RTL_NUMBER_OF(MmPlatformMemoryTypePrecedence
))
112 /* Does the current have a valid index? */
115 /* Yes, what about the comparator? */
118 /* Let the indexes fight! */
122 /* Succeed the comparator, its index is unknown */
127 /* The comparator isn't system, so it precedes it */
131 /* Descriptor is not system class, but comparator is -- it succeeds it */
132 if (Class2
== BlSystemClass
)
137 /* Descriptor is loader class -- it precedes */
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
) && (MemoryDescriptor
< &MmStaticMemoryDescriptors
[511])))
169 /* It's a global/static descriptor, so just zero it */
170 RtlZeroMemory(MemoryDescriptor
, sizeof(BL_MEMORY_DESCRIPTOR
));
171 Status
= STATUS_SUCCESS
;
175 /* It's a dynamic descriptor, so free it */
176 EfiPrintf(L
"Dynamic descriptors not yet supported\r\n");
177 Status
= STATUS_NOT_IMPLEMENTED
;
185 MmMdpSaveCurrentListPointer (
186 _In_ PBL_MEMORY_DESCRIPTOR_LIST MdList
,
187 _In_ PLIST_ENTRY Current
190 /* Make sure that this is not a global descriptor and not the first one */
191 if (((Current
< &MmGlobalMemoryDescriptors
->ListEntry
) ||
192 (Current
>= &MmGlobalMemoryDescriptors
[MmGlobalMemoryDescriptorCount
].ListEntry
)) &&
193 (Current
!= MdList
->First
))
195 /* Save this as the current pointer */
196 MdList
->This
= Current
;
202 _In_ PBL_MEMORY_DESCRIPTOR_LIST MdList
205 PLIST_ENTRY First
, NextEntry
;
208 /* Iterate the list */
209 for (Count
= 0, First
= MdList
->First
, NextEntry
= First
->Flink
;
211 NextEntry
= NextEntry
->Flink
, Count
++);
213 /* Return the count */
219 _In_ PBL_MEMORY_DESCRIPTOR_LIST MdList
,
221 _In_ PLIST_ENTRY ListHead
224 /* Check if a list was specified */
228 MdList
->First
= ListHead
;
232 /* Otherwise, use the internal, built-in list */
233 InitializeListHead(&MdList
->ListHead
);
234 MdList
->First
= &MdList
->ListHead
;
240 /* Initialize current iterator to nothing */
246 _In_ PBL_MEMORY_DESCRIPTOR_LIST DestinationList
,
247 _In_ PBL_MEMORY_DESCRIPTOR_LIST SourceList
,
248 _In_opt_ PBL_MEMORY_DESCRIPTOR ListDescriptor
,
249 _Out_ PULONG ActualCount
,
256 PLIST_ENTRY First
, NextEntry
;
257 PBL_MEMORY_DESCRIPTOR Descriptor
;
259 /* Both parameters must be present */
260 if (!(DestinationList
) || !(SourceList
))
262 return STATUS_INVALID_PARAMETER
;
266 Status
= STATUS_SUCCESS
;
268 /* Check if a descriptor is being used to store the list */
271 /* See how big it is */
272 Flags
|= BL_MM_ADD_DESCRIPTOR_NEVER_COALESCE_FLAG
;
277 /* We are using our internal descriptors instead */
278 Used
= &MmGlobalMemoryDescriptorsUsed
;
279 ++MmDescriptorCallTreeCount
;
281 /* Use as many as are available */
282 Count
= MmGlobalMemoryDescriptorCount
;
283 ListDescriptor
= MmGlobalMemoryDescriptors
;
286 /* Never truncate descriptors during a list copy */
287 Flags
|= BL_MM_ADD_DESCRIPTOR_NEVER_TRUNCATE_FLAG
;
289 /* Iterate through the list */
290 First
= SourceList
->First
;
291 NextEntry
= First
->Flink
;
292 while ((NextEntry
!= First
) && (NT_SUCCESS(Status
)))
294 /* Make sure there's still space */
297 Status
= STATUS_NO_MEMORY
;
301 /* Get the current descriptor */
302 Descriptor
= CONTAINING_RECORD(NextEntry
,
303 BL_MEMORY_DESCRIPTOR
,
306 /* Copy it into one of the descriptors we have */
307 RtlCopyMemory(&ListDescriptor
[*Used
],
309 sizeof(*Descriptor
));
311 /* Add it to the list we have */
312 Status
= MmMdAddDescriptorToList(DestinationList
,
313 &ListDescriptor
[*Used
],
317 /* Move to the next entry */
318 NextEntry
= NextEntry
->Flink
;
321 /* Check if the global descriptors were used */
322 if (ListDescriptor
== MmGlobalMemoryDescriptors
)
324 /* Unwind our usage */
325 MmMdFreeGlobalDescriptors();
326 --MmDescriptorCallTreeCount
;
329 /* Return back to caller */
334 MmMdRemoveDescriptorFromList (
335 _In_ PBL_MEMORY_DESCRIPTOR_LIST MdList
,
336 _In_ PBL_MEMORY_DESCRIPTOR Entry
339 /* Remove the entry */
340 RemoveEntryList(&Entry
->ListEntry
);
342 /* Check if this was the current link */
343 if (MdList
->This
== &Entry
->ListEntry
)
345 /* Remove the current link and set the next one */
347 MmMdpSaveCurrentListPointer(MdList
, Entry
->ListEntry
.Blink
);
353 _In_ PBL_MEMORY_DESCRIPTOR_LIST MdList
356 PLIST_ENTRY FirstEntry
, NextEntry
;
357 PBL_MEMORY_DESCRIPTOR Entry
;
359 /* Go over every descriptor from the top */
360 FirstEntry
= MdList
->First
;
361 NextEntry
= FirstEntry
->Flink
;
362 while (NextEntry
!= FirstEntry
)
364 /* Remove and free each one */
365 Entry
= CONTAINING_RECORD(NextEntry
, BL_MEMORY_DESCRIPTOR
, ListEntry
);
366 NextEntry
= NextEntry
->Flink
;
367 MmMdRemoveDescriptorFromList(MdList
, Entry
);
368 MmMdFreeDescriptor(Entry
);
372 PBL_MEMORY_DESCRIPTOR
373 MmMdInitByteGranularDescriptor (
375 _In_ BL_MEMORY_TYPE Type
,
376 _In_ ULONGLONG BasePage
,
377 _In_ ULONGLONG VirtualPage
,
378 _In_ ULONGLONG PageCount
381 PBL_MEMORY_DESCRIPTOR MemoryDescriptor
;
383 /* If we're out of descriptors, bail out */
384 if (MmGlobalMemoryDescriptorsUsed
>= MmGlobalMemoryDescriptorCount
)
386 EfiPrintf(L
"Out of descriptors!\r\n");
390 /* Take one of the available descriptors and fill it out */
391 MemoryDescriptor
= &MmGlobalMemoryDescriptors
[MmGlobalMemoryDescriptorsUsed
];
392 MemoryDescriptor
->BaseAddress
= BasePage
;
393 MemoryDescriptor
->VirtualPage
= VirtualPage
;
394 MemoryDescriptor
->PageCount
= PageCount
;
395 MemoryDescriptor
->Flags
= Flags
;
396 MemoryDescriptor
->Type
= Type
;
397 InitializeListHead(&MemoryDescriptor
->ListEntry
);
399 /* Increment the count and return the descriptor */
400 MmGlobalMemoryDescriptorsUsed
++;
401 return MemoryDescriptor
;
405 MmMdpTruncateDescriptor (
406 __in PBL_MEMORY_DESCRIPTOR_LIST MdList
,
407 __in PBL_MEMORY_DESCRIPTOR MemoryDescriptor
,
411 PBL_MEMORY_DESCRIPTOR NextDescriptor
, PreviousDescriptor
;
412 PLIST_ENTRY NextEntry
, PreviousEntry
;
413 ULONGLONG EndPage
, PreviousEndPage
;// , NextEndPage;
415 /* Get the next descriptor */
416 NextEntry
= MemoryDescriptor
->ListEntry
.Flink
;
417 NextDescriptor
= CONTAINING_RECORD(NextEntry
, BL_MEMORY_DESCRIPTOR
, ListEntry
);
419 /* Get the previous descriptor */
420 PreviousEntry
= MemoryDescriptor
->ListEntry
.Blink
;
421 PreviousDescriptor
= CONTAINING_RECORD(PreviousEntry
, BL_MEMORY_DESCRIPTOR
, ListEntry
);
423 /* Calculate end pages */
424 EndPage
= MemoryDescriptor
->BasePage
+ MemoryDescriptor
->PageCount
;
425 //NextEndPage = NextDescriptor->BasePage + NextDescriptor->PageCount;
426 PreviousEndPage
= PreviousDescriptor
->BasePage
+ PreviousDescriptor
->PageCount
;
428 /* Check for backward overlap */
429 if ((PreviousEntry
!= MdList
->First
) && (MemoryDescriptor
->BasePage
< PreviousEndPage
))
431 EfiPrintf(L
"Overlap detected -- this is unexpected on x86/x64 platforms\r\n");
434 /* Check for forward overlap */
435 if ((NextEntry
!= MdList
->First
) && (NextDescriptor
->BasePage
< EndPage
))
437 EfiPrintf(L
"Overlap detected -- this is unexpected on x86/x64 platforms\r\n");
445 MmMdpCoalesceDescriptor (
446 __in PBL_MEMORY_DESCRIPTOR_LIST MdList
,
447 __in PBL_MEMORY_DESCRIPTOR MemoryDescriptor
,
451 PBL_MEMORY_DESCRIPTOR NextDescriptor
, PreviousDescriptor
;
452 PLIST_ENTRY NextEntry
, PreviousEntry
;
453 ULONGLONG EndPage
, PreviousEndPage
, PreviousMappedEndPage
, MappedEndPage
;
455 /* Get the next descriptor */
456 NextEntry
= MemoryDescriptor
->ListEntry
.Flink
;
457 NextDescriptor
= CONTAINING_RECORD(NextEntry
, BL_MEMORY_DESCRIPTOR
, ListEntry
);
459 /* Get the previous descriptor */
460 PreviousEntry
= MemoryDescriptor
->ListEntry
.Blink
;
461 PreviousDescriptor
= CONTAINING_RECORD(PreviousEntry
, BL_MEMORY_DESCRIPTOR
, ListEntry
);
463 /* Calculate end pages */
464 EndPage
= MemoryDescriptor
->BasePage
+ MemoryDescriptor
->PageCount
;
465 MappedEndPage
= MemoryDescriptor
->BasePage
+ MemoryDescriptor
->PageCount
;
466 PreviousMappedEndPage
= PreviousDescriptor
->VirtualPage
+ PreviousDescriptor
->PageCount
;
467 PreviousEndPage
= PreviousDescriptor
->BasePage
+ PreviousDescriptor
->PageCount
;
468 PreviousMappedEndPage
= PreviousDescriptor
->VirtualPage
+ PreviousDescriptor
->PageCount
;
470 /* Check if the previous entry touches the current entry, and is compatible */
471 if ((PreviousEntry
!= MdList
->First
) &&
472 (PreviousDescriptor
->Type
== MemoryDescriptor
->Type
) &&
473 ((PreviousDescriptor
->Flags
^ MemoryDescriptor
->Flags
) & 0x1B19FFFF) &&
474 (PreviousEndPage
== MemoryDescriptor
->BasePage
) &&
475 ((!(MemoryDescriptor
->VirtualPage
) && !(PreviousDescriptor
->VirtualPage
)) ||
476 ((MemoryDescriptor
->VirtualPage
) && (PreviousDescriptor
->VirtualPage
) &&
477 (PreviousMappedEndPage
== MemoryDescriptor
->VirtualPage
))))
479 EfiPrintf(L
"Previous descriptor coalescable!\r\n");
482 /* CHeck if the current entry touches the next entry, and is compatible */
483 if ((NextEntry
!= MdList
->First
) &&
484 (NextDescriptor
->Type
== MemoryDescriptor
->Type
) &&
485 ((NextDescriptor
->Flags
^ MemoryDescriptor
->Flags
) & 0x1B19FFFF) &&
486 (EndPage
== NextDescriptor
->BasePage
) &&
487 ((!(MemoryDescriptor
->VirtualPage
) && !(PreviousDescriptor
->VirtualPage
)) ||
488 ((MemoryDescriptor
->VirtualPage
) && (PreviousDescriptor
->VirtualPage
) &&
489 (MappedEndPage
== NextDescriptor
->VirtualPage
))))
491 EfiPrintf(L
"Next descriptor coalescable!\r\n");
499 MmMdAddDescriptorToList (
500 _In_ PBL_MEMORY_DESCRIPTOR_LIST MdList
,
501 _In_ PBL_MEMORY_DESCRIPTOR MemoryDescriptor
,
505 PLIST_ENTRY ThisEntry
, FirstEntry
;
506 PBL_MEMORY_DESCRIPTOR ThisDescriptor
;
508 /* Arguments must be present */
509 if (!(MdList
) || !(MemoryDescriptor
))
511 return STATUS_INVALID_PARAMETER
;
514 /* Check if coalescing is forcefully disabled */
515 if (Flags
& BL_MM_ADD_DESCRIPTOR_NEVER_COALESCE_FLAG
)
517 /* Then we won't be coalescing */
518 Flags
&= BL_MM_ADD_DESCRIPTOR_COALESCE_FLAG
;
522 /* Coalesce if the descriptor requires it */
523 if (MemoryDescriptor
->Flags
& BlMemoryCoalesced
)
525 Flags
|= BL_MM_ADD_DESCRIPTOR_COALESCE_FLAG
;
529 /* Check if truncation is forcefully disabled */
530 if (Flags
& BL_MM_ADD_DESCRIPTOR_NEVER_TRUNCATE_FLAG
)
532 Flags
&= ~BL_MM_ADD_DESCRIPTOR_TRUNCATE_FLAG
;
535 /* Update the current list pointer if the descriptor requires it */
536 if (MemoryDescriptor
->Flags
& BlMemoryUpdate
)
538 Flags
|= BL_MM_ADD_DESCRIPTOR_UPDATE_LIST_POINTER_FLAG
;
541 /* Get the current descriptor */
542 ThisEntry
= MdList
->This
;
543 ThisDescriptor
= CONTAINING_RECORD(ThisEntry
, BL_MEMORY_DESCRIPTOR
, ListEntry
);
545 /* Also get the first descriptor */
546 FirstEntry
= MdList
->First
;
548 /* Check if there's no current pointer, or if it's higher than the new one */
550 (MemoryDescriptor
->BaseAddress
<= ThisDescriptor
->BaseAddress
))
552 /* Start at the first descriptor instead, since current is past us */
553 ThisEntry
= FirstEntry
->Flink
;
554 ThisDescriptor
= CONTAINING_RECORD(ThisEntry
, BL_MEMORY_DESCRIPTOR
, ListEntry
);
557 /* Loop until we find the right location to insert */
560 /* Have we gotten back to the first entry? */
561 if (ThisEntry
== FirstEntry
)
563 /* Then we didn't find a good match, so insert it right here */
564 InsertTailList(FirstEntry
, &MemoryDescriptor
->ListEntry
);
566 /* Do we have to truncate? */
567 if (Flags
& BL_MM_ADD_DESCRIPTOR_TRUNCATE_FLAG
)
569 /* Do it and then exit */
570 if (MmMdpTruncateDescriptor(MdList
, MemoryDescriptor
, Flags
))
572 return STATUS_SUCCESS
;
576 /* Do we have to coalesce? */
577 if (Flags
& BL_MM_ADD_DESCRIPTOR_COALESCE_FLAG
)
579 /* Do it and then exit */
580 if (MmMdpCoalesceDescriptor(MdList
, MemoryDescriptor
, Flags
))
582 return STATUS_SUCCESS
;
586 /* Do we have to update the current pointer? */
587 if (Flags
& BL_MM_ADD_DESCRIPTOR_UPDATE_LIST_POINTER_FLAG
)
590 MmMdpSaveCurrentListPointer(MdList
, &MemoryDescriptor
->ListEntry
);
594 return STATUS_SUCCESS
;
597 /* Is the new descriptor below this address, and has precedence over it? */
598 if ((MemoryDescriptor
->BaseAddress
< ThisDescriptor
->BaseAddress
) &&
599 (MmMdpHasPrecedence(MemoryDescriptor
->Type
, ThisDescriptor
->Type
)))
601 /* Then insert right here */
602 InsertTailList(ThisEntry
, &MemoryDescriptor
->ListEntry
);
603 return STATUS_SUCCESS
;
606 /* Try the next descriptor */
607 ThisEntry
= ThisEntry
->Flink
;
608 ThisDescriptor
= CONTAINING_RECORD(ThisEntry
, BL_MEMORY_DESCRIPTOR
, ListEntry
);
613 MmMdRemoveRegionFromMdlEx (
614 __in PBL_MEMORY_DESCRIPTOR_LIST MdList
,
616 __in ULONGLONG BasePage
,
617 __in ULONGLONG PageCount
,
618 __in PBL_MEMORY_DESCRIPTOR_LIST NewMdList
621 BOOLEAN HaveNewList
, UseVirtualPage
;
623 PLIST_ENTRY ListHead
, NextEntry
;
624 PBL_MEMORY_DESCRIPTOR Descriptor
;
625 BL_MEMORY_DESCRIPTOR NewDescriptor
;
626 ULONGLONG RegionSize
;
627 ULONGLONG FoundBasePage
, FoundEndPage
, FoundPageCount
, EndPage
;
629 /* Set initial status */
630 Status
= STATUS_SUCCESS
;
632 /* Check if removed descriptors should go into a new list */
633 if (NewMdList
!= NULL
)
636 MmMdInitializeListHead(NewMdList
);
637 NewMdList
->Type
= MdList
->Type
;
639 /* Remember for later */
648 /* Is the region being removed physical? */
649 UseVirtualPage
= FALSE
;
650 if (!(Flags
& BL_MM_REMOVE_VIRTUAL_REGION_FLAG
))
652 /* Is this a list of virtual descriptors? */
653 if (MdList
->Type
== BlMdVirtual
)
655 /* Request is nonsensical, fail */
656 Status
= STATUS_INVALID_PARAMETER
;
662 /* Is this a list of physical descriptors? */
663 if (MdList
->Type
== BlMdPhysical
)
665 /* We'll have to use the virtual page instead */
666 UseVirtualPage
= TRUE
;
671 ListHead
= MdList
->First
;
672 NextEntry
= ListHead
->Flink
;
673 while (NextEntry
!= ListHead
)
675 /* Get the descriptor */
676 Descriptor
= CONTAINING_RECORD(NextEntry
, BL_MEMORY_DESCRIPTOR
, ListEntry
);
678 /* Extract range details */
679 FoundBasePage
= UseVirtualPage
? Descriptor
->VirtualPage
: Descriptor
->BasePage
;
680 FoundPageCount
= Descriptor
->PageCount
;
681 FoundEndPage
= FoundBasePage
+ FoundPageCount
;
682 EndPage
= PageCount
+ BasePage
;
684 /* Make a copy of the original descriptor */
685 RtlCopyMemory(&NewDescriptor
, NextEntry
, sizeof(NewDescriptor
));
687 /* Check if the region to be removed starts after the found region starts */
688 if ((BasePage
> FoundBasePage
) || (FoundBasePage
>= EndPage
))
690 /* Check if the region ends after the found region */
691 if ((BasePage
>= FoundEndPage
) || (FoundEndPage
> EndPage
))
693 /* Check if the found region starts after the region or ends before the region */
694 if ((FoundBasePage
>= BasePage
) || (EndPage
>= FoundEndPage
))
696 /* This descriptor doesn't cover any part of the range -- nothing to do */
701 /* This descriptor fully covers the entire allocation */
702 FoundBasePage
= Descriptor
->BasePage
;
703 FoundPageCount
= BasePage
- FoundBasePage
;
705 /* This is how many pages we will eat away from the descriptor */
706 RegionSize
= FoundPageCount
+ PageCount
;
708 /* Update the descriptor to account for the consumed pages */
709 Descriptor
->BasePage
+= RegionSize
;
710 Descriptor
->PageCount
-= RegionSize
;
711 if (Descriptor
->VirtualPage
)
713 Descriptor
->VirtualPage
+= RegionSize
;
716 /* Initialize a descriptor for the start of the region */
717 Descriptor
= MmMdInitByteGranularDescriptor(Descriptor
->Flags
,
720 Descriptor
->VirtualPage
,
724 Status
= STATUS_NO_MEMORY
;
728 /* Add it into the list */
729 Status
= MmMdAddDescriptorToList(MdList
, Descriptor
, Flags
);
730 if (!NT_SUCCESS(Status
))
732 Status
= STATUS_NO_MEMORY
;
739 /* This descriptor contains the entire allocation */
740 RegionSize
= FoundEndPage
- BasePage
;
741 Descriptor
->PageCount
-= RegionSize
;
745 NextEntry
= NextEntry
->Flink
;
750 * This descriptor contains the end of the allocation. It may:
752 * - Contain the full allocation (i.e.: the start is aligned)
753 * - Contain parts of the end of the allocation (i.e.: the end is beyond)
754 * - Contain the entire tail end of the allocation (i..e:the end is within)
756 * So first, figure out if we cover the entire end or not
758 if (EndPage
< FoundEndPage
)
760 /* The allocation goes past the end of this descriptor */
761 FoundEndPage
= EndPage
;
764 /* This is how many pages we will eat away from the descriptor */
765 RegionSize
= FoundEndPage
- FoundBasePage
;
767 /* Update the descriptor to account for the consumed pages */
768 Descriptor
->BasePage
+= RegionSize
;
769 Descriptor
->PageCount
-= RegionSize
;
770 if (Descriptor
->VirtualPage
)
772 Descriptor
->VirtualPage
+= RegionSize
;
775 /* Go to the next entry */
776 NextEntry
= NextEntry
->Flink
;
778 /* Check if the descriptor is now empty */
779 if (!Descriptor
->PageCount
)
782 MmMdRemoveDescriptorFromList(MdList
, Descriptor
);
783 MmMdFreeDescriptor(Descriptor
);
785 /* Check if we're supposed to insert it into a new list */
788 EfiPrintf(L
"Not yet implemented\r\n");
789 Status
= STATUS_NOT_IMPLEMENTED
;
797 /* Check for failure cleanup */
798 if (!NT_SUCCESS(Status
))
800 /* Did we have to build a new list? */
803 /* Free and re-initialize it */
804 MmMdFreeList(NewMdList
);
805 MmMdInitializeListHead(NewMdList
);
806 NewMdList
->Type
= MdList
->Type
;
813 PBL_MEMORY_DESCRIPTOR
814 MmMdFindDescriptorFromMdl (
815 _In_ PBL_MEMORY_DESCRIPTOR_LIST MdList
,
821 PLIST_ENTRY NextEntry
, ListHead
;
822 PBL_MEMORY_DESCRIPTOR Current
;
825 /* Assume physical */
828 /* Check if the caller wants physical memory */
829 if (!(Flags
& BL_MM_REMOVE_VIRTUAL_REGION_FLAG
))
831 /* Check if this is a virtual memory list */
832 if (MdList
->Type
== BlMdVirtual
)
834 /* We won't find anything */
838 else if (MdList
->Type
== BlMdPhysical
)
840 /* Otherwise, caller wants virtual, but this is a physical list */
842 NextEntry
= MdList
->First
->Flink
;
845 /* Check if this is a physical search */
848 /* Check if we can use the current pointer */
849 NextEntry
= MdList
->This
;
852 /* We can't -- start at the beginning */
853 NextEntry
= MdList
->First
->Flink
;
857 /* If the page is below the current pointer, restart */
858 Current
= CONTAINING_RECORD(NextEntry
, BL_MEMORY_DESCRIPTOR
, ListEntry
);
859 if (Page
< Current
->BasePage
)
861 NextEntry
= MdList
->First
->Flink
;
866 /* Loop the list of descriptors */
867 ListHead
= MdList
->First
;
868 while (NextEntry
!= ListHead
)
870 /* Get the current one */
871 Current
= CONTAINING_RECORD(NextEntry
, BL_MEMORY_DESCRIPTOR
, ListEntry
);
873 /* Check if we are looking for virtual memory */
876 /* Use the base address */
877 BasePage
= Current
->VirtualPage
;
882 BasePage
= Current
->BasePage
;
885 /* If this is a virtual descriptor, make sure it has a base address */
886 if ((!(IsVirtual
) || (BasePage
)) &&
887 (BasePage
<= Page
) &&
888 (Page
< (BasePage
+ Current
->PageCount
)))
890 /* The descriptor fits the page being requested */
894 /* Try the next one */
895 NextEntry
= NextEntry
->Flink
;
898 /* Nothing found if we're here */
902 PBL_MEMORY_DESCRIPTOR
904 _In_ ULONG WhichList
,
909 PBL_MEMORY_DESCRIPTOR FoundDescriptor
;
911 /* Check if the caller is looking for mapped, allocated memory */
912 if (WhichList
& BL_MM_INCLUDE_MAPPED_ALLOCATED
)
914 /* Find a descriptor in that list */
915 FoundDescriptor
= MmMdFindDescriptorFromMdl(&MmMdlMappedAllocated
, Flags
, Page
);
919 return FoundDescriptor
;
923 /* Check if the caller is looking for mapped, unallocated memory */
924 if (WhichList
& BL_MM_INCLUDE_MAPPED_UNALLOCATED
)
926 /* Find a descriptor in that list */
927 FoundDescriptor
= MmMdFindDescriptorFromMdl(&MmMdlMappedUnallocated
, Flags
, Page
);
931 return FoundDescriptor
;
935 /* Check if the caller is looking for unmapped, allocated memory */
936 if (WhichList
& BL_MM_INCLUDE_UNMAPPED_ALLOCATED
)
938 /* Find a descriptor in that list */
939 FoundDescriptor
= MmMdFindDescriptorFromMdl(&MmMdlUnmappedAllocated
, Flags
, Page
);
943 return FoundDescriptor
;
947 /* Check if the caller is looking for unmapped, unallocated memory */
948 if (WhichList
& BL_MM_INCLUDE_UNMAPPED_UNALLOCATED
)
950 /* Find a descriptor in that list */
951 FoundDescriptor
= MmMdFindDescriptorFromMdl(&MmMdlUnmappedUnallocated
, Flags
, Page
);
955 return FoundDescriptor
;
959 /* Check if the caller is looking for reserved, allocated memory */
960 if (WhichList
& BL_MM_INCLUDE_RESERVED_ALLOCATED
)
962 /* Find a descriptor in that list */
963 FoundDescriptor
= MmMdFindDescriptorFromMdl(&MmMdlReservedAllocated
, Flags
, Page
);
967 return FoundDescriptor
;
971 /* Check if the caller is looking for bad memory */
972 if (WhichList
& BL_MM_INCLUDE_BAD_MEMORY
)
974 /* Find a descriptor in that list */
975 FoundDescriptor
= MmMdFindDescriptorFromMdl(&MmMdlBadMemory
, Flags
, Page
);
979 return FoundDescriptor
;
983 /* Check if the caller is looking for truncated memory */
984 if (WhichList
& BL_MM_INCLUDE_TRUNCATED_MEMORY
)
986 /* Find a descriptor in that list */
987 FoundDescriptor
= MmMdFindDescriptorFromMdl(&MmMdlTruncatedMemory
, Flags
, Page
);
991 return FoundDescriptor
;
995 /* Check if the caller is looking for persistent memory */
996 if (WhichList
& BL_MM_INCLUDE_PERSISTENT_MEMORY
)
998 /* Find a descriptor in that list */
999 FoundDescriptor
= MmMdFindDescriptorFromMdl(&MmMdlPersistentMemory
, Flags
, Page
);
1000 if (FoundDescriptor
)
1003 return FoundDescriptor
;
1007 /* Nothing if we got here */
1012 MmMdFindSatisfyingRegion (
1013 _In_ PBL_MEMORY_DESCRIPTOR Descriptor
,
1014 _Out_ PBL_MEMORY_DESCRIPTOR NewDescriptor
,
1015 _In_ ULONGLONG Pages
,
1016 _In_ PBL_ADDRESS_RANGE BaseRange
,
1017 _In_ PBL_ADDRESS_RANGE VirtualRange
,
1018 _In_ BOOLEAN TopDown
,
1019 _In_ BL_MEMORY_TYPE MemoryType
,
1021 _In_ ULONG Alignment
1024 ULONGLONG BaseMin
, BaseMax
;
1025 ULONGLONG VirtualPage
, BasePage
;
1027 /* Extract the minimum and maximum range */
1028 BaseMin
= BaseRange
->Minimum
;
1029 BaseMax
= BaseRange
->Maximum
;
1031 /* Don't go below where the descriptor starts */
1032 if (BaseMin
< Descriptor
->BasePage
)
1034 BaseMin
= Descriptor
->BasePage
;
1037 /* Don't go beyond where the descriptor ends */
1038 if (BaseMax
> (Descriptor
->BasePage
+ Descriptor
->PageCount
- 1))
1040 BaseMax
= (Descriptor
->BasePage
+ Descriptor
->PageCount
- 1);
1043 /* Check for start overflow */
1044 if (BaseMin
> BaseMax
)
1046 EfiPrintf(L
"Descriptor overflow\r\n");
1050 /* Align the base as required */
1053 BaseMin
= ALIGN_UP_BY(BaseMin
, Alignment
);
1056 /* Check for range overflow */
1057 if (((BaseMin
+ Pages
- 1) < BaseMin
) || ((BaseMin
+ Pages
- 1) > BaseMax
))
1062 /* Check if this was a top-down request */
1065 /* Then get the highest page possible */
1066 BasePage
= BaseMax
- Pages
+ 1;
1069 /* Align it as needed */
1070 BasePage
= ALIGN_DOWN_BY(BasePage
, Alignment
);
1075 /* Otherwise, get the lowest page possible */
1079 /* If a virtual address range was passed in, this must be a virtual descriptor */
1080 if (((VirtualRange
->Minimum
) || (VirtualRange
->Maximum
)) &&
1081 !(Descriptor
->VirtualPage
))
1086 /* Any mapped page already? */
1087 if (Descriptor
->VirtualPage
)
1089 EfiPrintf(L
"Virtual memory not yet supported\r\n");
1094 /* Nothing to worry about */
1098 /* Bail out if the memory type attributes don't match */
1099 if ((((Flags
& 0xFF) & (Descriptor
->Flags
& 0xFF)) != (Flags
& 0xFF)) ||
1100 (((Flags
& 0xFF00) & (Descriptor
->Flags
& 0xFF00)) != (Flags
& 0xFF00)))
1102 EfiPrintf(L
"Incorrect memory attributes\r\n");
1106 /* Bail out if the allocation flags don't match */
1107 if (((Flags
^ Descriptor
->Flags
) & (BlMemoryRuntime
| BlMemoryBelow1MB
| BlMemoryLargePages
)))
1109 //EfiPrintf(L"Incorrect memory allocation flags\r\n");
1113 /* Bail out if the type doesn't match */
1114 if (Descriptor
->Type
!= MemoryType
)
1116 //EfiPrintf(L"Incorrect descriptor type: %lx %lx\r\n", Descriptor->Type, MemoryType);
1120 /* We have a matching region, fill out the descriptor for it */
1121 NewDescriptor
->BasePage
= BasePage
;
1122 NewDescriptor
->PageCount
= Pages
;
1123 NewDescriptor
->Type
= Descriptor
->Type
;
1124 NewDescriptor
->VirtualPage
= VirtualPage
;
1125 NewDescriptor
->Flags
= Descriptor
->Flags
;
1126 //EfiPrintf(L"Found a matching descriptor: %08I64X with %08I64X pages\r\n", BasePage, Pages);
1131 MmMdFreeGlobalDescriptors (
1135 PBL_MEMORY_DESCRIPTOR Descriptor
, OldDescriptor
;
1137 PLIST_ENTRY OldFlink
, OldBlink
;
1139 /* Make sure we're not int middle of a call using a descriptor */
1140 if (MmDescriptorCallTreeCount
!= 1)
1145 /* Loop every current global descriptor */
1146 while (Index
< MmGlobalMemoryDescriptorsUsed
)
1148 /* Does it have any valid pageS? */
1149 OldDescriptor
= &MmGlobalMemoryDescriptors
[Index
];
1150 if (OldDescriptor
->PageCount
)
1152 /* Allocate a copy of it */
1153 Descriptor
= BlMmAllocateHeap(sizeof(*Descriptor
));
1159 /* Save the links */
1160 OldBlink
= OldDescriptor
->ListEntry
.Blink
;
1161 OldFlink
= OldDescriptor
->ListEntry
.Flink
;
1164 *Descriptor
= *OldDescriptor
;
1167 OldBlink
->Flink
= &Descriptor
->ListEntry
;
1168 OldFlink
->Blink
= &Descriptor
->ListEntry
;
1170 /* Zero the descriptor */
1171 RtlZeroMemory(OldDescriptor
, sizeof(*OldDescriptor
));
1178 /* All global descriptors freed */
1179 MmGlobalMemoryDescriptorsUsed
= 0;
1185 _In_ PBL_LIBRARY_PARAMETERS LibraryParameters
1188 /* Are we in phase 1? */
1191 /* Switch to dynamic descriptors if we have too many */
1192 if (LibraryParameters
->DescriptorCount
> RTL_NUMBER_OF(MmStaticMemoryDescriptors
))
1194 MmMdpSwitchToDynamicDescriptors(LibraryParameters
->DescriptorCount
);
1199 /* In phase 0, start with a pool of 512 static descriptors */
1200 MmGlobalMemoryDescriptorCount
= RTL_NUMBER_OF(MmStaticMemoryDescriptors
);
1201 MmGlobalMemoryDescriptors
= MmStaticMemoryDescriptors
;
1202 RtlZeroMemory(MmStaticMemoryDescriptors
, sizeof(MmStaticMemoryDescriptors
));
1203 MmGlobalMemoryDescriptorsUsed
= 0;