2 SMM Memory page management functions.
4 Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
10 #include <Library/SmmServicesTableLib.h>
12 #define TRUNCATE_TO_PAGES(a) ((a) >> EFI_PAGE_SHIFT)
14 LIST_ENTRY mSmmMemoryMap
= INITIALIZE_LIST_HEAD_VARIABLE (mSmmMemoryMap
);
20 #define MEMORY_MAP_SIGNATURE SIGNATURE_32('m','m','a','p')
31 LIST_ENTRY gMemoryMap
= INITIALIZE_LIST_HEAD_VARIABLE (gMemoryMap
);
33 #define MAX_MAP_DEPTH 6
36 /// mMapDepth - depth of new descriptor stack
40 /// mMapStack - space to use as temp storage to build new map descriptors
42 MEMORY_MAP mMapStack
[MAX_MAP_DEPTH
];
43 UINTN mFreeMapStack
= 0;
45 /// This list maintain the free memory map list
47 LIST_ENTRY mFreeMemoryMapEntryList
= INITIALIZE_LIST_HEAD_VARIABLE (mFreeMemoryMapEntryList
);
50 Allocates pages from the memory map.
52 @param[in] Type The type of allocation to perform.
53 @param[in] MemoryType The type of memory to turn the allocated pages
55 @param[in] NumberOfPages The number of pages to allocate.
56 @param[out] Memory A pointer to receive the base allocated memory
58 @param[in] AddRegion If this memory is new added region.
59 @param[in] NeedGuard Flag to indicate Guard page is needed
62 @retval EFI_INVALID_PARAMETER Parameters violate checking rules defined in spec.
63 @retval EFI_NOT_FOUND Could not allocate pages match the requirement.
64 @retval EFI_OUT_OF_RESOURCES No enough pages to allocate.
65 @retval EFI_SUCCESS Pages successfully allocated.
69 SmmInternalAllocatePagesEx (
70 IN EFI_ALLOCATE_TYPE Type
,
71 IN EFI_MEMORY_TYPE MemoryType
,
72 IN UINTN NumberOfPages
,
73 OUT EFI_PHYSICAL_ADDRESS
*Memory
,
79 Internal function. Deque a descriptor entry from the mFreeMemoryMapEntryList.
80 If the list is emtry, then allocate a new page to refuel the list.
81 Please Note this algorithm to allocate the memory map descriptor has a property
82 that the memory allocated for memory entries always grows, and will never really be freed.
84 @return The Memory map descriptor dequeued from the mFreeMemoryMapEntryList
88 AllocateMemoryMapEntry (
92 EFI_PHYSICAL_ADDRESS Mem
;
94 MEMORY_MAP
*FreeDescriptorEntries
;
98 // DEBUG((DEBUG_INFO, "AllocateMemoryMapEntry\n"));
100 if (IsListEmpty (&mFreeMemoryMapEntryList
)) {
101 // DEBUG((DEBUG_INFO, "mFreeMemoryMapEntryList is empty\n"));
103 // The list is empty, to allocate one page to refuel the list
105 Status
= SmmInternalAllocatePagesEx (
107 EfiRuntimeServicesData
,
108 EFI_SIZE_TO_PAGES (RUNTIME_PAGE_ALLOCATION_GRANULARITY
),
113 ASSERT_EFI_ERROR (Status
);
114 if (!EFI_ERROR (Status
)) {
115 FreeDescriptorEntries
= (MEMORY_MAP
*)(UINTN
)Mem
;
116 // DEBUG((DEBUG_INFO, "New FreeDescriptorEntries - 0x%x\n", FreeDescriptorEntries));
118 // Enqueue the free memory map entries into the list
120 for (Index
= 0; Index
< RUNTIME_PAGE_ALLOCATION_GRANULARITY
/ sizeof (MEMORY_MAP
); Index
++) {
121 FreeDescriptorEntries
[Index
].Signature
= MEMORY_MAP_SIGNATURE
;
122 InsertTailList (&mFreeMemoryMapEntryList
, &FreeDescriptorEntries
[Index
].Link
);
130 // dequeue the first descriptor from the list
132 Entry
= CR (mFreeMemoryMapEntryList
.ForwardLink
, MEMORY_MAP
, Link
, MEMORY_MAP_SIGNATURE
);
133 RemoveEntryList (&Entry
->Link
);
139 Internal function. Moves any memory descriptors that are on the
140 temporary descriptor stack to heap.
144 CoreFreeMemoryMapStack (
151 // If already freeing the map stack, then return
153 if (mFreeMapStack
!= 0) {
159 // Move the temporary memory descriptor stack into pool
163 while (mMapDepth
!= 0) {
165 // Deque an memory map entry from mFreeMemoryMapEntryList
167 Entry
= AllocateMemoryMapEntry ();
171 // Update to proper entry
175 if (mMapStack
[mMapDepth
].Link
.ForwardLink
!= NULL
) {
176 CopyMem (Entry
, &mMapStack
[mMapDepth
], sizeof (MEMORY_MAP
));
177 Entry
->FromStack
= FALSE
;
180 // Move this entry to general memory
182 InsertTailList (&mMapStack
[mMapDepth
].Link
, &Entry
->Link
);
183 RemoveEntryList (&mMapStack
[mMapDepth
].Link
);
184 mMapStack
[mMapDepth
].Link
.ForwardLink
= NULL
;
192 Insert new entry from memory map.
194 @param[in] Link The old memory map entry to be linked.
195 @param[in] Start The start address of new memory map entry.
196 @param[in] End The end address of new memory map entry.
197 @param[in] Type The type of new memory map entry.
198 @param[in] Next If new entry is inserted to the next of old entry.
199 @param[in] AddRegion If this memory is new added region.
206 IN EFI_MEMORY_TYPE Type
,
213 Entry
= &mMapStack
[mMapDepth
];
215 ASSERT (mMapDepth
< MAX_MAP_DEPTH
);
216 Entry
->FromStack
= TRUE
;
218 Entry
->Signature
= MEMORY_MAP_SIGNATURE
;
220 Entry
->Start
= Start
;
223 InsertHeadList (Link
, &Entry
->Link
);
225 InsertTailList (Link
, &Entry
->Link
);
230 Remove old entry from memory map.
232 @param[in] Entry Memory map entry to be removed.
239 RemoveEntryList (&Entry
->Link
);
240 Entry
->Link
.ForwardLink
= NULL
;
242 if (!Entry
->FromStack
) {
243 InsertTailList (&mFreeMemoryMapEntryList
, &Entry
->Link
);
248 Update SMM memory map entry.
250 @param[in] Type The type of allocation to perform.
251 @param[in] Memory The base of memory address.
252 @param[in] NumberOfPages The number of pages to allocate.
253 @param[in] AddRegion If this memory is new added region.
256 ConvertSmmMemoryMapEntry (
257 IN EFI_MEMORY_TYPE Type
,
258 IN EFI_PHYSICAL_ADDRESS Memory
,
259 IN UINTN NumberOfPages
,
265 MEMORY_MAP
*NextEntry
;
266 LIST_ENTRY
*NextLink
;
267 MEMORY_MAP
*PreviousEntry
;
268 LIST_ENTRY
*PreviousLink
;
269 EFI_PHYSICAL_ADDRESS Start
;
270 EFI_PHYSICAL_ADDRESS End
;
273 End
= Memory
+ EFI_PAGES_TO_SIZE (NumberOfPages
) - 1;
276 // Exclude memory region
278 Link
= gMemoryMap
.ForwardLink
;
279 while (Link
!= &gMemoryMap
) {
280 Entry
= CR (Link
, MEMORY_MAP
, Link
, MEMORY_MAP_SIGNATURE
);
281 Link
= Link
->ForwardLink
;
284 // ---------------------------------------------------
285 // | +----------+ +------+ +------+ +------+ |
286 // ---|gMemoryMep|---|Entry1|---|Entry2|---|Entry3|---
287 // +----------+ ^ +------+ +------+ +------+
293 if (Entry
->Start
> End
) {
294 if ((Entry
->Start
== End
+ 1) && (Entry
->Type
== Type
)) {
295 Entry
->Start
= Start
;
310 if ((Entry
->Start
<= Start
) && (Entry
->End
>= End
)) {
311 if (Entry
->Type
!= Type
) {
312 if (Entry
->Start
< Start
) {
314 // ---------------------------------------------------
315 // | +----------+ +------+ +------+ +------+ |
316 // ---|gMemoryMep|---|Entry1|---|EntryX|---|Entry3|---
317 // +----------+ +------+ ^ +------+ +------+
333 if (Entry
->End
> End
) {
335 // ---------------------------------------------------
336 // | +----------+ +------+ +------+ +------+ |
337 // ---|gMemoryMep|---|Entry1|---|EntryX|---|Entry3|---
338 // +----------+ +------+ +------+ ^ +------+
357 Entry
->Start
= Start
;
364 NextLink
= Entry
->Link
.ForwardLink
;
365 if (NextLink
!= &gMemoryMap
) {
366 NextEntry
= CR (NextLink
, MEMORY_MAP
, Link
, MEMORY_MAP_SIGNATURE
);
368 // ---------------------------------------------------
369 // | +----------+ +------+ +-----------------+ |
370 // ---|gMemoryMep|---|Entry1|---|EntryX Entry3|---
371 // +----------+ +------+ +-----------------+
373 if ((Entry
->Type
== NextEntry
->Type
) && (Entry
->End
+ 1 == NextEntry
->Start
)) {
374 Entry
->End
= NextEntry
->End
;
375 RemoveOldEntry (NextEntry
);
379 PreviousLink
= Entry
->Link
.BackLink
;
380 if (PreviousLink
!= &gMemoryMap
) {
381 PreviousEntry
= CR (PreviousLink
, MEMORY_MAP
, Link
, MEMORY_MAP_SIGNATURE
);
383 // ---------------------------------------------------
384 // | +----------+ +-----------------+ +------+ |
385 // ---|gMemoryMep|---|Entry1 EntryX|---|Entry3|---
386 // +----------+ +-----------------+ +------+
388 if ((PreviousEntry
->Type
== Entry
->Type
) && (PreviousEntry
->End
+ 1 == Entry
->Start
)) {
389 PreviousEntry
->End
= Entry
->End
;
390 RemoveOldEntry (Entry
);
400 // ---------------------------------------------------
401 // | +----------+ +------+ +------+ +------+ |
402 // ---|gMemoryMep|---|Entry1|---|Entry2|---|Entry3|---
403 // +----------+ +------+ +------+ +------+ ^
409 Link
= gMemoryMap
.BackLink
;
410 if (Link
!= &gMemoryMap
) {
411 Entry
= CR (Link
, MEMORY_MAP
, Link
, MEMORY_MAP_SIGNATURE
);
412 if ((Entry
->End
+ 1 == Start
) && (Entry
->Type
== Type
)) {
430 Return the count of Smm memory map entry.
432 @return The count of Smm memory map entry.
435 GetSmmMemoryMapEntryCount (
443 Link
= gMemoryMap
.ForwardLink
;
444 while (Link
!= &gMemoryMap
) {
445 Link
= Link
->ForwardLink
;
453 Internal Function. Allocate n pages from given free page node.
455 @param Pages The free page node.
456 @param NumberOfPages Number of pages to be allocated.
457 @param MaxAddress Request to allocate memory below this address.
459 @return Memory address of allocated pages.
463 InternalAllocPagesOnOneNode (
464 IN OUT FREE_PAGE_LIST
*Pages
,
465 IN UINTN NumberOfPages
,
471 FREE_PAGE_LIST
*Node
;
473 Top
= TRUNCATE_TO_PAGES (MaxAddress
+ 1 - (UINTN
)Pages
);
474 if (Top
> Pages
->NumberOfPages
) {
475 Top
= Pages
->NumberOfPages
;
478 Bottom
= Top
- NumberOfPages
;
480 if (Top
< Pages
->NumberOfPages
) {
481 Node
= (FREE_PAGE_LIST
*)((UINTN
)Pages
+ EFI_PAGES_TO_SIZE (Top
));
482 Node
->NumberOfPages
= Pages
->NumberOfPages
- Top
;
483 InsertHeadList (&Pages
->Link
, &Node
->Link
);
487 Pages
->NumberOfPages
= Bottom
;
489 RemoveEntryList (&Pages
->Link
);
492 return (UINTN
)Pages
+ EFI_PAGES_TO_SIZE (Bottom
);
496 Internal Function. Allocate n pages from free page list below MaxAddress.
498 @param FreePageList The free page node.
499 @param NumberOfPages Number of pages to be allocated.
500 @param MaxAddress Request to allocate memory below this address.
502 @return Memory address of allocated pages.
506 InternalAllocMaxAddress (
507 IN OUT LIST_ENTRY
*FreePageList
,
508 IN UINTN NumberOfPages
,
513 FREE_PAGE_LIST
*Pages
;
515 for (Node
= FreePageList
->BackLink
; Node
!= FreePageList
; Node
= Node
->BackLink
) {
516 Pages
= BASE_CR (Node
, FREE_PAGE_LIST
, Link
);
517 if ((Pages
->NumberOfPages
>= NumberOfPages
) &&
518 ((UINTN
)Pages
+ EFI_PAGES_TO_SIZE (NumberOfPages
) - 1 <= MaxAddress
))
520 return InternalAllocPagesOnOneNode (Pages
, NumberOfPages
, MaxAddress
);
528 Internal Function. Allocate n pages from free page list at given address.
530 @param FreePageList The free page node.
531 @param NumberOfPages Number of pages to be allocated.
532 @param MaxAddress Request to allocate memory below this address.
534 @return Memory address of allocated pages.
538 InternalAllocAddress (
539 IN OUT LIST_ENTRY
*FreePageList
,
540 IN UINTN NumberOfPages
,
546 FREE_PAGE_LIST
*Pages
;
548 if ((Address
& EFI_PAGE_MASK
) != 0) {
552 EndAddress
= Address
+ EFI_PAGES_TO_SIZE (NumberOfPages
);
553 for (Node
= FreePageList
->BackLink
; Node
!= FreePageList
; Node
= Node
->BackLink
) {
554 Pages
= BASE_CR (Node
, FREE_PAGE_LIST
, Link
);
555 if ((UINTN
)Pages
<= Address
) {
556 if ((UINTN
)Pages
+ EFI_PAGES_TO_SIZE (Pages
->NumberOfPages
) < EndAddress
) {
560 return InternalAllocPagesOnOneNode (Pages
, NumberOfPages
, EndAddress
);
568 Allocates pages from the memory map.
570 @param[in] Type The type of allocation to perform.
571 @param[in] MemoryType The type of memory to turn the allocated pages
573 @param[in] NumberOfPages The number of pages to allocate.
574 @param[out] Memory A pointer to receive the base allocated memory
576 @param[in] AddRegion If this memory is new added region.
577 @param[in] NeedGuard Flag to indicate Guard page is needed
580 @retval EFI_INVALID_PARAMETER Parameters violate checking rules defined in spec.
581 @retval EFI_NOT_FOUND Could not allocate pages match the requirement.
582 @retval EFI_OUT_OF_RESOURCES No enough pages to allocate.
583 @retval EFI_SUCCESS Pages successfully allocated.
587 SmmInternalAllocatePagesEx (
588 IN EFI_ALLOCATE_TYPE Type
,
589 IN EFI_MEMORY_TYPE MemoryType
,
590 IN UINTN NumberOfPages
,
591 OUT EFI_PHYSICAL_ADDRESS
*Memory
,
592 IN BOOLEAN AddRegion
,
596 UINTN RequestedAddress
;
598 if ((MemoryType
!= EfiRuntimeServicesCode
) &&
599 (MemoryType
!= EfiRuntimeServicesData
))
601 return EFI_INVALID_PARAMETER
;
604 if (NumberOfPages
> TRUNCATE_TO_PAGES ((UINTN
)-1) + 1) {
605 return EFI_OUT_OF_RESOURCES
;
609 // We don't track memory type in SMM
611 RequestedAddress
= (UINTN
)*Memory
;
613 case AllocateAnyPages
:
614 RequestedAddress
= (UINTN
)(-1);
615 case AllocateMaxAddress
:
617 *Memory
= InternalAllocMaxAddressWithGuard (
623 if (*Memory
== (UINTN
)-1) {
624 return EFI_OUT_OF_RESOURCES
;
626 ASSERT (VerifyMemoryGuard (*Memory
, NumberOfPages
) == TRUE
);
631 *Memory
= InternalAllocMaxAddress (
636 if (*Memory
== (UINTN
)-1) {
637 return EFI_OUT_OF_RESOURCES
;
641 case AllocateAddress
:
642 *Memory
= InternalAllocAddress (
647 if (*Memory
!= RequestedAddress
) {
648 return EFI_NOT_FOUND
;
653 return EFI_INVALID_PARAMETER
;
657 // Update SmmMemoryMap here.
659 ConvertSmmMemoryMapEntry (MemoryType
, *Memory
, NumberOfPages
, AddRegion
);
661 CoreFreeMemoryMapStack ();
668 Allocates pages from the memory map.
670 @param[in] Type The type of allocation to perform.
671 @param[in] MemoryType The type of memory to turn the allocated pages
673 @param[in] NumberOfPages The number of pages to allocate.
674 @param[out] Memory A pointer to receive the base allocated memory
676 @param[in] NeedGuard Flag to indicate Guard page is needed
679 @retval EFI_INVALID_PARAMETER Parameters violate checking rules defined in spec.
680 @retval EFI_NOT_FOUND Could not allocate pages match the requirement.
681 @retval EFI_OUT_OF_RESOURCES No enough pages to allocate.
682 @retval EFI_SUCCESS Pages successfully allocated.
687 SmmInternalAllocatePages (
688 IN EFI_ALLOCATE_TYPE Type
,
689 IN EFI_MEMORY_TYPE MemoryType
,
690 IN UINTN NumberOfPages
,
691 OUT EFI_PHYSICAL_ADDRESS
*Memory
,
695 return SmmInternalAllocatePagesEx (
706 Allocates pages from the memory map.
708 @param Type The type of allocation to perform.
709 @param MemoryType The type of memory to turn the allocated pages
711 @param NumberOfPages The number of pages to allocate.
712 @param Memory A pointer to receive the base allocated memory
715 @retval EFI_INVALID_PARAMETER Parameters violate checking rules defined in spec.
716 @retval EFI_NOT_FOUND Could not allocate pages match the requirement.
717 @retval EFI_OUT_OF_RESOURCES No enough pages to allocate.
718 @retval EFI_SUCCESS Pages successfully allocated.
724 IN EFI_ALLOCATE_TYPE Type
,
725 IN EFI_MEMORY_TYPE MemoryType
,
726 IN UINTN NumberOfPages
,
727 OUT EFI_PHYSICAL_ADDRESS
*Memory
733 NeedGuard
= IsPageTypeToGuard (MemoryType
, Type
);
734 Status
= SmmInternalAllocatePages (
741 if (!EFI_ERROR (Status
)) {
742 SmmCoreUpdateProfile (
743 (EFI_PHYSICAL_ADDRESS
)(UINTN
)RETURN_ADDRESS (0),
744 MemoryProfileActionAllocatePages
,
746 EFI_PAGES_TO_SIZE (NumberOfPages
),
747 (VOID
*)(UINTN
)*Memory
,
756 Internal Function. Merge two adjacent nodes.
758 @param First The first of two nodes to merge.
760 @return Pointer to node after merge (if success) or pointer to next node (if fail).
765 IN FREE_PAGE_LIST
*First
768 FREE_PAGE_LIST
*Next
;
770 Next
= BASE_CR (First
->Link
.ForwardLink
, FREE_PAGE_LIST
, Link
);
772 TRUNCATE_TO_PAGES ((UINTN
)Next
- (UINTN
)First
) >= First
->NumberOfPages
775 if (TRUNCATE_TO_PAGES ((UINTN
)Next
- (UINTN
)First
) == First
->NumberOfPages
) {
776 First
->NumberOfPages
+= Next
->NumberOfPages
;
777 RemoveEntryList (&Next
->Link
);
785 Frees previous allocated pages.
787 @param[in] Memory Base address of memory being freed.
788 @param[in] NumberOfPages The number of pages to free.
789 @param[in] AddRegion If this memory is new added region.
791 @retval EFI_NOT_FOUND Could not find the entry that covers the range.
792 @retval EFI_INVALID_PARAMETER Address not aligned, Address is zero or NumberOfPages is zero.
793 @return EFI_SUCCESS Pages successfully freed.
797 SmmInternalFreePagesEx (
798 IN EFI_PHYSICAL_ADDRESS Memory
,
799 IN UINTN NumberOfPages
,
804 FREE_PAGE_LIST
*Pages
;
806 if (((Memory
& EFI_PAGE_MASK
) != 0) || (Memory
== 0) || (NumberOfPages
== 0)) {
807 return EFI_INVALID_PARAMETER
;
811 Node
= mSmmMemoryMap
.ForwardLink
;
812 while (Node
!= &mSmmMemoryMap
) {
813 Pages
= BASE_CR (Node
, FREE_PAGE_LIST
, Link
);
814 if (Memory
< (UINTN
)Pages
) {
818 Node
= Node
->ForwardLink
;
821 if ((Node
!= &mSmmMemoryMap
) &&
822 (Memory
+ EFI_PAGES_TO_SIZE (NumberOfPages
) > (UINTN
)Pages
))
824 return EFI_INVALID_PARAMETER
;
827 if (Node
->BackLink
!= &mSmmMemoryMap
) {
828 Pages
= BASE_CR (Node
->BackLink
, FREE_PAGE_LIST
, Link
);
829 if ((UINTN
)Pages
+ EFI_PAGES_TO_SIZE (Pages
->NumberOfPages
) > Memory
) {
830 return EFI_INVALID_PARAMETER
;
834 Pages
= (FREE_PAGE_LIST
*)(UINTN
)Memory
;
835 Pages
->NumberOfPages
= NumberOfPages
;
836 InsertTailList (Node
, &Pages
->Link
);
838 if (Pages
->Link
.BackLink
!= &mSmmMemoryMap
) {
839 Pages
= InternalMergeNodes (
840 BASE_CR (Pages
->Link
.BackLink
, FREE_PAGE_LIST
, Link
)
844 if (Node
!= &mSmmMemoryMap
) {
845 InternalMergeNodes (Pages
);
849 // Update SmmMemoryMap here.
851 ConvertSmmMemoryMapEntry (EfiConventionalMemory
, Memory
, NumberOfPages
, AddRegion
);
853 CoreFreeMemoryMapStack ();
860 Frees previous allocated pages.
862 @param[in] Memory Base address of memory being freed.
863 @param[in] NumberOfPages The number of pages to free.
864 @param[in] IsGuarded Is the memory to free guarded or not.
866 @retval EFI_NOT_FOUND Could not find the entry that covers the range.
867 @retval EFI_INVALID_PARAMETER Address not aligned, Address is zero or NumberOfPages is zero.
868 @return EFI_SUCCESS Pages successfully freed.
873 SmmInternalFreePages (
874 IN EFI_PHYSICAL_ADDRESS Memory
,
875 IN UINTN NumberOfPages
,
880 return SmmInternalFreePagesExWithGuard (Memory
, NumberOfPages
, FALSE
);
883 return SmmInternalFreePagesEx (Memory
, NumberOfPages
, FALSE
);
887 Check whether the input range is in memory map.
889 @param Memory Base address of memory being inputed.
890 @param NumberOfPages The number of pages.
892 @retval TRUE In memory map.
893 @retval FALSE Not in memory map.
898 IN EFI_PHYSICAL_ADDRESS Memory
,
899 IN UINTN NumberOfPages
904 EFI_PHYSICAL_ADDRESS Last
;
906 Last
= Memory
+ EFI_PAGES_TO_SIZE (NumberOfPages
) - 1;
908 Link
= gMemoryMap
.ForwardLink
;
909 while (Link
!= &gMemoryMap
) {
910 Entry
= CR (Link
, MEMORY_MAP
, Link
, MEMORY_MAP_SIGNATURE
);
911 Link
= Link
->ForwardLink
;
913 if ((Entry
->Start
<= Memory
) && (Entry
->End
>= Last
)) {
922 Frees previous allocated pages.
924 @param Memory Base address of memory being freed.
925 @param NumberOfPages The number of pages to free.
927 @retval EFI_NOT_FOUND Could not find the entry that covers the range.
928 @retval EFI_INVALID_PARAMETER Address not aligned, Address is zero or NumberOfPages is zero.
929 @return EFI_SUCCESS Pages successfully freed.
935 IN EFI_PHYSICAL_ADDRESS Memory
,
936 IN UINTN NumberOfPages
942 if (!InMemMap (Memory
, NumberOfPages
)) {
943 return EFI_NOT_FOUND
;
946 IsGuarded
= IsHeapGuardEnabled () && IsMemoryGuarded (Memory
);
947 Status
= SmmInternalFreePages (Memory
, NumberOfPages
, IsGuarded
);
948 if (!EFI_ERROR (Status
)) {
949 SmmCoreUpdateProfile (
950 (EFI_PHYSICAL_ADDRESS
)(UINTN
)RETURN_ADDRESS (0),
951 MemoryProfileActionFreePages
,
953 EFI_PAGES_TO_SIZE (NumberOfPages
),
954 (VOID
*)(UINTN
)Memory
,
963 Add free SMRAM region for use by memory service.
965 @param MemBase Base address of memory region.
966 @param MemLength Length of the memory region.
967 @param Type Memory type.
968 @param Attributes Memory region state.
973 IN EFI_PHYSICAL_ADDRESS MemBase
,
975 IN EFI_MEMORY_TYPE Type
,
979 UINTN AlignedMemBase
;
982 // Add EfiRuntimeServicesData for memory regions that is already allocated, needs testing, or needs ECC initialization
984 if ((Attributes
& (EFI_ALLOCATED
| EFI_NEEDS_TESTING
| EFI_NEEDS_ECC_INITIALIZATION
)) != 0) {
985 Type
= EfiRuntimeServicesData
;
987 Type
= EfiConventionalMemory
;
990 DEBUG ((DEBUG_INFO
, "SmmAddMemoryRegion\n"));
991 DEBUG ((DEBUG_INFO
, " MemBase - 0x%lx\n", MemBase
));
992 DEBUG ((DEBUG_INFO
, " MemLength - 0x%lx\n", MemLength
));
993 DEBUG ((DEBUG_INFO
, " Type - 0x%x\n", Type
));
994 DEBUG ((DEBUG_INFO
, " Attributes - 0x%lx\n", Attributes
));
997 // Align range on an EFI_PAGE_SIZE boundary
999 AlignedMemBase
= (UINTN
)(MemBase
+ EFI_PAGE_MASK
) & ~EFI_PAGE_MASK
;
1000 MemLength
-= AlignedMemBase
- MemBase
;
1001 if (Type
== EfiConventionalMemory
) {
1002 SmmInternalFreePagesEx (AlignedMemBase
, TRUNCATE_TO_PAGES ((UINTN
)MemLength
), TRUE
);
1004 ConvertSmmMemoryMapEntry (EfiRuntimeServicesData
, AlignedMemBase
, TRUNCATE_TO_PAGES ((UINTN
)MemLength
), TRUE
);
1007 CoreFreeMemoryMapStack ();
1011 This function returns a copy of the current memory map. The map is an array of
1012 memory descriptors, each of which describes a contiguous block of memory.
1014 @param[in, out] MemoryMapSize A pointer to the size, in bytes, of the
1015 MemoryMap buffer. On input, this is the size of
1016 the buffer allocated by the caller. On output,
1017 it is the size of the buffer returned by the
1018 firmware if the buffer was large enough, or the
1019 size of the buffer needed to contain the map if
1020 the buffer was too small.
1021 @param[in, out] MemoryMap A pointer to the buffer in which firmware places
1022 the current memory map.
1023 @param[out] MapKey A pointer to the location in which firmware
1024 returns the key for the current memory map.
1025 @param[out] DescriptorSize A pointer to the location in which firmware
1026 returns the size, in bytes, of an individual
1027 EFI_MEMORY_DESCRIPTOR.
1028 @param[out] DescriptorVersion A pointer to the location in which firmware
1029 returns the version number associated with the
1030 EFI_MEMORY_DESCRIPTOR.
1032 @retval EFI_SUCCESS The memory map was returned in the MemoryMap
1034 @retval EFI_BUFFER_TOO_SMALL The MemoryMap buffer was too small. The current
1035 buffer size needed to hold the memory map is
1036 returned in MemoryMapSize.
1037 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
1042 SmmCoreGetMemoryMap (
1043 IN OUT UINTN
*MemoryMapSize
,
1044 IN OUT EFI_MEMORY_DESCRIPTOR
*MemoryMap
,
1046 OUT UINTN
*DescriptorSize
,
1047 OUT UINT32
*DescriptorVersion
1056 Size
= sizeof (EFI_MEMORY_DESCRIPTOR
);
1059 // Make sure Size != sizeof(EFI_MEMORY_DESCRIPTOR). This will
1060 // prevent people from having pointer math bugs in their code.
1061 // now you have to use *DescriptorSize to make things work.
1063 Size
+= sizeof (UINT64
) - (Size
% sizeof (UINT64
));
1065 if (DescriptorSize
!= NULL
) {
1066 *DescriptorSize
= Size
;
1069 if (DescriptorVersion
!= NULL
) {
1070 *DescriptorVersion
= EFI_MEMORY_DESCRIPTOR_VERSION
;
1073 Count
= GetSmmMemoryMapEntryCount ();
1074 BufferSize
= Size
* Count
;
1075 if (*MemoryMapSize
< BufferSize
) {
1076 *MemoryMapSize
= BufferSize
;
1077 return EFI_BUFFER_TOO_SMALL
;
1080 *MemoryMapSize
= BufferSize
;
1081 if (MemoryMap
== NULL
) {
1082 return EFI_INVALID_PARAMETER
;
1085 ZeroMem (MemoryMap
, BufferSize
);
1086 Link
= gMemoryMap
.ForwardLink
;
1087 while (Link
!= &gMemoryMap
) {
1088 Entry
= CR (Link
, MEMORY_MAP
, Link
, MEMORY_MAP_SIGNATURE
);
1089 Link
= Link
->ForwardLink
;
1091 MemoryMap
->Type
= Entry
->Type
;
1092 MemoryMap
->PhysicalStart
= Entry
->Start
;
1093 MemoryMap
->NumberOfPages
= RShiftU64 (Entry
->End
- Entry
->Start
+ 1, EFI_PAGE_SHIFT
);
1095 MemoryMap
= NEXT_MEMORY_DESCRIPTOR (MemoryMap
, Size
);