1. Produce SMM memory profile protocol.
2. Consume PcdMemoryProfilePropertyMask to support disable recording
at the start.
3. Consume PcdMemoryProfileDriverPath to control which drivers need
memory profile data.

Cc: Jiewen Yao <jiewen....@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Star Zeng <star.z...@intel.com>
Reviewed-by: Jiewen Yao <jiewen....@intel.com>
---
 MdeModulePkg/Core/PiSmmCore/Page.c               |   20 +-
 MdeModulePkg/Core/PiSmmCore/PiSmmCore.c          |    3 +-
 MdeModulePkg/Core/PiSmmCore/PiSmmCore.h          |   57 +-
 MdeModulePkg/Core/PiSmmCore/PiSmmCore.inf        |    6 +-
 MdeModulePkg/Core/PiSmmCore/Pool.c               |   20 +-
 MdeModulePkg/Core/PiSmmCore/SmramProfileRecord.c | 1319 +++++++++++++++++-----
 6 files changed, 1110 insertions(+), 315 deletions(-)

diff --git a/MdeModulePkg/Core/PiSmmCore/Page.c 
b/MdeModulePkg/Core/PiSmmCore/Page.c
index 9cc2a4cabc6e..5c04e8c8bf4d 100644
--- a/MdeModulePkg/Core/PiSmmCore/Page.c
+++ b/MdeModulePkg/Core/PiSmmCore/Page.c
@@ -1,7 +1,7 @@
 /** @file
   SMM Memory page management functions.
 
-  Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2009 - 2016, 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        
@@ -226,7 +226,14 @@ SmmAllocatePages (
 
   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);
+    SmmCoreUpdateProfile (
+      (EFI_PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS (0),
+      MemoryProfileActionAllocatePages,
+      MemoryType,
+      EFI_PAGES_TO_SIZE (NumberOfPages),
+      (VOID *) (UINTN) *Memory,
+      NULL
+      );
   }
   return Status;
 }
@@ -344,7 +351,14 @@ SmmFreePages (
 
   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);
+    SmmCoreUpdateProfile (
+      (EFI_PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS (0),
+      MemoryProfileActionFreePages,
+      EfiMaxMemoryType,
+      EFI_PAGES_TO_SIZE (NumberOfPages),
+      (VOID *) (UINTN) Memory,
+      NULL
+      );
   }
   return Status;
 }
diff --git a/MdeModulePkg/Core/PiSmmCore/PiSmmCore.c 
b/MdeModulePkg/Core/PiSmmCore/PiSmmCore.c
index 7245f201fbdf..551560b1fce1 100644
--- a/MdeModulePkg/Core/PiSmmCore/PiSmmCore.c
+++ b/MdeModulePkg/Core/PiSmmCore/PiSmmCore.c
@@ -1,7 +1,7 @@
 /** @file
   SMM Core Main Entry Point
 
-  Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2009 - 2016, 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        
@@ -632,6 +632,7 @@ SmmMain (
   }
 
   RegisterSmramProfileHandler ();
+  SmramProfileInstallProtocol ();
 
   SmmCoreInstallLoadedImage ();
 
diff --git a/MdeModulePkg/Core/PiSmmCore/PiSmmCore.h 
b/MdeModulePkg/Core/PiSmmCore/PiSmmCore.h
index 0e9c92abef9a..000864d3aab0 100644
--- a/MdeModulePkg/Core/PiSmmCore/PiSmmCore.h
+++ b/MdeModulePkg/Core/PiSmmCore/PiSmmCore.h
@@ -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 - 2015, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2009 - 2016, 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        
@@ -42,6 +42,7 @@
 #include <Library/BaseLib.h>
 #include <Library/BaseMemoryLib.h>
 #include <Library/PeCoffLib.h>
+#include <Library/PeCoffGetEntryPointLib.h>
 #include <Library/CacheMaintenanceLib.h>
 #include <Library/DebugLib.h>
 #include <Library/ReportStatusCodeLib.h>
@@ -885,16 +886,27 @@ SmramProfileInit (
   );
 
 /**
+  Install SMRAM profile protocol.
+
+**/
+VOID
+SmramProfileInstallProtocol (
+  VOID
+  );
+
+/**
   Register SMM image to SMRAM profile.
 
   @param DriverEntry    SMM image info.
   @param RegisterToDxe  Register image to DXE.
 
-  @retval TRUE          Register success.
-  @retval FALSE         Register fail.
+  @return EFI_SUCCESS           Register successfully.
+  @return EFI_UNSUPPORTED       Memory profile unsupported,
+                                or memory profile for the image is not 
required.
+  @return EFI_OUT_OF_RESOURCES  No enough resource for this register.
 
 **/
-BOOLEAN
+EFI_STATUS
 RegisterSmramProfileImage (
   IN EFI_SMM_DRIVER_ENTRY   *DriverEntry,
   IN BOOLEAN                RegisterToDxe
@@ -906,11 +918,13 @@ RegisterSmramProfileImage (
   @param DriverEntry        SMM image info.
   @param UnregisterToDxe    Unregister image from DXE.
 
-  @retval TRUE              Unregister success.
-  @retval FALSE             Unregister fail.
+  @return EFI_SUCCESS           Unregister successfully.
+  @return EFI_UNSUPPORTED       Memory profile unsupported,
+                                or memory profile for the image is not 
required.
+  @return EFI_NOT_FOUND         The image is not found.
 
 **/
-BOOLEAN
+EFI_STATUS
 UnregisterSmramProfileImage (
   IN EFI_SMM_DRIVER_ENTRY   *DriverEntry,
   IN BOOLEAN                UnregisterToDxe
@@ -922,20 +936,31 @@ UnregisterSmramProfileImage (
   @param CallerAddress  Address of caller who call Allocate or Free.
   @param Action         This Allocate or Free action.
   @param MemoryType     Memory type.
+                        EfiMaxMemoryType means the MemoryType is unknown.
   @param Size           Buffer size.
   @param Buffer         Buffer address.
-
-  @retval TRUE          Profile udpate success.
-  @retval FALSE         Profile update fail.
+  @param ActionString   String for memory profile action.
+                        Only needed for user defined allocate action.
+
+  @return EFI_SUCCESS           Memory profile is updated.
+  @return EFI_UNSUPPORTED       Memory profile is unsupported,
+                                or memory profile for the image is not 
required,
+                                or memory profile for the memory type is not 
required.
+  @return EFI_ACCESS_DENIED     It is during memory profile data getting.
+  @return EFI_ABORTED           Memory profile recording is not enabled.
+  @return EFI_OUT_OF_RESOURCES  No enough resource to update memory profile 
for allocate action.
+  @return EFI_NOT_FOUND         No matched allocate info found for free action.
 
 **/
-BOOLEAN
+EFI_STATUS
+EFIAPI
 SmmCoreUpdateProfile (
-  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
+  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,
+  IN CHAR8                  *ActionString OPTIONAL
   );
 
 /**
diff --git a/MdeModulePkg/Core/PiSmmCore/PiSmmCore.inf 
b/MdeModulePkg/Core/PiSmmCore/PiSmmCore.inf
index 9c06b2ac2fd7..f7e32c4e09a8 100644
--- a/MdeModulePkg/Core/PiSmmCore/PiSmmCore.inf
+++ b/MdeModulePkg/Core/PiSmmCore/PiSmmCore.inf
@@ -1,7 +1,7 @@
 ## @file
 # This module provide an SMM CIS compliant implementation of SMM Core.
 #
-# Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2009 - 2016, 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
@@ -48,6 +48,7 @@ [LibraryClasses]
   BaseLib
   BaseMemoryLib
   PeCoffLib
+  PeCoffGetEntryPointLib
   CacheMaintenanceLib  
   DebugLib
   ReportStatusCodeLib
@@ -81,6 +82,7 @@ [Pcd]
   gEfiMdeModulePkgTokenSpaceGuid.PcdLoadModuleAtFixAddressEnable        ## 
CONSUMES
   gEfiMdeModulePkgTokenSpaceGuid.PcdMemoryProfileMemoryType             ## 
CONSUMES
   gEfiMdeModulePkgTokenSpaceGuid.PcdMemoryProfilePropertyMask           ## 
CONSUMES
+  gEfiMdeModulePkgTokenSpaceGuid.PcdMemoryProfileDriverPath             ## 
CONSUMES
 
 [Guids]
   gAprioriGuid                                  ## SOMETIMES_CONSUMES   ## File
@@ -92,6 +94,8 @@ [Guids]
   ## SOMETIMES_CONSUMES   ## GUID # Locate protocol
   ## SOMETIMES_PRODUCES   ## GUID # SmiHandlerRegister
   gEdkiiMemoryProfileGuid
+  ## SOMETIMES_PRODUCES   ## GUID # Install protocol
+  gEdkiiSmmMemoryProfileGuid
   gZeroGuid                                     ## SOMETIMES_CONSUMES   ## GUID
 
 [UserExtensions.TianoCore."ExtraFiles"]
diff --git a/MdeModulePkg/Core/PiSmmCore/Pool.c 
b/MdeModulePkg/Core/PiSmmCore/Pool.c
index 761988e4162b..49b5db9030c5 100644
--- a/MdeModulePkg/Core/PiSmmCore/Pool.c
+++ b/MdeModulePkg/Core/PiSmmCore/Pool.c
@@ -1,7 +1,7 @@
 /** @file
   SMM Memory pool management functions.
 
-  Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2009 - 2016, 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        
@@ -260,7 +260,14 @@ SmmAllocatePool (
 
   Status = SmmInternalAllocatePool (PoolType, Size, Buffer);
   if (!EFI_ERROR (Status)) {
-    SmmCoreUpdateProfile ((EFI_PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS (0), 
MemoryProfileActionAllocatePool, PoolType, Size, *Buffer);
+    SmmCoreUpdateProfile (
+      (EFI_PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS (0),
+      MemoryProfileActionAllocatePool,
+      PoolType,
+      Size,
+      *Buffer,
+      NULL
+      );
   }
   return Status;
 }
@@ -319,7 +326,14 @@ SmmFreePool (
 
   Status = SmmInternalFreePool (Buffer);
   if (!EFI_ERROR (Status)) {
-    SmmCoreUpdateProfile ((EFI_PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS (0), 
MemoryProfileActionFreePool, 0, 0, Buffer);
+    SmmCoreUpdateProfile (
+      (EFI_PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS (0),
+      MemoryProfileActionFreePool,
+      EfiMaxMemoryType,
+      0,
+      Buffer,
+      NULL
+      );
   }
   return Status;
 }
diff --git a/MdeModulePkg/Core/PiSmmCore/SmramProfileRecord.c 
b/MdeModulePkg/Core/PiSmmCore/SmramProfileRecord.c
index 57b34a018dc4..281e382d5c81 100644
--- a/MdeModulePkg/Core/PiSmmCore/SmramProfileRecord.c
+++ b/MdeModulePkg/Core/PiSmmCore/SmramProfileRecord.c
@@ -15,6 +15,10 @@
 #include "PiSmmCore.h"
 
 #define IS_SMRAM_PROFILE_ENABLED ((PcdGet8 (PcdMemoryProfilePropertyMask) & 
BIT1) != 0)
+#define IS_UEFI_MEMORY_PROFILE_ENABLED ((PcdGet8 
(PcdMemoryProfilePropertyMask) & BIT0) != 0)
+
+#define GET_OCCUPIED_SIZE(ActualSize, Alignment) \
+  ((ActualSize) + (((Alignment) - ((ActualSize) & ((Alignment) - 1))) & 
((Alignment) - 1)))
 
 typedef struct {
   UINT32                        Signature;
@@ -26,12 +30,14 @@ typedef struct {
   UINT32                        Signature;
   MEMORY_PROFILE_DRIVER_INFO    DriverInfo;
   LIST_ENTRY                    *AllocInfoList;
+  CHAR8                         *PdbString;
   LIST_ENTRY                    Link;
 } MEMORY_PROFILE_DRIVER_INFO_DATA;
 
 typedef struct {
   UINT32                        Signature;
   MEMORY_PROFILE_ALLOC_INFO     AllocInfo;
+  CHAR8                         *ActionString;
   LIST_ENTRY                    Link;
 } MEMORY_PROFILE_ALLOC_INFO_DATA;
 
@@ -72,7 +78,10 @@ GLOBAL_REMOVE_IF_UNREFERENCED MEMORY_PROFILE_CONTEXT_DATA 
mSmramProfileContext =
 GLOBAL_REMOVE_IF_UNREFERENCED MEMORY_PROFILE_CONTEXT_DATA 
*mSmramProfileContextPtr = NULL;
 
 BOOLEAN mSmramReadyToLock;
-BOOLEAN mSmramProfileRecordingStatus = FALSE;
+BOOLEAN mSmramProfileGettingStatus = FALSE;
+BOOLEAN mSmramProfileRecordingEnable = MEMORY_PROFILE_RECORDING_DISABLE;
+EFI_DEVICE_PATH_PROTOCOL *mSmramProfileDriverPath;
+UINTN                    mSmramProfileDriverPathSize;
 
 /**
   Dump SMRAM infromation.
@@ -84,6 +93,155 @@ DumpSmramInfo (
   );
 
 /**
+  Get memory profile data.
+
+  @param[in]      This              The EDKII_SMM_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_UNSUPPORTED           Memory profile is unsupported.
+  @return EFI_BUFFER_TO_SMALL       The ProfileSize is too small for the 
resulting data. 
+                                    ProfileSize is updated with the size 
required.
+
+**/
+EFI_STATUS
+EFIAPI
+SmramProfileProtocolGetData (
+  IN     EDKII_SMM_MEMORY_PROFILE_PROTOCOL  *This,
+  IN OUT UINT64                             *ProfileSize,
+     OUT VOID                               *ProfileBuffer
+  );
+
+/**
+  Register image to memory profile.
+
+  @param[in] This               The EDKII_SMM_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 successfully.
+  @return EFI_UNSUPPORTED       Memory profile is unsupported,
+                                or memory profile for the image is not 
required.
+  @return EFI_OUT_OF_RESOURCE   No enough resource for this register.
+
+**/
+EFI_STATUS
+EFIAPI
+SmramProfileProtocolRegisterImage (
+  IN EDKII_SMM_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_SMM_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 successfully.
+  @return EFI_UNSUPPORTED       Memory profile is unsupported,
+                                or memory profile for the image is not 
required.
+  @return EFI_NOT_FOUND         The image is not found.
+
+**/
+EFI_STATUS
+EFIAPI
+SmramProfileProtocolUnregisterImage (
+  IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL  *This,
+  IN EFI_DEVICE_PATH_PROTOCOL           *FilePath,
+  IN PHYSICAL_ADDRESS                   ImageBase,
+  IN UINT64                             ImageSize
+  );
+
+/**
+  Get memory profile recording state.
+
+  @param[in]  This              The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.
+  @param[out] RecordingState    Recording state.
+
+  @return EFI_SUCCESS           Memory profile recording state is returned.
+  @return EFI_UNSUPPORTED       Memory profile is unsupported.
+  @return EFI_INVALID_PARAMETER RecordingState is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+SmramProfileProtocolGetRecordingState (
+  IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL  *This,
+  OUT BOOLEAN                           *RecordingState
+  );
+
+/**
+  Set memory profile recording state.
+
+  @param[in] This               The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.
+  @param[in] RecordingState     Recording state.
+
+  @return EFI_SUCCESS           Set memory profile recording state 
successfully.
+  @return EFI_UNSUPPORTED       Memory profile is unsupported.
+
+**/
+EFI_STATUS
+EFIAPI
+SmramProfileProtocolSetRecordingState (
+  IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL  *This,
+  IN BOOLEAN                            RecordingState
+  );
+
+/**
+  Record memory profile of multilevel caller.
+
+  @param[in] This               The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.
+  @param[in] CallerAddress      Address of caller.
+  @param[in] Action             Memory profile action.
+  @param[in] MemoryType         Memory type.
+                                EfiMaxMemoryType means the MemoryType is 
unknown.
+  @param[in] Buffer             Buffer address.
+  @param[in] Size               Buffer size.
+  @param[in] ActionString       String for memory profile action.
+                                Only needed for user defined allocate action.
+
+  @return EFI_SUCCESS           Memory profile is updated.
+  @return EFI_UNSUPPORTED       Memory profile is unsupported,
+                                or memory profile for the image is not 
required,
+                                or memory profile for the memory type is not 
required.
+  @return EFI_ACCESS_DENIED     It is during memory profile data getting.
+  @return EFI_ABORTED           Memory profile recording is not enabled.
+  @return EFI_OUT_OF_RESOURCES  No enough resource to update memory profile 
for allocate action.
+  @return EFI_NOT_FOUND         No matched allocate info found for free action.
+
+**/
+EFI_STATUS
+EFIAPI
+SmramProfileProtocolRecord (
+  IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL  *This,
+  IN PHYSICAL_ADDRESS                   CallerAddress,
+  IN MEMORY_PROFILE_ACTION              Action,
+  IN EFI_MEMORY_TYPE                    MemoryType,
+  IN VOID                               *Buffer,
+  IN UINTN                              Size,
+  IN CHAR8                              *ActionString OPTIONAL
+  );
+
+EDKII_SMM_MEMORY_PROFILE_PROTOCOL mSmmProfileProtocol = {
+  SmramProfileProtocolGetData,
+  SmramProfileProtocolRegisterImage,
+  SmramProfileProtocolUnregisterImage,
+  SmramProfileProtocolGetRecordingState,
+  SmramProfileProtocolSetRecordingState,
+  SmramProfileProtocolRecord,
+};
+
+/**
   Return SMRAM profile context.
 
   @return SMRAM profile context.
@@ -239,7 +397,6 @@ InternalPeCoffGetEntryPoint (
   @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.
@@ -260,13 +417,27 @@ BuildDriverInfo (
   MEMORY_PROFILE_DRIVER_INFO        *DriverInfo;
   MEMORY_PROFILE_DRIVER_INFO_DATA   *DriverInfoData;
   VOID                              *EntryPointInImage;
+  CHAR8                             *PdbString;
+  UINTN                             PdbSize;
+  UINTN                             PdbOccupiedSize;
+
+  PdbSize = 0;
+  PdbOccupiedSize = 0;
+  PdbString = NULL;
+  if (ImageBase != 0) {
+    PdbString = PeCoffLoaderGetPdbPointer ((VOID*) (UINTN) ImageBase);
+    if (PdbString != NULL) {
+      PdbSize = AsciiStrSize (PdbString);
+      PdbOccupiedSize = GET_OCCUPIED_SIZE (PdbSize, sizeof (UINT64));
+    }
+  }
 
   //
   // Use SmmInternalAllocatePool() that will not update profile for this 
AllocatePool action.
   //
   Status = SmmInternalAllocatePool (
              EfiRuntimeServicesData,
-             sizeof (*DriverInfoData) + sizeof (LIST_ENTRY),
+             sizeof (*DriverInfoData) + sizeof (LIST_ENTRY) + PdbSize,
              (VOID **) &DriverInfoData
              );
   if (EFI_ERROR (Status)) {
@@ -278,7 +449,7 @@ BuildDriverInfo (
   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.Length = (UINT16) (sizeof (MEMORY_PROFILE_DRIVER_INFO) + 
PdbOccupiedSize);
   DriverInfo->Header.Revision = MEMORY_PROFILE_DRIVER_INFO_REVISION;
   if (FileName != NULL) {
     CopyMem (&DriverInfo->FileName, FileName, sizeof (EFI_GUID));
@@ -302,6 +473,14 @@ BuildDriverInfo (
   DriverInfo->CurrentUsage = 0;
   DriverInfo->PeakUsage = 0;
   DriverInfo->AllocRecordCount = 0;
+  if (PdbSize != 0) {
+    DriverInfo->PdbStringOffset = (UINT16) sizeof (MEMORY_PROFILE_DRIVER_INFO);
+    DriverInfoData->PdbString = (CHAR8 *) (DriverInfoData->AllocInfoList + 1);
+    CopyMem (DriverInfoData->PdbString, PdbString, PdbSize);
+  } else {
+    DriverInfo->PdbStringOffset = 0;
+    DriverInfoData->PdbString = NULL;
+  }
 
   InsertTailList (ContextData->DriverInfoList, &DriverInfoData->Link);
   ContextData->Context.ImageCount ++;
@@ -332,7 +511,7 @@ RegisterImageToDxe (
   MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FilePath;
   UINT8                             TempBuffer[sizeof 
(MEDIA_FW_VOL_FILEPATH_DEVICE_PATH) + sizeof (EFI_DEVICE_PATH_PROTOCOL)];
 
-  if (IS_SMRAM_PROFILE_ENABLED) {
+  if (IS_UEFI_MEMORY_PROFILE_ENABLED) {
 
     FilePath = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *)TempBuffer;
     Status = gBS->LocateProtocol (&gEdkiiMemoryProfileGuid, NULL, (VOID **) 
&ProfileProtocol);
@@ -371,7 +550,7 @@ UnregisterImageFromDxe (
   MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FilePath;
   UINT8                             TempBuffer[sizeof 
(MEDIA_FW_VOL_FILEPATH_DEVICE_PATH) + sizeof (EFI_DEVICE_PATH_PROTOCOL)];
 
-  if (IS_SMRAM_PROFILE_ENABLED) {
+  if (IS_UEFI_MEMORY_PROFILE_ENABLED) {
 
     FilePath = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *)TempBuffer;
     Status = gBS->LocateProtocol (&gEdkiiMemoryProfileGuid, NULL, (VOID *) 
&ProfileProtocol);
@@ -390,6 +569,65 @@ UnregisterImageFromDxe (
 }
 
 /**
+  Return if record for this driver is needed..
+
+  @param DriverFilePath     Driver file path.
+
+  @retval TRUE              Record for this driver is needed.
+  @retval FALSE             Record for this driver is not needed.
+
+**/
+BOOLEAN
+NeedRecordThisDriver (
+  IN EFI_DEVICE_PATH_PROTOCOL       *DriverFilePath
+  )
+{
+  EFI_DEVICE_PATH_PROTOCOL    *TmpDevicePath;
+  EFI_DEVICE_PATH_PROTOCOL    *DevicePathInstance;
+  UINTN                       DevicePathSize;
+  UINTN                       FilePathSize;
+
+  if (!IsDevicePathValid (mSmramProfileDriverPath, 
mSmramProfileDriverPathSize)) {
+    //
+    // Invalid Device Path means record all.
+    //
+    return TRUE;
+  }
+  
+  //
+  // Record FilePath without end node.
+  //
+  FilePathSize = GetDevicePathSize (DriverFilePath) - 
sizeof(EFI_DEVICE_PATH_PROTOCOL);
+
+  DevicePathInstance = mSmramProfileDriverPath;
+  do {
+    //
+    // Find End node (it might be END_ENTIRE or END_INSTANCE)
+    //
+    TmpDevicePath = DevicePathInstance;
+    while (!IsDevicePathEndType (TmpDevicePath)) {
+      TmpDevicePath = NextDevicePathNode (TmpDevicePath);
+    }
+
+    //
+    // Do not compare END node
+    //
+    DevicePathSize = (UINTN)TmpDevicePath - (UINTN)DevicePathInstance;
+    if ((FilePathSize == DevicePathSize) &&
+        (CompareMem (DriverFilePath, DevicePathInstance, DevicePathSize) == 
0)) {
+      return TRUE;
+    }
+
+    //
+    // Get next instance
+    //
+    DevicePathInstance = (EFI_DEVICE_PATH_PROTOCOL 
*)((UINTN)DevicePathInstance + DevicePathSize + 
DevicePathNodeLength(TmpDevicePath));
+  } while (DevicePathSubType (TmpDevicePath) != 
END_ENTIRE_DEVICE_PATH_SUBTYPE);
+
+  return FALSE;
+}
+
+/**
   Register SMM Core to SMRAM profile.
 
   @param ContextData    SMRAM profile context.
@@ -405,15 +643,16 @@ RegisterSmmCore (
 {
   MEMORY_PROFILE_DRIVER_INFO_DATA   *DriverInfoData;
   PHYSICAL_ADDRESS                  ImageBase;
+  UINT8                             
TempBuffer[sizeof(MEDIA_FW_VOL_FILEPATH_DEVICE_PATH) + 
sizeof(EFI_DEVICE_PATH_PROTOCOL)];
+  MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FilePath;
 
-  ASSERT (ContextData != NULL);
+  FilePath = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) TempBuffer;
+  EfiInitializeFwVolDevicepathNode (FilePath, &gEfiCallerIdGuid);
+  SetDevicePathEndNode (FilePath + 1);
 
-  RegisterImageToDxe (
-    &gEfiCallerIdGuid,
-    gSmmCorePrivate->PiSmmCoreImageBase,
-    gSmmCorePrivate->PiSmmCoreImageSize,
-    EFI_FV_FILETYPE_SMM_CORE
-    );
+  if (!NeedRecordThisDriver ((EFI_DEVICE_PATH_PROTOCOL *) FilePath)) {
+    return FALSE;
+  }
 
   ImageBase = gSmmCorePrivate->PiSmmCoreImageBase;
   DriverInfoData = BuildDriverInfo (
@@ -443,6 +682,13 @@ SmramProfileInit (
 {
   MEMORY_PROFILE_CONTEXT_DATA *SmramProfileContext;
 
+  RegisterImageToDxe (
+    &gEfiCallerIdGuid,
+    gSmmCorePrivate->PiSmmCoreImageBase,
+    gSmmCorePrivate->PiSmmCoreImageSize,
+    EFI_FV_FILETYPE_SMM_CORE
+    );
+
   if (!IS_SMRAM_PROFILE_ENABLED) {
     return;
   }
@@ -452,7 +698,14 @@ SmramProfileInit (
     return;
   }
 
-  mSmramProfileRecordingStatus = TRUE;
+  mSmramProfileGettingStatus = FALSE;
+  if ((PcdGet8 (PcdMemoryProfilePropertyMask) & BIT7) != 0) {
+    mSmramProfileRecordingEnable = MEMORY_PROFILE_RECORDING_DISABLE;
+  } else {
+    mSmramProfileRecordingEnable = MEMORY_PROFILE_RECORDING_ENABLE;
+  }
+  mSmramProfileDriverPathSize = PcdGetSize (PcdMemoryProfileDriverPath);
+  mSmramProfileDriverPath = AllocateCopyPool (mSmramProfileDriverPathSize, 
PcdGetPtr (PcdMemoryProfileDriverPath));
   mSmramProfileContextPtr = &mSmramProfileContext;
 
   RegisterSmmCore (&mSmramProfileContext);
@@ -461,16 +714,75 @@ SmramProfileInit (
 }
 
 /**
+  Install SMRAM profile protocol.
+
+**/
+VOID
+SmramProfileInstallProtocol (
+  VOID
+  )
+{
+  EFI_HANDLE    Handle;
+  EFI_STATUS    Status;
+
+  if (!IS_SMRAM_PROFILE_ENABLED) {
+    return;
+  }
+
+  Handle = NULL;
+  Status = SmmInstallProtocolInterface (
+             &Handle,
+             &gEdkiiSmmMemoryProfileGuid,
+             EFI_NATIVE_INTERFACE,
+             &mSmmProfileProtocol
+             );
+  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;
+  if (FilePath != 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 SMM image to SMRAM profile.
 
   @param DriverEntry    SMM image info.
   @param RegisterToDxe  Register image to DXE.
 
-  @retval TRUE          Register success.
-  @retval FALSE         Register fail.
+  @return EFI_SUCCESS           Register successfully.
+  @return EFI_UNSUPPORTED       Memory profile is unsupported,
+                                or memory profile for the image is not 
required.
+  @return EFI_OUT_OF_RESOURCES  No enough resource for this register.
 
 **/
-BOOLEAN
+EFI_STATUS
 RegisterSmramProfileImage (
   IN EFI_SMM_DRIVER_ENTRY   *DriverEntry,
   IN BOOLEAN                RegisterToDxe
@@ -478,10 +790,8 @@ RegisterSmramProfileImage (
 {
   MEMORY_PROFILE_CONTEXT_DATA       *ContextData;
   MEMORY_PROFILE_DRIVER_INFO_DATA   *DriverInfoData;
-
-  if (!IS_SMRAM_PROFILE_ENABLED) {
-    return FALSE;
-  }
+  UINT8                             
TempBuffer[sizeof(MEDIA_FW_VOL_FILEPATH_DEVICE_PATH) + 
sizeof(EFI_DEVICE_PATH_PROTOCOL)];
+  MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FilePath;
 
   if (RegisterToDxe) {
     RegisterImageToDxe (
@@ -492,9 +802,21 @@ RegisterSmramProfileImage (
       );
   }
 
+  if (!IS_SMRAM_PROFILE_ENABLED) {
+    return EFI_UNSUPPORTED;
+  }
+
+  FilePath = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) TempBuffer;
+  EfiInitializeFwVolDevicepathNode (FilePath, &DriverEntry->FileName);
+  SetDevicePathEndNode (FilePath + 1);
+
+  if (!NeedRecordThisDriver ((EFI_DEVICE_PATH_PROTOCOL *) FilePath)) {
+    return EFI_UNSUPPORTED;
+  }
+
   ContextData = GetSmramProfileContext ();
   if (ContextData == NULL) {
-    return FALSE;
+    return EFI_UNSUPPORTED;
   }
 
   DriverInfoData = BuildDriverInfo (
@@ -507,10 +829,10 @@ RegisterSmramProfileImage (
                      EFI_FV_FILETYPE_SMM
                      );
   if (DriverInfoData == NULL) {
-    return FALSE;
+    return EFI_OUT_OF_RESOURCES;
   }
 
-  return TRUE;
+  return EFI_SUCCESS;
 }
 
 /**
@@ -558,42 +880,6 @@ GetMemoryProfileDriverInfoByFileNameAndAddress (
 }
 
 /**
-  Search dummy image from SMRAM 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)
 
@@ -632,10 +918,7 @@ GetMemoryProfileDriverInfoFromAddress (
     }
   }
 
-  //
-  // Should never come here.
-  //
-  return FindDummyImage (ContextData);
+  return NULL;
 }
 
 /**
@@ -644,11 +927,13 @@ GetMemoryProfileDriverInfoFromAddress (
   @param DriverEntry        SMM image info.
   @param UnregisterFromDxe  Unregister image from DXE.
 
-  @retval TRUE              Unregister success.
-  @retval FALSE             Unregister fail.
+  @return EFI_SUCCESS           Unregister successfully.
+  @return EFI_UNSUPPORTED       Memory profile is unsupported,
+                                or memory profile for the image is not 
required.
+  @return EFI_NOT_FOUND         The image is not found.
 
 **/
-BOOLEAN
+EFI_STATUS
 UnregisterSmramProfileImage (
   IN EFI_SMM_DRIVER_ENTRY  *DriverEntry,
   IN BOOLEAN               UnregisterFromDxe
@@ -660,10 +945,8 @@ UnregisterSmramProfileImage (
   EFI_GUID                          *FileName;
   PHYSICAL_ADDRESS                  ImageAddress;
   VOID                              *EntryPointInImage;
-
-  if (!IS_SMRAM_PROFILE_ENABLED) {
-    return FALSE;
-  }
+  UINT8                             
TempBuffer[sizeof(MEDIA_FW_VOL_FILEPATH_DEVICE_PATH) + 
sizeof(EFI_DEVICE_PATH_PROTOCOL)];
+  MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FilePath;
 
   if (UnregisterFromDxe) {
     UnregisterImageFromDxe (
@@ -673,9 +956,21 @@ UnregisterSmramProfileImage (
       );
   }
 
+  if (!IS_SMRAM_PROFILE_ENABLED) {
+    return EFI_UNSUPPORTED;
+  }
+
+  FilePath = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) TempBuffer;
+  EfiInitializeFwVolDevicepathNode (FilePath, &DriverEntry->FileName);
+  SetDevicePathEndNode (FilePath + 1);
+
+  if (!NeedRecordThisDriver ((EFI_DEVICE_PATH_PROTOCOL *) FilePath)) {
+    return EFI_UNSUPPORTED;
+  }
+
   ContextData = GetSmramProfileContext ();
   if (ContextData == NULL) {
-    return FALSE;
+    return EFI_UNSUPPORTED;
   }
 
   DriverInfoData = NULL;
@@ -697,12 +992,13 @@ UnregisterSmramProfileImage (
     DriverInfoData = GetMemoryProfileDriverInfoFromAddress (ContextData, 
ImageAddress);
   }
   if (DriverInfoData == NULL) {
-    return FALSE;
+    return EFI_NOT_FOUND;
   }
 
   ContextData->Context.TotalImageSize -= DriverInfoData->DriverInfo.ImageSize;
 
-  DriverInfoData->DriverInfo.ImageBase = 0;
+  // Keep the ImageBase for RVA calculation in Application.
+  //DriverInfoData->DriverInfo.ImageBase = 0;
   DriverInfoData->DriverInfo.ImageSize = 0;
 
   if (DriverInfoData->DriverInfo.PeakUsage == 0) {
@@ -714,7 +1010,7 @@ UnregisterSmramProfileImage (
     SmmInternalFreePool (DriverInfoData);
   }
 
-  return TRUE;
+  return EFI_SUCCESS;
 }
 
 /**
@@ -807,54 +1103,80 @@ SmramProfileUpdateFreePages (
   @param MemoryType     Memory type.
   @param Size           Buffer size.
   @param Buffer         Buffer address.
+  @param ActionString   String for memory profile action.
 
-  @retval TRUE          Profile udpate success.
-  @retval FALSE         Profile update fail.
+  @return EFI_SUCCESS           Memory profile is updated.
+  @return EFI_UNSUPPORTED       Memory profile is unsupported,
+                                or memory profile for the image is not 
required.
+  @return EFI_OUT_OF_RESOURCES  No enough resource to update memory profile 
for allocate action.
 
 **/
-BOOLEAN
+EFI_STATUS
 SmmCoreUpdateProfileAllocate (
   IN PHYSICAL_ADDRESS       CallerAddress,
   IN MEMORY_PROFILE_ACTION  Action,
   IN EFI_MEMORY_TYPE        MemoryType,
   IN UINTN                  Size,
-  IN VOID                   *Buffer
+  IN VOID                   *Buffer,
+  IN CHAR8                  *ActionString OPTIONAL
   )
 {
   EFI_STATUS                        Status;
-  MEMORY_PROFILE_CONTEXT           *Context;
-  MEMORY_PROFILE_DRIVER_INFO       *DriverInfo;
-  MEMORY_PROFILE_ALLOC_INFO        *AllocInfo;
+  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;
+  MEMORY_PROFILE_ACTION             BasicAction;
+  UINTN                             ActionStringSize;
+  UINTN                             ActionStringOccupiedSize;
 
-  AllocInfoData = NULL;
+  BasicAction = Action & MEMORY_PROFILE_ACTION_BASIC_MASK;
 
   ContextData = GetSmramProfileContext ();
   if (ContextData == NULL) {
-    return FALSE;
+    return EFI_UNSUPPORTED;
   }
 
   DriverInfoData = GetMemoryProfileDriverInfoFromAddress (ContextData, 
CallerAddress);
-  ASSERT (DriverInfoData != NULL);
+  if (DriverInfoData == NULL) {
+    return EFI_UNSUPPORTED;
+  }
+
+  ActionStringSize = 0;
+  ActionStringOccupiedSize = 0;
+  if (ActionString != NULL) {
+    ActionStringSize = AsciiStrSize (ActionString);
+    ActionStringOccupiedSize = GET_OCCUPIED_SIZE (ActionStringSize, sizeof 
(UINT64));
+  }
 
   //
   // Use SmmInternalAllocatePool() that will not update profile for this 
AllocatePool action.
   //
+  AllocInfoData = NULL;
   Status = SmmInternalAllocatePool (
              EfiRuntimeServicesData,
-             sizeof (*AllocInfoData),
+             sizeof (*AllocInfoData) + ActionStringSize,
              (VOID **) &AllocInfoData
              );
   if (EFI_ERROR (Status)) {
-    return FALSE;
+    return EFI_OUT_OF_RESOURCES;
+  }
+  ASSERT (AllocInfoData != NULL);
+
+  //
+  // Only update SequenceCount if and only if it is basic action.
+  //
+  if (Action == BasicAction) {
+    ContextData->Context.SequenceCount ++;
   }
+
   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.Length      = (UINT16) (sizeof (MEMORY_PROFILE_ALLOC_INFO) 
+ ActionStringOccupiedSize);
   AllocInfo->Header.Revision    = MEMORY_PROFILE_ALLOC_INFO_REVISION;
   AllocInfo->CallerAddress      = CallerAddress;
   AllocInfo->SequenceId         = ContextData->Context.SequenceCount;
@@ -862,42 +1184,56 @@ SmmCoreUpdateProfileAllocate (
   AllocInfo->MemoryType         = MemoryType;
   AllocInfo->Buffer             = (PHYSICAL_ADDRESS) (UINTN) Buffer;
   AllocInfo->Size               = Size;
+  if (ActionString != NULL) {
+    AllocInfo->ActionStringOffset = (UINT16) sizeof 
(MEMORY_PROFILE_ALLOC_INFO);
+    AllocInfoData->ActionString = (CHAR8 *) (AllocInfoData + 1);
+    CopyMem (AllocInfoData->ActionString, ActionString, ActionStringSize);
+  } else {
+    AllocInfo->ActionStringOffset = 0;
+    AllocInfoData->ActionString = NULL;
+  }
 
   InsertTailList (DriverInfoData->AllocInfoList, &AllocInfoData->Link);
 
-  ProfileMemoryIndex = GetProfileMemoryIndex (MemoryType);
-
+  Context = &ContextData->Context;
   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];
+  //
+  // Update summary if and only if it is basic action.
+  //
+  if (Action == BasicAction) {
+    ProfileMemoryIndex = GetProfileMemoryIndex (MemoryType);
+
+    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];
+    }
+
+    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];
+    }
+
+    SmramProfileUpdateFreePages (ContextData);
   }
-  Context->SequenceCount ++;
 
-  SmramProfileUpdateFreePages (ContextData);
-  return TRUE;
+  return EFI_SUCCESS;
 }
 
 /**
   Get memory profile alloc info from memory profile
 
   @param DriverInfoData     Driver info
-  @param Action             This Free action
+  @param BasicAction        This Free basic action
   @param Size               Buffer size
   @param Buffer             Buffer address
 
@@ -906,7 +1242,7 @@ SmmCoreUpdateProfileAllocate (
 MEMORY_PROFILE_ALLOC_INFO_DATA *
 GetMemoryProfileAllocInfoFromAddress (
   IN MEMORY_PROFILE_DRIVER_INFO_DATA    *DriverInfoData,
-  IN MEMORY_PROFILE_ACTION              Action,
+  IN MEMORY_PROFILE_ACTION              BasicAction,
   IN UINTN                              Size,
   IN VOID                               *Buffer
   )
@@ -928,10 +1264,10 @@ GetMemoryProfileAllocInfoFromAddress (
                       MEMORY_PROFILE_ALLOC_INFO_SIGNATURE
                       );
     AllocInfo = &AllocInfoData->AllocInfo;
-    if (AllocInfo->Action != Action) {
+    if ((AllocInfo->Action & MEMORY_PROFILE_ACTION_BASIC_MASK) != BasicAction) 
{
       continue;
     }
-    switch (Action) {
+    switch (BasicAction) {
       case MemoryProfileActionAllocatePages:
         if ((AllocInfo->Buffer <= (PHYSICAL_ADDRESS) (UINTN) Buffer) &&
             ((AllocInfo->Buffer + AllocInfo->Size) >= ((PHYSICAL_ADDRESS) 
(UINTN) Buffer + Size))) {
@@ -960,11 +1296,12 @@ GetMemoryProfileAllocInfoFromAddress (
   @param Size           Buffer size.
   @param Buffer         Buffer address.
 
-  @retval TRUE          Profile udpate success.
-  @retval FALSE         Profile update fail.
+  @return EFI_SUCCESS           Memory profile is updated.
+  @return EFI_UNSUPPORTED       Memory profile is unsupported.
+  @return EFI_NOT_FOUND         No matched allocate info found for free action.
 
 **/
-BOOLEAN
+EFI_STATUS
 SmmCoreUpdateProfileFree (
   IN PHYSICAL_ADDRESS       CallerAddress,
   IN MEMORY_PROFILE_ACTION  Action,
@@ -982,114 +1319,140 @@ SmmCoreUpdateProfileFree (
   MEMORY_PROFILE_DRIVER_INFO_DATA  *ThisDriverInfoData;
   MEMORY_PROFILE_ALLOC_INFO_DATA   *AllocInfoData;
   EFI_MEMORY_TYPE                  ProfileMemoryIndex;
+  MEMORY_PROFILE_ACTION            BasicAction;
+  BOOLEAN                          Found;
+
+  BasicAction = Action & MEMORY_PROFILE_ACTION_BASIC_MASK;
 
   ContextData = GetSmramProfileContext ();
   if (ContextData == NULL) {
-    return FALSE;
+    return EFI_UNSUPPORTED;
   }
 
   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) {
+  //
+  // Do not return if DriverInfoData == NULL here,
+  // because driver A might free memory allocated by driver B.
+  //
+
+  //
+  // Need use do-while loop to find all possible record,
+  // because one address might be recorded multiple times.
+  //
+  Found = FALSE;
+  AllocInfoData = NULL;
+  do {
+    if (DriverInfoData != NULL) {
+      switch (BasicAction) {
         case MemoryProfileActionFreePages:
-          AllocInfoData = GetMemoryProfileAllocInfoFromAddress 
(ThisDriverInfoData, MemoryProfileActionAllocatePages, Size, Buffer);
+          AllocInfoData = GetMemoryProfileAllocInfoFromAddress 
(DriverInfoData, MemoryProfileActionAllocatePages, Size, Buffer);
           break;
         case MemoryProfileActionFreePool:
-          AllocInfoData = GetMemoryProfileAllocInfoFromAddress 
(ThisDriverInfoData, MemoryProfileActionAllocatePool, 0, Buffer);
+          AllocInfoData = GetMemoryProfileAllocInfoFromAddress 
(DriverInfoData, 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.
+      // Legal case, because driver A might free memory allocated by driver B, 
by some protocol.
       //
-      return FALSE;
-    }
-  }
+      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 (BasicAction) {
+          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;
+        }
+      }
 
-  Context = &ContextData->Context;
-  DriverInfo = &DriverInfoData->DriverInfo;
-  AllocInfo = &AllocInfoData->AllocInfo;
+      if (AllocInfoData == NULL) {
+        //
+        // If (!Found), no matched allocate info is found for this free action.
+        // It is because the specified memory type allocate actions have been 
filtered by
+        // CoreNeedRecordProfile(), but free actions have no memory type 
information,
+        // they can not be filtered by CoreNeedRecordProfile(). Then, they 
will be
+        // filtered here.
+        //
+        // If (Found), it is normal exit path.
+        return (Found ? EFI_SUCCESS : EFI_NOT_FOUND);
+      }
+    }
 
-  ProfileMemoryIndex = GetProfileMemoryIndex (AllocInfo->MemoryType);
+    Found = TRUE;
 
-  Context->CurrentTotalUsage -= AllocInfo->Size;
-  Context->CurrentTotalUsageByType[ProfileMemoryIndex] -= AllocInfo->Size;
+    Context = &ContextData->Context;
+    DriverInfo = &DriverInfoData->DriverInfo;
+    AllocInfo = &AllocInfoData->AllocInfo;
 
-  DriverInfo->CurrentUsage -= AllocInfo->Size;
-  DriverInfo->CurrentUsageByType[ProfileMemoryIndex] -= AllocInfo->Size;
-  DriverInfo->AllocRecordCount --;
+    DriverInfo->AllocRecordCount --;
+    //
+    // Update summary if and only if it is basic action.
+    //
+    if (AllocInfo->Action == (AllocInfo->Action & 
MEMORY_PROFILE_ACTION_BASIC_MASK)) {
+      ProfileMemoryIndex = GetProfileMemoryIndex (AllocInfo->MemoryType);
 
-  RemoveEntryList (&AllocInfoData->Link);
+      Context->CurrentTotalUsage -= AllocInfo->Size;
+      Context->CurrentTotalUsageByType[ProfileMemoryIndex] -= AllocInfo->Size;
 
-  if (Action == MemoryProfileActionFreePages) {
-    if (AllocInfo->Buffer != (PHYSICAL_ADDRESS) (UINTN) Buffer) {
-      SmmCoreUpdateProfileAllocate (
-        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)) {
-      SmmCoreUpdateProfileAllocate (
-        AllocInfo->CallerAddress,
-        MemoryProfileActionAllocatePages,
-        AllocInfo->MemoryType,
-        (UINTN) ((AllocInfo->Buffer + AllocInfo->Size) - ((PHYSICAL_ADDRESS) 
(UINTN) Buffer + Size)),
-        (VOID *) ((UINTN) Buffer + Size)
-        );
+      DriverInfo->CurrentUsage -= AllocInfo->Size;
+      DriverInfo->CurrentUsageByType[ProfileMemoryIndex] -= AllocInfo->Size;
     }
-  }
 
-  //
-  // Use SmmInternalFreePool() that will not update profile for this FreePool 
action.
-  //
-  SmmInternalFreePool (AllocInfoData);
+    RemoveEntryList (&AllocInfoData->Link);
+
+    if (BasicAction == MemoryProfileActionFreePages) {
+      if (AllocInfo->Buffer != (PHYSICAL_ADDRESS) (UINTN) Buffer) {
+        SmmCoreUpdateProfileAllocate (
+          AllocInfo->CallerAddress,
+          AllocInfo->Action,
+          AllocInfo->MemoryType,
+          (UINTN) ((PHYSICAL_ADDRESS) (UINTN) Buffer - AllocInfo->Buffer),
+          (VOID *) (UINTN) AllocInfo->Buffer,
+          AllocInfoData->ActionString
+          );
+      }
+      if (AllocInfo->Buffer + AllocInfo->Size != ((PHYSICAL_ADDRESS) (UINTN) 
Buffer + Size)) {
+        SmmCoreUpdateProfileAllocate (
+          AllocInfo->CallerAddress,
+          AllocInfo->Action,
+          AllocInfo->MemoryType,
+          (UINTN) ((AllocInfo->Buffer + AllocInfo->Size) - ((PHYSICAL_ADDRESS) 
(UINTN) Buffer + Size)),
+          (VOID *) ((UINTN) Buffer + Size),
+          AllocInfoData->ActionString
+          );
+      }
+    }
 
-  return TRUE;
+    //
+    // Use SmmInternalFreePool() that will not update profile for this 
FreePool action.
+    //
+    SmmInternalFreePool (AllocInfoData);
+  } while (TRUE);
 }
 
 /**
@@ -1098,68 +1461,91 @@ SmmCoreUpdateProfileFree (
   @param CallerAddress  Address of caller who call Allocate or Free.
   @param Action         This Allocate or Free action.
   @param MemoryType     Memory type.
+                        EfiMaxMemoryType means the MemoryType is unknown.
   @param Size           Buffer size.
   @param Buffer         Buffer address.
-
-  @retval TRUE          Profile udpate success.
-  @retval FALSE         Profile update fail.
+  @param ActionString   String for memory profile action.
+                        Only needed for user defined allocate action.
+
+  @return EFI_SUCCESS           Memory profile is updated.
+  @return EFI_UNSUPPORTED       Memory profile is unsupported,
+                                or memory profile for the image is not 
required,
+                                or memory profile for the memory type is not 
required.
+  @return EFI_ACCESS_DENIED     It is during memory profile data getting.
+  @return EFI_ABORTED           Memory profile recording is not enabled.
+  @return EFI_OUT_OF_RESOURCES  No enough resource to update memory profile 
for allocate action.
+  @return EFI_NOT_FOUND         No matched allocate info found for free action.
 
 **/
-BOOLEAN
+EFI_STATUS
+EFIAPI
 SmmCoreUpdateProfile (
   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
+  IN VOID                   *Buffer,
+  IN CHAR8                  *ActionString OPTIONAL
   )
 {
+  EFI_STATUS                    Status;
   MEMORY_PROFILE_CONTEXT_DATA   *ContextData;
+  MEMORY_PROFILE_ACTION         BasicAction;
 
   if (!IS_SMRAM_PROFILE_ENABLED) {
-    return FALSE;
+    return EFI_UNSUPPORTED;
   }
 
-  if (!mSmramProfileRecordingStatus) {
-    return FALSE;
+  if (mSmramProfileGettingStatus) {
+    return EFI_ACCESS_DENIED;
+  }
+
+  if (!mSmramProfileRecordingEnable) {
+    return EFI_ABORTED;
   }
 
   //
+  // Get the basic action to know how to process the record
+  //
+  BasicAction = Action & MEMORY_PROFILE_ACTION_BASIC_MASK;
+
+  //
   // Free operations have no memory type information, so skip the check.
   //
-  if ((Action == MemoryProfileActionAllocatePages) || (Action == 
MemoryProfileActionAllocatePool)) {
+  if ((BasicAction == MemoryProfileActionAllocatePages) || (BasicAction == 
MemoryProfileActionAllocatePool)) {
     //
     // Only record limited MemoryType.
     //
     if (!SmmCoreNeedRecordProfile (MemoryType)) {
-      return FALSE;
+      return EFI_UNSUPPORTED;
     }
   }
 
   ContextData = GetSmramProfileContext ();
   if (ContextData == NULL) {
-    return FALSE;
+    return EFI_UNSUPPORTED;
   }
 
-  switch (Action) {
+  switch (BasicAction) {
     case MemoryProfileActionAllocatePages:
-      SmmCoreUpdateProfileAllocate (CallerAddress, Action, MemoryType, Size, 
Buffer);
+      Status = SmmCoreUpdateProfileAllocate (CallerAddress, Action, 
MemoryType, Size, Buffer, ActionString);
       break;
     case MemoryProfileActionFreePages:
-      SmmCoreUpdateProfileFree (CallerAddress, Action, Size, Buffer);
+      Status = SmmCoreUpdateProfileFree (CallerAddress, Action, Size, Buffer);
       break;
     case MemoryProfileActionAllocatePool:
-      SmmCoreUpdateProfileAllocate (CallerAddress, Action, MemoryType, Size, 
Buffer);
+      Status = SmmCoreUpdateProfileAllocate (CallerAddress, Action, 
MemoryType, Size, Buffer, ActionString);
       break;
     case MemoryProfileActionFreePool:
-      SmmCoreUpdateProfileFree (CallerAddress, Action, 0, Buffer);
+      Status = SmmCoreUpdateProfileFree (CallerAddress, Action, 0, Buffer);
       break;
     default:
       ASSERT (FALSE);
+      Status = EFI_UNSUPPORTED;
       break;
   }
 
-  return TRUE;
+  return Status;
 }
 
 /**
@@ -1192,17 +1578,20 @@ SmramProfileGetDataSize (
   VOID
   )
 {
-  MEMORY_PROFILE_CONTEXT_DATA      *ContextData;
-  MEMORY_PROFILE_DRIVER_INFO_DATA  *DriverInfoData;
-  LIST_ENTRY                      *DriverInfoList;
-  LIST_ENTRY                      *DriverLink;
-  UINTN                           TotalSize;
-  LIST_ENTRY                      *Node;
-  LIST_ENTRY                      *FreePageList;
-  LIST_ENTRY                      *FreePoolList;
-  FREE_POOL_HEADER                *Pool;
-  UINTN                           PoolListIndex;
-  UINTN                           Index;
+  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;
+  UINTN                             TotalSize;
+  LIST_ENTRY                        *Node;
+  LIST_ENTRY                        *FreePageList;
+  LIST_ENTRY                        *FreePoolList;
+  FREE_POOL_HEADER                  *Pool;
+  UINTN                             PoolListIndex;
+  UINTN                             Index;
 
   ContextData = GetSmramProfileContext ();
   if (ContextData == NULL) {
@@ -1210,7 +1599,6 @@ SmramProfileGetDataSize (
   }
 
   TotalSize = sizeof (MEMORY_PROFILE_CONTEXT);
-  TotalSize += sizeof (MEMORY_PROFILE_DRIVER_INFO) * (UINTN) 
ContextData->Context.ImageCount;
 
   DriverInfoList = ContextData->DriverInfoList;
   for (DriverLink = DriverInfoList->ForwardLink;
@@ -1222,7 +1610,20 @@ SmramProfileGetDataSize (
                    Link,
                    MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
                    );
-    TotalSize += sizeof (MEMORY_PROFILE_ALLOC_INFO) * (UINTN) 
DriverInfoData->DriverInfo.AllocRecordCount;
+    TotalSize += DriverInfoData->DriverInfo.Header.Length;
+
+    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
+                        );
+      TotalSize += AllocInfoData->AllocInfo.Header.Length;
+    }
   }
 
 
@@ -1291,6 +1692,8 @@ SmramProfileCopyData (
   MEMORY_PROFILE_DESCRIPTOR       *MemoryProfileDescriptor;
   UINT64                          Offset;
   UINT64                          RemainingSize;
+  UINTN                           PdbSize;
+  UINTN                           ActionStringSize;
 
   ContextData = GetSmramProfileContext ();
   if (ContextData == NULL) {
@@ -1322,17 +1725,21 @@ SmramProfileCopyData (
                        Link,
                        MEMORY_PROFILE_DRIVER_INFO_SIGNATURE
                        );
-    if (*ProfileOffset < (Offset + sizeof (MEMORY_PROFILE_DRIVER_INFO))) {
-      if (RemainingSize >= sizeof (MEMORY_PROFILE_DRIVER_INFO)) {
+    if (*ProfileOffset < (Offset + DriverInfoData->DriverInfo.Header.Length)) {
+      if (RemainingSize >= DriverInfoData->DriverInfo.Header.Length) {
         DriverInfo = ProfileBuffer;
         CopyMem (DriverInfo, &DriverInfoData->DriverInfo, sizeof 
(MEMORY_PROFILE_DRIVER_INFO));
-        RemainingSize -= sizeof (MEMORY_PROFILE_DRIVER_INFO);
-        ProfileBuffer = (UINT8 *) ProfileBuffer + sizeof 
(MEMORY_PROFILE_DRIVER_INFO);
+        if (DriverInfo->PdbStringOffset != 0) {
+          PdbSize = AsciiStrSize (DriverInfoData->PdbString);
+          CopyMem ((VOID *) ((UINTN) DriverInfo + 
DriverInfo->PdbStringOffset), DriverInfoData->PdbString, PdbSize);
+        }
+        RemainingSize -= DriverInfo->Header.Length;
+        ProfileBuffer = (UINT8 *) ProfileBuffer + DriverInfo->Header.Length;
       } else {
         goto Done;
       }
     }
-    Offset += sizeof (MEMORY_PROFILE_DRIVER_INFO);
+    Offset += DriverInfoData->DriverInfo.Header.Length;
 
     AllocInfoList = DriverInfoData->AllocInfoList;
     for (AllocLink = AllocInfoList->ForwardLink;
@@ -1344,17 +1751,21 @@ SmramProfileCopyData (
                         Link,
                         MEMORY_PROFILE_ALLOC_INFO_SIGNATURE
                         );
-      if (*ProfileOffset < (Offset + sizeof (MEMORY_PROFILE_ALLOC_INFO))) {
-        if (RemainingSize >= sizeof (MEMORY_PROFILE_ALLOC_INFO)) {
+      if (*ProfileOffset < (Offset + AllocInfoData->AllocInfo.Header.Length)) {
+        if (RemainingSize >= AllocInfoData->AllocInfo.Header.Length) {
           AllocInfo = ProfileBuffer;
           CopyMem (AllocInfo, &AllocInfoData->AllocInfo, sizeof 
(MEMORY_PROFILE_ALLOC_INFO));
-          RemainingSize -= sizeof (MEMORY_PROFILE_ALLOC_INFO);
-          ProfileBuffer = (UINT8 *) ProfileBuffer + sizeof 
(MEMORY_PROFILE_ALLOC_INFO);
+          if (AllocInfo->ActionStringOffset) {
+            ActionStringSize = AsciiStrSize (AllocInfoData->ActionString);
+            CopyMem ((VOID *) ((UINTN) AllocInfo + 
AllocInfo->ActionStringOffset), AllocInfoData->ActionString, ActionStringSize);
+          }
+          RemainingSize -= AllocInfo->Header.Length;
+          ProfileBuffer = (UINT8 *) ProfileBuffer + AllocInfo->Header.Length;
         } else {
           goto Done;
         }
       }
-      Offset += sizeof (MEMORY_PROFILE_ALLOC_INFO);
+      Offset += AllocInfoData->AllocInfo.Header.Length;
     }
   }
 
@@ -1485,6 +1896,241 @@ Done:
 }
 
 /**
+  Get memory profile data.
+
+  @param[in]      This              The EDKII_SMM_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_UNSUPPORTED           Memory profile is unsupported.
+  @return EFI_BUFFER_TO_SMALL       The ProfileSize is too small for the 
resulting data. 
+                                    ProfileSize is updated with the size 
required.
+
+**/
+EFI_STATUS
+EFIAPI
+SmramProfileProtocolGetData (
+  IN     EDKII_SMM_MEMORY_PROFILE_PROTOCOL  *This,
+  IN OUT UINT64                             *ProfileSize,
+     OUT VOID                               *ProfileBuffer
+  )
+{
+  UINT64                                Size;
+  UINT64                                Offset;
+  MEMORY_PROFILE_CONTEXT_DATA           *ContextData;
+  BOOLEAN                               SmramProfileGettingStatus;
+
+  ContextData = GetSmramProfileContext ();
+  if (ContextData == NULL) {
+    return EFI_UNSUPPORTED;
+  }
+
+  SmramProfileGettingStatus = mSmramProfileGettingStatus;
+  mSmramProfileGettingStatus = TRUE;
+
+  Size = SmramProfileGetDataSize ();
+
+  if (*ProfileSize < Size) {
+    *ProfileSize = Size;
+    mSmramProfileGettingStatus = SmramProfileGettingStatus;
+    return EFI_BUFFER_TOO_SMALL;
+  }
+
+  Offset = 0;
+  SmramProfileCopyData (ProfileBuffer, &Size, &Offset);
+  *ProfileSize = Size;
+
+  mSmramProfileGettingStatus = SmramProfileGettingStatus;
+  return EFI_SUCCESS;
+}
+
+/**
+  Register image to memory profile.
+
+  @param[in] This               The EDKII_SMM_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 successfully.
+  @return EFI_UNSUPPORTED       Memory profile is unsupported,
+                                or memory profile for the image is not 
required.
+  @return EFI_OUT_OF_RESOURCES  No enough resource for this register.
+
+**/
+EFI_STATUS
+EFIAPI
+SmramProfileProtocolRegisterImage (
+  IN EDKII_SMM_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;
+  EFI_SMM_DRIVER_ENTRY              DriverEntry;
+  VOID                              *EntryPointInImage;
+  EFI_GUID                          *Name;
+  
+  ZeroMem (&DriverEntry, sizeof (DriverEntry));
+  Name = GetFileNameFromFilePath (FilePath);
+  if (Name != NULL) {
+    CopyMem (&DriverEntry.FileName, Name, sizeof (EFI_GUID));
+  }
+  DriverEntry.ImageBuffer = ImageBase;
+  DriverEntry.NumberOfPage = EFI_SIZE_TO_PAGES ((UINTN) ImageSize);
+  Status = InternalPeCoffGetEntryPoint ((VOID *) (UINTN) 
DriverEntry.ImageBuffer, &EntryPointInImage);
+  ASSERT_EFI_ERROR (Status);
+  DriverEntry.ImageEntryPoint = (PHYSICAL_ADDRESS) (UINTN) EntryPointInImage;
+
+  return RegisterSmramProfileImage (&DriverEntry, FALSE);
+}
+
+/**
+  Unregister image from memory profile.
+
+  @param[in] This               The EDKII_SMM_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 successfully.
+  @return EFI_UNSUPPORTED       Memory profile is unsupported,
+                                or memory profile for the image is not 
required.
+  @return EFI_NOT_FOUND         The image is not found.
+
+**/
+EFI_STATUS
+EFIAPI
+SmramProfileProtocolUnregisterImage (
+  IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL  *This,
+  IN EFI_DEVICE_PATH_PROTOCOL           *FilePath,
+  IN PHYSICAL_ADDRESS                   ImageBase,
+  IN UINT64                             ImageSize
+  )
+{
+  EFI_STATUS                        Status;
+  EFI_SMM_DRIVER_ENTRY              DriverEntry;
+  VOID                              *EntryPointInImage;
+  EFI_GUID                          *Name;
+
+  ZeroMem (&DriverEntry, sizeof (DriverEntry));
+  Name = GetFileNameFromFilePath (FilePath);
+  if (Name != NULL) {
+    CopyMem (&DriverEntry.FileName, Name, sizeof (EFI_GUID));
+  }
+  DriverEntry.ImageBuffer = ImageBase;
+  DriverEntry.NumberOfPage = EFI_SIZE_TO_PAGES ((UINTN) ImageSize);
+  Status = InternalPeCoffGetEntryPoint ((VOID *) (UINTN) 
DriverEntry.ImageBuffer, &EntryPointInImage);
+  ASSERT_EFI_ERROR (Status);
+  DriverEntry.ImageEntryPoint = (PHYSICAL_ADDRESS) (UINTN) EntryPointInImage;
+
+  return UnregisterSmramProfileImage (&DriverEntry, FALSE);
+}
+
+/**
+  Get memory profile recording state.
+
+  @param[in]  This              The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.
+  @param[out] RecordingState    Recording state.
+
+  @return EFI_SUCCESS           Memory profile recording state is returned.
+  @return EFI_UNSUPPORTED       Memory profile is unsupported.
+  @return EFI_INVALID_PARAMETER RecordingState is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+SmramProfileProtocolGetRecordingState (
+  IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL  *This,
+  OUT BOOLEAN                           *RecordingState
+  )
+{
+  MEMORY_PROFILE_CONTEXT_DATA           *ContextData;
+
+  ContextData = GetSmramProfileContext ();
+  if (ContextData == NULL) {
+    return EFI_UNSUPPORTED;
+  }
+
+  if (RecordingState == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+  *RecordingState = mSmramProfileRecordingEnable;
+  return EFI_SUCCESS;
+}
+
+/**
+  Set memory profile recording state.
+
+  @param[in] This               The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.
+  @param[in] RecordingState     Recording state.
+
+  @return EFI_SUCCESS           Set memory profile recording state 
successfully.
+  @return EFI_UNSUPPORTED       Memory profile is unsupported.
+
+**/
+EFI_STATUS
+EFIAPI
+SmramProfileProtocolSetRecordingState (
+  IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL  *This,
+  IN BOOLEAN                            RecordingState
+  )
+{
+  MEMORY_PROFILE_CONTEXT_DATA           *ContextData;
+
+  ContextData = GetSmramProfileContext ();
+  if (ContextData == NULL) {
+    return EFI_UNSUPPORTED;
+  }
+
+  mSmramProfileRecordingEnable = RecordingState;
+  return EFI_SUCCESS;
+}
+
+/**
+  Record memory profile of multilevel caller.
+
+  @param[in] This               The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.
+  @param[in] CallerAddress      Address of caller.
+  @param[in] Action             Memory profile action.
+  @param[in] MemoryType         Memory type.
+                                EfiMaxMemoryType means the MemoryType is 
unknown.
+  @param[in] Buffer             Buffer address.
+  @param[in] Size               Buffer size.
+  @param[in] ActionString       String for memory profile action.
+                                Only needed for user defined allocate action.
+
+  @return EFI_SUCCESS           Memory profile is updated.
+  @return EFI_UNSUPPORTED       Memory profile is unsupported,
+                                or memory profile for the image is not 
required,
+                                or memory profile for the memory type is not 
required.
+  @return EFI_ACCESS_DENIED     It is during memory profile data getting.
+  @return EFI_ABORTED           Memory profile recording is not enabled.
+  @return EFI_OUT_OF_RESOURCES  No enough resource to update memory profile 
for allocate action.
+  @return EFI_NOT_FOUND         No matched allocate info found for free action.
+
+**/
+EFI_STATUS
+EFIAPI
+SmramProfileProtocolRecord (
+  IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL  *This,
+  IN PHYSICAL_ADDRESS                   CallerAddress,
+  IN MEMORY_PROFILE_ACTION              Action,
+  IN EFI_MEMORY_TYPE                    MemoryType,
+  IN VOID                               *Buffer,
+  IN UINTN                              Size,
+  IN CHAR8                              *ActionString OPTIONAL
+  )
+{
+  return SmmCoreUpdateProfile (CallerAddress, Action, MemoryType, Size, 
Buffer, ActionString);
+}
+
+/**
   SMRAM profile handler to get profile info.
 
   @param SmramProfileParameterGetInfo The parameter of SMM profile get size.
@@ -1496,20 +2142,20 @@ SmramProfileHandlerGetInfo (
   )
 {
   MEMORY_PROFILE_CONTEXT_DATA   *ContextData;
-  BOOLEAN                       SmramProfileRecordingStatus;
+  BOOLEAN                       SmramProfileGettingStatus;
 
   ContextData = GetSmramProfileContext ();
   if (ContextData == NULL) {
     return ;
   }
 
-  SmramProfileRecordingStatus = mSmramProfileRecordingStatus;
-  mSmramProfileRecordingStatus = FALSE;
+  SmramProfileGettingStatus = mSmramProfileGettingStatus;
+  mSmramProfileGettingStatus = TRUE;
 
   SmramProfileParameterGetInfo->ProfileSize = SmramProfileGetDataSize();
   SmramProfileParameterGetInfo->Header.ReturnStatus = 0;
 
-  mSmramProfileRecordingStatus = SmramProfileRecordingStatus;
+  mSmramProfileGettingStatus = SmramProfileGettingStatus;
 }
 
 /**
@@ -1527,15 +2173,15 @@ SmramProfileHandlerGetData (
   UINT64                                    ProfileOffset;
   SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA  SmramProfileGetData;
   MEMORY_PROFILE_CONTEXT_DATA               *ContextData;
-  BOOLEAN                                   SmramProfileRecordingStatus;
+  BOOLEAN                                   SmramProfileGettingStatus;
 
   ContextData = GetSmramProfileContext ();
   if (ContextData == NULL) {
     return ;
   }
 
-  SmramProfileRecordingStatus = mSmramProfileRecordingStatus;
-  mSmramProfileRecordingStatus = FALSE;
+  SmramProfileGettingStatus = mSmramProfileGettingStatus;
+  mSmramProfileGettingStatus = TRUE;
 
 
   CopyMem (&SmramProfileGetData, SmramProfileParameterGetData, sizeof 
(SmramProfileGetData));
@@ -1564,7 +2210,7 @@ SmramProfileHandlerGetData (
   SmramProfileParameterGetData->Header.ReturnStatus = 0;
 
 Done:
-  mSmramProfileRecordingStatus = SmramProfileRecordingStatus;
+  mSmramProfileGettingStatus = SmramProfileGettingStatus;
 }
 
 /**
@@ -1580,15 +2226,15 @@ SmramProfileHandlerGetDataByOffset (
 {
   SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA_BY_OFFSET    
SmramProfileGetDataByOffset;
   MEMORY_PROFILE_CONTEXT_DATA                           *ContextData;
-  BOOLEAN                                               
SmramProfileRecordingStatus;
+  BOOLEAN                                               
SmramProfileGettingStatus;
 
   ContextData = GetSmramProfileContext ();
   if (ContextData == NULL) {
     return ;
   }
 
-  SmramProfileRecordingStatus = mSmramProfileRecordingStatus;
-  mSmramProfileRecordingStatus = FALSE;
+  SmramProfileGettingStatus = mSmramProfileGettingStatus;
+  mSmramProfileGettingStatus = TRUE;
 
 
   CopyMem (&SmramProfileGetDataByOffset, SmramProfileParameterGetDataByOffset, 
sizeof (SmramProfileGetDataByOffset));
@@ -1607,7 +2253,7 @@ SmramProfileHandlerGetDataByOffset (
   SmramProfileParameterGetDataByOffset->Header.ReturnStatus = 0;
 
 Done:
-  mSmramProfileRecordingStatus = SmramProfileRecordingStatus;
+  mSmramProfileGettingStatus = SmramProfileGettingStatus;
 }
 
 /**
@@ -1624,7 +2270,6 @@ SmramProfileHandlerRegisterImage (
   EFI_STATUS                        Status;
   EFI_SMM_DRIVER_ENTRY              DriverEntry;
   VOID                              *EntryPointInImage;
-  BOOLEAN                           Ret;
 
   ZeroMem (&DriverEntry, sizeof (DriverEntry));
   CopyMem (&DriverEntry.FileName, 
&SmramProfileParameterRegisterImage->FileName, sizeof(EFI_GUID));
@@ -1634,8 +2279,8 @@ SmramProfileHandlerRegisterImage (
   ASSERT_EFI_ERROR (Status);
   DriverEntry.ImageEntryPoint = (PHYSICAL_ADDRESS) (UINTN) EntryPointInImage;
 
-  Ret = RegisterSmramProfileImage (&DriverEntry, FALSE);
-  if (Ret) {
+  Status = RegisterSmramProfileImage (&DriverEntry, FALSE);
+  if (!EFI_ERROR (Status)) {
     SmramProfileParameterRegisterImage->Header.ReturnStatus = 0;
   }
 }
@@ -1654,7 +2299,6 @@ SmramProfileHandlerUnregisterImage (
   EFI_STATUS                        Status;
   EFI_SMM_DRIVER_ENTRY              DriverEntry;
   VOID                              *EntryPointInImage;
-  BOOLEAN                           Ret;
 
   ZeroMem (&DriverEntry, sizeof (DriverEntry));
   CopyMem (&DriverEntry.FileName, 
&SmramProfileParameterUnregisterImage->FileName, sizeof (EFI_GUID));
@@ -1664,8 +2308,8 @@ SmramProfileHandlerUnregisterImage (
   ASSERT_EFI_ERROR (Status);
   DriverEntry.ImageEntryPoint = (PHYSICAL_ADDRESS) (UINTN) EntryPointInImage;
 
-  Ret = UnregisterSmramProfileImage (&DriverEntry, FALSE);
-  if (Ret) {
+  Status = UnregisterSmramProfileImage (&DriverEntry, FALSE);
+  if (!EFI_ERROR (Status)) {
     SmramProfileParameterUnregisterImage->Header.ReturnStatus = 0;
   }
 }
@@ -1697,6 +2341,7 @@ SmramProfileHandler (
 {
   SMRAM_PROFILE_PARAMETER_HEADER           *SmramProfileParameterHeader;
   UINTN                                    TempCommBufferSize;
+  SMRAM_PROFILE_PARAMETER_RECORDING_STATE  *ParameterRecordingState;
 
   DEBUG ((EFI_D_ERROR, "SmramProfileHandler Enter\n"));
 
@@ -1775,6 +2420,27 @@ SmramProfileHandler (
     }
     SmramProfileHandlerUnregisterImage 
((SMRAM_PROFILE_PARAMETER_UNREGISTER_IMAGE *) (UINTN) CommBuffer);
     break;
+  case SMRAM_PROFILE_COMMAND_GET_RECORDING_STATE:
+    DEBUG ((EFI_D_ERROR, "SmramProfileHandlerGetRecordingState\n"));
+    if (TempCommBufferSize != sizeof 
(SMRAM_PROFILE_PARAMETER_RECORDING_STATE)) {
+      DEBUG ((EFI_D_ERROR, "SmramProfileHandler: SMM communication buffer size 
invalid!\n"));
+      return EFI_SUCCESS;
+    }
+    ParameterRecordingState = (SMRAM_PROFILE_PARAMETER_RECORDING_STATE *) 
(UINTN) CommBuffer;
+    ParameterRecordingState->RecordingState = mSmramProfileRecordingEnable;
+    ParameterRecordingState->Header.ReturnStatus = 0;
+    break;
+  case SMRAM_PROFILE_COMMAND_SET_RECORDING_STATE:
+    DEBUG ((EFI_D_ERROR, "SmramProfileHandlerSetRecordingState\n"));
+    if (TempCommBufferSize != sizeof 
(SMRAM_PROFILE_PARAMETER_RECORDING_STATE)) {
+      DEBUG ((EFI_D_ERROR, "SmramProfileHandler: SMM communication buffer size 
invalid!\n"));
+      return EFI_SUCCESS;
+    }
+    ParameterRecordingState = (SMRAM_PROFILE_PARAMETER_RECORDING_STATE *) 
(UINTN) CommBuffer;
+    mSmramProfileRecordingEnable = ParameterRecordingState->RecordingState;
+    ParameterRecordingState->Header.ReturnStatus = 0;
+    break;
+
   default:
     break;
   }
@@ -1821,15 +2487,15 @@ DumpSmramRange (
 {
   UINTN                         Index;
   MEMORY_PROFILE_CONTEXT_DATA   *ContextData;
-  BOOLEAN                       SmramProfileRecordingStatus;
+  BOOLEAN                       SmramProfileGettingStatus;
 
   ContextData = GetSmramProfileContext ();
   if (ContextData == NULL) {
     return ;
   }
 
-  SmramProfileRecordingStatus = mSmramProfileRecordingStatus;
-  mSmramProfileRecordingStatus = FALSE;
+  SmramProfileGettingStatus = mSmramProfileGettingStatus;
+  mSmramProfileGettingStatus = TRUE;
 
   DEBUG ((EFI_D_INFO, "FullSmramRange address - 0x%08x\n", mFullSmramRanges));
 
@@ -1846,7 +2512,7 @@ DumpSmramRange (
 
   DEBUG ((EFI_D_INFO, "======= SmramProfile end =======\n"));
 
-  mSmramProfileRecordingStatus = SmramProfileRecordingStatus;
+  mSmramProfileGettingStatus = SmramProfileGettingStatus;
 }
 
 /**
@@ -1863,15 +2529,15 @@ DumpFreePagesList (
   FREE_PAGE_LIST                *Pages;
   UINTN                         Index;
   MEMORY_PROFILE_CONTEXT_DATA   *ContextData;
-  BOOLEAN                       SmramProfileRecordingStatus;
+  BOOLEAN                       SmramProfileGettingStatus;
 
   ContextData = GetSmramProfileContext ();
   if (ContextData == NULL) {
     return ;
   }
 
-  SmramProfileRecordingStatus = mSmramProfileRecordingStatus;
-  mSmramProfileRecordingStatus = FALSE;
+  SmramProfileGettingStatus = mSmramProfileGettingStatus;
+  mSmramProfileGettingStatus = TRUE;
 
   DEBUG ((EFI_D_INFO, "======= SmramProfile begin =======\n"));
 
@@ -1888,7 +2554,7 @@ DumpFreePagesList (
 
   DEBUG ((EFI_D_INFO, "======= SmramProfile end =======\n"));
 
-  mSmramProfileRecordingStatus = SmramProfileRecordingStatus;
+  mSmramProfileGettingStatus = SmramProfileGettingStatus;
 }
 
 /**
@@ -1900,21 +2566,21 @@ DumpFreePoolList (
   VOID
   )
 {
-  LIST_ENTRY                     *FreePoolList;
-  LIST_ENTRY                     *Node;
-  FREE_POOL_HEADER               *Pool;
-  UINTN                          Index;
-  UINTN                          PoolListIndex;
+  LIST_ENTRY                    *FreePoolList;
+  LIST_ENTRY                    *Node;
+  FREE_POOL_HEADER              *Pool;
+  UINTN                         Index;
+  UINTN                         PoolListIndex;
   MEMORY_PROFILE_CONTEXT_DATA   *ContextData;
-  BOOLEAN                       SmramProfileRecordingStatus;
+  BOOLEAN                       SmramProfileGettingStatus;
 
   ContextData = GetSmramProfileContext ();
   if (ContextData == NULL) {
     return ;
   }
 
-  SmramProfileRecordingStatus = mSmramProfileRecordingStatus;
-  mSmramProfileRecordingStatus = FALSE;
+  SmramProfileGettingStatus = mSmramProfileGettingStatus;
+  mSmramProfileGettingStatus = TRUE;
 
   DEBUG ((EFI_D_INFO, "======= SmramProfile begin =======\n"));
 
@@ -1934,25 +2600,56 @@ DumpFreePoolList (
 
   DEBUG ((EFI_D_INFO, "======= SmramProfile end =======\n"));
 
-  mSmramProfileRecordingStatus = SmramProfileRecordingStatus;
+  mSmramProfileGettingStatus = SmramProfileGettingStatus;
 }
 
-GLOBAL_REMOVE_IF_UNREFERENCED CHAR16 *mActionString[] = {
-  L"Unknown",
-  L"AllocatePages",
-  L"FreePages",
-  L"AllocatePool",
-  L"FreePool",
+GLOBAL_REMOVE_IF_UNREFERENCED CHAR8 *mSmmActionString[] = {
+  "SmmUnknown",
+  "gSmst->SmmAllocatePages",
+  "gSmst->SmmFreePages",
+  "gSmst->SmmAllocatePool",
+  "gSmst->SmmFreePool",
 };
 
 typedef struct {
+  MEMORY_PROFILE_ACTION  Action;
+  CHAR8                 *String;
+} ACTION_STRING;
+
+ACTION_STRING mExtActionString[] = {
+  {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_PAGES,                    
"Lib:AllocatePages"},
+  {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_PAGES,            
"Lib:AllocateRuntimePages"},
+  {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RESERVED_PAGES,           
"Lib:AllocateReservedPages"},
+  {MEMORY_PROFILE_ACTION_LIB_FREE_PAGES,                        
"Lib:FreePages"},
+  {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_ALIGNED_PAGES,            
"Lib:AllocateAlignedPages"},
+  {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_ALIGNED_RUNTIME_PAGES,    
"Lib:AllocateAlignedRuntimePages"},
+  {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_ALIGNED_RESERVED_PAGES,   
"Lib:AllocateAlignedReservedPages"},
+  {MEMORY_PROFILE_ACTION_LIB_FREE_ALIGNED_PAGES,                
"Lib:FreeAlignedPages"},
+  {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_POOL,                     
"Lib:AllocatePool"},
+  {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_POOL,             
"Lib:AllocateRuntimePool"},
+  {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RESERVED_POOL,            
"Lib:AllocateReservedPool"},
+  {MEMORY_PROFILE_ACTION_LIB_FREE_POOL,                         
"Lib:FreePool"},
+  {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_ZERO_POOL,                
"Lib:AllocateZeroPool"},
+  {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_ZERO_POOL,        
"Lib:AllocateRuntimeZeroPool"},
+  {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RESERVED_ZERO_POOL,       
"Lib:AllocateReservedZeroPool"},
+  {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_COPY_POOL,                
"Lib:AllocateCopyPool"},
+  {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_COPY_POOL,        
"Lib:AllocateRuntimeCopyPool"},
+  {MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RESERVED_COPY_POOL,       
"Lib:AllocateReservedCopyPool"},
+  {MEMORY_PROFILE_ACTION_LIB_REALLOCATE_POOL,                   
"Lib:ReallocatePool"},
+  {MEMORY_PROFILE_ACTION_LIB_REALLOCATE_RUNTIME_POOL,           
"Lib:ReallocateRuntimePool"},
+  {MEMORY_PROFILE_ACTION_LIB_REALLOCATE_RESERVED_POOL,          
"Lib:ReallocateReservedPool"},
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED CHAR8 mUserDefinedActionString[] = 
{"UserDefined-0x80000000"};
+
+typedef struct {
   EFI_MEMORY_TYPE   MemoryType;
-  CHAR16            *MemoryTypeStr;
+  CHAR8             *MemoryTypeStr;
 } PROFILE_MEMORY_TYPE_STRING;
 
 GLOBAL_REMOVE_IF_UNREFERENCED PROFILE_MEMORY_TYPE_STRING mMemoryTypeString[] = 
{
-  {EfiRuntimeServicesCode, L"EfiRuntimeServicesCode"},
-  {EfiRuntimeServicesData, L"EfiRuntimeServicesData"}
+  {EfiRuntimeServicesCode, "EfiRuntimeServicesCode"},
+  {EfiRuntimeServicesData, "EfiRuntimeServicesData"}
 };
 
 /**
@@ -1963,7 +2660,7 @@ GLOBAL_REMOVE_IF_UNREFERENCED PROFILE_MEMORY_TYPE_STRING 
mMemoryTypeString[] = {
   @return Pointer to string.
 
 **/
-CHAR16 *
+CHAR8 *
 ProfileMemoryTypeToStr (
   IN EFI_MEMORY_TYPE    MemoryType
   )
@@ -1975,7 +2672,39 @@ ProfileMemoryTypeToStr (
     }
   }
 
-  return L"UnexpectedMemoryType";
+  return "UnexpectedMemoryType";
+}
+
+/**
+  Action to string.
+
+  @param[in] Action                     Profile action.
+
+  @return Pointer to string.
+
+**/
+CHAR8 *
+ProfileActionToStr (
+  IN MEMORY_PROFILE_ACTION  Action
+  )
+{
+  UINTN     Index;
+  UINTN     ActionStringCount;
+  CHAR8     **ActionString;
+
+  ActionString = mSmmActionString;
+  ActionStringCount = sizeof (mSmmActionString) / sizeof (mSmmActionString[0]);
+
+  if ((UINTN) (UINT32) Action < ActionStringCount) {
+    return ActionString[Action];
+  }
+  for (Index = 0; Index < sizeof (mExtActionString) / sizeof 
(mExtActionString[0]); Index++) {
+    if (mExtActionString[Index].Action == Action) {
+      return mExtActionString[Index].String;
+    }
+  }
+
+  return ActionString[0];
 }
 
 /**
@@ -1999,7 +2728,7 @@ DumpSmramProfile (
   LIST_ENTRY                        *AllocInfoList;
   UINTN                             AllocIndex;
   LIST_ENTRY                        *AllocLink;
-  BOOLEAN                           SmramProfileRecordingStatus;
+  BOOLEAN                           SmramProfileGettingStatus;
   UINTN                             TypeIndex;
 
   ContextData = GetSmramProfileContext ();
@@ -2007,8 +2736,8 @@ DumpSmramProfile (
     return ;
   }
 
-  SmramProfileRecordingStatus = mSmramProfileRecordingStatus;
-  mSmramProfileRecordingStatus = FALSE;
+  SmramProfileGettingStatus = mSmramProfileGettingStatus;
+  mSmramProfileGettingStatus = TRUE;
 
   Context = &ContextData->Context;
   DEBUG ((EFI_D_INFO, "======= SmramProfile begin =======\n"));
@@ -2019,8 +2748,8 @@ DumpSmramProfile (
   for (TypeIndex = 0; TypeIndex < sizeof (Context->CurrentTotalUsageByType) / 
sizeof (Context->CurrentTotalUsageByType[0]); TypeIndex++) {
     if ((Context->CurrentTotalUsageByType[TypeIndex] != 0) ||
         (Context->PeakTotalUsageByType[TypeIndex] != 0)) {
-      DEBUG ((EFI_D_INFO, "  CurrentTotalUsage[0x%02x]  - 0x%016lx (%s)\n", 
TypeIndex, Context->CurrentTotalUsageByType[TypeIndex], ProfileMemoryTypeToStr 
(TypeIndex)));
-      DEBUG ((EFI_D_INFO, "  PeakTotalUsage[0x%02x]     - 0x%016lx (%s)\n", 
TypeIndex, Context->PeakTotalUsageByType[TypeIndex], ProfileMemoryTypeToStr 
(TypeIndex)));
+      DEBUG ((EFI_D_INFO, "  CurrentTotalUsage[0x%02x]  - 0x%016lx (%a)\n", 
TypeIndex, Context->CurrentTotalUsageByType[TypeIndex], ProfileMemoryTypeToStr 
(TypeIndex)));
+      DEBUG ((EFI_D_INFO, "  PeakTotalUsage[0x%02x]     - 0x%016lx (%a)\n", 
TypeIndex, Context->PeakTotalUsageByType[TypeIndex], ProfileMemoryTypeToStr 
(TypeIndex)));
     }
   }
   DEBUG ((EFI_D_INFO, "  TotalImageSize        - 0x%016lx\n", 
Context->TotalImageSize));
@@ -2050,8 +2779,8 @@ DumpSmramProfile (
     for (TypeIndex = 0; TypeIndex < sizeof (DriverInfo->CurrentUsageByType) / 
sizeof (DriverInfo->CurrentUsageByType[0]); TypeIndex++) {
       if ((DriverInfo->CurrentUsageByType[TypeIndex] != 0) ||
           (DriverInfo->PeakUsageByType[TypeIndex] != 0)) {
-        DEBUG ((EFI_D_INFO, "    CurrentUsage[0x%02x]     - 0x%016lx (%s)\n", 
TypeIndex, DriverInfo->CurrentUsageByType[TypeIndex], ProfileMemoryTypeToStr 
(TypeIndex)));
-        DEBUG ((EFI_D_INFO, "    PeakUsage[0x%02x]        - 0x%016lx (%s)\n", 
TypeIndex, DriverInfo->PeakUsageByType[TypeIndex], ProfileMemoryTypeToStr 
(TypeIndex)));
+        DEBUG ((EFI_D_INFO, "    CurrentUsage[0x%02x]     - 0x%016lx (%a)\n", 
TypeIndex, DriverInfo->CurrentUsageByType[TypeIndex], ProfileMemoryTypeToStr 
(TypeIndex)));
+        DEBUG ((EFI_D_INFO, "    PeakUsage[0x%02x]        - 0x%016lx (%a)\n", 
TypeIndex, DriverInfo->PeakUsageByType[TypeIndex], ProfileMemoryTypeToStr 
(TypeIndex)));
       }
     }
     DEBUG ((EFI_D_INFO, "    AllocRecordCount    - 0x%08x\n", 
DriverInfo->AllocRecordCount));
@@ -2070,8 +2799,16 @@ DumpSmramProfile (
       DEBUG ((EFI_D_INFO, "    MEMORY_PROFILE_ALLOC_INFO (0x%x)\n", 
AllocIndex));
       DEBUG ((EFI_D_INFO, "      CallerAddress  - 0x%016lx (Offset: 
0x%08x)\n", AllocInfo->CallerAddress, AllocInfo->CallerAddress - 
DriverInfo->ImageBase));
       DEBUG ((EFI_D_INFO, "      SequenceId     - 0x%08x\n", 
AllocInfo->SequenceId));
-      DEBUG ((EFI_D_INFO, "      Action         - 0x%08x (%s)\n", 
AllocInfo->Action, mActionString[(AllocInfo->Action < 
sizeof(mActionString)/sizeof(mActionString[0])) ? AllocInfo->Action : 0]));
-      DEBUG ((EFI_D_INFO, "      MemoryType     - 0x%08x\n", 
AllocInfo->MemoryType));
+      if ((AllocInfo->Action & MEMORY_PROFILE_ACTION_USER_DEFINED_MASK) != 0) {
+        if (AllocInfoData->ActionString != NULL) {
+          DEBUG ((EFI_D_INFO, "      Action         - 0x%08x (%a)\n", 
AllocInfo->Action, AllocInfoData->ActionString));
+        } else {
+          DEBUG ((EFI_D_INFO, "      Action         - 0x%08x 
(UserDefined-0x%08x)\n", AllocInfo->Action, AllocInfo->Action));
+        }
+      } else {
+        DEBUG ((EFI_D_INFO, "      Action         - 0x%08x (%a)\n", 
AllocInfo->Action, ProfileActionToStr (AllocInfo->Action)));
+      }
+      DEBUG ((EFI_D_INFO, "      MemoryType     - 0x%08x (%a)\n", 
AllocInfo->MemoryType, ProfileMemoryTypeToStr (AllocInfo->MemoryType)));
       DEBUG ((EFI_D_INFO, "      Buffer         - 0x%016lx\n", 
AllocInfo->Buffer));
       DEBUG ((EFI_D_INFO, "      Size           - 0x%016lx\n", 
AllocInfo->Size));
     }
@@ -2079,7 +2816,7 @@ DumpSmramProfile (
 
   DEBUG ((EFI_D_INFO, "======= SmramProfile end =======\n"));
 
-  mSmramProfileRecordingStatus = SmramProfileRecordingStatus;
+  mSmramProfileGettingStatus = SmramProfileGettingStatus;
 }
 
 /**
-- 
2.7.0.windows.1

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel

Reply via email to