2 SMM Memory pool management functions.
4 Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.<BR>
5 Copyright (c) 2016 - 2021, Arm Limited. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
10 #include "StandaloneMmCore.h"
12 LIST_ENTRY mMmPoolLists
[MAX_POOL_INDEX
];
14 // To cache the MMRAM base since when Loading modules At fixed address feature is enabled,
15 // all module is assigned an offset relative the MMRAM base in build time.
17 GLOBAL_REMOVE_IF_UNREFERENCED EFI_PHYSICAL_ADDRESS gLoadModuleAtFixAddressMmramBase
= 0;
20 Called to initialize the memory service.
22 @param MmramRangeCount Number of MMRAM Regions
23 @param MmramRanges Pointer to MMRAM Descriptors
27 MmInitializeMemoryServices (
28 IN UINTN MmramRangeCount
,
29 IN EFI_MMRAM_DESCRIPTOR
*MmramRanges
35 // Initialize Pool list
37 for (Index
= sizeof (mMmPoolLists
) / sizeof (*mMmPoolLists
); Index
> 0;) {
38 InitializeListHead (&mMmPoolLists
[--Index
]);
42 // Initialize free MMRAM regions
44 for (Index
= 0; Index
< MmramRangeCount
; Index
++) {
46 // BUGBUG: Add legacy MMRAM region is buggy.
48 if (MmramRanges
[Index
].CpuStart
< BASE_1MB
) {
54 "MmAddMemoryRegion %d : 0x%016lx - 0x%016lx\n",
56 MmramRanges
[Index
].CpuStart
,
57 MmramRanges
[Index
].PhysicalSize
60 MmramRanges
[Index
].CpuStart
,
61 MmramRanges
[Index
].PhysicalSize
,
62 EfiConventionalMemory
,
63 MmramRanges
[Index
].RegionState
69 Internal Function. Allocate a pool by specified PoolIndex.
71 @param PoolIndex Index which indicate the Pool size.
72 @param FreePoolHdr The returned Free pool.
74 @retval EFI_OUT_OF_RESOURCES Allocation failed.
75 @retval EFI_SUCCESS Pool successfully allocated.
79 InternalAllocPoolByIndex (
81 OUT FREE_POOL_HEADER
**FreePoolHdr
85 FREE_POOL_HEADER
*Hdr
;
86 EFI_PHYSICAL_ADDRESS Address
;
88 ASSERT (PoolIndex
<= MAX_POOL_INDEX
);
91 if (PoolIndex
== MAX_POOL_INDEX
) {
92 Status
= MmInternalAllocatePages (
94 EfiRuntimeServicesData
,
95 EFI_SIZE_TO_PAGES (MAX_POOL_SIZE
<< 1),
98 if (EFI_ERROR (Status
)) {
99 return EFI_OUT_OF_RESOURCES
;
102 Hdr
= (FREE_POOL_HEADER
*)(UINTN
)Address
;
103 } else if (!IsListEmpty (&mMmPoolLists
[PoolIndex
])) {
104 Hdr
= BASE_CR (GetFirstNode (&mMmPoolLists
[PoolIndex
]), FREE_POOL_HEADER
, Link
);
105 RemoveEntryList (&Hdr
->Link
);
107 Status
= InternalAllocPoolByIndex (PoolIndex
+ 1, &Hdr
);
108 if (!EFI_ERROR (Status
)) {
109 Hdr
->Header
.Size
>>= 1;
110 Hdr
->Header
.Available
= TRUE
;
111 InsertHeadList (&mMmPoolLists
[PoolIndex
], &Hdr
->Link
);
112 Hdr
= (FREE_POOL_HEADER
*)((UINT8
*)Hdr
+ Hdr
->Header
.Size
);
116 if (!EFI_ERROR (Status
)) {
117 Hdr
->Header
.Size
= MIN_POOL_SIZE
<< PoolIndex
;
118 Hdr
->Header
.Available
= FALSE
;
126 Internal Function. Free a pool by specified PoolIndex.
128 @param FreePoolHdr The pool to free.
130 @retval EFI_SUCCESS Pool successfully freed.
134 InternalFreePoolByIndex (
135 IN FREE_POOL_HEADER
*FreePoolHdr
140 ASSERT ((FreePoolHdr
->Header
.Size
& (FreePoolHdr
->Header
.Size
- 1)) == 0);
141 ASSERT (((UINTN
)FreePoolHdr
& (FreePoolHdr
->Header
.Size
- 1)) == 0);
142 ASSERT (FreePoolHdr
->Header
.Size
>= MIN_POOL_SIZE
);
144 PoolIndex
= (UINTN
)(HighBitSet32 ((UINT32
)FreePoolHdr
->Header
.Size
) - MIN_POOL_SHIFT
);
145 FreePoolHdr
->Header
.Available
= TRUE
;
146 ASSERT (PoolIndex
< MAX_POOL_INDEX
);
147 InsertHeadList (&mMmPoolLists
[PoolIndex
], &FreePoolHdr
->Link
);
152 Allocate pool of a particular type.
154 @param PoolType Type of pool to allocate.
155 @param Size The amount of pool to allocate.
156 @param Buffer The address to return a pointer to the allocated
159 @retval EFI_INVALID_PARAMETER PoolType not valid.
160 @retval EFI_OUT_OF_RESOURCES Size exceeds max pool size or allocation failed.
161 @retval EFI_SUCCESS Pool successfully allocated.
166 MmInternalAllocatePool (
167 IN EFI_MEMORY_TYPE PoolType
,
172 POOL_HEADER
*PoolHdr
;
173 FREE_POOL_HEADER
*FreePoolHdr
;
175 EFI_PHYSICAL_ADDRESS Address
;
178 if ((PoolType
!= EfiRuntimeServicesCode
) &&
179 (PoolType
!= EfiRuntimeServicesData
))
181 return EFI_INVALID_PARAMETER
;
184 Size
+= sizeof (*PoolHdr
);
185 if (Size
> MAX_POOL_SIZE
) {
186 Size
= EFI_SIZE_TO_PAGES (Size
);
187 Status
= MmInternalAllocatePages (AllocateAnyPages
, PoolType
, Size
, &Address
);
188 if (EFI_ERROR (Status
)) {
192 PoolHdr
= (POOL_HEADER
*)(UINTN
)Address
;
193 PoolHdr
->Size
= EFI_PAGES_TO_SIZE (Size
);
194 PoolHdr
->Available
= FALSE
;
195 *Buffer
= PoolHdr
+ 1;
199 Size
= (Size
+ MIN_POOL_SIZE
- 1) >> MIN_POOL_SHIFT
;
200 PoolIndex
= (UINTN
)HighBitSet32 ((UINT32
)Size
);
201 if ((Size
& (Size
- 1)) != 0) {
205 Status
= InternalAllocPoolByIndex (PoolIndex
, &FreePoolHdr
);
206 if (!EFI_ERROR (Status
)) {
207 *Buffer
= &FreePoolHdr
->Header
+ 1;
214 Allocate pool of a particular type.
216 @param PoolType Type of pool to allocate.
217 @param Size The amount of pool to allocate.
218 @param Buffer The address to return a pointer to the allocated
221 @retval EFI_INVALID_PARAMETER PoolType not valid.
222 @retval EFI_OUT_OF_RESOURCES Size exceeds max pool size or allocation failed.
223 @retval EFI_SUCCESS Pool successfully allocated.
229 IN EFI_MEMORY_TYPE PoolType
,
236 Status
= MmInternalAllocatePool (PoolType
, Size
, Buffer
);
243 @param Buffer The allocated pool entry to free.
245 @retval EFI_INVALID_PARAMETER Buffer is not a valid value.
246 @retval EFI_SUCCESS Pool successfully freed.
255 FREE_POOL_HEADER
*FreePoolHdr
;
257 if (Buffer
== NULL
) {
258 return EFI_INVALID_PARAMETER
;
261 FreePoolHdr
= (FREE_POOL_HEADER
*)((POOL_HEADER
*)Buffer
- 1);
262 ASSERT (!FreePoolHdr
->Header
.Available
);
264 if (FreePoolHdr
->Header
.Size
> MAX_POOL_SIZE
) {
265 ASSERT (((UINTN
)FreePoolHdr
& EFI_PAGE_MASK
) == 0);
266 ASSERT ((FreePoolHdr
->Header
.Size
& EFI_PAGE_MASK
) == 0);
267 return MmInternalFreePages (
268 (EFI_PHYSICAL_ADDRESS
)(UINTN
)FreePoolHdr
,
269 EFI_SIZE_TO_PAGES (FreePoolHdr
->Header
.Size
)
273 return InternalFreePoolByIndex (FreePoolHdr
);
279 @param Buffer The allocated pool entry to free.
281 @retval EFI_INVALID_PARAMETER Buffer is not a valid value.
282 @retval EFI_SUCCESS Pool successfully freed.
293 Status
= MmInternalFreePool (Buffer
);