2 SMM Memory page management functions.
4 Copyright (c) 2009 - 2018, 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.
67 @param[in] NeedGuard Flag to indicate Guard page is needed
70 @retval EFI_INVALID_PARAMETER Parameters violate checking rules defined in spec.
71 @retval EFI_NOT_FOUND Could not allocate pages match the requirement.
72 @retval EFI_OUT_OF_RESOURCES No enough pages to allocate.
73 @retval EFI_SUCCESS Pages successfully allocated.
77 SmmInternalAllocatePagesEx (
78 IN EFI_ALLOCATE_TYPE Type
,
79 IN EFI_MEMORY_TYPE MemoryType
,
80 IN UINTN NumberOfPages
,
81 OUT EFI_PHYSICAL_ADDRESS
*Memory
,
87 Internal function. Deque a descriptor entry from the mFreeMemoryMapEntryList.
88 If the list is emtry, then allocate a new page to refuel the list.
89 Please Note this algorithm to allocate the memory map descriptor has a property
90 that the memory allocated for memory entries always grows, and will never really be freed.
92 @return The Memory map descriptor dequed from the mFreeMemoryMapEntryList
96 AllocateMemoryMapEntry (
100 EFI_PHYSICAL_ADDRESS Mem
;
102 MEMORY_MAP
* FreeDescriptorEntries
;
106 //DEBUG((DEBUG_INFO, "AllocateMemoryMapEntry\n"));
108 if (IsListEmpty (&mFreeMemoryMapEntryList
)) {
109 //DEBUG((DEBUG_INFO, "mFreeMemoryMapEntryList is empty\n"));
111 // The list is empty, to allocate one page to refuel the list
113 Status
= SmmInternalAllocatePagesEx (
115 EfiRuntimeServicesData
,
116 EFI_SIZE_TO_PAGES (RUNTIME_PAGE_ALLOCATION_GRANULARITY
),
121 ASSERT_EFI_ERROR (Status
);
122 if(!EFI_ERROR (Status
)) {
123 FreeDescriptorEntries
= (MEMORY_MAP
*)(UINTN
)Mem
;
124 //DEBUG((DEBUG_INFO, "New FreeDescriptorEntries - 0x%x\n", FreeDescriptorEntries));
126 // Enque the free memmory map entries into the list
128 for (Index
= 0; Index
< RUNTIME_PAGE_ALLOCATION_GRANULARITY
/ sizeof(MEMORY_MAP
); Index
++) {
129 FreeDescriptorEntries
[Index
].Signature
= MEMORY_MAP_SIGNATURE
;
130 InsertTailList (&mFreeMemoryMapEntryList
, &FreeDescriptorEntries
[Index
].Link
);
137 // dequeue the first descriptor from the list
139 Entry
= CR (mFreeMemoryMapEntryList
.ForwardLink
, MEMORY_MAP
, Link
, MEMORY_MAP_SIGNATURE
);
140 RemoveEntryList (&Entry
->Link
);
147 Internal function. Moves any memory descriptors that are on the
148 temporary descriptor stack to heap.
152 CoreFreeMemoryMapStack (
159 // If already freeing the map stack, then return
161 if (mFreeMapStack
!= 0) {
167 // Move the temporary memory descriptor stack into pool
171 while (mMapDepth
!= 0) {
173 // Deque an memory map entry from mFreeMemoryMapEntryList
175 Entry
= AllocateMemoryMapEntry ();
179 // Update to proper entry
183 if (mMapStack
[mMapDepth
].Link
.ForwardLink
!= NULL
) {
185 CopyMem (Entry
, &mMapStack
[mMapDepth
], sizeof (MEMORY_MAP
));
186 Entry
->FromStack
= FALSE
;
189 // Move this entry to general memory
191 InsertTailList (&mMapStack
[mMapDepth
].Link
, &Entry
->Link
);
192 RemoveEntryList (&mMapStack
[mMapDepth
].Link
);
193 mMapStack
[mMapDepth
].Link
.ForwardLink
= NULL
;
201 Insert new entry from memory map.
203 @param[in] Link The old memory map entry to be linked.
204 @param[in] Start The start address of new memory map entry.
205 @param[in] End The end address of new memory map entry.
206 @param[in] Type The type of new memory map entry.
207 @param[in] Next If new entry is inserted to the next of old entry.
208 @param[in] AddRegion If this memory is new added region.
215 IN EFI_MEMORY_TYPE Type
,
222 Entry
= &mMapStack
[mMapDepth
];
224 ASSERT (mMapDepth
< MAX_MAP_DEPTH
);
225 Entry
->FromStack
= TRUE
;
227 Entry
->Signature
= MEMORY_MAP_SIGNATURE
;
229 Entry
->Start
= Start
;
232 InsertHeadList (Link
, &Entry
->Link
);
234 InsertTailList (Link
, &Entry
->Link
);
239 Remove old entry from memory map.
241 @param[in] Entry Memory map entry to be removed.
248 RemoveEntryList (&Entry
->Link
);
249 Entry
->Link
.ForwardLink
= NULL
;
251 if (!Entry
->FromStack
) {
252 InsertTailList (&mFreeMemoryMapEntryList
, &Entry
->Link
);
257 Update SMM memory map entry.
259 @param[in] Type The type of allocation to perform.
260 @param[in] Memory The base of memory address.
261 @param[in] NumberOfPages The number of pages to allocate.
262 @param[in] AddRegion If this memory is new added region.
265 ConvertSmmMemoryMapEntry (
266 IN EFI_MEMORY_TYPE Type
,
267 IN EFI_PHYSICAL_ADDRESS Memory
,
268 IN UINTN NumberOfPages
,
274 MEMORY_MAP
*NextEntry
;
275 LIST_ENTRY
*NextLink
;
276 MEMORY_MAP
*PreviousEntry
;
277 LIST_ENTRY
*PreviousLink
;
278 EFI_PHYSICAL_ADDRESS Start
;
279 EFI_PHYSICAL_ADDRESS End
;
282 End
= Memory
+ EFI_PAGES_TO_SIZE(NumberOfPages
) - 1;
285 // Exclude memory region
287 Link
= gMemoryMap
.ForwardLink
;
288 while (Link
!= &gMemoryMap
) {
289 Entry
= CR (Link
, MEMORY_MAP
, Link
, MEMORY_MAP_SIGNATURE
);
290 Link
= Link
->ForwardLink
;
293 // ---------------------------------------------------
294 // | +----------+ +------+ +------+ +------+ |
295 // ---|gMemoryMep|---|Entry1|---|Entry2|---|Entry3|---
296 // +----------+ ^ +------+ +------+ +------+
302 if (Entry
->Start
> End
) {
303 if ((Entry
->Start
== End
+ 1) && (Entry
->Type
== Type
)) {
304 Entry
->Start
= Start
;
318 if ((Entry
->Start
<= Start
) && (Entry
->End
>= End
)) {
319 if (Entry
->Type
!= Type
) {
320 if (Entry
->Start
< Start
) {
322 // ---------------------------------------------------
323 // | +----------+ +------+ +------+ +------+ |
324 // ---|gMemoryMep|---|Entry1|---|EntryX|---|Entry3|---
325 // +----------+ +------+ ^ +------+ +------+
340 if (Entry
->End
> End
) {
342 // ---------------------------------------------------
343 // | +----------+ +------+ +------+ +------+ |
344 // ---|gMemoryMep|---|Entry1|---|EntryX|---|Entry3|---
345 // +----------+ +------+ +------+ ^ +------+
363 Entry
->Start
= Start
;
370 NextLink
= Entry
->Link
.ForwardLink
;
371 if (NextLink
!= &gMemoryMap
) {
372 NextEntry
= CR (NextLink
, MEMORY_MAP
, Link
, MEMORY_MAP_SIGNATURE
);
374 // ---------------------------------------------------
375 // | +----------+ +------+ +-----------------+ |
376 // ---|gMemoryMep|---|Entry1|---|EntryX Entry3|---
377 // +----------+ +------+ +-----------------+
379 if ((Entry
->Type
== NextEntry
->Type
) && (Entry
->End
+ 1 == NextEntry
->Start
)) {
380 Entry
->End
= NextEntry
->End
;
381 RemoveOldEntry (NextEntry
);
384 PreviousLink
= Entry
->Link
.BackLink
;
385 if (PreviousLink
!= &gMemoryMap
) {
386 PreviousEntry
= CR (PreviousLink
, MEMORY_MAP
, Link
, MEMORY_MAP_SIGNATURE
);
388 // ---------------------------------------------------
389 // | +----------+ +-----------------+ +------+ |
390 // ---|gMemoryMep|---|Entry1 EntryX|---|Entry3|---
391 // +----------+ +-----------------+ +------+
393 if ((PreviousEntry
->Type
== Entry
->Type
) && (PreviousEntry
->End
+ 1 == Entry
->Start
)) {
394 PreviousEntry
->End
= Entry
->End
;
395 RemoveOldEntry (Entry
);
404 // ---------------------------------------------------
405 // | +----------+ +------+ +------+ +------+ |
406 // ---|gMemoryMep|---|Entry1|---|Entry2|---|Entry3|---
407 // +----------+ +------+ +------+ +------+ ^
413 Link
= gMemoryMap
.BackLink
;
414 if (Link
!= &gMemoryMap
) {
415 Entry
= CR (Link
, MEMORY_MAP
, Link
, MEMORY_MAP_SIGNATURE
);
416 if ((Entry
->End
+ 1 == Start
) && (Entry
->Type
== Type
)) {
433 Return the count of Smm memory map entry.
435 @return The count of Smm memory map entry.
438 GetSmmMemoryMapEntryCount (
446 Link
= gMemoryMap
.ForwardLink
;
447 while (Link
!= &gMemoryMap
) {
448 Link
= Link
->ForwardLink
;
457 Internal Function. Allocate n pages from given free page node.
459 @param Pages The free page node.
460 @param NumberOfPages Number of pages to be allocated.
461 @param MaxAddress Request to allocate memory below this address.
463 @return Memory address of allocated pages.
467 InternalAllocPagesOnOneNode (
468 IN OUT FREE_PAGE_LIST
*Pages
,
469 IN UINTN NumberOfPages
,
475 FREE_PAGE_LIST
*Node
;
477 Top
= TRUNCATE_TO_PAGES (MaxAddress
+ 1 - (UINTN
)Pages
);
478 if (Top
> Pages
->NumberOfPages
) {
479 Top
= Pages
->NumberOfPages
;
481 Bottom
= Top
- NumberOfPages
;
483 if (Top
< Pages
->NumberOfPages
) {
484 Node
= (FREE_PAGE_LIST
*)((UINTN
)Pages
+ EFI_PAGES_TO_SIZE (Top
));
485 Node
->NumberOfPages
= Pages
->NumberOfPages
- Top
;
486 InsertHeadList (&Pages
->Link
, &Node
->Link
);
490 Pages
->NumberOfPages
= Bottom
;
492 RemoveEntryList (&Pages
->Link
);
495 return (UINTN
)Pages
+ EFI_PAGES_TO_SIZE (Bottom
);
499 Internal Function. Allocate n pages from free page list below MaxAddress.
501 @param FreePageList The free page node.
502 @param NumberOfPages Number of pages to be allocated.
503 @param MaxAddress Request to allocate memory below this address.
505 @return Memory address of allocated pages.
509 InternalAllocMaxAddress (
510 IN OUT LIST_ENTRY
*FreePageList
,
511 IN UINTN NumberOfPages
,
516 FREE_PAGE_LIST
*Pages
;
518 for (Node
= FreePageList
->BackLink
; Node
!= FreePageList
; Node
= Node
->BackLink
) {
519 Pages
= BASE_CR (Node
, FREE_PAGE_LIST
, Link
);
520 if (Pages
->NumberOfPages
>= NumberOfPages
&&
521 (UINTN
)Pages
+ EFI_PAGES_TO_SIZE (NumberOfPages
) - 1 <= MaxAddress
) {
522 return InternalAllocPagesOnOneNode (Pages
, NumberOfPages
, MaxAddress
);
529 Internal Function. Allocate n pages from free page list at given address.
531 @param FreePageList The free page node.
532 @param NumberOfPages Number of pages to be allocated.
533 @param MaxAddress Request to allocate memory below this address.
535 @return Memory address of allocated pages.
539 InternalAllocAddress (
540 IN OUT LIST_ENTRY
*FreePageList
,
541 IN UINTN NumberOfPages
,
547 FREE_PAGE_LIST
*Pages
;
549 if ((Address
& EFI_PAGE_MASK
) != 0) {
553 EndAddress
= Address
+ EFI_PAGES_TO_SIZE (NumberOfPages
);
554 for (Node
= FreePageList
->BackLink
; Node
!= FreePageList
; Node
= Node
->BackLink
) {
555 Pages
= BASE_CR (Node
, FREE_PAGE_LIST
, Link
);
556 if ((UINTN
)Pages
<= Address
) {
557 if ((UINTN
)Pages
+ EFI_PAGES_TO_SIZE (Pages
->NumberOfPages
) < EndAddress
) {
560 return InternalAllocPagesOnOneNode (Pages
, NumberOfPages
, EndAddress
);
567 Allocates pages from the memory map.
569 @param[in] Type The type of allocation to perform.
570 @param[in] MemoryType The type of memory to turn the allocated pages
572 @param[in] NumberOfPages The number of pages to allocate.
573 @param[out] Memory A pointer to receive the base allocated memory
575 @param[in] AddRegion If this memory is new added region.
576 @param[in] NeedGuard Flag to indicate Guard page is needed
579 @retval EFI_INVALID_PARAMETER Parameters violate checking rules defined in spec.
580 @retval EFI_NOT_FOUND Could not allocate pages match the requirement.
581 @retval EFI_OUT_OF_RESOURCES No enough pages to allocate.
582 @retval EFI_SUCCESS Pages successfully allocated.
586 SmmInternalAllocatePagesEx (
587 IN EFI_ALLOCATE_TYPE Type
,
588 IN EFI_MEMORY_TYPE MemoryType
,
589 IN UINTN NumberOfPages
,
590 OUT EFI_PHYSICAL_ADDRESS
*Memory
,
591 IN BOOLEAN AddRegion
,
595 UINTN RequestedAddress
;
597 if (MemoryType
!= EfiRuntimeServicesCode
&&
598 MemoryType
!= EfiRuntimeServicesData
) {
599 return EFI_INVALID_PARAMETER
;
602 if (NumberOfPages
> TRUNCATE_TO_PAGES ((UINTN
)-1) + 1) {
603 return EFI_OUT_OF_RESOURCES
;
607 // We don't track memory type in SMM
609 RequestedAddress
= (UINTN
)*Memory
;
611 case AllocateAnyPages
:
612 RequestedAddress
= (UINTN
)(-1);
613 case AllocateMaxAddress
:
615 *Memory
= InternalAllocMaxAddressWithGuard (
621 if (*Memory
== (UINTN
)-1) {
622 return EFI_OUT_OF_RESOURCES
;
624 ASSERT (VerifyMemoryGuard (*Memory
, NumberOfPages
) == TRUE
);
629 *Memory
= InternalAllocMaxAddress (
634 if (*Memory
== (UINTN
)-1) {
635 return EFI_OUT_OF_RESOURCES
;
638 case AllocateAddress
:
639 *Memory
= InternalAllocAddress (
644 if (*Memory
!= RequestedAddress
) {
645 return EFI_NOT_FOUND
;
649 return EFI_INVALID_PARAMETER
;
653 // Update SmmMemoryMap here.
655 ConvertSmmMemoryMapEntry (MemoryType
, *Memory
, NumberOfPages
, AddRegion
);
657 CoreFreeMemoryMapStack();
664 Allocates pages from the memory map.
666 @param[in] Type The type of allocation to perform.
667 @param[in] MemoryType The type of memory to turn the allocated pages
669 @param[in] NumberOfPages The number of pages to allocate.
670 @param[out] Memory A pointer to receive the base allocated memory
672 @param[in] NeedGuard Flag to indicate Guard page is needed
675 @retval EFI_INVALID_PARAMETER Parameters violate checking rules defined in spec.
676 @retval EFI_NOT_FOUND Could not allocate pages match the requirement.
677 @retval EFI_OUT_OF_RESOURCES No enough pages to allocate.
678 @retval EFI_SUCCESS Pages successfully allocated.
683 SmmInternalAllocatePages (
684 IN EFI_ALLOCATE_TYPE Type
,
685 IN EFI_MEMORY_TYPE MemoryType
,
686 IN UINTN NumberOfPages
,
687 OUT EFI_PHYSICAL_ADDRESS
*Memory
,
691 return SmmInternalAllocatePagesEx (Type
, MemoryType
, NumberOfPages
, Memory
,
696 Allocates pages from the memory map.
698 @param Type The type of allocation to perform.
699 @param MemoryType The type of memory to turn the allocated pages
701 @param NumberOfPages The number of pages to allocate.
702 @param Memory A pointer to receive the base allocated memory
705 @retval EFI_INVALID_PARAMETER Parameters violate checking rules defined in spec.
706 @retval EFI_NOT_FOUND Could not allocate pages match the requirement.
707 @retval EFI_OUT_OF_RESOURCES No enough pages to allocate.
708 @retval EFI_SUCCESS Pages successfully allocated.
714 IN EFI_ALLOCATE_TYPE Type
,
715 IN EFI_MEMORY_TYPE MemoryType
,
716 IN UINTN NumberOfPages
,
717 OUT EFI_PHYSICAL_ADDRESS
*Memory
723 NeedGuard
= IsPageTypeToGuard (MemoryType
, Type
);
724 Status
= SmmInternalAllocatePages (Type
, MemoryType
, NumberOfPages
, Memory
,
726 if (!EFI_ERROR (Status
)) {
727 SmmCoreUpdateProfile (
728 (EFI_PHYSICAL_ADDRESS
) (UINTN
) RETURN_ADDRESS (0),
729 MemoryProfileActionAllocatePages
,
731 EFI_PAGES_TO_SIZE (NumberOfPages
),
732 (VOID
*) (UINTN
) *Memory
,
740 Internal Function. Merge two adjacent nodes.
742 @param First The first of two nodes to merge.
744 @return Pointer to node after merge (if success) or pointer to next node (if fail).
749 IN FREE_PAGE_LIST
*First
752 FREE_PAGE_LIST
*Next
;
754 Next
= BASE_CR (First
->Link
.ForwardLink
, FREE_PAGE_LIST
, Link
);
756 TRUNCATE_TO_PAGES ((UINTN
)Next
- (UINTN
)First
) >= First
->NumberOfPages
);
758 if (TRUNCATE_TO_PAGES ((UINTN
)Next
- (UINTN
)First
) == First
->NumberOfPages
) {
759 First
->NumberOfPages
+= Next
->NumberOfPages
;
760 RemoveEntryList (&Next
->Link
);
767 Frees previous allocated pages.
769 @param[in] Memory Base address of memory being freed.
770 @param[in] NumberOfPages The number of pages to free.
771 @param[in] AddRegion If this memory is new added region.
773 @retval EFI_NOT_FOUND Could not find the entry that covers the range.
774 @retval EFI_INVALID_PARAMETER Address not aligned, Address is zero or NumberOfPages is zero.
775 @return EFI_SUCCESS Pages successfully freed.
779 SmmInternalFreePagesEx (
780 IN EFI_PHYSICAL_ADDRESS Memory
,
781 IN UINTN NumberOfPages
,
786 FREE_PAGE_LIST
*Pages
;
788 if (((Memory
& EFI_PAGE_MASK
) != 0) || (Memory
== 0) || (NumberOfPages
== 0)) {
789 return EFI_INVALID_PARAMETER
;
793 Node
= mSmmMemoryMap
.ForwardLink
;
794 while (Node
!= &mSmmMemoryMap
) {
795 Pages
= BASE_CR (Node
, FREE_PAGE_LIST
, Link
);
796 if (Memory
< (UINTN
)Pages
) {
799 Node
= Node
->ForwardLink
;
802 if (Node
!= &mSmmMemoryMap
&&
803 Memory
+ EFI_PAGES_TO_SIZE (NumberOfPages
) > (UINTN
)Pages
) {
804 return EFI_INVALID_PARAMETER
;
807 if (Node
->BackLink
!= &mSmmMemoryMap
) {
808 Pages
= BASE_CR (Node
->BackLink
, FREE_PAGE_LIST
, Link
);
809 if ((UINTN
)Pages
+ EFI_PAGES_TO_SIZE (Pages
->NumberOfPages
) > Memory
) {
810 return EFI_INVALID_PARAMETER
;
814 Pages
= (FREE_PAGE_LIST
*)(UINTN
)Memory
;
815 Pages
->NumberOfPages
= NumberOfPages
;
816 InsertTailList (Node
, &Pages
->Link
);
818 if (Pages
->Link
.BackLink
!= &mSmmMemoryMap
) {
819 Pages
= InternalMergeNodes (
820 BASE_CR (Pages
->Link
.BackLink
, FREE_PAGE_LIST
, Link
)
824 if (Node
!= &mSmmMemoryMap
) {
825 InternalMergeNodes (Pages
);
829 // Update SmmMemoryMap here.
831 ConvertSmmMemoryMapEntry (EfiConventionalMemory
, Memory
, NumberOfPages
, AddRegion
);
833 CoreFreeMemoryMapStack();
840 Frees previous allocated pages.
842 @param[in] Memory Base address of memory being freed.
843 @param[in] NumberOfPages The number of pages to free.
844 @param[in] IsGuarded Is the memory to free guarded or not.
846 @retval EFI_NOT_FOUND Could not find the entry that covers the range.
847 @retval EFI_INVALID_PARAMETER Address not aligned, Address is zero or NumberOfPages is zero.
848 @return EFI_SUCCESS Pages successfully freed.
853 SmmInternalFreePages (
854 IN EFI_PHYSICAL_ADDRESS Memory
,
855 IN UINTN NumberOfPages
,
860 return SmmInternalFreePagesExWithGuard (Memory
, NumberOfPages
, FALSE
);
862 return SmmInternalFreePagesEx (Memory
, NumberOfPages
, FALSE
);
866 Frees previous allocated pages.
868 @param Memory Base address of memory being freed.
869 @param NumberOfPages The number of pages to free.
871 @retval EFI_NOT_FOUND Could not find the entry that covers the range.
872 @retval EFI_INVALID_PARAMETER Address not aligned, Address is zero or NumberOfPages is zero.
873 @return EFI_SUCCESS Pages successfully freed.
879 IN EFI_PHYSICAL_ADDRESS Memory
,
880 IN UINTN NumberOfPages
886 IsGuarded
= IsHeapGuardEnabled () && IsMemoryGuarded (Memory
);
887 Status
= SmmInternalFreePages (Memory
, NumberOfPages
, IsGuarded
);
888 if (!EFI_ERROR (Status
)) {
889 SmmCoreUpdateProfile (
890 (EFI_PHYSICAL_ADDRESS
) (UINTN
) RETURN_ADDRESS (0),
891 MemoryProfileActionFreePages
,
893 EFI_PAGES_TO_SIZE (NumberOfPages
),
894 (VOID
*) (UINTN
) Memory
,
902 Add free SMRAM region for use by memory service.
904 @param MemBase Base address of memory region.
905 @param MemLength Length of the memory region.
906 @param Type Memory type.
907 @param Attributes Memory region state.
912 IN EFI_PHYSICAL_ADDRESS MemBase
,
914 IN EFI_MEMORY_TYPE Type
,
918 UINTN AlignedMemBase
;
921 // Add EfiRuntimeServicesData for memory regions that is already allocated, needs testing, or needs ECC initialization
923 if ((Attributes
& (EFI_ALLOCATED
| EFI_NEEDS_TESTING
| EFI_NEEDS_ECC_INITIALIZATION
)) != 0) {
924 Type
= EfiRuntimeServicesData
;
926 Type
= EfiConventionalMemory
;
929 DEBUG ((DEBUG_INFO
, "SmmAddMemoryRegion\n"));
930 DEBUG ((DEBUG_INFO
, " MemBase - 0x%lx\n", MemBase
));
931 DEBUG ((DEBUG_INFO
, " MemLength - 0x%lx\n", MemLength
));
932 DEBUG ((DEBUG_INFO
, " Type - 0x%x\n", Type
));
933 DEBUG ((DEBUG_INFO
, " Attributes - 0x%lx\n", Attributes
));
936 // Align range on an EFI_PAGE_SIZE boundary
938 AlignedMemBase
= (UINTN
)(MemBase
+ EFI_PAGE_MASK
) & ~EFI_PAGE_MASK
;
939 MemLength
-= AlignedMemBase
- MemBase
;
940 if (Type
== EfiConventionalMemory
) {
941 SmmInternalFreePagesEx (AlignedMemBase
, TRUNCATE_TO_PAGES ((UINTN
)MemLength
), TRUE
);
943 ConvertSmmMemoryMapEntry (EfiRuntimeServicesData
, AlignedMemBase
, TRUNCATE_TO_PAGES ((UINTN
)MemLength
), TRUE
);
946 CoreFreeMemoryMapStack ();
950 This function returns a copy of the current memory map. The map is an array of
951 memory descriptors, each of which describes a contiguous block of memory.
953 @param[in, out] MemoryMapSize A pointer to the size, in bytes, of the
954 MemoryMap buffer. On input, this is the size of
955 the buffer allocated by the caller. On output,
956 it is the size of the buffer returned by the
957 firmware if the buffer was large enough, or the
958 size of the buffer needed to contain the map if
959 the buffer was too small.
960 @param[in, out] MemoryMap A pointer to the buffer in which firmware places
961 the current memory map.
962 @param[out] MapKey A pointer to the location in which firmware
963 returns the key for the current memory map.
964 @param[out] DescriptorSize A pointer to the location in which firmware
965 returns the size, in bytes, of an individual
966 EFI_MEMORY_DESCRIPTOR.
967 @param[out] DescriptorVersion A pointer to the location in which firmware
968 returns the version number associated with the
969 EFI_MEMORY_DESCRIPTOR.
971 @retval EFI_SUCCESS The memory map was returned in the MemoryMap
973 @retval EFI_BUFFER_TOO_SMALL The MemoryMap buffer was too small. The current
974 buffer size needed to hold the memory map is
975 returned in MemoryMapSize.
976 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
981 SmmCoreGetMemoryMap (
982 IN OUT UINTN
*MemoryMapSize
,
983 IN OUT EFI_MEMORY_DESCRIPTOR
*MemoryMap
,
985 OUT UINTN
*DescriptorSize
,
986 OUT UINT32
*DescriptorVersion
995 Size
= sizeof (EFI_MEMORY_DESCRIPTOR
);
998 // Make sure Size != sizeof(EFI_MEMORY_DESCRIPTOR). This will
999 // prevent people from having pointer math bugs in their code.
1000 // now you have to use *DescriptorSize to make things work.
1002 Size
+= sizeof(UINT64
) - (Size
% sizeof (UINT64
));
1004 if (DescriptorSize
!= NULL
) {
1005 *DescriptorSize
= Size
;
1008 if (DescriptorVersion
!= NULL
) {
1009 *DescriptorVersion
= EFI_MEMORY_DESCRIPTOR_VERSION
;
1012 Count
= GetSmmMemoryMapEntryCount ();
1013 BufferSize
= Size
* Count
;
1014 if (*MemoryMapSize
< BufferSize
) {
1015 *MemoryMapSize
= BufferSize
;
1016 return EFI_BUFFER_TOO_SMALL
;
1019 *MemoryMapSize
= BufferSize
;
1020 if (MemoryMap
== NULL
) {
1021 return EFI_INVALID_PARAMETER
;
1024 ZeroMem (MemoryMap
, BufferSize
);
1025 Link
= gMemoryMap
.ForwardLink
;
1026 while (Link
!= &gMemoryMap
) {
1027 Entry
= CR (Link
, MEMORY_MAP
, Link
, MEMORY_MAP_SIGNATURE
);
1028 Link
= Link
->ForwardLink
;
1030 MemoryMap
->Type
= Entry
->Type
;
1031 MemoryMap
->PhysicalStart
= Entry
->Start
;
1032 MemoryMap
->NumberOfPages
= RShiftU64 (Entry
->End
- Entry
->Start
+ 1, EFI_PAGE_SHIFT
);
1034 MemoryMap
= NEXT_MEMORY_DESCRIPTOR (MemoryMap
, Size
);