]> git.proxmox.com Git - mirror_edk2.git/blame - StandaloneMmPkg/Core/Pool.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / StandaloneMmPkg / Core / Pool.c
CommitLineData
6b46d772
SV
1/** @file\r
2 SMM Memory pool management functions.\r
3\r
4 Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.<BR>\r
9ef62f50 5 Copyright (c) 2016 - 2021, Arm Limited. All rights reserved.<BR>\r
86094561 6 SPDX-License-Identifier: BSD-2-Clause-Patent\r
6b46d772
SV
7\r
8**/\r
9\r
10#include "StandaloneMmCore.h"\r
11\r
12LIST_ENTRY mMmPoolLists[MAX_POOL_INDEX];\r
13//\r
14// To cache the MMRAM base since when Loading modules At fixed address feature is enabled,\r
15// all module is assigned an offset relative the MMRAM base in build time.\r
16//\r
91415a36 17GLOBAL_REMOVE_IF_UNREFERENCED EFI_PHYSICAL_ADDRESS gLoadModuleAtFixAddressMmramBase = 0;\r
6b46d772
SV
18\r
19/**\r
20 Called to initialize the memory service.\r
21\r
22 @param MmramRangeCount Number of MMRAM Regions\r
23 @param MmramRanges Pointer to MMRAM Descriptors\r
24\r
25**/\r
26VOID\r
27MmInitializeMemoryServices (\r
28 IN UINTN MmramRangeCount,\r
29 IN EFI_MMRAM_DESCRIPTOR *MmramRanges\r
30 )\r
31{\r
91415a36 32 UINTN Index;\r
6b46d772
SV
33\r
34 //\r
35 // Initialize Pool list\r
36 //\r
37 for (Index = sizeof (mMmPoolLists) / sizeof (*mMmPoolLists); Index > 0;) {\r
38 InitializeListHead (&mMmPoolLists[--Index]);\r
39 }\r
40\r
6b46d772
SV
41 //\r
42 // Initialize free MMRAM regions\r
43 //\r
44 for (Index = 0; Index < MmramRangeCount; Index++) {\r
45 //\r
46 // BUGBUG: Add legacy MMRAM region is buggy.\r
47 //\r
48 if (MmramRanges[Index].CpuStart < BASE_1MB) {\r
49 continue;\r
50 }\r
91415a36
MK
51\r
52 DEBUG ((\r
53 DEBUG_INFO,\r
54 "MmAddMemoryRegion %d : 0x%016lx - 0x%016lx\n",\r
55 Index,\r
56 MmramRanges[Index].CpuStart,\r
57 MmramRanges[Index].PhysicalSize\r
58 ));\r
6b46d772
SV
59 MmAddMemoryRegion (\r
60 MmramRanges[Index].CpuStart,\r
61 MmramRanges[Index].PhysicalSize,\r
62 EfiConventionalMemory,\r
63 MmramRanges[Index].RegionState\r
64 );\r
65 }\r
6b46d772
SV
66}\r
67\r
68/**\r
69 Internal Function. Allocate a pool by specified PoolIndex.\r
70\r
71 @param PoolIndex Index which indicate the Pool size.\r
72 @param FreePoolHdr The returned Free pool.\r
73\r
74 @retval EFI_OUT_OF_RESOURCES Allocation failed.\r
75 @retval EFI_SUCCESS Pool successfully allocated.\r
76\r
77**/\r
78EFI_STATUS\r
79InternalAllocPoolByIndex (\r
80 IN UINTN PoolIndex,\r
81 OUT FREE_POOL_HEADER **FreePoolHdr\r
82 )\r
83{\r
84 EFI_STATUS Status;\r
85 FREE_POOL_HEADER *Hdr;\r
86 EFI_PHYSICAL_ADDRESS Address;\r
87\r
88 ASSERT (PoolIndex <= MAX_POOL_INDEX);\r
89 Status = EFI_SUCCESS;\r
91415a36 90 Hdr = NULL;\r
6b46d772
SV
91 if (PoolIndex == MAX_POOL_INDEX) {\r
92 Status = MmInternalAllocatePages (\r
9ef62f50 93 AllocateAnyPages,\r
6b46d772
SV
94 EfiRuntimeServicesData,\r
95 EFI_SIZE_TO_PAGES (MAX_POOL_SIZE << 1),\r
96 &Address\r
97 );\r
98 if (EFI_ERROR (Status)) {\r
99 return EFI_OUT_OF_RESOURCES;\r
100 }\r
91415a36
MK
101\r
102 Hdr = (FREE_POOL_HEADER *)(UINTN)Address;\r
6b46d772
SV
103 } else if (!IsListEmpty (&mMmPoolLists[PoolIndex])) {\r
104 Hdr = BASE_CR (GetFirstNode (&mMmPoolLists[PoolIndex]), FREE_POOL_HEADER, Link);\r
105 RemoveEntryList (&Hdr->Link);\r
106 } else {\r
107 Status = InternalAllocPoolByIndex (PoolIndex + 1, &Hdr);\r
108 if (!EFI_ERROR (Status)) {\r
91415a36 109 Hdr->Header.Size >>= 1;\r
6b46d772
SV
110 Hdr->Header.Available = TRUE;\r
111 InsertHeadList (&mMmPoolLists[PoolIndex], &Hdr->Link);\r
91415a36 112 Hdr = (FREE_POOL_HEADER *)((UINT8 *)Hdr + Hdr->Header.Size);\r
6b46d772
SV
113 }\r
114 }\r
115\r
116 if (!EFI_ERROR (Status)) {\r
91415a36 117 Hdr->Header.Size = MIN_POOL_SIZE << PoolIndex;\r
6b46d772
SV
118 Hdr->Header.Available = FALSE;\r
119 }\r
120\r
121 *FreePoolHdr = Hdr;\r
122 return Status;\r
123}\r
124\r
125/**\r
126 Internal Function. Free a pool by specified PoolIndex.\r
127\r
128 @param FreePoolHdr The pool to free.\r
129\r
130 @retval EFI_SUCCESS Pool successfully freed.\r
131\r
132**/\r
133EFI_STATUS\r
134InternalFreePoolByIndex (\r
135 IN FREE_POOL_HEADER *FreePoolHdr\r
136 )\r
137{\r
138 UINTN PoolIndex;\r
139\r
140 ASSERT ((FreePoolHdr->Header.Size & (FreePoolHdr->Header.Size - 1)) == 0);\r
141 ASSERT (((UINTN)FreePoolHdr & (FreePoolHdr->Header.Size - 1)) == 0);\r
142 ASSERT (FreePoolHdr->Header.Size >= MIN_POOL_SIZE);\r
143\r
91415a36 144 PoolIndex = (UINTN)(HighBitSet32 ((UINT32)FreePoolHdr->Header.Size) - MIN_POOL_SHIFT);\r
6b46d772
SV
145 FreePoolHdr->Header.Available = TRUE;\r
146 ASSERT (PoolIndex < MAX_POOL_INDEX);\r
147 InsertHeadList (&mMmPoolLists[PoolIndex], &FreePoolHdr->Link);\r
148 return EFI_SUCCESS;\r
149}\r
150\r
151/**\r
152 Allocate pool of a particular type.\r
153\r
154 @param PoolType Type of pool to allocate.\r
155 @param Size The amount of pool to allocate.\r
156 @param Buffer The address to return a pointer to the allocated\r
157 pool.\r
158\r
159 @retval EFI_INVALID_PARAMETER PoolType not valid.\r
160 @retval EFI_OUT_OF_RESOURCES Size exceeds max pool size or allocation failed.\r
161 @retval EFI_SUCCESS Pool successfully allocated.\r
162\r
163**/\r
164EFI_STATUS\r
165EFIAPI\r
166MmInternalAllocatePool (\r
167 IN EFI_MEMORY_TYPE PoolType,\r
168 IN UINTN Size,\r
169 OUT VOID **Buffer\r
170 )\r
171{\r
172 POOL_HEADER *PoolHdr;\r
173 FREE_POOL_HEADER *FreePoolHdr;\r
174 EFI_STATUS Status;\r
175 EFI_PHYSICAL_ADDRESS Address;\r
176 UINTN PoolIndex;\r
177\r
91415a36
MK
178 if ((PoolType != EfiRuntimeServicesCode) &&\r
179 (PoolType != EfiRuntimeServicesData))\r
180 {\r
6b46d772
SV
181 return EFI_INVALID_PARAMETER;\r
182 }\r
183\r
184 Size += sizeof (*PoolHdr);\r
185 if (Size > MAX_POOL_SIZE) {\r
91415a36 186 Size = EFI_SIZE_TO_PAGES (Size);\r
6b46d772
SV
187 Status = MmInternalAllocatePages (AllocateAnyPages, PoolType, Size, &Address);\r
188 if (EFI_ERROR (Status)) {\r
189 return Status;\r
190 }\r
191\r
91415a36
MK
192 PoolHdr = (POOL_HEADER *)(UINTN)Address;\r
193 PoolHdr->Size = EFI_PAGES_TO_SIZE (Size);\r
6b46d772 194 PoolHdr->Available = FALSE;\r
91415a36 195 *Buffer = PoolHdr + 1;\r
6b46d772
SV
196 return Status;\r
197 }\r
198\r
91415a36
MK
199 Size = (Size + MIN_POOL_SIZE - 1) >> MIN_POOL_SHIFT;\r
200 PoolIndex = (UINTN)HighBitSet32 ((UINT32)Size);\r
6b46d772
SV
201 if ((Size & (Size - 1)) != 0) {\r
202 PoolIndex++;\r
203 }\r
204\r
205 Status = InternalAllocPoolByIndex (PoolIndex, &FreePoolHdr);\r
206 if (!EFI_ERROR (Status)) {\r
207 *Buffer = &FreePoolHdr->Header + 1;\r
208 }\r
91415a36 209\r
6b46d772
SV
210 return Status;\r
211}\r
212\r
213/**\r
214 Allocate pool of a particular type.\r
215\r
216 @param PoolType Type of pool to allocate.\r
217 @param Size The amount of pool to allocate.\r
218 @param Buffer The address to return a pointer to the allocated\r
219 pool.\r
220\r
221 @retval EFI_INVALID_PARAMETER PoolType not valid.\r
222 @retval EFI_OUT_OF_RESOURCES Size exceeds max pool size or allocation failed.\r
223 @retval EFI_SUCCESS Pool successfully allocated.\r
224\r
225**/\r
226EFI_STATUS\r
227EFIAPI\r
228MmAllocatePool (\r
229 IN EFI_MEMORY_TYPE PoolType,\r
230 IN UINTN Size,\r
231 OUT VOID **Buffer\r
232 )\r
233{\r
234 EFI_STATUS Status;\r
235\r
236 Status = MmInternalAllocatePool (PoolType, Size, Buffer);\r
237 return Status;\r
238}\r
239\r
240/**\r
241 Frees pool.\r
242\r
243 @param Buffer The allocated pool entry to free.\r
244\r
245 @retval EFI_INVALID_PARAMETER Buffer is not a valid value.\r
246 @retval EFI_SUCCESS Pool successfully freed.\r
247\r
248**/\r
249EFI_STATUS\r
250EFIAPI\r
251MmInternalFreePool (\r
252 IN VOID *Buffer\r
253 )\r
254{\r
255 FREE_POOL_HEADER *FreePoolHdr;\r
256\r
257 if (Buffer == NULL) {\r
258 return EFI_INVALID_PARAMETER;\r
259 }\r
260\r
91415a36 261 FreePoolHdr = (FREE_POOL_HEADER *)((POOL_HEADER *)Buffer - 1);\r
6b46d772
SV
262 ASSERT (!FreePoolHdr->Header.Available);\r
263\r
264 if (FreePoolHdr->Header.Size > MAX_POOL_SIZE) {\r
265 ASSERT (((UINTN)FreePoolHdr & EFI_PAGE_MASK) == 0);\r
266 ASSERT ((FreePoolHdr->Header.Size & EFI_PAGE_MASK) == 0);\r
267 return MmInternalFreePages (\r
268 (EFI_PHYSICAL_ADDRESS)(UINTN)FreePoolHdr,\r
269 EFI_SIZE_TO_PAGES (FreePoolHdr->Header.Size)\r
270 );\r
271 }\r
91415a36 272\r
6b46d772
SV
273 return InternalFreePoolByIndex (FreePoolHdr);\r
274}\r
275\r
276/**\r
277 Frees pool.\r
278\r
279 @param Buffer The allocated pool entry to free.\r
280\r
281 @retval EFI_INVALID_PARAMETER Buffer is not a valid value.\r
282 @retval EFI_SUCCESS Pool successfully freed.\r
283\r
284**/\r
285EFI_STATUS\r
286EFIAPI\r
287MmFreePool (\r
288 IN VOID *Buffer\r
289 )\r
290{\r
291 EFI_STATUS Status;\r
292\r
293 Status = MmInternalFreePool (Buffer);\r
294 return Status;\r
295}\r