Cc: Wu Hao <hao.a.wu@intel.com> Cc: Star Zeng <star.zeng@intel.com> Cc: Eric Dong <eric.dong@intel.com> Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Jian J Wang <jian.j.wang@intel.com> Reviewed-by: Hao Wu <hao.a.wu@intel.com>
		
			
				
	
	
		
			456 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			456 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
  SMM Memory pool management functions.
 | 
						|
 | 
						|
  Copyright (c) 2009 - 2017, Intel Corporation. All rights reserved.<BR>
 | 
						|
  This program and the accompanying materials are licensed and made available 
 | 
						|
  under the terms and conditions of the BSD License which accompanies this 
 | 
						|
  distribution.  The full text of the license may be found at        
 | 
						|
  http://opensource.org/licenses/bsd-license.php                                            
 | 
						|
 | 
						|
  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     
 | 
						|
  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             
 | 
						|
 | 
						|
**/
 | 
						|
 | 
						|
#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;
 | 
						|
  }
 | 
						|
 | 
						|
  MemoryGuarded = IsHeapGuardEnabled () &&
 | 
						|
                  IsMemoryGuarded ((EFI_PHYSICAL_ADDRESS)(UINTN)Buffer);
 | 
						|
  HasPoolTail   = !(MemoryGuarded &&
 | 
						|
                    ((PcdGet8 (PcdHeapGuardPropertyMask) & BIT7) == 0));
 | 
						|
 | 
						|
  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;
 | 
						|
  }
 | 
						|
 | 
						|
  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;
 | 
						|
}
 |