2 SMM Memory pool management functions.
4 Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.<BR>
5 Copyright (c) 2016 - 2018, 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
]);
43 // Initialize free MMRAM regions
45 for (Index
= 0; Index
< MmramRangeCount
; Index
++) {
47 // BUGBUG: Add legacy MMRAM region is buggy.
49 if (MmramRanges
[Index
].CpuStart
< BASE_1MB
) {
52 DEBUG ((DEBUG_INFO
, "MmAddMemoryRegion %d : 0x%016lx - 0x%016lx\n",
53 Index
, MmramRanges
[Index
].CpuStart
, MmramRanges
[Index
].PhysicalSize
));
55 MmramRanges
[Index
].CpuStart
,
56 MmramRanges
[Index
].PhysicalSize
,
57 EfiConventionalMemory
,
58 MmramRanges
[Index
].RegionState
65 Internal Function. Allocate a pool by specified PoolIndex.
67 @param PoolIndex Index which indicate the Pool size.
68 @param FreePoolHdr The returned Free pool.
70 @retval EFI_OUT_OF_RESOURCES Allocation failed.
71 @retval EFI_SUCCESS Pool successfully allocated.
75 InternalAllocPoolByIndex (
77 OUT FREE_POOL_HEADER
**FreePoolHdr
81 FREE_POOL_HEADER
*Hdr
;
82 EFI_PHYSICAL_ADDRESS Address
;
84 ASSERT (PoolIndex
<= MAX_POOL_INDEX
);
87 if (PoolIndex
== MAX_POOL_INDEX
) {
88 Status
= MmInternalAllocatePages (
90 EfiRuntimeServicesData
,
91 EFI_SIZE_TO_PAGES (MAX_POOL_SIZE
<< 1),
94 if (EFI_ERROR (Status
)) {
95 return EFI_OUT_OF_RESOURCES
;
97 Hdr
= (FREE_POOL_HEADER
*) (UINTN
) Address
;
98 } else if (!IsListEmpty (&mMmPoolLists
[PoolIndex
])) {
99 Hdr
= BASE_CR (GetFirstNode (&mMmPoolLists
[PoolIndex
]), FREE_POOL_HEADER
, Link
);
100 RemoveEntryList (&Hdr
->Link
);
102 Status
= InternalAllocPoolByIndex (PoolIndex
+ 1, &Hdr
);
103 if (!EFI_ERROR (Status
)) {
104 Hdr
->Header
.Size
>>= 1;
105 Hdr
->Header
.Available
= TRUE
;
106 InsertHeadList (&mMmPoolLists
[PoolIndex
], &Hdr
->Link
);
107 Hdr
= (FREE_POOL_HEADER
*)((UINT8
*)Hdr
+ Hdr
->Header
.Size
);
111 if (!EFI_ERROR (Status
)) {
112 Hdr
->Header
.Size
= MIN_POOL_SIZE
<< PoolIndex
;
113 Hdr
->Header
.Available
= FALSE
;
121 Internal Function. Free a pool by specified PoolIndex.
123 @param FreePoolHdr The pool to free.
125 @retval EFI_SUCCESS Pool successfully freed.
129 InternalFreePoolByIndex (
130 IN FREE_POOL_HEADER
*FreePoolHdr
135 ASSERT ((FreePoolHdr
->Header
.Size
& (FreePoolHdr
->Header
.Size
- 1)) == 0);
136 ASSERT (((UINTN
)FreePoolHdr
& (FreePoolHdr
->Header
.Size
- 1)) == 0);
137 ASSERT (FreePoolHdr
->Header
.Size
>= MIN_POOL_SIZE
);
139 PoolIndex
= (UINTN
) (HighBitSet32 ((UINT32
)FreePoolHdr
->Header
.Size
) - MIN_POOL_SHIFT
);
140 FreePoolHdr
->Header
.Available
= TRUE
;
141 ASSERT (PoolIndex
< MAX_POOL_INDEX
);
142 InsertHeadList (&mMmPoolLists
[PoolIndex
], &FreePoolHdr
->Link
);
147 Allocate pool of a particular type.
149 @param PoolType Type of pool to allocate.
150 @param Size The amount of pool to allocate.
151 @param Buffer The address to return a pointer to the allocated
154 @retval EFI_INVALID_PARAMETER PoolType not valid.
155 @retval EFI_OUT_OF_RESOURCES Size exceeds max pool size or allocation failed.
156 @retval EFI_SUCCESS Pool successfully allocated.
161 MmInternalAllocatePool (
162 IN EFI_MEMORY_TYPE PoolType
,
167 POOL_HEADER
*PoolHdr
;
168 FREE_POOL_HEADER
*FreePoolHdr
;
170 EFI_PHYSICAL_ADDRESS Address
;
173 if (PoolType
!= EfiRuntimeServicesCode
&&
174 PoolType
!= EfiRuntimeServicesData
) {
175 return EFI_INVALID_PARAMETER
;
178 Size
+= sizeof (*PoolHdr
);
179 if (Size
> MAX_POOL_SIZE
) {
180 Size
= EFI_SIZE_TO_PAGES (Size
);
181 Status
= MmInternalAllocatePages (AllocateAnyPages
, PoolType
, Size
, &Address
);
182 if (EFI_ERROR (Status
)) {
186 PoolHdr
= (POOL_HEADER
*)(UINTN
)Address
;
187 PoolHdr
->Size
= EFI_PAGES_TO_SIZE (Size
);
188 PoolHdr
->Available
= FALSE
;
189 *Buffer
= PoolHdr
+ 1;
193 Size
= (Size
+ MIN_POOL_SIZE
- 1) >> MIN_POOL_SHIFT
;
194 PoolIndex
= (UINTN
) HighBitSet32 ((UINT32
)Size
);
195 if ((Size
& (Size
- 1)) != 0) {
199 Status
= InternalAllocPoolByIndex (PoolIndex
, &FreePoolHdr
);
200 if (!EFI_ERROR (Status
)) {
201 *Buffer
= &FreePoolHdr
->Header
+ 1;
207 Allocate pool of a particular type.
209 @param PoolType Type of pool to allocate.
210 @param Size The amount of pool to allocate.
211 @param Buffer The address to return a pointer to the allocated
214 @retval EFI_INVALID_PARAMETER PoolType not valid.
215 @retval EFI_OUT_OF_RESOURCES Size exceeds max pool size or allocation failed.
216 @retval EFI_SUCCESS Pool successfully allocated.
222 IN EFI_MEMORY_TYPE PoolType
,
229 Status
= MmInternalAllocatePool (PoolType
, Size
, Buffer
);
236 @param Buffer The allocated pool entry to free.
238 @retval EFI_INVALID_PARAMETER Buffer is not a valid value.
239 @retval EFI_SUCCESS Pool successfully freed.
248 FREE_POOL_HEADER
*FreePoolHdr
;
250 if (Buffer
== NULL
) {
251 return EFI_INVALID_PARAMETER
;
254 FreePoolHdr
= (FREE_POOL_HEADER
*)((POOL_HEADER
*)Buffer
- 1);
255 ASSERT (!FreePoolHdr
->Header
.Available
);
257 if (FreePoolHdr
->Header
.Size
> MAX_POOL_SIZE
) {
258 ASSERT (((UINTN
)FreePoolHdr
& EFI_PAGE_MASK
) == 0);
259 ASSERT ((FreePoolHdr
->Header
.Size
& EFI_PAGE_MASK
) == 0);
260 return MmInternalFreePages (
261 (EFI_PHYSICAL_ADDRESS
)(UINTN
)FreePoolHdr
,
262 EFI_SIZE_TO_PAGES (FreePoolHdr
->Header
.Size
)
265 return InternalFreePoolByIndex (FreePoolHdr
);
271 @param Buffer The allocated pool entry to free.
273 @retval EFI_INVALID_PARAMETER Buffer is not a valid value.
274 @retval EFI_SUCCESS Pool successfully freed.
285 Status
= MmInternalFreePool (Buffer
);