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 This program and the accompanying materials are licensed and made available
7 under the terms and conditions of the BSD License which accompanies this
8 distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 #include "StandaloneMmCore.h"
18 LIST_ENTRY mMmPoolLists
[MAX_POOL_INDEX
];
20 // To cache the MMRAM base since when Loading modules At fixed address feature is enabled,
21 // all module is assigned an offset relative the MMRAM base in build time.
23 GLOBAL_REMOVE_IF_UNREFERENCED EFI_PHYSICAL_ADDRESS gLoadModuleAtFixAddressMmramBase
= 0;
26 Called to initialize the memory service.
28 @param MmramRangeCount Number of MMRAM Regions
29 @param MmramRanges Pointer to MMRAM Descriptors
33 MmInitializeMemoryServices (
34 IN UINTN MmramRangeCount
,
35 IN EFI_MMRAM_DESCRIPTOR
*MmramRanges
41 // Initialize Pool list
43 for (Index
= sizeof (mMmPoolLists
) / sizeof (*mMmPoolLists
); Index
> 0;) {
44 InitializeListHead (&mMmPoolLists
[--Index
]);
49 // Initialize free MMRAM regions
51 for (Index
= 0; Index
< MmramRangeCount
; Index
++) {
53 // BUGBUG: Add legacy MMRAM region is buggy.
55 if (MmramRanges
[Index
].CpuStart
< BASE_1MB
) {
58 DEBUG ((DEBUG_INFO
, "MmAddMemoryRegion %d : 0x%016lx - 0x%016lx\n",
59 Index
, MmramRanges
[Index
].CpuStart
, MmramRanges
[Index
].PhysicalSize
));
61 MmramRanges
[Index
].CpuStart
,
62 MmramRanges
[Index
].PhysicalSize
,
63 EfiConventionalMemory
,
64 MmramRanges
[Index
].RegionState
71 Internal Function. Allocate a pool by specified PoolIndex.
73 @param PoolIndex Index which indicate the Pool size.
74 @param FreePoolHdr The returned Free pool.
76 @retval EFI_OUT_OF_RESOURCES Allocation failed.
77 @retval EFI_SUCCESS Pool successfully allocated.
81 InternalAllocPoolByIndex (
83 OUT FREE_POOL_HEADER
**FreePoolHdr
87 FREE_POOL_HEADER
*Hdr
;
88 EFI_PHYSICAL_ADDRESS Address
;
90 ASSERT (PoolIndex
<= MAX_POOL_INDEX
);
93 if (PoolIndex
== MAX_POOL_INDEX
) {
94 Status
= MmInternalAllocatePages (
96 EfiRuntimeServicesData
,
97 EFI_SIZE_TO_PAGES (MAX_POOL_SIZE
<< 1),
100 if (EFI_ERROR (Status
)) {
101 return EFI_OUT_OF_RESOURCES
;
103 Hdr
= (FREE_POOL_HEADER
*) (UINTN
) Address
;
104 } else if (!IsListEmpty (&mMmPoolLists
[PoolIndex
])) {
105 Hdr
= BASE_CR (GetFirstNode (&mMmPoolLists
[PoolIndex
]), FREE_POOL_HEADER
, Link
);
106 RemoveEntryList (&Hdr
->Link
);
108 Status
= InternalAllocPoolByIndex (PoolIndex
+ 1, &Hdr
);
109 if (!EFI_ERROR (Status
)) {
110 Hdr
->Header
.Size
>>= 1;
111 Hdr
->Header
.Available
= TRUE
;
112 InsertHeadList (&mMmPoolLists
[PoolIndex
], &Hdr
->Link
);
113 Hdr
= (FREE_POOL_HEADER
*)((UINT8
*)Hdr
+ Hdr
->Header
.Size
);
117 if (!EFI_ERROR (Status
)) {
118 Hdr
->Header
.Size
= MIN_POOL_SIZE
<< PoolIndex
;
119 Hdr
->Header
.Available
= FALSE
;
127 Internal Function. Free a pool by specified PoolIndex.
129 @param FreePoolHdr The pool to free.
131 @retval EFI_SUCCESS Pool successfully freed.
135 InternalFreePoolByIndex (
136 IN FREE_POOL_HEADER
*FreePoolHdr
141 ASSERT ((FreePoolHdr
->Header
.Size
& (FreePoolHdr
->Header
.Size
- 1)) == 0);
142 ASSERT (((UINTN
)FreePoolHdr
& (FreePoolHdr
->Header
.Size
- 1)) == 0);
143 ASSERT (FreePoolHdr
->Header
.Size
>= MIN_POOL_SIZE
);
145 PoolIndex
= (UINTN
) (HighBitSet32 ((UINT32
)FreePoolHdr
->Header
.Size
) - MIN_POOL_SHIFT
);
146 FreePoolHdr
->Header
.Available
= TRUE
;
147 ASSERT (PoolIndex
< MAX_POOL_INDEX
);
148 InsertHeadList (&mMmPoolLists
[PoolIndex
], &FreePoolHdr
->Link
);
153 Allocate pool of a particular type.
155 @param PoolType Type of pool to allocate.
156 @param Size The amount of pool to allocate.
157 @param Buffer The address to return a pointer to the allocated
160 @retval EFI_INVALID_PARAMETER PoolType not valid.
161 @retval EFI_OUT_OF_RESOURCES Size exceeds max pool size or allocation failed.
162 @retval EFI_SUCCESS Pool successfully allocated.
167 MmInternalAllocatePool (
168 IN EFI_MEMORY_TYPE PoolType
,
173 POOL_HEADER
*PoolHdr
;
174 FREE_POOL_HEADER
*FreePoolHdr
;
176 EFI_PHYSICAL_ADDRESS Address
;
179 if (PoolType
!= EfiRuntimeServicesCode
&&
180 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;
213 Allocate pool of a particular type.
215 @param PoolType Type of pool to allocate.
216 @param Size The amount of pool to allocate.
217 @param Buffer The address to return a pointer to the allocated
220 @retval EFI_INVALID_PARAMETER PoolType not valid.
221 @retval EFI_OUT_OF_RESOURCES Size exceeds max pool size or allocation failed.
222 @retval EFI_SUCCESS Pool successfully allocated.
228 IN EFI_MEMORY_TYPE PoolType
,
235 Status
= MmInternalAllocatePool (PoolType
, Size
, Buffer
);
242 @param Buffer The allocated pool entry to free.
244 @retval EFI_INVALID_PARAMETER Buffer is not a valid value.
245 @retval EFI_SUCCESS Pool successfully freed.
254 FREE_POOL_HEADER
*FreePoolHdr
;
256 if (Buffer
== NULL
) {
257 return EFI_INVALID_PARAMETER
;
260 FreePoolHdr
= (FREE_POOL_HEADER
*)((POOL_HEADER
*)Buffer
- 1);
261 ASSERT (!FreePoolHdr
->Header
.Available
);
263 if (FreePoolHdr
->Header
.Size
> MAX_POOL_SIZE
) {
264 ASSERT (((UINTN
)FreePoolHdr
& EFI_PAGE_MASK
) == 0);
265 ASSERT ((FreePoolHdr
->Header
.Size
& EFI_PAGE_MASK
) == 0);
266 return MmInternalFreePages (
267 (EFI_PHYSICAL_ADDRESS
)(UINTN
)FreePoolHdr
,
268 EFI_SIZE_TO_PAGES (FreePoolHdr
->Header
.Size
)
271 return InternalFreePoolByIndex (FreePoolHdr
);
277 @param Buffer The allocated pool entry to free.
279 @retval EFI_INVALID_PARAMETER Buffer is not a valid value.
280 @retval EFI_SUCCESS Pool successfully freed.
291 Status
= MmInternalFreePool (Buffer
);