]> git.proxmox.com Git - mirror_edk2.git/blame - StandaloneMmPkg/Core/Pool.c
SourceLevelDebugPkg: Apply uncrustify changes
[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
17GLOBAL_REMOVE_IF_UNREFERENCED EFI_PHYSICAL_ADDRESS gLoadModuleAtFixAddressMmramBase = 0;\r
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
32 UINTN Index;\r
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
41\r
42 //\r
43 // Initialize free MMRAM regions\r
44 //\r
45 for (Index = 0; Index < MmramRangeCount; Index++) {\r
46 //\r
47 // BUGBUG: Add legacy MMRAM region is buggy.\r
48 //\r
49 if (MmramRanges[Index].CpuStart < BASE_1MB) {\r
50 continue;\r
51 }\r
52 DEBUG ((DEBUG_INFO, "MmAddMemoryRegion %d : 0x%016lx - 0x%016lx\n",\r
9ef62f50 53 Index, MmramRanges[Index].CpuStart, MmramRanges[Index].PhysicalSize));\r
6b46d772
SV
54 MmAddMemoryRegion (\r
55 MmramRanges[Index].CpuStart,\r
56 MmramRanges[Index].PhysicalSize,\r
57 EfiConventionalMemory,\r
58 MmramRanges[Index].RegionState\r
59 );\r
60 }\r
61\r
62}\r
63\r
64/**\r
65 Internal Function. Allocate a pool by specified PoolIndex.\r
66\r
67 @param PoolIndex Index which indicate the Pool size.\r
68 @param FreePoolHdr The returned Free pool.\r
69\r
70 @retval EFI_OUT_OF_RESOURCES Allocation failed.\r
71 @retval EFI_SUCCESS Pool successfully allocated.\r
72\r
73**/\r
74EFI_STATUS\r
75InternalAllocPoolByIndex (\r
76 IN UINTN PoolIndex,\r
77 OUT FREE_POOL_HEADER **FreePoolHdr\r
78 )\r
79{\r
80 EFI_STATUS Status;\r
81 FREE_POOL_HEADER *Hdr;\r
82 EFI_PHYSICAL_ADDRESS Address;\r
83\r
84 ASSERT (PoolIndex <= MAX_POOL_INDEX);\r
85 Status = EFI_SUCCESS;\r
86 Hdr = NULL;\r
87 if (PoolIndex == MAX_POOL_INDEX) {\r
88 Status = MmInternalAllocatePages (\r
9ef62f50 89 AllocateAnyPages,\r
6b46d772
SV
90 EfiRuntimeServicesData,\r
91 EFI_SIZE_TO_PAGES (MAX_POOL_SIZE << 1),\r
92 &Address\r
93 );\r
94 if (EFI_ERROR (Status)) {\r
95 return EFI_OUT_OF_RESOURCES;\r
96 }\r
97 Hdr = (FREE_POOL_HEADER *) (UINTN) Address;\r
98 } else if (!IsListEmpty (&mMmPoolLists[PoolIndex])) {\r
99 Hdr = BASE_CR (GetFirstNode (&mMmPoolLists[PoolIndex]), FREE_POOL_HEADER, Link);\r
100 RemoveEntryList (&Hdr->Link);\r
101 } else {\r
102 Status = InternalAllocPoolByIndex (PoolIndex + 1, &Hdr);\r
103 if (!EFI_ERROR (Status)) {\r
104 Hdr->Header.Size >>= 1;\r
105 Hdr->Header.Available = TRUE;\r
106 InsertHeadList (&mMmPoolLists[PoolIndex], &Hdr->Link);\r
107 Hdr = (FREE_POOL_HEADER*)((UINT8*)Hdr + Hdr->Header.Size);\r
108 }\r
109 }\r
110\r
111 if (!EFI_ERROR (Status)) {\r
112 Hdr->Header.Size = MIN_POOL_SIZE << PoolIndex;\r
113 Hdr->Header.Available = FALSE;\r
114 }\r
115\r
116 *FreePoolHdr = Hdr;\r
117 return Status;\r
118}\r
119\r
120/**\r
121 Internal Function. Free a pool by specified PoolIndex.\r
122\r
123 @param FreePoolHdr The pool to free.\r
124\r
125 @retval EFI_SUCCESS Pool successfully freed.\r
126\r
127**/\r
128EFI_STATUS\r
129InternalFreePoolByIndex (\r
130 IN FREE_POOL_HEADER *FreePoolHdr\r
131 )\r
132{\r
133 UINTN PoolIndex;\r
134\r
135 ASSERT ((FreePoolHdr->Header.Size & (FreePoolHdr->Header.Size - 1)) == 0);\r
136 ASSERT (((UINTN)FreePoolHdr & (FreePoolHdr->Header.Size - 1)) == 0);\r
137 ASSERT (FreePoolHdr->Header.Size >= MIN_POOL_SIZE);\r
138\r
139 PoolIndex = (UINTN) (HighBitSet32 ((UINT32)FreePoolHdr->Header.Size) - MIN_POOL_SHIFT);\r
140 FreePoolHdr->Header.Available = TRUE;\r
141 ASSERT (PoolIndex < MAX_POOL_INDEX);\r
142 InsertHeadList (&mMmPoolLists[PoolIndex], &FreePoolHdr->Link);\r
143 return EFI_SUCCESS;\r
144}\r
145\r
146/**\r
147 Allocate pool of a particular type.\r
148\r
149 @param PoolType Type of pool to allocate.\r
150 @param Size The amount of pool to allocate.\r
151 @param Buffer The address to return a pointer to the allocated\r
152 pool.\r
153\r
154 @retval EFI_INVALID_PARAMETER PoolType not valid.\r
155 @retval EFI_OUT_OF_RESOURCES Size exceeds max pool size or allocation failed.\r
156 @retval EFI_SUCCESS Pool successfully allocated.\r
157\r
158**/\r
159EFI_STATUS\r
160EFIAPI\r
161MmInternalAllocatePool (\r
162 IN EFI_MEMORY_TYPE PoolType,\r
163 IN UINTN Size,\r
164 OUT VOID **Buffer\r
165 )\r
166{\r
167 POOL_HEADER *PoolHdr;\r
168 FREE_POOL_HEADER *FreePoolHdr;\r
169 EFI_STATUS Status;\r
170 EFI_PHYSICAL_ADDRESS Address;\r
171 UINTN PoolIndex;\r
172\r
173 if (PoolType != EfiRuntimeServicesCode &&\r
174 PoolType != EfiRuntimeServicesData) {\r
175 return EFI_INVALID_PARAMETER;\r
176 }\r
177\r
178 Size += sizeof (*PoolHdr);\r
179 if (Size > MAX_POOL_SIZE) {\r
180 Size = EFI_SIZE_TO_PAGES (Size);\r
181 Status = MmInternalAllocatePages (AllocateAnyPages, PoolType, Size, &Address);\r
182 if (EFI_ERROR (Status)) {\r
183 return Status;\r
184 }\r
185\r
186 PoolHdr = (POOL_HEADER*)(UINTN)Address;\r
187 PoolHdr->Size = EFI_PAGES_TO_SIZE (Size);\r
188 PoolHdr->Available = FALSE;\r
189 *Buffer = PoolHdr + 1;\r
190 return Status;\r
191 }\r
192\r
193 Size = (Size + MIN_POOL_SIZE - 1) >> MIN_POOL_SHIFT;\r
194 PoolIndex = (UINTN) HighBitSet32 ((UINT32)Size);\r
195 if ((Size & (Size - 1)) != 0) {\r
196 PoolIndex++;\r
197 }\r
198\r
199 Status = InternalAllocPoolByIndex (PoolIndex, &FreePoolHdr);\r
200 if (!EFI_ERROR (Status)) {\r
201 *Buffer = &FreePoolHdr->Header + 1;\r
202 }\r
203 return Status;\r
204}\r
205\r
206/**\r
207 Allocate pool of a particular type.\r
208\r
209 @param PoolType Type of pool to allocate.\r
210 @param Size The amount of pool to allocate.\r
211 @param Buffer The address to return a pointer to the allocated\r
212 pool.\r
213\r
214 @retval EFI_INVALID_PARAMETER PoolType not valid.\r
215 @retval EFI_OUT_OF_RESOURCES Size exceeds max pool size or allocation failed.\r
216 @retval EFI_SUCCESS Pool successfully allocated.\r
217\r
218**/\r
219EFI_STATUS\r
220EFIAPI\r
221MmAllocatePool (\r
222 IN EFI_MEMORY_TYPE PoolType,\r
223 IN UINTN Size,\r
224 OUT VOID **Buffer\r
225 )\r
226{\r
227 EFI_STATUS Status;\r
228\r
229 Status = MmInternalAllocatePool (PoolType, Size, Buffer);\r
230 return Status;\r
231}\r
232\r
233/**\r
234 Frees pool.\r
235\r
236 @param Buffer The allocated pool entry to free.\r
237\r
238 @retval EFI_INVALID_PARAMETER Buffer is not a valid value.\r
239 @retval EFI_SUCCESS Pool successfully freed.\r
240\r
241**/\r
242EFI_STATUS\r
243EFIAPI\r
244MmInternalFreePool (\r
245 IN VOID *Buffer\r
246 )\r
247{\r
248 FREE_POOL_HEADER *FreePoolHdr;\r
249\r
250 if (Buffer == NULL) {\r
251 return EFI_INVALID_PARAMETER;\r
252 }\r
253\r
254 FreePoolHdr = (FREE_POOL_HEADER*)((POOL_HEADER*)Buffer - 1);\r
255 ASSERT (!FreePoolHdr->Header.Available);\r
256\r
257 if (FreePoolHdr->Header.Size > MAX_POOL_SIZE) {\r
258 ASSERT (((UINTN)FreePoolHdr & EFI_PAGE_MASK) == 0);\r
259 ASSERT ((FreePoolHdr->Header.Size & EFI_PAGE_MASK) == 0);\r
260 return MmInternalFreePages (\r
261 (EFI_PHYSICAL_ADDRESS)(UINTN)FreePoolHdr,\r
262 EFI_SIZE_TO_PAGES (FreePoolHdr->Header.Size)\r
263 );\r
264 }\r
265 return InternalFreePoolByIndex (FreePoolHdr);\r
266}\r
267\r
268/**\r
269 Frees pool.\r
270\r
271 @param Buffer The allocated pool entry to free.\r
272\r
273 @retval EFI_INVALID_PARAMETER Buffer is not a valid value.\r
274 @retval EFI_SUCCESS Pool successfully freed.\r
275\r
276**/\r
277EFI_STATUS\r
278EFIAPI\r
279MmFreePool (\r
280 IN VOID *Buffer\r
281 )\r
282{\r
283 EFI_STATUS Status;\r
284\r
285 Status = MmInternalFreePool (Buffer);\r
286 return Status;\r
287}\r