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')
32 LIST_ENTRY gMemoryMap
= INITIALIZE_LIST_HEAD_VARIABLE (gMemoryMap
);
35 #define MAX_MAP_DEPTH 6
38 /// mMapDepth - depth of new descriptor stack
42 /// mMapStack - space to use as temp storage to build new map descriptors
44 MEMORY_MAP mMapStack
[MAX_MAP_DEPTH
];
45 UINTN mFreeMapStack
= 0;
47 /// This list maintain the free memory map list
49 LIST_ENTRY mFreeMemoryMapEntryList
= INITIALIZE_LIST_HEAD_VARIABLE (mFreeMemoryMapEntryList
);
52 Allocates pages from the memory map.
54 @param[in] Type The type of allocation to perform.
55 @param[in] MemoryType The type of memory to turn the allocated pages
57 @param[in] NumberOfPages The number of pages to allocate.
58 @param[out] Memory A pointer to receive the base allocated memory
60 @param[in] AddRegion If this memory is new added region.
61 @param[in] NeedGuard Flag to indicate Guard page is needed
64 @retval EFI_INVALID_PARAMETER Parameters violate checking rules defined in spec.
65 @retval EFI_NOT_FOUND Could not allocate pages match the requirement.
66 @retval EFI_OUT_OF_RESOURCES No enough pages to allocate.
67 @retval EFI_SUCCESS Pages successfully allocated.
71 SmmInternalAllocatePagesEx (
72 IN EFI_ALLOCATE_TYPE Type
,
73 IN EFI_MEMORY_TYPE MemoryType
,
74 IN UINTN NumberOfPages
,
75 OUT EFI_PHYSICAL_ADDRESS
*Memory
,
81 Internal function. Deque a descriptor entry from the mFreeMemoryMapEntryList.
82 If the list is emtry, then allocate a new page to refuel the list.
83 Please Note this algorithm to allocate the memory map descriptor has a property
84 that the memory allocated for memory entries always grows, and will never really be freed.
86 @return The Memory map descriptor dequeued from the mFreeMemoryMapEntryList
90 AllocateMemoryMapEntry (
94 EFI_PHYSICAL_ADDRESS Mem
;
96 MEMORY_MAP
* FreeDescriptorEntries
;
100 //DEBUG((DEBUG_INFO, "AllocateMemoryMapEntry\n"));
102 if (IsListEmpty (&mFreeMemoryMapEntryList
)) {
103 //DEBUG((DEBUG_INFO, "mFreeMemoryMapEntryList is empty\n"));
105 // The list is empty, to allocate one page to refuel the list
107 Status
= SmmInternalAllocatePagesEx (
109 EfiRuntimeServicesData
,
110 EFI_SIZE_TO_PAGES (RUNTIME_PAGE_ALLOCATION_GRANULARITY
),
115 ASSERT_EFI_ERROR (Status
);
116 if(!EFI_ERROR (Status
)) {
117 FreeDescriptorEntries
= (MEMORY_MAP
*)(UINTN
)Mem
;
118 //DEBUG((DEBUG_INFO, "New FreeDescriptorEntries - 0x%x\n", FreeDescriptorEntries));
120 // Enqueue the free memory map entries into the list
122 for (Index
= 0; Index
< RUNTIME_PAGE_ALLOCATION_GRANULARITY
/ sizeof(MEMORY_MAP
); Index
++) {
123 FreeDescriptorEntries
[Index
].Signature
= MEMORY_MAP_SIGNATURE
;
124 InsertTailList (&mFreeMemoryMapEntryList
, &FreeDescriptorEntries
[Index
].Link
);
131 // dequeue the first descriptor from the list
133 Entry
= CR (mFreeMemoryMapEntryList
.ForwardLink
, MEMORY_MAP
, Link
, MEMORY_MAP_SIGNATURE
);
134 RemoveEntryList (&Entry
->Link
);
141 Internal function. Moves any memory descriptors that are on the
142 temporary descriptor stack to heap.
146 CoreFreeMemoryMapStack (
153 // If already freeing the map stack, then return
155 if (mFreeMapStack
!= 0) {
161 // Move the temporary memory descriptor stack into pool
165 while (mMapDepth
!= 0) {
167 // Deque an memory map entry from mFreeMemoryMapEntryList
169 Entry
= AllocateMemoryMapEntry ();
173 // Update to proper entry
177 if (mMapStack
[mMapDepth
].Link
.ForwardLink
!= NULL
) {
179 CopyMem (Entry
, &mMapStack
[mMapDepth
], sizeof (MEMORY_MAP
));
180 Entry
->FromStack
= FALSE
;
183 // Move this entry to general memory
185 InsertTailList (&mMapStack
[mMapDepth
].Link
, &Entry
->Link
);
186 RemoveEntryList (&mMapStack
[mMapDepth
].Link
);
187 mMapStack
[mMapDepth
].Link
.ForwardLink
= NULL
;
195 Insert new entry from memory map.
197 @param[in] Link The old memory map entry to be linked.
198 @param[in] Start The start address of new memory map entry.
199 @param[in] End The end address of new memory map entry.
200 @param[in] Type The type of new memory map entry.
201 @param[in] Next If new entry is inserted to the next of old entry.
202 @param[in] AddRegion If this memory is new added region.
209 IN EFI_MEMORY_TYPE Type
,
216 Entry
= &mMapStack
[mMapDepth
];
218 ASSERT (mMapDepth
< MAX_MAP_DEPTH
);
219 Entry
->FromStack
= TRUE
;
221 Entry
->Signature
= MEMORY_MAP_SIGNATURE
;
223 Entry
->Start
= Start
;
226 InsertHeadList (Link
, &Entry
->Link
);
228 InsertTailList (Link
, &Entry
->Link
);
233 Remove old entry from memory map.
235 @param[in] Entry Memory map entry to be removed.
242 RemoveEntryList (&Entry
->Link
);
243 Entry
->Link
.ForwardLink
= NULL
;
245 if (!Entry
->FromStack
) {
246 InsertTailList (&mFreeMemoryMapEntryList
, &Entry
->Link
);
251 Update SMM memory map entry.
253 @param[in] Type The type of allocation to perform.
254 @param[in] Memory The base of memory address.
255 @param[in] NumberOfPages The number of pages to allocate.
256 @param[in] AddRegion If this memory is new added region.
259 ConvertSmmMemoryMapEntry (
260 IN EFI_MEMORY_TYPE Type
,
261 IN EFI_PHYSICAL_ADDRESS Memory
,
262 IN UINTN NumberOfPages
,
268 MEMORY_MAP
*NextEntry
;
269 LIST_ENTRY
*NextLink
;
270 MEMORY_MAP
*PreviousEntry
;
271 LIST_ENTRY
*PreviousLink
;
272 EFI_PHYSICAL_ADDRESS Start
;
273 EFI_PHYSICAL_ADDRESS End
;
276 End
= Memory
+ EFI_PAGES_TO_SIZE(NumberOfPages
) - 1;
279 // Exclude memory region
281 Link
= gMemoryMap
.ForwardLink
;
282 while (Link
!= &gMemoryMap
) {
283 Entry
= CR (Link
, MEMORY_MAP
, Link
, MEMORY_MAP_SIGNATURE
);
284 Link
= Link
->ForwardLink
;
287 // ---------------------------------------------------
288 // | +----------+ +------+ +------+ +------+ |
289 // ---|gMemoryMep|---|Entry1|---|Entry2|---|Entry3|---
290 // +----------+ ^ +------+ +------+ +------+
296 if (Entry
->Start
> End
) {
297 if ((Entry
->Start
== End
+ 1) && (Entry
->Type
== Type
)) {
298 Entry
->Start
= Start
;
312 if ((Entry
->Start
<= Start
) && (Entry
->End
>= End
)) {
313 if (Entry
->Type
!= Type
) {
314 if (Entry
->Start
< Start
) {
316 // ---------------------------------------------------
317 // | +----------+ +------+ +------+ +------+ |
318 // ---|gMemoryMep|---|Entry1|---|EntryX|---|Entry3|---
319 // +----------+ +------+ ^ +------+ +------+
334 if (Entry
->End
> End
) {
336 // ---------------------------------------------------
337 // | +----------+ +------+ +------+ +------+ |
338 // ---|gMemoryMep|---|Entry1|---|EntryX|---|Entry3|---
339 // +----------+ +------+ +------+ ^ +------+
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
);
378 PreviousLink
= Entry
->Link
.BackLink
;
379 if (PreviousLink
!= &gMemoryMap
) {
380 PreviousEntry
= CR (PreviousLink
, MEMORY_MAP
, Link
, MEMORY_MAP_SIGNATURE
);
382 // ---------------------------------------------------
383 // | +----------+ +-----------------+ +------+ |
384 // ---|gMemoryMep|---|Entry1 EntryX|---|Entry3|---
385 // +----------+ +-----------------+ +------+
387 if ((PreviousEntry
->Type
== Entry
->Type
) && (PreviousEntry
->End
+ 1 == Entry
->Start
)) {
388 PreviousEntry
->End
= Entry
->End
;
389 RemoveOldEntry (Entry
);
398 // ---------------------------------------------------
399 // | +----------+ +------+ +------+ +------+ |
400 // ---|gMemoryMep|---|Entry1|---|Entry2|---|Entry3|---
401 // +----------+ +------+ +------+ +------+ ^
407 Link
= gMemoryMap
.BackLink
;
408 if (Link
!= &gMemoryMap
) {
409 Entry
= CR (Link
, MEMORY_MAP
, Link
, MEMORY_MAP_SIGNATURE
);
410 if ((Entry
->End
+ 1 == Start
) && (Entry
->Type
== Type
)) {
427 Return the count of Smm memory map entry.
429 @return The count of Smm memory map entry.
432 GetSmmMemoryMapEntryCount (
440 Link
= gMemoryMap
.ForwardLink
;
441 while (Link
!= &gMemoryMap
) {
442 Link
= Link
->ForwardLink
;
451 Internal Function. Allocate n pages from given free page node.
453 @param Pages The free page node.
454 @param NumberOfPages Number of pages to be allocated.
455 @param MaxAddress Request to allocate memory below this address.
457 @return Memory address of allocated pages.
461 InternalAllocPagesOnOneNode (
462 IN OUT FREE_PAGE_LIST
*Pages
,
463 IN UINTN NumberOfPages
,
469 FREE_PAGE_LIST
*Node
;
471 Top
= TRUNCATE_TO_PAGES (MaxAddress
+ 1 - (UINTN
)Pages
);
472 if (Top
> Pages
->NumberOfPages
) {
473 Top
= Pages
->NumberOfPages
;
475 Bottom
= Top
- NumberOfPages
;
477 if (Top
< Pages
->NumberOfPages
) {
478 Node
= (FREE_PAGE_LIST
*)((UINTN
)Pages
+ EFI_PAGES_TO_SIZE (Top
));
479 Node
->NumberOfPages
= Pages
->NumberOfPages
- Top
;
480 InsertHeadList (&Pages
->Link
, &Node
->Link
);
484 Pages
->NumberOfPages
= Bottom
;
486 RemoveEntryList (&Pages
->Link
);
489 return (UINTN
)Pages
+ EFI_PAGES_TO_SIZE (Bottom
);
493 Internal Function. Allocate n pages from free page list below MaxAddress.
495 @param FreePageList The free page node.
496 @param NumberOfPages Number of pages to be allocated.
497 @param MaxAddress Request to allocate memory below this address.
499 @return Memory address of allocated pages.
503 InternalAllocMaxAddress (
504 IN OUT LIST_ENTRY
*FreePageList
,
505 IN UINTN NumberOfPages
,
510 FREE_PAGE_LIST
*Pages
;
512 for (Node
= FreePageList
->BackLink
; Node
!= FreePageList
; Node
= Node
->BackLink
) {
513 Pages
= BASE_CR (Node
, FREE_PAGE_LIST
, Link
);
514 if (Pages
->NumberOfPages
>= NumberOfPages
&&
515 (UINTN
)Pages
+ EFI_PAGES_TO_SIZE (NumberOfPages
) - 1 <= MaxAddress
) {
516 return InternalAllocPagesOnOneNode (Pages
, NumberOfPages
, MaxAddress
);
523 Internal Function. Allocate n pages from free page list at given address.
525 @param FreePageList The free page node.
526 @param NumberOfPages Number of pages to be allocated.
527 @param MaxAddress Request to allocate memory below this address.
529 @return Memory address of allocated pages.
533 InternalAllocAddress (
534 IN OUT LIST_ENTRY
*FreePageList
,
535 IN UINTN NumberOfPages
,
541 FREE_PAGE_LIST
*Pages
;
543 if ((Address
& EFI_PAGE_MASK
) != 0) {
547 EndAddress
= Address
+ EFI_PAGES_TO_SIZE (NumberOfPages
);
548 for (Node
= FreePageList
->BackLink
; Node
!= FreePageList
; Node
= Node
->BackLink
) {
549 Pages
= BASE_CR (Node
, FREE_PAGE_LIST
, Link
);
550 if ((UINTN
)Pages
<= Address
) {
551 if ((UINTN
)Pages
+ EFI_PAGES_TO_SIZE (Pages
->NumberOfPages
) < EndAddress
) {
554 return InternalAllocPagesOnOneNode (Pages
, NumberOfPages
, EndAddress
);
561 Allocates pages from the memory map.
563 @param[in] Type The type of allocation to perform.
564 @param[in] MemoryType The type of memory to turn the allocated pages
566 @param[in] NumberOfPages The number of pages to allocate.
567 @param[out] Memory A pointer to receive the base allocated memory
569 @param[in] AddRegion If this memory is new added region.
570 @param[in] NeedGuard Flag to indicate Guard page is needed
573 @retval EFI_INVALID_PARAMETER Parameters violate checking rules defined in spec.
574 @retval EFI_NOT_FOUND Could not allocate pages match the requirement.
575 @retval EFI_OUT_OF_RESOURCES No enough pages to allocate.
576 @retval EFI_SUCCESS Pages successfully allocated.
580 SmmInternalAllocatePagesEx (
581 IN EFI_ALLOCATE_TYPE Type
,
582 IN EFI_MEMORY_TYPE MemoryType
,
583 IN UINTN NumberOfPages
,
584 OUT EFI_PHYSICAL_ADDRESS
*Memory
,
585 IN BOOLEAN AddRegion
,
589 UINTN RequestedAddress
;
591 if (MemoryType
!= EfiRuntimeServicesCode
&&
592 MemoryType
!= EfiRuntimeServicesData
) {
593 return EFI_INVALID_PARAMETER
;
596 if (NumberOfPages
> TRUNCATE_TO_PAGES ((UINTN
)-1) + 1) {
597 return EFI_OUT_OF_RESOURCES
;
601 // We don't track memory type in SMM
603 RequestedAddress
= (UINTN
)*Memory
;
605 case AllocateAnyPages
:
606 RequestedAddress
= (UINTN
)(-1);
607 case AllocateMaxAddress
:
609 *Memory
= InternalAllocMaxAddressWithGuard (
615 if (*Memory
== (UINTN
)-1) {
616 return EFI_OUT_OF_RESOURCES
;
618 ASSERT (VerifyMemoryGuard (*Memory
, NumberOfPages
) == TRUE
);
623 *Memory
= InternalAllocMaxAddress (
628 if (*Memory
== (UINTN
)-1) {
629 return EFI_OUT_OF_RESOURCES
;
632 case AllocateAddress
:
633 *Memory
= InternalAllocAddress (
638 if (*Memory
!= RequestedAddress
) {
639 return EFI_NOT_FOUND
;
643 return EFI_INVALID_PARAMETER
;
647 // Update SmmMemoryMap here.
649 ConvertSmmMemoryMapEntry (MemoryType
, *Memory
, NumberOfPages
, AddRegion
);
651 CoreFreeMemoryMapStack();
658 Allocates pages from the memory map.
660 @param[in] Type The type of allocation to perform.
661 @param[in] MemoryType The type of memory to turn the allocated pages
663 @param[in] NumberOfPages The number of pages to allocate.
664 @param[out] Memory A pointer to receive the base allocated memory
666 @param[in] NeedGuard Flag to indicate Guard page is needed
669 @retval EFI_INVALID_PARAMETER Parameters violate checking rules defined in spec.
670 @retval EFI_NOT_FOUND Could not allocate pages match the requirement.
671 @retval EFI_OUT_OF_RESOURCES No enough pages to allocate.
672 @retval EFI_SUCCESS Pages successfully allocated.
677 SmmInternalAllocatePages (
678 IN EFI_ALLOCATE_TYPE Type
,
679 IN EFI_MEMORY_TYPE MemoryType
,
680 IN UINTN NumberOfPages
,
681 OUT EFI_PHYSICAL_ADDRESS
*Memory
,
685 return SmmInternalAllocatePagesEx (Type
, MemoryType
, NumberOfPages
, Memory
,
690 Allocates pages from the memory map.
692 @param Type The type of allocation to perform.
693 @param MemoryType The type of memory to turn the allocated pages
695 @param NumberOfPages The number of pages to allocate.
696 @param Memory A pointer to receive the base allocated memory
699 @retval EFI_INVALID_PARAMETER Parameters violate checking rules defined in spec.
700 @retval EFI_NOT_FOUND Could not allocate pages match the requirement.
701 @retval EFI_OUT_OF_RESOURCES No enough pages to allocate.
702 @retval EFI_SUCCESS Pages successfully allocated.
708 IN EFI_ALLOCATE_TYPE Type
,
709 IN EFI_MEMORY_TYPE MemoryType
,
710 IN UINTN NumberOfPages
,
711 OUT EFI_PHYSICAL_ADDRESS
*Memory
717 NeedGuard
= IsPageTypeToGuard (MemoryType
, Type
);
718 Status
= SmmInternalAllocatePages (Type
, MemoryType
, NumberOfPages
, Memory
,
720 if (!EFI_ERROR (Status
)) {
721 SmmCoreUpdateProfile (
722 (EFI_PHYSICAL_ADDRESS
) (UINTN
) RETURN_ADDRESS (0),
723 MemoryProfileActionAllocatePages
,
725 EFI_PAGES_TO_SIZE (NumberOfPages
),
726 (VOID
*) (UINTN
) *Memory
,
734 Internal Function. Merge two adjacent nodes.
736 @param First The first of two nodes to merge.
738 @return Pointer to node after merge (if success) or pointer to next node (if fail).
743 IN FREE_PAGE_LIST
*First
746 FREE_PAGE_LIST
*Next
;
748 Next
= BASE_CR (First
->Link
.ForwardLink
, FREE_PAGE_LIST
, Link
);
750 TRUNCATE_TO_PAGES ((UINTN
)Next
- (UINTN
)First
) >= First
->NumberOfPages
);
752 if (TRUNCATE_TO_PAGES ((UINTN
)Next
- (UINTN
)First
) == First
->NumberOfPages
) {
753 First
->NumberOfPages
+= Next
->NumberOfPages
;
754 RemoveEntryList (&Next
->Link
);
761 Frees previous allocated pages.
763 @param[in] Memory Base address of memory being freed.
764 @param[in] NumberOfPages The number of pages to free.
765 @param[in] AddRegion If this memory is new added region.
767 @retval EFI_NOT_FOUND Could not find the entry that covers the range.
768 @retval EFI_INVALID_PARAMETER Address not aligned, Address is zero or NumberOfPages is zero.
769 @return EFI_SUCCESS Pages successfully freed.
773 SmmInternalFreePagesEx (
774 IN EFI_PHYSICAL_ADDRESS Memory
,
775 IN UINTN NumberOfPages
,
780 FREE_PAGE_LIST
*Pages
;
782 if (((Memory
& EFI_PAGE_MASK
) != 0) || (Memory
== 0) || (NumberOfPages
== 0)) {
783 return EFI_INVALID_PARAMETER
;
787 Node
= mSmmMemoryMap
.ForwardLink
;
788 while (Node
!= &mSmmMemoryMap
) {
789 Pages
= BASE_CR (Node
, FREE_PAGE_LIST
, Link
);
790 if (Memory
< (UINTN
)Pages
) {
793 Node
= Node
->ForwardLink
;
796 if (Node
!= &mSmmMemoryMap
&&
797 Memory
+ EFI_PAGES_TO_SIZE (NumberOfPages
) > (UINTN
)Pages
) {
798 return EFI_INVALID_PARAMETER
;
801 if (Node
->BackLink
!= &mSmmMemoryMap
) {
802 Pages
= BASE_CR (Node
->BackLink
, FREE_PAGE_LIST
, Link
);
803 if ((UINTN
)Pages
+ EFI_PAGES_TO_SIZE (Pages
->NumberOfPages
) > Memory
) {
804 return EFI_INVALID_PARAMETER
;
808 Pages
= (FREE_PAGE_LIST
*)(UINTN
)Memory
;
809 Pages
->NumberOfPages
= NumberOfPages
;
810 InsertTailList (Node
, &Pages
->Link
);
812 if (Pages
->Link
.BackLink
!= &mSmmMemoryMap
) {
813 Pages
= InternalMergeNodes (
814 BASE_CR (Pages
->Link
.BackLink
, FREE_PAGE_LIST
, Link
)
818 if (Node
!= &mSmmMemoryMap
) {
819 InternalMergeNodes (Pages
);
823 // Update SmmMemoryMap here.
825 ConvertSmmMemoryMapEntry (EfiConventionalMemory
, Memory
, NumberOfPages
, AddRegion
);
827 CoreFreeMemoryMapStack();
834 Frees previous allocated pages.
836 @param[in] Memory Base address of memory being freed.
837 @param[in] NumberOfPages The number of pages to free.
838 @param[in] IsGuarded Is the memory to free guarded or not.
840 @retval EFI_NOT_FOUND Could not find the entry that covers the range.
841 @retval EFI_INVALID_PARAMETER Address not aligned, Address is zero or NumberOfPages is zero.
842 @return EFI_SUCCESS Pages successfully freed.
847 SmmInternalFreePages (
848 IN EFI_PHYSICAL_ADDRESS Memory
,
849 IN UINTN NumberOfPages
,
854 return SmmInternalFreePagesExWithGuard (Memory
, NumberOfPages
, FALSE
);
856 return SmmInternalFreePagesEx (Memory
, NumberOfPages
, FALSE
);
860 Check whether the input range is in memory map.
862 @param Memory Base address of memory being inputed.
863 @param NumberOfPages The number of pages.
865 @retval TRUE In memory map.
866 @retval FALSE Not in memory map.
871 IN EFI_PHYSICAL_ADDRESS Memory
,
872 IN UINTN NumberOfPages
877 EFI_PHYSICAL_ADDRESS Last
;
879 Last
= Memory
+ EFI_PAGES_TO_SIZE (NumberOfPages
) - 1;
881 Link
= gMemoryMap
.ForwardLink
;
882 while (Link
!= &gMemoryMap
) {
883 Entry
= CR (Link
, MEMORY_MAP
, Link
, MEMORY_MAP_SIGNATURE
);
884 Link
= Link
->ForwardLink
;
886 if ((Entry
->Start
<= Memory
) && (Entry
->End
>= Last
)) {
895 Frees previous allocated pages.
897 @param Memory Base address of memory being freed.
898 @param NumberOfPages The number of pages to free.
900 @retval EFI_NOT_FOUND Could not find the entry that covers the range.
901 @retval EFI_INVALID_PARAMETER Address not aligned, Address is zero or NumberOfPages is zero.
902 @return EFI_SUCCESS Pages successfully freed.
908 IN EFI_PHYSICAL_ADDRESS Memory
,
909 IN UINTN NumberOfPages
915 if (!InMemMap(Memory
, NumberOfPages
)) {
916 return EFI_NOT_FOUND
;
919 IsGuarded
= IsHeapGuardEnabled () && IsMemoryGuarded (Memory
);
920 Status
= SmmInternalFreePages (Memory
, NumberOfPages
, IsGuarded
);
921 if (!EFI_ERROR (Status
)) {
922 SmmCoreUpdateProfile (
923 (EFI_PHYSICAL_ADDRESS
) (UINTN
) RETURN_ADDRESS (0),
924 MemoryProfileActionFreePages
,
926 EFI_PAGES_TO_SIZE (NumberOfPages
),
927 (VOID
*) (UINTN
) Memory
,
935 Add free SMRAM region for use by memory service.
937 @param MemBase Base address of memory region.
938 @param MemLength Length of the memory region.
939 @param Type Memory type.
940 @param Attributes Memory region state.
945 IN EFI_PHYSICAL_ADDRESS MemBase
,
947 IN EFI_MEMORY_TYPE Type
,
951 UINTN AlignedMemBase
;
954 // Add EfiRuntimeServicesData for memory regions that is already allocated, needs testing, or needs ECC initialization
956 if ((Attributes
& (EFI_ALLOCATED
| EFI_NEEDS_TESTING
| EFI_NEEDS_ECC_INITIALIZATION
)) != 0) {
957 Type
= EfiRuntimeServicesData
;
959 Type
= EfiConventionalMemory
;
962 DEBUG ((DEBUG_INFO
, "SmmAddMemoryRegion\n"));
963 DEBUG ((DEBUG_INFO
, " MemBase - 0x%lx\n", MemBase
));
964 DEBUG ((DEBUG_INFO
, " MemLength - 0x%lx\n", MemLength
));
965 DEBUG ((DEBUG_INFO
, " Type - 0x%x\n", Type
));
966 DEBUG ((DEBUG_INFO
, " Attributes - 0x%lx\n", Attributes
));
969 // Align range on an EFI_PAGE_SIZE boundary
971 AlignedMemBase
= (UINTN
)(MemBase
+ EFI_PAGE_MASK
) & ~EFI_PAGE_MASK
;
972 MemLength
-= AlignedMemBase
- MemBase
;
973 if (Type
== EfiConventionalMemory
) {
974 SmmInternalFreePagesEx (AlignedMemBase
, TRUNCATE_TO_PAGES ((UINTN
)MemLength
), TRUE
);
976 ConvertSmmMemoryMapEntry (EfiRuntimeServicesData
, AlignedMemBase
, TRUNCATE_TO_PAGES ((UINTN
)MemLength
), TRUE
);
979 CoreFreeMemoryMapStack ();
983 This function returns a copy of the current memory map. The map is an array of
984 memory descriptors, each of which describes a contiguous block of memory.
986 @param[in, out] MemoryMapSize A pointer to the size, in bytes, of the
987 MemoryMap buffer. On input, this is the size of
988 the buffer allocated by the caller. On output,
989 it is the size of the buffer returned by the
990 firmware if the buffer was large enough, or the
991 size of the buffer needed to contain the map if
992 the buffer was too small.
993 @param[in, out] MemoryMap A pointer to the buffer in which firmware places
994 the current memory map.
995 @param[out] MapKey A pointer to the location in which firmware
996 returns the key for the current memory map.
997 @param[out] DescriptorSize A pointer to the location in which firmware
998 returns the size, in bytes, of an individual
999 EFI_MEMORY_DESCRIPTOR.
1000 @param[out] DescriptorVersion A pointer to the location in which firmware
1001 returns the version number associated with the
1002 EFI_MEMORY_DESCRIPTOR.
1004 @retval EFI_SUCCESS The memory map was returned in the MemoryMap
1006 @retval EFI_BUFFER_TOO_SMALL The MemoryMap buffer was too small. The current
1007 buffer size needed to hold the memory map is
1008 returned in MemoryMapSize.
1009 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
1014 SmmCoreGetMemoryMap (
1015 IN OUT UINTN
*MemoryMapSize
,
1016 IN OUT EFI_MEMORY_DESCRIPTOR
*MemoryMap
,
1018 OUT UINTN
*DescriptorSize
,
1019 OUT UINT32
*DescriptorVersion
1028 Size
= sizeof (EFI_MEMORY_DESCRIPTOR
);
1031 // Make sure Size != sizeof(EFI_MEMORY_DESCRIPTOR). This will
1032 // prevent people from having pointer math bugs in their code.
1033 // now you have to use *DescriptorSize to make things work.
1035 Size
+= sizeof(UINT64
) - (Size
% sizeof (UINT64
));
1037 if (DescriptorSize
!= NULL
) {
1038 *DescriptorSize
= Size
;
1041 if (DescriptorVersion
!= NULL
) {
1042 *DescriptorVersion
= EFI_MEMORY_DESCRIPTOR_VERSION
;
1045 Count
= GetSmmMemoryMapEntryCount ();
1046 BufferSize
= Size
* Count
;
1047 if (*MemoryMapSize
< BufferSize
) {
1048 *MemoryMapSize
= BufferSize
;
1049 return EFI_BUFFER_TOO_SMALL
;
1052 *MemoryMapSize
= BufferSize
;
1053 if (MemoryMap
== NULL
) {
1054 return EFI_INVALID_PARAMETER
;
1057 ZeroMem (MemoryMap
, BufferSize
);
1058 Link
= gMemoryMap
.ForwardLink
;
1059 while (Link
!= &gMemoryMap
) {
1060 Entry
= CR (Link
, MEMORY_MAP
, Link
, MEMORY_MAP_SIGNATURE
);
1061 Link
= Link
->ForwardLink
;
1063 MemoryMap
->Type
= Entry
->Type
;
1064 MemoryMap
->PhysicalStart
= Entry
->Start
;
1065 MemoryMap
->NumberOfPages
= RShiftU64 (Entry
->End
- Entry
->Start
+ 1, EFI_PAGE_SHIFT
);
1067 MemoryMap
= NEXT_MEMORY_DESCRIPTOR (MemoryMap
, Size
);