summaryrefslogtreecommitdiff
path: root/MdeModulePkg/Core/PiSmmCore/Pool.c
diff options
context:
space:
mode:
Diffstat (limited to 'MdeModulePkg/Core/PiSmmCore/Pool.c')
-rw-r--r--MdeModulePkg/Core/PiSmmCore/Pool.c928
1 files changed, 464 insertions, 464 deletions
diff --git a/MdeModulePkg/Core/PiSmmCore/Pool.c b/MdeModulePkg/Core/PiSmmCore/Pool.c
index e1ff40a8ea..6d1565d430 100644
--- a/MdeModulePkg/Core/PiSmmCore/Pool.c
+++ b/MdeModulePkg/Core/PiSmmCore/Pool.c
@@ -1,464 +1,464 @@
-/** @file
- SMM Memory pool management functions.
-
- Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
- SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#include "PiSmmCore.h"
-
-LIST_ENTRY mSmmPoolLists[SmmPoolTypeMax][MAX_POOL_INDEX];
-//
-// To cache the SMRAM base since when Loading modules At fixed address feature is enabled,
-// all module is assigned an offset relative the SMRAM base in build time.
-//
-GLOBAL_REMOVE_IF_UNREFERENCED EFI_PHYSICAL_ADDRESS gLoadModuleAtFixAddressSmramBase = 0;
-
-/**
- Convert a UEFI memory type to SMM pool type.
-
- @param[in] MemoryType Type of pool to allocate.
-
- @return SMM pool type
-**/
-SMM_POOL_TYPE
-UefiMemoryTypeToSmmPoolType (
- IN EFI_MEMORY_TYPE MemoryType
- )
-{
- ASSERT ((MemoryType == EfiRuntimeServicesCode) || (MemoryType == EfiRuntimeServicesData));
- switch (MemoryType) {
- case EfiRuntimeServicesCode:
- return SmmPoolTypeCode;
- case EfiRuntimeServicesData:
- return SmmPoolTypeData;
- default:
- return SmmPoolTypeMax;
- }
-}
-
-/**
- Called to initialize the memory service.
-
- @param SmramRangeCount Number of SMRAM Regions
- @param SmramRanges Pointer to SMRAM Descriptors
-
-**/
-VOID
-SmmInitializeMemoryServices (
- IN UINTN SmramRangeCount,
- IN EFI_SMRAM_DESCRIPTOR *SmramRanges
- )
-{
- UINTN Index;
- EFI_STATUS Status;
- UINTN SmmPoolTypeIndex;
- EFI_LOAD_FIXED_ADDRESS_CONFIGURATION_TABLE *LMFAConfigurationTable;
-
- //
- // Initialize Pool list
- //
- for (SmmPoolTypeIndex = 0; SmmPoolTypeIndex < SmmPoolTypeMax; SmmPoolTypeIndex++) {
- for (Index = 0; Index < ARRAY_SIZE (mSmmPoolLists[SmmPoolTypeIndex]); Index++) {
- InitializeListHead (&mSmmPoolLists[SmmPoolTypeIndex][Index]);
- }
- }
-
- Status = EfiGetSystemConfigurationTable (
- &gLoadFixedAddressConfigurationTableGuid,
- (VOID **)&LMFAConfigurationTable
- );
- if (!EFI_ERROR (Status) && (LMFAConfigurationTable != NULL)) {
- gLoadModuleAtFixAddressSmramBase = LMFAConfigurationTable->SmramBase;
- }
-
- //
- // Add Free SMRAM regions
- // Need add Free memory at first, to let gSmmMemoryMap record data
- //
- for (Index = 0; Index < SmramRangeCount; Index++) {
- if ((SmramRanges[Index].RegionState & (EFI_ALLOCATED | EFI_NEEDS_TESTING | EFI_NEEDS_ECC_INITIALIZATION)) != 0) {
- continue;
- }
-
- SmmAddMemoryRegion (
- SmramRanges[Index].CpuStart,
- SmramRanges[Index].PhysicalSize,
- EfiConventionalMemory,
- SmramRanges[Index].RegionState
- );
- }
-
- //
- // Add the allocated SMRAM regions
- //
- for (Index = 0; Index < SmramRangeCount; Index++) {
- if ((SmramRanges[Index].RegionState & (EFI_ALLOCATED | EFI_NEEDS_TESTING | EFI_NEEDS_ECC_INITIALIZATION)) == 0) {
- continue;
- }
-
- SmmAddMemoryRegion (
- SmramRanges[Index].CpuStart,
- SmramRanges[Index].PhysicalSize,
- EfiConventionalMemory,
- SmramRanges[Index].RegionState
- );
- }
-}
-
-/**
- Internal Function. Allocate a pool by specified PoolIndex.
-
- @param PoolType Type of pool to allocate.
- @param PoolIndex Index which indicate the Pool size.
- @param FreePoolHdr The returned Free pool.
-
- @retval EFI_OUT_OF_RESOURCES Allocation failed.
- @retval EFI_SUCCESS Pool successfully allocated.
-
-**/
-EFI_STATUS
-InternalAllocPoolByIndex (
- IN EFI_MEMORY_TYPE PoolType,
- IN UINTN PoolIndex,
- OUT FREE_POOL_HEADER **FreePoolHdr
- )
-{
- EFI_STATUS Status;
- FREE_POOL_HEADER *Hdr;
- POOL_TAIL *Tail;
- EFI_PHYSICAL_ADDRESS Address;
- SMM_POOL_TYPE SmmPoolType;
-
- Address = 0;
- SmmPoolType = UefiMemoryTypeToSmmPoolType (PoolType);
-
- ASSERT (PoolIndex <= MAX_POOL_INDEX);
- Status = EFI_SUCCESS;
- Hdr = NULL;
- if (PoolIndex == MAX_POOL_INDEX) {
- Status = SmmInternalAllocatePages (
- AllocateAnyPages,
- PoolType,
- EFI_SIZE_TO_PAGES (MAX_POOL_SIZE << 1),
- &Address,
- FALSE
- );
- if (EFI_ERROR (Status)) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- Hdr = (FREE_POOL_HEADER *)(UINTN)Address;
- } else if (!IsListEmpty (&mSmmPoolLists[SmmPoolType][PoolIndex])) {
- Hdr = BASE_CR (GetFirstNode (&mSmmPoolLists[SmmPoolType][PoolIndex]), FREE_POOL_HEADER, Link);
- RemoveEntryList (&Hdr->Link);
- } else {
- Status = InternalAllocPoolByIndex (PoolType, PoolIndex + 1, &Hdr);
- if (!EFI_ERROR (Status)) {
- Hdr->Header.Signature = 0;
- Hdr->Header.Size >>= 1;
- Hdr->Header.Available = TRUE;
- Hdr->Header.Type = 0;
- Tail = HEAD_TO_TAIL (&Hdr->Header);
- Tail->Signature = 0;
- Tail->Size = 0;
- InsertHeadList (&mSmmPoolLists[SmmPoolType][PoolIndex], &Hdr->Link);
- Hdr = (FREE_POOL_HEADER *)((UINT8 *)Hdr + Hdr->Header.Size);
- }
- }
-
- if (!EFI_ERROR (Status)) {
- Hdr->Header.Signature = POOL_HEAD_SIGNATURE;
- Hdr->Header.Size = MIN_POOL_SIZE << PoolIndex;
- Hdr->Header.Available = FALSE;
- Hdr->Header.Type = PoolType;
- Tail = HEAD_TO_TAIL (&Hdr->Header);
- Tail->Signature = POOL_TAIL_SIGNATURE;
- Tail->Size = Hdr->Header.Size;
- }
-
- *FreePoolHdr = Hdr;
- return Status;
-}
-
-/**
- Internal Function. Free a pool by specified PoolIndex.
-
- @param FreePoolHdr The pool to free.
- @param PoolTail The pointer to the pool tail.
-
- @retval EFI_SUCCESS Pool successfully freed.
-
-**/
-EFI_STATUS
-InternalFreePoolByIndex (
- IN FREE_POOL_HEADER *FreePoolHdr,
- IN POOL_TAIL *PoolTail
- )
-{
- UINTN PoolIndex;
- SMM_POOL_TYPE SmmPoolType;
-
- ASSERT ((FreePoolHdr->Header.Size & (FreePoolHdr->Header.Size - 1)) == 0);
- ASSERT (((UINTN)FreePoolHdr & (FreePoolHdr->Header.Size - 1)) == 0);
- ASSERT (FreePoolHdr->Header.Size >= MIN_POOL_SIZE);
-
- SmmPoolType = UefiMemoryTypeToSmmPoolType (FreePoolHdr->Header.Type);
-
- PoolIndex = (UINTN)(HighBitSet32 ((UINT32)FreePoolHdr->Header.Size) - MIN_POOL_SHIFT);
- FreePoolHdr->Header.Signature = 0;
- FreePoolHdr->Header.Available = TRUE;
- FreePoolHdr->Header.Type = 0;
- PoolTail->Signature = 0;
- PoolTail->Size = 0;
- ASSERT (PoolIndex < MAX_POOL_INDEX);
- InsertHeadList (&mSmmPoolLists[SmmPoolType][PoolIndex], &FreePoolHdr->Link);
- return EFI_SUCCESS;
-}
-
-/**
- Allocate pool of a particular type.
-
- @param PoolType Type of pool to allocate.
- @param Size The amount of pool to allocate.
- @param Buffer The address to return a pointer to the allocated
- pool.
-
- @retval EFI_INVALID_PARAMETER PoolType not valid.
- @retval EFI_OUT_OF_RESOURCES Size exceeds max pool size or allocation failed.
- @retval EFI_SUCCESS Pool successfully allocated.
-
-**/
-EFI_STATUS
-EFIAPI
-SmmInternalAllocatePool (
- IN EFI_MEMORY_TYPE PoolType,
- IN UINTN Size,
- OUT VOID **Buffer
- )
-{
- POOL_HEADER *PoolHdr;
- POOL_TAIL *PoolTail;
- FREE_POOL_HEADER *FreePoolHdr;
- EFI_STATUS Status;
- EFI_PHYSICAL_ADDRESS Address;
- UINTN PoolIndex;
- BOOLEAN HasPoolTail;
- BOOLEAN NeedGuard;
- UINTN NoPages;
-
- Address = 0;
-
- if ((PoolType != EfiRuntimeServicesCode) &&
- (PoolType != EfiRuntimeServicesData))
- {
- return EFI_INVALID_PARAMETER;
- }
-
- NeedGuard = IsPoolTypeToGuard (PoolType);
- HasPoolTail = !(NeedGuard &&
- ((PcdGet8 (PcdHeapGuardPropertyMask) & BIT7) == 0));
-
- //
- // Adjust the size by the pool header & tail overhead
- //
- Size += POOL_OVERHEAD;
- if ((Size > MAX_POOL_SIZE) || NeedGuard) {
- if (!HasPoolTail) {
- Size -= sizeof (POOL_TAIL);
- }
-
- NoPages = EFI_SIZE_TO_PAGES (Size);
- Status = SmmInternalAllocatePages (
- AllocateAnyPages,
- PoolType,
- NoPages,
- &Address,
- NeedGuard
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- if (NeedGuard) {
- ASSERT (VerifyMemoryGuard (Address, NoPages) == TRUE);
- Address = (EFI_PHYSICAL_ADDRESS)(UINTN)AdjustPoolHeadA (
- Address,
- NoPages,
- Size
- );
- }
-
- PoolHdr = (POOL_HEADER *)(UINTN)Address;
- PoolHdr->Signature = POOL_HEAD_SIGNATURE;
- PoolHdr->Size = EFI_PAGES_TO_SIZE (NoPages);
- PoolHdr->Available = FALSE;
- PoolHdr->Type = PoolType;
-
- if (HasPoolTail) {
- PoolTail = HEAD_TO_TAIL (PoolHdr);
- PoolTail->Signature = POOL_TAIL_SIGNATURE;
- PoolTail->Size = PoolHdr->Size;
- }
-
- *Buffer = PoolHdr + 1;
- return Status;
- }
-
- Size = (Size + MIN_POOL_SIZE - 1) >> MIN_POOL_SHIFT;
- PoolIndex = (UINTN)HighBitSet32 ((UINT32)Size);
- if ((Size & (Size - 1)) != 0) {
- PoolIndex++;
- }
-
- Status = InternalAllocPoolByIndex (PoolType, PoolIndex, &FreePoolHdr);
- if (!EFI_ERROR (Status)) {
- *Buffer = &FreePoolHdr->Header + 1;
- }
-
- return Status;
-}
-
-/**
- Allocate pool of a particular type.
-
- @param PoolType Type of pool to allocate.
- @param Size The amount of pool to allocate.
- @param Buffer The address to return a pointer to the allocated
- pool.
-
- @retval EFI_INVALID_PARAMETER PoolType not valid.
- @retval EFI_OUT_OF_RESOURCES Size exceeds max pool size or allocation failed.
- @retval EFI_SUCCESS Pool successfully allocated.
-
-**/
-EFI_STATUS
-EFIAPI
-SmmAllocatePool (
- IN EFI_MEMORY_TYPE PoolType,
- IN UINTN Size,
- OUT VOID **Buffer
- )
-{
- EFI_STATUS Status;
-
- Status = SmmInternalAllocatePool (PoolType, Size, Buffer);
- if (!EFI_ERROR (Status)) {
- SmmCoreUpdateProfile (
- (EFI_PHYSICAL_ADDRESS)(UINTN)RETURN_ADDRESS (0),
- MemoryProfileActionAllocatePool,
- PoolType,
- Size,
- *Buffer,
- NULL
- );
- }
-
- return Status;
-}
-
-/**
- Frees pool.
-
- @param Buffer The allocated pool entry to free.
-
- @retval EFI_INVALID_PARAMETER Buffer is not a valid value.
- @retval EFI_SUCCESS Pool successfully freed.
-
-**/
-EFI_STATUS
-EFIAPI
-SmmInternalFreePool (
- IN VOID *Buffer
- )
-{
- FREE_POOL_HEADER *FreePoolHdr;
- POOL_TAIL *PoolTail;
- BOOLEAN HasPoolTail;
- BOOLEAN MemoryGuarded;
-
- if (Buffer == NULL) {
- return EFI_INVALID_PARAMETER;
- }
-
- FreePoolHdr = (FREE_POOL_HEADER *)((POOL_HEADER *)Buffer - 1);
- ASSERT (FreePoolHdr->Header.Signature == POOL_HEAD_SIGNATURE);
- ASSERT (!FreePoolHdr->Header.Available);
- if (FreePoolHdr->Header.Signature != POOL_HEAD_SIGNATURE) {
- return EFI_INVALID_PARAMETER;
- }
-
- MemoryGuarded = IsHeapGuardEnabled () &&
- IsMemoryGuarded ((EFI_PHYSICAL_ADDRESS)(UINTN)FreePoolHdr);
- HasPoolTail = !(MemoryGuarded &&
- ((PcdGet8 (PcdHeapGuardPropertyMask) & BIT7) == 0));
-
- if (HasPoolTail) {
- PoolTail = HEAD_TO_TAIL (&FreePoolHdr->Header);
- ASSERT (PoolTail->Signature == POOL_TAIL_SIGNATURE);
- ASSERT (FreePoolHdr->Header.Size == PoolTail->Size);
- if (PoolTail->Signature != POOL_TAIL_SIGNATURE) {
- return EFI_INVALID_PARAMETER;
- }
-
- if (FreePoolHdr->Header.Size != PoolTail->Size) {
- return EFI_INVALID_PARAMETER;
- }
- } else {
- PoolTail = NULL;
- }
-
- if (MemoryGuarded) {
- Buffer = AdjustPoolHeadF ((EFI_PHYSICAL_ADDRESS)(UINTN)FreePoolHdr);
- return SmmInternalFreePages (
- (EFI_PHYSICAL_ADDRESS)(UINTN)Buffer,
- EFI_SIZE_TO_PAGES (FreePoolHdr->Header.Size),
- TRUE
- );
- }
-
- if (FreePoolHdr->Header.Size > MAX_POOL_SIZE) {
- ASSERT (((UINTN)FreePoolHdr & EFI_PAGE_MASK) == 0);
- ASSERT ((FreePoolHdr->Header.Size & EFI_PAGE_MASK) == 0);
- return SmmInternalFreePages (
- (EFI_PHYSICAL_ADDRESS)(UINTN)FreePoolHdr,
- EFI_SIZE_TO_PAGES (FreePoolHdr->Header.Size),
- FALSE
- );
- }
-
- return InternalFreePoolByIndex (FreePoolHdr, PoolTail);
-}
-
-/**
- Frees pool.
-
- @param Buffer The allocated pool entry to free.
-
- @retval EFI_INVALID_PARAMETER Buffer is not a valid value.
- @retval EFI_SUCCESS Pool successfully freed.
-
-**/
-EFI_STATUS
-EFIAPI
-SmmFreePool (
- IN VOID *Buffer
- )
-{
- EFI_STATUS Status;
-
- Status = SmmInternalFreePool (Buffer);
- if (!EFI_ERROR (Status)) {
- SmmCoreUpdateProfile (
- (EFI_PHYSICAL_ADDRESS)(UINTN)RETURN_ADDRESS (0),
- MemoryProfileActionFreePool,
- EfiMaxMemoryType,
- 0,
- Buffer,
- NULL
- );
- }
-
- return Status;
-}
+/** @file
+ SMM Memory pool management functions.
+
+ Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "PiSmmCore.h"
+
+LIST_ENTRY mSmmPoolLists[SmmPoolTypeMax][MAX_POOL_INDEX];
+//
+// To cache the SMRAM base since when Loading modules At fixed address feature is enabled,
+// all module is assigned an offset relative the SMRAM base in build time.
+//
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_PHYSICAL_ADDRESS gLoadModuleAtFixAddressSmramBase = 0;
+
+/**
+ Convert a UEFI memory type to SMM pool type.
+
+ @param[in] MemoryType Type of pool to allocate.
+
+ @return SMM pool type
+**/
+SMM_POOL_TYPE
+UefiMemoryTypeToSmmPoolType (
+ IN EFI_MEMORY_TYPE MemoryType
+ )
+{
+ ASSERT ((MemoryType == EfiRuntimeServicesCode) || (MemoryType == EfiRuntimeServicesData));
+ switch (MemoryType) {
+ case EfiRuntimeServicesCode:
+ return SmmPoolTypeCode;
+ case EfiRuntimeServicesData:
+ return SmmPoolTypeData;
+ default:
+ return SmmPoolTypeMax;
+ }
+}
+
+/**
+ Called to initialize the memory service.
+
+ @param SmramRangeCount Number of SMRAM Regions
+ @param SmramRanges Pointer to SMRAM Descriptors
+
+**/
+VOID
+SmmInitializeMemoryServices (
+ IN UINTN SmramRangeCount,
+ IN EFI_SMRAM_DESCRIPTOR *SmramRanges
+ )
+{
+ UINTN Index;
+ EFI_STATUS Status;
+ UINTN SmmPoolTypeIndex;
+ EFI_LOAD_FIXED_ADDRESS_CONFIGURATION_TABLE *LMFAConfigurationTable;
+
+ //
+ // Initialize Pool list
+ //
+ for (SmmPoolTypeIndex = 0; SmmPoolTypeIndex < SmmPoolTypeMax; SmmPoolTypeIndex++) {
+ for (Index = 0; Index < ARRAY_SIZE (mSmmPoolLists[SmmPoolTypeIndex]); Index++) {
+ InitializeListHead (&mSmmPoolLists[SmmPoolTypeIndex][Index]);
+ }
+ }
+
+ Status = EfiGetSystemConfigurationTable (
+ &gLoadFixedAddressConfigurationTableGuid,
+ (VOID **)&LMFAConfigurationTable
+ );
+ if (!EFI_ERROR (Status) && (LMFAConfigurationTable != NULL)) {
+ gLoadModuleAtFixAddressSmramBase = LMFAConfigurationTable->SmramBase;
+ }
+
+ //
+ // Add Free SMRAM regions
+ // Need add Free memory at first, to let gSmmMemoryMap record data
+ //
+ for (Index = 0; Index < SmramRangeCount; Index++) {
+ if ((SmramRanges[Index].RegionState & (EFI_ALLOCATED | EFI_NEEDS_TESTING | EFI_NEEDS_ECC_INITIALIZATION)) != 0) {
+ continue;
+ }
+
+ SmmAddMemoryRegion (
+ SmramRanges[Index].CpuStart,
+ SmramRanges[Index].PhysicalSize,
+ EfiConventionalMemory,
+ SmramRanges[Index].RegionState
+ );
+ }
+
+ //
+ // Add the allocated SMRAM regions
+ //
+ for (Index = 0; Index < SmramRangeCount; Index++) {
+ if ((SmramRanges[Index].RegionState & (EFI_ALLOCATED | EFI_NEEDS_TESTING | EFI_NEEDS_ECC_INITIALIZATION)) == 0) {
+ continue;
+ }
+
+ SmmAddMemoryRegion (
+ SmramRanges[Index].CpuStart,
+ SmramRanges[Index].PhysicalSize,
+ EfiConventionalMemory,
+ SmramRanges[Index].RegionState
+ );
+ }
+}
+
+/**
+ Internal Function. Allocate a pool by specified PoolIndex.
+
+ @param PoolType Type of pool to allocate.
+ @param PoolIndex Index which indicate the Pool size.
+ @param FreePoolHdr The returned Free pool.
+
+ @retval EFI_OUT_OF_RESOURCES Allocation failed.
+ @retval EFI_SUCCESS Pool successfully allocated.
+
+**/
+EFI_STATUS
+InternalAllocPoolByIndex (
+ IN EFI_MEMORY_TYPE PoolType,
+ IN UINTN PoolIndex,
+ OUT FREE_POOL_HEADER **FreePoolHdr
+ )
+{
+ EFI_STATUS Status;
+ FREE_POOL_HEADER *Hdr;
+ POOL_TAIL *Tail;
+ EFI_PHYSICAL_ADDRESS Address;
+ SMM_POOL_TYPE SmmPoolType;
+
+ Address = 0;
+ SmmPoolType = UefiMemoryTypeToSmmPoolType (PoolType);
+
+ ASSERT (PoolIndex <= MAX_POOL_INDEX);
+ Status = EFI_SUCCESS;
+ Hdr = NULL;
+ if (PoolIndex == MAX_POOL_INDEX) {
+ Status = SmmInternalAllocatePages (
+ AllocateAnyPages,
+ PoolType,
+ EFI_SIZE_TO_PAGES (MAX_POOL_SIZE << 1),
+ &Address,
+ FALSE
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Hdr = (FREE_POOL_HEADER *)(UINTN)Address;
+ } else if (!IsListEmpty (&mSmmPoolLists[SmmPoolType][PoolIndex])) {
+ Hdr = BASE_CR (GetFirstNode (&mSmmPoolLists[SmmPoolType][PoolIndex]), FREE_POOL_HEADER, Link);
+ RemoveEntryList (&Hdr->Link);
+ } else {
+ Status = InternalAllocPoolByIndex (PoolType, PoolIndex + 1, &Hdr);
+ if (!EFI_ERROR (Status)) {
+ Hdr->Header.Signature = 0;
+ Hdr->Header.Size >>= 1;
+ Hdr->Header.Available = TRUE;
+ Hdr->Header.Type = 0;
+ Tail = HEAD_TO_TAIL (&Hdr->Header);
+ Tail->Signature = 0;
+ Tail->Size = 0;
+ InsertHeadList (&mSmmPoolLists[SmmPoolType][PoolIndex], &Hdr->Link);
+ Hdr = (FREE_POOL_HEADER *)((UINT8 *)Hdr + Hdr->Header.Size);
+ }
+ }
+
+ if (!EFI_ERROR (Status)) {
+ Hdr->Header.Signature = POOL_HEAD_SIGNATURE;
+ Hdr->Header.Size = MIN_POOL_SIZE << PoolIndex;
+ Hdr->Header.Available = FALSE;
+ Hdr->Header.Type = PoolType;
+ Tail = HEAD_TO_TAIL (&Hdr->Header);
+ Tail->Signature = POOL_TAIL_SIGNATURE;
+ Tail->Size = Hdr->Header.Size;
+ }
+
+ *FreePoolHdr = Hdr;
+ return Status;
+}
+
+/**
+ Internal Function. Free a pool by specified PoolIndex.
+
+ @param FreePoolHdr The pool to free.
+ @param PoolTail The pointer to the pool tail.
+
+ @retval EFI_SUCCESS Pool successfully freed.
+
+**/
+EFI_STATUS
+InternalFreePoolByIndex (
+ IN FREE_POOL_HEADER *FreePoolHdr,
+ IN POOL_TAIL *PoolTail
+ )
+{
+ UINTN PoolIndex;
+ SMM_POOL_TYPE SmmPoolType;
+
+ ASSERT ((FreePoolHdr->Header.Size & (FreePoolHdr->Header.Size - 1)) == 0);
+ ASSERT (((UINTN)FreePoolHdr & (FreePoolHdr->Header.Size - 1)) == 0);
+ ASSERT (FreePoolHdr->Header.Size >= MIN_POOL_SIZE);
+
+ SmmPoolType = UefiMemoryTypeToSmmPoolType (FreePoolHdr->Header.Type);
+
+ PoolIndex = (UINTN)(HighBitSet32 ((UINT32)FreePoolHdr->Header.Size) - MIN_POOL_SHIFT);
+ FreePoolHdr->Header.Signature = 0;
+ FreePoolHdr->Header.Available = TRUE;
+ FreePoolHdr->Header.Type = 0;
+ PoolTail->Signature = 0;
+ PoolTail->Size = 0;
+ ASSERT (PoolIndex < MAX_POOL_INDEX);
+ InsertHeadList (&mSmmPoolLists[SmmPoolType][PoolIndex], &FreePoolHdr->Link);
+ return EFI_SUCCESS;
+}
+
+/**
+ Allocate pool of a particular type.
+
+ @param PoolType Type of pool to allocate.
+ @param Size The amount of pool to allocate.
+ @param Buffer The address to return a pointer to the allocated
+ pool.
+
+ @retval EFI_INVALID_PARAMETER PoolType not valid.
+ @retval EFI_OUT_OF_RESOURCES Size exceeds max pool size or allocation failed.
+ @retval EFI_SUCCESS Pool successfully allocated.
+
+**/
+EFI_STATUS
+EFIAPI
+SmmInternalAllocatePool (
+ IN EFI_MEMORY_TYPE PoolType,
+ IN UINTN Size,
+ OUT VOID **Buffer
+ )
+{
+ POOL_HEADER *PoolHdr;
+ POOL_TAIL *PoolTail;
+ FREE_POOL_HEADER *FreePoolHdr;
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS Address;
+ UINTN PoolIndex;
+ BOOLEAN HasPoolTail;
+ BOOLEAN NeedGuard;
+ UINTN NoPages;
+
+ Address = 0;
+
+ if ((PoolType != EfiRuntimeServicesCode) &&
+ (PoolType != EfiRuntimeServicesData))
+ {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ NeedGuard = IsPoolTypeToGuard (PoolType);
+ HasPoolTail = !(NeedGuard &&
+ ((PcdGet8 (PcdHeapGuardPropertyMask) & BIT7) == 0));
+
+ //
+ // Adjust the size by the pool header & tail overhead
+ //
+ Size += POOL_OVERHEAD;
+ if ((Size > MAX_POOL_SIZE) || NeedGuard) {
+ if (!HasPoolTail) {
+ Size -= sizeof (POOL_TAIL);
+ }
+
+ NoPages = EFI_SIZE_TO_PAGES (Size);
+ Status = SmmInternalAllocatePages (
+ AllocateAnyPages,
+ PoolType,
+ NoPages,
+ &Address,
+ NeedGuard
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (NeedGuard) {
+ ASSERT (VerifyMemoryGuard (Address, NoPages) == TRUE);
+ Address = (EFI_PHYSICAL_ADDRESS)(UINTN)AdjustPoolHeadA (
+ Address,
+ NoPages,
+ Size
+ );
+ }
+
+ PoolHdr = (POOL_HEADER *)(UINTN)Address;
+ PoolHdr->Signature = POOL_HEAD_SIGNATURE;
+ PoolHdr->Size = EFI_PAGES_TO_SIZE (NoPages);
+ PoolHdr->Available = FALSE;
+ PoolHdr->Type = PoolType;
+
+ if (HasPoolTail) {
+ PoolTail = HEAD_TO_TAIL (PoolHdr);
+ PoolTail->Signature = POOL_TAIL_SIGNATURE;
+ PoolTail->Size = PoolHdr->Size;
+ }
+
+ *Buffer = PoolHdr + 1;
+ return Status;
+ }
+
+ Size = (Size + MIN_POOL_SIZE - 1) >> MIN_POOL_SHIFT;
+ PoolIndex = (UINTN)HighBitSet32 ((UINT32)Size);
+ if ((Size & (Size - 1)) != 0) {
+ PoolIndex++;
+ }
+
+ Status = InternalAllocPoolByIndex (PoolType, PoolIndex, &FreePoolHdr);
+ if (!EFI_ERROR (Status)) {
+ *Buffer = &FreePoolHdr->Header + 1;
+ }
+
+ return Status;
+}
+
+/**
+ Allocate pool of a particular type.
+
+ @param PoolType Type of pool to allocate.
+ @param Size The amount of pool to allocate.
+ @param Buffer The address to return a pointer to the allocated
+ pool.
+
+ @retval EFI_INVALID_PARAMETER PoolType not valid.
+ @retval EFI_OUT_OF_RESOURCES Size exceeds max pool size or allocation failed.
+ @retval EFI_SUCCESS Pool successfully allocated.
+
+**/
+EFI_STATUS
+EFIAPI
+SmmAllocatePool (
+ IN EFI_MEMORY_TYPE PoolType,
+ IN UINTN Size,
+ OUT VOID **Buffer
+ )
+{
+ EFI_STATUS Status;
+
+ Status = SmmInternalAllocatePool (PoolType, Size, Buffer);
+ if (!EFI_ERROR (Status)) {
+ SmmCoreUpdateProfile (
+ (EFI_PHYSICAL_ADDRESS)(UINTN)RETURN_ADDRESS (0),
+ MemoryProfileActionAllocatePool,
+ PoolType,
+ Size,
+ *Buffer,
+ NULL
+ );
+ }
+
+ return Status;
+}
+
+/**
+ Frees pool.
+
+ @param Buffer The allocated pool entry to free.
+
+ @retval EFI_INVALID_PARAMETER Buffer is not a valid value.
+ @retval EFI_SUCCESS Pool successfully freed.
+
+**/
+EFI_STATUS
+EFIAPI
+SmmInternalFreePool (
+ IN VOID *Buffer
+ )
+{
+ FREE_POOL_HEADER *FreePoolHdr;
+ POOL_TAIL *PoolTail;
+ BOOLEAN HasPoolTail;
+ BOOLEAN MemoryGuarded;
+
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ FreePoolHdr = (FREE_POOL_HEADER *)((POOL_HEADER *)Buffer - 1);
+ ASSERT (FreePoolHdr->Header.Signature == POOL_HEAD_SIGNATURE);
+ ASSERT (!FreePoolHdr->Header.Available);
+ if (FreePoolHdr->Header.Signature != POOL_HEAD_SIGNATURE) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ MemoryGuarded = IsHeapGuardEnabled () &&
+ IsMemoryGuarded ((EFI_PHYSICAL_ADDRESS)(UINTN)FreePoolHdr);
+ HasPoolTail = !(MemoryGuarded &&
+ ((PcdGet8 (PcdHeapGuardPropertyMask) & BIT7) == 0));
+
+ if (HasPoolTail) {
+ PoolTail = HEAD_TO_TAIL (&FreePoolHdr->Header);
+ ASSERT (PoolTail->Signature == POOL_TAIL_SIGNATURE);
+ ASSERT (FreePoolHdr->Header.Size == PoolTail->Size);
+ if (PoolTail->Signature != POOL_TAIL_SIGNATURE) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (FreePoolHdr->Header.Size != PoolTail->Size) {
+ return EFI_INVALID_PARAMETER;
+ }
+ } else {
+ PoolTail = NULL;
+ }
+
+ if (MemoryGuarded) {
+ Buffer = AdjustPoolHeadF ((EFI_PHYSICAL_ADDRESS)(UINTN)FreePoolHdr);
+ return SmmInternalFreePages (
+ (EFI_PHYSICAL_ADDRESS)(UINTN)Buffer,
+ EFI_SIZE_TO_PAGES (FreePoolHdr->Header.Size),
+ TRUE
+ );
+ }
+
+ if (FreePoolHdr->Header.Size > MAX_POOL_SIZE) {
+ ASSERT (((UINTN)FreePoolHdr & EFI_PAGE_MASK) == 0);
+ ASSERT ((FreePoolHdr->Header.Size & EFI_PAGE_MASK) == 0);
+ return SmmInternalFreePages (
+ (EFI_PHYSICAL_ADDRESS)(UINTN)FreePoolHdr,
+ EFI_SIZE_TO_PAGES (FreePoolHdr->Header.Size),
+ FALSE
+ );
+ }
+
+ return InternalFreePoolByIndex (FreePoolHdr, PoolTail);
+}
+
+/**
+ Frees pool.
+
+ @param Buffer The allocated pool entry to free.
+
+ @retval EFI_INVALID_PARAMETER Buffer is not a valid value.
+ @retval EFI_SUCCESS Pool successfully freed.
+
+**/
+EFI_STATUS
+EFIAPI
+SmmFreePool (
+ IN VOID *Buffer
+ )
+{
+ EFI_STATUS Status;
+
+ Status = SmmInternalFreePool (Buffer);
+ if (!EFI_ERROR (Status)) {
+ SmmCoreUpdateProfile (
+ (EFI_PHYSICAL_ADDRESS)(UINTN)RETURN_ADDRESS (0),
+ MemoryProfileActionFreePool,
+ EfiMaxMemoryType,
+ 0,
+ Buffer,
+ NULL
+ );
+ }
+
+ return Status;
+}