]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Core/PiSmmCore/Pool.c
MdeModulePkg/PiSmmCore: Fix potentially uninitialized local variable
[mirror_edk2.git] / MdeModulePkg / Core / PiSmmCore / Pool.c
1 /** @file
2 SMM Memory pool management functions.
3
4 Copyright (c) 2009 - 2017, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials are licensed and made available
6 under the terms and conditions of the BSD License which accompanies this
7 distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 **/
14
15 #include "PiSmmCore.h"
16
17 LIST_ENTRY mSmmPoolLists[SmmPoolTypeMax][MAX_POOL_INDEX];
18 //
19 // To cache the SMRAM base since when Loading modules At fixed address feature is enabled,
20 // all module is assigned an offset relative the SMRAM base in build time.
21 //
22 GLOBAL_REMOVE_IF_UNREFERENCED EFI_PHYSICAL_ADDRESS gLoadModuleAtFixAddressSmramBase = 0;
23
24 /**
25 Convert a UEFI memory type to SMM pool type.
26
27 @param[in] MemoryType Type of pool to allocate.
28
29 @return SMM pool type
30 **/
31 SMM_POOL_TYPE
32 UefiMemoryTypeToSmmPoolType (
33 IN EFI_MEMORY_TYPE MemoryType
34 )
35 {
36 ASSERT ((MemoryType == EfiRuntimeServicesCode) || (MemoryType == EfiRuntimeServicesData));
37 switch (MemoryType) {
38 case EfiRuntimeServicesCode:
39 return SmmPoolTypeCode;
40 case EfiRuntimeServicesData:
41 return SmmPoolTypeData;
42 default:
43 return SmmPoolTypeMax;
44 }
45 }
46
47
48 /**
49 Called to initialize the memory service.
50
51 @param SmramRangeCount Number of SMRAM Regions
52 @param SmramRanges Pointer to SMRAM Descriptors
53
54 **/
55 VOID
56 SmmInitializeMemoryServices (
57 IN UINTN SmramRangeCount,
58 IN EFI_SMRAM_DESCRIPTOR *SmramRanges
59 )
60 {
61 UINTN Index;
62 EFI_STATUS Status;
63 UINTN SmmPoolTypeIndex;
64 EFI_LOAD_FIXED_ADDRESS_CONFIGURATION_TABLE *LMFAConfigurationTable;
65
66 //
67 // Initialize Pool list
68 //
69 for (SmmPoolTypeIndex = 0; SmmPoolTypeIndex < SmmPoolTypeMax; SmmPoolTypeIndex++) {
70 for (Index = 0; Index < ARRAY_SIZE (mSmmPoolLists[SmmPoolTypeIndex]); Index++) {
71 InitializeListHead (&mSmmPoolLists[SmmPoolTypeIndex][Index]);
72 }
73 }
74
75 Status = EfiGetSystemConfigurationTable (
76 &gLoadFixedAddressConfigurationTableGuid,
77 (VOID **) &LMFAConfigurationTable
78 );
79 if (!EFI_ERROR (Status) && LMFAConfigurationTable != NULL) {
80 gLoadModuleAtFixAddressSmramBase = LMFAConfigurationTable->SmramBase;
81 }
82
83 //
84 // Add Free SMRAM regions
85 // Need add Free memory at first, to let gSmmMemoryMap record data
86 //
87 for (Index = 0; Index < SmramRangeCount; Index++) {
88 if ((SmramRanges[Index].RegionState & (EFI_ALLOCATED | EFI_NEEDS_TESTING | EFI_NEEDS_ECC_INITIALIZATION)) != 0) {
89 continue;
90 }
91 SmmAddMemoryRegion (
92 SmramRanges[Index].CpuStart,
93 SmramRanges[Index].PhysicalSize,
94 EfiConventionalMemory,
95 SmramRanges[Index].RegionState
96 );
97 }
98
99 //
100 // Add the allocated SMRAM regions
101 //
102 for (Index = 0; Index < SmramRangeCount; Index++) {
103 if ((SmramRanges[Index].RegionState & (EFI_ALLOCATED | EFI_NEEDS_TESTING | EFI_NEEDS_ECC_INITIALIZATION)) == 0) {
104 continue;
105 }
106 SmmAddMemoryRegion (
107 SmramRanges[Index].CpuStart,
108 SmramRanges[Index].PhysicalSize,
109 EfiConventionalMemory,
110 SmramRanges[Index].RegionState
111 );
112 }
113
114 }
115
116 /**
117 Internal Function. Allocate a pool by specified PoolIndex.
118
119 @param PoolType Type of pool to allocate.
120 @param PoolIndex Index which indicate the Pool size.
121 @param FreePoolHdr The returned Free pool.
122
123 @retval EFI_OUT_OF_RESOURCES Allocation failed.
124 @retval EFI_SUCCESS Pool successfully allocated.
125
126 **/
127 EFI_STATUS
128 InternalAllocPoolByIndex (
129 IN EFI_MEMORY_TYPE PoolType,
130 IN UINTN PoolIndex,
131 OUT FREE_POOL_HEADER **FreePoolHdr
132 )
133 {
134 EFI_STATUS Status;
135 FREE_POOL_HEADER *Hdr;
136 EFI_PHYSICAL_ADDRESS Address;
137 SMM_POOL_TYPE SmmPoolType;
138
139 Address = 0;
140 SmmPoolType = UefiMemoryTypeToSmmPoolType(PoolType);
141
142 ASSERT (PoolIndex <= MAX_POOL_INDEX);
143 Status = EFI_SUCCESS;
144 Hdr = NULL;
145 if (PoolIndex == MAX_POOL_INDEX) {
146 Status = SmmInternalAllocatePages (AllocateAnyPages, PoolType, EFI_SIZE_TO_PAGES (MAX_POOL_SIZE << 1), &Address);
147 if (EFI_ERROR (Status)) {
148 return EFI_OUT_OF_RESOURCES;
149 }
150 Hdr = (FREE_POOL_HEADER *) (UINTN) Address;
151 } else if (!IsListEmpty (&mSmmPoolLists[SmmPoolType][PoolIndex])) {
152 Hdr = BASE_CR (GetFirstNode (&mSmmPoolLists[SmmPoolType][PoolIndex]), FREE_POOL_HEADER, Link);
153 RemoveEntryList (&Hdr->Link);
154 } else {
155 Status = InternalAllocPoolByIndex (PoolType, PoolIndex + 1, &Hdr);
156 if (!EFI_ERROR (Status)) {
157 Hdr->Header.Size >>= 1;
158 Hdr->Header.Available = TRUE;
159 Hdr->Header.Type = PoolType;
160 InsertHeadList (&mSmmPoolLists[SmmPoolType][PoolIndex], &Hdr->Link);
161 Hdr = (FREE_POOL_HEADER*)((UINT8*)Hdr + Hdr->Header.Size);
162 }
163 }
164
165 if (!EFI_ERROR (Status)) {
166 Hdr->Header.Size = MIN_POOL_SIZE << PoolIndex;
167 Hdr->Header.Available = FALSE;
168 Hdr->Header.Type = PoolType;
169 }
170
171 *FreePoolHdr = Hdr;
172 return Status;
173 }
174
175 /**
176 Internal Function. Free a pool by specified PoolIndex.
177
178 @param FreePoolHdr The pool to free.
179
180 @retval EFI_SUCCESS Pool successfully freed.
181
182 **/
183 EFI_STATUS
184 InternalFreePoolByIndex (
185 IN FREE_POOL_HEADER *FreePoolHdr
186 )
187 {
188 UINTN PoolIndex;
189 SMM_POOL_TYPE SmmPoolType;
190
191 ASSERT ((FreePoolHdr->Header.Size & (FreePoolHdr->Header.Size - 1)) == 0);
192 ASSERT (((UINTN)FreePoolHdr & (FreePoolHdr->Header.Size - 1)) == 0);
193 ASSERT (FreePoolHdr->Header.Size >= MIN_POOL_SIZE);
194
195 SmmPoolType = UefiMemoryTypeToSmmPoolType(FreePoolHdr->Header.Type);
196
197 PoolIndex = (UINTN) (HighBitSet32 ((UINT32)FreePoolHdr->Header.Size) - MIN_POOL_SHIFT);
198 FreePoolHdr->Header.Available = TRUE;
199 ASSERT (PoolIndex < MAX_POOL_INDEX);
200 InsertHeadList (&mSmmPoolLists[SmmPoolType][PoolIndex], &FreePoolHdr->Link);
201 return EFI_SUCCESS;
202 }
203
204 /**
205 Allocate pool of a particular type.
206
207 @param PoolType Type of pool to allocate.
208 @param Size The amount of pool to allocate.
209 @param Buffer The address to return a pointer to the allocated
210 pool.
211
212 @retval EFI_INVALID_PARAMETER PoolType not valid.
213 @retval EFI_OUT_OF_RESOURCES Size exceeds max pool size or allocation failed.
214 @retval EFI_SUCCESS Pool successfully allocated.
215
216 **/
217 EFI_STATUS
218 EFIAPI
219 SmmInternalAllocatePool (
220 IN EFI_MEMORY_TYPE PoolType,
221 IN UINTN Size,
222 OUT VOID **Buffer
223 )
224 {
225 POOL_HEADER *PoolHdr;
226 FREE_POOL_HEADER *FreePoolHdr;
227 EFI_STATUS Status;
228 EFI_PHYSICAL_ADDRESS Address;
229 UINTN PoolIndex;
230
231 Address = 0;
232
233 if (PoolType != EfiRuntimeServicesCode &&
234 PoolType != EfiRuntimeServicesData) {
235 return EFI_INVALID_PARAMETER;
236 }
237
238 Size += sizeof (*PoolHdr);
239 if (Size > MAX_POOL_SIZE) {
240 Size = EFI_SIZE_TO_PAGES (Size);
241 Status = SmmInternalAllocatePages (AllocateAnyPages, PoolType, Size, &Address);
242 if (EFI_ERROR (Status)) {
243 return Status;
244 }
245
246 PoolHdr = (POOL_HEADER*)(UINTN)Address;
247 PoolHdr->Size = EFI_PAGES_TO_SIZE (Size);
248 PoolHdr->Available = FALSE;
249 PoolHdr->Type = PoolType;
250 *Buffer = PoolHdr + 1;
251 return Status;
252 }
253
254 Size = (Size + MIN_POOL_SIZE - 1) >> MIN_POOL_SHIFT;
255 PoolIndex = (UINTN) HighBitSet32 ((UINT32)Size);
256 if ((Size & (Size - 1)) != 0) {
257 PoolIndex++;
258 }
259
260 Status = InternalAllocPoolByIndex (PoolType, PoolIndex, &FreePoolHdr);
261 if (!EFI_ERROR(Status)) {
262 *Buffer = &FreePoolHdr->Header + 1;
263 }
264 return Status;
265 }
266
267 /**
268 Allocate pool of a particular type.
269
270 @param PoolType Type of pool to allocate.
271 @param Size The amount of pool to allocate.
272 @param Buffer The address to return a pointer to the allocated
273 pool.
274
275 @retval EFI_INVALID_PARAMETER PoolType not valid.
276 @retval EFI_OUT_OF_RESOURCES Size exceeds max pool size or allocation failed.
277 @retval EFI_SUCCESS Pool successfully allocated.
278
279 **/
280 EFI_STATUS
281 EFIAPI
282 SmmAllocatePool (
283 IN EFI_MEMORY_TYPE PoolType,
284 IN UINTN Size,
285 OUT VOID **Buffer
286 )
287 {
288 EFI_STATUS Status;
289
290 Status = SmmInternalAllocatePool (PoolType, Size, Buffer);
291 if (!EFI_ERROR (Status)) {
292 SmmCoreUpdateProfile (
293 (EFI_PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS (0),
294 MemoryProfileActionAllocatePool,
295 PoolType,
296 Size,
297 *Buffer,
298 NULL
299 );
300 }
301 return Status;
302 }
303
304 /**
305 Frees pool.
306
307 @param Buffer The allocated pool entry to free.
308
309 @retval EFI_INVALID_PARAMETER Buffer is not a valid value.
310 @retval EFI_SUCCESS Pool successfully freed.
311
312 **/
313 EFI_STATUS
314 EFIAPI
315 SmmInternalFreePool (
316 IN VOID *Buffer
317 )
318 {
319 FREE_POOL_HEADER *FreePoolHdr;
320
321 if (Buffer == NULL) {
322 return EFI_INVALID_PARAMETER;
323 }
324
325 FreePoolHdr = (FREE_POOL_HEADER*)((POOL_HEADER*)Buffer - 1);
326 ASSERT (!FreePoolHdr->Header.Available);
327
328 if (FreePoolHdr->Header.Size > MAX_POOL_SIZE) {
329 ASSERT (((UINTN)FreePoolHdr & EFI_PAGE_MASK) == 0);
330 ASSERT ((FreePoolHdr->Header.Size & EFI_PAGE_MASK) == 0);
331 return SmmInternalFreePages (
332 (EFI_PHYSICAL_ADDRESS)(UINTN)FreePoolHdr,
333 EFI_SIZE_TO_PAGES (FreePoolHdr->Header.Size)
334 );
335 }
336 return InternalFreePoolByIndex (FreePoolHdr);
337 }
338
339 /**
340 Frees pool.
341
342 @param Buffer The allocated pool entry to free.
343
344 @retval EFI_INVALID_PARAMETER Buffer is not a valid value.
345 @retval EFI_SUCCESS Pool successfully freed.
346
347 **/
348 EFI_STATUS
349 EFIAPI
350 SmmFreePool (
351 IN VOID *Buffer
352 )
353 {
354 EFI_STATUS Status;
355
356 Status = SmmInternalFreePool (Buffer);
357 if (!EFI_ERROR (Status)) {
358 SmmCoreUpdateProfile (
359 (EFI_PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS (0),
360 MemoryProfileActionFreePool,
361 EfiMaxMemoryType,
362 0,
363 Buffer,
364 NULL
365 );
366 }
367 return Status;
368 }