TianoCore EDK2 master
Loading...
Searching...
No Matches
Pool.c
Go to the documentation of this file.
1
9#include "PiSmmCore.h"
10
11LIST_ENTRY mSmmPoolLists[SmmPoolTypeMax][MAX_POOL_INDEX];
12//
13// To cache the SMRAM base since when Loading modules At fixed address feature is enabled,
14// all module is assigned an offset relative the SMRAM base in build time.
15//
16GLOBAL_REMOVE_IF_UNREFERENCED EFI_PHYSICAL_ADDRESS gLoadModuleAtFixAddressSmramBase = 0;
17
25SMM_POOL_TYPE
27 IN EFI_MEMORY_TYPE MemoryType
28 )
29{
30 ASSERT ((MemoryType == EfiRuntimeServicesCode) || (MemoryType == EfiRuntimeServicesData));
31 switch (MemoryType) {
33 return SmmPoolTypeCode;
35 return SmmPoolTypeData;
36 default:
37 return SmmPoolTypeMax;
38 }
39}
40
48VOID
50 IN UINTN SmramRangeCount,
51 IN EFI_SMRAM_DESCRIPTOR *SmramRanges
52 )
53{
54 UINTN Index;
55 EFI_STATUS Status;
56 UINTN SmmPoolTypeIndex;
57 EFI_LOAD_FIXED_ADDRESS_CONFIGURATION_TABLE *LMFAConfigurationTable;
58
59 //
60 // Initialize Pool list
61 //
62 for (SmmPoolTypeIndex = 0; SmmPoolTypeIndex < SmmPoolTypeMax; SmmPoolTypeIndex++) {
63 for (Index = 0; Index < ARRAY_SIZE (mSmmPoolLists[SmmPoolTypeIndex]); Index++) {
64 InitializeListHead (&mSmmPoolLists[SmmPoolTypeIndex][Index]);
65 }
66 }
67
69 &gLoadFixedAddressConfigurationTableGuid,
70 (VOID **)&LMFAConfigurationTable
71 );
72 if (!EFI_ERROR (Status) && (LMFAConfigurationTable != NULL)) {
73 gLoadModuleAtFixAddressSmramBase = LMFAConfigurationTable->SmramBase;
74 }
75
76 //
77 // Add Free SMRAM regions
78 // Need add Free memory at first, to let gSmmMemoryMap record data
79 //
80 for (Index = 0; Index < SmramRangeCount; Index++) {
81 if ((SmramRanges[Index].RegionState & (EFI_ALLOCATED | EFI_NEEDS_TESTING | EFI_NEEDS_ECC_INITIALIZATION)) != 0) {
82 continue;
83 }
84
86 SmramRanges[Index].CpuStart,
87 SmramRanges[Index].PhysicalSize,
89 SmramRanges[Index].RegionState
90 );
91 }
92
93 //
94 // Add the allocated SMRAM regions
95 //
96 for (Index = 0; Index < SmramRangeCount; Index++) {
97 if ((SmramRanges[Index].RegionState & (EFI_ALLOCATED | EFI_NEEDS_TESTING | EFI_NEEDS_ECC_INITIALIZATION)) == 0) {
98 continue;
99 }
100
102 SmramRanges[Index].CpuStart,
103 SmramRanges[Index].PhysicalSize,
105 SmramRanges[Index].RegionState
106 );
107 }
108}
109
123 IN EFI_MEMORY_TYPE PoolType,
124 IN UINTN PoolIndex,
125 OUT FREE_POOL_HEADER **FreePoolHdr
126 )
127{
128 EFI_STATUS Status;
129 FREE_POOL_HEADER *Hdr;
130 POOL_TAIL *Tail;
131 EFI_PHYSICAL_ADDRESS Address;
132 SMM_POOL_TYPE SmmPoolType;
133
134 Address = 0;
135 SmmPoolType = UefiMemoryTypeToSmmPoolType (PoolType);
136
137 ASSERT (PoolIndex <= MAX_POOL_INDEX);
138 Status = EFI_SUCCESS;
139 Hdr = NULL;
140 if (PoolIndex == MAX_POOL_INDEX) {
141 Status = SmmInternalAllocatePages (
143 PoolType,
144 EFI_SIZE_TO_PAGES (MAX_POOL_SIZE << 1),
145 &Address,
146 FALSE
147 );
148 if (EFI_ERROR (Status)) {
149 return EFI_OUT_OF_RESOURCES;
150 }
151
152 Hdr = (FREE_POOL_HEADER *)(UINTN)Address;
153 } else if (!IsListEmpty (&mSmmPoolLists[SmmPoolType][PoolIndex])) {
154 Hdr = BASE_CR (GetFirstNode (&mSmmPoolLists[SmmPoolType][PoolIndex]), FREE_POOL_HEADER, Link);
155 RemoveEntryList (&Hdr->Link);
156 } else {
157 Status = InternalAllocPoolByIndex (PoolType, PoolIndex + 1, &Hdr);
158 if (!EFI_ERROR (Status)) {
159 Hdr->Header.Signature = 0;
160 Hdr->Header.Size >>= 1;
161 Hdr->Header.Available = TRUE;
162 Hdr->Header.Type = 0;
163 Tail = HEAD_TO_TAIL (&Hdr->Header);
164 Tail->Signature = 0;
165 Tail->Size = 0;
166 InsertHeadList (&mSmmPoolLists[SmmPoolType][PoolIndex], &Hdr->Link);
167 Hdr = (FREE_POOL_HEADER *)((UINT8 *)Hdr + Hdr->Header.Size);
168 }
169 }
170
171 if (!EFI_ERROR (Status)) {
172 Hdr->Header.Signature = POOL_HEAD_SIGNATURE;
173 Hdr->Header.Size = MIN_POOL_SIZE << PoolIndex;
174 Hdr->Header.Available = FALSE;
175 Hdr->Header.Type = PoolType;
176 Tail = HEAD_TO_TAIL (&Hdr->Header);
177 Tail->Signature = POOL_TAIL_SIGNATURE;
178 Tail->Size = Hdr->Header.Size;
179 }
180
181 *FreePoolHdr = Hdr;
182 return Status;
183}
184
194STATIC
197 IN FREE_POOL_HEADER *FreePoolHdr,
198 IN POOL_TAIL *PoolTail OPTIONAL
199 )
200{
201 UINTN PoolIndex;
202 SMM_POOL_TYPE SmmPoolType;
203
204 ASSERT ((FreePoolHdr->Header.Size & (FreePoolHdr->Header.Size - 1)) == 0);
205 ASSERT (((UINTN)FreePoolHdr & (FreePoolHdr->Header.Size - 1)) == 0);
206 ASSERT (FreePoolHdr->Header.Size >= MIN_POOL_SIZE);
207
208 SmmPoolType = UefiMemoryTypeToSmmPoolType (FreePoolHdr->Header.Type);
209
210 PoolIndex = (UINTN)(HighBitSet32 ((UINT32)FreePoolHdr->Header.Size) - MIN_POOL_SHIFT);
211 FreePoolHdr->Header.Signature = 0;
212 FreePoolHdr->Header.Available = TRUE;
213 FreePoolHdr->Header.Type = 0;
214 if (PoolTail != NULL) {
215 PoolTail->Signature = 0;
216 PoolTail->Size = 0;
217 }
218
219 ASSERT (PoolIndex < MAX_POOL_INDEX);
220 InsertHeadList (&mSmmPoolLists[SmmPoolType][PoolIndex], &FreePoolHdr->Link);
221 return EFI_SUCCESS;
222}
223
238EFIAPI
240 IN EFI_MEMORY_TYPE PoolType,
241 IN UINTN Size,
242 OUT VOID **Buffer
243 )
244{
245 POOL_HEADER *PoolHdr;
246 POOL_TAIL *PoolTail;
247 FREE_POOL_HEADER *FreePoolHdr;
248 EFI_STATUS Status;
249 EFI_PHYSICAL_ADDRESS Address;
250 UINTN PoolIndex;
251 BOOLEAN HasPoolTail;
252 BOOLEAN NeedGuard;
253 UINTN NoPages;
254
255 Address = 0;
256
257 if ((PoolType != EfiRuntimeServicesCode) &&
258 (PoolType != EfiRuntimeServicesData))
259 {
260 return EFI_INVALID_PARAMETER;
261 }
262
263 NeedGuard = IsPoolTypeToGuard (PoolType);
264 HasPoolTail = !(NeedGuard &&
265 ((PcdGet8 (PcdHeapGuardPropertyMask) & BIT7) == 0));
266
267 //
268 // Adjust the size by the pool header & tail overhead
269 //
270 Size += POOL_OVERHEAD;
271 if ((Size > MAX_POOL_SIZE) || NeedGuard) {
272 if (!HasPoolTail) {
273 Size -= sizeof (POOL_TAIL);
274 }
275
276 NoPages = EFI_SIZE_TO_PAGES (Size);
277 Status = SmmInternalAllocatePages (
279 PoolType,
280 NoPages,
281 &Address,
282 NeedGuard
283 );
284 if (EFI_ERROR (Status)) {
285 return Status;
286 }
287
288 if (NeedGuard) {
289 ASSERT (VerifyMemoryGuard (Address, NoPages) == TRUE);
291 Address,
292 NoPages,
293 Size
294 );
295 }
296
297 PoolHdr = (POOL_HEADER *)(UINTN)Address;
298 PoolHdr->Signature = POOL_HEAD_SIGNATURE;
299 PoolHdr->Size = EFI_PAGES_TO_SIZE (NoPages);
300 PoolHdr->Available = FALSE;
301 PoolHdr->Type = PoolType;
302
303 if (HasPoolTail) {
304 PoolTail = HEAD_TO_TAIL (PoolHdr);
305 PoolTail->Signature = POOL_TAIL_SIGNATURE;
306 PoolTail->Size = PoolHdr->Size;
307 }
308
309 *Buffer = PoolHdr + 1;
310 return Status;
311 }
312
313 Size = (Size + MIN_POOL_SIZE - 1) >> MIN_POOL_SHIFT;
314 PoolIndex = (UINTN)HighBitSet32 ((UINT32)Size);
315 if ((Size & (Size - 1)) != 0) {
316 PoolIndex++;
317 }
318
319 Status = InternalAllocPoolByIndex (PoolType, PoolIndex, &FreePoolHdr);
320 if (!EFI_ERROR (Status)) {
321 *Buffer = &FreePoolHdr->Header + 1;
322 }
323
324 return Status;
325}
326
341EFIAPI
343 IN EFI_MEMORY_TYPE PoolType,
344 IN UINTN Size,
345 OUT VOID **Buffer
346 )
347{
348 EFI_STATUS Status;
349
350 Status = SmmInternalAllocatePool (PoolType, Size, Buffer);
351 if (!EFI_ERROR (Status)) {
354 MemoryProfileActionAllocatePool,
355 PoolType,
356 Size,
357 *Buffer,
358 NULL
359 );
360 }
361
362 return Status;
363}
364
375EFIAPI
377 IN VOID *Buffer
378 )
379{
380 FREE_POOL_HEADER *FreePoolHdr;
381 POOL_TAIL *PoolTail;
382 BOOLEAN HasPoolTail;
383 BOOLEAN MemoryGuarded;
384
385 if (Buffer == NULL) {
386 return EFI_INVALID_PARAMETER;
387 }
388
389 FreePoolHdr = (FREE_POOL_HEADER *)((POOL_HEADER *)Buffer - 1);
390 ASSERT (FreePoolHdr->Header.Signature == POOL_HEAD_SIGNATURE);
391 ASSERT (!FreePoolHdr->Header.Available);
392 if (FreePoolHdr->Header.Signature != POOL_HEAD_SIGNATURE) {
393 return EFI_INVALID_PARAMETER;
394 }
395
396 MemoryGuarded = IsHeapGuardEnabled () &&
398 HasPoolTail = !(MemoryGuarded &&
399 ((PcdGet8 (PcdHeapGuardPropertyMask) & BIT7) == 0));
400
401 if (HasPoolTail) {
402 PoolTail = HEAD_TO_TAIL (&FreePoolHdr->Header);
403 ASSERT (PoolTail->Signature == POOL_TAIL_SIGNATURE);
404 ASSERT (FreePoolHdr->Header.Size == PoolTail->Size);
405 if (PoolTail->Signature != POOL_TAIL_SIGNATURE) {
406 return EFI_INVALID_PARAMETER;
407 }
408
409 if (FreePoolHdr->Header.Size != PoolTail->Size) {
410 return EFI_INVALID_PARAMETER;
411 }
412 } else {
413 PoolTail = NULL;
414 }
415
416 if (MemoryGuarded) {
417 Buffer = AdjustPoolHeadF ((EFI_PHYSICAL_ADDRESS)(UINTN)FreePoolHdr);
418 return SmmInternalFreePages (
420 EFI_SIZE_TO_PAGES (FreePoolHdr->Header.Size),
421 TRUE
422 );
423 }
424
425 if (FreePoolHdr->Header.Size > MAX_POOL_SIZE) {
426 ASSERT (((UINTN)FreePoolHdr & EFI_PAGE_MASK) == 0);
427 ASSERT ((FreePoolHdr->Header.Size & EFI_PAGE_MASK) == 0);
428 return SmmInternalFreePages (
429 (EFI_PHYSICAL_ADDRESS)(UINTN)FreePoolHdr,
430 EFI_SIZE_TO_PAGES (FreePoolHdr->Header.Size),
431 FALSE
432 );
433 }
434
435 return InternalFreePoolByIndex (FreePoolHdr, PoolTail);
436}
437
448EFIAPI
450 IN VOID *Buffer
451 )
452{
453 EFI_STATUS Status;
454
455 Status = SmmInternalFreePool (Buffer);
456 if (!EFI_ERROR (Status)) {
459 MemoryProfileActionFreePool,
460 EfiMaxMemoryType,
461 0,
462 Buffer,
463 NULL
464 );
465 }
466
467 return Status;
468}
UINT64 UINTN
BOOLEAN EFIAPI IsListEmpty(IN CONST LIST_ENTRY *ListHead)
Definition: LinkedList.c:403
LIST_ENTRY *EFIAPI InsertHeadList(IN OUT LIST_ENTRY *ListHead, IN OUT LIST_ENTRY *Entry)
Definition: LinkedList.c:218
LIST_ENTRY *EFIAPI GetFirstNode(IN CONST LIST_ENTRY *List)
Definition: LinkedList.c:298
LIST_ENTRY *EFIAPI RemoveEntryList(IN CONST LIST_ENTRY *Entry)
Definition: LinkedList.c:590
LIST_ENTRY *EFIAPI InitializeListHead(IN OUT LIST_ENTRY *ListHead)
Definition: LinkedList.c:182
INTN EFIAPI HighBitSet32(IN UINT32 Operand)
Definition: HighBitSet32.c:27
VOID * AdjustPoolHeadF(IN EFI_PHYSICAL_ADDRESS Memory, IN UINTN NoPages, IN UINTN Size)
Definition: HeapGuard.c:1047
BOOLEAN IsHeapGuardEnabled(UINT8 GuardType)
Definition: HeapGuard.c:674
BOOLEAN IsPoolTypeToGuard(IN EFI_MEMORY_TYPE MemoryType)
Definition: HeapGuard.c:637
BOOLEAN EFIAPI IsMemoryGuarded(IN EFI_PHYSICAL_ADDRESS Address)
Definition: HeapGuard.c:486
VOID * AdjustPoolHeadA(IN EFI_PHYSICAL_ADDRESS Memory, IN UINTN NoPages, IN UINTN Size)
Definition: HeapGuard.c:1016
EFI_STATUS EFIAPI SmmInternalAllocatePages(IN EFI_ALLOCATE_TYPE Type, IN EFI_MEMORY_TYPE MemoryType, IN UINTN NumberOfPages, OUT EFI_PHYSICAL_ADDRESS *Memory, IN BOOLEAN NeedGuard)
Definition: Page.c:691
EFI_STATUS EFIAPI SmmInternalFreePages(IN EFI_PHYSICAL_ADDRESS Memory, IN UINTN NumberOfPages, IN BOOLEAN IsGuarded)
Definition: Page.c:877
VOID SmmAddMemoryRegion(IN EFI_PHYSICAL_ADDRESS MemBase, IN UINT64 MemLength, IN EFI_MEMORY_TYPE Type, IN UINT64 Attributes)
Definition: Page.c:976
EFI_STATUS EFIAPI SmmInternalFreePool(IN VOID *Buffer)
Definition: Pool.c:376
EFI_STATUS EFIAPI SmmInternalAllocatePool(IN EFI_MEMORY_TYPE PoolType, IN UINTN Size, OUT VOID **Buffer)
Definition: Pool.c:239
EFI_STATUS EFIAPI SmmFreePool(IN VOID *Buffer)
Definition: Pool.c:449
STATIC EFI_STATUS InternalFreePoolByIndex(IN FREE_POOL_HEADER *FreePoolHdr, IN POOL_TAIL *PoolTail OPTIONAL)
Definition: Pool.c:196
EFI_STATUS EFIAPI SmmAllocatePool(IN EFI_MEMORY_TYPE PoolType, IN UINTN Size, OUT VOID **Buffer)
Definition: Pool.c:342
EFI_STATUS InternalAllocPoolByIndex(IN EFI_MEMORY_TYPE PoolType, IN UINTN PoolIndex, OUT FREE_POOL_HEADER **FreePoolHdr)
Definition: Pool.c:122
SMM_POOL_TYPE UefiMemoryTypeToSmmPoolType(IN EFI_MEMORY_TYPE MemoryType)
Definition: Pool.c:26
VOID SmmInitializeMemoryServices(IN UINTN SmramRangeCount, IN EFI_SMRAM_DESCRIPTOR *SmramRanges)
Definition: Pool.c:49
#define NULL
Definition: Base.h:319
#define STATIC
Definition: Base.h:264
#define RETURN_ADDRESS(L)
Definition: Base.h:1379
#define VOID
Definition: Base.h:269
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define ARRAY_SIZE(Array)
Definition: Base.h:1393
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define GLOBAL_REMOVE_IF_UNREFERENCED
Definition: Base.h:48
#define BASE_CR(Record, TYPE, Field)
Definition: Base.h:891
#define PcdGet8(TokenName)
Definition: PcdLib.h:336
BOOLEAN VerifyMemoryGuard(IN EFI_PHYSICAL_ADDRESS BaseAddress, IN UINTN NumberOfPages)
Definition: HeapGuard.c:1381
EFI_STATUS EFIAPI SmmCoreUpdateProfile(IN PHYSICAL_ADDRESS CallerAddress, IN MEMORY_PROFILE_ACTION Action, IN EFI_MEMORY_TYPE MemoryType, IN UINTN Size, IN VOID *Buffer, IN CHAR8 *ActionString OPTIONAL)
UINT64 EFI_PHYSICAL_ADDRESS
Definition: UefiBaseType.h:50
#define EFI_PAGES_TO_SIZE(Pages)
Definition: UefiBaseType.h:213
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
#define EFI_SIZE_TO_PAGES(Size)
Definition: UefiBaseType.h:200
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_STATUS EFIAPI EfiGetSystemConfigurationTable(IN EFI_GUID *TableGuid, OUT VOID **Table)
Definition: UefiLib.c:78
EFI_MEMORY_TYPE
@ EfiConventionalMemory
@ EfiRuntimeServicesCode
@ EfiRuntimeServicesData
@ AllocateAnyPages
Definition: UefiSpec.h:33
EFI_PHYSICAL_ADDRESS SmramBase
SMRAM base address. The build tool assigns an offset relative to the SMRAM base for a SMM driver.
Definition: Pool.c:35