]> git.proxmox.com Git - mirror_edk2.git/blob - StandaloneMmPkg/Core/Pool.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / StandaloneMmPkg / Core / Pool.c
1 /** @file
2 SMM Memory pool management functions.
3
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
7
8 **/
9
10 #include "StandaloneMmCore.h"
11
12 LIST_ENTRY mMmPoolLists[MAX_POOL_INDEX];
13 //
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.
16 //
17 GLOBAL_REMOVE_IF_UNREFERENCED EFI_PHYSICAL_ADDRESS gLoadModuleAtFixAddressMmramBase = 0;
18
19 /**
20 Called to initialize the memory service.
21
22 @param MmramRangeCount Number of MMRAM Regions
23 @param MmramRanges Pointer to MMRAM Descriptors
24
25 **/
26 VOID
27 MmInitializeMemoryServices (
28 IN UINTN MmramRangeCount,
29 IN EFI_MMRAM_DESCRIPTOR *MmramRanges
30 )
31 {
32 UINTN Index;
33
34 //
35 // Initialize Pool list
36 //
37 for (Index = sizeof (mMmPoolLists) / sizeof (*mMmPoolLists); Index > 0;) {
38 InitializeListHead (&mMmPoolLists[--Index]);
39 }
40
41 //
42 // Initialize free MMRAM regions
43 //
44 for (Index = 0; Index < MmramRangeCount; Index++) {
45 //
46 // BUGBUG: Add legacy MMRAM region is buggy.
47 //
48 if (MmramRanges[Index].CpuStart < BASE_1MB) {
49 continue;
50 }
51
52 DEBUG ((
53 DEBUG_INFO,
54 "MmAddMemoryRegion %d : 0x%016lx - 0x%016lx\n",
55 Index,
56 MmramRanges[Index].CpuStart,
57 MmramRanges[Index].PhysicalSize
58 ));
59 MmAddMemoryRegion (
60 MmramRanges[Index].CpuStart,
61 MmramRanges[Index].PhysicalSize,
62 EfiConventionalMemory,
63 MmramRanges[Index].RegionState
64 );
65 }
66 }
67
68 /**
69 Internal Function. Allocate a pool by specified PoolIndex.
70
71 @param PoolIndex Index which indicate the Pool size.
72 @param FreePoolHdr The returned Free pool.
73
74 @retval EFI_OUT_OF_RESOURCES Allocation failed.
75 @retval EFI_SUCCESS Pool successfully allocated.
76
77 **/
78 EFI_STATUS
79 InternalAllocPoolByIndex (
80 IN UINTN PoolIndex,
81 OUT FREE_POOL_HEADER **FreePoolHdr
82 )
83 {
84 EFI_STATUS Status;
85 FREE_POOL_HEADER *Hdr;
86 EFI_PHYSICAL_ADDRESS Address;
87
88 ASSERT (PoolIndex <= MAX_POOL_INDEX);
89 Status = EFI_SUCCESS;
90 Hdr = NULL;
91 if (PoolIndex == MAX_POOL_INDEX) {
92 Status = MmInternalAllocatePages (
93 AllocateAnyPages,
94 EfiRuntimeServicesData,
95 EFI_SIZE_TO_PAGES (MAX_POOL_SIZE << 1),
96 &Address
97 );
98 if (EFI_ERROR (Status)) {
99 return EFI_OUT_OF_RESOURCES;
100 }
101
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);
106 } else {
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);
113 }
114 }
115
116 if (!EFI_ERROR (Status)) {
117 Hdr->Header.Size = MIN_POOL_SIZE << PoolIndex;
118 Hdr->Header.Available = FALSE;
119 }
120
121 *FreePoolHdr = Hdr;
122 return Status;
123 }
124
125 /**
126 Internal Function. Free a pool by specified PoolIndex.
127
128 @param FreePoolHdr The pool to free.
129
130 @retval EFI_SUCCESS Pool successfully freed.
131
132 **/
133 EFI_STATUS
134 InternalFreePoolByIndex (
135 IN FREE_POOL_HEADER *FreePoolHdr
136 )
137 {
138 UINTN PoolIndex;
139
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);
143
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);
148 return EFI_SUCCESS;
149 }
150
151 /**
152 Allocate pool of a particular type.
153
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
157 pool.
158
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.
162
163 **/
164 EFI_STATUS
165 EFIAPI
166 MmInternalAllocatePool (
167 IN EFI_MEMORY_TYPE PoolType,
168 IN UINTN Size,
169 OUT VOID **Buffer
170 )
171 {
172 POOL_HEADER *PoolHdr;
173 FREE_POOL_HEADER *FreePoolHdr;
174 EFI_STATUS Status;
175 EFI_PHYSICAL_ADDRESS Address;
176 UINTN PoolIndex;
177
178 if ((PoolType != EfiRuntimeServicesCode) &&
179 (PoolType != EfiRuntimeServicesData))
180 {
181 return EFI_INVALID_PARAMETER;
182 }
183
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)) {
189 return Status;
190 }
191
192 PoolHdr = (POOL_HEADER *)(UINTN)Address;
193 PoolHdr->Size = EFI_PAGES_TO_SIZE (Size);
194 PoolHdr->Available = FALSE;
195 *Buffer = PoolHdr + 1;
196 return Status;
197 }
198
199 Size = (Size + MIN_POOL_SIZE - 1) >> MIN_POOL_SHIFT;
200 PoolIndex = (UINTN)HighBitSet32 ((UINT32)Size);
201 if ((Size & (Size - 1)) != 0) {
202 PoolIndex++;
203 }
204
205 Status = InternalAllocPoolByIndex (PoolIndex, &FreePoolHdr);
206 if (!EFI_ERROR (Status)) {
207 *Buffer = &FreePoolHdr->Header + 1;
208 }
209
210 return Status;
211 }
212
213 /**
214 Allocate pool of a particular type.
215
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
219 pool.
220
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.
224
225 **/
226 EFI_STATUS
227 EFIAPI
228 MmAllocatePool (
229 IN EFI_MEMORY_TYPE PoolType,
230 IN UINTN Size,
231 OUT VOID **Buffer
232 )
233 {
234 EFI_STATUS Status;
235
236 Status = MmInternalAllocatePool (PoolType, Size, Buffer);
237 return Status;
238 }
239
240 /**
241 Frees pool.
242
243 @param Buffer The allocated pool entry to free.
244
245 @retval EFI_INVALID_PARAMETER Buffer is not a valid value.
246 @retval EFI_SUCCESS Pool successfully freed.
247
248 **/
249 EFI_STATUS
250 EFIAPI
251 MmInternalFreePool (
252 IN VOID *Buffer
253 )
254 {
255 FREE_POOL_HEADER *FreePoolHdr;
256
257 if (Buffer == NULL) {
258 return EFI_INVALID_PARAMETER;
259 }
260
261 FreePoolHdr = (FREE_POOL_HEADER *)((POOL_HEADER *)Buffer - 1);
262 ASSERT (!FreePoolHdr->Header.Available);
263
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)
270 );
271 }
272
273 return InternalFreePoolByIndex (FreePoolHdr);
274 }
275
276 /**
277 Frees pool.
278
279 @param Buffer The allocated pool entry to free.
280
281 @retval EFI_INVALID_PARAMETER Buffer is not a valid value.
282 @retval EFI_SUCCESS Pool successfully freed.
283
284 **/
285 EFI_STATUS
286 EFIAPI
287 MmFreePool (
288 IN VOID *Buffer
289 )
290 {
291 EFI_STATUS Status;
292
293 Status = MmInternalFreePool (Buffer);
294 return Status;
295 }