2 SMM Memory page management functions.
4 Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials are licensed and made available
6 under the terms and conditions of the BSD License which accompanies this
7 distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 #include "PiSmmCore.h"
16 #include <Library/SmmServicesTableLib.h>
18 #define TRUNCATE_TO_PAGES(a) ((a) >> EFI_PAGE_SHIFT)
20 LIST_ENTRY mSmmMemoryMap
= INITIALIZE_LIST_HEAD_VARIABLE (mSmmMemoryMap
);
26 #define MEMORY_MAP_SIGNATURE SIGNATURE_32('m','m','a','p')
38 LIST_ENTRY gMemoryMap
= INITIALIZE_LIST_HEAD_VARIABLE (gMemoryMap
);
41 #define MAX_MAP_DEPTH 6
44 /// mMapDepth - depth of new descriptor stack
48 /// mMapStack - space to use as temp storage to build new map descriptors
50 MEMORY_MAP mMapStack
[MAX_MAP_DEPTH
];
51 UINTN mFreeMapStack
= 0;
53 /// This list maintain the free memory map list
55 LIST_ENTRY mFreeMemoryMapEntryList
= INITIALIZE_LIST_HEAD_VARIABLE (mFreeMemoryMapEntryList
);
58 Allocates pages from the memory map.
60 @param[in] Type The type of allocation to perform.
61 @param[in] MemoryType The type of memory to turn the allocated pages
63 @param[in] NumberOfPages The number of pages to allocate.
64 @param[out] Memory A pointer to receive the base allocated memory
66 @param[in] AddRegion If this memory is new added region.
68 @retval EFI_INVALID_PARAMETER Parameters violate checking rules defined in spec.
69 @retval EFI_NOT_FOUND Could not allocate pages match the requirement.
70 @retval EFI_OUT_OF_RESOURCES No enough pages to allocate.
71 @retval EFI_SUCCESS Pages successfully allocated.
75 SmmInternalAllocatePagesEx (
76 IN EFI_ALLOCATE_TYPE Type
,
77 IN EFI_MEMORY_TYPE MemoryType
,
78 IN UINTN NumberOfPages
,
79 OUT EFI_PHYSICAL_ADDRESS
*Memory
,
84 Internal function. Deque a descriptor entry from the mFreeMemoryMapEntryList.
85 If the list is emtry, then allocate a new page to refuel the list.
86 Please Note this algorithm to allocate the memory map descriptor has a property
87 that the memory allocated for memory entries always grows, and will never really be freed.
89 @return The Memory map descriptor dequed from the mFreeMemoryMapEntryList
93 AllocateMemoryMapEntry (
97 EFI_PHYSICAL_ADDRESS Mem
;
99 MEMORY_MAP
* FreeDescriptorEntries
;
103 //DEBUG((DEBUG_INFO, "AllocateMemoryMapEntry\n"));
105 if (IsListEmpty (&mFreeMemoryMapEntryList
)) {
106 //DEBUG((DEBUG_INFO, "mFreeMemoryMapEntryList is empty\n"));
108 // The list is empty, to allocate one page to refuel the list
110 Status
= SmmInternalAllocatePagesEx (
112 EfiRuntimeServicesData
,
113 EFI_SIZE_TO_PAGES(DEFAULT_PAGE_ALLOCATION
),
117 ASSERT_EFI_ERROR (Status
);
118 if(!EFI_ERROR (Status
)) {
119 FreeDescriptorEntries
= (MEMORY_MAP
*)(UINTN
)Mem
;
120 //DEBUG((DEBUG_INFO, "New FreeDescriptorEntries - 0x%x\n", FreeDescriptorEntries));
122 // Enque the free memmory map entries into the list
124 for (Index
= 0; Index
< DEFAULT_PAGE_ALLOCATION
/ sizeof(MEMORY_MAP
); Index
++) {
125 FreeDescriptorEntries
[Index
].Signature
= MEMORY_MAP_SIGNATURE
;
126 InsertTailList (&mFreeMemoryMapEntryList
, &FreeDescriptorEntries
[Index
].Link
);
133 // dequeue the first descriptor from the list
135 Entry
= CR (mFreeMemoryMapEntryList
.ForwardLink
, MEMORY_MAP
, Link
, MEMORY_MAP_SIGNATURE
);
136 RemoveEntryList (&Entry
->Link
);
143 Internal function. Moves any memory descriptors that are on the
144 temporary descriptor stack to heap.
148 CoreFreeMemoryMapStack (
155 // If already freeing the map stack, then return
157 if (mFreeMapStack
!= 0) {
163 // Move the temporary memory descriptor stack into pool
167 while (mMapDepth
!= 0) {
169 // Deque an memory map entry from mFreeMemoryMapEntryList
171 Entry
= AllocateMemoryMapEntry ();
175 // Update to proper entry
179 if (mMapStack
[mMapDepth
].Link
.ForwardLink
!= NULL
) {
181 CopyMem (Entry
, &mMapStack
[mMapDepth
], sizeof (MEMORY_MAP
));
182 Entry
->FromStack
= FALSE
;
185 // Move this entry to general memory
187 InsertTailList (&mMapStack
[mMapDepth
].Link
, &Entry
->Link
);
188 RemoveEntryList (&mMapStack
[mMapDepth
].Link
);
189 mMapStack
[mMapDepth
].Link
.ForwardLink
= NULL
;
197 Insert new entry from memory map.
199 @param[in] Link The old memory map entry to be linked.
200 @param[in] Start The start address of new memory map entry.
201 @param[in] End The end address of new memory map entry.
202 @param[in] Type The type of new memory map entry.
203 @param[in] Next If new entry is inserted to the next of old entry.
204 @param[in] AddRegion If this memory is new added region.
211 IN EFI_MEMORY_TYPE Type
,
218 Entry
= &mMapStack
[mMapDepth
];
220 ASSERT (mMapDepth
< MAX_MAP_DEPTH
);
221 Entry
->FromStack
= TRUE
;
223 Entry
->Signature
= MEMORY_MAP_SIGNATURE
;
225 Entry
->Start
= Start
;
228 InsertHeadList (Link
, &Entry
->Link
);
230 InsertTailList (Link
, &Entry
->Link
);
235 Remove old entry from memory map.
237 @param[in] Entry Memory map entry to be removed.
244 RemoveEntryList (&Entry
->Link
);
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
;
449 Dump Smm memory map entry.
452 DumpSmmMemoryMapEntry (
458 EFI_PHYSICAL_ADDRESS Last
;
461 DEBUG ((DEBUG_INFO
, "DumpSmmMemoryMapEntry:\n"));
462 Link
= gMemoryMap
.ForwardLink
;
463 while (Link
!= &gMemoryMap
) {
464 Entry
= CR (Link
, MEMORY_MAP
, Link
, MEMORY_MAP_SIGNATURE
);
465 Link
= Link
->ForwardLink
;
467 if ((Last
!= 0) && (Last
!= (UINT64
)-1)) {
468 if (Last
+ 1 != Entry
->Start
) {
473 } else if (Last
== 0) {
477 DEBUG ((DEBUG_INFO
, "Entry (Link - 0x%x)\n", &Entry
->Link
));
478 DEBUG ((DEBUG_INFO
, " Signature - 0x%x\n", Entry
->Signature
));
479 DEBUG ((DEBUG_INFO
, " Link.ForwardLink - 0x%x\n", Entry
->Link
.ForwardLink
));
480 DEBUG ((DEBUG_INFO
, " Link.BackLink - 0x%x\n", Entry
->Link
.BackLink
));
481 DEBUG ((DEBUG_INFO
, " Type - 0x%x\n", Entry
->Type
));
482 DEBUG ((DEBUG_INFO
, " Start - 0x%016lx\n", Entry
->Start
));
483 DEBUG ((DEBUG_INFO
, " End - 0x%016lx\n", Entry
->End
));
486 ASSERT (Last
!= (UINT64
)-1);
498 FREE_PAGE_LIST
*Pages
;
500 DEBUG ((DEBUG_INFO
, "DumpSmmMemoryMap\n"));
503 Node
= mSmmMemoryMap
.ForwardLink
;
504 while (Node
!= &mSmmMemoryMap
) {
505 Pages
= BASE_CR (Node
, FREE_PAGE_LIST
, Link
);
506 DEBUG ((DEBUG_INFO
, "Pages - 0x%x\n", Pages
));
507 DEBUG ((DEBUG_INFO
, "Pages->NumberOfPages - 0x%x\n", Pages
->NumberOfPages
));
508 Node
= Node
->ForwardLink
;
513 Check if a Smm base~length is in Smm memory map.
515 @param[in] Base The base address of Smm memory to be checked.
516 @param[in] Length THe length of Smm memory to be checked.
518 @retval TRUE Smm base~length is in smm memory map.
519 @retval FALSE Smm base~length is in smm memory map.
522 SmmMemoryMapConsistencyCheckRange (
523 IN EFI_PHYSICAL_ADDRESS Base
,
532 Link
= gMemoryMap
.ForwardLink
;
533 while (Link
!= &gMemoryMap
) {
534 Entry
= CR (Link
, MEMORY_MAP
, Link
, MEMORY_MAP_SIGNATURE
);
535 Link
= Link
->ForwardLink
;
537 if (Entry
->Type
!= EfiConventionalMemory
) {
540 if (Entry
->Start
== Base
&& Entry
->End
== Base
+ Length
- 1) {
550 Check the consistency of Smm memory map.
553 SmmMemoryMapConsistencyCheck (
558 FREE_PAGE_LIST
*Pages
;
562 Node
= mSmmMemoryMap
.ForwardLink
;
563 while (Node
!= &mSmmMemoryMap
) {
564 Pages
= BASE_CR (Node
, FREE_PAGE_LIST
, Link
);
565 Result
= SmmMemoryMapConsistencyCheckRange ((EFI_PHYSICAL_ADDRESS
)(UINTN
)Pages
, (UINTN
)EFI_PAGES_TO_SIZE(Pages
->NumberOfPages
));
567 Node
= Node
->ForwardLink
;
572 Internal Function. Allocate n pages from given free page node.
574 @param Pages The free page node.
575 @param NumberOfPages Number of pages to be allocated.
576 @param MaxAddress Request to allocate memory below this address.
578 @return Memory address of allocated pages.
582 InternalAllocPagesOnOneNode (
583 IN OUT FREE_PAGE_LIST
*Pages
,
584 IN UINTN NumberOfPages
,
590 FREE_PAGE_LIST
*Node
;
592 Top
= TRUNCATE_TO_PAGES (MaxAddress
+ 1 - (UINTN
)Pages
);
593 if (Top
> Pages
->NumberOfPages
) {
594 Top
= Pages
->NumberOfPages
;
596 Bottom
= Top
- NumberOfPages
;
598 if (Top
< Pages
->NumberOfPages
) {
599 Node
= (FREE_PAGE_LIST
*)((UINTN
)Pages
+ EFI_PAGES_TO_SIZE (Top
));
600 Node
->NumberOfPages
= Pages
->NumberOfPages
- Top
;
601 InsertHeadList (&Pages
->Link
, &Node
->Link
);
605 Pages
->NumberOfPages
= Bottom
;
607 RemoveEntryList (&Pages
->Link
);
610 return (UINTN
)Pages
+ EFI_PAGES_TO_SIZE (Bottom
);
614 Internal Function. Allocate n pages from free page list below MaxAddress.
616 @param FreePageList The free page node.
617 @param NumberOfPages Number of pages to be allocated.
618 @param MaxAddress Request to allocate memory below this address.
620 @return Memory address of allocated pages.
624 InternalAllocMaxAddress (
625 IN OUT LIST_ENTRY
*FreePageList
,
626 IN UINTN NumberOfPages
,
631 FREE_PAGE_LIST
*Pages
;
633 for (Node
= FreePageList
->BackLink
; Node
!= FreePageList
; Node
= Node
->BackLink
) {
634 Pages
= BASE_CR (Node
, FREE_PAGE_LIST
, Link
);
635 if (Pages
->NumberOfPages
>= NumberOfPages
&&
636 (UINTN
)Pages
+ EFI_PAGES_TO_SIZE (NumberOfPages
) - 1 <= MaxAddress
) {
637 return InternalAllocPagesOnOneNode (Pages
, NumberOfPages
, MaxAddress
);
644 Internal Function. Allocate n pages from free page list at given address.
646 @param FreePageList The free page node.
647 @param NumberOfPages Number of pages to be allocated.
648 @param MaxAddress Request to allocate memory below this address.
650 @return Memory address of allocated pages.
654 InternalAllocAddress (
655 IN OUT LIST_ENTRY
*FreePageList
,
656 IN UINTN NumberOfPages
,
662 FREE_PAGE_LIST
*Pages
;
664 if ((Address
& EFI_PAGE_MASK
) != 0) {
668 EndAddress
= Address
+ EFI_PAGES_TO_SIZE (NumberOfPages
);
669 for (Node
= FreePageList
->BackLink
; Node
!= FreePageList
; Node
= Node
->BackLink
) {
670 Pages
= BASE_CR (Node
, FREE_PAGE_LIST
, Link
);
671 if ((UINTN
)Pages
<= Address
) {
672 if ((UINTN
)Pages
+ EFI_PAGES_TO_SIZE (Pages
->NumberOfPages
) < EndAddress
) {
675 return InternalAllocPagesOnOneNode (Pages
, NumberOfPages
, EndAddress
);
682 Allocates pages from the memory map.
684 @param[in] Type The type of allocation to perform.
685 @param[in] MemoryType The type of memory to turn the allocated pages
687 @param[in] NumberOfPages The number of pages to allocate.
688 @param[out] Memory A pointer to receive the base allocated memory
690 @param[in] AddRegion If this memory is new added region.
692 @retval EFI_INVALID_PARAMETER Parameters violate checking rules defined in spec.
693 @retval EFI_NOT_FOUND Could not allocate pages match the requirement.
694 @retval EFI_OUT_OF_RESOURCES No enough pages to allocate.
695 @retval EFI_SUCCESS Pages successfully allocated.
699 SmmInternalAllocatePagesEx (
700 IN EFI_ALLOCATE_TYPE Type
,
701 IN EFI_MEMORY_TYPE MemoryType
,
702 IN UINTN NumberOfPages
,
703 OUT EFI_PHYSICAL_ADDRESS
*Memory
,
707 UINTN RequestedAddress
;
709 if (MemoryType
!= EfiRuntimeServicesCode
&&
710 MemoryType
!= EfiRuntimeServicesData
) {
711 return EFI_INVALID_PARAMETER
;
714 if (NumberOfPages
> TRUNCATE_TO_PAGES ((UINTN
)-1) + 1) {
715 return EFI_OUT_OF_RESOURCES
;
719 // We don't track memory type in SMM
721 RequestedAddress
= (UINTN
)*Memory
;
723 case AllocateAnyPages
:
724 RequestedAddress
= (UINTN
)(-1);
725 case AllocateMaxAddress
:
726 *Memory
= InternalAllocMaxAddress (
731 if (*Memory
== (UINTN
)-1) {
732 return EFI_OUT_OF_RESOURCES
;
735 case AllocateAddress
:
736 *Memory
= InternalAllocAddress (
741 if (*Memory
!= RequestedAddress
) {
742 return EFI_NOT_FOUND
;
746 return EFI_INVALID_PARAMETER
;
750 // Update SmmMemoryMap here.
752 ConvertSmmMemoryMapEntry (MemoryType
, *Memory
, NumberOfPages
, AddRegion
);
754 CoreFreeMemoryMapStack();
761 Allocates pages from the memory map.
763 @param[in] Type The type of allocation to perform.
764 @param[in] MemoryType The type of memory to turn the allocated pages
766 @param[in] NumberOfPages The number of pages to allocate.
767 @param[out] Memory A pointer to receive the base allocated memory
770 @retval EFI_INVALID_PARAMETER Parameters violate checking rules defined in spec.
771 @retval EFI_NOT_FOUND Could not allocate pages match the requirement.
772 @retval EFI_OUT_OF_RESOURCES No enough pages to allocate.
773 @retval EFI_SUCCESS Pages successfully allocated.
778 SmmInternalAllocatePages (
779 IN EFI_ALLOCATE_TYPE Type
,
780 IN EFI_MEMORY_TYPE MemoryType
,
781 IN UINTN NumberOfPages
,
782 OUT EFI_PHYSICAL_ADDRESS
*Memory
785 return SmmInternalAllocatePagesEx (Type
, MemoryType
, NumberOfPages
, Memory
, FALSE
);
789 Allocates pages from the memory map.
791 @param Type The type of allocation to perform.
792 @param MemoryType The type of memory to turn the allocated pages
794 @param NumberOfPages The number of pages to allocate.
795 @param Memory A pointer to receive the base allocated memory
798 @retval EFI_INVALID_PARAMETER Parameters violate checking rules defined in spec.
799 @retval EFI_NOT_FOUND Could not allocate pages match the requirement.
800 @retval EFI_OUT_OF_RESOURCES No enough pages to allocate.
801 @retval EFI_SUCCESS Pages successfully allocated.
807 IN EFI_ALLOCATE_TYPE Type
,
808 IN EFI_MEMORY_TYPE MemoryType
,
809 IN UINTN NumberOfPages
,
810 OUT EFI_PHYSICAL_ADDRESS
*Memory
815 Status
= SmmInternalAllocatePages (Type
, MemoryType
, NumberOfPages
, Memory
);
816 if (!EFI_ERROR (Status
)) {
817 SmmCoreUpdateProfile (
818 (EFI_PHYSICAL_ADDRESS
) (UINTN
) RETURN_ADDRESS (0),
819 MemoryProfileActionAllocatePages
,
821 EFI_PAGES_TO_SIZE (NumberOfPages
),
822 (VOID
*) (UINTN
) *Memory
,
830 Internal Function. Merge two adjacent nodes.
832 @param First The first of two nodes to merge.
834 @return Pointer to node after merge (if success) or pointer to next node (if fail).
839 IN FREE_PAGE_LIST
*First
842 FREE_PAGE_LIST
*Next
;
844 Next
= BASE_CR (First
->Link
.ForwardLink
, FREE_PAGE_LIST
, Link
);
846 TRUNCATE_TO_PAGES ((UINTN
)Next
- (UINTN
)First
) >= First
->NumberOfPages
);
848 if (TRUNCATE_TO_PAGES ((UINTN
)Next
- (UINTN
)First
) == First
->NumberOfPages
) {
849 First
->NumberOfPages
+= Next
->NumberOfPages
;
850 RemoveEntryList (&Next
->Link
);
857 Frees previous allocated pages.
859 @param[in] Memory Base address of memory being freed.
860 @param[in] NumberOfPages The number of pages to free.
861 @param[in] AddRegion If this memory is new added region.
863 @retval EFI_NOT_FOUND Could not find the entry that covers the range.
864 @retval EFI_INVALID_PARAMETER Address not aligned, Address is zero or NumberOfPages is zero.
865 @return EFI_SUCCESS Pages successfully freed.
869 SmmInternalFreePagesEx (
870 IN EFI_PHYSICAL_ADDRESS Memory
,
871 IN UINTN NumberOfPages
,
876 FREE_PAGE_LIST
*Pages
;
878 if (((Memory
& EFI_PAGE_MASK
) != 0) || (Memory
== 0) || (NumberOfPages
== 0)) {
879 return EFI_INVALID_PARAMETER
;
883 Node
= mSmmMemoryMap
.ForwardLink
;
884 while (Node
!= &mSmmMemoryMap
) {
885 Pages
= BASE_CR (Node
, FREE_PAGE_LIST
, Link
);
886 if (Memory
< (UINTN
)Pages
) {
889 Node
= Node
->ForwardLink
;
892 if (Node
!= &mSmmMemoryMap
&&
893 Memory
+ EFI_PAGES_TO_SIZE (NumberOfPages
) > (UINTN
)Pages
) {
894 return EFI_INVALID_PARAMETER
;
897 if (Node
->BackLink
!= &mSmmMemoryMap
) {
898 Pages
= BASE_CR (Node
->BackLink
, FREE_PAGE_LIST
, Link
);
899 if ((UINTN
)Pages
+ EFI_PAGES_TO_SIZE (Pages
->NumberOfPages
) > Memory
) {
900 return EFI_INVALID_PARAMETER
;
904 Pages
= (FREE_PAGE_LIST
*)(UINTN
)Memory
;
905 Pages
->NumberOfPages
= NumberOfPages
;
906 InsertTailList (Node
, &Pages
->Link
);
908 if (Pages
->Link
.BackLink
!= &mSmmMemoryMap
) {
909 Pages
= InternalMergeNodes (
910 BASE_CR (Pages
->Link
.BackLink
, FREE_PAGE_LIST
, Link
)
914 if (Node
!= &mSmmMemoryMap
) {
915 InternalMergeNodes (Pages
);
919 // Update SmmMemoryMap here.
921 ConvertSmmMemoryMapEntry (EfiConventionalMemory
, Memory
, NumberOfPages
, AddRegion
);
923 CoreFreeMemoryMapStack();
930 Frees previous allocated pages.
932 @param[in] Memory Base address of memory being freed.
933 @param[in] NumberOfPages The number of pages to free.
935 @retval EFI_NOT_FOUND Could not find the entry that covers the range.
936 @retval EFI_INVALID_PARAMETER Address not aligned, Address is zero or NumberOfPages is zero.
937 @return EFI_SUCCESS Pages successfully freed.
942 SmmInternalFreePages (
943 IN EFI_PHYSICAL_ADDRESS Memory
,
944 IN UINTN NumberOfPages
947 return SmmInternalFreePagesEx (Memory
, NumberOfPages
, FALSE
);
951 Frees previous allocated pages.
953 @param Memory Base address of memory being freed.
954 @param NumberOfPages The number of pages to free.
956 @retval EFI_NOT_FOUND Could not find the entry that covers the range.
957 @retval EFI_INVALID_PARAMETER Address not aligned, Address is zero or NumberOfPages is zero.
958 @return EFI_SUCCESS Pages successfully freed.
964 IN EFI_PHYSICAL_ADDRESS Memory
,
965 IN UINTN NumberOfPages
970 Status
= SmmInternalFreePages (Memory
, NumberOfPages
);
971 if (!EFI_ERROR (Status
)) {
972 SmmCoreUpdateProfile (
973 (EFI_PHYSICAL_ADDRESS
) (UINTN
) RETURN_ADDRESS (0),
974 MemoryProfileActionFreePages
,
976 EFI_PAGES_TO_SIZE (NumberOfPages
),
977 (VOID
*) (UINTN
) Memory
,
985 Add free SMRAM region for use by memory service.
987 @param MemBase Base address of memory region.
988 @param MemLength Length of the memory region.
989 @param Type Memory type.
990 @param Attributes Memory region state.
995 IN EFI_PHYSICAL_ADDRESS MemBase
,
997 IN EFI_MEMORY_TYPE Type
,
1001 UINTN AlignedMemBase
;
1004 // Add EfiRuntimeServicesData for memory regions that is already allocated, needs testing, or needs ECC initialization
1006 if ((Attributes
& (EFI_ALLOCATED
| EFI_NEEDS_TESTING
| EFI_NEEDS_ECC_INITIALIZATION
)) != 0) {
1007 Type
= EfiRuntimeServicesData
;
1009 Type
= EfiConventionalMemory
;
1012 DEBUG ((DEBUG_INFO
, "SmmAddMemoryRegion\n"));
1013 DEBUG ((DEBUG_INFO
, " MemBase - 0x%lx\n", MemBase
));
1014 DEBUG ((DEBUG_INFO
, " MemLength - 0x%lx\n", MemLength
));
1015 DEBUG ((DEBUG_INFO
, " Type - 0x%x\n", Type
));
1016 DEBUG ((DEBUG_INFO
, " Attributes - 0x%lx\n", Attributes
));
1019 // Align range on an EFI_PAGE_SIZE boundary
1021 AlignedMemBase
= (UINTN
)(MemBase
+ EFI_PAGE_MASK
) & ~EFI_PAGE_MASK
;
1022 MemLength
-= AlignedMemBase
- MemBase
;
1023 if (Type
== EfiConventionalMemory
) {
1024 SmmInternalFreePagesEx (AlignedMemBase
, TRUNCATE_TO_PAGES ((UINTN
)MemLength
), TRUE
);
1026 ConvertSmmMemoryMapEntry (EfiRuntimeServicesData
, AlignedMemBase
, TRUNCATE_TO_PAGES ((UINTN
)MemLength
), TRUE
);
1029 CoreFreeMemoryMapStack ();
1033 This function returns a copy of the current memory map. The map is an array of
1034 memory descriptors, each of which describes a contiguous block of memory.
1036 @param[in, out] MemoryMapSize A pointer to the size, in bytes, of the
1037 MemoryMap buffer. On input, this is the size of
1038 the buffer allocated by the caller. On output,
1039 it is the size of the buffer returned by the
1040 firmware if the buffer was large enough, or the
1041 size of the buffer needed to contain the map if
1042 the buffer was too small.
1043 @param[in, out] MemoryMap A pointer to the buffer in which firmware places
1044 the current memory map.
1045 @param[out] MapKey A pointer to the location in which firmware
1046 returns the key for the current memory map.
1047 @param[out] DescriptorSize A pointer to the location in which firmware
1048 returns the size, in bytes, of an individual
1049 EFI_MEMORY_DESCRIPTOR.
1050 @param[out] DescriptorVersion A pointer to the location in which firmware
1051 returns the version number associated with the
1052 EFI_MEMORY_DESCRIPTOR.
1054 @retval EFI_SUCCESS The memory map was returned in the MemoryMap
1056 @retval EFI_BUFFER_TOO_SMALL The MemoryMap buffer was too small. The current
1057 buffer size needed to hold the memory map is
1058 returned in MemoryMapSize.
1059 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
1064 SmmCoreGetMemoryMap (
1065 IN OUT UINTN
*MemoryMapSize
,
1066 IN OUT EFI_MEMORY_DESCRIPTOR
*MemoryMap
,
1068 OUT UINTN
*DescriptorSize
,
1069 OUT UINT32
*DescriptorVersion
1078 Size
= sizeof (EFI_MEMORY_DESCRIPTOR
);
1081 // Make sure Size != sizeof(EFI_MEMORY_DESCRIPTOR). This will
1082 // prevent people from having pointer math bugs in their code.
1083 // now you have to use *DescriptorSize to make things work.
1085 Size
+= sizeof(UINT64
) - (Size
% sizeof (UINT64
));
1087 if (DescriptorSize
!= NULL
) {
1088 *DescriptorSize
= Size
;
1091 if (DescriptorVersion
!= NULL
) {
1092 *DescriptorVersion
= EFI_MEMORY_DESCRIPTOR_VERSION
;
1095 Count
= GetSmmMemoryMapEntryCount ();
1096 BufferSize
= Size
* Count
;
1097 if (*MemoryMapSize
< BufferSize
) {
1098 *MemoryMapSize
= BufferSize
;
1099 return EFI_BUFFER_TOO_SMALL
;
1102 *MemoryMapSize
= BufferSize
;
1103 if (MemoryMap
== NULL
) {
1104 return EFI_INVALID_PARAMETER
;
1107 ZeroMem (MemoryMap
, BufferSize
);
1108 Link
= gMemoryMap
.ForwardLink
;
1109 while (Link
!= &gMemoryMap
) {
1110 Entry
= CR (Link
, MEMORY_MAP
, Link
, MEMORY_MAP_SIGNATURE
);
1111 Link
= Link
->ForwardLink
;
1113 MemoryMap
->Type
= Entry
->Type
;
1114 MemoryMap
->PhysicalStart
= Entry
->Start
;
1115 MemoryMap
->NumberOfPages
= RShiftU64 (Entry
->End
- Entry
->Start
+ 1, EFI_PAGE_SHIFT
);
1117 MemoryMap
= NEXT_MEMORY_DESCRIPTOR (MemoryMap
, Size
);