]> git.proxmox.com Git - mirror_edk2.git/blob - StandaloneMmPkg/Core/Pool.c
NetworkPkg: Move Network library header file from MdeModulePkg to NetworkPkg
[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 - 2018, 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 //
43 // Initialize free MMRAM regions
44 //
45 for (Index = 0; Index < MmramRangeCount; Index++) {
46 //
47 // BUGBUG: Add legacy MMRAM region is buggy.
48 //
49 if (MmramRanges[Index].CpuStart < BASE_1MB) {
50 continue;
51 }
52 DEBUG ((DEBUG_INFO, "MmAddMemoryRegion %d : 0x%016lx - 0x%016lx\n",
53 Index, MmramRanges[Index].CpuStart, MmramRanges[Index].PhysicalSize));
54 MmAddMemoryRegion (
55 MmramRanges[Index].CpuStart,
56 MmramRanges[Index].PhysicalSize,
57 EfiConventionalMemory,
58 MmramRanges[Index].RegionState
59 );
60 }
61
62 }
63
64 /**
65 Internal Function. Allocate a pool by specified PoolIndex.
66
67 @param PoolIndex Index which indicate the Pool size.
68 @param FreePoolHdr The returned Free pool.
69
70 @retval EFI_OUT_OF_RESOURCES Allocation failed.
71 @retval EFI_SUCCESS Pool successfully allocated.
72
73 **/
74 EFI_STATUS
75 InternalAllocPoolByIndex (
76 IN UINTN PoolIndex,
77 OUT FREE_POOL_HEADER **FreePoolHdr
78 )
79 {
80 EFI_STATUS Status;
81 FREE_POOL_HEADER *Hdr;
82 EFI_PHYSICAL_ADDRESS Address;
83
84 ASSERT (PoolIndex <= MAX_POOL_INDEX);
85 Status = EFI_SUCCESS;
86 Hdr = NULL;
87 if (PoolIndex == MAX_POOL_INDEX) {
88 Status = MmInternalAllocatePages (
89 AllocateAnyPages,
90 EfiRuntimeServicesData,
91 EFI_SIZE_TO_PAGES (MAX_POOL_SIZE << 1),
92 &Address
93 );
94 if (EFI_ERROR (Status)) {
95 return EFI_OUT_OF_RESOURCES;
96 }
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);
101 } else {
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);
108 }
109 }
110
111 if (!EFI_ERROR (Status)) {
112 Hdr->Header.Size = MIN_POOL_SIZE << PoolIndex;
113 Hdr->Header.Available = FALSE;
114 }
115
116 *FreePoolHdr = Hdr;
117 return Status;
118 }
119
120 /**
121 Internal Function. Free a pool by specified PoolIndex.
122
123 @param FreePoolHdr The pool to free.
124
125 @retval EFI_SUCCESS Pool successfully freed.
126
127 **/
128 EFI_STATUS
129 InternalFreePoolByIndex (
130 IN FREE_POOL_HEADER *FreePoolHdr
131 )
132 {
133 UINTN PoolIndex;
134
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);
138
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);
143 return EFI_SUCCESS;
144 }
145
146 /**
147 Allocate pool of a particular type.
148
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
152 pool.
153
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.
157
158 **/
159 EFI_STATUS
160 EFIAPI
161 MmInternalAllocatePool (
162 IN EFI_MEMORY_TYPE PoolType,
163 IN UINTN Size,
164 OUT VOID **Buffer
165 )
166 {
167 POOL_HEADER *PoolHdr;
168 FREE_POOL_HEADER *FreePoolHdr;
169 EFI_STATUS Status;
170 EFI_PHYSICAL_ADDRESS Address;
171 UINTN PoolIndex;
172
173 if (PoolType != EfiRuntimeServicesCode &&
174 PoolType != EfiRuntimeServicesData) {
175 return EFI_INVALID_PARAMETER;
176 }
177
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)) {
183 return Status;
184 }
185
186 PoolHdr = (POOL_HEADER*)(UINTN)Address;
187 PoolHdr->Size = EFI_PAGES_TO_SIZE (Size);
188 PoolHdr->Available = FALSE;
189 *Buffer = PoolHdr + 1;
190 return Status;
191 }
192
193 Size = (Size + MIN_POOL_SIZE - 1) >> MIN_POOL_SHIFT;
194 PoolIndex = (UINTN) HighBitSet32 ((UINT32)Size);
195 if ((Size & (Size - 1)) != 0) {
196 PoolIndex++;
197 }
198
199 Status = InternalAllocPoolByIndex (PoolIndex, &FreePoolHdr);
200 if (!EFI_ERROR (Status)) {
201 *Buffer = &FreePoolHdr->Header + 1;
202 }
203 return Status;
204 }
205
206 /**
207 Allocate pool of a particular type.
208
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
212 pool.
213
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.
217
218 **/
219 EFI_STATUS
220 EFIAPI
221 MmAllocatePool (
222 IN EFI_MEMORY_TYPE PoolType,
223 IN UINTN Size,
224 OUT VOID **Buffer
225 )
226 {
227 EFI_STATUS Status;
228
229 Status = MmInternalAllocatePool (PoolType, Size, Buffer);
230 return Status;
231 }
232
233 /**
234 Frees pool.
235
236 @param Buffer The allocated pool entry to free.
237
238 @retval EFI_INVALID_PARAMETER Buffer is not a valid value.
239 @retval EFI_SUCCESS Pool successfully freed.
240
241 **/
242 EFI_STATUS
243 EFIAPI
244 MmInternalFreePool (
245 IN VOID *Buffer
246 )
247 {
248 FREE_POOL_HEADER *FreePoolHdr;
249
250 if (Buffer == NULL) {
251 return EFI_INVALID_PARAMETER;
252 }
253
254 FreePoolHdr = (FREE_POOL_HEADER*)((POOL_HEADER*)Buffer - 1);
255 ASSERT (!FreePoolHdr->Header.Available);
256
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)
263 );
264 }
265 return InternalFreePoolByIndex (FreePoolHdr);
266 }
267
268 /**
269 Frees pool.
270
271 @param Buffer The allocated pool entry to free.
272
273 @retval EFI_INVALID_PARAMETER Buffer is not a valid value.
274 @retval EFI_SUCCESS Pool successfully freed.
275
276 **/
277 EFI_STATUS
278 EFIAPI
279 MmFreePool (
280 IN VOID *Buffer
281 )
282 {
283 EFI_STATUS Status;
284
285 Status = MmInternalFreePool (Buffer);
286 return Status;
287 }