Revision: 16335
          http://sourceforge.net/p/edk2/code/16335
Author:   lzeng14
Date:     2014-11-12 03:27:48 +0000 (Wed, 12 Nov 2014)
Log Message:
-----------
MdeModulePkg DxeCore/PiSmmCore: Add UEFI memory and SMRAM profile support.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Star Zeng <[email protected]>
Reviewed-by: Jiewen Yao <[email protected]>

Modified Paths:
--------------
    trunk/edk2/MdeModulePkg/Core/Dxe/DxeMain/DxeMain.c
    trunk/edk2/MdeModulePkg/Core/Dxe/DxeMain.h
    trunk/edk2/MdeModulePkg/Core/Dxe/DxeMain.inf
    trunk/edk2/MdeModulePkg/Core/Dxe/Image/Image.c
    trunk/edk2/MdeModulePkg/Core/Dxe/Image/Image.h
    trunk/edk2/MdeModulePkg/Core/Dxe/Mem/Page.c
    trunk/edk2/MdeModulePkg/Core/Dxe/Mem/Pool.c
    trunk/edk2/MdeModulePkg/Core/PiSmmCore/Dispatcher.c
    trunk/edk2/MdeModulePkg/Core/PiSmmCore/Page.c
    trunk/edk2/MdeModulePkg/Core/PiSmmCore/PiSmmCore.c
    trunk/edk2/MdeModulePkg/Core/PiSmmCore/PiSmmCore.h
    trunk/edk2/MdeModulePkg/Core/PiSmmCore/PiSmmCore.inf
    trunk/edk2/MdeModulePkg/Core/PiSmmCore/PiSmmCorePrivateData.h
    trunk/edk2/MdeModulePkg/Core/PiSmmCore/PiSmmIpl.c
    trunk/edk2/MdeModulePkg/Core/PiSmmCore/Pool.c
    trunk/edk2/MdeModulePkg/MdeModulePkg.dec
    trunk/edk2/MdeModulePkg/MdeModulePkg.dsc
    trunk/edk2/MdeModulePkg/MdeModulePkg.uni
    
trunk/edk2/MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/BootScriptExecutorDxe.inf
    trunk/edk2/MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/ScriptExecute.c
    trunk/edk2/MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/ScriptExecute.h

Added Paths:
-----------
    trunk/edk2/MdeModulePkg/Application/MemoryProfileInfo/
    trunk/edk2/MdeModulePkg/Application/MemoryProfileInfo/MemoryProfileInfo.c
    trunk/edk2/MdeModulePkg/Application/MemoryProfileInfo/MemoryProfileInfo.inf
    trunk/edk2/MdeModulePkg/Application/MemoryProfileInfo/MemoryProfileInfo.uni
    
trunk/edk2/MdeModulePkg/Application/MemoryProfileInfo/MemoryProfileInfoExtra.uni
    trunk/edk2/MdeModulePkg/Core/Dxe/Mem/MemoryProfileRecord.c
    trunk/edk2/MdeModulePkg/Core/PiSmmCore/SmramProfileRecord.c
    trunk/edk2/MdeModulePkg/Include/Guid/MemoryProfile.h

Added: trunk/edk2/MdeModulePkg/Application/MemoryProfileInfo/MemoryProfileInfo.c
===================================================================
--- trunk/edk2/MdeModulePkg/Application/MemoryProfileInfo/MemoryProfileInfo.c   
                        (rev 0)
+++ trunk/edk2/MdeModulePkg/Application/MemoryProfileInfo/MemoryProfileInfo.c   
2014-11-12 03:27:48 UTC (rev 16335)
@@ -0,0 +1,712 @@
+/** @file
+  
+  Copyright (c) 2014, 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 <Uefi.h>
+#include <PiDxe.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiApplicationEntryPoint.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/DebugLib.h>
+#include <Library/DxeServicesLib.h>
+#include <Library/PeCoffGetEntryPointLib.h>
+#include <Library/PrintLib.h>
+
+#include <Protocol/SmmCommunication.h>
+#include <Protocol/SmmAccess2.h>
+
+#include <Guid/ZeroGuid.h>
+#include <Guid/MemoryProfile.h>
+
+CHAR16 *mActionString[] = {
+  L"Unknown",
+  L"AllocatePages",
+  L"FreePages",
+  L"AllocatePool",
+  L"FreePool",
+};
+
+CHAR16 *mMemoryTypeString[] = {
+  L"EfiReservedMemoryType",
+  L"EfiLoaderCode",
+  L"EfiLoaderData",
+  L"EfiBootServicesCode",
+  L"EfiBootServicesData",
+  L"EfiRuntimeServicesCode",
+  L"EfiRuntimeServicesData",
+  L"EfiConventionalMemory",
+  L"EfiUnusableMemory",
+  L"EfiACPIReclaimMemory",
+  L"EfiACPIMemoryNVS",
+  L"EfiMemoryMappedIO",
+  L"EfiMemoryMappedIOPortSpace",
+  L"EfiPalCode",
+  L"EfiOSReserved",
+};
+
+CHAR16 *mSubsystemString[] = {
+  L"Unknown",
+  L"NATIVE",
+  L"WINDOWS_GUI",
+  L"WINDOWS_CUI",
+  L"Unknown",
+  L"Unknown",
+  L"Unknown",
+  L"POSIX_CUI",
+  L"Unknown",
+  L"WINDOWS_CE_GUI",
+  L"EFI_APPLICATION",
+  L"EFI_BOOT_SERVICE_DRIVER",
+  L"EFI_RUNTIME_DRIVER",
+  L"EFI_ROM",
+  L"XBOX",
+  L"Unknown",
+};
+
+CHAR16 *mFileTypeString[] = {
+  L"Unknown",
+  L"RAW",
+  L"FREEFORM",
+  L"SECURITY_CORE",
+  L"PEI_CORE",
+  L"DXE_CORE",
+  L"PEIM",
+  L"DRIVER",
+  L"COMBINED_PEIM_DRIVER",
+  L"APPLICATION",
+  L"SMM",
+  L"FIRMWARE_VOLUME_IMAGE",
+  L"COMBINED_SMM_DXE",
+  L"SMM_CORE",
+};
+
+#define PROFILE_NAME_STRING_LENGTH  36
+CHAR16 mNameString[PROFILE_NAME_STRING_LENGTH + 1];
+
+/** 
+  Get the file name portion of the Pdb File Name.
+  
+  The portion of the Pdb File Name between the last backslash and
+  either a following period or the end of the string is converted
+  to Unicode and copied into UnicodeBuffer.  The name is truncated,
+  if necessary, to ensure that UnicodeBuffer is not overrun.
+  
+  @param[in]  PdbFileName     Pdb file name.
+  @param[out] UnicodeBuffer   The resultant Unicode File Name.
+  
+**/
+VOID
+GetShortPdbFileName (
+  IN  CHAR8     *PdbFileName,
+  OUT CHAR16    *UnicodeBuffer
+  )
+{
+  UINTN IndexA;     // Current work location within an ASCII string.
+  UINTN IndexU;     // Current work location within a Unicode string.
+  UINTN StartIndex;
+  UINTN EndIndex;
+
+  ZeroMem (UnicodeBuffer, PROFILE_NAME_STRING_LENGTH * sizeof (CHAR16));
+
+  if (PdbFileName == NULL) {
+    StrnCpy (UnicodeBuffer, L" ", 1);
+  } else {
+    StartIndex = 0;
+    for (EndIndex = 0; PdbFileName[EndIndex] != 0; EndIndex++);
+    for (IndexA = 0; PdbFileName[IndexA] != 0; IndexA++) {
+      if (PdbFileName[IndexA] == '\\') {
+        StartIndex = IndexA + 1;
+      }
+
+      if (PdbFileName[IndexA] == '.') {
+        EndIndex = IndexA;
+      }
+    }
+
+    IndexU = 0;
+    for (IndexA = StartIndex; IndexA < EndIndex; IndexA++) {
+      UnicodeBuffer[IndexU] = (CHAR16) PdbFileName[IndexA];
+      IndexU++;
+      if (IndexU >= PROFILE_NAME_STRING_LENGTH) {
+        UnicodeBuffer[PROFILE_NAME_STRING_LENGTH] = 0;
+        break;
+      }
+    }
+  }
+}
+
+/** 
+  Get a human readable name for an image.
+  The following methods will be tried orderly:
+    1. Image PDB
+    2. FFS UI section
+    3. Image GUID
+
+  @param[in] DriverInfo Pointer to memory profile driver info.
+
+  @post The resulting Unicode name string is stored in the mNameString global 
array.
+
+**/
+VOID
+GetDriverNameString (
+ IN MEMORY_PROFILE_DRIVER_INFO  *DriverInfo
+ )
+{
+  EFI_STATUS                  Status;
+  CHAR8                       *PdbFileName;
+  CHAR16                      *NameString;
+  UINTN                       StringSize;
+
+  //
+  // Method 1: Get the name string from image PDB
+  //
+  if ((DriverInfo->ImageBase != 0) && (DriverInfo->FileType != 
EFI_FV_FILETYPE_SMM) && (DriverInfo->FileType != EFI_FV_FILETYPE_SMM_CORE)) {
+    PdbFileName = PeCoffLoaderGetPdbPointer ((VOID *) (UINTN) 
DriverInfo->ImageBase);
+
+    if (PdbFileName != NULL) {
+      GetShortPdbFileName (PdbFileName, mNameString);
+      return;
+    }
+  }
+
+  if (!CompareGuid (&DriverInfo->FileName, &gZeroGuid)) {
+    //
+    // Try to get the image's FFS UI section by image GUID
+    //
+    NameString = NULL;
+    StringSize = 0;
+    Status = GetSectionFromAnyFv (
+              &DriverInfo->FileName,
+              EFI_SECTION_USER_INTERFACE,
+              0,
+              (VOID **) &NameString,
+              &StringSize
+              );
+    if (!EFI_ERROR (Status)) {
+      //
+      // Method 2: Get the name string from FFS UI section
+      //
+      StrnCpy (mNameString, NameString, PROFILE_NAME_STRING_LENGTH);
+      mNameString[PROFILE_NAME_STRING_LENGTH] = 0;
+      FreePool (NameString);
+      return;
+    }
+  }
+
+  //
+  // Method 3: Get the name string from image GUID
+  //
+  UnicodeSPrint (mNameString, sizeof (mNameString), L"%g", 
&DriverInfo->FileName);
+}
+
+/**
+  Dump memory profile allocate information.
+
+  @param[in] DriverInfo         Pointer to memory profile driver info.
+  @param[in] AllocIndex         Memory profile alloc info index.
+  @param[in] AllocInfo          Pointer to memory profile alloc info.
+
+  @return Pointer to next memory profile alloc info.
+
+**/
+MEMORY_PROFILE_ALLOC_INFO *
+DumpMemoryProfileAllocInfo (
+  IN MEMORY_PROFILE_DRIVER_INFO *DriverInfo,
+  IN UINTN                      AllocIndex,
+  IN MEMORY_PROFILE_ALLOC_INFO  *AllocInfo
+  )
+{
+  if (AllocInfo->Header.Signature != MEMORY_PROFILE_ALLOC_INFO_SIGNATURE) {
+    return NULL;
+  }
+  Print (L"    MEMORY_PROFILE_ALLOC_INFO (0x%x)\n", AllocIndex);
+  Print (L"      Signature     - 0x%08x\n", AllocInfo->Header.Signature);
+  Print (L"      Length        - 0x%04x\n", AllocInfo->Header.Length);
+  Print (L"      Revision      - 0x%04x\n", AllocInfo->Header.Revision);  
+  Print (L"      CallerAddress - 0x%016lx (Offset: 0x%08x)\n", 
AllocInfo->CallerAddress, (UINTN) (AllocInfo->CallerAddress - 
DriverInfo->ImageBase));
+  Print (L"      SequenceId    - 0x%08x\n", AllocInfo->SequenceId);
+  Print (L"      Action        - 0x%08x (%s)\n", AllocInfo->Action, 
mActionString[(AllocInfo->Action < 
sizeof(mActionString)/sizeof(mActionString[0])) ? AllocInfo->Action : 0]);
+  Print (L"      MemoryType    - 0x%08x (%s)\n", AllocInfo->MemoryType, 
mMemoryTypeString[(AllocInfo->MemoryType < 
sizeof(mMemoryTypeString)/sizeof(mMemoryTypeString[0])) ? AllocInfo->MemoryType 
: (sizeof(mMemoryTypeString)/sizeof(mMemoryTypeString[0]) - 1)]);
+  Print (L"      Buffer        - 0x%016lx\n", AllocInfo->Buffer);
+  Print (L"      Size          - 0x%016lx\n", AllocInfo->Size);
+
+  return (MEMORY_PROFILE_ALLOC_INFO *) ((UINTN) AllocInfo + 
AllocInfo->Header.Length);
+}
+
+/**
+  Dump memory profile driver information.
+
+  @param[in] DriverIndex        Memory profile driver info index.
+  @param[in] DriverInfo         Pointer to memory profile driver info.
+
+  @return Pointer to next memory profile driver info.
+
+**/
+MEMORY_PROFILE_DRIVER_INFO *
+DumpMemoryProfileDriverInfo (
+  IN UINTN                      DriverIndex,
+  IN MEMORY_PROFILE_DRIVER_INFO *DriverInfo
+  )
+{
+  UINTN                         TypeIndex;
+  MEMORY_PROFILE_ALLOC_INFO     *AllocInfo;
+  UINTN                         AllocIndex;
+
+  if (DriverInfo->Header.Signature != MEMORY_PROFILE_DRIVER_INFO_SIGNATURE) {
+    return NULL;
+  }
+  Print (L"  MEMORY_PROFILE_DRIVER_INFO (0x%x)\n", DriverIndex);
+  Print (L"    Signature               - 0x%08x\n", 
DriverInfo->Header.Signature);
+  Print (L"    Length                  - 0x%04x\n", DriverInfo->Header.Length);
+  Print (L"    Revision                - 0x%04x\n", 
DriverInfo->Header.Revision);  
+  GetDriverNameString (DriverInfo);
+  Print (L"    FileName                - %s\n", &mNameString);
+  Print (L"    ImageBase               - 0x%016lx\n", DriverInfo->ImageBase);
+  Print (L"    ImageSize               - 0x%016lx\n", DriverInfo->ImageSize);
+  Print (L"    EntryPoint              - 0x%016lx\n", DriverInfo->EntryPoint);
+  Print (L"    ImageSubsystem          - 0x%04x (%s)\n", 
DriverInfo->ImageSubsystem, mSubsystemString[(DriverInfo->ImageSubsystem < 
sizeof(mSubsystemString)/sizeof(mSubsystemString[0])) ? 
DriverInfo->ImageSubsystem : 0]);
+  Print (L"    FileType                - 0x%02x (%s)\n", DriverInfo->FileType, 
mFileTypeString[(DriverInfo->FileType < 
sizeof(mFileTypeString)/sizeof(mFileTypeString[0])) ? DriverInfo->FileType : 
0]);
+  Print (L"    CurrentUsage            - 0x%016lx\n", 
DriverInfo->CurrentUsage);
+  Print (L"    PeakUsage               - 0x%016lx\n", DriverInfo->PeakUsage);
+  for (TypeIndex = 0; TypeIndex <= EfiMaxMemoryType; TypeIndex++) {
+    if ((DriverInfo->CurrentUsageByType[TypeIndex] != 0) ||
+        (DriverInfo->PeakUsageByType[TypeIndex] != 0)) {
+      Print (L"    CurrentUsage[0x%02x]      - 0x%016lx (%s)\n", TypeIndex, 
DriverInfo->CurrentUsageByType[TypeIndex], mMemoryTypeString[TypeIndex]);
+      Print (L"    PeakUsage[0x%02x]         - 0x%016lx (%s)\n", TypeIndex, 
DriverInfo->PeakUsageByType[TypeIndex], mMemoryTypeString[TypeIndex]);
+    }
+  }
+  Print (L"    AllocRecordCount        - 0x%08x\n", 
DriverInfo->AllocRecordCount);
+
+  AllocInfo = (MEMORY_PROFILE_ALLOC_INFO *) ((UINTN) DriverInfo + 
DriverInfo->Header.Length);
+  for (AllocIndex = 0; AllocIndex < DriverInfo->AllocRecordCount; 
AllocIndex++) {
+    AllocInfo = DumpMemoryProfileAllocInfo (DriverInfo, AllocIndex, AllocInfo);
+    if (AllocInfo == NULL) {
+      return NULL;
+    }
+  }
+  return (MEMORY_PROFILE_DRIVER_INFO *) AllocInfo;
+}
+
+/**
+  Dump memory profile context information.
+
+  @param[in] Context            Pointer to memory profile context.
+
+  @return Pointer to the end of memory profile context buffer.
+
+**/
+VOID *
+DumpMemoryProfileContext (
+  IN MEMORY_PROFILE_CONTEXT     *Context
+  )
+{
+  UINTN                         TypeIndex;
+  MEMORY_PROFILE_DRIVER_INFO    *DriverInfo;
+  UINTN                         DriverIndex;
+
+  if (Context->Header.Signature != MEMORY_PROFILE_CONTEXT_SIGNATURE) {
+    return NULL;
+  }
+  Print (L"MEMORY_PROFILE_CONTEXT\n");
+  Print (L"  Signature                     - 0x%08x\n", 
Context->Header.Signature);
+  Print (L"  Length                        - 0x%04x\n", 
Context->Header.Length);
+  Print (L"  Revision                      - 0x%04x\n", 
Context->Header.Revision);  
+  Print (L"  CurrentTotalUsage             - 0x%016lx\n", 
Context->CurrentTotalUsage);
+  Print (L"  PeakTotalUsage                - 0x%016lx\n", 
Context->PeakTotalUsage);
+  for (TypeIndex = 0; TypeIndex <= EfiMaxMemoryType; TypeIndex++) {
+    if ((Context->CurrentTotalUsageByType[TypeIndex] != 0) ||
+        (Context->PeakTotalUsageByType[TypeIndex] != 0)) {
+      Print (L"  CurrentTotalUsage[0x%02x]       - 0x%016lx (%s)\n", 
TypeIndex, Context->CurrentTotalUsageByType[TypeIndex], 
mMemoryTypeString[TypeIndex]);
+      Print (L"  PeakTotalUsage[0x%02x]          - 0x%016lx (%s)\n", 
TypeIndex, Context->PeakTotalUsageByType[TypeIndex], 
mMemoryTypeString[TypeIndex]);
+    }
+  }
+  Print (L"  TotalImageSize                - 0x%016lx\n", 
Context->TotalImageSize);
+  Print (L"  ImageCount                    - 0x%08x\n", Context->ImageCount);
+  Print (L"  SequenceCount                 - 0x%08x\n", 
Context->SequenceCount);
+
+  DriverInfo = (MEMORY_PROFILE_DRIVER_INFO *) ((UINTN) Context + 
Context->Header.Length);
+  for (DriverIndex = 0; DriverIndex < Context->ImageCount; DriverIndex++) {
+    DriverInfo = DumpMemoryProfileDriverInfo (DriverIndex, DriverInfo);
+    if (DriverInfo == NULL) {
+      return NULL;
+    }
+  }
+  return (VOID *) DriverInfo;
+}
+
+/**
+  Dump memory profile descriptor information.
+
+  @param[in] DescriptorIndex    Memory profile descriptor index.
+  @param[in] Descriptor         Pointer to memory profile descriptor.
+
+  @return Pointer to next memory profile descriptor.
+
+**/
+MEMORY_PROFILE_DESCRIPTOR *
+DumpMemoryProfileDescriptor (
+  IN UINTN                      DescriptorIndex,
+  IN MEMORY_PROFILE_DESCRIPTOR  *Descriptor
+  )
+{
+  if (Descriptor->Header.Signature != MEMORY_PROFILE_DESCRIPTOR_SIGNATURE) {
+    return NULL;
+  }
+  Print (L"  MEMORY_PROFILE_DESCRIPTOR (0x%x)\n", DescriptorIndex);
+  Print (L"    Signature               - 0x%08x\n", 
Descriptor->Header.Signature);
+  Print (L"    Length                  - 0x%04x\n", Descriptor->Header.Length);
+  Print (L"    Revision                - 0x%04x\n", 
Descriptor->Header.Revision);  
+  Print (L"    Address                 - 0x%016lx\n", Descriptor->Address);
+  Print (L"    Size                    - 0x%016lx\n", Descriptor->Size);
+
+  return (MEMORY_PROFILE_DESCRIPTOR *) ((UINTN) Descriptor + 
Descriptor->Header.Length);
+}
+
+/**
+  Dump memory profile free memory information.
+
+  @param[in] FreeMemory         Pointer to memory profile free memory.
+
+  @return Pointer to the end of memory profile free memory buffer.
+
+**/
+VOID *
+DumpMemoryProfileFreeMemory (
+  IN MEMORY_PROFILE_FREE_MEMORY *FreeMemory
+  )
+{
+  MEMORY_PROFILE_DESCRIPTOR     *Descriptor;
+  UINTN                         DescriptorIndex;
+
+  if (FreeMemory->Header.Signature != MEMORY_PROFILE_FREE_MEMORY_SIGNATURE) {
+    return NULL;
+  }
+  Print (L"MEMORY_PROFILE_FREE_MEMORY\n");
+  Print (L"  Signature                     - 0x%08x\n", 
FreeMemory->Header.Signature);
+  Print (L"  Length                        - 0x%04x\n", 
FreeMemory->Header.Length);
+  Print (L"  Revision                      - 0x%04x\n", 
FreeMemory->Header.Revision);  
+  Print (L"  TotalFreeMemoryPages          - 0x%016lx\n", 
FreeMemory->TotalFreeMemoryPages);
+  Print (L"  FreeMemoryEntryCount          - 0x%08x\n", 
FreeMemory->FreeMemoryEntryCount);
+
+  Descriptor = (MEMORY_PROFILE_DESCRIPTOR *) ((UINTN) FreeMemory + 
FreeMemory->Header.Length);
+  for (DescriptorIndex = 0; DescriptorIndex < 
FreeMemory->FreeMemoryEntryCount; DescriptorIndex++) {
+    Descriptor = DumpMemoryProfileDescriptor (DescriptorIndex, Descriptor);
+    if (Descriptor == NULL) {
+      return NULL;
+    }
+  }
+
+  return (VOID *) Descriptor;
+}
+
+/**
+  Dump memory profile memory range information.
+
+  @param[in] MemoryRange        Pointer to memory profile memory range.
+
+  @return Pointer to the end of memory profile memory range buffer.
+
+**/
+VOID *
+DumpMemoryProfileMemoryRange (
+  IN MEMORY_PROFILE_MEMORY_RANGE    *MemoryRange
+  )
+{
+  MEMORY_PROFILE_DESCRIPTOR     *Descriptor;
+  UINTN                         DescriptorIndex;
+
+  if (MemoryRange->Header.Signature != MEMORY_PROFILE_MEMORY_RANGE_SIGNATURE) {
+    return NULL;
+  }
+  Print (L"MEMORY_PROFILE_MEMORY_RANGE\n");
+  Print (L"  Signature                     - 0x%08x\n", 
MemoryRange->Header.Signature);
+  Print (L"  Length                        - 0x%04x\n", 
MemoryRange->Header.Length);
+  Print (L"  Revision                      - 0x%04x\n", 
MemoryRange->Header.Revision);  
+  Print (L"  MemoryRangeCount              - 0x%08x\n", 
MemoryRange->MemoryRangeCount);
+
+  Descriptor = (MEMORY_PROFILE_DESCRIPTOR *) ((UINTN) MemoryRange + 
MemoryRange->Header.Length);
+  for (DescriptorIndex = 0; DescriptorIndex < MemoryRange->MemoryRangeCount; 
DescriptorIndex++) {
+    Descriptor = DumpMemoryProfileDescriptor (DescriptorIndex, Descriptor);
+    if (Descriptor == NULL) {
+      return NULL;
+    }
+  }
+
+  return (VOID *) Descriptor;
+}
+
+/**
+  Scan memory profile by Signature.
+
+  @param[in] ProfileBuffer      Memory profile base address.
+  @param[in] ProfileSize        Memory profile size.
+  @param[in] Signature          Signature.
+
+  @return Pointer to the stucture with the signature.
+
+**/
+VOID *
+ScanMemoryProfileBySignature (
+  IN PHYSICAL_ADDRESS           ProfileBuffer,
+  IN UINT64                     ProfileSize,
+  IN UINT32                     Signature
+  )
+{
+  MEMORY_PROFILE_COMMON_HEADER  *CommonHeader;
+  UINTN                          ProfileEnd;
+
+  ProfileEnd = (UINTN) (ProfileBuffer + ProfileSize);
+  CommonHeader = (MEMORY_PROFILE_COMMON_HEADER *) (UINTN) ProfileBuffer;
+  while ((UINTN) CommonHeader < ProfileEnd) {
+    if (CommonHeader->Signature == Signature) {
+      //
+      // Found it.
+      //
+      return (VOID *) CommonHeader;
+    }
+    CommonHeader = (MEMORY_PROFILE_COMMON_HEADER *) ((UINTN) CommonHeader + 
CommonHeader->Length);
+  }
+
+  return NULL;
+}
+
+/**
+  Dump memory profile information.
+
+  @param[in] ProfileBuffer      Memory profile base address.
+  @param[in] ProfileSize        Memory profile size.
+
+**/
+VOID
+DumpMemoryProfile (
+  IN PHYSICAL_ADDRESS           ProfileBuffer,
+  IN UINT64                     ProfileSize
+  )
+{
+  MEMORY_PROFILE_CONTEXT        *Context;
+  MEMORY_PROFILE_FREE_MEMORY    *FreeMemory;
+  MEMORY_PROFILE_MEMORY_RANGE   *MemoryRange;
+
+  Context = (MEMORY_PROFILE_CONTEXT *) ScanMemoryProfileBySignature 
(ProfileBuffer, ProfileSize, MEMORY_PROFILE_CONTEXT_SIGNATURE);
+  if (Context != NULL) {
+    DumpMemoryProfileContext (Context);
+  }
+
+  FreeMemory = (MEMORY_PROFILE_FREE_MEMORY *) ScanMemoryProfileBySignature 
(ProfileBuffer, ProfileSize, MEMORY_PROFILE_FREE_MEMORY_SIGNATURE);
+  if (FreeMemory != NULL) {
+    DumpMemoryProfileFreeMemory (FreeMemory);
+  }
+
+  MemoryRange = (MEMORY_PROFILE_MEMORY_RANGE *) ScanMemoryProfileBySignature 
(ProfileBuffer, ProfileSize, MEMORY_PROFILE_MEMORY_RANGE_SIGNATURE);
+  if (MemoryRange != NULL) {
+    DumpMemoryProfileMemoryRange (MemoryRange);
+  }
+}
+
+/**
+  Get and dump UEFI memory profile data.
+
+  @return EFI_SUCCESS   Get the memory profile data successfully.
+  @return other         Fail to get the memory profile data.
+
+**/
+EFI_STATUS
+GetUefiMemoryProfileData (
+  VOID
+  )
+{
+  EFI_STATUS                    Status;
+  EDKII_MEMORY_PROFILE_PROTOCOL *ProfileProtocol;
+  VOID                          *Data;
+  UINT64                        Size;
+
+  Status = gBS->LocateProtocol (&gEdkiiMemoryProfileGuid, NULL, (VOID **) 
&ProfileProtocol);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((EFI_D_ERROR, "UefiMemoryProfile: Locate MemoryProfile protocol - 
%r\n", Status));
+    return Status;
+  }
+
+  Size = 0;
+  Data = NULL;
+  Status = ProfileProtocol->GetData (
+                              ProfileProtocol,
+                              &Size,
+                              Data
+                              );
+  if (Status != EFI_BUFFER_TOO_SMALL) {
+    Print (L"UefiMemoryProfile: GetData - %r\n", Status);
+    return Status;
+  }
+
+  //
+  // Add one sizeof (MEMORY_PROFILE_ALLOC_INFO) to Size for this AllocatePool 
action.
+  //
+  Size = Size + sizeof (MEMORY_PROFILE_ALLOC_INFO);
+  Data = AllocateZeroPool ((UINTN) Size);
+  if (Data == NULL) {
+    Print (L"UefiMemoryProfile: AllocateZeroPool (0x%x) - %r\n", Size, Status);
+    return Status;
+  }
+
+  Status = ProfileProtocol->GetData (
+                              ProfileProtocol,
+                              &Size,
+                              Data
+                              );
+  if (EFI_ERROR (Status)) {
+    FreePool (Data);
+    Print (L"UefiMemoryProfile: GetData - %r\n", Status);
+    return Status;
+  }
+
+
+  Print (L"UefiMemoryProfileSize - 0x%x\n", Size);
+  Print (L"======= UefiMemoryProfile begin =======\n");
+  DumpMemoryProfile ((PHYSICAL_ADDRESS) (UINTN) Data, Size);
+  Print (L"======= UefiMemoryProfile end =======\n\n\n");
+
+  FreePool (Data);
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Get and dump SMRAM profile data.
+
+  @return EFI_SUCCESS   Get the SMRAM profile data successfully.
+  @return other         Fail to get the SMRAM profile data.
+
+**/
+EFI_STATUS
+GetSmramProfileData (
+  VOID
+  )
+{
+  EFI_STATUS                                    Status;
+  UINTN                                         CommSize;
+  UINT8                                         CommBuffer[sizeof (EFI_GUID) + 
sizeof (UINTN) + sizeof (SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA)];
+  EFI_SMM_COMMUNICATE_HEADER                    *CommHeader;
+  SMRAM_PROFILE_PARAMETER_GET_PROFILE_INFO      *CommGetProfileInfo;
+  SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA      *CommGetProfileData;
+  UINT64                                        ProfileSize;
+  PHYSICAL_ADDRESS                              ProfileBuffer;
+  EFI_SMM_COMMUNICATION_PROTOCOL                *SmmCommunication;
+
+  Status = gBS->LocateProtocol (&gEfiSmmCommunicationProtocolGuid, NULL, (VOID 
**) &SmmCommunication);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((EFI_D_ERROR, "SmramProfile: Locate SmmCommunication protocol - 
%r\n", Status));
+    return Status;
+  }
+
+  //
+  // Get Size
+  //
+  CommHeader = (EFI_SMM_COMMUNICATE_HEADER *) &CommBuffer[0];
+  CopyMem (&CommHeader->HeaderGuid, &gEdkiiMemoryProfileGuid, sizeof 
(gEdkiiMemoryProfileGuid));
+  CommHeader->MessageLength = sizeof 
(SMRAM_PROFILE_PARAMETER_GET_PROFILE_INFO);
+
+  CommGetProfileInfo = (SMRAM_PROFILE_PARAMETER_GET_PROFILE_INFO *) 
&CommBuffer[OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data)];
+  CommGetProfileInfo->Header.Command      = 
SMRAM_PROFILE_COMMAND_GET_PROFILE_INFO;
+  CommGetProfileInfo->Header.DataLength   = sizeof (*CommGetProfileInfo);
+  CommGetProfileInfo->Header.ReturnStatus = (UINT64)-1;
+  CommGetProfileInfo->ProfileSize         = 0;
+
+  CommSize = sizeof (EFI_GUID) + sizeof (UINTN) + CommHeader->MessageLength;
+  Status = SmmCommunication->Communicate (SmmCommunication, CommBuffer, 
&CommSize);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((EFI_D_ERROR, "SmramProfile: SmmCommunication - %r\n", Status));
+    return Status;
+  }
+
+  if (CommGetProfileInfo->Header.ReturnStatus != 0) {
+    Print (L"SmramProfile: GetProfileInfo - 0x%0x\n", 
CommGetProfileInfo->Header.ReturnStatus);
+    return EFI_SUCCESS;
+  }
+
+  ProfileSize = CommGetProfileInfo->ProfileSize;
+
+  //
+  // Get Data
+  //
+  ProfileBuffer = (PHYSICAL_ADDRESS) (UINTN) AllocateZeroPool ((UINTN) 
ProfileSize);
+  if (ProfileBuffer == 0) {
+    Print (L"UefiMemoryProfile: AllocateZeroPool (0x%x) - %r\n", (UINTN) 
ProfileSize, Status);
+    return EFI_SUCCESS;
+  }
+
+  CommHeader = (EFI_SMM_COMMUNICATE_HEADER *) &CommBuffer[0];
+  CopyMem (&CommHeader->HeaderGuid, &gEdkiiMemoryProfileGuid, 
sizeof(gEdkiiMemoryProfileGuid));
+  CommHeader->MessageLength = sizeof 
(SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA);
+
+  CommGetProfileData = (SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA 
*)&CommBuffer[OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data)];
+  CommGetProfileData->Header.Command      = 
SMRAM_PROFILE_COMMAND_GET_PROFILE_DATA;
+  CommGetProfileData->Header.DataLength   = sizeof (*CommGetProfileData);
+  CommGetProfileData->Header.ReturnStatus = (UINT64)-1;
+  CommGetProfileData->ProfileSize         = ProfileSize;
+  CommGetProfileData->ProfileBuffer       = ProfileBuffer;
+
+  CommSize = sizeof (EFI_GUID) + sizeof (UINTN) + CommHeader->MessageLength;
+  Status = SmmCommunication->Communicate (SmmCommunication, CommBuffer, 
&CommSize);
+  ASSERT_EFI_ERROR (Status);
+
+  if (CommGetProfileData->Header.ReturnStatus != 0) {
+    Print (L"GetProfileData - 0x%x\n", 
CommGetProfileData->Header.ReturnStatus);
+    return EFI_SUCCESS;
+  }
+
+
+  Print (L"SmramProfileSize - 0x%x\n", CommGetProfileData->ProfileSize);
+  Print (L"======= SmramProfile begin =======\n");
+  DumpMemoryProfile (CommGetProfileData->ProfileBuffer, 
CommGetProfileData->ProfileSize);
+  Print (L"======= SmramProfile end =======\n\n\n");
+
+  FreePool ((VOID *) (UINTN) CommGetProfileData->ProfileBuffer);
+
+  return EFI_SUCCESS;
+}
+
+/**
+  The user Entry Point for Application. The user code starts with this function
+  as the real entry point for the image goes into a library that calls this 
function.
+
+  @param[in] ImageHandle    The firmware allocated handle for the EFI image.  
+  @param[in] SystemTable    A pointer to the EFI System Table.
+  
+  @retval EFI_SUCCESS       The entry point is executed successfully.
+  @retval other             Some error occurs when executing this entry point.
+
+**/
+EFI_STATUS
+EFIAPI
+UefiMain (
+  IN EFI_HANDLE         ImageHandle,
+  IN EFI_SYSTEM_TABLE   *SystemTable
+  )
+{
+  EFI_STATUS                    Status;
+
+  Status = GetUefiMemoryProfileData ();
+  if (EFI_ERROR (Status)) {
+    DEBUG ((EFI_D_ERROR, "GetUefiMemoryProfileData - %r\n", Status));
+  }
+
+  Status = GetSmramProfileData ();
+  if (EFI_ERROR (Status)) {
+    DEBUG ((EFI_D_ERROR, "GetSmramProfileData - %r\n", Status));
+  }
+
+  return EFI_SUCCESS;
+}

Added: 
trunk/edk2/MdeModulePkg/Application/MemoryProfileInfo/MemoryProfileInfo.inf
===================================================================
--- trunk/edk2/MdeModulePkg/Application/MemoryProfileInfo/MemoryProfileInfo.inf 
                        (rev 0)
+++ trunk/edk2/MdeModulePkg/Application/MemoryProfileInfo/MemoryProfileInfo.inf 
2014-11-12 03:27:48 UTC (rev 16335)
@@ -0,0 +1,62 @@
+## @file
+#  Shell application to dump UEFI memory and SMRAM profile information.
+#
+#  Note that if the feature is not enabled by setting 
PcdMemoryProfilePropertyMask,
+#  the application will not display memory profile information.
+#
+#  Copyright (c) 2014, 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.
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = MemoryProfileInfo
+  MODULE_UNI_FILE                = MemoryProfileInfo.uni
+  FILE_GUID                      = 21429B90-5F67-4e93-AF55-1D314D646E12
+  MODULE_TYPE                    = UEFI_APPLICATION
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = UefiMain
+
+#
+# The following information is for reference only and not required by the 
build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64 IPF EBC
+#
+
+[Sources]
+  MemoryProfileInfo.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+  UefiApplicationEntryPoint
+  BaseLib
+  BaseMemoryLib
+  UefiBootServicesTableLib
+  UefiRuntimeServicesTableLib
+  DebugLib
+  UefiLib
+  MemoryAllocationLib
+  DxeServicesLib
+  PeCoffGetEntryPointLib
+  PrintLib
+  
+[Guids]
+  ## SOMETIMES_CONSUMES   ## GUID # Locate protocol
+  ## SOMETIMES_CONSUMES   ## GUID # SmiHandlerRegister
+  gEdkiiMemoryProfileGuid
+  gZeroGuid                            ## SOMETIMES_CONSUMES   ## GUID
+
+[Protocols]
+  gEfiSmmCommunicationProtocolGuid     ## SOMETIMES_CONSUMES
+
+[UserExtensions.TianoCore."ExtraFiles"]
+  MemoryProfileInfoExtra.uni

Added: 
trunk/edk2/MdeModulePkg/Application/MemoryProfileInfo/MemoryProfileInfo.uni
===================================================================
(Binary files differ)

Index: 
trunk/edk2/MdeModulePkg/Application/MemoryProfileInfo/MemoryProfileInfo.uni
===================================================================
--- trunk/edk2/MdeModulePkg/Application/MemoryProfileInfo/MemoryProfileInfo.uni 
2014-11-12 03:18:09 UTC (rev 16334)
+++ trunk/edk2/MdeModulePkg/Application/MemoryProfileInfo/MemoryProfileInfo.uni 
2014-11-12 03:27:48 UTC (rev 16335)

Property changes on: 
trunk/edk2/MdeModulePkg/Application/MemoryProfileInfo/MemoryProfileInfo.uni
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Added: 
trunk/edk2/MdeModulePkg/Application/MemoryProfileInfo/MemoryProfileInfoExtra.uni
===================================================================
(Binary files differ)

Index: 
trunk/edk2/MdeModulePkg/Application/MemoryProfileInfo/MemoryProfileInfoExtra.uni
===================================================================
--- 
trunk/edk2/MdeModulePkg/Application/MemoryProfileInfo/MemoryProfileInfoExtra.uni
    2014-11-12 03:18:09 UTC (rev 16334)
+++ 
trunk/edk2/MdeModulePkg/Application/MemoryProfileInfo/MemoryProfileInfoExtra.uni
    2014-11-12 03:27:48 UTC (rev 16335)

Property changes on: 
trunk/edk2/MdeModulePkg/Application/MemoryProfileInfo/MemoryProfileInfoExtra.uni
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Modified: trunk/edk2/MdeModulePkg/Core/Dxe/DxeMain/DxeMain.c
===================================================================
--- trunk/edk2/MdeModulePkg/Core/Dxe/DxeMain/DxeMain.c  2014-11-12 03:18:09 UTC 
(rev 16334)
+++ trunk/edk2/MdeModulePkg/Core/Dxe/DxeMain/DxeMain.c  2014-11-12 03:27:48 UTC 
(rev 16335)
@@ -268,6 +268,8 @@
   //
   CoreInitializeMemoryServices (&HobStart, &MemoryBaseAddress, &MemoryLength);
 
+  MemoryProfileInit (HobStart);
+
   //
   // Allocate the EFI System Table and EFI Runtime Service Table from 
EfiRuntimeServicesData
   // Use the templates to initialize the contents of the EFI System Table and 
EFI Runtime Services Table
@@ -382,6 +384,8 @@
   Status = CoreInitializeEventServices ();
   ASSERT_EFI_ERROR (Status);
 
+  MemoryProfileInstallProtocol ();
+
   //
   // Get persisted vector hand-off info from GUIDeed HOB again due to HobStart 
may be updated,
   // and install configuration table

Modified: trunk/edk2/MdeModulePkg/Core/Dxe/DxeMain.h
===================================================================
--- trunk/edk2/MdeModulePkg/Core/Dxe/DxeMain.h  2014-11-12 03:18:09 UTC (rev 
16334)
+++ trunk/edk2/MdeModulePkg/Core/Dxe/DxeMain.h  2014-11-12 03:27:48 UTC (rev 
16335)
@@ -69,6 +69,8 @@
 #include <Guid/IdleLoopEvent.h>
 #include <Guid/VectorHandoffTable.h>
 #include <Ppi/VectorHandoffInfo.h>
+#include <Guid/ZeroGuid.h>
+#include <Guid/MemoryProfile.h>
 
 #include <Library/DxeCoreEntryPoint.h>
 #include <Library/DebugLib.h>
@@ -191,6 +193,56 @@
   EFI_HANDLE            DeviceHandle;
 } EFI_GCD_MAP_ENTRY;
 
+
+#define LOADED_IMAGE_PRIVATE_DATA_SIGNATURE   SIGNATURE_32('l','d','r','i')
+
+typedef struct {
+  UINTN                       Signature;
+  /// Image handle
+  EFI_HANDLE                  Handle;   
+  /// Image type
+  UINTN                       Type;           
+  /// If entrypoint has been called
+  BOOLEAN                     Started;        
+  /// The image's entry point
+  EFI_IMAGE_ENTRY_POINT       EntryPoint;     
+  /// loaded image protocol
+  EFI_LOADED_IMAGE_PROTOCOL   Info;           
+  /// Location in memory
+  EFI_PHYSICAL_ADDRESS        ImageBasePage;  
+  /// Number of pages
+  UINTN                       NumberOfPages;  
+  /// Original fixup data
+  CHAR8                       *FixupData;     
+  /// Tpl of started image
+  EFI_TPL                     Tpl;            
+  /// Status returned by started image
+  EFI_STATUS                  Status;         
+  /// Size of ExitData from started image
+  UINTN                       ExitDataSize;   
+  /// Pointer to exit data from started image
+  VOID                        *ExitData;      
+  /// Pointer to pool allocation for context save/retore
+  VOID                        *JumpBuffer;    
+  /// Pointer to buffer for context save/retore
+  BASE_LIBRARY_JUMP_BUFFER    *JumpContext;  
+  /// Machine type from PE image
+  UINT16                      Machine;        
+  /// EBC Protocol pointer
+  EFI_EBC_PROTOCOL            *Ebc;           
+  /// Runtime image list
+  EFI_RUNTIME_IMAGE_ENTRY     *RuntimeData;   
+  /// Pointer to Loaded Image Device Path Protocl
+  EFI_DEVICE_PATH_PROTOCOL    *LoadedImageDevicePath;  
+  /// PeCoffLoader ImageContext
+  PE_COFF_LOADER_IMAGE_CONTEXT  ImageContext; 
+  /// Status returned by LoadImage() service.
+  EFI_STATUS                  LoadImageStatus;
+} LOADED_IMAGE_PRIVATE_DATA;
+
+#define LOADED_IMAGE_PRIVATE_DATA_FROM_THIS(a) \
+          CR(a, LOADED_IMAGE_PRIVATE_DATA, Info, 
LOADED_IMAGE_PRIVATE_DATA_SIGNATURE)
+
 //
 // DXE Core Global Variables
 //
@@ -1192,8 +1244,33 @@
   IN OUT EFI_PHYSICAL_ADDRESS  *Memory
   );
 
+/**
+  Allocates pages from the memory map.
 
+  @param  Type                   The type of allocation to perform
+  @param  MemoryType             The type of memory to turn the allocated pages
+                                 into
+  @param  NumberOfPages          The number of pages to allocate
+  @param  Memory                 A pointer to receive the base allocated memory
+                                 address
 
+  @return Status. On success, Memory is filled in with the base address 
allocated
+  @retval EFI_INVALID_PARAMETER  Parameters violate checking rules defined in
+                                 spec.
+  @retval EFI_NOT_FOUND          Could not allocate pages match the 
requirement.
+  @retval EFI_OUT_OF_RESOURCES   No enough pages to allocate.
+  @retval EFI_SUCCESS            Pages successfully allocated.
+
+**/
+EFI_STATUS
+EFIAPI
+CoreInternalAllocatePages (
+  IN EFI_ALLOCATE_TYPE      Type,
+  IN EFI_MEMORY_TYPE        MemoryType,
+  IN UINTN                  NumberOfPages,
+  IN OUT EFI_PHYSICAL_ADDRESS  *Memory
+  );
+
 /**
   Frees previous allocated pages.
 
@@ -1212,8 +1289,24 @@
   IN UINTN                  NumberOfPages
   );
 
+/**
+  Frees previous allocated pages.
 
+  @param  Memory                 Base address of memory being freed
+  @param  NumberOfPages          The number of pages to free
 
+  @retval EFI_NOT_FOUND          Could not find the entry that covers the range
+  @retval EFI_INVALID_PARAMETER  Address not aligned
+  @return EFI_SUCCESS         -Pages successfully freed.
+
+**/
+EFI_STATUS
+EFIAPI
+CoreInternalFreePages (
+  IN EFI_PHYSICAL_ADDRESS   Memory,
+  IN UINTN                  NumberOfPages
+  );
+
 /**
   This function returns a copy of the current memory map. The map is an array 
of
   memory descriptors, each of which describes a contiguous block of memory.
@@ -1277,8 +1370,27 @@
   OUT VOID            **Buffer
   );
 
+/**
+  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 or Buffer is NULL
+  @retval EFI_OUT_OF_RESOURCES   Size exceeds max pool size or allocation 
failed.
+  @retval EFI_SUCCESS            Pool successfully allocated.
+
+**/
+EFI_STATUS
+EFIAPI
+CoreInternalAllocatePool (
+  IN EFI_MEMORY_TYPE  PoolType,
+  IN UINTN            Size,
+  OUT VOID            **Buffer
+  );
+
 /**
   Frees pool.
 
@@ -1294,8 +1406,21 @@
   IN VOID        *Buffer
   );
 
+/**
+  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
+CoreInternalFreePool (
+  IN VOID        *Buffer
+  );
+
 /**
   Loads an EFI image into memory and returns a handle to the image.
 
@@ -2619,4 +2744,76 @@
   IN EFI_FIRMWARE_VOLUME_HEADER *FvHeader
   );
 
+/**
+  Initialize memory profile.
+
+  @param HobStart   The start address of the HOB.
+
+**/
+VOID
+MemoryProfileInit (
+  IN VOID   *HobStart
+  );
+
+/**
+  Install memory profile protocol.
+
+**/
+VOID
+MemoryProfileInstallProtocol (
+  VOID
+  );
+
+/**
+  Register image to memory profile.
+
+  @param DriverEntry    Image info.
+  @param FileType       Image file type.
+
+  @retval TRUE          Register success.
+  @retval FALSE         Register fail.
+
+**/
+BOOLEAN
+RegisterMemoryProfileImage (
+  IN LOADED_IMAGE_PRIVATE_DATA  *DriverEntry,
+  IN EFI_FV_FILETYPE            FileType
+  );
+
+/**
+  Unregister image from memory profile.
+
+  @param DriverEntry    Image info.
+
+  @retval TRUE          Unregister success.
+  @retval FALSE         Unregister fail.
+
+**/
+BOOLEAN
+UnregisterMemoryProfileImage (
+  IN LOADED_IMAGE_PRIVATE_DATA  *DriverEntry
+  );
+
+/**
+  Update memory profile information.
+
+  @param CallerAddress  Address of caller who call Allocate or Free.
+  @param Action         This Allocate or Free action.
+  @param MemoryType     Memory type.
+  @param Size           Buffer size.
+  @param Buffer         Buffer address.
+
+  @retval TRUE          Profile udpate success.
+  @retval FALSE         Profile update fail.
+
+**/
+BOOLEAN
+CoreUpdateProfile (
+  IN EFI_PHYSICAL_ADDRESS   CallerAddress,
+  IN MEMORY_PROFILE_ACTION  Action,
+  IN EFI_MEMORY_TYPE        MemoryType, // Valid for AllocatePages/AllocatePool
+  IN UINTN                  Size,       // Valid for 
AllocatePages/FreePages/AllocatePool
+  IN VOID                   *Buffer
+  );
+
 #endif

Modified: trunk/edk2/MdeModulePkg/Core/Dxe/DxeMain.inf
===================================================================
--- trunk/edk2/MdeModulePkg/Core/Dxe/DxeMain.inf        2014-11-12 03:18:09 UTC 
(rev 16334)
+++ trunk/edk2/MdeModulePkg/Core/Dxe/DxeMain.inf        2014-11-12 03:27:48 UTC 
(rev 16335)
@@ -52,6 +52,7 @@
   Mem/Page.c
   Mem/MemData.c
   Mem/Imem.h
+  Mem/MemoryProfileRecord.c
   FwVolBlock/FwVolBlock.c
   FwVolBlock/FwVolBlock.h
   FwVol/FwVolWrite.c
@@ -120,6 +121,8 @@
   gIdleLoopEventGuid
   gEventExitBootServicesFailedGuid              ## SOMETIMES_PRODUCES   ## 
Event
   gEfiVectorHandoffTableGuid                    ## SOMETIMES_PRODUCES   ## 
SystemTable
+  gEdkiiMemoryProfileGuid                       ## SOMETIMES_PRODUCES   ## 
GUID # Install protocol
+  gZeroGuid                                     ## SOMETIMES_CONSUMES   ## GUID
 
 [Ppis]
   gEfiVectorHandoffInfoPpiGuid                  ## UNDEFINED # HOB
@@ -177,6 +180,8 @@
   gEfiMdeModulePkgTokenSpaceGuid.PcdLoadFixAddressRuntimeCodePageNumber     ## 
SOMETIMES_CONSUMES
   gEfiMdeModulePkgTokenSpaceGuid.PcdLoadModuleAtFixAddressEnable            ## 
CONSUMES
   gEfiMdeModulePkgTokenSpaceGuid.PcdMaxEfiSystemTablePointerAddress         ## 
CONSUMES
+  gEfiMdeModulePkgTokenSpaceGuid.PcdMemoryProfileMemoryType                 ## 
CONSUMES
+  gEfiMdeModulePkgTokenSpaceGuid.PcdMemoryProfilePropertyMask               ## 
CONSUMES
 
 # [Hob]
 # RESOURCE_DESCRIPTOR   ## CONSUMES
@@ -190,4 +195,4 @@
 #
 
 [UserExtensions.TianoCore."ExtraFiles"]
-  DxeCoreExtra.uni
\ No newline at end of file
+  DxeCoreExtra.uni

Modified: trunk/edk2/MdeModulePkg/Core/Dxe/Image/Image.c
===================================================================
--- trunk/edk2/MdeModulePkg/Core/Dxe/Image/Image.c      2014-11-12 03:18:09 UTC 
(rev 16334)
+++ trunk/edk2/MdeModulePkg/Core/Dxe/Image/Image.c      2014-11-12 03:27:48 UTC 
(rev 16335)
@@ -1626,6 +1626,7 @@
   // Subsequent calls to LongJump() cause a non-zero value to be returned by 
SetJump().
   //
   if (SetJumpFlag == 0) {
+    RegisterMemoryProfileImage (Image, (Image->ImageContext.ImageType == 
EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION ? EFI_FV_FILETYPE_APPLICATION : 
EFI_FV_FILETYPE_DRIVER));
     //
     // Call the image's entry point
     //
@@ -1851,6 +1852,7 @@
     Status = EFI_INVALID_PARAMETER;
     goto Done;
   }
+  UnregisterMemoryProfileImage (Image);
 
   if (Image->Started) {
     //

Modified: trunk/edk2/MdeModulePkg/Core/Dxe/Image/Image.h
===================================================================
--- trunk/edk2/MdeModulePkg/Core/Dxe/Image/Image.h      2014-11-12 03:18:09 UTC 
(rev 16334)
+++ trunk/edk2/MdeModulePkg/Core/Dxe/Image/Image.h      2014-11-12 03:27:48 UTC 
(rev 16335)
@@ -16,56 +16,6 @@
 #ifndef _IMAGE_H_
 #define _IMAGE_H_
 
-#define LOADED_IMAGE_PRIVATE_DATA_SIGNATURE   SIGNATURE_32('l','d','r','i')
-
-typedef struct {
-  UINTN                       Signature;
-  /// Image handle
-  EFI_HANDLE                  Handle;   
-  /// Image type
-  UINTN                       Type;           
-  /// If entrypoint has been called
-  BOOLEAN                     Started;        
-  /// The image's entry point
-  EFI_IMAGE_ENTRY_POINT       EntryPoint;     
-  /// loaded image protocol
-  EFI_LOADED_IMAGE_PROTOCOL   Info;           
-  /// Location in memory
-  EFI_PHYSICAL_ADDRESS        ImageBasePage;  
-  /// Number of pages
-  UINTN                       NumberOfPages;  
-  /// Original fixup data
-  CHAR8                       *FixupData;     
-  /// Tpl of started image
-  EFI_TPL                     Tpl;            
-  /// Status returned by started image
-  EFI_STATUS                  Status;         
-  /// Size of ExitData from started image
-  UINTN                       ExitDataSize;   
-  /// Pointer to exit data from started image
-  VOID                        *ExitData;      
-  /// Pointer to pool allocation for context save/retore
-  VOID                        *JumpBuffer;    
-  /// Pointer to buffer for context save/retore
-  BASE_LIBRARY_JUMP_BUFFER    *JumpContext;  
-  /// Machine type from PE image
-  UINT16                      Machine;        
-  /// EBC Protocol pointer
-  EFI_EBC_PROTOCOL            *Ebc;           
-  /// Runtime image list
-  EFI_RUNTIME_IMAGE_ENTRY     *RuntimeData;   
-  /// Pointer to Loaded Image Device Path Protocl
-  EFI_DEVICE_PATH_PROTOCOL    *LoadedImageDevicePath;  
-  /// PeCoffLoader ImageContext
-  PE_COFF_LOADER_IMAGE_CONTEXT  ImageContext; 
-  /// Status returned by LoadImage() service.
-  EFI_STATUS                  LoadImageStatus;
-} LOADED_IMAGE_PRIVATE_DATA;
-
-#define LOADED_IMAGE_PRIVATE_DATA_FROM_THIS(a) \
-          CR(a, LOADED_IMAGE_PRIVATE_DATA, Info, 
LOADED_IMAGE_PRIVATE_DATA_SIGNATURE)
-
-
 #define LOAD_PE32_IMAGE_PRIVATE_DATA_SIGNATURE  SIGNATURE_32('l','p','e','i')
 
 typedef struct {

Added: trunk/edk2/MdeModulePkg/Core/Dxe/Mem/MemoryProfileRecord.c
===================================================================
--- trunk/edk2/MdeModulePkg/Core/Dxe/Mem/MemoryProfileRecord.c                  
        (rev 0)
+++ trunk/edk2/MdeModulePkg/Core/Dxe/Mem/MemoryProfileRecord.c  2014-11-12 
03:27:48 UTC (rev 16335)
@@ -0,0 +1,1377 @@
+/** @file
+  Support routines for UEFI memory profile.
+
+  Copyright (c) 2014, 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 "DxeMain.h"
+
+#define IS_UEFI_MEMORY_PROFILE_ENABLED ((PcdGet8 
(PcdMemoryProfilePropertyMask) & BIT0) != 0)
+
+typedef struct {
+  UINT32                        Signature;
+  MEMORY_PROFILE_CONTEXT        Context;
+  LIST_ENTRY                    *DriverInfoList;
+} MEMORY_PROFILE_CONTEXT_DATA;
+
+typedef struct {
+  UINT32                        Signature;
+  MEMORY_PROFILE_DRIVER_INFO    DriverInfo;
+  LIST_ENTRY                    *AllocInfoList;
+  LIST_ENTRY                    Link;
+} MEMORY_PROFILE_DRIVER_INFO_DATA;
+
+typedef struct {
+  UINT32                        Signature;
+  MEMORY_PROFILE_ALLOC_INFO     AllocInfo;
+  LIST_ENTRY                    Link;
+} MEMORY_PROFILE_ALLOC_INFO_DATA;
+
+
+GLOBAL_REMOVE_IF_UNREFERENCED LIST_ENTRY  mImageQueue = 
INITIALIZE_LIST_HEAD_VARIABLE (mImageQueue);
+GLOBAL_REMOVE_IF_UNREFERENCED MEMORY_PROFILE_CONTEXT_DATA 
mMemoryProfileContext = {
+  MEMORY_PROFILE_CONTEXT_SIGNATURE,
+  {
+    {
+      MEMORY_PROFILE_CONTEXT_SIGNATURE,
+      sizeof (MEMORY_PROFILE_CONTEXT),
+      MEMORY_PROFILE_CONTEXT_REVISION
+    },
+    0,
+    0,
+    {0},
+    {0},
+    0,
+    0,
+    0
+  },
+  &mImageQueue,
+};
+GLOBAL_REMOVE_IF_UNREFERENCED MEMORY_PROFILE_CONTEXT_DATA 
*mMemoryProfileContextPtr = NULL;
+
+BOOLEAN mMemoryProfileRecordingStatus = FALSE;
+
+/**
+  Get memory profile data.
+
+  @param[in]      This              The EDKII_MEMORY_PROFILE_PROTOCOL instance.
+  @param[in, out] ProfileSize       On entry, points to the size in bytes of 
the ProfileBuffer.
+                                    On return, points to the size of the data 
returned in ProfileBuffer.
+  @param[out]     ProfileBuffer     Profile buffer.
+                      
+  @return EFI_SUCCESS               Get the memory profile data successfully.
+  @return EFI_BUFFER_TO_SMALL       The ProfileSize is too small for the 
resulting data. 
+                                    ProfileSize is updated with the size 
required.
+
+**/
+EFI_STATUS
+EFIAPI
+ProfileProtocolGetData (
+  IN     EDKII_MEMORY_PROFILE_PROTOCOL  *This,
+  IN OUT UINT64                         *ProfileSize,
+     OUT VOID                           *ProfileBuffer
+  );
+
+/**
+  Register image to memory profile.
+
+  @param[in] This               The EDKII_MEMORY_PROFILE_PROTOCOL instance.
+  @param[in] FilePath           File path of the image.
+  @param[in] ImageBase          Image base address.
+  @param[in] ImageSize          Image size.
+  @param[in] FileType           File type of the image.
+
+  @return EFI_SUCCESS           Register success.
+  @return EFI_OUT_OF_RESOURCE   No enough resource for this register.
+
+**/
+EFI_STATUS
+EFIAPI
+ProfileProtocolRegisterImage (
+  IN EDKII_MEMORY_PROFILE_PROTOCOL      *This,
+  IN EFI_DEVICE_PATH_PROTOCOL           *FilePath,
+  IN PHYSICAL_ADDRESS                   ImageBase,
+  IN UINT64                             ImageSize,
+  IN EFI_FV_FILETYPE                    FileType
+  );
+
+/**
+  Unregister image from memory profile.
+
+  @param[in] This               The EDKII_MEMORY_PROFILE_PROTOCOL instance.
+  @param[in] FilePath           File path of the image.
+  @param[in] ImageBase          Image base address.
+  @param[in] ImageSize          Image size.
+
+  @return EFI_SUCCESS           Unregister success.
+  @return EFI_NOT_FOUND         The image is not found.
+
+**/
+EFI_STATUS
+EFIAPI
+ProfileProtocolUnregisterImage (
+  IN EDKII_MEMORY_PROFILE_PROTOCOL      *This,
+  IN EFI_DEVICE_PATH_PROTOCOL           *FilePath,
+  IN PHYSICAL_ADDRESS                   ImageBase,
+  IN UINT64                             ImageSize
+  );
+
+EDKII_MEMORY_PROFILE_PROTOCOL mProfileProtocol = {
+  ProfileProtocolGetData,
+  ProfileProtocolRegisterImage,
+  ProfileProtocolUnregisterImage
+};
+
+/**
+  Return memory profile context.
+
+  @return Memory profile context.
+
+**/
+MEMORY_PROFILE_CONTEXT_DATA *
+GetMemoryProfileContext (
+  VOID
+  )
+{
+  return mMemoryProfileContextPtr;
+}
+
+/**
+  Retrieves the magic value from the PE/COFF header.
+
+  @param Hdr    The buffer in which to return the PE32, PE32+, or TE header.
+
+  @return EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC - Image is PE32
+  @return EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC - Image is PE32+
+
+**/
+UINT16
+InternalPeCoffGetPeHeaderMagicValue (
+  IN  EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION  Hdr
+  )
+{
+  //
+  // NOTE: Some versions of Linux ELILO for Itanium have an incorrect magic 
value
+  //       in the PE/COFF Header.  If the MachineType is Itanium(IA64) and the
+  //       Magic value in the OptionalHeader is  
EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
+  //       then override the returned value to 
EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
+  //
+  if (Hdr.Pe32->FileHeader.Machine == IMAGE_FILE_MACHINE_IA64 && 
Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
+    return EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;
+  }
+  //
+  // Return the magic value from the PC/COFF Optional Header
+  //
+  return Hdr.Pe32->OptionalHeader.Magic;
+}
+
+/**
+  Retrieves and returns the Subsystem of a PE/COFF image that has been loaded 
into system memory.
+  If Pe32Data is NULL, then ASSERT().
+
+  @param Pe32Data   The pointer to the PE/COFF image that is loaded in system 
memory.
+
+  @return The Subsystem of the PE/COFF image.
+
+**/
+UINT16
+InternalPeCoffGetSubsystem (
+  IN VOID  *Pe32Data
+  )
+{
+  EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION  Hdr;
+  EFI_IMAGE_DOS_HEADER                 *DosHdr;
+  UINT16                               Magic;
+
+  ASSERT (Pe32Data != NULL);
+
+  DosHdr = (EFI_IMAGE_DOS_HEADER *) Pe32Data;
+  if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {
+    //
+    // DOS image header is present, so read the PE header after the DOS image 
header.
+    //
+    Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *) ((UINTN) Pe32Data + (UINTN) 
((DosHdr->e_lfanew) & 0x0ffff));
+  } else {
+    //
+    // DOS image header is not present, so PE header is at the image base.
+    //
+    Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *) Pe32Data;
+  }
+
+  if (Hdr.Te->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {
+    return Hdr.Te->Subsystem;
+  } else if (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE)  {
+    Magic = InternalPeCoffGetPeHeaderMagicValue (Hdr);
+    if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
+      return Hdr.Pe32->OptionalHeader.Subsystem;
+    } else if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
+      return Hdr.Pe32Plus->OptionalHeader.Subsystem;
+    }
+  }
+
+  return 0x0000;
+}
+
+/**
+  Retrieves and returns a pointer to the entry point to a PE/COFF image that 
has been loaded
+  into system memory with the PE/COFF Loader Library functions.
+
+  Retrieves the entry point to the PE/COFF image specified by Pe32Data and 
returns this entry
+  point in EntryPoint.  If the entry point could not be retrieved from the 
PE/COFF image, then
+  return RETURN_INVALID_PARAMETER.  Otherwise return RETURN_SUCCESS.
+  If Pe32Data is NULL, then ASSERT().
+  If EntryPoint is NULL, then ASSERT().
+
+  @param  Pe32Data                  The pointer to the PE/COFF image that is 
loaded in system memory.
+  @param  EntryPoint                The pointer to entry point to the PE/COFF 
image to return.
+
+  @retval RETURN_SUCCESS            EntryPoint was returned.
+  @retval RETURN_INVALID_PARAMETER  The entry point could not be found in the 
PE/COFF image.
+
+**/
+RETURN_STATUS
+InternalPeCoffGetEntryPoint (
+  IN  VOID  *Pe32Data,
+  OUT VOID  **EntryPoint
+  )
+{
+  EFI_IMAGE_DOS_HEADER                  *DosHdr;
+  EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION   Hdr;
+
+  ASSERT (Pe32Data   != NULL);
+  ASSERT (EntryPoint != NULL);
+
+  DosHdr = (EFI_IMAGE_DOS_HEADER *) Pe32Data;
+  if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {
+    //
+    // DOS image header is present, so read the PE header after the DOS image 
header.
+    //
+    Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *) ((UINTN) Pe32Data + (UINTN) 
((DosHdr->e_lfanew) & 0x0ffff));
+  } else {
+    //
+    // DOS image header is not present, so PE header is at the image base.
+    //
+    Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *) Pe32Data;
+  }
+
+  //
+  // Calculate the entry point relative to the start of the image.
+  // AddressOfEntryPoint is common for PE32 & PE32+
+  //
+  if (Hdr.Te->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {
+    *EntryPoint = (VOID *) ((UINTN) Pe32Data + (UINTN) 
(Hdr.Te->AddressOfEntryPoint & 0x0ffffffff) + sizeof (EFI_TE_IMAGE_HEADER) - 
Hdr.Te->StrippedSize);
+    return RETURN_SUCCESS;
+  } else if (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE) {
+    *EntryPoint = (VOID *) ((UINTN) Pe32Data + (UINTN) 
(Hdr.Pe32->OptionalHeader.AddressOfEntryPoint & 0x0ffffffff));
+    return RETURN_SUCCESS;
+  }
+
+  return RETURN_UNSUPPORTED;
+}
+
+/**
+  Build driver info.
+
+  @param ContextData    Memory profile context.
+  @param FileName       File name of the image.
+  @param ImageBase      Image base address.
+  @param ImageSize      Image size.
+  @param EntryPoint     Entry point of the image.
+  @param ImageSubsystem Image subsystem of the image.
+  @param FileType       File type of the image.
+
+  @return Pointer to memory profile driver info.
+
+**/
+MEMORY_PROFILE_DRIVER_INFO_DATA *
+BuildDriverInfo (
+  IN MEMORY_PROFILE_CONTEXT_DATA    *ContextData,
+  IN EFI_GUID                       *FileName,
+  IN PHYSICAL_ADDRESS               ImageBase,
+  IN UINT64                         ImageSize,
+  IN PHYSICAL_ADDRESS               EntryPoint,
+  IN UINT16                         ImageSubsystem,
+  IN EFI_FV_FILETYPE                FileType
+  )
+{
+  EFI_STATUS                        Status;
+  MEMORY_PROFILE_DRIVER_INFO        *DriverInfo;
+  MEMORY_PROFILE_DRIVER_INFO_DATA   *DriverInfoData;
+  VOID                              *EntryPointInImage;
+
+  //
+  // Use CoreInternalAllocatePool() that will not update profile for this 
AllocatePool action.
+  //
+  Status = CoreInternalAllocatePool (
+             EfiBootServicesData,
+             sizeof (*DriverInfoData) + sizeof (LIST_ENTRY),
+             (VOID **) &DriverInfoData
+             );
+  if (EFI_ERROR (Status)) {
+    return NULL;
+  }
+
+  ZeroMem (DriverInfoData, sizeof (*DriverInfoData));
+
+  DriverInfo = &DriverInfoData->DriverInfo;
+  DriverInfoData->Signature = MEMORY_PROFILE_DRIVER_INFO_SIGNATURE;
+  DriverInfo->Header.Signature = MEMORY_PROFILE_DRIVER_INFO_SIGNATURE;
+  DriverInfo->Header.Length = sizeof (MEMORY_PROFILE_DRIVER_INFO);
+  DriverInfo->Header.Revision = MEMORY_PROFILE_DRIVER_INFO_REVISION;
+  if (FileName != NULL) {
+    CopyMem (&DriverInfo->FileName, FileName, sizeof (EFI_GUID));
+  }
+  DriverInfo->ImageBase = ImageBase;
+  DriverInfo->ImageSize = ImageSize;
+  DriverInfo->EntryPoint = EntryPoint;
+  DriverInfo->ImageSubsystem = ImageSubsystem;
+  if ((EntryPoint != 0) && ((EntryPoint < ImageBase) || (EntryPoint >= 
(ImageBase + ImageSize)))) {
+    //
+    // If the EntryPoint is not in the range of image buffer, it should come 
from emulation environment.
+    // So patch ImageBuffer here to align the EntryPoint.
+    //
+    Status = InternalPeCoffGetEntryPoint ((VOID *) (UINTN) ImageBase, 
&EntryPointInImage);
+    ASSERT_EFI_ERROR (Status);
+    DriverInfo->ImageBase = ImageBase + EntryPoint - (PHYSICAL_ADDRESS) 
(UINTN) EntryPointInImage;
+  }
+  DriverInfo->FileType = FileType;
+  DriverInfoData->AllocInfoList = (LIST_ENTRY *) (DriverInfoData + 1);
+  InitializeListHead (DriverInfoData->AllocInfoList);
+  DriverInfo->CurrentUsage = 0;
+  DriverInfo->PeakUsage = 0;
+  DriverInfo->AllocRecordCount = 0;
+
+  InsertTailList (ContextData->DriverInfoList, &DriverInfoData->Link);
+  ContextData->Context.ImageCount ++;
+  ContextData->Context.TotalImageSize += DriverInfo->ImageSize;
+
+  return DriverInfoData;
+}
+
+/**
+  Register DXE Core to memory profile.
+
+  @param HobStart       The start address of the HOB.
+  @param ContextData    Memory profile context.
+
+  @retval TRUE      Register success.
+  @retval FALSE     Register fail.
+
+**/
+BOOLEAN
+RegisterDxeCore (
+  IN VOID                           *HobStart,
+  IN MEMORY_PROFILE_CONTEXT_DATA    *ContextData
+  )
+{
+  EFI_PEI_HOB_POINTERS              DxeCoreHob;
+  MEMORY_PROFILE_DRIVER_INFO_DATA   *DriverInfoData;
+  PHYSICAL_ADDRESS                  ImageBase;
+
+  ASSERT (ContextData != NULL);
+
+  //
+  // Searching for image hob
+  //
+  DxeCoreHob.Raw          = HobStart;
+  while ((DxeCoreHob.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, 
DxeCoreHob.Raw)) != NULL) {
+    if (CompareGuid 
(&DxeCoreHob.MemoryAllocationModule->MemoryAllocationHeader.Name, 
&gEfiHobMemoryAllocModuleGuid)) {
+      //
+      // Find Dxe Core HOB
+      //
+      break;
+    }
+    DxeCoreHob.Raw = GET_NEXT_HOB (DxeCoreHob);
+  }
+  ASSERT (DxeCoreHob.Raw != NULL);
+
+  ImageBase = 
DxeCoreHob.MemoryAllocationModule->MemoryAllocationHeader.MemoryBaseAddress;
+  DriverInfoData = BuildDriverInfo (
+                     ContextData,
+                     &DxeCoreHob.MemoryAllocationModule->ModuleName,
+                     ImageBase,
+                     
DxeCoreHob.MemoryAllocationModule->MemoryAllocationHeader.MemoryLength,
+                     DxeCoreHob.MemoryAllocationModule->EntryPoint,
+                     InternalPeCoffGetSubsystem ((VOID *) (UINTN) ImageBase),
+                     EFI_FV_FILETYPE_DXE_CORE
+                     );
+  if (DriverInfoData == NULL) {
+    return FALSE;
+  }
+
+  return TRUE;
+}
+
+/**
+  Initialize memory profile.
+
+  @param HobStart   The start address of the HOB.
+
+**/
+VOID
+MemoryProfileInit (
+  IN VOID   *HobStart
+  )
+{
+  MEMORY_PROFILE_CONTEXT_DATA   *ContextData;
+
+  if (!IS_UEFI_MEMORY_PROFILE_ENABLED) {
+    return;
+  }
+
+  ContextData = GetMemoryProfileContext ();
+  if (ContextData != NULL) {
+    return;
+  }
+
+  mMemoryProfileRecordingStatus = TRUE;
+  mMemoryProfileContextPtr = &mMemoryProfileContext;
+
+  RegisterDxeCore (HobStart, &mMemoryProfileContext);
+
+  DEBUG ((EFI_D_INFO, "MemoryProfileInit MemoryProfileContext - 0x%x\n", 
&mMemoryProfileContext));
+}
+
+/**
+  Install memory profile protocol.
+
+**/
+VOID
+MemoryProfileInstallProtocol (
+  VOID
+  )
+{
+  EFI_HANDLE    Handle;
+  EFI_STATUS    Status;
+
+  if (!IS_UEFI_MEMORY_PROFILE_ENABLED) {
+    return;
+  }
+
+  Handle = NULL;
+  Status = CoreInstallMultipleProtocolInterfaces (
+             &Handle,
+             &gEdkiiMemoryProfileGuid,
+             &mProfileProtocol,
+             NULL
+             );
+  ASSERT_EFI_ERROR (Status);
+}
+
+/**
+  Get the GUID file name from the file path.
+
+  @param FilePath  File path.
+
+  @return The GUID file name from the file path.
+
+**/
+EFI_GUID *
+GetFileNameFromFilePath (
+  IN EFI_DEVICE_PATH_PROTOCOL   *FilePath
+  )
+{
+  MEDIA_FW_VOL_FILEPATH_DEVICE_PATH     *ThisFilePath;
+  EFI_GUID                              *FileName;
+
+  FileName = NULL;
+  ThisFilePath = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) FilePath;
+  while (!IsDevicePathEnd (ThisFilePath)) {
+    FileName = EfiGetNameGuidFromFwVolDevicePathNode (ThisFilePath);
+    if (FileName != NULL) {
+      break;
+    }
+    ThisFilePath = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) NextDevicePathNode 
(ThisFilePath);
+  }
+
+  return FileName;
+}
+
+/**
+  Register image to memory profile.
+
+  @param DriverEntry    Image info.
+  @param FileType       Image file type.
+
+  @retval TRUE          Register success.
+  @retval FALSE         Register fail.
+
+**/
+BOOLEAN
+RegisterMemoryProfileImage (
+  IN LOADED_IMAGE_PRIVATE_DATA  *DriverEntry,
+  IN EFI_FV_FILETYPE            FileType
+  )
+{
+  MEMORY_PROFILE_CONTEXT_DATA       *ContextData;
+  MEMORY_PROFILE_DRIVER_INFO_DATA   *DriverInfoData;
+
+  if (!IS_UEFI_MEMORY_PROFILE_ENABLED) {
+    return FALSE;
+  }
+
+  ContextData = GetMemoryProfileContext ();
+  if (ContextData == NULL) {
+    return FALSE;
+  }
+
+  DriverInfoData = BuildDriverInfo (
+                     ContextData,
+                     GetFileNameFromFilePath (DriverEntry->Info.FilePath),
+                     DriverEntry->ImageContext.ImageAddress,
+                     DriverEntry->ImageContext.ImageSize,
+                     DriverEntry->ImageContext.EntryPoint,
+                     DriverEntry->ImageContext.ImageType,
+                     FileType
+                     );
+  if (DriverInfoData == NULL) {
+    return FALSE;
+  }
+
+  return TRUE;
+}
+
+/**
+  Search image from memory profile.
+
+  @param ContextData    Memory profile context.
+  @param FileName       Image file name.
+  @param Address        Image Address.
+
+  @return Pointer to memory profile driver info.
+
+**/
+MEMORY_PROFILE_DRIVER_INFO_DATA *
+GetMemoryProfileDriverInfoByFileNameAndAddress (
+  IN MEMORY_PROFILE_CONTEXT_DATA    *ContextData,
+  IN EFI_GUID                       *FileName,
+  IN PHYSICAL_ADDRESS               Address
+  )
+{
+  MEMORY_PROFILE_DRIVER_INFO        *DriverInfo;
+  MEMORY_PROFILE_DRIVER_INFO_DATA   *DriverInfoData;
+  LIST_ENTRY                        *DriverLink;
+  LIST_ENTRY                        *DriverInfoList;
+
+  DriverInfoList = ContextData->DriverInfoList;
+
+  for (DriverLink = DriverInfoList->ForwardLink;
+       DriverLink != DriverInfoList;
+       DriverLink = DriverLink->ForwardLink) {
+    DriverInfoData = CR (
+                       DriverLink,
+                       MEMORY_PROFILE_DRIVER_INFO_DATA,
+                       Link,
+                       MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
+                       );
+    DriverInfo = &DriverInfoData->DriverInfo;
+    if ((CompareGuid (&DriverInfo->FileName, FileName)) &&
+        (Address >= DriverInfo->ImageBase) &&
+        (Address < (DriverInfo->ImageBase + DriverInfo->ImageSize))) {
+      return DriverInfoData;
+    }
+  }
+
+  return NULL;
+}
+
+/**
+  Search dummy image from memory profile.
+
+  @param ContextData    Memory profile context.
+
+  @return Pointer to memory profile driver info.
+
+**/
+MEMORY_PROFILE_DRIVER_INFO_DATA *
+FindDummyImage (
+  IN MEMORY_PROFILE_CONTEXT_DATA    *ContextData
+  )
+{
+  MEMORY_PROFILE_DRIVER_INFO_DATA   *DriverInfoData;
+  LIST_ENTRY                        *DriverLink;
+  LIST_ENTRY                        *DriverInfoList;
+
+  DriverInfoList = ContextData->DriverInfoList;
+
+  for (DriverLink = DriverInfoList->ForwardLink;
+       DriverLink != DriverInfoList;
+       DriverLink = DriverLink->ForwardLink) {
+    DriverInfoData = CR (
+                   DriverLink,
+                   MEMORY_PROFILE_DRIVER_INFO_DATA,
+                   Link,
+                   MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
+                   );
+    if (CompareGuid (&gZeroGuid, &DriverInfoData->DriverInfo.FileName)) {
+      return DriverInfoData;
+    }
+  }
+
+  return BuildDriverInfo (ContextData, &gZeroGuid, 0, 0, 0, 0, 0);
+}
+
+/**
+  Search image from memory profile.
+  It will return image, if (Address >= ImageBuffer) AND (Address < ImageBuffer 
+ ImageSize)
+
+  @param ContextData    Memory profile context.
+  @param Address        Image or Function address.
+
+  @return Pointer to memory profile driver info.
+
+**/
+MEMORY_PROFILE_DRIVER_INFO_DATA *
+GetMemoryProfileDriverInfoFromAddress (
+  IN MEMORY_PROFILE_CONTEXT_DATA    *ContextData,
+  IN PHYSICAL_ADDRESS               Address
+  )
+{
+  MEMORY_PROFILE_DRIVER_INFO        *DriverInfo;
+  MEMORY_PROFILE_DRIVER_INFO_DATA   *DriverInfoData;
+  LIST_ENTRY                        *DriverLink;
+  LIST_ENTRY                        *DriverInfoList;
+
+  DriverInfoList = ContextData->DriverInfoList;
+
+  for (DriverLink = DriverInfoList->ForwardLink;
+       DriverLink != DriverInfoList;
+       DriverLink = DriverLink->ForwardLink) {
+    DriverInfoData = CR (
+                       DriverLink,
+                       MEMORY_PROFILE_DRIVER_INFO_DATA,
+                       Link,
+                       MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
+                       );
+    DriverInfo = &DriverInfoData->DriverInfo;
+    if ((Address >= DriverInfo->ImageBase) &&
+        (Address < (DriverInfo->ImageBase + DriverInfo->ImageSize))) {
+      return DriverInfoData;
+    }
+  }
+
+  //
+  // Should never come here.
+  //
+  return FindDummyImage (ContextData);
+}
+
+/**
+  Unregister image from memory profile.
+
+  @param DriverEntry    Image info.
+
+  @retval TRUE          Unregister success.
+  @retval FALSE         Unregister fail.
+
+**/
+BOOLEAN
+UnregisterMemoryProfileImage (
+  IN LOADED_IMAGE_PRIVATE_DATA      *DriverEntry
+  )
+{
+  EFI_STATUS                        Status;
+  MEMORY_PROFILE_CONTEXT_DATA       *ContextData;
+  MEMORY_PROFILE_DRIVER_INFO_DATA   *DriverInfoData;
+  EFI_GUID                          *FileName;
+  PHYSICAL_ADDRESS                  ImageAddress;
+  VOID                              *EntryPointInImage;
+
+  if (!IS_UEFI_MEMORY_PROFILE_ENABLED) {
+    return FALSE;
+  }
+
+  ContextData = GetMemoryProfileContext ();
+  if (ContextData == NULL) {
+    return FALSE;
+  }
+
+  DriverInfoData = NULL;
+  FileName = GetFileNameFromFilePath (DriverEntry->Info.FilePath);
+  ImageAddress = DriverEntry->ImageContext.ImageAddress;
+  if ((DriverEntry->ImageContext.EntryPoint < ImageAddress) || 
(DriverEntry->ImageContext.EntryPoint >= (ImageAddress + 
DriverEntry->ImageContext.ImageSize))) {
+    //
+    // If the EntryPoint is not in the range of image buffer, it should come 
from emulation environment.
+    // So patch ImageAddress here to align the EntryPoint.
+    //
+    Status = InternalPeCoffGetEntryPoint ((VOID *) (UINTN) ImageAddress, 
&EntryPointInImage);
+    ASSERT_EFI_ERROR (Status);
+    ImageAddress = ImageAddress + (UINTN) DriverEntry->ImageContext.EntryPoint 
- (UINTN) EntryPointInImage;
+  }
+  if (FileName != NULL) {
+    DriverInfoData = GetMemoryProfileDriverInfoByFileNameAndAddress 
(ContextData, FileName, ImageAddress);
+  }
+  if (DriverInfoData == NULL) {
+    DriverInfoData = GetMemoryProfileDriverInfoFromAddress (ContextData, 
ImageAddress);
+  }
+  if (DriverInfoData == NULL) {
+    return FALSE;
+  }
+
+  ContextData->Context.TotalImageSize -= DriverInfoData->DriverInfo.ImageSize;
+
+  DriverInfoData->DriverInfo.ImageBase = 0;
+  DriverInfoData->DriverInfo.ImageSize = 0;
+
+  if (DriverInfoData->DriverInfo.PeakUsage == 0) {
+    ContextData->Context.ImageCount --;
+    RemoveEntryList (&DriverInfoData->Link);
+    //
+    // Use CoreInternalFreePool() that will not update profile for this 
FreePool action.
+    //
+    CoreInternalFreePool (DriverInfoData);
+  }
+
+  return TRUE;
+}
+
+/**
+  Return if this memory type needs to be recorded into memory profile.
+  If BIOS memory type (0 ~ EfiMaxMemoryType), it checks bit (1 << MemoryType).
+  If OS memory type (0x80000000 ~ 0xFFFFFFFF), it checks bit63 - 
0x8000000000000000.
+
+  @param MemoryType     Memory type.
+
+  @retval TRUE          This memory type need to be recorded.
+  @retval FALSE         This memory type need not to be recorded.
+
+**/
+BOOLEAN
+CoreNeedRecordProfile (
+  IN EFI_MEMORY_TYPE    MemoryType
+  )
+{
+  UINT64 TestBit;
+
+  if ((UINT32) MemoryType >= 0x80000000) {
+    TestBit = BIT63;
+  } else {
+    TestBit = LShiftU64 (1, MemoryType);
+  }
+
+  if ((PcdGet64 (PcdMemoryProfileMemoryType) & TestBit) != 0) {
+    return TRUE;
+  } else {
+    return FALSE;
+  }
+}
+
+/**
+  Convert EFI memory type to profile memory index. The rule is:
+  If BIOS memory type (0 ~ EfiMaxMemoryType), ProfileMemoryIndex = MemoryType.
+  If OS memory type (0x80000000 ~ 0xFFFFFFFF), ProfileMemoryIndex = 
EfiMaxMemoryType.
+
+  @param MemoryType     Memory type.
+
+  @return EFI memory type as profile memory index.
+
+**/
+EFI_MEMORY_TYPE
+GetProfileMemoryIndex (
+  IN EFI_MEMORY_TYPE    MemoryType
+  )
+{
+  if ((UINT32) MemoryType >= 0x80000000) {
+    return EfiMaxMemoryType;
+  } else {
+    return MemoryType;
+  }
+}
+
+/**
+  Update memory profile Allocate information.
+
+  @param CallerAddress  Address of caller who call Allocate.
+  @param Action         This Allocate action.
+  @param MemoryType     Memory type.
+  @param Size           Buffer size.
+  @param Buffer         Buffer address.
+
+  @retval TRUE          Profile udpate success.
+  @retval FALSE         Profile update fail.
+
+**/
+BOOLEAN
+CoreUpdateProfileAllocate (
+  IN PHYSICAL_ADDRESS       CallerAddress,
+  IN MEMORY_PROFILE_ACTION  Action,
+  IN EFI_MEMORY_TYPE        MemoryType,
+  IN UINTN                  Size,
+  IN VOID                   *Buffer
+  )
+{
+  EFI_STATUS                        Status;
+  MEMORY_PROFILE_CONTEXT           *Context;
+  MEMORY_PROFILE_DRIVER_INFO       *DriverInfo;
+  MEMORY_PROFILE_ALLOC_INFO        *AllocInfo;
+  MEMORY_PROFILE_CONTEXT_DATA       *ContextData;
+  MEMORY_PROFILE_DRIVER_INFO_DATA   *DriverInfoData;
+  MEMORY_PROFILE_ALLOC_INFO_DATA    *AllocInfoData;
+  EFI_MEMORY_TYPE                   ProfileMemoryIndex;
+
+  ContextData = GetMemoryProfileContext ();
+  if (ContextData == NULL) {
+    return FALSE;
+  }
+
+  DriverInfoData = GetMemoryProfileDriverInfoFromAddress (ContextData, 
CallerAddress);
+  ASSERT (DriverInfoData != NULL);
+
+  //
+  // Use CoreInternalAllocatePool() that will not update profile for this 
AllocatePool action.
+  //
+  Status = CoreInternalAllocatePool (
+             EfiBootServicesData,
+             sizeof (*AllocInfoData),
+             (VOID **) &AllocInfoData
+             );
+  if (EFI_ERROR (Status)) {
+    return FALSE;
+  }
+  AllocInfo = &AllocInfoData->AllocInfo;
+  AllocInfoData->Signature      = MEMORY_PROFILE_ALLOC_INFO_SIGNATURE;
+  AllocInfo->Header.Signature   = MEMORY_PROFILE_ALLOC_INFO_SIGNATURE;
+  AllocInfo->Header.Length      = sizeof (MEMORY_PROFILE_ALLOC_INFO);
+  AllocInfo->Header.Revision    = MEMORY_PROFILE_ALLOC_INFO_REVISION;
+  AllocInfo->CallerAddress      = CallerAddress;
+  AllocInfo->SequenceId         = ContextData->Context.SequenceCount;
+  AllocInfo->Action             = Action;
+  AllocInfo->MemoryType         = MemoryType;
+  AllocInfo->Buffer             = (PHYSICAL_ADDRESS) (UINTN) Buffer;
+  AllocInfo->Size               = Size;
+
+  InsertTailList (DriverInfoData->AllocInfoList, &AllocInfoData->Link);
+
+  ProfileMemoryIndex = GetProfileMemoryIndex (MemoryType);
+
+  DriverInfo = &DriverInfoData->DriverInfo;
+  DriverInfo->CurrentUsage += Size;
+  if (DriverInfo->PeakUsage < DriverInfo->CurrentUsage) {
+    DriverInfo->PeakUsage = DriverInfo->CurrentUsage;
+  }
+  DriverInfo->CurrentUsageByType[ProfileMemoryIndex] += Size;
+  if (DriverInfo->PeakUsageByType[ProfileMemoryIndex] < 
DriverInfo->CurrentUsageByType[ProfileMemoryIndex]) {
+    DriverInfo->PeakUsageByType[ProfileMemoryIndex] = 
DriverInfo->CurrentUsageByType[ProfileMemoryIndex];
+  }
+  DriverInfo->AllocRecordCount ++;
+
+  Context = &ContextData->Context;
+  Context->CurrentTotalUsage += Size;
+  if (Context->PeakTotalUsage < Context->CurrentTotalUsage) {
+    Context->PeakTotalUsage = Context->CurrentTotalUsage;
+  }
+  Context->CurrentTotalUsageByType[ProfileMemoryIndex] += Size;
+  if (Context->PeakTotalUsageByType[ProfileMemoryIndex] < 
Context->CurrentTotalUsageByType[ProfileMemoryIndex]) {
+    Context->PeakTotalUsageByType[ProfileMemoryIndex] = 
Context->CurrentTotalUsageByType[ProfileMemoryIndex];
+  }
+  Context->SequenceCount ++;
+
+  return TRUE;
+}
+
+/**
+  Get memory profile alloc info from memory profile
+
+  @param DriverInfoData     Driver info
+  @param Action             This Free action
+  @param Size               Buffer size
+  @param Buffer             Buffer address
+
+  @return Pointer to memory profile alloc info.
+**/
+MEMORY_PROFILE_ALLOC_INFO_DATA *
+GetMemoryProfileAllocInfoFromAddress (
+  IN MEMORY_PROFILE_DRIVER_INFO_DATA    *DriverInfoData,
+  IN MEMORY_PROFILE_ACTION              Action,
+  IN UINTN                              Size,
+  IN VOID                               *Buffer
+  )
+{
+  LIST_ENTRY                        *AllocInfoList;
+  LIST_ENTRY                        *AllocLink;
+  MEMORY_PROFILE_ALLOC_INFO         *AllocInfo;
+  MEMORY_PROFILE_ALLOC_INFO_DATA    *AllocInfoData;
+
+  AllocInfoList = DriverInfoData->AllocInfoList;
+
+  for (AllocLink = AllocInfoList->ForwardLink;
+       AllocLink != AllocInfoList;
+       AllocLink = AllocLink->ForwardLink) {
+    AllocInfoData = CR (
+                      AllocLink,
+                      MEMORY_PROFILE_ALLOC_INFO_DATA,
+                      Link,
+                      MEMORY_PROFILE_ALLOC_INFO_SIGNATURE
+                      );
+    AllocInfo = &AllocInfoData->AllocInfo;
+    if (AllocInfo->Action != Action) {
+      continue;
+    }
+    switch (Action) {
+      case MemoryProfileActionAllocatePages:
+        if ((AllocInfo->Buffer <= (PHYSICAL_ADDRESS) (UINTN) Buffer) &&
+            ((AllocInfo->Buffer + AllocInfo->Size) >= ((PHYSICAL_ADDRESS) 
(UINTN) Buffer + Size))) {
+          return AllocInfoData;
+        }
+        break;
+      case MemoryProfileActionAllocatePool:
+        if (AllocInfo->Buffer == (PHYSICAL_ADDRESS) (UINTN) Buffer) {
+          return AllocInfoData;
+        }
+        break;
+      default:
+        ASSERT (FALSE);
+        break;
+    }
+  }
+
+  return NULL;
+}
+
+/**
+  Update memory profile Free information.
+
+  @param CallerAddress  Address of caller who call Free.
+  @param Action         This Free action.
+  @param Size           Buffer size.
+  @param Buffer         Buffer address.
+
+  @retval TRUE          Profile udpate success.
+  @retval FALSE         Profile update fail.
+
+**/
+BOOLEAN
+CoreUpdateProfileFree (
+  IN PHYSICAL_ADDRESS       CallerAddress,
+  IN MEMORY_PROFILE_ACTION  Action,
+  IN UINTN                  Size,
+  IN VOID                   *Buffer
+  )
+{
+  MEMORY_PROFILE_CONTEXT           *Context;
+  MEMORY_PROFILE_DRIVER_INFO       *DriverInfo;
+  MEMORY_PROFILE_ALLOC_INFO        *AllocInfo;
+  MEMORY_PROFILE_CONTEXT_DATA      *ContextData;
+  MEMORY_PROFILE_DRIVER_INFO_DATA  *DriverInfoData;
+  LIST_ENTRY                       *DriverLink;
+  LIST_ENTRY                       *DriverInfoList;
+  MEMORY_PROFILE_DRIVER_INFO_DATA  *ThisDriverInfoData;
+  MEMORY_PROFILE_ALLOC_INFO_DATA   *AllocInfoData;
+  EFI_MEMORY_TYPE                  ProfileMemoryIndex;
+
+  ContextData = GetMemoryProfileContext ();
+  if (ContextData == NULL) {
+    return FALSE;
+  }
+
+  DriverInfoData = GetMemoryProfileDriverInfoFromAddress (ContextData, 
CallerAddress);
+  ASSERT (DriverInfoData != NULL);
+
+  switch (Action) {
+    case MemoryProfileActionFreePages:
+      AllocInfoData = GetMemoryProfileAllocInfoFromAddress (DriverInfoData, 
MemoryProfileActionAllocatePages, Size, Buffer);
+      break;
+    case MemoryProfileActionFreePool:
+      AllocInfoData = GetMemoryProfileAllocInfoFromAddress (DriverInfoData, 
MemoryProfileActionAllocatePool, 0, Buffer);
+      break;
+    default:
+      ASSERT (FALSE);
+      AllocInfoData = NULL;
+      break;
+  }
+  if (AllocInfoData == NULL) {
+    //
+    // Legal case, because driver A might free memory allocated by driver B, 
by some protocol.
+    //
+    DriverInfoList = ContextData->DriverInfoList;
+
+    for (DriverLink = DriverInfoList->ForwardLink;
+         DriverLink != DriverInfoList;
+         DriverLink = DriverLink->ForwardLink) {
+      ThisDriverInfoData = CR (
+                             DriverLink,
+                             MEMORY_PROFILE_DRIVER_INFO_DATA,
+                             Link,
+                             MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
+                             );
+      switch (Action) {
+        case MemoryProfileActionFreePages:
+          AllocInfoData = GetMemoryProfileAllocInfoFromAddress 
(ThisDriverInfoData, MemoryProfileActionAllocatePages, Size, Buffer);
+          break;
+        case MemoryProfileActionFreePool:
+          AllocInfoData = GetMemoryProfileAllocInfoFromAddress 
(ThisDriverInfoData, MemoryProfileActionAllocatePool, 0, Buffer);
+          break;
+        default:
+          ASSERT (FALSE);
+          AllocInfoData = NULL;
+          break;
+      }
+      if (AllocInfoData != NULL) {
+        DriverInfoData = ThisDriverInfoData;
+        break;
+      }
+    }
+
+    if (AllocInfoData == NULL) {
+      //
+      // No matched allocate operation is found for this free operation.
+      // It is because the specified memory type allocate operation has been
+      // filtered by CoreNeedRecordProfile(), but free operations have no
+      // memory type information, they can not be filtered by 
CoreNeedRecordProfile().
+      // Then, they will be filtered here.
+      //
+      return FALSE;
+    }
+  }
+
+  Context = &ContextData->Context;
+  DriverInfo = &DriverInfoData->DriverInfo;
+  AllocInfo = &AllocInfoData->AllocInfo;
+
+  ProfileMemoryIndex = GetProfileMemoryIndex (AllocInfo->MemoryType);
+
+  Context->CurrentTotalUsage -= AllocInfo->Size;
+  Context->CurrentTotalUsageByType[ProfileMemoryIndex] -= AllocInfo->Size;
+
+  DriverInfo->CurrentUsage -= AllocInfo->Size;
+  DriverInfo->CurrentUsageByType[ProfileMemoryIndex] -= AllocInfo->Size;
+  DriverInfo->AllocRecordCount --;
+
+  RemoveEntryList (&AllocInfoData->Link);
+
+  if (Action == MemoryProfileActionFreePages) {
+    if (AllocInfo->Buffer != (PHYSICAL_ADDRESS) (UINTN) Buffer) {
+      CoreUpdateProfileAllocate (
+        AllocInfo->CallerAddress,
+        MemoryProfileActionAllocatePages,
+        AllocInfo->MemoryType,
+        (UINTN) ((PHYSICAL_ADDRESS) (UINTN) Buffer - AllocInfo->Buffer),
+        (VOID *) (UINTN) AllocInfo->Buffer
+        );
+    }
+    if (AllocInfo->Buffer + AllocInfo->Size != ((PHYSICAL_ADDRESS) (UINTN) 
Buffer + Size)) {
+      CoreUpdateProfileAllocate (
+        AllocInfo->CallerAddress,
+        MemoryProfileActionAllocatePages,
+        AllocInfo->MemoryType,
+        (UINTN) ((AllocInfo->Buffer + AllocInfo->Size) - ((PHYSICAL_ADDRESS) 
(UINTN) Buffer + Size)),
+        (VOID *) ((UINTN) Buffer + Size)
+        );
+    }
+  }
+
+  //
+  // Use CoreInternalFreePool() that will not update profile for this FreePool 
action.
+  //
+  CoreInternalFreePool (AllocInfoData);
+
+  return TRUE;
+}
+
+/**
+  Update memory profile information.
+
+  @param CallerAddress  Address of caller who call Allocate or Free.
+  @param Action         This Allocate or Free action.
+  @param MemoryType     Memory type.
+  @param Size           Buffer size.
+  @param Buffer         Buffer address.
+
+  @retval TRUE          Profile udpate success.
+  @retval FALSE         Profile update fail.
+
+**/
+BOOLEAN
+CoreUpdateProfile (
+  IN PHYSICAL_ADDRESS       CallerAddress,
+  IN MEMORY_PROFILE_ACTION  Action,
+  IN EFI_MEMORY_TYPE        MemoryType, // Valid for AllocatePages/AllocatePool
+  IN UINTN                  Size,       // Valid for 
AllocatePages/FreePages/AllocatePool
+  IN VOID                   *Buffer
+  )
+{
+  MEMORY_PROFILE_CONTEXT_DATA   *ContextData;
+
+  if (!IS_UEFI_MEMORY_PROFILE_ENABLED) {
+    return FALSE;
+  }
+
+  if (!mMemoryProfileRecordingStatus) {
+    return FALSE;
+  }
+
+  //
+  // Free operations have no memory type information, so skip the check.
+  //
+  if ((Action == MemoryProfileActionAllocatePages) || (Action == 
MemoryProfileActionAllocatePool)) {
+    //
+    // Only record limited MemoryType.
+    //
+    if (!CoreNeedRecordProfile (MemoryType)) {
+      return FALSE;
+    }
+  }
+
+  ContextData = GetMemoryProfileContext ();
+  if (ContextData == NULL) {
+    return FALSE;
+  }
+
+  switch (Action) {
+    case MemoryProfileActionAllocatePages:
+      CoreUpdateProfileAllocate (CallerAddress, Action, MemoryType, Size, 
Buffer);
+      break;
+    case MemoryProfileActionFreePages:
+      CoreUpdateProfileFree (CallerAddress, Action, Size, Buffer);
+      break;
+    case MemoryProfileActionAllocatePool:
+      CoreUpdateProfileAllocate (CallerAddress, Action, MemoryType, Size, 
Buffer);
+      break;
+    case MemoryProfileActionFreePool:
+      CoreUpdateProfileFree (CallerAddress, Action, 0, Buffer);
+      break;
+    default:
+      ASSERT (FALSE);
+      break;
+  }
+  return TRUE;
+}
+
+////////////////////
+
+/**
+  Get memory profile data size.
+
+  @return Memory profile data size.
+
+**/
+UINTN
+MemoryProfileGetDataSize (
+  VOID
+  )
+{
+  MEMORY_PROFILE_CONTEXT_DATA       *ContextData;
+  MEMORY_PROFILE_DRIVER_INFO_DATA   *DriverInfoData;
+  LIST_ENTRY                        *DriverInfoList;
+  LIST_ENTRY                        *DriverLink;
+  UINTN                             TotalSize;
+
+
+  ContextData = GetMemoryProfileContext ();
+  if (ContextData == NULL) {
+    return 0;
+  }
+
+  TotalSize = sizeof (MEMORY_PROFILE_CONTEXT);
+  TotalSize += sizeof (MEMORY_PROFILE_DRIVER_INFO) * (UINTN) 
ContextData->Context.ImageCount;
+
+  DriverInfoList = ContextData->DriverInfoList;
+  for (DriverLink = DriverInfoList->ForwardLink;
+       DriverLink != DriverInfoList;
+       DriverLink = DriverLink->ForwardLink) {
+    DriverInfoData = CR (
+                       DriverLink,
+                       MEMORY_PROFILE_DRIVER_INFO_DATA,
+                       Link,
+                       MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
+                       );
+    TotalSize += sizeof (MEMORY_PROFILE_ALLOC_INFO) * (UINTN) 
DriverInfoData->DriverInfo.AllocRecordCount;
+  }
+
+  return TotalSize;
+}
+
+/**
+  Copy memory profile data.
+
+  @param ProfileBuffer  The buffer to hold memory profile data.
+
+**/
+VOID
+MemoryProfileCopyData (
+  IN VOID   *ProfileBuffer
+  )
+{
+  MEMORY_PROFILE_CONTEXT            *Context;
+  MEMORY_PROFILE_DRIVER_INFO        *DriverInfo;
+  MEMORY_PROFILE_ALLOC_INFO         *AllocInfo;
+  MEMORY_PROFILE_CONTEXT_DATA       *ContextData;
+  MEMORY_PROFILE_DRIVER_INFO_DATA   *DriverInfoData;
+  MEMORY_PROFILE_ALLOC_INFO_DATA    *AllocInfoData;
+  LIST_ENTRY                        *DriverInfoList;
+  LIST_ENTRY                        *DriverLink;
+  LIST_ENTRY                        *AllocInfoList;
+  LIST_ENTRY                        *AllocLink;
+
+  ContextData = GetMemoryProfileContext ();
+  if (ContextData == NULL) {
+    return ;
+  }
+
+  Context = ProfileBuffer;
+  CopyMem (Context, &ContextData->Context, sizeof (MEMORY_PROFILE_CONTEXT));
+  DriverInfo = (MEMORY_PROFILE_DRIVER_INFO *) (Context + 1);
+
+  DriverInfoList = ContextData->DriverInfoList;
+  for (DriverLink = DriverInfoList->ForwardLink;
+       DriverLink != DriverInfoList;
+       DriverLink = DriverLink->ForwardLink) {
+    DriverInfoData = CR (
+                       DriverLink,
+                       MEMORY_PROFILE_DRIVER_INFO_DATA,
+                       Link,
+                       MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
+                       );
+    CopyMem (DriverInfo, &DriverInfoData->DriverInfo, sizeof 
(MEMORY_PROFILE_DRIVER_INFO));
+    AllocInfo = (MEMORY_PROFILE_ALLOC_INFO *) (DriverInfo + 1);
+
+    AllocInfoList = DriverInfoData->AllocInfoList;
+    for (AllocLink = AllocInfoList->ForwardLink;
+         AllocLink != AllocInfoList;
+         AllocLink = AllocLink->ForwardLink) {
+      AllocInfoData = CR (
+                        AllocLink,
+                        MEMORY_PROFILE_ALLOC_INFO_DATA,
+                        Link,
+                        MEMORY_PROFILE_ALLOC_INFO_SIGNATURE
+                        );
+      CopyMem (AllocInfo, &AllocInfoData->AllocInfo, sizeof 
(MEMORY_PROFILE_ALLOC_INFO));
+      AllocInfo += 1;
+    }
+
+    DriverInfo = (MEMORY_PROFILE_DRIVER_INFO *) ((UINTN) (DriverInfo + 1) + 
sizeof (MEMORY_PROFILE_ALLOC_INFO) * (UINTN) DriverInfo->AllocRecordCount);
+  }
+}
+
+/**
+  Get memory profile data.
+
+  @param[in]      This              The EDKII_MEMORY_PROFILE_PROTOCOL instance.
+  @param[in, out] ProfileSize       On entry, points to the size in bytes of 
the ProfileBuffer.
+                                    On return, points to the size of the data 
returned in ProfileBuffer.
+  @param[out]     ProfileBuffer     Profile buffer.
+                      
+  @return EFI_SUCCESS               Get the memory profile data successfully.
+  @return EFI_BUFFER_TO_SMALL       The ProfileSize is too small for the 
resulting data. 
+                                    ProfileSize is updated with the size 
required.
+
+**/
+EFI_STATUS
+EFIAPI
+ProfileProtocolGetData (
+  IN     EDKII_MEMORY_PROFILE_PROTOCOL  *This,
+  IN OUT UINT64                         *ProfileSize,
+     OUT VOID                           *ProfileBuffer
+  )
+{
+  UINTN                                 Size;
+  MEMORY_PROFILE_CONTEXT_DATA           *ContextData;
+  BOOLEAN                               MemoryProfileRecordingStatus;
+
+  ContextData = GetMemoryProfileContext ();
+  if (ContextData == NULL) {
+    return EFI_UNSUPPORTED;
+  }
+
+  MemoryProfileRecordingStatus = mMemoryProfileRecordingStatus;
+  mMemoryProfileRecordingStatus = FALSE;
+
+  Size = MemoryProfileGetDataSize ();
+
+  if (*ProfileSize < Size) {
+    *ProfileSize = Size;
+    mMemoryProfileRecordingStatus = MemoryProfileRecordingStatus;
+    return EFI_BUFFER_TOO_SMALL;
+  }
+
+  *ProfileSize = Size;
+  MemoryProfileCopyData (ProfileBuffer);
+
+  mMemoryProfileRecordingStatus = MemoryProfileRecordingStatus;
+  return EFI_SUCCESS;
+}
+
+/**
+  Register image to memory profile.
+
+  @param[in] This               The EDKII_MEMORY_PROFILE_PROTOCOL instance.
+  @param[in] FilePath           File path of the image.
+  @param[in] ImageBase          Image base address.
+  @param[in] ImageSize          Image size.
+  @param[in] FileType           File type of the image.
+
+  @return EFI_SUCCESS           Register success.
+  @return EFI_OUT_OF_RESOURCE   No enough resource for this register.
+
+**/
+EFI_STATUS
+EFIAPI
+ProfileProtocolRegisterImage (
+  IN EDKII_MEMORY_PROFILE_PROTOCOL  *This,
+  IN EFI_DEVICE_PATH_PROTOCOL       *FilePath,
+  IN PHYSICAL_ADDRESS               ImageBase,
+  IN UINT64                         ImageSize,
+  IN EFI_FV_FILETYPE                FileType
+  )
+{
+  EFI_STATUS                        Status;
+  LOADED_IMAGE_PRIVATE_DATA         DriverEntry;
+  VOID                              *EntryPointInImage;
+
+  ZeroMem (&DriverEntry, sizeof (DriverEntry));
+  DriverEntry.Info.FilePath = FilePath;
+  DriverEntry.ImageContext.ImageAddress = ImageBase;
+  DriverEntry.ImageContext.ImageSize = ImageSize;
+  Status = InternalPeCoffGetEntryPoint ((VOID *) (UINTN) ImageBase, 
&EntryPointInImage);
+  ASSERT_EFI_ERROR (Status);
+  DriverEntry.ImageContext.EntryPoint = (PHYSICAL_ADDRESS) (UINTN) 
EntryPointInImage;
+  DriverEntry.ImageContext.ImageType = InternalPeCoffGetSubsystem ((VOID *) 
(UINTN) ImageBase);
+
+  return RegisterMemoryProfileImage (&DriverEntry, FileType) ? EFI_SUCCESS: 
EFI_OUT_OF_RESOURCES;
+}
+
+/**
+  Unregister image from memory profile.
+
+  @param[in] This               The EDKII_MEMORY_PROFILE_PROTOCOL instance.
+  @param[in] FilePath           File path of the image.
+  @param[in] ImageBase          Image base address.
+  @param[in] ImageSize          Image size.
+
+  @return EFI_SUCCESS           Unregister success.
+  @return EFI_NOT_FOUND         The image is not found.
+
+**/
+EFI_STATUS
+EFIAPI
+ProfileProtocolUnregisterImage (
+  IN EDKII_MEMORY_PROFILE_PROTOCOL  *This,
+  IN EFI_DEVICE_PATH_PROTOCOL       *FilePath,
+  IN PHYSICAL_ADDRESS               ImageBase,
+  IN UINT64                         ImageSize
+  )
+{
+  EFI_STATUS                        Status;
+  LOADED_IMAGE_PRIVATE_DATA         DriverEntry;
+  VOID                              *EntryPointInImage;
+
+  ZeroMem (&DriverEntry, sizeof (DriverEntry));
+  DriverEntry.Info.FilePath = FilePath;
+  DriverEntry.ImageContext.ImageAddress = ImageBase;
+  DriverEntry.ImageContext.ImageSize = ImageSize;
+  Status = InternalPeCoffGetEntryPoint ((VOID *) (UINTN) ImageBase, 
&EntryPointInImage);
+  ASSERT_EFI_ERROR (Status);
+  DriverEntry.ImageContext.EntryPoint = (PHYSICAL_ADDRESS) (UINTN) 
EntryPointInImage;
+
+  return UnregisterMemoryProfileImage (&DriverEntry) ? EFI_SUCCESS: 
EFI_NOT_FOUND;
+}
+
+////////////////////

Modified: trunk/edk2/MdeModulePkg/Core/Dxe/Mem/Page.c
===================================================================
--- trunk/edk2/MdeModulePkg/Core/Dxe/Mem/Page.c 2014-11-12 03:18:09 UTC (rev 
16334)
+++ trunk/edk2/MdeModulePkg/Core/Dxe/Mem/Page.c 2014-11-12 03:27:48 UTC (rev 
16335)
@@ -1106,7 +1106,7 @@
 **/
 EFI_STATUS
 EFIAPI
-CoreAllocatePages (
+CoreInternalAllocatePages (
   IN EFI_ALLOCATE_TYPE      Type,
   IN EFI_MEMORY_TYPE        MemoryType,
   IN UINTN                  NumberOfPages,
@@ -1192,7 +1192,42 @@
   return Status;
 }
 
+/**
+  Allocates pages from the memory map.
 
+  @param  Type                   The type of allocation to perform
+  @param  MemoryType             The type of memory to turn the allocated pages
+                                 into
+  @param  NumberOfPages          The number of pages to allocate
+  @param  Memory                 A pointer to receive the base allocated memory
+                                 address
+
+  @return Status. On success, Memory is filled in with the base address 
allocated
+  @retval EFI_INVALID_PARAMETER  Parameters violate checking rules defined in
+                                 spec.
+  @retval EFI_NOT_FOUND          Could not allocate pages match the 
requirement.
+  @retval EFI_OUT_OF_RESOURCES   No enough pages to allocate.
+  @retval EFI_SUCCESS            Pages successfully allocated.
+
+**/
+EFI_STATUS
+EFIAPI
+CoreAllocatePages (
+  IN  EFI_ALLOCATE_TYPE     Type,
+  IN  EFI_MEMORY_TYPE       MemoryType,
+  IN  UINTN                 NumberOfPages,
+  OUT EFI_PHYSICAL_ADDRESS  *Memory
+  )
+{
+  EFI_STATUS  Status;
+
+  Status = CoreInternalAllocatePages (Type, MemoryType, NumberOfPages, Memory);
+  if (!EFI_ERROR (Status)) {
+    CoreUpdateProfile ((EFI_PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS (0), 
MemoryProfileActionAllocatePages, MemoryType, EFI_PAGES_TO_SIZE 
(NumberOfPages), (VOID *) (UINTN) *Memory);
+  }
+  return Status;
+}
+
 /**
   Frees previous allocated pages.
 
@@ -1206,7 +1241,7 @@
 **/
 EFI_STATUS
 EFIAPI
-CoreFreePages (
+CoreInternalFreePages (
   IN EFI_PHYSICAL_ADDRESS   Memory,
   IN UINTN                  NumberOfPages
   )
@@ -1268,6 +1303,33 @@
 }
 
 /**
+  Frees previous allocated pages.
+
+  @param  Memory                 Base address of memory being freed
+  @param  NumberOfPages          The number of pages to free
+
+  @retval EFI_NOT_FOUND          Could not find the entry that covers the range
+  @retval EFI_INVALID_PARAMETER  Address not aligned
+  @return EFI_SUCCESS         -Pages successfully freed.
+
+**/
+EFI_STATUS
+EFIAPI
+CoreFreePages (
+  IN EFI_PHYSICAL_ADDRESS  Memory,
+  IN UINTN                 NumberOfPages
+  )
+{
+  EFI_STATUS  Status;
+
+  Status = CoreInternalFreePages (Memory, NumberOfPages);
+  if (!EFI_ERROR (Status)) {
+    CoreUpdateProfile ((EFI_PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS (0), 
MemoryProfileActionFreePages, 0, EFI_PAGES_TO_SIZE (NumberOfPages), (VOID *) 
(UINTN) Memory);
+  }
+  return Status;
+}
+
+/**
   This function checks to see if the last memory map descriptor in a memory map
   can be merged with any of the other memory map descriptors in a memorymap.
   Memory descriptors may be merged if they are adjacent and have the same type

Modified: trunk/edk2/MdeModulePkg/Core/Dxe/Mem/Pool.c
===================================================================
--- trunk/edk2/MdeModulePkg/Core/Dxe/Mem/Pool.c 2014-11-12 03:18:09 UTC (rev 
16334)
+++ trunk/edk2/MdeModulePkg/Core/Dxe/Mem/Pool.c 2014-11-12 03:27:48 UTC (rev 
16335)
@@ -175,7 +175,7 @@
 **/
 EFI_STATUS
 EFIAPI
-CoreAllocatePool (
+CoreInternalAllocatePool (
   IN EFI_MEMORY_TYPE  PoolType,
   IN UINTN            Size,
   OUT VOID            **Buffer
@@ -218,8 +218,36 @@
   return (*Buffer != NULL) ? EFI_SUCCESS : EFI_OUT_OF_RESOURCES;
 }
 
+/**
+  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 or Buffer is NULL. 
+  @retval EFI_OUT_OF_RESOURCES   Size exceeds max pool size or allocation 
failed.
+  @retval EFI_SUCCESS            Pool successfully allocated.
+
+**/
+EFI_STATUS
+EFIAPI
+CoreAllocatePool (
+  IN EFI_MEMORY_TYPE  PoolType,
+  IN UINTN            Size,
+  OUT VOID            **Buffer
+  )
+{
+  EFI_STATUS  Status;
+
+  Status = CoreInternalAllocatePool (PoolType, Size, Buffer);
+  if (!EFI_ERROR (Status)) {
+    CoreUpdateProfile ((EFI_PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS (0), 
MemoryProfileActionAllocatePool, PoolType, Size, *Buffer);
+  }
+  return Status;
+}
+
 /**
   Internal function to allocate pool of a particular type.
   Caller must have the memory lock held
@@ -373,7 +401,7 @@
 **/
 EFI_STATUS
 EFIAPI
-CoreFreePool (
+CoreInternalFreePool (
   IN VOID        *Buffer
   )
 {
@@ -389,8 +417,30 @@
   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
+CoreFreePool (
+  IN VOID  *Buffer
+  )
+{
+  EFI_STATUS  Status;
+
+  Status = CoreInternalFreePool (Buffer);
+  if (!EFI_ERROR (Status)) {
+    CoreUpdateProfile ((EFI_PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS (0), 
MemoryProfileActionFreePool, 0, 0, Buffer);
+  }
+  return Status;
+}
+
 /**
   Internal function to free a pool entry.
   Caller must have the memory lock held
@@ -558,3 +608,4 @@
 
   return EFI_SUCCESS;
 }
+

Modified: trunk/edk2/MdeModulePkg/Core/PiSmmCore/Dispatcher.c
===================================================================
--- trunk/edk2/MdeModulePkg/Core/PiSmmCore/Dispatcher.c 2014-11-12 03:18:09 UTC 
(rev 16334)
+++ trunk/edk2/MdeModulePkg/Core/PiSmmCore/Dispatcher.c 2014-11-12 03:27:48 UTC 
(rev 16335)
@@ -874,10 +874,12 @@
       //
       // For each SMM driver, pass NULL as ImageHandle
       //
+      RegisterSmramProfileImage (DriverEntry, TRUE);
       PERF_START (DriverEntry->ImageHandle, "StartImage:", NULL, 0);
       Status = 
((EFI_IMAGE_ENTRY_POINT)(UINTN)DriverEntry->ImageEntryPoint)(DriverEntry->ImageHandle,
 gST);
       PERF_END (DriverEntry->ImageHandle, "StartImage:", NULL, 0);
       if (EFI_ERROR(Status)){
+        UnregisterSmramProfileImage (DriverEntry, TRUE);
         SmmFreePages(DriverEntry->ImageBuffer, DriverEntry->NumberOfPage);
       }
 

Modified: trunk/edk2/MdeModulePkg/Core/PiSmmCore/Page.c
===================================================================
--- trunk/edk2/MdeModulePkg/Core/PiSmmCore/Page.c       2014-11-12 03:18:09 UTC 
(rev 16334)
+++ trunk/edk2/MdeModulePkg/Core/PiSmmCore/Page.c       2014-11-12 03:27:48 UTC 
(rev 16335)
@@ -1,7 +1,7 @@
 /** @file
   SMM Memory page management functions.
 
-  Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2009 - 2014, 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        
@@ -16,11 +16,6 @@
 
 #define TRUNCATE_TO_PAGES(a)  ((a) >> EFI_PAGE_SHIFT)
 
-typedef struct {
-  LIST_ENTRY  Link;
-  UINTN       NumberOfPages;
-} FREE_PAGE_LIST;
-
 LIST_ENTRY  mSmmMemoryMap = INITIALIZE_LIST_HEAD_VARIABLE (mSmmMemoryMap);
 
 /**
@@ -151,7 +146,7 @@
 **/
 EFI_STATUS
 EFIAPI
-SmmAllocatePages (
+SmmInternalAllocatePages (
   IN  EFI_ALLOCATE_TYPE     Type,
   IN  EFI_MEMORY_TYPE       MemoryType,
   IN  UINTN                 NumberOfPages,
@@ -203,6 +198,40 @@
 }
 
 /**
+  Allocates pages from the memory map.
+
+  @param  Type                   The type of allocation to perform.
+  @param  MemoryType             The type of memory to turn the allocated pages
+                                 into.
+  @param  NumberOfPages          The number of pages to allocate.
+  @param  Memory                 A pointer to receive the base allocated memory
+                                 address.
+
+  @retval EFI_INVALID_PARAMETER  Parameters violate checking rules defined in 
spec.
+  @retval EFI_NOT_FOUND          Could not allocate pages match the 
requirement.
+  @retval EFI_OUT_OF_RESOURCES   No enough pages to allocate.
+  @retval EFI_SUCCESS            Pages successfully allocated.
+
+**/
+EFI_STATUS
+EFIAPI
+SmmAllocatePages (
+  IN  EFI_ALLOCATE_TYPE     Type,
+  IN  EFI_MEMORY_TYPE       MemoryType,
+  IN  UINTN                 NumberOfPages,
+  OUT EFI_PHYSICAL_ADDRESS  *Memory
+  )
+{
+  EFI_STATUS  Status;
+
+  Status = SmmInternalAllocatePages (Type, MemoryType, NumberOfPages, Memory);
+  if (!EFI_ERROR (Status)) {
+    SmmCoreUpdateProfile ((EFI_PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS (0), 
MemoryProfileActionAllocatePages, MemoryType, EFI_PAGES_TO_SIZE 
(NumberOfPages), (VOID *) (UINTN) *Memory);
+  }
+  return Status;
+}
+
+/**
   Internal Function. Merge two adjacent nodes.
 
   @param  First             The first of two nodes to merge.
@@ -242,7 +271,7 @@
 **/
 EFI_STATUS
 EFIAPI
-SmmFreePages (
+SmmInternalFreePages (
   IN EFI_PHYSICAL_ADDRESS  Memory,
   IN UINTN                 NumberOfPages
   )
@@ -294,6 +323,33 @@
 }
 
 /**
+  Frees previous allocated pages.
+
+  @param  Memory                 Base address of memory being freed.
+  @param  NumberOfPages          The number of pages to free.
+
+  @retval EFI_NOT_FOUND          Could not find the entry that covers the 
range.
+  @retval EFI_INVALID_PARAMETER  Address not aligned.
+  @return EFI_SUCCESS            Pages successfully freed.
+
+**/
+EFI_STATUS
+EFIAPI
+SmmFreePages (
+  IN EFI_PHYSICAL_ADDRESS  Memory,
+  IN UINTN                 NumberOfPages
+  )
+{
+  EFI_STATUS  Status;
+
+  Status = SmmInternalFreePages (Memory, NumberOfPages);
+  if (!EFI_ERROR (Status)) {
+    SmmCoreUpdateProfile ((EFI_PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS (0), 
MemoryProfileActionFreePages, 0, EFI_PAGES_TO_SIZE (NumberOfPages), (VOID *) 
(UINTN) Memory);
+  }
+  return Status;
+}
+
+/**
   Add free SMRAM region for use by memory service.
 
   @param  MemBase                Base address of memory region.

Modified: trunk/edk2/MdeModulePkg/Core/PiSmmCore/PiSmmCore.c
===================================================================
--- trunk/edk2/MdeModulePkg/Core/PiSmmCore/PiSmmCore.c  2014-11-12 03:18:09 UTC 
(rev 16334)
+++ trunk/edk2/MdeModulePkg/Core/PiSmmCore/PiSmmCore.c  2014-11-12 03:27:48 UTC 
(rev 16335)
@@ -1,7 +1,7 @@
 /** @file
   SMM Core Main Entry Point
 
-  Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2009 - 2014, 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        
@@ -82,6 +82,9 @@
   { NULL,                     NULL,                               NULL, FALSE }
 };
 
+UINTN                           mFullSmramRangeCount;
+EFI_SMRAM_DESCRIPTOR            *mFullSmramRanges;
+
 /**
   Place holder function until all the SMM System Table Service are available.
 
@@ -226,6 +229,8 @@
   gST = NULL;
   gBS = NULL;
 
+  SmramProfileReadyToLock ();
+
   return Status;
 }
 
@@ -401,7 +406,17 @@
   //
   SmmInitializeMemoryServices (gSmmCorePrivate->SmramRangeCount, 
gSmmCorePrivate->SmramRanges);
 
+  SmramProfileInit ();
+
   //
+  // Copy FullSmramRanges to SMRAM
+  //
+  mFullSmramRangeCount = gSmmCorePrivate->FullSmramRangeCount;
+  mFullSmramRanges = AllocatePool (mFullSmramRangeCount * sizeof 
(EFI_SMRAM_DESCRIPTOR));
+  ASSERT (mFullSmramRanges != NULL);
+  CopyMem (mFullSmramRanges, gSmmCorePrivate->FullSmramRanges, 
mFullSmramRangeCount * sizeof (EFI_SMRAM_DESCRIPTOR));
+
+  //
   // Register all SMI Handlers required by the SMM Core
   //
   for (Index = 0; mSmmCoreSmiHandlers[Index].HandlerType != NULL; Index++) {
@@ -412,6 +427,8 @@
                );
     ASSERT_EFI_ERROR (Status);
   }
-  
+
+  RegisterSmramProfileHandler ();
+
   return EFI_SUCCESS;
 }

Modified: trunk/edk2/MdeModulePkg/Core/PiSmmCore/PiSmmCore.h
===================================================================
--- trunk/edk2/MdeModulePkg/Core/PiSmmCore/PiSmmCore.h  2014-11-12 03:18:09 UTC 
(rev 16334)
+++ trunk/edk2/MdeModulePkg/Core/PiSmmCore/PiSmmCore.h  2014-11-12 03:27:48 UTC 
(rev 16335)
@@ -2,7 +2,7 @@
   The internal header file includes the common header files, defines
   internal structure and functions used by SmmCore module.
 
-  Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2009 - 2014, 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        
@@ -33,6 +33,8 @@
 #include <Guid/Apriori.h>
 #include <Guid/EventGroup.h>
 #include <Guid/EventLegacyBios.h>
+#include <Guid/ZeroGuid.h>
+#include <Guid/MemoryProfile.h>
 
 #include <Library/BaseLib.h>
 #include <Library/BaseMemoryLib.h>
@@ -272,6 +274,31 @@
   );
 
 /**
+  Allocates pages from the memory map.
+
+  @param  Type                   The type of allocation to perform
+  @param  MemoryType             The type of memory to turn the allocated pages
+                                 into
+  @param  NumberOfPages          The number of pages to allocate
+  @param  Memory                 A pointer to receive the base allocated memory
+                                 address
+
+  @retval EFI_INVALID_PARAMETER  Parameters violate checking rules defined in 
spec.
+  @retval EFI_NOT_FOUND          Could not allocate pages match the 
requirement.
+  @retval EFI_OUT_OF_RESOURCES   No enough pages to allocate.
+  @retval EFI_SUCCESS            Pages successfully allocated.
+
+**/
+EFI_STATUS
+EFIAPI
+SmmInternalAllocatePages (
+  IN      EFI_ALLOCATE_TYPE         Type,
+  IN      EFI_MEMORY_TYPE           MemoryType,
+  IN      UINTN                     NumberOfPages,
+  OUT     EFI_PHYSICAL_ADDRESS      *Memory
+  );
+
+/**
   Frees previous allocated pages.
 
   @param  Memory                 Base address of memory being freed
@@ -290,6 +317,24 @@
   );
 
 /**
+  Frees previous allocated pages.
+
+  @param  Memory                 Base address of memory being freed
+  @param  NumberOfPages          The number of pages to free
+
+  @retval EFI_NOT_FOUND          Could not find the entry that covers the range
+  @retval EFI_INVALID_PARAMETER  Address not aligned
+  @return EFI_SUCCESS            Pages successfully freed.
+
+**/
+EFI_STATUS
+EFIAPI
+SmmInternalFreePages (
+  IN      EFI_PHYSICAL_ADDRESS      Memory,
+  IN      UINTN                     NumberOfPages
+  );
+
+/**
   Allocate pool of a particular type.
 
   @param  PoolType               Type of pool to allocate
@@ -311,6 +356,27 @@
   );
 
 /**

@@ Diff output truncated at 100000 characters. @@

------------------------------------------------------------------------------
Comprehensive Server Monitoring with Site24x7.
Monitor 10 servers for $9/Month.
Get alerted through email, SMS, voice calls or mobile push notifications.
Take corrective actions from your mobile device.
http://pubads.g.doubleclick.net/gampad/clk?id=154624111&iu=/4140/ostg.clktrk
_______________________________________________
edk2-commits mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/edk2-commits

Reply via email to