]> git.proxmox.com Git - mirror_edk2.git/commitdiff
MdeModulePkg DxeCore/PiSmmCore: Add UEFI memory and SMRAM profile support.
authorStar Zeng <star.zeng@intel.com>
Wed, 12 Nov 2014 03:27:48 +0000 (03:27 +0000)
committerlzeng14 <lzeng14@Edk2>
Wed, 12 Nov 2014 03:27:48 +0000 (03:27 +0000)
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Star Zeng <star.zeng@intel.com>
Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@16335 6f19259b-4bc3-4df7-8a09-765794883524

28 files changed:
MdeModulePkg/Application/MemoryProfileInfo/MemoryProfileInfo.c [new file with mode: 0644]
MdeModulePkg/Application/MemoryProfileInfo/MemoryProfileInfo.inf [new file with mode: 0644]
MdeModulePkg/Application/MemoryProfileInfo/MemoryProfileInfo.uni [new file with mode: 0644]
MdeModulePkg/Application/MemoryProfileInfo/MemoryProfileInfoExtra.uni [new file with mode: 0644]
MdeModulePkg/Core/Dxe/DxeMain.h
MdeModulePkg/Core/Dxe/DxeMain.inf
MdeModulePkg/Core/Dxe/DxeMain/DxeMain.c
MdeModulePkg/Core/Dxe/Image/Image.c
MdeModulePkg/Core/Dxe/Image/Image.h
MdeModulePkg/Core/Dxe/Mem/MemoryProfileRecord.c [new file with mode: 0644]
MdeModulePkg/Core/Dxe/Mem/Page.c
MdeModulePkg/Core/Dxe/Mem/Pool.c
MdeModulePkg/Core/PiSmmCore/Dispatcher.c
MdeModulePkg/Core/PiSmmCore/Page.c
MdeModulePkg/Core/PiSmmCore/PiSmmCore.c
MdeModulePkg/Core/PiSmmCore/PiSmmCore.h
MdeModulePkg/Core/PiSmmCore/PiSmmCore.inf
MdeModulePkg/Core/PiSmmCore/PiSmmCorePrivateData.h
MdeModulePkg/Core/PiSmmCore/PiSmmIpl.c
MdeModulePkg/Core/PiSmmCore/Pool.c
MdeModulePkg/Core/PiSmmCore/SmramProfileRecord.c [new file with mode: 0644]
MdeModulePkg/Include/Guid/MemoryProfile.h [new file with mode: 0644]
MdeModulePkg/MdeModulePkg.dec
MdeModulePkg/MdeModulePkg.dsc
MdeModulePkg/MdeModulePkg.uni
MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/BootScriptExecutorDxe.inf
MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/ScriptExecute.c
MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/ScriptExecute.h

diff --git a/MdeModulePkg/Application/MemoryProfileInfo/MemoryProfileInfo.c b/MdeModulePkg/Application/MemoryProfileInfo/MemoryProfileInfo.c
new file mode 100644 (file)
index 0000000..4896ebd
--- /dev/null
@@ -0,0 +1,712 @@
+/** @file\r
+  \r
+  Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>\r
+  This program and the accompanying materials                          \r
+  are licensed and made available under the terms and conditions of the BSD License         \r
+  which accompanies this distribution.  The full text of the license may be found at        \r
+  http://opensource.org/licenses/bsd-license.php                                            \r
+\r
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
+\r
+**/\r
+\r
+#include <Uefi.h>\r
+#include <PiDxe.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/UefiLib.h>\r
+#include <Library/UefiApplicationEntryPoint.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/UefiRuntimeServicesTableLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/DxeServicesLib.h>\r
+#include <Library/PeCoffGetEntryPointLib.h>\r
+#include <Library/PrintLib.h>\r
+\r
+#include <Protocol/SmmCommunication.h>\r
+#include <Protocol/SmmAccess2.h>\r
+\r
+#include <Guid/ZeroGuid.h>\r
+#include <Guid/MemoryProfile.h>\r
+\r
+CHAR16 *mActionString[] = {\r
+  L"Unknown",\r
+  L"AllocatePages",\r
+  L"FreePages",\r
+  L"AllocatePool",\r
+  L"FreePool",\r
+};\r
+\r
+CHAR16 *mMemoryTypeString[] = {\r
+  L"EfiReservedMemoryType",\r
+  L"EfiLoaderCode",\r
+  L"EfiLoaderData",\r
+  L"EfiBootServicesCode",\r
+  L"EfiBootServicesData",\r
+  L"EfiRuntimeServicesCode",\r
+  L"EfiRuntimeServicesData",\r
+  L"EfiConventionalMemory",\r
+  L"EfiUnusableMemory",\r
+  L"EfiACPIReclaimMemory",\r
+  L"EfiACPIMemoryNVS",\r
+  L"EfiMemoryMappedIO",\r
+  L"EfiMemoryMappedIOPortSpace",\r
+  L"EfiPalCode",\r
+  L"EfiOSReserved",\r
+};\r
+\r
+CHAR16 *mSubsystemString[] = {\r
+  L"Unknown",\r
+  L"NATIVE",\r
+  L"WINDOWS_GUI",\r
+  L"WINDOWS_CUI",\r
+  L"Unknown",\r
+  L"Unknown",\r
+  L"Unknown",\r
+  L"POSIX_CUI",\r
+  L"Unknown",\r
+  L"WINDOWS_CE_GUI",\r
+  L"EFI_APPLICATION",\r
+  L"EFI_BOOT_SERVICE_DRIVER",\r
+  L"EFI_RUNTIME_DRIVER",\r
+  L"EFI_ROM",\r
+  L"XBOX",\r
+  L"Unknown",\r
+};\r
+\r
+CHAR16 *mFileTypeString[] = {\r
+  L"Unknown",\r
+  L"RAW",\r
+  L"FREEFORM",\r
+  L"SECURITY_CORE",\r
+  L"PEI_CORE",\r
+  L"DXE_CORE",\r
+  L"PEIM",\r
+  L"DRIVER",\r
+  L"COMBINED_PEIM_DRIVER",\r
+  L"APPLICATION",\r
+  L"SMM",\r
+  L"FIRMWARE_VOLUME_IMAGE",\r
+  L"COMBINED_SMM_DXE",\r
+  L"SMM_CORE",\r
+};\r
+\r
+#define PROFILE_NAME_STRING_LENGTH  36\r
+CHAR16 mNameString[PROFILE_NAME_STRING_LENGTH + 1];\r
+\r
+/** \r
+  Get the file name portion of the Pdb File Name.\r
+  \r
+  The portion of the Pdb File Name between the last backslash and\r
+  either a following period or the end of the string is converted\r
+  to Unicode and copied into UnicodeBuffer.  The name is truncated,\r
+  if necessary, to ensure that UnicodeBuffer is not overrun.\r
+  \r
+  @param[in]  PdbFileName     Pdb file name.\r
+  @param[out] UnicodeBuffer   The resultant Unicode File Name.\r
+  \r
+**/\r
+VOID\r
+GetShortPdbFileName (\r
+  IN  CHAR8     *PdbFileName,\r
+  OUT CHAR16    *UnicodeBuffer\r
+  )\r
+{\r
+  UINTN IndexA;     // Current work location within an ASCII string.\r
+  UINTN IndexU;     // Current work location within a Unicode string.\r
+  UINTN StartIndex;\r
+  UINTN EndIndex;\r
+\r
+  ZeroMem (UnicodeBuffer, PROFILE_NAME_STRING_LENGTH * sizeof (CHAR16));\r
+\r
+  if (PdbFileName == NULL) {\r
+    StrnCpy (UnicodeBuffer, L" ", 1);\r
+  } else {\r
+    StartIndex = 0;\r
+    for (EndIndex = 0; PdbFileName[EndIndex] != 0; EndIndex++);\r
+    for (IndexA = 0; PdbFileName[IndexA] != 0; IndexA++) {\r
+      if (PdbFileName[IndexA] == '\\') {\r
+        StartIndex = IndexA + 1;\r
+      }\r
+\r
+      if (PdbFileName[IndexA] == '.') {\r
+        EndIndex = IndexA;\r
+      }\r
+    }\r
+\r
+    IndexU = 0;\r
+    for (IndexA = StartIndex; IndexA < EndIndex; IndexA++) {\r
+      UnicodeBuffer[IndexU] = (CHAR16) PdbFileName[IndexA];\r
+      IndexU++;\r
+      if (IndexU >= PROFILE_NAME_STRING_LENGTH) {\r
+        UnicodeBuffer[PROFILE_NAME_STRING_LENGTH] = 0;\r
+        break;\r
+      }\r
+    }\r
+  }\r
+}\r
+\r
+/** \r
+  Get a human readable name for an image.\r
+  The following methods will be tried orderly:\r
+    1. Image PDB\r
+    2. FFS UI section\r
+    3. Image GUID\r
+\r
+  @param[in] DriverInfo Pointer to memory profile driver info.\r
+\r
+  @post The resulting Unicode name string is stored in the mNameString global array.\r
+\r
+**/\r
+VOID\r
+GetDriverNameString (\r
+ IN MEMORY_PROFILE_DRIVER_INFO  *DriverInfo\r
+ )\r
+{\r
+  EFI_STATUS                  Status;\r
+  CHAR8                       *PdbFileName;\r
+  CHAR16                      *NameString;\r
+  UINTN                       StringSize;\r
+\r
+  //\r
+  // Method 1: Get the name string from image PDB\r
+  //\r
+  if ((DriverInfo->ImageBase != 0) && (DriverInfo->FileType != EFI_FV_FILETYPE_SMM) && (DriverInfo->FileType != EFI_FV_FILETYPE_SMM_CORE)) {\r
+    PdbFileName = PeCoffLoaderGetPdbPointer ((VOID *) (UINTN) DriverInfo->ImageBase);\r
+\r
+    if (PdbFileName != NULL) {\r
+      GetShortPdbFileName (PdbFileName, mNameString);\r
+      return;\r
+    }\r
+  }\r
+\r
+  if (!CompareGuid (&DriverInfo->FileName, &gZeroGuid)) {\r
+    //\r
+    // Try to get the image's FFS UI section by image GUID\r
+    //\r
+    NameString = NULL;\r
+    StringSize = 0;\r
+    Status = GetSectionFromAnyFv (\r
+              &DriverInfo->FileName,\r
+              EFI_SECTION_USER_INTERFACE,\r
+              0,\r
+              (VOID **) &NameString,\r
+              &StringSize\r
+              );\r
+    if (!EFI_ERROR (Status)) {\r
+      //\r
+      // Method 2: Get the name string from FFS UI section\r
+      //\r
+      StrnCpy (mNameString, NameString, PROFILE_NAME_STRING_LENGTH);\r
+      mNameString[PROFILE_NAME_STRING_LENGTH] = 0;\r
+      FreePool (NameString);\r
+      return;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Method 3: Get the name string from image GUID\r
+  //\r
+  UnicodeSPrint (mNameString, sizeof (mNameString), L"%g", &DriverInfo->FileName);\r
+}\r
+\r
+/**\r
+  Dump memory profile allocate information.\r
+\r
+  @param[in] DriverInfo         Pointer to memory profile driver info.\r
+  @param[in] AllocIndex         Memory profile alloc info index.\r
+  @param[in] AllocInfo          Pointer to memory profile alloc info.\r
+\r
+  @return Pointer to next memory profile alloc info.\r
+\r
+**/\r
+MEMORY_PROFILE_ALLOC_INFO *\r
+DumpMemoryProfileAllocInfo (\r
+  IN MEMORY_PROFILE_DRIVER_INFO *DriverInfo,\r
+  IN UINTN                      AllocIndex,\r
+  IN MEMORY_PROFILE_ALLOC_INFO  *AllocInfo\r
+  )\r
+{\r
+  if (AllocInfo->Header.Signature != MEMORY_PROFILE_ALLOC_INFO_SIGNATURE) {\r
+    return NULL;\r
+  }\r
+  Print (L"    MEMORY_PROFILE_ALLOC_INFO (0x%x)\n", AllocIndex);\r
+  Print (L"      Signature     - 0x%08x\n", AllocInfo->Header.Signature);\r
+  Print (L"      Length        - 0x%04x\n", AllocInfo->Header.Length);\r
+  Print (L"      Revision      - 0x%04x\n", AllocInfo->Header.Revision);  \r
+  Print (L"      CallerAddress - 0x%016lx (Offset: 0x%08x)\n", AllocInfo->CallerAddress, (UINTN) (AllocInfo->CallerAddress - DriverInfo->ImageBase));\r
+  Print (L"      SequenceId    - 0x%08x\n", AllocInfo->SequenceId);\r
+  Print (L"      Action        - 0x%08x (%s)\n", AllocInfo->Action, mActionString[(AllocInfo->Action < sizeof(mActionString)/sizeof(mActionString[0])) ? AllocInfo->Action : 0]);\r
+  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)]);\r
+  Print (L"      Buffer        - 0x%016lx\n", AllocInfo->Buffer);\r
+  Print (L"      Size          - 0x%016lx\n", AllocInfo->Size);\r
+\r
+  return (MEMORY_PROFILE_ALLOC_INFO *) ((UINTN) AllocInfo + AllocInfo->Header.Length);\r
+}\r
+\r
+/**\r
+  Dump memory profile driver information.\r
+\r
+  @param[in] DriverIndex        Memory profile driver info index.\r
+  @param[in] DriverInfo         Pointer to memory profile driver info.\r
+\r
+  @return Pointer to next memory profile driver info.\r
+\r
+**/\r
+MEMORY_PROFILE_DRIVER_INFO *\r
+DumpMemoryProfileDriverInfo (\r
+  IN UINTN                      DriverIndex,\r
+  IN MEMORY_PROFILE_DRIVER_INFO *DriverInfo\r
+  )\r
+{\r
+  UINTN                         TypeIndex;\r
+  MEMORY_PROFILE_ALLOC_INFO     *AllocInfo;\r
+  UINTN                         AllocIndex;\r
+\r
+  if (DriverInfo->Header.Signature != MEMORY_PROFILE_DRIVER_INFO_SIGNATURE) {\r
+    return NULL;\r
+  }\r
+  Print (L"  MEMORY_PROFILE_DRIVER_INFO (0x%x)\n", DriverIndex);\r
+  Print (L"    Signature               - 0x%08x\n", DriverInfo->Header.Signature);\r
+  Print (L"    Length                  - 0x%04x\n", DriverInfo->Header.Length);\r
+  Print (L"    Revision                - 0x%04x\n", DriverInfo->Header.Revision);  \r
+  GetDriverNameString (DriverInfo);\r
+  Print (L"    FileName                - %s\n", &mNameString);\r
+  Print (L"    ImageBase               - 0x%016lx\n", DriverInfo->ImageBase);\r
+  Print (L"    ImageSize               - 0x%016lx\n", DriverInfo->ImageSize);\r
+  Print (L"    EntryPoint              - 0x%016lx\n", DriverInfo->EntryPoint);\r
+  Print (L"    ImageSubsystem          - 0x%04x (%s)\n", DriverInfo->ImageSubsystem, mSubsystemString[(DriverInfo->ImageSubsystem < sizeof(mSubsystemString)/sizeof(mSubsystemString[0])) ? DriverInfo->ImageSubsystem : 0]);\r
+  Print (L"    FileType                - 0x%02x (%s)\n", DriverInfo->FileType, mFileTypeString[(DriverInfo->FileType < sizeof(mFileTypeString)/sizeof(mFileTypeString[0])) ? DriverInfo->FileType : 0]);\r
+  Print (L"    CurrentUsage            - 0x%016lx\n", DriverInfo->CurrentUsage);\r
+  Print (L"    PeakUsage               - 0x%016lx\n", DriverInfo->PeakUsage);\r
+  for (TypeIndex = 0; TypeIndex <= EfiMaxMemoryType; TypeIndex++) {\r
+    if ((DriverInfo->CurrentUsageByType[TypeIndex] != 0) ||\r
+        (DriverInfo->PeakUsageByType[TypeIndex] != 0)) {\r
+      Print (L"    CurrentUsage[0x%02x]      - 0x%016lx (%s)\n", TypeIndex, DriverInfo->CurrentUsageByType[TypeIndex], mMemoryTypeString[TypeIndex]);\r
+      Print (L"    PeakUsage[0x%02x]         - 0x%016lx (%s)\n", TypeIndex, DriverInfo->PeakUsageByType[TypeIndex], mMemoryTypeString[TypeIndex]);\r
+    }\r
+  }\r
+  Print (L"    AllocRecordCount        - 0x%08x\n", DriverInfo->AllocRecordCount);\r
+\r
+  AllocInfo = (MEMORY_PROFILE_ALLOC_INFO *) ((UINTN) DriverInfo + DriverInfo->Header.Length);\r
+  for (AllocIndex = 0; AllocIndex < DriverInfo->AllocRecordCount; AllocIndex++) {\r
+    AllocInfo = DumpMemoryProfileAllocInfo (DriverInfo, AllocIndex, AllocInfo);\r
+    if (AllocInfo == NULL) {\r
+      return NULL;\r
+    }\r
+  }\r
+  return (MEMORY_PROFILE_DRIVER_INFO *) AllocInfo;\r
+}\r
+\r
+/**\r
+  Dump memory profile context information.\r
+\r
+  @param[in] Context            Pointer to memory profile context.\r
+\r
+  @return Pointer to the end of memory profile context buffer.\r
+\r
+**/\r
+VOID *\r
+DumpMemoryProfileContext (\r
+  IN MEMORY_PROFILE_CONTEXT     *Context\r
+  )\r
+{\r
+  UINTN                         TypeIndex;\r
+  MEMORY_PROFILE_DRIVER_INFO    *DriverInfo;\r
+  UINTN                         DriverIndex;\r
+\r
+  if (Context->Header.Signature != MEMORY_PROFILE_CONTEXT_SIGNATURE) {\r
+    return NULL;\r
+  }\r
+  Print (L"MEMORY_PROFILE_CONTEXT\n");\r
+  Print (L"  Signature                     - 0x%08x\n", Context->Header.Signature);\r
+  Print (L"  Length                        - 0x%04x\n", Context->Header.Length);\r
+  Print (L"  Revision                      - 0x%04x\n", Context->Header.Revision);  \r
+  Print (L"  CurrentTotalUsage             - 0x%016lx\n", Context->CurrentTotalUsage);\r
+  Print (L"  PeakTotalUsage                - 0x%016lx\n", Context->PeakTotalUsage);\r
+  for (TypeIndex = 0; TypeIndex <= EfiMaxMemoryType; TypeIndex++) {\r
+    if ((Context->CurrentTotalUsageByType[TypeIndex] != 0) ||\r
+        (Context->PeakTotalUsageByType[TypeIndex] != 0)) {\r
+      Print (L"  CurrentTotalUsage[0x%02x]       - 0x%016lx (%s)\n", TypeIndex, Context->CurrentTotalUsageByType[TypeIndex], mMemoryTypeString[TypeIndex]);\r
+      Print (L"  PeakTotalUsage[0x%02x]          - 0x%016lx (%s)\n", TypeIndex, Context->PeakTotalUsageByType[TypeIndex], mMemoryTypeString[TypeIndex]);\r
+    }\r
+  }\r
+  Print (L"  TotalImageSize                - 0x%016lx\n", Context->TotalImageSize);\r
+  Print (L"  ImageCount                    - 0x%08x\n", Context->ImageCount);\r
+  Print (L"  SequenceCount                 - 0x%08x\n", Context->SequenceCount);\r
+\r
+  DriverInfo = (MEMORY_PROFILE_DRIVER_INFO *) ((UINTN) Context + Context->Header.Length);\r
+  for (DriverIndex = 0; DriverIndex < Context->ImageCount; DriverIndex++) {\r
+    DriverInfo = DumpMemoryProfileDriverInfo (DriverIndex, DriverInfo);\r
+    if (DriverInfo == NULL) {\r
+      return NULL;\r
+    }\r
+  }\r
+  return (VOID *) DriverInfo;\r
+}\r
+\r
+/**\r
+  Dump memory profile descriptor information.\r
+\r
+  @param[in] DescriptorIndex    Memory profile descriptor index.\r
+  @param[in] Descriptor         Pointer to memory profile descriptor.\r
+\r
+  @return Pointer to next memory profile descriptor.\r
+\r
+**/\r
+MEMORY_PROFILE_DESCRIPTOR *\r
+DumpMemoryProfileDescriptor (\r
+  IN UINTN                      DescriptorIndex,\r
+  IN MEMORY_PROFILE_DESCRIPTOR  *Descriptor\r
+  )\r
+{\r
+  if (Descriptor->Header.Signature != MEMORY_PROFILE_DESCRIPTOR_SIGNATURE) {\r
+    return NULL;\r
+  }\r
+  Print (L"  MEMORY_PROFILE_DESCRIPTOR (0x%x)\n", DescriptorIndex);\r
+  Print (L"    Signature               - 0x%08x\n", Descriptor->Header.Signature);\r
+  Print (L"    Length                  - 0x%04x\n", Descriptor->Header.Length);\r
+  Print (L"    Revision                - 0x%04x\n", Descriptor->Header.Revision);  \r
+  Print (L"    Address                 - 0x%016lx\n", Descriptor->Address);\r
+  Print (L"    Size                    - 0x%016lx\n", Descriptor->Size);\r
+\r
+  return (MEMORY_PROFILE_DESCRIPTOR *) ((UINTN) Descriptor + Descriptor->Header.Length);\r
+}\r
+\r
+/**\r
+  Dump memory profile free memory information.\r
+\r
+  @param[in] FreeMemory         Pointer to memory profile free memory.\r
+\r
+  @return Pointer to the end of memory profile free memory buffer.\r
+\r
+**/\r
+VOID *\r
+DumpMemoryProfileFreeMemory (\r
+  IN MEMORY_PROFILE_FREE_MEMORY *FreeMemory\r
+  )\r
+{\r
+  MEMORY_PROFILE_DESCRIPTOR     *Descriptor;\r
+  UINTN                         DescriptorIndex;\r
+\r
+  if (FreeMemory->Header.Signature != MEMORY_PROFILE_FREE_MEMORY_SIGNATURE) {\r
+    return NULL;\r
+  }\r
+  Print (L"MEMORY_PROFILE_FREE_MEMORY\n");\r
+  Print (L"  Signature                     - 0x%08x\n", FreeMemory->Header.Signature);\r
+  Print (L"  Length                        - 0x%04x\n", FreeMemory->Header.Length);\r
+  Print (L"  Revision                      - 0x%04x\n", FreeMemory->Header.Revision);  \r
+  Print (L"  TotalFreeMemoryPages          - 0x%016lx\n", FreeMemory->TotalFreeMemoryPages);\r
+  Print (L"  FreeMemoryEntryCount          - 0x%08x\n", FreeMemory->FreeMemoryEntryCount);\r
+\r
+  Descriptor = (MEMORY_PROFILE_DESCRIPTOR *) ((UINTN) FreeMemory + FreeMemory->Header.Length);\r
+  for (DescriptorIndex = 0; DescriptorIndex < FreeMemory->FreeMemoryEntryCount; DescriptorIndex++) {\r
+    Descriptor = DumpMemoryProfileDescriptor (DescriptorIndex, Descriptor);\r
+    if (Descriptor == NULL) {\r
+      return NULL;\r
+    }\r
+  }\r
+\r
+  return (VOID *) Descriptor;\r
+}\r
+\r
+/**\r
+  Dump memory profile memory range information.\r
+\r
+  @param[in] MemoryRange        Pointer to memory profile memory range.\r
+\r
+  @return Pointer to the end of memory profile memory range buffer.\r
+\r
+**/\r
+VOID *\r
+DumpMemoryProfileMemoryRange (\r
+  IN MEMORY_PROFILE_MEMORY_RANGE    *MemoryRange\r
+  )\r
+{\r
+  MEMORY_PROFILE_DESCRIPTOR     *Descriptor;\r
+  UINTN                         DescriptorIndex;\r
+\r
+  if (MemoryRange->Header.Signature != MEMORY_PROFILE_MEMORY_RANGE_SIGNATURE) {\r
+    return NULL;\r
+  }\r
+  Print (L"MEMORY_PROFILE_MEMORY_RANGE\n");\r
+  Print (L"  Signature                     - 0x%08x\n", MemoryRange->Header.Signature);\r
+  Print (L"  Length                        - 0x%04x\n", MemoryRange->Header.Length);\r
+  Print (L"  Revision                      - 0x%04x\n", MemoryRange->Header.Revision);  \r
+  Print (L"  MemoryRangeCount              - 0x%08x\n", MemoryRange->MemoryRangeCount);\r
+\r
+  Descriptor = (MEMORY_PROFILE_DESCRIPTOR *) ((UINTN) MemoryRange + MemoryRange->Header.Length);\r
+  for (DescriptorIndex = 0; DescriptorIndex < MemoryRange->MemoryRangeCount; DescriptorIndex++) {\r
+    Descriptor = DumpMemoryProfileDescriptor (DescriptorIndex, Descriptor);\r
+    if (Descriptor == NULL) {\r
+      return NULL;\r
+    }\r
+  }\r
+\r
+  return (VOID *) Descriptor;\r
+}\r
+\r
+/**\r
+  Scan memory profile by Signature.\r
+\r
+  @param[in] ProfileBuffer      Memory profile base address.\r
+  @param[in] ProfileSize        Memory profile size.\r
+  @param[in] Signature          Signature.\r
+\r
+  @return Pointer to the stucture with the signature.\r
+\r
+**/\r
+VOID *\r
+ScanMemoryProfileBySignature (\r
+  IN PHYSICAL_ADDRESS           ProfileBuffer,\r
+  IN UINT64                     ProfileSize,\r
+  IN UINT32                     Signature\r
+  )\r
+{\r
+  MEMORY_PROFILE_COMMON_HEADER  *CommonHeader;\r
+  UINTN                          ProfileEnd;\r
+\r
+  ProfileEnd = (UINTN) (ProfileBuffer + ProfileSize);\r
+  CommonHeader = (MEMORY_PROFILE_COMMON_HEADER *) (UINTN) ProfileBuffer;\r
+  while ((UINTN) CommonHeader < ProfileEnd) {\r
+    if (CommonHeader->Signature == Signature) {\r
+      //\r
+      // Found it.\r
+      //\r
+      return (VOID *) CommonHeader;\r
+    }\r
+    CommonHeader = (MEMORY_PROFILE_COMMON_HEADER *) ((UINTN) CommonHeader + CommonHeader->Length);\r
+  }\r
+\r
+  return NULL;\r
+}\r
+\r
+/**\r
+  Dump memory profile information.\r
+\r
+  @param[in] ProfileBuffer      Memory profile base address.\r
+  @param[in] ProfileSize        Memory profile size.\r
+\r
+**/\r
+VOID\r
+DumpMemoryProfile (\r
+  IN PHYSICAL_ADDRESS           ProfileBuffer,\r
+  IN UINT64                     ProfileSize\r
+  )\r
+{\r
+  MEMORY_PROFILE_CONTEXT        *Context;\r
+  MEMORY_PROFILE_FREE_MEMORY    *FreeMemory;\r
+  MEMORY_PROFILE_MEMORY_RANGE   *MemoryRange;\r
+\r
+  Context = (MEMORY_PROFILE_CONTEXT *) ScanMemoryProfileBySignature (ProfileBuffer, ProfileSize, MEMORY_PROFILE_CONTEXT_SIGNATURE);\r
+  if (Context != NULL) {\r
+    DumpMemoryProfileContext (Context);\r
+  }\r
+\r
+  FreeMemory = (MEMORY_PROFILE_FREE_MEMORY *) ScanMemoryProfileBySignature (ProfileBuffer, ProfileSize, MEMORY_PROFILE_FREE_MEMORY_SIGNATURE);\r
+  if (FreeMemory != NULL) {\r
+    DumpMemoryProfileFreeMemory (FreeMemory);\r
+  }\r
+\r
+  MemoryRange = (MEMORY_PROFILE_MEMORY_RANGE *) ScanMemoryProfileBySignature (ProfileBuffer, ProfileSize, MEMORY_PROFILE_MEMORY_RANGE_SIGNATURE);\r
+  if (MemoryRange != NULL) {\r
+    DumpMemoryProfileMemoryRange (MemoryRange);\r
+  }\r
+}\r
+\r
+/**\r
+  Get and dump UEFI memory profile data.\r
+\r
+  @return EFI_SUCCESS   Get the memory profile data successfully.\r
+  @return other         Fail to get the memory profile data.\r
+\r
+**/\r
+EFI_STATUS\r
+GetUefiMemoryProfileData (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS                    Status;\r
+  EDKII_MEMORY_PROFILE_PROTOCOL *ProfileProtocol;\r
+  VOID                          *Data;\r
+  UINT64                        Size;\r
+\r
+  Status = gBS->LocateProtocol (&gEdkiiMemoryProfileGuid, NULL, (VOID **) &ProfileProtocol);\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((EFI_D_ERROR, "UefiMemoryProfile: Locate MemoryProfile protocol - %r\n", Status));\r
+    return Status;\r
+  }\r
+\r
+  Size = 0;\r
+  Data = NULL;\r
+  Status = ProfileProtocol->GetData (\r
+                              ProfileProtocol,\r
+                              &Size,\r
+                              Data\r
+                              );\r
+  if (Status != EFI_BUFFER_TOO_SMALL) {\r
+    Print (L"UefiMemoryProfile: GetData - %r\n", Status);\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Add one sizeof (MEMORY_PROFILE_ALLOC_INFO) to Size for this AllocatePool action.\r
+  //\r
+  Size = Size + sizeof (MEMORY_PROFILE_ALLOC_INFO);\r
+  Data = AllocateZeroPool ((UINTN) Size);\r
+  if (Data == NULL) {\r
+    Print (L"UefiMemoryProfile: AllocateZeroPool (0x%x) - %r\n", Size, Status);\r
+    return Status;\r
+  }\r
+\r
+  Status = ProfileProtocol->GetData (\r
+                              ProfileProtocol,\r
+                              &Size,\r
+                              Data\r
+                              );\r
+  if (EFI_ERROR (Status)) {\r
+    FreePool (Data);\r
+    Print (L"UefiMemoryProfile: GetData - %r\n", Status);\r
+    return Status;\r
+  }\r
+\r
+\r
+  Print (L"UefiMemoryProfileSize - 0x%x\n", Size);\r
+  Print (L"======= UefiMemoryProfile begin =======\n");\r
+  DumpMemoryProfile ((PHYSICAL_ADDRESS) (UINTN) Data, Size);\r
+  Print (L"======= UefiMemoryProfile end =======\n\n\n");\r
+\r
+  FreePool (Data);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Get and dump SMRAM profile data.\r
+\r
+  @return EFI_SUCCESS   Get the SMRAM profile data successfully.\r
+  @return other         Fail to get the SMRAM profile data.\r
+\r
+**/\r
+EFI_STATUS\r
+GetSmramProfileData (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS                                    Status;\r
+  UINTN                                         CommSize;\r
+  UINT8                                         CommBuffer[sizeof (EFI_GUID) + sizeof (UINTN) + sizeof (SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA)];\r
+  EFI_SMM_COMMUNICATE_HEADER                    *CommHeader;\r
+  SMRAM_PROFILE_PARAMETER_GET_PROFILE_INFO      *CommGetProfileInfo;\r
+  SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA      *CommGetProfileData;\r
+  UINT64                                        ProfileSize;\r
+  PHYSICAL_ADDRESS                              ProfileBuffer;\r
+  EFI_SMM_COMMUNICATION_PROTOCOL                *SmmCommunication;\r
+\r
+  Status = gBS->LocateProtocol (&gEfiSmmCommunicationProtocolGuid, NULL, (VOID **) &SmmCommunication);\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((EFI_D_ERROR, "SmramProfile: Locate SmmCommunication protocol - %r\n", Status));\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Get Size\r
+  //\r
+  CommHeader = (EFI_SMM_COMMUNICATE_HEADER *) &CommBuffer[0];\r
+  CopyMem (&CommHeader->HeaderGuid, &gEdkiiMemoryProfileGuid, sizeof (gEdkiiMemoryProfileGuid));\r
+  CommHeader->MessageLength = sizeof (SMRAM_PROFILE_PARAMETER_GET_PROFILE_INFO);\r
+\r
+  CommGetProfileInfo = (SMRAM_PROFILE_PARAMETER_GET_PROFILE_INFO *) &CommBuffer[OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data)];\r
+  CommGetProfileInfo->Header.Command      = SMRAM_PROFILE_COMMAND_GET_PROFILE_INFO;\r
+  CommGetProfileInfo->Header.DataLength   = sizeof (*CommGetProfileInfo);\r
+  CommGetProfileInfo->Header.ReturnStatus = (UINT64)-1;\r
+  CommGetProfileInfo->ProfileSize         = 0;\r
+\r
+  CommSize = sizeof (EFI_GUID) + sizeof (UINTN) + CommHeader->MessageLength;\r
+  Status = SmmCommunication->Communicate (SmmCommunication, CommBuffer, &CommSize);\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((EFI_D_ERROR, "SmramProfile: SmmCommunication - %r\n", Status));\r
+    return Status;\r
+  }\r
+\r
+  if (CommGetProfileInfo->Header.ReturnStatus != 0) {\r
+    Print (L"SmramProfile: GetProfileInfo - 0x%0x\n", CommGetProfileInfo->Header.ReturnStatus);\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  ProfileSize = CommGetProfileInfo->ProfileSize;\r
+\r
+  //\r
+  // Get Data\r
+  //\r
+  ProfileBuffer = (PHYSICAL_ADDRESS) (UINTN) AllocateZeroPool ((UINTN) ProfileSize);\r
+  if (ProfileBuffer == 0) {\r
+    Print (L"UefiMemoryProfile: AllocateZeroPool (0x%x) - %r\n", (UINTN) ProfileSize, Status);\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  CommHeader = (EFI_SMM_COMMUNICATE_HEADER *) &CommBuffer[0];\r
+  CopyMem (&CommHeader->HeaderGuid, &gEdkiiMemoryProfileGuid, sizeof(gEdkiiMemoryProfileGuid));\r
+  CommHeader->MessageLength = sizeof (SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA);\r
+\r
+  CommGetProfileData = (SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA *)&CommBuffer[OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data)];\r
+  CommGetProfileData->Header.Command      = SMRAM_PROFILE_COMMAND_GET_PROFILE_DATA;\r
+  CommGetProfileData->Header.DataLength   = sizeof (*CommGetProfileData);\r
+  CommGetProfileData->Header.ReturnStatus = (UINT64)-1;\r
+  CommGetProfileData->ProfileSize         = ProfileSize;\r
+  CommGetProfileData->ProfileBuffer       = ProfileBuffer;\r
+\r
+  CommSize = sizeof (EFI_GUID) + sizeof (UINTN) + CommHeader->MessageLength;\r
+  Status = SmmCommunication->Communicate (SmmCommunication, CommBuffer, &CommSize);\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  if (CommGetProfileData->Header.ReturnStatus != 0) {\r
+    Print (L"GetProfileData - 0x%x\n", CommGetProfileData->Header.ReturnStatus);\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+\r
+  Print (L"SmramProfileSize - 0x%x\n", CommGetProfileData->ProfileSize);\r
+  Print (L"======= SmramProfile begin =======\n");\r
+  DumpMemoryProfile (CommGetProfileData->ProfileBuffer, CommGetProfileData->ProfileSize);\r
+  Print (L"======= SmramProfile end =======\n\n\n");\r
+\r
+  FreePool ((VOID *) (UINTN) CommGetProfileData->ProfileBuffer);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  The user Entry Point for Application. The user code starts with this function\r
+  as the real entry point for the image goes into a library that calls this function.\r
+\r
+  @param[in] ImageHandle    The firmware allocated handle for the EFI image.  \r
+  @param[in] SystemTable    A pointer to the EFI System Table.\r
+  \r
+  @retval EFI_SUCCESS       The entry point is executed successfully.\r
+  @retval other             Some error occurs when executing this entry point.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+UefiMain (\r
+  IN EFI_HANDLE         ImageHandle,\r
+  IN EFI_SYSTEM_TABLE   *SystemTable\r
+  )\r
+{\r
+  EFI_STATUS                    Status;\r
+\r
+  Status = GetUefiMemoryProfileData ();\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((EFI_D_ERROR, "GetUefiMemoryProfileData - %r\n", Status));\r
+  }\r
+\r
+  Status = GetSmramProfileData ();\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((EFI_D_ERROR, "GetSmramProfileData - %r\n", Status));\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
diff --git a/MdeModulePkg/Application/MemoryProfileInfo/MemoryProfileInfo.inf b/MdeModulePkg/Application/MemoryProfileInfo/MemoryProfileInfo.inf
new file mode 100644 (file)
index 0000000..6fd1f7b
--- /dev/null
@@ -0,0 +1,62 @@
+## @file\r
+#  Shell application to dump UEFI memory and SMRAM profile information.\r
+#\r
+#  Note that if the feature is not enabled by setting PcdMemoryProfilePropertyMask,\r
+#  the application will not display memory profile information.\r
+#\r
+#  Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>\r
+#  This program and the accompanying materials\r
+#  are licensed and made available under the terms and conditions of the BSD License\r
+#  which accompanies this distribution. The full text of the license may be found at\r
+#  http://opensource.org/licenses/bsd-license.php\r
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+##\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = MemoryProfileInfo\r
+  MODULE_UNI_FILE                = MemoryProfileInfo.uni\r
+  FILE_GUID                      = 21429B90-5F67-4e93-AF55-1D314D646E12\r
+  MODULE_TYPE                    = UEFI_APPLICATION\r
+  VERSION_STRING                 = 1.0\r
+  ENTRY_POINT                    = UefiMain\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+#  VALID_ARCHITECTURES           = IA32 X64 IPF EBC\r
+#\r
+\r
+[Sources]\r
+  MemoryProfileInfo.c\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  MdeModulePkg/MdeModulePkg.dec\r
+\r
+[LibraryClasses]\r
+  UefiApplicationEntryPoint\r
+  BaseLib\r
+  BaseMemoryLib\r
+  UefiBootServicesTableLib\r
+  UefiRuntimeServicesTableLib\r
+  DebugLib\r
+  UefiLib\r
+  MemoryAllocationLib\r
+  DxeServicesLib\r
+  PeCoffGetEntryPointLib\r
+  PrintLib\r
+  \r
+[Guids]\r
+  ## SOMETIMES_CONSUMES   ## GUID # Locate protocol\r
+  ## SOMETIMES_CONSUMES   ## GUID # SmiHandlerRegister\r
+  gEdkiiMemoryProfileGuid\r
+  gZeroGuid                            ## SOMETIMES_CONSUMES   ## GUID\r
+\r
+[Protocols]\r
+  gEfiSmmCommunicationProtocolGuid     ## SOMETIMES_CONSUMES\r
+\r
+[UserExtensions.TianoCore."ExtraFiles"]\r
+  MemoryProfileInfoExtra.uni\r
diff --git a/MdeModulePkg/Application/MemoryProfileInfo/MemoryProfileInfo.uni b/MdeModulePkg/Application/MemoryProfileInfo/MemoryProfileInfo.uni
new file mode 100644 (file)
index 0000000..fe48826
Binary files /dev/null and b/MdeModulePkg/Application/MemoryProfileInfo/MemoryProfileInfo.uni differ
diff --git a/MdeModulePkg/Application/MemoryProfileInfo/MemoryProfileInfoExtra.uni b/MdeModulePkg/Application/MemoryProfileInfo/MemoryProfileInfoExtra.uni
new file mode 100644 (file)
index 0000000..3290511
Binary files /dev/null and b/MdeModulePkg/Application/MemoryProfileInfo/MemoryProfileInfoExtra.uni differ
index 75542b343298b611acdf04d64c8981759ed51c17..bb2bfab370ff8ec32bb749336b9383684ad54d8d 100644 (file)
@@ -69,6 +69,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #include <Guid/IdleLoopEvent.h>\r
 #include <Guid/VectorHandoffTable.h>\r
 #include <Ppi/VectorHandoffInfo.h>\r
+#include <Guid/ZeroGuid.h>\r
+#include <Guid/MemoryProfile.h>\r
 \r
 #include <Library/DxeCoreEntryPoint.h>\r
 #include <Library/DebugLib.h>\r
@@ -191,6 +193,56 @@ typedef struct {
   EFI_HANDLE            DeviceHandle;\r
 } EFI_GCD_MAP_ENTRY;\r
 \r
+\r
+#define LOADED_IMAGE_PRIVATE_DATA_SIGNATURE   SIGNATURE_32('l','d','r','i')\r
+\r
+typedef struct {\r
+  UINTN                       Signature;\r
+  /// Image handle\r
+  EFI_HANDLE                  Handle;   \r
+  /// Image type\r
+  UINTN                       Type;           \r
+  /// If entrypoint has been called\r
+  BOOLEAN                     Started;        \r
+  /// The image's entry point\r
+  EFI_IMAGE_ENTRY_POINT       EntryPoint;     \r
+  /// loaded image protocol\r
+  EFI_LOADED_IMAGE_PROTOCOL   Info;           \r
+  /// Location in memory\r
+  EFI_PHYSICAL_ADDRESS        ImageBasePage;  \r
+  /// Number of pages\r
+  UINTN                       NumberOfPages;  \r
+  /// Original fixup data\r
+  CHAR8                       *FixupData;     \r
+  /// Tpl of started image\r
+  EFI_TPL                     Tpl;            \r
+  /// Status returned by started image\r
+  EFI_STATUS                  Status;         \r
+  /// Size of ExitData from started image\r
+  UINTN                       ExitDataSize;   \r
+  /// Pointer to exit data from started image\r
+  VOID                        *ExitData;      \r
+  /// Pointer to pool allocation for context save/retore\r
+  VOID                        *JumpBuffer;    \r
+  /// Pointer to buffer for context save/retore\r
+  BASE_LIBRARY_JUMP_BUFFER    *JumpContext;  \r
+  /// Machine type from PE image\r
+  UINT16                      Machine;        \r
+  /// EBC Protocol pointer\r
+  EFI_EBC_PROTOCOL            *Ebc;           \r
+  /// Runtime image list\r
+  EFI_RUNTIME_IMAGE_ENTRY     *RuntimeData;   \r
+  /// Pointer to Loaded Image Device Path Protocl\r
+  EFI_DEVICE_PATH_PROTOCOL    *LoadedImageDevicePath;  \r
+  /// PeCoffLoader ImageContext\r
+  PE_COFF_LOADER_IMAGE_CONTEXT  ImageContext; \r
+  /// Status returned by LoadImage() service.\r
+  EFI_STATUS                  LoadImageStatus;\r
+} LOADED_IMAGE_PRIVATE_DATA;\r
+\r
+#define LOADED_IMAGE_PRIVATE_DATA_FROM_THIS(a) \\r
+          CR(a, LOADED_IMAGE_PRIVATE_DATA, Info, LOADED_IMAGE_PRIVATE_DATA_SIGNATURE)\r
+\r
 //\r
 // DXE Core Global Variables\r
 //\r
@@ -1192,7 +1244,32 @@ CoreAllocatePages (
   IN OUT EFI_PHYSICAL_ADDRESS  *Memory\r
   );\r
 \r
+/**\r
+  Allocates pages from the memory map.\r
+\r
+  @param  Type                   The type of allocation to perform\r
+  @param  MemoryType             The type of memory to turn the allocated pages\r
+                                 into\r
+  @param  NumberOfPages          The number of pages to allocate\r
+  @param  Memory                 A pointer to receive the base allocated memory\r
+                                 address\r
+\r
+  @return Status. On success, Memory is filled in with the base address allocated\r
+  @retval EFI_INVALID_PARAMETER  Parameters violate checking rules defined in\r
+                                 spec.\r
+  @retval EFI_NOT_FOUND          Could not allocate pages match the requirement.\r
+  @retval EFI_OUT_OF_RESOURCES   No enough pages to allocate.\r
+  @retval EFI_SUCCESS            Pages successfully allocated.\r
 \r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+CoreInternalAllocatePages (\r
+  IN EFI_ALLOCATE_TYPE      Type,\r
+  IN EFI_MEMORY_TYPE        MemoryType,\r
+  IN UINTN                  NumberOfPages,\r
+  IN OUT EFI_PHYSICAL_ADDRESS  *Memory\r
+  );\r
 \r
 /**\r
   Frees previous allocated pages.\r
@@ -1212,7 +1289,23 @@ CoreFreePages (
   IN UINTN                  NumberOfPages\r
   );\r
 \r
+/**\r
+  Frees previous allocated pages.\r
+\r
+  @param  Memory                 Base address of memory being freed\r
+  @param  NumberOfPages          The number of pages to free\r
+\r
+  @retval EFI_NOT_FOUND          Could not find the entry that covers the range\r
+  @retval EFI_INVALID_PARAMETER  Address not aligned\r
+  @return EFI_SUCCESS         -Pages successfully freed.\r
 \r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+CoreInternalFreePages (\r
+  IN EFI_PHYSICAL_ADDRESS   Memory,\r
+  IN UINTN                  NumberOfPages\r
+  );\r
 \r
 /**\r
   This function returns a copy of the current memory map. The map is an array of\r
@@ -1277,7 +1370,26 @@ CoreAllocatePool (
   OUT VOID            **Buffer\r
   );\r
 \r
+/**\r
+  Allocate pool of a particular type.\r
+\r
+  @param  PoolType               Type of pool to allocate\r
+  @param  Size                   The amount of pool to allocate\r
+  @param  Buffer                 The address to return a pointer to the allocated\r
+                                 pool\r
 \r
+  @retval EFI_INVALID_PARAMETER  PoolType not valid or Buffer is NULL\r
+  @retval EFI_OUT_OF_RESOURCES   Size exceeds max pool size or allocation failed.\r
+  @retval EFI_SUCCESS            Pool successfully allocated.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+CoreInternalAllocatePool (\r
+  IN EFI_MEMORY_TYPE  PoolType,\r
+  IN UINTN            Size,\r
+  OUT VOID            **Buffer\r
+  );\r
 \r
 /**\r
   Frees pool.\r
@@ -1294,7 +1406,20 @@ CoreFreePool (
   IN VOID        *Buffer\r
   );\r
 \r
+/**\r
+  Frees pool.\r
+\r
+  @param  Buffer                 The allocated pool entry to free\r
 \r
+  @retval EFI_INVALID_PARAMETER  Buffer is not a valid value.\r
+  @retval EFI_SUCCESS            Pool successfully freed.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+CoreInternalFreePool (\r
+  IN VOID        *Buffer\r
+  );\r
 \r
 /**\r
   Loads an EFI image into memory and returns a handle to the image.\r
@@ -2619,4 +2744,76 @@ VerifyFvHeaderChecksum (
   IN EFI_FIRMWARE_VOLUME_HEADER *FvHeader\r
   );\r
 \r
+/**\r
+  Initialize memory profile.\r
+\r
+  @param HobStart   The start address of the HOB.\r
+\r
+**/\r
+VOID\r
+MemoryProfileInit (\r
+  IN VOID   *HobStart\r
+  );\r
+\r
+/**\r
+  Install memory profile protocol.\r
+\r
+**/\r
+VOID\r
+MemoryProfileInstallProtocol (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  Register image to memory profile.\r
+\r
+  @param DriverEntry    Image info.\r
+  @param FileType       Image file type.\r
+\r
+  @retval TRUE          Register success.\r
+  @retval FALSE         Register fail.\r
+\r
+**/\r
+BOOLEAN\r
+RegisterMemoryProfileImage (\r
+  IN LOADED_IMAGE_PRIVATE_DATA  *DriverEntry,\r
+  IN EFI_FV_FILETYPE            FileType\r
+  );\r
+\r
+/**\r
+  Unregister image from memory profile.\r
+\r
+  @param DriverEntry    Image info.\r
+\r
+  @retval TRUE          Unregister success.\r
+  @retval FALSE         Unregister fail.\r
+\r
+**/\r
+BOOLEAN\r
+UnregisterMemoryProfileImage (\r
+  IN LOADED_IMAGE_PRIVATE_DATA  *DriverEntry\r
+  );\r
+\r
+/**\r
+  Update memory profile information.\r
+\r
+  @param CallerAddress  Address of caller who call Allocate or Free.\r
+  @param Action         This Allocate or Free action.\r
+  @param MemoryType     Memory type.\r
+  @param Size           Buffer size.\r
+  @param Buffer         Buffer address.\r
+\r
+  @retval TRUE          Profile udpate success.\r
+  @retval FALSE         Profile update fail.\r
+\r
+**/\r
+BOOLEAN\r
+CoreUpdateProfile (\r
+  IN EFI_PHYSICAL_ADDRESS   CallerAddress,\r
+  IN MEMORY_PROFILE_ACTION  Action,\r
+  IN EFI_MEMORY_TYPE        MemoryType, // Valid for AllocatePages/AllocatePool\r
+  IN UINTN                  Size,       // Valid for AllocatePages/FreePages/AllocatePool\r
+  IN VOID                   *Buffer\r
+  );\r
+\r
 #endif\r
index adac56041ab3ffabb6f36bcf6a238af8c026913d..0a63f3cb9232bf00d51bd074ce56b5e394f2fa84 100644 (file)
@@ -52,6 +52,7 @@
   Mem/Page.c\r
   Mem/MemData.c\r
   Mem/Imem.h\r
+  Mem/MemoryProfileRecord.c\r
   FwVolBlock/FwVolBlock.c\r
   FwVolBlock/FwVolBlock.h\r
   FwVol/FwVolWrite.c\r
   gIdleLoopEventGuid\r
   gEventExitBootServicesFailedGuid              ## SOMETIMES_PRODUCES   ## Event\r
   gEfiVectorHandoffTableGuid                    ## SOMETIMES_PRODUCES   ## SystemTable\r
+  gEdkiiMemoryProfileGuid                       ## SOMETIMES_PRODUCES   ## GUID # Install protocol\r
+  gZeroGuid                                     ## SOMETIMES_CONSUMES   ## GUID\r
 \r
 [Ppis]\r
   gEfiVectorHandoffInfoPpiGuid                  ## UNDEFINED # HOB\r
   gEfiMdeModulePkgTokenSpaceGuid.PcdLoadFixAddressRuntimeCodePageNumber     ## SOMETIMES_CONSUMES\r
   gEfiMdeModulePkgTokenSpaceGuid.PcdLoadModuleAtFixAddressEnable            ## CONSUMES\r
   gEfiMdeModulePkgTokenSpaceGuid.PcdMaxEfiSystemTablePointerAddress         ## CONSUMES\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdMemoryProfileMemoryType                 ## CONSUMES\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdMemoryProfilePropertyMask               ## CONSUMES\r
 \r
 # [Hob]\r
 # RESOURCE_DESCRIPTOR   ## CONSUMES\r
 #\r
 \r
 [UserExtensions.TianoCore."ExtraFiles"]\r
-  DxeCoreExtra.uni
\ No newline at end of file
+  DxeCoreExtra.uni\r
index 5a8814041c11b7c0e8f4b4da18fc33ccfd1d6032..1ac5cc17212d590479723f9216e85e3f69852fe3 100644 (file)
@@ -268,6 +268,8 @@ DxeMain (
   //\r
   CoreInitializeMemoryServices (&HobStart, &MemoryBaseAddress, &MemoryLength);\r
 \r
+  MemoryProfileInit (HobStart);\r
+\r
   //\r
   // Allocate the EFI System Table and EFI Runtime Service Table from EfiRuntimeServicesData\r
   // Use the templates to initialize the contents of the EFI System Table and EFI Runtime Services Table\r
@@ -382,6 +384,8 @@ DxeMain (
   Status = CoreInitializeEventServices ();\r
   ASSERT_EFI_ERROR (Status);\r
 \r
+  MemoryProfileInstallProtocol ();\r
+\r
   //\r
   // Get persisted vector hand-off info from GUIDeed HOB again due to HobStart may be updated,\r
   // and install configuration table\r
index e7ad450db5d68f90d25a9fa1aff1f2416419ecdc..5b441f03fbbf089edb78a32a83d3fe63eb661d2a 100644 (file)
@@ -1626,6 +1626,7 @@ CoreStartImage (
   // Subsequent calls to LongJump() cause a non-zero value to be returned by SetJump().\r
   //\r
   if (SetJumpFlag == 0) {\r
+    RegisterMemoryProfileImage (Image, (Image->ImageContext.ImageType == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION ? EFI_FV_FILETYPE_APPLICATION : EFI_FV_FILETYPE_DRIVER));\r
     //\r
     // Call the image's entry point\r
     //\r
@@ -1851,6 +1852,7 @@ CoreUnloadImage (
     Status = EFI_INVALID_PARAMETER;\r
     goto Done;\r
   }\r
+  UnregisterMemoryProfileImage (Image);\r
 \r
   if (Image->Started) {\r
     //\r
index e9240c03b0c90021c06e4b5de85d30c451c69937..7fb8c9368e235a0b0209900a20a07b273d556952 100644 (file)
@@ -16,56 +16,6 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #ifndef _IMAGE_H_\r
 #define _IMAGE_H_\r
 \r
-#define LOADED_IMAGE_PRIVATE_DATA_SIGNATURE   SIGNATURE_32('l','d','r','i')\r
-\r
-typedef struct {\r
-  UINTN                       Signature;\r
-  /// Image handle\r
-  EFI_HANDLE                  Handle;   \r
-  /// Image type\r
-  UINTN                       Type;           \r
-  /// If entrypoint has been called\r
-  BOOLEAN                     Started;        \r
-  /// The image's entry point\r
-  EFI_IMAGE_ENTRY_POINT       EntryPoint;     \r
-  /// loaded image protocol\r
-  EFI_LOADED_IMAGE_PROTOCOL   Info;           \r
-  /// Location in memory\r
-  EFI_PHYSICAL_ADDRESS        ImageBasePage;  \r
-  /// Number of pages\r
-  UINTN                       NumberOfPages;  \r
-  /// Original fixup data\r
-  CHAR8                       *FixupData;     \r
-  /// Tpl of started image\r
-  EFI_TPL                     Tpl;            \r
-  /// Status returned by started image\r
-  EFI_STATUS                  Status;         \r
-  /// Size of ExitData from started image\r
-  UINTN                       ExitDataSize;   \r
-  /// Pointer to exit data from started image\r
-  VOID                        *ExitData;      \r
-  /// Pointer to pool allocation for context save/retore\r
-  VOID                        *JumpBuffer;    \r
-  /// Pointer to buffer for context save/retore\r
-  BASE_LIBRARY_JUMP_BUFFER    *JumpContext;  \r
-  /// Machine type from PE image\r
-  UINT16                      Machine;        \r
-  /// EBC Protocol pointer\r
-  EFI_EBC_PROTOCOL            *Ebc;           \r
-  /// Runtime image list\r
-  EFI_RUNTIME_IMAGE_ENTRY     *RuntimeData;   \r
-  /// Pointer to Loaded Image Device Path Protocl\r
-  EFI_DEVICE_PATH_PROTOCOL    *LoadedImageDevicePath;  \r
-  /// PeCoffLoader ImageContext\r
-  PE_COFF_LOADER_IMAGE_CONTEXT  ImageContext; \r
-  /// Status returned by LoadImage() service.\r
-  EFI_STATUS                  LoadImageStatus;\r
-} LOADED_IMAGE_PRIVATE_DATA;\r
-\r
-#define LOADED_IMAGE_PRIVATE_DATA_FROM_THIS(a) \\r
-          CR(a, LOADED_IMAGE_PRIVATE_DATA, Info, LOADED_IMAGE_PRIVATE_DATA_SIGNATURE)\r
-\r
-\r
 #define LOAD_PE32_IMAGE_PRIVATE_DATA_SIGNATURE  SIGNATURE_32('l','p','e','i')\r
 \r
 typedef struct {\r
diff --git a/MdeModulePkg/Core/Dxe/Mem/MemoryProfileRecord.c b/MdeModulePkg/Core/Dxe/Mem/MemoryProfileRecord.c
new file mode 100644 (file)
index 0000000..1602fdb
--- /dev/null
@@ -0,0 +1,1377 @@
+/** @file\r
+  Support routines for UEFI memory profile.\r
+\r
+  Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>\r
+  This program and the accompanying materials\r
+  are licensed and made available under the terms and conditions of the BSD License\r
+  which accompanies this distribution.  The full text of the license may be found at\r
+  http://opensource.org/licenses/bsd-license.php.\r
+\r
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "DxeMain.h"\r
+\r
+#define IS_UEFI_MEMORY_PROFILE_ENABLED ((PcdGet8 (PcdMemoryProfilePropertyMask) & BIT0) != 0)\r
+\r
+typedef struct {\r
+  UINT32                        Signature;\r
+  MEMORY_PROFILE_CONTEXT        Context;\r
+  LIST_ENTRY                    *DriverInfoList;\r
+} MEMORY_PROFILE_CONTEXT_DATA;\r
+\r
+typedef struct {\r
+  UINT32                        Signature;\r
+  MEMORY_PROFILE_DRIVER_INFO    DriverInfo;\r
+  LIST_ENTRY                    *AllocInfoList;\r
+  LIST_ENTRY                    Link;\r
+} MEMORY_PROFILE_DRIVER_INFO_DATA;\r
+\r
+typedef struct {\r
+  UINT32                        Signature;\r
+  MEMORY_PROFILE_ALLOC_INFO     AllocInfo;\r
+  LIST_ENTRY                    Link;\r
+} MEMORY_PROFILE_ALLOC_INFO_DATA;\r
+\r
+\r
+GLOBAL_REMOVE_IF_UNREFERENCED LIST_ENTRY  mImageQueue = INITIALIZE_LIST_HEAD_VARIABLE (mImageQueue);\r
+GLOBAL_REMOVE_IF_UNREFERENCED MEMORY_PROFILE_CONTEXT_DATA mMemoryProfileContext = {\r
+  MEMORY_PROFILE_CONTEXT_SIGNATURE,\r
+  {\r
+    {\r
+      MEMORY_PROFILE_CONTEXT_SIGNATURE,\r
+      sizeof (MEMORY_PROFILE_CONTEXT),\r
+      MEMORY_PROFILE_CONTEXT_REVISION\r
+    },\r
+    0,\r
+    0,\r
+    {0},\r
+    {0},\r
+    0,\r
+    0,\r
+    0\r
+  },\r
+  &mImageQueue,\r
+};\r
+GLOBAL_REMOVE_IF_UNREFERENCED MEMORY_PROFILE_CONTEXT_DATA *mMemoryProfileContextPtr = NULL;\r
+\r
+BOOLEAN mMemoryProfileRecordingStatus = FALSE;\r
+\r
+/**\r
+  Get memory profile data.\r
+\r
+  @param[in]      This              The EDKII_MEMORY_PROFILE_PROTOCOL instance.\r
+  @param[in, out] ProfileSize       On entry, points to the size in bytes of the ProfileBuffer.\r
+                                    On return, points to the size of the data returned in ProfileBuffer.\r
+  @param[out]     ProfileBuffer     Profile buffer.\r
+                      \r
+  @return EFI_SUCCESS               Get the memory profile data successfully.\r
+  @return EFI_BUFFER_TO_SMALL       The ProfileSize is too small for the resulting data. \r
+                                    ProfileSize is updated with the size required.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ProfileProtocolGetData (\r
+  IN     EDKII_MEMORY_PROFILE_PROTOCOL  *This,\r
+  IN OUT UINT64                         *ProfileSize,\r
+     OUT VOID                           *ProfileBuffer\r
+  );\r
+\r
+/**\r
+  Register image to memory profile.\r
+\r
+  @param[in] This               The EDKII_MEMORY_PROFILE_PROTOCOL instance.\r
+  @param[in] FilePath           File path of the image.\r
+  @param[in] ImageBase          Image base address.\r
+  @param[in] ImageSize          Image size.\r
+  @param[in] FileType           File type of the image.\r
+\r
+  @return EFI_SUCCESS           Register success.\r
+  @return EFI_OUT_OF_RESOURCE   No enough resource for this register.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ProfileProtocolRegisterImage (\r
+  IN EDKII_MEMORY_PROFILE_PROTOCOL      *This,\r
+  IN EFI_DEVICE_PATH_PROTOCOL           *FilePath,\r
+  IN PHYSICAL_ADDRESS                   ImageBase,\r
+  IN UINT64                             ImageSize,\r
+  IN EFI_FV_FILETYPE                    FileType\r
+  );\r
+\r
+/**\r
+  Unregister image from memory profile.\r
+\r
+  @param[in] This               The EDKII_MEMORY_PROFILE_PROTOCOL instance.\r
+  @param[in] FilePath           File path of the image.\r
+  @param[in] ImageBase          Image base address.\r
+  @param[in] ImageSize          Image size.\r
+\r
+  @return EFI_SUCCESS           Unregister success.\r
+  @return EFI_NOT_FOUND         The image is not found.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ProfileProtocolUnregisterImage (\r
+  IN EDKII_MEMORY_PROFILE_PROTOCOL      *This,\r
+  IN EFI_DEVICE_PATH_PROTOCOL           *FilePath,\r
+  IN PHYSICAL_ADDRESS                   ImageBase,\r
+  IN UINT64                             ImageSize\r
+  );\r
+\r
+EDKII_MEMORY_PROFILE_PROTOCOL mProfileProtocol = {\r
+  ProfileProtocolGetData,\r
+  ProfileProtocolRegisterImage,\r
+  ProfileProtocolUnregisterImage\r
+};\r
+\r
+/**\r
+  Return memory profile context.\r
+\r
+  @return Memory profile context.\r
+\r
+**/\r
+MEMORY_PROFILE_CONTEXT_DATA *\r
+GetMemoryProfileContext (\r
+  VOID\r
+  )\r
+{\r
+  return mMemoryProfileContextPtr;\r
+}\r
+\r
+/**\r
+  Retrieves the magic value from the PE/COFF header.\r
+\r
+  @param Hdr    The buffer in which to return the PE32, PE32+, or TE header.\r
+\r
+  @return EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC - Image is PE32\r
+  @return EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC - Image is PE32+\r
+\r
+**/\r
+UINT16\r
+InternalPeCoffGetPeHeaderMagicValue (\r
+  IN  EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION  Hdr\r
+  )\r
+{\r
+  //\r
+  // NOTE: Some versions of Linux ELILO for Itanium have an incorrect magic value\r
+  //       in the PE/COFF Header.  If the MachineType is Itanium(IA64) and the\r
+  //       Magic value in the OptionalHeader is  EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC\r
+  //       then override the returned value to EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC\r
+  //\r
+  if (Hdr.Pe32->FileHeader.Machine == IMAGE_FILE_MACHINE_IA64 && Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+    return EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;\r
+  }\r
+  //\r
+  // Return the magic value from the PC/COFF Optional Header\r
+  //\r
+  return Hdr.Pe32->OptionalHeader.Magic;\r
+}\r
+\r
+/**\r
+  Retrieves and returns the Subsystem of a PE/COFF image that has been loaded into system memory.\r
+  If Pe32Data is NULL, then ASSERT().\r
+\r
+  @param Pe32Data   The pointer to the PE/COFF image that is loaded in system memory.\r
+\r
+  @return The Subsystem of the PE/COFF image.\r
+\r
+**/\r
+UINT16\r
+InternalPeCoffGetSubsystem (\r
+  IN VOID  *Pe32Data\r
+  )\r
+{\r
+  EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION  Hdr;\r
+  EFI_IMAGE_DOS_HEADER                 *DosHdr;\r
+  UINT16                               Magic;\r
+\r
+  ASSERT (Pe32Data != NULL);\r
+\r
+  DosHdr = (EFI_IMAGE_DOS_HEADER *) Pe32Data;\r
+  if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {\r
+    //\r
+    // DOS image header is present, so read the PE header after the DOS image header.\r
+    //\r
+    Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *) ((UINTN) Pe32Data + (UINTN) ((DosHdr->e_lfanew) & 0x0ffff));\r
+  } else {\r
+    //\r
+    // DOS image header is not present, so PE header is at the image base.\r
+    //\r
+    Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *) Pe32Data;\r
+  }\r
+\r
+  if (Hdr.Te->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {\r
+    return Hdr.Te->Subsystem;\r
+  } else if (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE)  {\r
+    Magic = InternalPeCoffGetPeHeaderMagicValue (Hdr);\r
+    if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+      return Hdr.Pe32->OptionalHeader.Subsystem;\r
+    } else if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {\r
+      return Hdr.Pe32Plus->OptionalHeader.Subsystem;\r
+    }\r
+  }\r
+\r
+  return 0x0000;\r
+}\r
+\r
+/**\r
+  Retrieves and returns a pointer to the entry point to a PE/COFF image that has been loaded\r
+  into system memory with the PE/COFF Loader Library functions.\r
+\r
+  Retrieves the entry point to the PE/COFF image specified by Pe32Data and returns this entry\r
+  point in EntryPoint.  If the entry point could not be retrieved from the PE/COFF image, then\r
+  return RETURN_INVALID_PARAMETER.  Otherwise return RETURN_SUCCESS.\r
+  If Pe32Data is NULL, then ASSERT().\r
+  If EntryPoint is NULL, then ASSERT().\r
+\r
+  @param  Pe32Data                  The pointer to the PE/COFF image that is loaded in system memory.\r
+  @param  EntryPoint                The pointer to entry point to the PE/COFF image to return.\r
+\r
+  @retval RETURN_SUCCESS            EntryPoint was returned.\r
+  @retval RETURN_INVALID_PARAMETER  The entry point could not be found in the PE/COFF image.\r
+\r
+**/\r
+RETURN_STATUS\r
+InternalPeCoffGetEntryPoint (\r
+  IN  VOID  *Pe32Data,\r
+  OUT VOID  **EntryPoint\r
+  )\r
+{\r
+  EFI_IMAGE_DOS_HEADER                  *DosHdr;\r
+  EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION   Hdr;\r
+\r
+  ASSERT (Pe32Data   != NULL);\r
+  ASSERT (EntryPoint != NULL);\r
+\r
+  DosHdr = (EFI_IMAGE_DOS_HEADER *) Pe32Data;\r
+  if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {\r
+    //\r
+    // DOS image header is present, so read the PE header after the DOS image header.\r
+    //\r
+    Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *) ((UINTN) Pe32Data + (UINTN) ((DosHdr->e_lfanew) & 0x0ffff));\r
+  } else {\r
+    //\r
+    // DOS image header is not present, so PE header is at the image base.\r
+    //\r
+    Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *) Pe32Data;\r
+  }\r
+\r
+  //\r
+  // Calculate the entry point relative to the start of the image.\r
+  // AddressOfEntryPoint is common for PE32 & PE32+\r
+  //\r
+  if (Hdr.Te->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {\r
+    *EntryPoint = (VOID *) ((UINTN) Pe32Data + (UINTN) (Hdr.Te->AddressOfEntryPoint & 0x0ffffffff) + sizeof (EFI_TE_IMAGE_HEADER) - Hdr.Te->StrippedSize);\r
+    return RETURN_SUCCESS;\r
+  } else if (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE) {\r
+    *EntryPoint = (VOID *) ((UINTN) Pe32Data + (UINTN) (Hdr.Pe32->OptionalHeader.AddressOfEntryPoint & 0x0ffffffff));\r
+    return RETURN_SUCCESS;\r
+  }\r
+\r
+  return RETURN_UNSUPPORTED;\r
+}\r
+\r
+/**\r
+  Build driver info.\r
+\r
+  @param ContextData    Memory profile context.\r
+  @param FileName       File name of the image.\r
+  @param ImageBase      Image base address.\r
+  @param ImageSize      Image size.\r
+  @param EntryPoint     Entry point of the image.\r
+  @param ImageSubsystem Image subsystem of the image.\r
+  @param FileType       File type of the image.\r
+\r
+  @return Pointer to memory profile driver info.\r
+\r
+**/\r
+MEMORY_PROFILE_DRIVER_INFO_DATA *\r
+BuildDriverInfo (\r
+  IN MEMORY_PROFILE_CONTEXT_DATA    *ContextData,\r
+  IN EFI_GUID                       *FileName,\r
+  IN PHYSICAL_ADDRESS               ImageBase,\r
+  IN UINT64                         ImageSize,\r
+  IN PHYSICAL_ADDRESS               EntryPoint,\r
+  IN UINT16                         ImageSubsystem,\r
+  IN EFI_FV_FILETYPE                FileType\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+  MEMORY_PROFILE_DRIVER_INFO        *DriverInfo;\r
+  MEMORY_PROFILE_DRIVER_INFO_DATA   *DriverInfoData;\r
+  VOID                              *EntryPointInImage;\r
+\r
+  //\r
+  // Use CoreInternalAllocatePool() that will not update profile for this AllocatePool action.\r
+  //\r
+  Status = CoreInternalAllocatePool (\r
+             EfiBootServicesData,\r
+             sizeof (*DriverInfoData) + sizeof (LIST_ENTRY),\r
+             (VOID **) &DriverInfoData\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    return NULL;\r
+  }\r
+\r
+  ZeroMem (DriverInfoData, sizeof (*DriverInfoData));\r
+\r
+  DriverInfo = &DriverInfoData->DriverInfo;\r
+  DriverInfoData->Signature = MEMORY_PROFILE_DRIVER_INFO_SIGNATURE;\r
+  DriverInfo->Header.Signature = MEMORY_PROFILE_DRIVER_INFO_SIGNATURE;\r
+  DriverInfo->Header.Length = sizeof (MEMORY_PROFILE_DRIVER_INFO);\r
+  DriverInfo->Header.Revision = MEMORY_PROFILE_DRIVER_INFO_REVISION;\r
+  if (FileName != NULL) {\r
+    CopyMem (&DriverInfo->FileName, FileName, sizeof (EFI_GUID));\r
+  }\r
+  DriverInfo->ImageBase = ImageBase;\r
+  DriverInfo->ImageSize = ImageSize;\r
+  DriverInfo->EntryPoint = EntryPoint;\r
+  DriverInfo->ImageSubsystem = ImageSubsystem;\r
+  if ((EntryPoint != 0) && ((EntryPoint < ImageBase) || (EntryPoint >= (ImageBase + ImageSize)))) {\r
+    //\r
+    // If the EntryPoint is not in the range of image buffer, it should come from emulation environment.\r
+    // So patch ImageBuffer here to align the EntryPoint.\r
+    //\r
+    Status = InternalPeCoffGetEntryPoint ((VOID *) (UINTN) ImageBase, &EntryPointInImage);\r
+    ASSERT_EFI_ERROR (Status);\r
+    DriverInfo->ImageBase = ImageBase + EntryPoint - (PHYSICAL_ADDRESS) (UINTN) EntryPointInImage;\r
+  }\r
+  DriverInfo->FileType = FileType;\r
+  DriverInfoData->AllocInfoList = (LIST_ENTRY *) (DriverInfoData + 1);\r
+  InitializeListHead (DriverInfoData->AllocInfoList);\r
+  DriverInfo->CurrentUsage = 0;\r
+  DriverInfo->PeakUsage = 0;\r
+  DriverInfo->AllocRecordCount = 0;\r
+\r
+  InsertTailList (ContextData->DriverInfoList, &DriverInfoData->Link);\r
+  ContextData->Context.ImageCount ++;\r
+  ContextData->Context.TotalImageSize += DriverInfo->ImageSize;\r
+\r
+  return DriverInfoData;\r
+}\r
+\r
+/**\r
+  Register DXE Core to memory profile.\r
+\r
+  @param HobStart       The start address of the HOB.\r
+  @param ContextData    Memory profile context.\r
+\r
+  @retval TRUE      Register success.\r
+  @retval FALSE     Register fail.\r
+\r
+**/\r
+BOOLEAN\r
+RegisterDxeCore (\r
+  IN VOID                           *HobStart,\r
+  IN MEMORY_PROFILE_CONTEXT_DATA    *ContextData\r
+  )\r
+{\r
+  EFI_PEI_HOB_POINTERS              DxeCoreHob;\r
+  MEMORY_PROFILE_DRIVER_INFO_DATA   *DriverInfoData;\r
+  PHYSICAL_ADDRESS                  ImageBase;\r
+\r
+  ASSERT (ContextData != NULL);\r
+\r
+  //\r
+  // Searching for image hob\r
+  //\r
+  DxeCoreHob.Raw          = HobStart;\r
+  while ((DxeCoreHob.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, DxeCoreHob.Raw)) != NULL) {\r
+    if (CompareGuid (&DxeCoreHob.MemoryAllocationModule->MemoryAllocationHeader.Name, &gEfiHobMemoryAllocModuleGuid)) {\r
+      //\r
+      // Find Dxe Core HOB\r
+      //\r
+      break;\r
+    }\r
+    DxeCoreHob.Raw = GET_NEXT_HOB (DxeCoreHob);\r
+  }\r
+  ASSERT (DxeCoreHob.Raw != NULL);\r
+\r
+  ImageBase = DxeCoreHob.MemoryAllocationModule->MemoryAllocationHeader.MemoryBaseAddress;\r
+  DriverInfoData = BuildDriverInfo (\r
+                     ContextData,\r
+                     &DxeCoreHob.MemoryAllocationModule->ModuleName,\r
+                     ImageBase,\r
+                     DxeCoreHob.MemoryAllocationModule->MemoryAllocationHeader.MemoryLength,\r
+                     DxeCoreHob.MemoryAllocationModule->EntryPoint,\r
+                     InternalPeCoffGetSubsystem ((VOID *) (UINTN) ImageBase),\r
+                     EFI_FV_FILETYPE_DXE_CORE\r
+                     );\r
+  if (DriverInfoData == NULL) {\r
+    return FALSE;\r
+  }\r
+\r
+  return TRUE;\r
+}\r
+\r
+/**\r
+  Initialize memory profile.\r
+\r
+  @param HobStart   The start address of the HOB.\r
+\r
+**/\r
+VOID\r
+MemoryProfileInit (\r
+  IN VOID   *HobStart\r
+  )\r
+{\r
+  MEMORY_PROFILE_CONTEXT_DATA   *ContextData;\r
+\r
+  if (!IS_UEFI_MEMORY_PROFILE_ENABLED) {\r
+    return;\r
+  }\r
+\r
+  ContextData = GetMemoryProfileContext ();\r
+  if (ContextData != NULL) {\r
+    return;\r
+  }\r
+\r
+  mMemoryProfileRecordingStatus = TRUE;\r
+  mMemoryProfileContextPtr = &mMemoryProfileContext;\r
+\r
+  RegisterDxeCore (HobStart, &mMemoryProfileContext);\r
+\r
+  DEBUG ((EFI_D_INFO, "MemoryProfileInit MemoryProfileContext - 0x%x\n", &mMemoryProfileContext));\r
+}\r
+\r
+/**\r
+  Install memory profile protocol.\r
+\r
+**/\r
+VOID\r
+MemoryProfileInstallProtocol (\r
+  VOID\r
+  )\r
+{\r
+  EFI_HANDLE    Handle;\r
+  EFI_STATUS    Status;\r
+\r
+  if (!IS_UEFI_MEMORY_PROFILE_ENABLED) {\r
+    return;\r
+  }\r
+\r
+  Handle = NULL;\r
+  Status = CoreInstallMultipleProtocolInterfaces (\r
+             &Handle,\r
+             &gEdkiiMemoryProfileGuid,\r
+             &mProfileProtocol,\r
+             NULL\r
+             );\r
+  ASSERT_EFI_ERROR (Status);\r
+}\r
+\r
+/**\r
+  Get the GUID file name from the file path.\r
+\r
+  @param FilePath  File path.\r
+\r
+  @return The GUID file name from the file path.\r
+\r
+**/\r
+EFI_GUID *\r
+GetFileNameFromFilePath (\r
+  IN EFI_DEVICE_PATH_PROTOCOL   *FilePath\r
+  )\r
+{\r
+  MEDIA_FW_VOL_FILEPATH_DEVICE_PATH     *ThisFilePath;\r
+  EFI_GUID                              *FileName;\r
+\r
+  FileName = NULL;\r
+  ThisFilePath = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) FilePath;\r
+  while (!IsDevicePathEnd (ThisFilePath)) {\r
+    FileName = EfiGetNameGuidFromFwVolDevicePathNode (ThisFilePath);\r
+    if (FileName != NULL) {\r
+      break;\r
+    }\r
+    ThisFilePath = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) NextDevicePathNode (ThisFilePath);\r
+  }\r
+\r
+  return FileName;\r
+}\r
+\r
+/**\r
+  Register image to memory profile.\r
+\r
+  @param DriverEntry    Image info.\r
+  @param FileType       Image file type.\r
+\r
+  @retval TRUE          Register success.\r
+  @retval FALSE         Register fail.\r
+\r
+**/\r
+BOOLEAN\r
+RegisterMemoryProfileImage (\r
+  IN LOADED_IMAGE_PRIVATE_DATA  *DriverEntry,\r
+  IN EFI_FV_FILETYPE            FileType\r
+  )\r
+{\r
+  MEMORY_PROFILE_CONTEXT_DATA       *ContextData;\r
+  MEMORY_PROFILE_DRIVER_INFO_DATA   *DriverInfoData;\r
+\r
+  if (!IS_UEFI_MEMORY_PROFILE_ENABLED) {\r
+    return FALSE;\r
+  }\r
+\r
+  ContextData = GetMemoryProfileContext ();\r
+  if (ContextData == NULL) {\r
+    return FALSE;\r
+  }\r
+\r
+  DriverInfoData = BuildDriverInfo (\r
+                     ContextData,\r
+                     GetFileNameFromFilePath (DriverEntry->Info.FilePath),\r
+                     DriverEntry->ImageContext.ImageAddress,\r
+                     DriverEntry->ImageContext.ImageSize,\r
+                     DriverEntry->ImageContext.EntryPoint,\r
+                     DriverEntry->ImageContext.ImageType,\r
+                     FileType\r
+                     );\r
+  if (DriverInfoData == NULL) {\r
+    return FALSE;\r
+  }\r
+\r
+  return TRUE;\r
+}\r
+\r
+/**\r
+  Search image from memory profile.\r
+\r
+  @param ContextData    Memory profile context.\r
+  @param FileName       Image file name.\r
+  @param Address        Image Address.\r
+\r
+  @return Pointer to memory profile driver info.\r
+\r
+**/\r
+MEMORY_PROFILE_DRIVER_INFO_DATA *\r
+GetMemoryProfileDriverInfoByFileNameAndAddress (\r
+  IN MEMORY_PROFILE_CONTEXT_DATA    *ContextData,\r
+  IN EFI_GUID                       *FileName,\r
+  IN PHYSICAL_ADDRESS               Address\r
+  )\r
+{\r
+  MEMORY_PROFILE_DRIVER_INFO        *DriverInfo;\r
+  MEMORY_PROFILE_DRIVER_INFO_DATA   *DriverInfoData;\r
+  LIST_ENTRY                        *DriverLink;\r
+  LIST_ENTRY                        *DriverInfoList;\r
+\r
+  DriverInfoList = ContextData->DriverInfoList;\r
+\r
+  for (DriverLink = DriverInfoList->ForwardLink;\r
+       DriverLink != DriverInfoList;\r
+       DriverLink = DriverLink->ForwardLink) {\r
+    DriverInfoData = CR (\r
+                       DriverLink,\r
+                       MEMORY_PROFILE_DRIVER_INFO_DATA,\r
+                       Link,\r
+                       MEMORY_PROFILE_DRIVER_INFO_SIGNATURE\r
+                       );\r
+    DriverInfo = &DriverInfoData->DriverInfo;\r
+    if ((CompareGuid (&DriverInfo->FileName, FileName)) &&\r
+        (Address >= DriverInfo->ImageBase) &&\r
+        (Address < (DriverInfo->ImageBase + DriverInfo->ImageSize))) {\r
+      return DriverInfoData;\r
+    }\r
+  }\r
+\r
+  return NULL;\r
+}\r
+\r
+/**\r
+  Search dummy image from memory profile.\r
+\r
+  @param ContextData    Memory profile context.\r
+\r
+  @return Pointer to memory profile driver info.\r
+\r
+**/\r
+MEMORY_PROFILE_DRIVER_INFO_DATA *\r
+FindDummyImage (\r
+  IN MEMORY_PROFILE_CONTEXT_DATA    *ContextData\r
+  )\r
+{\r
+  MEMORY_PROFILE_DRIVER_INFO_DATA   *DriverInfoData;\r
+  LIST_ENTRY                        *DriverLink;\r
+  LIST_ENTRY                        *DriverInfoList;\r
+\r
+  DriverInfoList = ContextData->DriverInfoList;\r
+\r
+  for (DriverLink = DriverInfoList->ForwardLink;\r
+       DriverLink != DriverInfoList;\r
+       DriverLink = DriverLink->ForwardLink) {\r
+    DriverInfoData = CR (\r
+                   DriverLink,\r
+                   MEMORY_PROFILE_DRIVER_INFO_DATA,\r
+                   Link,\r
+                   MEMORY_PROFILE_DRIVER_INFO_SIGNATURE\r
+                   );\r
+    if (CompareGuid (&gZeroGuid, &DriverInfoData->DriverInfo.FileName)) {\r
+      return DriverInfoData;\r
+    }\r
+  }\r
+\r
+  return BuildDriverInfo (ContextData, &gZeroGuid, 0, 0, 0, 0, 0);\r
+}\r
+\r
+/**\r
+  Search image from memory profile.\r
+  It will return image, if (Address >= ImageBuffer) AND (Address < ImageBuffer + ImageSize)\r
+\r
+  @param ContextData    Memory profile context.\r
+  @param Address        Image or Function address.\r
+\r
+  @return Pointer to memory profile driver info.\r
+\r
+**/\r
+MEMORY_PROFILE_DRIVER_INFO_DATA *\r
+GetMemoryProfileDriverInfoFromAddress (\r
+  IN MEMORY_PROFILE_CONTEXT_DATA    *ContextData,\r
+  IN PHYSICAL_ADDRESS               Address\r
+  )\r
+{\r
+  MEMORY_PROFILE_DRIVER_INFO        *DriverInfo;\r
+  MEMORY_PROFILE_DRIVER_INFO_DATA   *DriverInfoData;\r
+  LIST_ENTRY                        *DriverLink;\r
+  LIST_ENTRY                        *DriverInfoList;\r
+\r
+  DriverInfoList = ContextData->DriverInfoList;\r
+\r
+  for (DriverLink = DriverInfoList->ForwardLink;\r
+       DriverLink != DriverInfoList;\r
+       DriverLink = DriverLink->ForwardLink) {\r
+    DriverInfoData = CR (\r
+                       DriverLink,\r
+                       MEMORY_PROFILE_DRIVER_INFO_DATA,\r
+                       Link,\r
+                       MEMORY_PROFILE_DRIVER_INFO_SIGNATURE\r
+                       );\r
+    DriverInfo = &DriverInfoData->DriverInfo;\r
+    if ((Address >= DriverInfo->ImageBase) &&\r
+        (Address < (DriverInfo->ImageBase + DriverInfo->ImageSize))) {\r
+      return DriverInfoData;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Should never come here.\r
+  //\r
+  return FindDummyImage (ContextData);\r
+}\r
+\r
+/**\r
+  Unregister image from memory profile.\r
+\r
+  @param DriverEntry    Image info.\r
+\r
+  @retval TRUE          Unregister success.\r
+  @retval FALSE         Unregister fail.\r
+\r
+**/\r
+BOOLEAN\r
+UnregisterMemoryProfileImage (\r
+  IN LOADED_IMAGE_PRIVATE_DATA      *DriverEntry\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+  MEMORY_PROFILE_CONTEXT_DATA       *ContextData;\r
+  MEMORY_PROFILE_DRIVER_INFO_DATA   *DriverInfoData;\r
+  EFI_GUID                          *FileName;\r
+  PHYSICAL_ADDRESS                  ImageAddress;\r
+  VOID                              *EntryPointInImage;\r
+\r
+  if (!IS_UEFI_MEMORY_PROFILE_ENABLED) {\r
+    return FALSE;\r
+  }\r
+\r
+  ContextData = GetMemoryProfileContext ();\r
+  if (ContextData == NULL) {\r
+    return FALSE;\r
+  }\r
+\r
+  DriverInfoData = NULL;\r
+  FileName = GetFileNameFromFilePath (DriverEntry->Info.FilePath);\r
+  ImageAddress = DriverEntry->ImageContext.ImageAddress;\r
+  if ((DriverEntry->ImageContext.EntryPoint < ImageAddress) || (DriverEntry->ImageContext.EntryPoint >= (ImageAddress + DriverEntry->ImageContext.ImageSize))) {\r
+    //\r
+    // If the EntryPoint is not in the range of image buffer, it should come from emulation environment.\r
+    // So patch ImageAddress here to align the EntryPoint.\r
+    //\r
+    Status = InternalPeCoffGetEntryPoint ((VOID *) (UINTN) ImageAddress, &EntryPointInImage);\r
+    ASSERT_EFI_ERROR (Status);\r
+    ImageAddress = ImageAddress + (UINTN) DriverEntry->ImageContext.EntryPoint - (UINTN) EntryPointInImage;\r
+  }\r
+  if (FileName != NULL) {\r
+    DriverInfoData = GetMemoryProfileDriverInfoByFileNameAndAddress (ContextData, FileName, ImageAddress);\r
+  }\r
+  if (DriverInfoData == NULL) {\r
+    DriverInfoData = GetMemoryProfileDriverInfoFromAddress (ContextData, ImageAddress);\r
+  }\r
+  if (DriverInfoData == NULL) {\r
+    return FALSE;\r
+  }\r
+\r
+  ContextData->Context.TotalImageSize -= DriverInfoData->DriverInfo.ImageSize;\r
+\r
+  DriverInfoData->DriverInfo.ImageBase = 0;\r
+  DriverInfoData->DriverInfo.ImageSize = 0;\r
+\r
+  if (DriverInfoData->DriverInfo.PeakUsage == 0) {\r
+    ContextData->Context.ImageCount --;\r
+    RemoveEntryList (&DriverInfoData->Link);\r
+    //\r
+    // Use CoreInternalFreePool() that will not update profile for this FreePool action.\r
+    //\r
+    CoreInternalFreePool (DriverInfoData);\r
+  }\r
+\r
+  return TRUE;\r
+}\r
+\r
+/**\r
+  Return if this memory type needs to be recorded into memory profile.\r
+  If BIOS memory type (0 ~ EfiMaxMemoryType), it checks bit (1 << MemoryType).\r
+  If OS memory type (0x80000000 ~ 0xFFFFFFFF), it checks bit63 - 0x8000000000000000.\r
+\r
+  @param MemoryType     Memory type.\r
+\r
+  @retval TRUE          This memory type need to be recorded.\r
+  @retval FALSE         This memory type need not to be recorded.\r
+\r
+**/\r
+BOOLEAN\r
+CoreNeedRecordProfile (\r
+  IN EFI_MEMORY_TYPE    MemoryType\r
+  )\r
+{\r
+  UINT64 TestBit;\r
+\r
+  if ((UINT32) MemoryType >= 0x80000000) {\r
+    TestBit = BIT63;\r
+  } else {\r
+    TestBit = LShiftU64 (1, MemoryType);\r
+  }\r
+\r
+  if ((PcdGet64 (PcdMemoryProfileMemoryType) & TestBit) != 0) {\r
+    return TRUE;\r
+  } else {\r
+    return FALSE;\r
+  }\r
+}\r
+\r
+/**\r
+  Convert EFI memory type to profile memory index. The rule is:\r
+  If BIOS memory type (0 ~ EfiMaxMemoryType), ProfileMemoryIndex = MemoryType.\r
+  If OS memory type (0x80000000 ~ 0xFFFFFFFF), ProfileMemoryIndex = EfiMaxMemoryType.\r
+\r
+  @param MemoryType     Memory type.\r
+\r
+  @return EFI memory type as profile memory index.\r
+\r
+**/\r
+EFI_MEMORY_TYPE\r
+GetProfileMemoryIndex (\r
+  IN EFI_MEMORY_TYPE    MemoryType\r
+  )\r
+{\r
+  if ((UINT32) MemoryType >= 0x80000000) {\r
+    return EfiMaxMemoryType;\r
+  } else {\r
+    return MemoryType;\r
+  }\r
+}\r
+\r
+/**\r
+  Update memory profile Allocate information.\r
+\r
+  @param CallerAddress  Address of caller who call Allocate.\r
+  @param Action         This Allocate action.\r
+  @param MemoryType     Memory type.\r
+  @param Size           Buffer size.\r
+  @param Buffer         Buffer address.\r
+\r
+  @retval TRUE          Profile udpate success.\r
+  @retval FALSE         Profile update fail.\r
+\r
+**/\r
+BOOLEAN\r
+CoreUpdateProfileAllocate (\r
+  IN PHYSICAL_ADDRESS       CallerAddress,\r
+  IN MEMORY_PROFILE_ACTION  Action,\r
+  IN EFI_MEMORY_TYPE        MemoryType,\r
+  IN UINTN                  Size,\r
+  IN VOID                   *Buffer\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+  MEMORY_PROFILE_CONTEXT           *Context;\r
+  MEMORY_PROFILE_DRIVER_INFO       *DriverInfo;\r
+  MEMORY_PROFILE_ALLOC_INFO        *AllocInfo;\r
+  MEMORY_PROFILE_CONTEXT_DATA       *ContextData;\r
+  MEMORY_PROFILE_DRIVER_INFO_DATA   *DriverInfoData;\r
+  MEMORY_PROFILE_ALLOC_INFO_DATA    *AllocInfoData;\r
+  EFI_MEMORY_TYPE                   ProfileMemoryIndex;\r
+\r
+  ContextData = GetMemoryProfileContext ();\r
+  if (ContextData == NULL) {\r
+    return FALSE;\r
+  }\r
+\r
+  DriverInfoData = GetMemoryProfileDriverInfoFromAddress (ContextData, CallerAddress);\r
+  ASSERT (DriverInfoData != NULL);\r
+\r
+  //\r
+  // Use CoreInternalAllocatePool() that will not update profile for this AllocatePool action.\r
+  //\r
+  Status = CoreInternalAllocatePool (\r
+             EfiBootServicesData,\r
+             sizeof (*AllocInfoData),\r
+             (VOID **) &AllocInfoData\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    return FALSE;\r
+  }\r
+  AllocInfo = &AllocInfoData->AllocInfo;\r
+  AllocInfoData->Signature      = MEMORY_PROFILE_ALLOC_INFO_SIGNATURE;\r
+  AllocInfo->Header.Signature   = MEMORY_PROFILE_ALLOC_INFO_SIGNATURE;\r
+  AllocInfo->Header.Length      = sizeof (MEMORY_PROFILE_ALLOC_INFO);\r
+  AllocInfo->Header.Revision    = MEMORY_PROFILE_ALLOC_INFO_REVISION;\r
+  AllocInfo->CallerAddress      = CallerAddress;\r
+  AllocInfo->SequenceId         = ContextData->Context.SequenceCount;\r
+  AllocInfo->Action             = Action;\r
+  AllocInfo->MemoryType         = MemoryType;\r
+  AllocInfo->Buffer             = (PHYSICAL_ADDRESS) (UINTN) Buffer;\r
+  AllocInfo->Size               = Size;\r
+\r
+  InsertTailList (DriverInfoData->AllocInfoList, &AllocInfoData->Link);\r
+\r
+  ProfileMemoryIndex = GetProfileMemoryIndex (MemoryType);\r
+\r
+  DriverInfo = &DriverInfoData->DriverInfo;\r
+  DriverInfo->CurrentUsage += Size;\r
+  if (DriverInfo->PeakUsage < DriverInfo->CurrentUsage) {\r
+    DriverInfo->PeakUsage = DriverInfo->CurrentUsage;\r
+  }\r
+  DriverInfo->CurrentUsageByType[ProfileMemoryIndex] += Size;\r
+  if (DriverInfo->PeakUsageByType[ProfileMemoryIndex] < DriverInfo->CurrentUsageByType[ProfileMemoryIndex]) {\r
+    DriverInfo->PeakUsageByType[ProfileMemoryIndex] = DriverInfo->CurrentUsageByType[ProfileMemoryIndex];\r
+  }\r
+  DriverInfo->AllocRecordCount ++;\r
+\r
+  Context = &ContextData->Context;\r
+  Context->CurrentTotalUsage += Size;\r
+  if (Context->PeakTotalUsage < Context->CurrentTotalUsage) {\r
+    Context->PeakTotalUsage = Context->CurrentTotalUsage;\r
+  }\r
+  Context->CurrentTotalUsageByType[ProfileMemoryIndex] += Size;\r
+  if (Context->PeakTotalUsageByType[ProfileMemoryIndex] < Context->CurrentTotalUsageByType[ProfileMemoryIndex]) {\r
+    Context->PeakTotalUsageByType[ProfileMemoryIndex] = Context->CurrentTotalUsageByType[ProfileMemoryIndex];\r
+  }\r
+  Context->SequenceCount ++;\r
+\r
+  return TRUE;\r
+}\r
+\r
+/**\r
+  Get memory profile alloc info from memory profile\r
+\r
+  @param DriverInfoData     Driver info\r
+  @param Action             This Free action\r
+  @param Size               Buffer size\r
+  @param Buffer             Buffer address\r
+\r
+  @return Pointer to memory profile alloc info.\r
+**/\r
+MEMORY_PROFILE_ALLOC_INFO_DATA *\r
+GetMemoryProfileAllocInfoFromAddress (\r
+  IN MEMORY_PROFILE_DRIVER_INFO_DATA    *DriverInfoData,\r
+  IN MEMORY_PROFILE_ACTION              Action,\r
+  IN UINTN                              Size,\r
+  IN VOID                               *Buffer\r
+  )\r
+{\r
+  LIST_ENTRY                        *AllocInfoList;\r
+  LIST_ENTRY                        *AllocLink;\r
+  MEMORY_PROFILE_ALLOC_INFO         *AllocInfo;\r
+  MEMORY_PROFILE_ALLOC_INFO_DATA    *AllocInfoData;\r
+\r
+  AllocInfoList = DriverInfoData->AllocInfoList;\r
+\r
+  for (AllocLink = AllocInfoList->ForwardLink;\r
+       AllocLink != AllocInfoList;\r
+       AllocLink = AllocLink->ForwardLink) {\r
+    AllocInfoData = CR (\r
+                      AllocLink,\r
+                      MEMORY_PROFILE_ALLOC_INFO_DATA,\r
+                      Link,\r
+                      MEMORY_PROFILE_ALLOC_INFO_SIGNATURE\r
+                      );\r
+    AllocInfo = &AllocInfoData->AllocInfo;\r
+    if (AllocInfo->Action != Action) {\r
+      continue;\r
+    }\r
+    switch (Action) {\r
+      case MemoryProfileActionAllocatePages:\r
+        if ((AllocInfo->Buffer <= (PHYSICAL_ADDRESS) (UINTN) Buffer) &&\r
+            ((AllocInfo->Buffer + AllocInfo->Size) >= ((PHYSICAL_ADDRESS) (UINTN) Buffer + Size))) {\r
+          return AllocInfoData;\r
+        }\r
+        break;\r
+      case MemoryProfileActionAllocatePool:\r
+        if (AllocInfo->Buffer == (PHYSICAL_ADDRESS) (UINTN) Buffer) {\r
+          return AllocInfoData;\r
+        }\r
+        break;\r
+      default:\r
+        ASSERT (FALSE);\r
+        break;\r
+    }\r
+  }\r
+\r
+  return NULL;\r
+}\r
+\r
+/**\r
+  Update memory profile Free information.\r
+\r
+  @param CallerAddress  Address of caller who call Free.\r
+  @param Action         This Free action.\r
+  @param Size           Buffer size.\r
+  @param Buffer         Buffer address.\r
+\r
+  @retval TRUE          Profile udpate success.\r
+  @retval FALSE         Profile update fail.\r
+\r
+**/\r
+BOOLEAN\r
+CoreUpdateProfileFree (\r
+  IN PHYSICAL_ADDRESS       CallerAddress,\r
+  IN MEMORY_PROFILE_ACTION  Action,\r
+  IN UINTN                  Size,\r
+  IN VOID                   *Buffer\r
+  )\r
+{\r
+  MEMORY_PROFILE_CONTEXT           *Context;\r
+  MEMORY_PROFILE_DRIVER_INFO       *DriverInfo;\r
+  MEMORY_PROFILE_ALLOC_INFO        *AllocInfo;\r
+  MEMORY_PROFILE_CONTEXT_DATA      *ContextData;\r
+  MEMORY_PROFILE_DRIVER_INFO_DATA  *DriverInfoData;\r
+  LIST_ENTRY                       *DriverLink;\r
+  LIST_ENTRY                       *DriverInfoList;\r
+  MEMORY_PROFILE_DRIVER_INFO_DATA  *ThisDriverInfoData;\r
+  MEMORY_PROFILE_ALLOC_INFO_DATA   *AllocInfoData;\r
+  EFI_MEMORY_TYPE                  ProfileMemoryIndex;\r
+\r
+  ContextData = GetMemoryProfileContext ();\r
+  if (ContextData == NULL) {\r
+    return FALSE;\r
+  }\r
+\r
+  DriverInfoData = GetMemoryProfileDriverInfoFromAddress (ContextData, CallerAddress);\r
+  ASSERT (DriverInfoData != NULL);\r
+\r
+  switch (Action) {\r
+    case MemoryProfileActionFreePages:\r
+      AllocInfoData = GetMemoryProfileAllocInfoFromAddress (DriverInfoData, MemoryProfileActionAllocatePages, Size, Buffer);\r
+      break;\r
+    case MemoryProfileActionFreePool:\r
+      AllocInfoData = GetMemoryProfileAllocInfoFromAddress (DriverInfoData, MemoryProfileActionAllocatePool, 0, Buffer);\r
+      break;\r
+    default:\r
+      ASSERT (FALSE);\r
+      AllocInfoData = NULL;\r
+      break;\r
+  }\r
+  if (AllocInfoData == NULL) {\r
+    //\r
+    // Legal case, because driver A might free memory allocated by driver B, by some protocol.\r
+    //\r
+    DriverInfoList = ContextData->DriverInfoList;\r
+\r
+    for (DriverLink = DriverInfoList->ForwardLink;\r
+         DriverLink != DriverInfoList;\r
+         DriverLink = DriverLink->ForwardLink) {\r
+      ThisDriverInfoData = CR (\r
+                             DriverLink,\r
+                             MEMORY_PROFILE_DRIVER_INFO_DATA,\r
+                             Link,\r
+                             MEMORY_PROFILE_DRIVER_INFO_SIGNATURE\r
+                             );\r
+      switch (Action) {\r
+        case MemoryProfileActionFreePages:\r
+          AllocInfoData = GetMemoryProfileAllocInfoFromAddress (ThisDriverInfoData, MemoryProfileActionAllocatePages, Size, Buffer);\r
+          break;\r
+        case MemoryProfileActionFreePool:\r
+          AllocInfoData = GetMemoryProfileAllocInfoFromAddress (ThisDriverInfoData, MemoryProfileActionAllocatePool, 0, Buffer);\r
+          break;\r
+        default:\r
+          ASSERT (FALSE);\r
+          AllocInfoData = NULL;\r
+          break;\r
+      }\r
+      if (AllocInfoData != NULL) {\r
+        DriverInfoData = ThisDriverInfoData;\r
+        break;\r
+      }\r
+    }\r
+\r
+    if (AllocInfoData == NULL) {\r
+      //\r
+      // No matched allocate operation is found for this free operation.\r
+      // It is because the specified memory type allocate operation has been\r
+      // filtered by CoreNeedRecordProfile(), but free operations have no\r
+      // memory type information, they can not be filtered by CoreNeedRecordProfile().\r
+      // Then, they will be filtered here.\r
+      //\r
+      return FALSE;\r
+    }\r
+  }\r
+\r
+  Context = &ContextData->Context;\r
+  DriverInfo = &DriverInfoData->DriverInfo;\r
+  AllocInfo = &AllocInfoData->AllocInfo;\r
+\r
+  ProfileMemoryIndex = GetProfileMemoryIndex (AllocInfo->MemoryType);\r
+\r
+  Context->CurrentTotalUsage -= AllocInfo->Size;\r
+  Context->CurrentTotalUsageByType[ProfileMemoryIndex] -= AllocInfo->Size;\r
+\r
+  DriverInfo->CurrentUsage -= AllocInfo->Size;\r
+  DriverInfo->CurrentUsageByType[ProfileMemoryIndex] -= AllocInfo->Size;\r
+  DriverInfo->AllocRecordCount --;\r
+\r
+  RemoveEntryList (&AllocInfoData->Link);\r
+\r
+  if (Action == MemoryProfileActionFreePages) {\r
+    if (AllocInfo->Buffer != (PHYSICAL_ADDRESS) (UINTN) Buffer) {\r
+      CoreUpdateProfileAllocate (\r
+        AllocInfo->CallerAddress,\r
+        MemoryProfileActionAllocatePages,\r
+        AllocInfo->MemoryType,\r
+        (UINTN) ((PHYSICAL_ADDRESS) (UINTN) Buffer - AllocInfo->Buffer),\r
+        (VOID *) (UINTN) AllocInfo->Buffer\r
+        );\r
+    }\r
+    if (AllocInfo->Buffer + AllocInfo->Size != ((PHYSICAL_ADDRESS) (UINTN) Buffer + Size)) {\r
+      CoreUpdateProfileAllocate (\r
+        AllocInfo->CallerAddress,\r
+        MemoryProfileActionAllocatePages,\r
+        AllocInfo->MemoryType,\r
+        (UINTN) ((AllocInfo->Buffer + AllocInfo->Size) - ((PHYSICAL_ADDRESS) (UINTN) Buffer + Size)),\r
+        (VOID *) ((UINTN) Buffer + Size)\r
+        );\r
+    }\r
+  }\r
+\r
+  //\r
+  // Use CoreInternalFreePool() that will not update profile for this FreePool action.\r
+  //\r
+  CoreInternalFreePool (AllocInfoData);\r
+\r
+  return TRUE;\r
+}\r
+\r
+/**\r
+  Update memory profile information.\r
+\r
+  @param CallerAddress  Address of caller who call Allocate or Free.\r
+  @param Action         This Allocate or Free action.\r
+  @param MemoryType     Memory type.\r
+  @param Size           Buffer size.\r
+  @param Buffer         Buffer address.\r
+\r
+  @retval TRUE          Profile udpate success.\r
+  @retval FALSE         Profile update fail.\r
+\r
+**/\r
+BOOLEAN\r
+CoreUpdateProfile (\r
+  IN PHYSICAL_ADDRESS       CallerAddress,\r
+  IN MEMORY_PROFILE_ACTION  Action,\r
+  IN EFI_MEMORY_TYPE        MemoryType, // Valid for AllocatePages/AllocatePool\r
+  IN UINTN                  Size,       // Valid for AllocatePages/FreePages/AllocatePool\r
+  IN VOID                   *Buffer\r
+  )\r
+{\r
+  MEMORY_PROFILE_CONTEXT_DATA   *ContextData;\r
+\r
+  if (!IS_UEFI_MEMORY_PROFILE_ENABLED) {\r
+    return FALSE;\r
+  }\r
+\r
+  if (!mMemoryProfileRecordingStatus) {\r
+    return FALSE;\r
+  }\r
+\r
+  //\r
+  // Free operations have no memory type information, so skip the check.\r
+  //\r
+  if ((Action == MemoryProfileActionAllocatePages) || (Action == MemoryProfileActionAllocatePool)) {\r
+    //\r
+    // Only record limited MemoryType.\r
+    //\r
+    if (!CoreNeedRecordProfile (MemoryType)) {\r
+      return FALSE;\r
+    }\r
+  }\r
+\r
+  ContextData = GetMemoryProfileContext ();\r
+  if (ContextData == NULL) {\r
+    return FALSE;\r
+  }\r
+\r
+  switch (Action) {\r
+    case MemoryProfileActionAllocatePages:\r
+      CoreUpdateProfileAllocate (CallerAddress, Action, MemoryType, Size, Buffer);\r
+      break;\r
+    case MemoryProfileActionFreePages:\r
+      CoreUpdateProfileFree (CallerAddress, Action, Size, Buffer);\r
+      break;\r
+    case MemoryProfileActionAllocatePool:\r
+      CoreUpdateProfileAllocate (CallerAddress, Action, MemoryType, Size, Buffer);\r
+      break;\r
+    case MemoryProfileActionFreePool:\r
+      CoreUpdateProfileFree (CallerAddress, Action, 0, Buffer);\r
+      break;\r
+    default:\r
+      ASSERT (FALSE);\r
+      break;\r
+  }\r
+  return TRUE;\r
+}\r
+\r
+////////////////////\r
+\r
+/**\r
+  Get memory profile data size.\r
+\r
+  @return Memory profile data size.\r
+\r
+**/\r
+UINTN\r
+MemoryProfileGetDataSize (\r
+  VOID\r
+  )\r
+{\r
+  MEMORY_PROFILE_CONTEXT_DATA       *ContextData;\r
+  MEMORY_PROFILE_DRIVER_INFO_DATA   *DriverInfoData;\r
+  LIST_ENTRY                        *DriverInfoList;\r
+  LIST_ENTRY                        *DriverLink;\r
+  UINTN                             TotalSize;\r
+\r
+\r
+  ContextData = GetMemoryProfileContext ();\r
+  if (ContextData == NULL) {\r
+    return 0;\r
+  }\r
+\r
+  TotalSize = sizeof (MEMORY_PROFILE_CONTEXT);\r
+  TotalSize += sizeof (MEMORY_PROFILE_DRIVER_INFO) * (UINTN) ContextData->Context.ImageCount;\r
+\r
+  DriverInfoList = ContextData->DriverInfoList;\r
+  for (DriverLink = DriverInfoList->ForwardLink;\r
+       DriverLink != DriverInfoList;\r
+       DriverLink = DriverLink->ForwardLink) {\r
+    DriverInfoData = CR (\r
+                       DriverLink,\r
+                       MEMORY_PROFILE_DRIVER_INFO_DATA,\r
+                       Link,\r
+                       MEMORY_PROFILE_DRIVER_INFO_SIGNATURE\r
+                       );\r
+    TotalSize += sizeof (MEMORY_PROFILE_ALLOC_INFO) * (UINTN) DriverInfoData->DriverInfo.AllocRecordCount;\r
+  }\r
+\r
+  return TotalSize;\r
+}\r
+\r
+/**\r
+  Copy memory profile data.\r
+\r
+  @param ProfileBuffer  The buffer to hold memory profile data.\r
+\r
+**/\r
+VOID\r
+MemoryProfileCopyData (\r
+  IN VOID   *ProfileBuffer\r
+  )\r
+{\r
+  MEMORY_PROFILE_CONTEXT            *Context;\r
+  MEMORY_PROFILE_DRIVER_INFO        *DriverInfo;\r
+  MEMORY_PROFILE_ALLOC_INFO         *AllocInfo;\r
+  MEMORY_PROFILE_CONTEXT_DATA       *ContextData;\r
+  MEMORY_PROFILE_DRIVER_INFO_DATA   *DriverInfoData;\r
+  MEMORY_PROFILE_ALLOC_INFO_DATA    *AllocInfoData;\r
+  LIST_ENTRY                        *DriverInfoList;\r
+  LIST_ENTRY                        *DriverLink;\r
+  LIST_ENTRY                        *AllocInfoList;\r
+  LIST_ENTRY                        *AllocLink;\r
+\r
+  ContextData = GetMemoryProfileContext ();\r
+  if (ContextData == NULL) {\r
+    return ;\r
+  }\r
+\r
+  Context = ProfileBuffer;\r
+  CopyMem (Context, &ContextData->Context, sizeof (MEMORY_PROFILE_CONTEXT));\r
+  DriverInfo = (MEMORY_PROFILE_DRIVER_INFO *) (Context + 1);\r
+\r
+  DriverInfoList = ContextData->DriverInfoList;\r
+  for (DriverLink = DriverInfoList->ForwardLink;\r
+       DriverLink != DriverInfoList;\r
+       DriverLink = DriverLink->ForwardLink) {\r
+    DriverInfoData = CR (\r
+                       DriverLink,\r
+                       MEMORY_PROFILE_DRIVER_INFO_DATA,\r
+                       Link,\r
+                       MEMORY_PROFILE_DRIVER_INFO_SIGNATURE\r
+                       );\r
+    CopyMem (DriverInfo, &DriverInfoData->DriverInfo, sizeof (MEMORY_PROFILE_DRIVER_INFO));\r
+    AllocInfo = (MEMORY_PROFILE_ALLOC_INFO *) (DriverInfo + 1);\r
+\r
+    AllocInfoList = DriverInfoData->AllocInfoList;\r
+    for (AllocLink = AllocInfoList->ForwardLink;\r
+         AllocLink != AllocInfoList;\r
+         AllocLink = AllocLink->ForwardLink) {\r
+      AllocInfoData = CR (\r
+                        AllocLink,\r
+                        MEMORY_PROFILE_ALLOC_INFO_DATA,\r
+                        Link,\r
+                        MEMORY_PROFILE_ALLOC_INFO_SIGNATURE\r
+                        );\r
+      CopyMem (AllocInfo, &AllocInfoData->AllocInfo, sizeof (MEMORY_PROFILE_ALLOC_INFO));\r
+      AllocInfo += 1;\r
+    }\r
+\r
+    DriverInfo = (MEMORY_PROFILE_DRIVER_INFO *) ((UINTN) (DriverInfo + 1) + sizeof (MEMORY_PROFILE_ALLOC_INFO) * (UINTN) DriverInfo->AllocRecordCount);\r
+  }\r
+}\r
+\r
+/**\r
+  Get memory profile data.\r
+\r
+  @param[in]      This              The EDKII_MEMORY_PROFILE_PROTOCOL instance.\r
+  @param[in, out] ProfileSize       On entry, points to the size in bytes of the ProfileBuffer.\r
+                                    On return, points to the size of the data returned in ProfileBuffer.\r
+  @param[out]     ProfileBuffer     Profile buffer.\r
+                      \r
+  @return EFI_SUCCESS               Get the memory profile data successfully.\r
+  @return EFI_BUFFER_TO_SMALL       The ProfileSize is too small for the resulting data. \r
+                                    ProfileSize is updated with the size required.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ProfileProtocolGetData (\r
+  IN     EDKII_MEMORY_PROFILE_PROTOCOL  *This,\r
+  IN OUT UINT64                         *ProfileSize,\r
+     OUT VOID                           *ProfileBuffer\r
+  )\r
+{\r
+  UINTN                                 Size;\r
+  MEMORY_PROFILE_CONTEXT_DATA           *ContextData;\r
+  BOOLEAN                               MemoryProfileRecordingStatus;\r
+\r
+  ContextData = GetMemoryProfileContext ();\r
+  if (ContextData == NULL) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  MemoryProfileRecordingStatus = mMemoryProfileRecordingStatus;\r
+  mMemoryProfileRecordingStatus = FALSE;\r
+\r
+  Size = MemoryProfileGetDataSize ();\r
+\r
+  if (*ProfileSize < Size) {\r
+    *ProfileSize = Size;\r
+    mMemoryProfileRecordingStatus = MemoryProfileRecordingStatus;\r
+    return EFI_BUFFER_TOO_SMALL;\r
+  }\r
+\r
+  *ProfileSize = Size;\r
+  MemoryProfileCopyData (ProfileBuffer);\r
+\r
+  mMemoryProfileRecordingStatus = MemoryProfileRecordingStatus;\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Register image to memory profile.\r
+\r
+  @param[in] This               The EDKII_MEMORY_PROFILE_PROTOCOL instance.\r
+  @param[in] FilePath           File path of the image.\r
+  @param[in] ImageBase          Image base address.\r
+  @param[in] ImageSize          Image size.\r
+  @param[in] FileType           File type of the image.\r
+\r
+  @return EFI_SUCCESS           Register success.\r
+  @return EFI_OUT_OF_RESOURCE   No enough resource for this register.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ProfileProtocolRegisterImage (\r
+  IN EDKII_MEMORY_PROFILE_PROTOCOL  *This,\r
+  IN EFI_DEVICE_PATH_PROTOCOL       *FilePath,\r
+  IN PHYSICAL_ADDRESS               ImageBase,\r
+  IN UINT64                         ImageSize,\r
+  IN EFI_FV_FILETYPE                FileType\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+  LOADED_IMAGE_PRIVATE_DATA         DriverEntry;\r
+  VOID                              *EntryPointInImage;\r
+\r
+  ZeroMem (&DriverEntry, sizeof (DriverEntry));\r
+  DriverEntry.Info.FilePath = FilePath;\r
+  DriverEntry.ImageContext.ImageAddress = ImageBase;\r
+  DriverEntry.ImageContext.ImageSize = ImageSize;\r
+  Status = InternalPeCoffGetEntryPoint ((VOID *) (UINTN) ImageBase, &EntryPointInImage);\r
+  ASSERT_EFI_ERROR (Status);\r
+  DriverEntry.ImageContext.EntryPoint = (PHYSICAL_ADDRESS) (UINTN) EntryPointInImage;\r
+  DriverEntry.ImageContext.ImageType = InternalPeCoffGetSubsystem ((VOID *) (UINTN) ImageBase);\r
+\r
+  return RegisterMemoryProfileImage (&DriverEntry, FileType) ? EFI_SUCCESS: EFI_OUT_OF_RESOURCES;\r
+}\r
+\r
+/**\r
+  Unregister image from memory profile.\r
+\r
+  @param[in] This               The EDKII_MEMORY_PROFILE_PROTOCOL instance.\r
+  @param[in] FilePath           File path of the image.\r
+  @param[in] ImageBase          Image base address.\r
+  @param[in] ImageSize          Image size.\r
+\r
+  @return EFI_SUCCESS           Unregister success.\r
+  @return EFI_NOT_FOUND         The image is not found.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ProfileProtocolUnregisterImage (\r
+  IN EDKII_MEMORY_PROFILE_PROTOCOL  *This,\r
+  IN EFI_DEVICE_PATH_PROTOCOL       *FilePath,\r
+  IN PHYSICAL_ADDRESS               ImageBase,\r
+  IN UINT64                         ImageSize\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+  LOADED_IMAGE_PRIVATE_DATA         DriverEntry;\r
+  VOID                              *EntryPointInImage;\r
+\r
+  ZeroMem (&DriverEntry, sizeof (DriverEntry));\r
+  DriverEntry.Info.FilePath = FilePath;\r
+  DriverEntry.ImageContext.ImageAddress = ImageBase;\r
+  DriverEntry.ImageContext.ImageSize = ImageSize;\r
+  Status = InternalPeCoffGetEntryPoint ((VOID *) (UINTN) ImageBase, &EntryPointInImage);\r
+  ASSERT_EFI_ERROR (Status);\r
+  DriverEntry.ImageContext.EntryPoint = (PHYSICAL_ADDRESS) (UINTN) EntryPointInImage;\r
+\r
+  return UnregisterMemoryProfileImage (&DriverEntry) ? EFI_SUCCESS: EFI_NOT_FOUND;\r
+}\r
+\r
+////////////////////\r
index f5067f663eae8dd0b7c535e4b2c439176f3fd655..18780070c5eaf8df44a27756933ba236c8c3800a 100644 (file)
@@ -1106,7 +1106,7 @@ FindFreePages (
 **/\r
 EFI_STATUS\r
 EFIAPI\r
-CoreAllocatePages (\r
+CoreInternalAllocatePages (\r
   IN EFI_ALLOCATE_TYPE      Type,\r
   IN EFI_MEMORY_TYPE        MemoryType,\r
   IN UINTN                  NumberOfPages,\r
@@ -1192,6 +1192,41 @@ Done:
   return Status;\r
 }\r
 \r
+/**\r
+  Allocates pages from the memory map.\r
+\r
+  @param  Type                   The type of allocation to perform\r
+  @param  MemoryType             The type of memory to turn the allocated pages\r
+                                 into\r
+  @param  NumberOfPages          The number of pages to allocate\r
+  @param  Memory                 A pointer to receive the base allocated memory\r
+                                 address\r
+\r
+  @return Status. On success, Memory is filled in with the base address allocated\r
+  @retval EFI_INVALID_PARAMETER  Parameters violate checking rules defined in\r
+                                 spec.\r
+  @retval EFI_NOT_FOUND          Could not allocate pages match the requirement.\r
+  @retval EFI_OUT_OF_RESOURCES   No enough pages to allocate.\r
+  @retval EFI_SUCCESS            Pages successfully allocated.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+CoreAllocatePages (\r
+  IN  EFI_ALLOCATE_TYPE     Type,\r
+  IN  EFI_MEMORY_TYPE       MemoryType,\r
+  IN  UINTN                 NumberOfPages,\r
+  OUT EFI_PHYSICAL_ADDRESS  *Memory\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+\r
+  Status = CoreInternalAllocatePages (Type, MemoryType, NumberOfPages, Memory);\r
+  if (!EFI_ERROR (Status)) {\r
+    CoreUpdateProfile ((EFI_PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS (0), MemoryProfileActionAllocatePages, MemoryType, EFI_PAGES_TO_SIZE (NumberOfPages), (VOID *) (UINTN) *Memory);\r
+  }\r
+  return Status;\r
+}\r
 \r
 /**\r
   Frees previous allocated pages.\r
@@ -1206,7 +1241,7 @@ Done:
 **/\r
 EFI_STATUS\r
 EFIAPI\r
-CoreFreePages (\r
+CoreInternalFreePages (\r
   IN EFI_PHYSICAL_ADDRESS   Memory,\r
   IN UINTN                  NumberOfPages\r
   )\r
@@ -1267,6 +1302,33 @@ Done:
   return Status;\r
 }\r
 \r
+/**\r
+  Frees previous allocated pages.\r
+\r
+  @param  Memory                 Base address of memory being freed\r
+  @param  NumberOfPages          The number of pages to free\r
+\r
+  @retval EFI_NOT_FOUND          Could not find the entry that covers the range\r
+  @retval EFI_INVALID_PARAMETER  Address not aligned\r
+  @return EFI_SUCCESS         -Pages successfully freed.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+CoreFreePages (\r
+  IN EFI_PHYSICAL_ADDRESS  Memory,\r
+  IN UINTN                 NumberOfPages\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+\r
+  Status = CoreInternalFreePages (Memory, NumberOfPages);\r
+  if (!EFI_ERROR (Status)) {\r
+    CoreUpdateProfile ((EFI_PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS (0), MemoryProfileActionFreePages, 0, EFI_PAGES_TO_SIZE (NumberOfPages), (VOID *) (UINTN) Memory);\r
+  }\r
+  return Status;\r
+}\r
+\r
 /**\r
   This function checks to see if the last memory map descriptor in a memory map\r
   can be merged with any of the other memory map descriptors in a memorymap.\r
index 7d250980f03b93b1116d35a68ec9cc637f6c6c1a..1891bb73876aa94029e8455c1c1c7c57b89d3675 100644 (file)
@@ -175,7 +175,7 @@ LookupPoolHead (
 **/\r
 EFI_STATUS\r
 EFIAPI\r
-CoreAllocatePool (\r
+CoreInternalAllocatePool (\r
   IN EFI_MEMORY_TYPE  PoolType,\r
   IN UINTN            Size,\r
   OUT VOID            **Buffer\r
@@ -218,7 +218,35 @@ CoreAllocatePool (
   return (*Buffer != NULL) ? EFI_SUCCESS : EFI_OUT_OF_RESOURCES;\r
 }\r
 \r
+/**\r
+  Allocate pool of a particular type.\r
+\r
+  @param  PoolType               Type of pool to allocate\r
+  @param  Size                   The amount of pool to allocate\r
+  @param  Buffer                 The address to return a pointer to the allocated\r
+                                 pool\r
+\r
+  @retval EFI_INVALID_PARAMETER  PoolType not valid or Buffer is NULL. \r
+  @retval EFI_OUT_OF_RESOURCES   Size exceeds max pool size or allocation failed.\r
+  @retval EFI_SUCCESS            Pool successfully allocated.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+CoreAllocatePool (\r
+  IN EFI_MEMORY_TYPE  PoolType,\r
+  IN UINTN            Size,\r
+  OUT VOID            **Buffer\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
 \r
+  Status = CoreInternalAllocatePool (PoolType, Size, Buffer);\r
+  if (!EFI_ERROR (Status)) {\r
+    CoreUpdateProfile ((EFI_PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS (0), MemoryProfileActionAllocatePool, PoolType, Size, *Buffer);\r
+  }\r
+  return Status;\r
+}\r
 \r
 /**\r
   Internal function to allocate pool of a particular type.\r
@@ -373,7 +401,7 @@ Done:
 **/\r
 EFI_STATUS\r
 EFIAPI\r
-CoreFreePool (\r
+CoreInternalFreePool (\r
   IN VOID        *Buffer\r
   )\r
 {\r
@@ -389,7 +417,29 @@ CoreFreePool (
   return Status;\r
 }\r
 \r
+/**\r
+  Frees pool.\r
+\r
+  @param  Buffer                 The allocated pool entry to free\r
+\r
+  @retval EFI_INVALID_PARAMETER  Buffer is not a valid value.\r
+  @retval EFI_SUCCESS            Pool successfully freed.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+CoreFreePool (\r
+  IN VOID  *Buffer\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
 \r
+  Status = CoreInternalFreePool (Buffer);\r
+  if (!EFI_ERROR (Status)) {\r
+    CoreUpdateProfile ((EFI_PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS (0), MemoryProfileActionFreePool, 0, 0, Buffer);\r
+  }\r
+  return Status;\r
+}\r
 \r
 /**\r
   Internal function to free a pool entry.\r
@@ -558,3 +608,4 @@ CoreFreePoolI (
 \r
   return EFI_SUCCESS;\r
 }\r
+\r
index a4686306f6e2de9bde78f69cb87806cb6048c437..178681ec90aecc58fd7d46c093afc3943dfefc74 100644 (file)
@@ -874,10 +874,12 @@ SmmDispatcher (
       //\r
       // For each SMM driver, pass NULL as ImageHandle\r
       //\r
+      RegisterSmramProfileImage (DriverEntry, TRUE);\r
       PERF_START (DriverEntry->ImageHandle, "StartImage:", NULL, 0);\r
       Status = ((EFI_IMAGE_ENTRY_POINT)(UINTN)DriverEntry->ImageEntryPoint)(DriverEntry->ImageHandle, gST);\r
       PERF_END (DriverEntry->ImageHandle, "StartImage:", NULL, 0);\r
       if (EFI_ERROR(Status)){\r
+        UnregisterSmramProfileImage (DriverEntry, TRUE);\r
         SmmFreePages(DriverEntry->ImageBuffer, DriverEntry->NumberOfPage);\r
       }\r
 \r
index 5b6e849a2d924b6ed4b036bfaaaea39588ba81ae..9cc2a4cabc6efd265872d7f52614caf9d30ffc75 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   SMM Memory page management functions.\r
 \r
-  Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.<BR>\r
   This program and the accompanying materials are licensed and made available \r
   under the terms and conditions of the BSD License which accompanies this \r
   distribution.  The full text of the license may be found at        \r
 \r
 #define TRUNCATE_TO_PAGES(a)  ((a) >> EFI_PAGE_SHIFT)\r
 \r
-typedef struct {\r
-  LIST_ENTRY  Link;\r
-  UINTN       NumberOfPages;\r
-} FREE_PAGE_LIST;\r
-\r
 LIST_ENTRY  mSmmMemoryMap = INITIALIZE_LIST_HEAD_VARIABLE (mSmmMemoryMap);\r
 \r
 /**\r
@@ -151,7 +146,7 @@ InternalAllocAddress (
 **/\r
 EFI_STATUS\r
 EFIAPI\r
-SmmAllocatePages (\r
+SmmInternalAllocatePages (\r
   IN  EFI_ALLOCATE_TYPE     Type,\r
   IN  EFI_MEMORY_TYPE       MemoryType,\r
   IN  UINTN                 NumberOfPages,\r
@@ -202,6 +197,40 @@ SmmAllocatePages (
   return EFI_SUCCESS;\r
 }\r
 \r
+/**\r
+  Allocates pages from the memory map.\r
+\r
+  @param  Type                   The type of allocation to perform.\r
+  @param  MemoryType             The type of memory to turn the allocated pages\r
+                                 into.\r
+  @param  NumberOfPages          The number of pages to allocate.\r
+  @param  Memory                 A pointer to receive the base allocated memory\r
+                                 address.\r
+\r
+  @retval EFI_INVALID_PARAMETER  Parameters violate checking rules defined in spec.\r
+  @retval EFI_NOT_FOUND          Could not allocate pages match the requirement.\r
+  @retval EFI_OUT_OF_RESOURCES   No enough pages to allocate.\r
+  @retval EFI_SUCCESS            Pages successfully allocated.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SmmAllocatePages (\r
+  IN  EFI_ALLOCATE_TYPE     Type,\r
+  IN  EFI_MEMORY_TYPE       MemoryType,\r
+  IN  UINTN                 NumberOfPages,\r
+  OUT EFI_PHYSICAL_ADDRESS  *Memory\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+\r
+  Status = SmmInternalAllocatePages (Type, MemoryType, NumberOfPages, Memory);\r
+  if (!EFI_ERROR (Status)) {\r
+    SmmCoreUpdateProfile ((EFI_PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS (0), MemoryProfileActionAllocatePages, MemoryType, EFI_PAGES_TO_SIZE (NumberOfPages), (VOID *) (UINTN) *Memory);\r
+  }\r
+  return Status;\r
+}\r
+\r
 /**\r
   Internal Function. Merge two adjacent nodes.\r
 \r
@@ -242,7 +271,7 @@ InternalMergeNodes (
 **/\r
 EFI_STATUS\r
 EFIAPI\r
-SmmFreePages (\r
+SmmInternalFreePages (\r
   IN EFI_PHYSICAL_ADDRESS  Memory,\r
   IN UINTN                 NumberOfPages\r
   )\r
@@ -293,6 +322,33 @@ SmmFreePages (
   return EFI_SUCCESS;\r
 }\r
 \r
+/**\r
+  Frees previous allocated pages.\r
+\r
+  @param  Memory                 Base address of memory being freed.\r
+  @param  NumberOfPages          The number of pages to free.\r
+\r
+  @retval EFI_NOT_FOUND          Could not find the entry that covers the range.\r
+  @retval EFI_INVALID_PARAMETER  Address not aligned.\r
+  @return EFI_SUCCESS            Pages successfully freed.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SmmFreePages (\r
+  IN EFI_PHYSICAL_ADDRESS  Memory,\r
+  IN UINTN                 NumberOfPages\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+\r
+  Status = SmmInternalFreePages (Memory, NumberOfPages);\r
+  if (!EFI_ERROR (Status)) {\r
+    SmmCoreUpdateProfile ((EFI_PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS (0), MemoryProfileActionFreePages, 0, EFI_PAGES_TO_SIZE (NumberOfPages), (VOID *) (UINTN) Memory);\r
+  }\r
+  return Status;\r
+}\r
+\r
 /**\r
   Add free SMRAM region for use by memory service.\r
 \r
index a7220e4235ab87847f8533d3791c2651239ca15f..d16baedec9c319caa980a3f1fcdbf0f397121d00 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   SMM Core Main Entry Point\r
 \r
-  Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.<BR>\r
   This program and the accompanying materials are licensed and made available \r
   under the terms and conditions of the BSD License which accompanies this \r
   distribution.  The full text of the license may be found at        \r
@@ -82,6 +82,9 @@ SMM_CORE_SMI_HANDLERS  mSmmCoreSmiHandlers[] = {
   { NULL,                     NULL,                               NULL, FALSE }\r
 };\r
 \r
+UINTN                           mFullSmramRangeCount;\r
+EFI_SMRAM_DESCRIPTOR            *mFullSmramRanges;\r
+\r
 /**\r
   Place holder function until all the SMM System Table Service are available.\r
 \r
@@ -226,6 +229,8 @@ SmmReadyToLockHandler (
   gST = NULL;\r
   gBS = NULL;\r
 \r
+  SmramProfileReadyToLock ();\r
+\r
   return Status;\r
 }\r
 \r
@@ -401,6 +406,16 @@ SmmMain (
   //\r
   SmmInitializeMemoryServices (gSmmCorePrivate->SmramRangeCount, gSmmCorePrivate->SmramRanges);\r
 \r
+  SmramProfileInit ();\r
+\r
+  //\r
+  // Copy FullSmramRanges to SMRAM\r
+  //\r
+  mFullSmramRangeCount = gSmmCorePrivate->FullSmramRangeCount;\r
+  mFullSmramRanges = AllocatePool (mFullSmramRangeCount * sizeof (EFI_SMRAM_DESCRIPTOR));\r
+  ASSERT (mFullSmramRanges != NULL);\r
+  CopyMem (mFullSmramRanges, gSmmCorePrivate->FullSmramRanges, mFullSmramRangeCount * sizeof (EFI_SMRAM_DESCRIPTOR));\r
+\r
   //\r
   // Register all SMI Handlers required by the SMM Core\r
   //\r
@@ -412,6 +427,8 @@ SmmMain (
                );\r
     ASSERT_EFI_ERROR (Status);\r
   }\r
-  \r
+\r
+  RegisterSmramProfileHandler ();\r
+\r
   return EFI_SUCCESS;\r
 }\r
index 5392fb231519960e4ebf16dd85991bbfa203d07f..d494519d2c2047bab9a92d4e845bc00f7c1ac155 100644 (file)
@@ -2,7 +2,7 @@
   The internal header file includes the common header files, defines\r
   internal structure and functions used by SmmCore module.\r
 \r
-  Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.<BR>\r
   This program and the accompanying materials are licensed and made available \r
   under the terms and conditions of the BSD License which accompanies this \r
   distribution.  The full text of the license may be found at        \r
@@ -33,6 +33,8 @@
 #include <Guid/Apriori.h>\r
 #include <Guid/EventGroup.h>\r
 #include <Guid/EventLegacyBios.h>\r
+#include <Guid/ZeroGuid.h>\r
+#include <Guid/MemoryProfile.h>\r
 \r
 #include <Library/BaseLib.h>\r
 #include <Library/BaseMemoryLib.h>\r
@@ -271,6 +273,31 @@ SmmAllocatePages (
   OUT     EFI_PHYSICAL_ADDRESS      *Memory\r
   );\r
 \r
+/**\r
+  Allocates pages from the memory map.\r
+\r
+  @param  Type                   The type of allocation to perform\r
+  @param  MemoryType             The type of memory to turn the allocated pages\r
+                                 into\r
+  @param  NumberOfPages          The number of pages to allocate\r
+  @param  Memory                 A pointer to receive the base allocated memory\r
+                                 address\r
+\r
+  @retval EFI_INVALID_PARAMETER  Parameters violate checking rules defined in spec.\r
+  @retval EFI_NOT_FOUND          Could not allocate pages match the requirement.\r
+  @retval EFI_OUT_OF_RESOURCES   No enough pages to allocate.\r
+  @retval EFI_SUCCESS            Pages successfully allocated.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SmmInternalAllocatePages (\r
+  IN      EFI_ALLOCATE_TYPE         Type,\r
+  IN      EFI_MEMORY_TYPE           MemoryType,\r
+  IN      UINTN                     NumberOfPages,\r
+  OUT     EFI_PHYSICAL_ADDRESS      *Memory\r
+  );\r
+\r
 /**\r
   Frees previous allocated pages.\r
 \r
@@ -289,6 +316,24 @@ SmmFreePages (
   IN      UINTN                     NumberOfPages\r
   );\r
 \r
+/**\r
+  Frees previous allocated pages.\r
+\r
+  @param  Memory                 Base address of memory being freed\r
+  @param  NumberOfPages          The number of pages to free\r
+\r
+  @retval EFI_NOT_FOUND          Could not find the entry that covers the range\r
+  @retval EFI_INVALID_PARAMETER  Address not aligned\r
+  @return EFI_SUCCESS            Pages successfully freed.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SmmInternalFreePages (\r
+  IN      EFI_PHYSICAL_ADDRESS      Memory,\r
+  IN      UINTN                     NumberOfPages\r
+  );\r
+\r
 /**\r
   Allocate pool of a particular type.\r
 \r
@@ -310,6 +355,27 @@ SmmAllocatePool (
   OUT     VOID                      **Buffer\r
   );\r
 \r
+/**\r
+  Allocate pool of a particular type.\r
+\r
+  @param  PoolType               Type of pool to allocate\r
+  @param  Size                   The amount of pool to allocate\r
+  @param  Buffer                 The address to return a pointer to the allocated\r
+                                 pool\r
+\r
+  @retval EFI_INVALID_PARAMETER  PoolType not valid\r
+  @retval EFI_OUT_OF_RESOURCES   Size exceeds max pool size or allocation failed.\r
+  @retval EFI_SUCCESS            Pool successfully allocated.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SmmInternalAllocatePool (\r
+  IN      EFI_MEMORY_TYPE           PoolType,\r
+  IN      UINTN                     Size,\r
+  OUT     VOID                      **Buffer\r
+  );\r
+\r
 /**\r
   Frees pool.\r
 \r
@@ -325,6 +391,21 @@ SmmFreePool (
   IN      VOID                      *Buffer\r
   );\r
 \r
+/**\r
+  Frees pool.\r
+\r
+  @param  Buffer                 The allocated pool entry to free\r
+\r
+  @retval EFI_INVALID_PARAMETER  Buffer is not a valid value.\r
+  @retval EFI_SUCCESS            Pool successfully freed.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SmmInternalFreePool (\r
+  IN      VOID                      *Buffer\r
+  );\r
+\r
 /**\r
   Installs a protocol interface into the boot services environment.\r
 \r
@@ -741,4 +822,101 @@ SmmIsSchedulable (
   IN  EFI_SMM_DRIVER_ENTRY   *DriverEntry\r
   );\r
 \r
+//\r
+// SmramProfile\r
+//\r
+\r
+/**\r
+  Initialize SMRAM profile.\r
+\r
+**/\r
+VOID\r
+SmramProfileInit (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  Register SMM image to SMRAM profile.\r
+\r
+  @param DriverEntry    SMM image info.\r
+  @param RegisterToDxe  Register image to DXE.\r
+\r
+  @retval TRUE          Register success.\r
+  @retval FALSE         Register fail.\r
+\r
+**/\r
+BOOLEAN\r
+RegisterSmramProfileImage (\r
+  IN EFI_SMM_DRIVER_ENTRY   *DriverEntry,\r
+  IN BOOLEAN                RegisterToDxe\r
+  );\r
+\r
+/**\r
+  Unregister image from SMRAM profile.\r
+\r
+  @param DriverEntry        SMM image info.\r
+  @param UnregisterToDxe    Unregister image from DXE.\r
+\r
+  @retval TRUE              Unregister success.\r
+  @retval FALSE             Unregister fail.\r
+\r
+**/\r
+BOOLEAN\r
+UnregisterSmramProfileImage (\r
+  IN EFI_SMM_DRIVER_ENTRY   *DriverEntry,\r
+  IN BOOLEAN                UnregisterToDxe\r
+  );\r
+\r
+/**\r
+  Update SMRAM profile information.\r
+\r
+  @param CallerAddress  Address of caller who call Allocate or Free.\r
+  @param Action         This Allocate or Free action.\r
+  @param MemoryType     Memory type.\r
+  @param Size           Buffer size.\r
+  @param Buffer         Buffer address.\r
+\r
+  @retval TRUE          Profile udpate success.\r
+  @retval FALSE         Profile update fail.\r
+\r
+**/\r
+BOOLEAN\r
+SmmCoreUpdateProfile (\r
+  IN EFI_PHYSICAL_ADDRESS CallerAddress,\r
+  IN MEMORY_PROFILE_ACTION Action,\r
+  IN EFI_MEMORY_TYPE      MemoryType, // Valid for AllocatePages/AllocatePool\r
+  IN UINTN                Size,       // Valid for AllocatePages/FreePages/AllocatePool\r
+  IN VOID                 *Buffer\r
+  );\r
+\r
+/**\r
+  Register SMRAM profile handler.\r
+\r
+**/\r
+VOID\r
+RegisterSmramProfileHandler (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  SMRAM profile ready to lock callback function.\r
+\r
+**/\r
+VOID\r
+SmramProfileReadyToLock (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  Dump SMRAM infromation.\r
+\r
+**/\r
+VOID\r
+DumpSmramInfo (\r
+  VOID\r
+  );\r
+\r
+extern UINTN                    mFullSmramRangeCount;\r
+extern EFI_SMRAM_DESCRIPTOR     *mFullSmramRanges;\r
+\r
 #endif\r
index 1225a20f2af725abf253ff47b26048e91bf0b6fe..0c8e690846ef97f571e12649f1dfa538935c4009 100644 (file)
@@ -37,6 +37,7 @@
   Dispatcher.c\r
   Smi.c\r
   InstallConfigurationTable.c\r
+  SmramProfileRecord.c\r
 \r
 [Packages]\r
   MdePkg/MdePkg.dec\r
 [Pcd]\r
   gEfiMdeModulePkgTokenSpaceGuid.PcdLoadFixAddressSmmCodePageNumber     ## SOMETIMES_CONSUMES\r
   gEfiMdeModulePkgTokenSpaceGuid.PcdLoadModuleAtFixAddressEnable        ## CONSUMES\r
-  \r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdMemoryProfileMemoryType             ## CONSUMES\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdMemoryProfilePropertyMask           ## CONSUMES\r
+\r
 [Guids]\r
   gAprioriGuid                                  ## SOMETIMES_CONSUMES   ## File\r
   gEfiEventDxeDispatchGuid                      ## PRODUCES             ## GUID # SmiHandlerRegister\r
   gEfiEventLegacyBootGuid                       ## PRODUCES             ## GUID # SmiHandlerRegister\r
   gEfiEndOfDxeEventGroupGuid                    ## PRODUCES             ## GUID # SmiHandlerRegister\r
+  ## SOMETIMES_CONSUMES   ## GUID # Locate protocol\r
+  ## SOMETIMES_PRODUCES   ## GUID # SmiHandlerRegister\r
+  gEdkiiMemoryProfileGuid\r
+  gZeroGuid                                     ## SOMETIMES_CONSUMES   ## GUID\r
 \r
 [UserExtensions.TianoCore."ExtraFiles"]\r
   PiSmmCoreExtra.uni\r
index 411ebd823f2f5f1897faf287847c2ff479b8a1d6..3934d2f2eccae31291fb13932fae667adba8884f 100644 (file)
@@ -2,7 +2,7 @@
   The internal header file that declared a data structure that is shared\r
   between the SMM IPL and the SMM Core.\r
 \r
-  Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.<BR>\r
   This program and the accompanying materials are licensed and made available \r
   under the terms and conditions of the BSD License which accompanies this \r
   distribution.  The full text of the license may be found at        \r
@@ -116,6 +116,57 @@ typedef struct {
   /// a software SMI handler back to the caller of the SMM Communication Protocol.\r
   ///\r
   EFI_STATUS                      ReturnStatus;\r
+\r
+  EFI_PHYSICAL_ADDRESS            PiSmmCoreImageBase;\r
+  UINT64                          PiSmmCoreImageSize;\r
+  EFI_PHYSICAL_ADDRESS            PiSmmCoreEntryPoint;\r
+\r
+  UINTN                           FullSmramRangeCount;\r
+  EFI_SMRAM_DESCRIPTOR            *FullSmramRanges;\r
 } SMM_CORE_PRIVATE_DATA;\r
 \r
+//\r
+// Page management\r
+//\r
+\r
+typedef struct {\r
+  LIST_ENTRY  Link;\r
+  UINTN       NumberOfPages;\r
+} FREE_PAGE_LIST;\r
+\r
+extern LIST_ENTRY  mSmmMemoryMap;\r
+\r
+//\r
+// Pool management\r
+//\r
+\r
+//\r
+// MIN_POOL_SHIFT must not be less than 5\r
+//\r
+#define MIN_POOL_SHIFT  6\r
+#define MIN_POOL_SIZE   (1 << MIN_POOL_SHIFT)\r
+\r
+//\r
+// MAX_POOL_SHIFT must not be less than EFI_PAGE_SHIFT - 1\r
+//\r
+#define MAX_POOL_SHIFT  (EFI_PAGE_SHIFT - 1)\r
+#define MAX_POOL_SIZE   (1 << MAX_POOL_SHIFT)\r
+\r
+//\r
+// MAX_POOL_INDEX are calculated by maximum and minimum pool sizes\r
+//\r
+#define MAX_POOL_INDEX  (MAX_POOL_SHIFT - MIN_POOL_SHIFT + 1)\r
+\r
+typedef struct {\r
+  UINTN        Size;\r
+  BOOLEAN      Available;\r
+} POOL_HEADER;\r
+\r
+typedef struct {\r
+  POOL_HEADER  Header;\r
+  LIST_ENTRY   Link;\r
+} FREE_POOL_HEADER;\r
+\r
+extern LIST_ENTRY  mSmmPoolLists[MAX_POOL_INDEX];\r
+\r
 #endif\r
index b0e387401c9fc7b1d1faa75df1baa0028a754497..21c69ca6ef5bbf8a503b97f8f561abbc9c0d4177 100644 (file)
@@ -979,6 +979,13 @@ ExecuteSmmCoreFromSmram (
       //\r
       DEBUG ((DEBUG_INFO, "SMM IPL calling SMM Core at SMRAM address %p\n", (VOID *)(UINTN)ImageContext.EntryPoint));\r
 \r
+      gSmmCorePrivate->PiSmmCoreImageBase = ImageContext.ImageAddress;\r
+      gSmmCorePrivate->PiSmmCoreImageSize = ImageContext.ImageSize;\r
+      DEBUG ((DEBUG_INFO, "PiSmmCoreImageBase - 0x%016lx\n", gSmmCorePrivate->PiSmmCoreImageBase));\r
+      DEBUG ((DEBUG_INFO, "PiSmmCoreImageSize - 0x%016lx\n", gSmmCorePrivate->PiSmmCoreImageSize));\r
+\r
+      gSmmCorePrivate->PiSmmCoreEntryPoint = ImageContext.EntryPoint;\r
+\r
       //\r
       // Execute image\r
       //\r
@@ -1076,6 +1083,14 @@ SmmIplEntry (
 \r
   gSmmCorePrivate->SmramRangeCount = Size / sizeof (EFI_SMRAM_DESCRIPTOR);\r
 \r
+  //\r
+  // Save a full copy\r
+  //\r
+  gSmmCorePrivate->FullSmramRangeCount = gSmmCorePrivate->SmramRangeCount;\r
+  gSmmCorePrivate->FullSmramRanges = (EFI_SMRAM_DESCRIPTOR *) AllocatePool (Size);\r
+  ASSERT (gSmmCorePrivate->FullSmramRanges != NULL);\r
+  CopyMem (gSmmCorePrivate->FullSmramRanges, gSmmCorePrivate->SmramRanges, Size);\r
+\r
   //\r
   // Open all SMRAM ranges\r
   //\r
index beb5cd965e0a157403649d1b90b01bf4070c9c0c..34dcc93f1ab4cedfe080308c719d3276782e9f41 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   SMM Memory pool management functions.\r
 \r
-  Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.<BR>\r
   This program and the accompanying materials are licensed and made available \r
   under the terms and conditions of the BSD License which accompanies this \r
   distribution.  The full text of the license may be found at        \r
 \r
 #include "PiSmmCore.h"\r
 \r
-//\r
-// MIN_POOL_SHIFT must not be less than 5\r
-//\r
-#define MIN_POOL_SHIFT  6\r
-#define MIN_POOL_SIZE   (1 << MIN_POOL_SHIFT)\r
-\r
-//\r
-// MAX_POOL_SHIFT must not be less than EFI_PAGE_SHIFT - 1\r
-//\r
-#define MAX_POOL_SHIFT  (EFI_PAGE_SHIFT - 1)\r
-#define MAX_POOL_SIZE   (1 << MAX_POOL_SHIFT)\r
-\r
-//\r
-// MAX_POOL_INDEX are calculated by maximum and minimum pool sizes\r
-//\r
-#define MAX_POOL_INDEX  (MAX_POOL_SHIFT - MIN_POOL_SHIFT + 1)\r
-\r
-typedef struct {\r
-  UINTN        Size;\r
-  BOOLEAN      Available;\r
-} POOL_HEADER;\r
-\r
-typedef struct {\r
-  POOL_HEADER  Header;\r
-  LIST_ENTRY   Link;\r
-} FREE_POOL_HEADER;\r
-\r
 LIST_ENTRY  mSmmPoolLists[MAX_POOL_INDEX];\r
 //\r
 // To cache the SMRAM base since when Loading modules At fixed address feature is enabled, \r
@@ -141,16 +114,18 @@ InternalAllocPoolByIndex (
   OUT FREE_POOL_HEADER  **FreePoolHdr\r
   )\r
 {\r
-  EFI_STATUS        Status;\r
-  FREE_POOL_HEADER  *Hdr;\r
+  EFI_STATUS            Status;\r
+  FREE_POOL_HEADER      *Hdr;\r
+  EFI_PHYSICAL_ADDRESS  Address;\r
 \r
   ASSERT (PoolIndex <= MAX_POOL_INDEX);\r
   Status = EFI_SUCCESS;\r
   if (PoolIndex == MAX_POOL_INDEX) {\r
-    Hdr = (FREE_POOL_HEADER *)AllocatePages (EFI_SIZE_TO_PAGES (MAX_POOL_SIZE << 1));\r
-    if (Hdr == NULL) {\r
+    Status = SmmInternalAllocatePages (AllocateAnyPages, EfiRuntimeServicesData, EFI_SIZE_TO_PAGES (MAX_POOL_SIZE << 1), &Address);\r
+    if (EFI_ERROR (Status)) {\r
       return EFI_OUT_OF_RESOURCES;\r
     }\r
+    Hdr = (FREE_POOL_HEADER *) (UINTN) Address;\r
   } else if (!IsListEmpty (&mSmmPoolLists[PoolIndex])) {\r
     Hdr = BASE_CR (GetFirstNode (&mSmmPoolLists[PoolIndex]), FREE_POOL_HEADER, Link);\r
     RemoveEntryList (&Hdr->Link);\r
@@ -214,7 +189,7 @@ InternalFreePoolByIndex (
 **/\r
 EFI_STATUS\r
 EFIAPI\r
-SmmAllocatePool (\r
+SmmInternalAllocatePool (\r
   IN   EFI_MEMORY_TYPE  PoolType,\r
   IN   UINTN            Size,\r
   OUT  VOID             **Buffer\r
@@ -234,7 +209,7 @@ SmmAllocatePool (
   Size += sizeof (*PoolHdr);\r
   if (Size > MAX_POOL_SIZE) {\r
     Size = EFI_SIZE_TO_PAGES (Size);\r
-    Status = SmmAllocatePages (AllocateAnyPages, PoolType, Size, &Address);\r
+    Status = SmmInternalAllocatePages (AllocateAnyPages, PoolType, Size, &Address);\r
     if (EFI_ERROR (Status)) {\r
       return Status;\r
     }\r
@@ -257,6 +232,36 @@ SmmAllocatePool (
   return Status;\r
 }\r
 \r
+/**\r
+  Allocate pool of a particular type.\r
+\r
+  @param  PoolType               Type of pool to allocate.\r
+  @param  Size                   The amount of pool to allocate.\r
+  @param  Buffer                 The address to return a pointer to the allocated\r
+                                 pool.\r
+\r
+  @retval EFI_INVALID_PARAMETER  PoolType not valid.\r
+  @retval EFI_OUT_OF_RESOURCES   Size exceeds max pool size or allocation failed.\r
+  @retval EFI_SUCCESS            Pool successfully allocated.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SmmAllocatePool (\r
+  IN   EFI_MEMORY_TYPE  PoolType,\r
+  IN   UINTN            Size,\r
+  OUT  VOID             **Buffer\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+\r
+  Status = SmmInternalAllocatePool (PoolType, Size, Buffer);\r
+  if (!EFI_ERROR (Status)) {\r
+    SmmCoreUpdateProfile ((EFI_PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS (0), MemoryProfileActionAllocatePool, PoolType, Size, *Buffer);\r
+  }\r
+  return Status;\r
+}\r
+\r
 /**\r
   Frees pool.\r
 \r
@@ -268,7 +273,7 @@ SmmAllocatePool (
 **/\r
 EFI_STATUS\r
 EFIAPI\r
-SmmFreePool (\r
+SmmInternalFreePool (\r
   IN VOID  *Buffer\r
   )\r
 {\r
@@ -284,10 +289,34 @@ SmmFreePool (
   if (FreePoolHdr->Header.Size > MAX_POOL_SIZE) {\r
     ASSERT (((UINTN)FreePoolHdr & EFI_PAGE_MASK) == 0);\r
     ASSERT ((FreePoolHdr->Header.Size & EFI_PAGE_MASK) == 0);\r
-    return SmmFreePages (\r
+    return SmmInternalFreePages (\r
              (EFI_PHYSICAL_ADDRESS)(UINTN)FreePoolHdr,\r
              EFI_SIZE_TO_PAGES (FreePoolHdr->Header.Size)\r
              );\r
   }\r
   return InternalFreePoolByIndex (FreePoolHdr);\r
 }\r
+\r
+/**\r
+  Frees pool.\r
+\r
+  @param  Buffer                 The allocated pool entry to free.\r
+\r
+  @retval EFI_INVALID_PARAMETER  Buffer is not a valid value.\r
+  @retval EFI_SUCCESS            Pool successfully freed.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SmmFreePool (\r
+  IN VOID  *Buffer\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+\r
+  Status = SmmInternalFreePool (Buffer);\r
+  if (!EFI_ERROR (Status)) {\r
+    SmmCoreUpdateProfile ((EFI_PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS (0), MemoryProfileActionFreePool, 0, 0, Buffer);\r
+  }\r
+  return Status;\r
+}\r
diff --git a/MdeModulePkg/Core/PiSmmCore/SmramProfileRecord.c b/MdeModulePkg/Core/PiSmmCore/SmramProfileRecord.c
new file mode 100644 (file)
index 0000000..24ab1b1
--- /dev/null
@@ -0,0 +1,1975 @@
+/** @file\r
+  Support routines for SMRAM profile.\r
+\r
+  Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>\r
+  This program and the accompanying materials\r
+  are licensed and made available under the terms and conditions of the BSD License\r
+  which accompanies this distribution.  The full text of the license may be found at\r
+  http://opensource.org/licenses/bsd-license.php.\r
+\r
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "PiSmmCore.h"\r
+\r
+#define IS_SMRAM_PROFILE_ENABLED ((PcdGet8 (PcdMemoryProfilePropertyMask) & BIT1) != 0)\r
+\r
+typedef struct {\r
+  UINT32                        Signature;\r
+  MEMORY_PROFILE_CONTEXT        Context;\r
+  LIST_ENTRY                    *DriverInfoList;\r
+} MEMORY_PROFILE_CONTEXT_DATA;\r
+\r
+typedef struct {\r
+  UINT32                        Signature;\r
+  MEMORY_PROFILE_DRIVER_INFO    DriverInfo;\r
+  LIST_ENTRY                    *AllocInfoList;\r
+  LIST_ENTRY                    Link;\r
+} MEMORY_PROFILE_DRIVER_INFO_DATA;\r
+\r
+typedef struct {\r
+  UINT32                        Signature;\r
+  MEMORY_PROFILE_ALLOC_INFO     AllocInfo;\r
+  LIST_ENTRY                    Link;\r
+} MEMORY_PROFILE_ALLOC_INFO_DATA;\r
+\r
+//\r
+// When free memory less than 4 pages, dump it.\r
+//\r
+#define SMRAM_INFO_DUMP_PAGE_THRESHOLD  4\r
+\r
+GLOBAL_REMOVE_IF_UNREFERENCED MEMORY_PROFILE_FREE_MEMORY mSmramFreeMemory = {\r
+  {\r
+    MEMORY_PROFILE_FREE_MEMORY_SIGNATURE,\r
+    sizeof (MEMORY_PROFILE_FREE_MEMORY),\r
+    MEMORY_PROFILE_FREE_MEMORY_REVISION\r
+  },\r
+  0,\r
+  0\r
+};\r
+\r
+GLOBAL_REMOVE_IF_UNREFERENCED LIST_ENTRY  mImageQueue = INITIALIZE_LIST_HEAD_VARIABLE (mImageQueue);\r
+GLOBAL_REMOVE_IF_UNREFERENCED MEMORY_PROFILE_CONTEXT_DATA mSmramProfileContext = {\r
+  MEMORY_PROFILE_CONTEXT_SIGNATURE,\r
+  {\r
+    {\r
+      MEMORY_PROFILE_CONTEXT_SIGNATURE,\r
+      sizeof (MEMORY_PROFILE_CONTEXT),\r
+      MEMORY_PROFILE_CONTEXT_REVISION\r
+    },\r
+    0,\r
+    0,\r
+    {0},\r
+    {0},\r
+    0,\r
+    0,\r
+    0\r
+  },\r
+  &mImageQueue,\r
+};\r
+GLOBAL_REMOVE_IF_UNREFERENCED MEMORY_PROFILE_CONTEXT_DATA *mSmramProfileContextPtr;\r
+\r
+BOOLEAN mSmramReadyToLock;\r
+BOOLEAN mSmramProfileRecordingStatus = FALSE;\r
+\r
+/**\r
+  Return SMRAM profile context.\r
+\r
+  @return SMRAM profile context.\r
+\r
+**/\r
+MEMORY_PROFILE_CONTEXT_DATA *\r
+GetSmramProfileContext (\r
+  VOID\r
+  )\r
+{\r
+  return mSmramProfileContextPtr;\r
+}\r
+\r
+/**\r
+  Retrieves the magic value from the PE/COFF header.\r
+\r
+  @param Hdr    The buffer in which to return the PE32, PE32+, or TE header.\r
+\r
+  @return EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC - Image is PE32\r
+  @return EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC - Image is PE32+\r
+\r
+**/\r
+UINT16\r
+InternalPeCoffGetPeHeaderMagicValue (\r
+  IN  EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION  Hdr\r
+  )\r
+{\r
+  //\r
+  // NOTE: Some versions of Linux ELILO for Itanium have an incorrect magic value\r
+  //       in the PE/COFF Header.  If the MachineType is Itanium(IA64) and the\r
+  //       Magic value in the OptionalHeader is  EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC\r
+  //       then override the returned value to EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC\r
+  //\r
+  if (Hdr.Pe32->FileHeader.Machine == IMAGE_FILE_MACHINE_IA64 && Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+    return EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;\r
+  }\r
+  //\r
+  // Return the magic value from the PC/COFF Optional Header\r
+  //\r
+  return Hdr.Pe32->OptionalHeader.Magic;\r
+}\r
+\r
+/**\r
+  Retrieves and returns the Subsystem of a PE/COFF image that has been loaded into system memory.\r
+  If Pe32Data is NULL, then ASSERT().\r
+\r
+  @param Pe32Data   The pointer to the PE/COFF image that is loaded in system memory.\r
+\r
+  @return The Subsystem of the PE/COFF image.\r
+\r
+**/\r
+UINT16\r
+InternalPeCoffGetSubsystem (\r
+  IN VOID  *Pe32Data\r
+  )\r
+{\r
+  EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION  Hdr;\r
+  EFI_IMAGE_DOS_HEADER                 *DosHdr;\r
+  UINT16                               Magic;\r
+\r
+  ASSERT (Pe32Data != NULL);\r
+\r
+  DosHdr = (EFI_IMAGE_DOS_HEADER *) Pe32Data;\r
+  if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {\r
+    //\r
+    // DOS image header is present, so read the PE header after the DOS image header.\r
+    //\r
+    Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *) ((UINTN) Pe32Data + (UINTN) ((DosHdr->e_lfanew) & 0x0ffff));\r
+  } else {\r
+    //\r
+    // DOS image header is not present, so PE header is at the image base.\r
+    //\r
+    Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *) Pe32Data;\r
+  }\r
+\r
+  if (Hdr.Te->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {\r
+    return Hdr.Te->Subsystem;\r
+  } else if (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE)  {\r
+    Magic = InternalPeCoffGetPeHeaderMagicValue (Hdr);\r
+    if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+      return Hdr.Pe32->OptionalHeader.Subsystem;\r
+    } else if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {\r
+      return Hdr.Pe32Plus->OptionalHeader.Subsystem;\r
+    }\r
+  }\r
+\r
+  return 0x0000;\r
+}\r
+\r
+/**\r
+  Retrieves and returns a pointer to the entry point to a PE/COFF image that has been loaded\r
+  into system memory with the PE/COFF Loader Library functions.\r
+\r
+  Retrieves the entry point to the PE/COFF image specified by Pe32Data and returns this entry\r
+  point in EntryPoint.  If the entry point could not be retrieved from the PE/COFF image, then\r
+  return RETURN_INVALID_PARAMETER.  Otherwise return RETURN_SUCCESS.\r
+  If Pe32Data is NULL, then ASSERT().\r
+  If EntryPoint is NULL, then ASSERT().\r
+\r
+  @param  Pe32Data                  The pointer to the PE/COFF image that is loaded in system memory.\r
+  @param  EntryPoint                The pointer to entry point to the PE/COFF image to return.\r
+\r
+  @retval RETURN_SUCCESS            EntryPoint was returned.\r
+  @retval RETURN_INVALID_PARAMETER  The entry point could not be found in the PE/COFF image.\r
+\r
+**/\r
+RETURN_STATUS\r
+InternalPeCoffGetEntryPoint (\r
+  IN  VOID  *Pe32Data,\r
+  OUT VOID  **EntryPoint\r
+  )\r
+{\r
+  EFI_IMAGE_DOS_HEADER                  *DosHdr;\r
+  EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION   Hdr;\r
+\r
+  ASSERT (Pe32Data   != NULL);\r
+  ASSERT (EntryPoint != NULL);\r
+\r
+  DosHdr = (EFI_IMAGE_DOS_HEADER *) Pe32Data;\r
+  if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {\r
+    //\r
+    // DOS image header is present, so read the PE header after the DOS image header.\r
+    //\r
+    Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *) ((UINTN) Pe32Data + (UINTN) ((DosHdr->e_lfanew) & 0x0ffff));\r
+  } else {\r
+    //\r
+    // DOS image header is not present, so PE header is at the image base.\r
+    //\r
+    Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *) Pe32Data;\r
+  }\r
+\r
+  //\r
+  // Calculate the entry point relative to the start of the image.\r
+  // AddressOfEntryPoint is common for PE32 & PE32+\r
+  //\r
+  if (Hdr.Te->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {\r
+    *EntryPoint = (VOID *) ((UINTN) Pe32Data + (UINTN) (Hdr.Te->AddressOfEntryPoint & 0x0ffffffff) + sizeof (EFI_TE_IMAGE_HEADER) - Hdr.Te->StrippedSize);\r
+    return RETURN_SUCCESS;\r
+  } else if (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE) {\r
+    *EntryPoint = (VOID *) ((UINTN) Pe32Data + (UINTN) (Hdr.Pe32->OptionalHeader.AddressOfEntryPoint & 0x0ffffffff));\r
+    return RETURN_SUCCESS;\r
+  }\r
+\r
+  return RETURN_UNSUPPORTED;\r
+}\r
+\r
+/**\r
+  Build driver info.\r
+\r
+  @param ContextData    Memory profile context.\r
+  @param FileName       File name of the image.\r
+  @param ImageBase      Image base address.\r
+  @param ImageSize      Image size.\r
+  @param EntryPoint     Entry point of the image.\r
+  @param ImageSubsystem Image subsystem of the image.\r
+\r
+  @param FileType       File type of the image.\r
+\r
+  @return Pointer to memory profile driver info.\r
+\r
+**/\r
+MEMORY_PROFILE_DRIVER_INFO_DATA *\r
+BuildDriverInfo (\r
+  IN MEMORY_PROFILE_CONTEXT_DATA    *ContextData,\r
+  IN EFI_GUID                       *FileName,\r
+  IN PHYSICAL_ADDRESS               ImageBase,\r
+  IN UINT64                         ImageSize,\r
+  IN PHYSICAL_ADDRESS               EntryPoint,\r
+  IN UINT16                         ImageSubsystem,\r
+  IN EFI_FV_FILETYPE                FileType\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+  MEMORY_PROFILE_DRIVER_INFO        *DriverInfo;\r
+  MEMORY_PROFILE_DRIVER_INFO_DATA   *DriverInfoData;\r
+  VOID                              *EntryPointInImage;\r
+\r
+  //\r
+  // Use SmmInternalAllocatePool() that will not update profile for this AllocatePool action.\r
+  //\r
+  Status = SmmInternalAllocatePool (\r
+             EfiRuntimeServicesData,\r
+             sizeof (*DriverInfoData) + sizeof (LIST_ENTRY),\r
+             (VOID **) &DriverInfoData\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    return NULL;\r
+  }\r
+\r
+  ZeroMem (DriverInfoData, sizeof (*DriverInfoData));\r
+\r
+  DriverInfo = &DriverInfoData->DriverInfo;\r
+  DriverInfoData->Signature = MEMORY_PROFILE_DRIVER_INFO_SIGNATURE;\r
+  DriverInfo->Header.Signature = MEMORY_PROFILE_DRIVER_INFO_SIGNATURE;\r
+  DriverInfo->Header.Length = sizeof (MEMORY_PROFILE_DRIVER_INFO);\r
+  DriverInfo->Header.Revision = MEMORY_PROFILE_DRIVER_INFO_REVISION;\r
+  if (FileName != NULL) {\r
+    CopyMem (&DriverInfo->FileName, FileName, sizeof (EFI_GUID));\r
+  }\r
+  DriverInfo->ImageBase = ImageBase;\r
+  DriverInfo->ImageSize = ImageSize;\r
+  DriverInfo->EntryPoint = EntryPoint;\r
+  DriverInfo->ImageSubsystem = ImageSubsystem;\r
+  if ((EntryPoint != 0) && ((EntryPoint < ImageBase) || (EntryPoint >= (ImageBase + ImageSize)))) {\r
+    //\r
+    // If the EntryPoint is not in the range of image buffer, it should come from emulation environment.\r
+    // So patch ImageBuffer here to align the EntryPoint.\r
+    //\r
+    Status = InternalPeCoffGetEntryPoint ((VOID *) (UINTN) ImageBase, &EntryPointInImage);\r
+    ASSERT_EFI_ERROR (Status);\r
+    DriverInfo->ImageBase = ImageBase + EntryPoint - (PHYSICAL_ADDRESS) (UINTN) EntryPointInImage;\r
+  }\r
+  DriverInfo->FileType = FileType;\r
+  DriverInfoData->AllocInfoList = (LIST_ENTRY *) (DriverInfoData + 1);\r
+  InitializeListHead (DriverInfoData->AllocInfoList);\r
+  DriverInfo->CurrentUsage = 0;\r
+  DriverInfo->PeakUsage = 0;\r
+  DriverInfo->AllocRecordCount = 0;\r
+\r
+  InsertTailList (ContextData->DriverInfoList, &DriverInfoData->Link);\r
+  ContextData->Context.ImageCount ++;\r
+  ContextData->Context.TotalImageSize += DriverInfo->ImageSize;\r
+\r
+  return DriverInfoData;\r
+}\r
+\r
+/**\r
+  Register image to DXE.\r
+\r
+  @param FileName       File name of the image.\r
+  @param ImageBase      Image base address.\r
+  @param ImageSize      Image size.\r
+  @param FileType       File type of the image.\r
+\r
+**/\r
+VOID\r
+RegisterImageToDxe (\r
+  IN EFI_GUID                       *FileName,\r
+  IN PHYSICAL_ADDRESS               ImageBase,\r
+  IN UINT64                         ImageSize,\r
+  IN EFI_FV_FILETYPE                FileType\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+  EDKII_MEMORY_PROFILE_PROTOCOL     *ProfileProtocol;\r
+  MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FilePath;\r
+  UINT8                             TempBuffer[sizeof (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH) + sizeof (EFI_DEVICE_PATH_PROTOCOL)];\r
+\r
+  if (IS_SMRAM_PROFILE_ENABLED) {\r
+\r
+    FilePath = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *)TempBuffer;\r
+    Status = gBS->LocateProtocol (&gEdkiiMemoryProfileGuid, NULL, (VOID **) &ProfileProtocol);\r
+    if (!EFI_ERROR (Status)) {\r
+      EfiInitializeFwVolDevicepathNode (FilePath, FileName);\r
+      SetDevicePathEndNode (FilePath + 1);\r
+\r
+      Status = ProfileProtocol->RegisterImage (\r
+                                  ProfileProtocol,\r
+                                  (EFI_DEVICE_PATH_PROTOCOL *) FilePath,\r
+                                  ImageBase,\r
+                                  ImageSize,\r
+                                  FileType\r
+                                  );\r
+    }\r
+  }\r
+}\r
+\r
+/**\r
+  Unregister image from DXE.\r
+\r
+  @param FileName       File name of the image.\r
+  @param ImageBase      Image base address.\r
+  @param ImageSize      Image size.\r
+\r
+**/\r
+VOID\r
+UnregisterImageFromDxe (\r
+  IN EFI_GUID                       *FileName,\r
+  IN PHYSICAL_ADDRESS               ImageBase,\r
+  IN UINT64                         ImageSize\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+  EDKII_MEMORY_PROFILE_PROTOCOL     *ProfileProtocol;\r
+  MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FilePath;\r
+  UINT8                             TempBuffer[sizeof (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH) + sizeof (EFI_DEVICE_PATH_PROTOCOL)];\r
+\r
+  if (IS_SMRAM_PROFILE_ENABLED) {\r
+\r
+    FilePath = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *)TempBuffer;\r
+    Status = gBS->LocateProtocol (&gEdkiiMemoryProfileGuid, NULL, (VOID *) &ProfileProtocol);\r
+    if (!EFI_ERROR (Status)) {\r
+      EfiInitializeFwVolDevicepathNode (FilePath, FileName);\r
+      SetDevicePathEndNode (FilePath + 1);\r
+\r
+      Status = ProfileProtocol->UnregisterImage (\r
+                                  ProfileProtocol,\r
+                                  (EFI_DEVICE_PATH_PROTOCOL *) FilePath,\r
+                                  ImageBase,\r
+                                  ImageSize\r
+                                  );\r
+    }\r
+  }\r
+}\r
+\r
+/**\r
+  Register SMM Core to SMRAM profile.\r
+\r
+  @param ContextData    SMRAM profile context.\r
+\r
+  @retval TRUE          Register success.\r
+  @retval FALSE         Register fail.\r
+\r
+**/\r
+BOOLEAN\r
+RegisterSmmCore (\r
+  IN MEMORY_PROFILE_CONTEXT_DATA    *ContextData\r
+  )\r
+{\r
+  MEMORY_PROFILE_DRIVER_INFO_DATA   *DriverInfoData;\r
+  PHYSICAL_ADDRESS                  ImageBase;\r
+\r
+  ASSERT (ContextData != NULL);\r
+\r
+  RegisterImageToDxe (\r
+    &gEfiCallerIdGuid,\r
+    gSmmCorePrivate->PiSmmCoreImageBase,\r
+    gSmmCorePrivate->PiSmmCoreImageSize,\r
+    EFI_FV_FILETYPE_SMM_CORE\r
+    );\r
+\r
+  ImageBase = gSmmCorePrivate->PiSmmCoreImageBase;\r
+  DriverInfoData = BuildDriverInfo (\r
+                     ContextData,\r
+                     &gEfiCallerIdGuid,\r
+                     ImageBase,\r
+                     gSmmCorePrivate->PiSmmCoreImageSize,\r
+                     gSmmCorePrivate->PiSmmCoreEntryPoint,\r
+                     InternalPeCoffGetSubsystem ((VOID *) (UINTN) ImageBase),\r
+                     EFI_FV_FILETYPE_SMM_CORE\r
+                     );\r
+  if (DriverInfoData == NULL) {\r
+    return FALSE;\r
+  }\r
+\r
+  return TRUE;\r
+}\r
+\r
+/**\r
+  Initialize SMRAM profile.\r
+\r
+**/\r
+VOID\r
+SmramProfileInit (\r
+  VOID\r
+  )\r
+{\r
+  MEMORY_PROFILE_CONTEXT_DATA *SmramProfileContext;\r
+\r
+  if (!IS_SMRAM_PROFILE_ENABLED) {\r
+    return;\r
+  }\r
+\r
+  SmramProfileContext = GetSmramProfileContext ();\r
+  if (SmramProfileContext != NULL) {\r
+    return;\r
+  }\r
+\r
+  mSmramProfileRecordingStatus = TRUE;\r
+  mSmramProfileContextPtr = &mSmramProfileContext;\r
+\r
+  RegisterSmmCore (&mSmramProfileContext);\r
+\r
+  DEBUG ((EFI_D_INFO, "SmramProfileInit SmramProfileContext - 0x%x\n", &mSmramProfileContext));\r
+}\r
+\r
+/**\r
+  Register SMM image to SMRAM profile.\r
+\r
+  @param DriverEntry    SMM image info.\r
+  @param RegisterToDxe  Register image to DXE.\r
+\r
+  @retval TRUE          Register success.\r
+  @retval FALSE         Register fail.\r
+\r
+**/\r
+BOOLEAN\r
+RegisterSmramProfileImage (\r
+  IN EFI_SMM_DRIVER_ENTRY   *DriverEntry,\r
+  IN BOOLEAN                RegisterToDxe\r
+  )\r
+{\r
+  MEMORY_PROFILE_CONTEXT_DATA       *ContextData;\r
+  MEMORY_PROFILE_DRIVER_INFO_DATA   *DriverInfoData;\r
+\r
+  if (!IS_SMRAM_PROFILE_ENABLED) {\r
+    return FALSE;\r
+  }\r
+\r
+  if (RegisterToDxe) {\r
+    RegisterImageToDxe (\r
+      &DriverEntry->FileName,\r
+      DriverEntry->ImageBuffer,\r
+      EFI_PAGES_TO_SIZE (DriverEntry->NumberOfPage),\r
+      EFI_FV_FILETYPE_SMM\r
+      );\r
+  }\r
+\r
+  ContextData = GetSmramProfileContext ();\r
+  if (ContextData == NULL) {\r
+    return FALSE;\r
+  }\r
+\r
+  DriverInfoData = BuildDriverInfo (\r
+                     ContextData,\r
+                     &DriverEntry->FileName,\r
+                     DriverEntry->ImageBuffer,\r
+                     EFI_PAGES_TO_SIZE (DriverEntry->NumberOfPage),\r
+                     DriverEntry->ImageEntryPoint,\r
+                     InternalPeCoffGetSubsystem ((VOID *) (UINTN) DriverEntry->ImageBuffer),\r
+                     EFI_FV_FILETYPE_SMM\r
+                     );\r
+  if (DriverInfoData == NULL) {\r
+    return FALSE;\r
+  }\r
+\r
+  return TRUE;\r
+}\r
+\r
+/**\r
+  Search image from memory profile.\r
+\r
+  @param ContextData    Memory profile context.\r
+  @param FileName       Image file name.\r
+  @param Address        Image Address.\r
+\r
+  @return Pointer to memory profile driver info.\r
+\r
+**/\r
+MEMORY_PROFILE_DRIVER_INFO_DATA *\r
+GetMemoryProfileDriverInfoByFileNameAndAddress (\r
+  IN MEMORY_PROFILE_CONTEXT_DATA    *ContextData,\r
+  IN EFI_GUID                       *FileName,\r
+  IN PHYSICAL_ADDRESS               Address\r
+  )\r
+{\r
+  MEMORY_PROFILE_DRIVER_INFO        *DriverInfo;\r
+  MEMORY_PROFILE_DRIVER_INFO_DATA   *DriverInfoData;\r
+  LIST_ENTRY                        *DriverLink;\r
+  LIST_ENTRY                        *DriverInfoList;\r
+\r
+  DriverInfoList = ContextData->DriverInfoList;\r
+\r
+  for (DriverLink = DriverInfoList->ForwardLink;\r
+       DriverLink != DriverInfoList;\r
+       DriverLink = DriverLink->ForwardLink) {\r
+    DriverInfoData = CR (\r
+                       DriverLink,\r
+                       MEMORY_PROFILE_DRIVER_INFO_DATA,\r
+                       Link,\r
+                       MEMORY_PROFILE_DRIVER_INFO_SIGNATURE\r
+                       );\r
+    DriverInfo = &DriverInfoData->DriverInfo;\r
+    if ((CompareGuid (&DriverInfo->FileName, FileName)) &&\r
+        (Address >= DriverInfo->ImageBase) &&\r
+        (Address < (DriverInfo->ImageBase + DriverInfo->ImageSize))) {\r
+      return DriverInfoData;\r
+    }\r
+  }\r
+\r
+  return NULL;\r
+}\r
+\r
+/**\r
+  Search dummy image from SMRAM profile.\r
+\r
+  @param ContextData    Memory profile context.\r
+\r
+  @return Pointer to memory profile driver info.\r
+\r
+**/\r
+MEMORY_PROFILE_DRIVER_INFO_DATA *\r
+FindDummyImage (\r
+  IN MEMORY_PROFILE_CONTEXT_DATA    *ContextData\r
+  )\r
+{\r
+  MEMORY_PROFILE_DRIVER_INFO_DATA   *DriverInfoData;\r
+  LIST_ENTRY                        *DriverLink;\r
+  LIST_ENTRY                        *DriverInfoList;\r
+\r
+  DriverInfoList = ContextData->DriverInfoList;\r
+\r
+  for (DriverLink = DriverInfoList->ForwardLink;\r
+       DriverLink != DriverInfoList;\r
+       DriverLink = DriverLink->ForwardLink) {\r
+    DriverInfoData = CR (\r
+                   DriverLink,\r
+                   MEMORY_PROFILE_DRIVER_INFO_DATA,\r
+                   Link,\r
+                   MEMORY_PROFILE_DRIVER_INFO_SIGNATURE\r
+                   );\r
+    if (CompareGuid (&gZeroGuid, &DriverInfoData->DriverInfo.FileName)) {\r
+      return DriverInfoData;\r
+    }\r
+  }\r
+\r
+  return BuildDriverInfo (ContextData, &gZeroGuid, 0, 0, 0, 0, 0);\r
+}\r
+\r
+/**\r
+  Search image from memory profile.\r
+  It will return image, if (Address >= ImageBuffer) AND (Address < ImageBuffer + ImageSize)\r
+\r
+  @param ContextData    Memory profile context.\r
+  @param Address        Image or Function address.\r
+\r
+  @return Pointer to memory profile driver info.\r
+\r
+**/\r
+MEMORY_PROFILE_DRIVER_INFO_DATA *\r
+GetMemoryProfileDriverInfoFromAddress (\r
+  IN MEMORY_PROFILE_CONTEXT_DATA    *ContextData,\r
+  IN PHYSICAL_ADDRESS               Address\r
+  )\r
+{\r
+  MEMORY_PROFILE_DRIVER_INFO        *DriverInfo;\r
+  MEMORY_PROFILE_DRIVER_INFO_DATA   *DriverInfoData;\r
+  LIST_ENTRY                        *DriverLink;\r
+  LIST_ENTRY                        *DriverInfoList;\r
+\r
+  DriverInfoList = ContextData->DriverInfoList;\r
+\r
+  for (DriverLink = DriverInfoList->ForwardLink;\r
+       DriverLink != DriverInfoList;\r
+       DriverLink = DriverLink->ForwardLink) {\r
+    DriverInfoData = CR (\r
+                       DriverLink,\r
+                       MEMORY_PROFILE_DRIVER_INFO_DATA,\r
+                       Link,\r
+                       MEMORY_PROFILE_DRIVER_INFO_SIGNATURE\r
+                       );\r
+    DriverInfo = &DriverInfoData->DriverInfo;\r
+    if ((Address >= DriverInfo->ImageBase) &&\r
+        (Address < (DriverInfo->ImageBase + DriverInfo->ImageSize))) {\r
+      return DriverInfoData;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Should never come here.\r
+  //\r
+  return FindDummyImage (ContextData);\r
+}\r
+\r
+/**\r
+  Unregister image from SMRAM profile.\r
+\r
+  @param DriverEntry        SMM image info.\r
+  @param UnregisterFromDxe  Unregister image from DXE.\r
+\r
+  @retval TRUE              Unregister success.\r
+  @retval FALSE             Unregister fail.\r
+\r
+**/\r
+BOOLEAN\r
+UnregisterSmramProfileImage (\r
+  IN EFI_SMM_DRIVER_ENTRY  *DriverEntry,\r
+  IN BOOLEAN               UnregisterFromDxe\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+  MEMORY_PROFILE_CONTEXT_DATA       *ContextData;\r
+  MEMORY_PROFILE_DRIVER_INFO_DATA   *DriverInfoData;\r
+  EFI_GUID                          *FileName;\r
+  PHYSICAL_ADDRESS                  ImageAddress;\r
+  VOID                              *EntryPointInImage;\r
+\r
+  if (!IS_SMRAM_PROFILE_ENABLED) {\r
+    return FALSE;\r
+  }\r
+\r
+  if (UnregisterFromDxe) {\r
+    UnregisterImageFromDxe (\r
+      &DriverEntry->FileName,\r
+      DriverEntry->ImageBuffer,\r
+      EFI_PAGES_TO_SIZE (DriverEntry->NumberOfPage)\r
+      );\r
+  }\r
+\r
+  ContextData = GetSmramProfileContext ();\r
+  if (ContextData == NULL) {\r
+    return FALSE;\r
+  }\r
+\r
+  DriverInfoData = NULL;\r
+  FileName = &DriverEntry->FileName;\r
+  ImageAddress = DriverEntry->ImageBuffer;\r
+  if ((DriverEntry->ImageEntryPoint < ImageAddress) || (DriverEntry->ImageEntryPoint >= (ImageAddress + EFI_PAGES_TO_SIZE (DriverEntry->NumberOfPage)))) {\r
+    //\r
+    // If the EntryPoint is not in the range of image buffer, it should come from emulation environment.\r
+    // So patch ImageAddress here to align the EntryPoint.\r
+    //\r
+    Status = InternalPeCoffGetEntryPoint ((VOID *) (UINTN) ImageAddress, &EntryPointInImage);\r
+    ASSERT_EFI_ERROR (Status);\r
+    ImageAddress = ImageAddress + (UINTN) DriverEntry->ImageEntryPoint - (UINTN) EntryPointInImage;\r
+  }\r
+  if (FileName != NULL) {\r
+    DriverInfoData = GetMemoryProfileDriverInfoByFileNameAndAddress (ContextData, FileName, ImageAddress);\r
+  }\r
+  if (DriverInfoData == NULL) {\r
+    DriverInfoData = GetMemoryProfileDriverInfoFromAddress (ContextData, ImageAddress);\r
+  }\r
+  if (DriverInfoData == NULL) {\r
+    return FALSE;\r
+  }\r
+\r
+  ContextData->Context.TotalImageSize -= DriverInfoData->DriverInfo.ImageSize;\r
+\r
+  DriverInfoData->DriverInfo.ImageBase = 0;\r
+  DriverInfoData->DriverInfo.ImageSize = 0;\r
+\r
+  if (DriverInfoData->DriverInfo.PeakUsage == 0) {\r
+    ContextData->Context.ImageCount --;\r
+    RemoveEntryList (&DriverInfoData->Link);\r
+    //\r
+    // Use SmmInternalFreePool() that will not update profile for this FreePool action.\r
+    //\r
+    SmmInternalFreePool (DriverInfoData);\r
+  }\r
+\r
+  return TRUE;\r
+}\r
+\r
+/**\r
+  Return if this memory type needs to be recorded into memory profile.\r
+  If BIOS memory type (0 ~ EfiMaxMemoryType), it checks bit (1 << MemoryType).\r
+  If OS memory type (0x80000000 ~ 0xFFFFFFFF), it checks bit63 - 0x8000000000000000.\r
+\r
+  @param MemoryType     Memory type.\r
+\r
+  @retval TRUE          This memory type need to be recorded.\r
+  @retval FALSE         This memory type need not to be recorded.\r
+\r
+**/\r
+BOOLEAN\r
+SmmCoreNeedRecordProfile (\r
+  IN EFI_MEMORY_TYPE    MemoryType\r
+  )\r
+{\r
+  UINT64 TestBit;\r
+\r
+  if ((UINT32) MemoryType >= 0x80000000) {\r
+    TestBit = BIT63;\r
+  } else {\r
+    TestBit = LShiftU64 (1, MemoryType);\r
+  }\r
+\r
+  if ((PcdGet64 (PcdMemoryProfileMemoryType) & TestBit) != 0) {\r
+    return TRUE;\r
+  } else {\r
+    return FALSE;\r
+  }\r
+}\r
+\r
+/**\r
+  Convert EFI memory type to profile memory index. The rule is:\r
+  If BIOS memory type (0 ~ EfiMaxMemoryType), ProfileMemoryIndex = MemoryType.\r
+  If OS memory type (0x80000000 ~ 0xFFFFFFFF), ProfileMemoryIndex = EfiMaxMemoryType.\r
+\r
+  @param MemoryType     Memory type.\r
+\r
+  @return EFI memory type as profile memory index.\r
+\r
+**/\r
+EFI_MEMORY_TYPE\r
+GetProfileMemoryIndex (\r
+  IN EFI_MEMORY_TYPE    MemoryType\r
+  )\r
+{\r
+  if ((UINT32) MemoryType >= 0x80000000) {\r
+    return EfiMaxMemoryType;\r
+  } else {\r
+    return MemoryType;\r
+  }\r
+}\r
+\r
+/**\r
+  Update SMRAM profile FreeMemoryPages information\r
+\r
+  @param ContextData    Memory profile context.\r
+\r
+**/\r
+VOID\r
+SmramProfileUpdateFreePages (\r
+  IN MEMORY_PROFILE_CONTEXT_DATA  *ContextData\r
+  )\r
+{\r
+  LIST_ENTRY                      *Node;\r
+  FREE_PAGE_LIST                  *Pages;\r
+  LIST_ENTRY                      *FreePageList;\r
+  UINTN                           NumberOfPages;\r
+\r
+  NumberOfPages = 0;\r
+  FreePageList = &mSmmMemoryMap;\r
+  for (Node = FreePageList->BackLink;\r
+       Node != FreePageList;\r
+       Node = Node->BackLink) {\r
+    Pages = BASE_CR (Node, FREE_PAGE_LIST, Link);\r
+    NumberOfPages += Pages->NumberOfPages;\r
+  }\r
+\r
+  mSmramFreeMemory.TotalFreeMemoryPages = NumberOfPages;\r
+\r
+  if (NumberOfPages <= SMRAM_INFO_DUMP_PAGE_THRESHOLD) {\r
+    DumpSmramInfo ();\r
+  }\r
+}\r
+\r
+/**\r
+  Update SMRAM profile Allocate information.\r
+\r
+  @param CallerAddress  Address of caller who call Allocate.\r
+  @param Action         This Allocate action.\r
+  @param MemoryType     Memory type.\r
+  @param Size           Buffer size.\r
+  @param Buffer         Buffer address.\r
+\r
+  @retval TRUE          Profile udpate success.\r
+  @retval FALSE         Profile update fail.\r
+\r
+**/\r
+BOOLEAN\r
+SmmCoreUpdateProfileAllocate (\r
+  IN PHYSICAL_ADDRESS       CallerAddress,\r
+  IN MEMORY_PROFILE_ACTION  Action,\r
+  IN EFI_MEMORY_TYPE        MemoryType,\r
+  IN UINTN                  Size,\r
+  IN VOID                   *Buffer\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+  MEMORY_PROFILE_CONTEXT           *Context;\r
+  MEMORY_PROFILE_DRIVER_INFO       *DriverInfo;\r
+  MEMORY_PROFILE_ALLOC_INFO        *AllocInfo;\r
+  MEMORY_PROFILE_CONTEXT_DATA       *ContextData;\r
+  MEMORY_PROFILE_DRIVER_INFO_DATA   *DriverInfoData;\r
+  MEMORY_PROFILE_ALLOC_INFO_DATA    *AllocInfoData;\r
+  EFI_MEMORY_TYPE                   ProfileMemoryIndex;\r
+\r
+  ContextData = GetSmramProfileContext ();\r
+  if (ContextData == NULL) {\r
+    return FALSE;\r
+  }\r
+\r
+  DriverInfoData = GetMemoryProfileDriverInfoFromAddress (ContextData, CallerAddress);\r
+  ASSERT (DriverInfoData != NULL);\r
+\r
+  //\r
+  // Use SmmInternalAllocatePool() that will not update profile for this AllocatePool action.\r
+  //\r
+  Status = SmmInternalAllocatePool (\r
+             EfiRuntimeServicesData,\r
+             sizeof (*AllocInfoData),\r
+             (VOID **) &AllocInfoData\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    return FALSE;\r
+  }\r
+  AllocInfo = &AllocInfoData->AllocInfo;\r
+  AllocInfoData->Signature      = MEMORY_PROFILE_ALLOC_INFO_SIGNATURE;\r
+  AllocInfo->Header.Signature   = MEMORY_PROFILE_ALLOC_INFO_SIGNATURE;\r
+  AllocInfo->Header.Length      = sizeof (MEMORY_PROFILE_ALLOC_INFO);\r
+  AllocInfo->Header.Revision    = MEMORY_PROFILE_ALLOC_INFO_REVISION;\r
+  AllocInfo->CallerAddress      = CallerAddress;\r
+  AllocInfo->SequenceId         = ContextData->Context.SequenceCount;\r
+  AllocInfo->Action             = Action;\r
+  AllocInfo->MemoryType         = MemoryType;\r
+  AllocInfo->Buffer             = (PHYSICAL_ADDRESS) (UINTN) Buffer;\r
+  AllocInfo->Size               = Size;\r
+\r
+  InsertTailList (DriverInfoData->AllocInfoList, &AllocInfoData->Link);\r
+\r
+  ProfileMemoryIndex = GetProfileMemoryIndex (MemoryType);\r
+\r
+  DriverInfo = &DriverInfoData->DriverInfo;\r
+  DriverInfo->CurrentUsage += Size;\r
+  if (DriverInfo->PeakUsage < DriverInfo->CurrentUsage) {\r
+    DriverInfo->PeakUsage = DriverInfo->CurrentUsage;\r
+  }\r
+  DriverInfo->CurrentUsageByType[ProfileMemoryIndex] += Size;\r
+  if (DriverInfo->PeakUsageByType[ProfileMemoryIndex] < DriverInfo->CurrentUsageByType[ProfileMemoryIndex]) {\r
+    DriverInfo->PeakUsageByType[ProfileMemoryIndex] = DriverInfo->CurrentUsageByType[ProfileMemoryIndex];\r
+  }\r
+  DriverInfo->AllocRecordCount ++;\r
+\r
+  Context = &ContextData->Context;\r
+  Context->CurrentTotalUsage += Size;\r
+  if (Context->PeakTotalUsage < Context->CurrentTotalUsage) {\r
+    Context->PeakTotalUsage = Context->CurrentTotalUsage;\r
+  }\r
+  Context->CurrentTotalUsageByType[ProfileMemoryIndex] += Size;\r
+  if (Context->PeakTotalUsageByType[ProfileMemoryIndex] < Context->CurrentTotalUsageByType[ProfileMemoryIndex]) {\r
+    Context->PeakTotalUsageByType[ProfileMemoryIndex] = Context->CurrentTotalUsageByType[ProfileMemoryIndex];\r
+  }\r
+  Context->SequenceCount ++;\r
+\r
+  SmramProfileUpdateFreePages (ContextData);\r
+  return TRUE;\r
+}\r
+\r
+/**\r
+  Get memory profile alloc info from memory profile\r
+\r
+  @param DriverInfoData     Driver info\r
+  @param Action             This Free action\r
+  @param Size               Buffer size\r
+  @param Buffer             Buffer address\r
+\r
+  @return Pointer to memory profile alloc info.\r
+**/\r
+MEMORY_PROFILE_ALLOC_INFO_DATA *\r
+GetMemoryProfileAllocInfoFromAddress (\r
+  IN MEMORY_PROFILE_DRIVER_INFO_DATA    *DriverInfoData,\r
+  IN MEMORY_PROFILE_ACTION              Action,\r
+  IN UINTN                              Size,\r
+  IN VOID                               *Buffer\r
+  )\r
+{\r
+  LIST_ENTRY                        *AllocInfoList;\r
+  LIST_ENTRY                        *AllocLink;\r
+  MEMORY_PROFILE_ALLOC_INFO         *AllocInfo;\r
+  MEMORY_PROFILE_ALLOC_INFO_DATA    *AllocInfoData;\r
+\r
+  AllocInfoList = DriverInfoData->AllocInfoList;\r
+\r
+  for (AllocLink = AllocInfoList->ForwardLink;\r
+       AllocLink != AllocInfoList;\r
+       AllocLink = AllocLink->ForwardLink) {\r
+    AllocInfoData = CR (\r
+                      AllocLink,\r
+                      MEMORY_PROFILE_ALLOC_INFO_DATA,\r
+                      Link,\r
+                      MEMORY_PROFILE_ALLOC_INFO_SIGNATURE\r
+                      );\r
+    AllocInfo = &AllocInfoData->AllocInfo;\r
+    if (AllocInfo->Action != Action) {\r
+      continue;\r
+    }\r
+    switch (Action) {\r
+      case MemoryProfileActionAllocatePages:\r
+        if ((AllocInfo->Buffer <= (PHYSICAL_ADDRESS) (UINTN) Buffer) &&\r
+            ((AllocInfo->Buffer + AllocInfo->Size) >= ((PHYSICAL_ADDRESS) (UINTN) Buffer + Size))) {\r
+          return AllocInfoData;\r
+        }\r
+        break;\r
+      case MemoryProfileActionAllocatePool:\r
+        if (AllocInfo->Buffer == (PHYSICAL_ADDRESS) (UINTN) Buffer) {\r
+          return AllocInfoData;\r
+        }\r
+        break;\r
+      default:\r
+        ASSERT (FALSE);\r
+        break;\r
+    }\r
+  }\r
+\r
+  return NULL;\r
+}\r
+\r
+/**\r
+  Update SMRAM profile Free information.\r
+\r
+  @param CallerAddress  Address of caller who call Free.\r
+  @param Action         This Free action.\r
+  @param Size           Buffer size.\r
+  @param Buffer         Buffer address.\r
+\r
+  @retval TRUE          Profile udpate success.\r
+  @retval FALSE         Profile update fail.\r
+\r
+**/\r
+BOOLEAN\r
+SmmCoreUpdateProfileFree (\r
+  IN PHYSICAL_ADDRESS       CallerAddress,\r
+  IN MEMORY_PROFILE_ACTION  Action,\r
+  IN UINTN                  Size,\r
+  IN VOID                   *Buffer\r
+  )\r
+{\r
+  MEMORY_PROFILE_CONTEXT           *Context;\r
+  MEMORY_PROFILE_DRIVER_INFO       *DriverInfo;\r
+  MEMORY_PROFILE_ALLOC_INFO        *AllocInfo;\r
+  MEMORY_PROFILE_CONTEXT_DATA      *ContextData;\r
+  MEMORY_PROFILE_DRIVER_INFO_DATA  *DriverInfoData;\r
+  LIST_ENTRY                       *DriverLink;\r
+  LIST_ENTRY                       *DriverInfoList;\r
+  MEMORY_PROFILE_DRIVER_INFO_DATA  *ThisDriverInfoData;\r
+  MEMORY_PROFILE_ALLOC_INFO_DATA   *AllocInfoData;\r
+  EFI_MEMORY_TYPE                  ProfileMemoryIndex;\r
+\r
+  ContextData = GetSmramProfileContext ();\r
+  if (ContextData == NULL) {\r
+    return FALSE;\r
+  }\r
+\r
+  DriverInfoData = GetMemoryProfileDriverInfoFromAddress (ContextData, CallerAddress);\r
+  ASSERT (DriverInfoData != NULL);\r
+\r
+  switch (Action) {\r
+    case MemoryProfileActionFreePages:\r
+      AllocInfoData = GetMemoryProfileAllocInfoFromAddress (DriverInfoData, MemoryProfileActionAllocatePages, Size, Buffer);\r
+      break;\r
+    case MemoryProfileActionFreePool:\r
+      AllocInfoData = GetMemoryProfileAllocInfoFromAddress (DriverInfoData, MemoryProfileActionAllocatePool, 0, Buffer);\r
+      break;\r
+    default:\r
+      ASSERT (FALSE);\r
+      AllocInfoData = NULL;\r
+      break;\r
+  }\r
+  if (AllocInfoData == NULL) {\r
+    //\r
+    // Legal case, because driver A might free memory allocated by driver B, by some protocol.\r
+    //\r
+    DriverInfoList = ContextData->DriverInfoList;\r
+\r
+    for (DriverLink = DriverInfoList->ForwardLink;\r
+         DriverLink != DriverInfoList;\r
+         DriverLink = DriverLink->ForwardLink) {\r
+      ThisDriverInfoData = CR (\r
+                             DriverLink,\r
+                             MEMORY_PROFILE_DRIVER_INFO_DATA,\r
+                             Link,\r
+                             MEMORY_PROFILE_DRIVER_INFO_SIGNATURE\r
+                             );\r
+      switch (Action) {\r
+        case MemoryProfileActionFreePages:\r
+          AllocInfoData = GetMemoryProfileAllocInfoFromAddress (ThisDriverInfoData, MemoryProfileActionAllocatePages, Size, Buffer);\r
+          break;\r
+        case MemoryProfileActionFreePool:\r
+          AllocInfoData = GetMemoryProfileAllocInfoFromAddress (ThisDriverInfoData, MemoryProfileActionAllocatePool, 0, Buffer);\r
+          break;\r
+        default:\r
+          ASSERT (FALSE);\r
+          AllocInfoData = NULL;\r
+          break;\r
+      }\r
+      if (AllocInfoData != NULL) {\r
+        DriverInfoData = ThisDriverInfoData;\r
+        break;\r
+      }\r
+    }\r
+\r
+    if (AllocInfoData == NULL) {\r
+      //\r
+      // No matched allocate operation is found for this free operation.\r
+      // It is because the specified memory type allocate operation has been\r
+      // filtered by CoreNeedRecordProfile(), but free operations have no\r
+      // memory type information, they can not be filtered by CoreNeedRecordProfile().\r
+      // Then, they will be filtered here.\r
+      //\r
+      return FALSE;\r
+    }\r
+  }\r
+\r
+  Context = &ContextData->Context;\r
+  DriverInfo = &DriverInfoData->DriverInfo;\r
+  AllocInfo = &AllocInfoData->AllocInfo;\r
+\r
+  ProfileMemoryIndex = GetProfileMemoryIndex (AllocInfo->MemoryType);\r
+\r
+  Context->CurrentTotalUsage -= AllocInfo->Size;\r
+  Context->CurrentTotalUsageByType[ProfileMemoryIndex] -= AllocInfo->Size;\r
+\r
+  DriverInfo->CurrentUsage -= AllocInfo->Size;\r
+  DriverInfo->CurrentUsageByType[ProfileMemoryIndex] -= AllocInfo->Size;\r
+  DriverInfo->AllocRecordCount --;\r
+\r
+  RemoveEntryList (&AllocInfoData->Link);\r
+\r
+  if (Action == MemoryProfileActionFreePages) {\r
+    if (AllocInfo->Buffer != (PHYSICAL_ADDRESS) (UINTN) Buffer) {\r
+      SmmCoreUpdateProfileAllocate (\r
+        AllocInfo->CallerAddress,\r
+        MemoryProfileActionAllocatePages,\r
+        AllocInfo->MemoryType,\r
+        (UINTN) ((PHYSICAL_ADDRESS) (UINTN) Buffer - AllocInfo->Buffer),\r
+        (VOID *) (UINTN) AllocInfo->Buffer\r
+        );\r
+    }\r
+    if (AllocInfo->Buffer + AllocInfo->Size != ((PHYSICAL_ADDRESS) (UINTN) Buffer + Size)) {\r
+      SmmCoreUpdateProfileAllocate (\r
+        AllocInfo->CallerAddress,\r
+        MemoryProfileActionAllocatePages,\r
+        AllocInfo->MemoryType,\r
+        (UINTN) ((AllocInfo->Buffer + AllocInfo->Size) - ((PHYSICAL_ADDRESS) (UINTN) Buffer + Size)),\r
+        (VOID *) ((UINTN) Buffer + Size)\r
+        );\r
+    }\r
+  }\r
+\r
+  //\r
+  // Use SmmInternalFreePool() that will not update profile for this FreePool action.\r
+  //\r
+  SmmInternalFreePool (AllocInfoData);\r
+\r
+  return TRUE;\r
+}\r
+\r
+/**\r
+  Update SMRAM profile information.\r
+\r
+  @param CallerAddress  Address of caller who call Allocate or Free.\r
+  @param Action         This Allocate or Free action.\r
+  @param MemoryType     Memory type.\r
+  @param Size           Buffer size.\r
+  @param Buffer         Buffer address.\r
+\r
+  @retval TRUE          Profile udpate success.\r
+  @retval FALSE         Profile update fail.\r
+\r
+**/\r
+BOOLEAN\r
+SmmCoreUpdateProfile (\r
+  IN PHYSICAL_ADDRESS       CallerAddress,\r
+  IN MEMORY_PROFILE_ACTION  Action,\r
+  IN EFI_MEMORY_TYPE        MemoryType, // Valid for AllocatePages/AllocatePool\r
+  IN UINTN                  Size,       // Valid for AllocatePages/FreePages/AllocatePool\r
+  IN VOID                   *Buffer\r
+  )\r
+{\r
+  MEMORY_PROFILE_CONTEXT_DATA   *ContextData;\r
+\r
+  if (!IS_SMRAM_PROFILE_ENABLED) {\r
+    return FALSE;\r
+  }\r
+\r
+  if (!mSmramProfileRecordingStatus) {\r
+    return FALSE;\r
+  }\r
+\r
+  //\r
+  // Free operations have no memory type information, so skip the check.\r
+  //\r
+  if ((Action == MemoryProfileActionAllocatePages) || (Action == MemoryProfileActionAllocatePool)) {\r
+    //\r
+    // Only record limited MemoryType.\r
+    //\r
+    if (!SmmCoreNeedRecordProfile (MemoryType)) {\r
+      return FALSE;\r
+    }\r
+  }\r
+\r
+  ContextData = GetSmramProfileContext ();\r
+  if (ContextData == NULL) {\r
+    return FALSE;\r
+  }\r
+\r
+  switch (Action) {\r
+    case MemoryProfileActionAllocatePages:\r
+      SmmCoreUpdateProfileAllocate (CallerAddress, Action, MemoryType, Size, Buffer);\r
+      break;\r
+    case MemoryProfileActionFreePages:\r
+      SmmCoreUpdateProfileFree (CallerAddress, Action, Size, Buffer);\r
+      break;\r
+    case MemoryProfileActionAllocatePool:\r
+      SmmCoreUpdateProfileAllocate (CallerAddress, Action, MemoryType, Size, Buffer);\r
+      break;\r
+    case MemoryProfileActionFreePool:\r
+      SmmCoreUpdateProfileFree (CallerAddress, Action, 0, Buffer);\r
+      break;\r
+    default:\r
+      ASSERT (FALSE);\r
+      break;\r
+  }\r
+\r
+  return TRUE;\r
+}\r
+\r
+/**\r
+  SMRAM profile ready to lock callback function.\r
+\r
+**/\r
+VOID\r
+SmramProfileReadyToLock (\r
+  VOID\r
+  )\r
+{\r
+  if (!IS_SMRAM_PROFILE_ENABLED) {\r
+    return;\r
+  }\r
+\r
+  DEBUG ((EFI_D_INFO, "SmramProfileReadyToLock\n"));\r
+  mSmramReadyToLock = TRUE;\r
+}\r
+\r
+////////////////////\r
+\r
+/**\r
+  This function check if the address is in SMRAM.\r
+\r
+  @param Buffer  the buffer address to be checked.\r
+  @param Length  the buffer length to be checked.\r
+\r
+  @retval TRUE  this address is in SMRAM.\r
+  @retval FALSE this address is NOT in SMRAM.\r
+\r
+**/\r
+BOOLEAN\r
+InternalIsAddressInSmram (\r
+  IN PHYSICAL_ADDRESS   Buffer,\r
+  IN UINT64             Length\r
+  )\r
+{\r
+  UINTN  Index;\r
+\r
+  for (Index = 0; Index < mFullSmramRangeCount; Index ++) {\r
+    if (((Buffer >= mFullSmramRanges[Index].CpuStart) && (Buffer < mFullSmramRanges[Index].CpuStart + mFullSmramRanges[Index].PhysicalSize)) ||\r
+        ((mFullSmramRanges[Index].CpuStart >= Buffer) && (mFullSmramRanges[Index].CpuStart < Buffer + Length))) {\r
+      return TRUE;\r
+    }\r
+  }\r
+\r
+  return FALSE;\r
+}\r
+\r
+/**\r
+  This function check if the address refered by Buffer and Length is valid.\r
+\r
+  @param Buffer  the buffer address to be checked.\r
+  @param Length  the buffer length to be checked.\r
+\r
+  @retval TRUE  this address is valid.\r
+  @retval FALSE this address is NOT valid.\r
+**/\r
+BOOLEAN\r
+InternalIsAddressValid (\r
+  IN UINTN                 Buffer,\r
+  IN UINTN                 Length\r
+  )\r
+{\r
+  if (Buffer > (MAX_ADDRESS - Length)) {\r
+    //\r
+    // Overflow happen\r
+    //\r
+    return FALSE;\r
+  }\r
+  if (InternalIsAddressInSmram ((PHYSICAL_ADDRESS) Buffer, (UINT64)Length)) {\r
+    return FALSE;\r
+  }\r
+  return TRUE;\r
+}\r
+\r
+/**\r
+  Get SMRAM profile data size.\r
+\r
+  @return SMRAM profile data size.\r
+\r
+**/\r
+UINTN\r
+SmramProfileGetDataSize (\r
+  VOID\r
+  )\r
+{\r
+  MEMORY_PROFILE_CONTEXT_DATA      *ContextData;\r
+  MEMORY_PROFILE_DRIVER_INFO_DATA  *DriverInfoData;\r
+  LIST_ENTRY                      *DriverInfoList;\r
+  LIST_ENTRY                      *DriverLink;\r
+  UINTN                           TotalSize;\r
+  LIST_ENTRY                      *Node;\r
+  LIST_ENTRY                      *FreePageList;\r
+  LIST_ENTRY                      *FreePoolList;\r
+  FREE_POOL_HEADER                *Pool;\r
+  UINTN                           PoolListIndex;\r
+  UINTN                           Index;\r
+\r
+  ContextData = GetSmramProfileContext ();\r
+  if (ContextData == NULL) {\r
+    return 0;\r
+  }\r
+\r
+  TotalSize = sizeof (MEMORY_PROFILE_CONTEXT);\r
+  TotalSize += sizeof (MEMORY_PROFILE_DRIVER_INFO) * (UINTN) ContextData->Context.ImageCount;\r
+\r
+  DriverInfoList = ContextData->DriverInfoList;\r
+  for (DriverLink = DriverInfoList->ForwardLink;\r
+       DriverLink != DriverInfoList;\r
+       DriverLink = DriverLink->ForwardLink) {\r
+    DriverInfoData = CR (\r
+                   DriverLink,\r
+                   MEMORY_PROFILE_DRIVER_INFO_DATA,\r
+                   Link,\r
+                   MEMORY_PROFILE_DRIVER_INFO_SIGNATURE\r
+                   );\r
+    TotalSize += sizeof (MEMORY_PROFILE_ALLOC_INFO) * (UINTN) DriverInfoData->DriverInfo.AllocRecordCount;\r
+  }\r
+\r
+\r
+  Index = 0;\r
+  FreePageList = &mSmmMemoryMap;\r
+  for (Node = FreePageList->BackLink;\r
+       Node != FreePageList;\r
+       Node = Node->BackLink) {\r
+    Index++;\r
+  }\r
+  for (PoolListIndex = 0; PoolListIndex < MAX_POOL_INDEX; PoolListIndex++) {\r
+    FreePoolList = &mSmmPoolLists[PoolListIndex];\r
+    for (Node = FreePoolList->BackLink;\r
+         Node != FreePoolList;\r
+         Node = Node->BackLink) {\r
+      Pool = BASE_CR (Node, FREE_POOL_HEADER, Link);\r
+      if (Pool->Header.Available) {\r
+        Index++;\r
+      }\r
+    }\r
+  }\r
+\r
+\r
+  TotalSize += (sizeof (MEMORY_PROFILE_FREE_MEMORY) + Index * sizeof (MEMORY_PROFILE_DESCRIPTOR));\r
+  TotalSize += (sizeof (MEMORY_PROFILE_MEMORY_RANGE) + mFullSmramRangeCount * sizeof (MEMORY_PROFILE_DESCRIPTOR));\r
+\r
+  return TotalSize;\r
+}\r
+\r
+/**\r
+  Copy SMRAM profile data.\r
+\r
+  @param ProfileBuffer  The buffer to hold SMRAM profile data.\r
+\r
+**/\r
+VOID\r
+SmramProfileCopyData (\r
+  IN VOID   *ProfileBuffer\r
+  )\r
+{\r
+  MEMORY_PROFILE_CONTEXT           *Context;\r
+  MEMORY_PROFILE_DRIVER_INFO       *DriverInfo;\r
+  MEMORY_PROFILE_ALLOC_INFO        *AllocInfo;\r
+  MEMORY_PROFILE_CONTEXT_DATA      *ContextData;\r
+  MEMORY_PROFILE_DRIVER_INFO_DATA  *DriverInfoData;\r
+  MEMORY_PROFILE_ALLOC_INFO_DATA   *AllocInfoData;\r
+  LIST_ENTRY                      *DriverInfoList;\r
+  LIST_ENTRY                      *DriverLink;\r
+  LIST_ENTRY                      *AllocInfoList;\r
+  LIST_ENTRY                      *AllocLink;\r
+  LIST_ENTRY                      *Node;\r
+  FREE_PAGE_LIST                  *Pages;\r
+  LIST_ENTRY                      *FreePageList;\r
+  LIST_ENTRY                      *FreePoolList;\r
+  FREE_POOL_HEADER                *Pool;\r
+  UINTN                           PoolListIndex;\r
+  UINT32                          Index;\r
+  MEMORY_PROFILE_FREE_MEMORY      *FreeMemory;\r
+  MEMORY_PROFILE_MEMORY_RANGE     *MemoryRange;\r
+  MEMORY_PROFILE_DESCRIPTOR       *MemoryProfileDescriptor;\r
+\r
+  ContextData = GetSmramProfileContext ();\r
+  if (ContextData == NULL) {\r
+    return ;\r
+  }\r
+\r
+  Context = ProfileBuffer;\r
+  CopyMem (Context, &ContextData->Context, sizeof (MEMORY_PROFILE_CONTEXT));\r
+  DriverInfo = (MEMORY_PROFILE_DRIVER_INFO *) (Context + 1);\r
+\r
+  DriverInfoList = ContextData->DriverInfoList;\r
+  for (DriverLink = DriverInfoList->ForwardLink;\r
+       DriverLink != DriverInfoList;\r
+       DriverLink = DriverLink->ForwardLink) {\r
+    DriverInfoData = CR (\r
+                       DriverLink,\r
+                       MEMORY_PROFILE_DRIVER_INFO_DATA,\r
+                       Link,\r
+                       MEMORY_PROFILE_DRIVER_INFO_SIGNATURE\r
+                       );\r
+    CopyMem (DriverInfo, &DriverInfoData->DriverInfo, sizeof (MEMORY_PROFILE_DRIVER_INFO));\r
+    AllocInfo = (MEMORY_PROFILE_ALLOC_INFO *) (DriverInfo + 1);\r
+\r
+    AllocInfoList = DriverInfoData->AllocInfoList;\r
+    for (AllocLink = AllocInfoList->ForwardLink;\r
+         AllocLink != AllocInfoList;\r
+         AllocLink = AllocLink->ForwardLink) {\r
+      AllocInfoData = CR (\r
+                        AllocLink,\r
+                        MEMORY_PROFILE_ALLOC_INFO_DATA,\r
+                        Link,\r
+                        MEMORY_PROFILE_ALLOC_INFO_SIGNATURE\r
+                        );\r
+      CopyMem (AllocInfo, &AllocInfoData->AllocInfo, sizeof (MEMORY_PROFILE_ALLOC_INFO));\r
+      AllocInfo += 1;\r
+    }\r
+\r
+    DriverInfo = (MEMORY_PROFILE_DRIVER_INFO *) ((UINTN) (DriverInfo + 1) + sizeof (MEMORY_PROFILE_ALLOC_INFO) * (UINTN) DriverInfo->AllocRecordCount);\r
+  }\r
+\r
+\r
+  FreeMemory = (MEMORY_PROFILE_FREE_MEMORY *) DriverInfo;\r
+  CopyMem (FreeMemory, &mSmramFreeMemory, sizeof (MEMORY_PROFILE_FREE_MEMORY));\r
+  MemoryProfileDescriptor = (MEMORY_PROFILE_DESCRIPTOR *) (FreeMemory + 1);\r
+  Index = 0;\r
+  FreePageList = &mSmmMemoryMap;\r
+  for (Node = FreePageList->BackLink;\r
+       Node != FreePageList;\r
+       Node = Node->BackLink) {\r
+    Pages = BASE_CR (Node, FREE_PAGE_LIST, Link);\r
+    MemoryProfileDescriptor->Header.Signature = MEMORY_PROFILE_DESCRIPTOR_SIGNATURE;\r
+    MemoryProfileDescriptor->Header.Length = sizeof (MEMORY_PROFILE_DESCRIPTOR);\r
+    MemoryProfileDescriptor->Header.Revision = MEMORY_PROFILE_DESCRIPTOR_REVISION;\r
+    MemoryProfileDescriptor->Address = (PHYSICAL_ADDRESS) (UINTN) Pages;\r
+    MemoryProfileDescriptor->Size = EFI_PAGES_TO_SIZE (Pages->NumberOfPages);\r
+    MemoryProfileDescriptor++;\r
+    Index++;\r
+  }\r
+  for (PoolListIndex = 0; PoolListIndex < MAX_POOL_INDEX; PoolListIndex++) {\r
+    FreePoolList = &mSmmPoolLists[MAX_POOL_INDEX - PoolListIndex - 1];\r
+    for (Node = FreePoolList->BackLink;\r
+         Node != FreePoolList;\r
+         Node = Node->BackLink) {\r
+      Pool = BASE_CR (Node, FREE_POOL_HEADER, Link);\r
+      if (Pool->Header.Available) {\r
+        MemoryProfileDescriptor->Header.Signature = MEMORY_PROFILE_DESCRIPTOR_SIGNATURE;\r
+        MemoryProfileDescriptor->Header.Length = sizeof (MEMORY_PROFILE_DESCRIPTOR);\r
+        MemoryProfileDescriptor->Header.Revision = MEMORY_PROFILE_DESCRIPTOR_REVISION;\r
+        MemoryProfileDescriptor->Address = (PHYSICAL_ADDRESS) (UINTN) Pool;\r
+        MemoryProfileDescriptor->Size = Pool->Header.Size;\r
+        MemoryProfileDescriptor++;\r
+        Index++;\r
+      }\r
+    }\r
+  }\r
+  FreeMemory->FreeMemoryEntryCount = Index;\r
+\r
+  MemoryRange = (MEMORY_PROFILE_MEMORY_RANGE *) MemoryProfileDescriptor;\r
+  MemoryRange->Header.Signature = MEMORY_PROFILE_MEMORY_RANGE_SIGNATURE;\r
+  MemoryRange->Header.Length = sizeof (MEMORY_PROFILE_MEMORY_RANGE);\r
+  MemoryRange->Header.Revision = MEMORY_PROFILE_MEMORY_RANGE_REVISION;\r
+  MemoryRange->MemoryRangeCount = (UINT32) mFullSmramRangeCount;\r
+  MemoryProfileDescriptor = (MEMORY_PROFILE_DESCRIPTOR *) (MemoryRange + 1);\r
+  for (Index = 0; Index < mFullSmramRangeCount; Index++) {\r
+    MemoryProfileDescriptor->Header.Signature = MEMORY_PROFILE_DESCRIPTOR_SIGNATURE;\r
+    MemoryProfileDescriptor->Header.Length = sizeof (MEMORY_PROFILE_DESCRIPTOR);\r
+    MemoryProfileDescriptor->Header.Revision = MEMORY_PROFILE_DESCRIPTOR_REVISION;\r
+    MemoryProfileDescriptor->Address = mFullSmramRanges[Index].PhysicalStart;\r
+    MemoryProfileDescriptor->Size = mFullSmramRanges[Index].PhysicalSize;\r
+    MemoryProfileDescriptor++; \r
+  }\r
+}\r
+\r
+/**\r
+  SMRAM profile handler to get profile info.\r
+\r
+  @param SmramProfileParameterGetInfo The parameter of SMM profile get size.\r
+\r
+**/\r
+VOID\r
+SmramProfileHandlerGetInfo (\r
+  IN SMRAM_PROFILE_PARAMETER_GET_PROFILE_INFO   *SmramProfileParameterGetInfo\r
+  )\r
+{\r
+  MEMORY_PROFILE_CONTEXT_DATA   *ContextData;\r
+  BOOLEAN                       SmramProfileRecordingStatus;\r
+\r
+  ContextData = GetSmramProfileContext ();\r
+  if (ContextData == NULL) {\r
+    return ;\r
+  }\r
+\r
+  SmramProfileRecordingStatus = mSmramProfileRecordingStatus;\r
+  mSmramProfileRecordingStatus = FALSE;\r
+\r
+  SmramProfileParameterGetInfo->ProfileSize = SmramProfileGetDataSize();\r
+  SmramProfileParameterGetInfo->Header.ReturnStatus = 0;\r
+\r
+  mSmramProfileRecordingStatus = SmramProfileRecordingStatus;\r
+}\r
+\r
+/**\r
+  SMRAM profile handler to get profile data.\r
+\r
+  @param SmramProfileParameterGetData The parameter of SMM profile get data.\r
+\r
+**/\r
+VOID\r
+SmramProfileHandlerGetData (\r
+  IN SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA   *SmramProfileParameterGetData\r
+  )\r
+{\r
+  UINT64                                    ProfileSize;\r
+  SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA  SmramProfileGetData;\r
+  MEMORY_PROFILE_CONTEXT_DATA               *ContextData;\r
+  BOOLEAN                                   SmramProfileRecordingStatus;\r
+\r
+  ContextData = GetSmramProfileContext ();\r
+  if (ContextData == NULL) {\r
+    return ;\r
+  }\r
+\r
+  SmramProfileRecordingStatus = mSmramProfileRecordingStatus;\r
+  mSmramProfileRecordingStatus = FALSE;\r
+\r
+\r
+  CopyMem (&SmramProfileGetData, SmramProfileParameterGetData, sizeof (SmramProfileGetData));\r
+\r
+  ProfileSize = SmramProfileGetDataSize();\r
+\r
+  //\r
+  // Sanity check\r
+  //\r
+  if (!InternalIsAddressValid ((UINTN) SmramProfileGetData.ProfileBuffer, (UINTN) ProfileSize)) {\r
+    DEBUG ((EFI_D_ERROR, "SmramProfileHandlerGetData: SMM ProfileBuffer in SMRAM or overflow!\n"));\r
+    SmramProfileParameterGetData->ProfileSize = ProfileSize;\r
+    SmramProfileParameterGetData->Header.ReturnStatus = (UINT64) (INT64) (INTN) EFI_ACCESS_DENIED;\r
+    goto Done;\r
+  }\r
+\r
+  if (SmramProfileGetData.ProfileSize < ProfileSize) {\r
+    SmramProfileParameterGetData->ProfileSize = ProfileSize;\r
+    SmramProfileParameterGetData->Header.ReturnStatus = (UINT64) (INT64) (INTN) EFI_BUFFER_TOO_SMALL;\r
+    goto Done;\r
+  }\r
+\r
+  SmramProfileParameterGetData->ProfileSize = ProfileSize;\r
+  SmramProfileCopyData ((VOID *) (UINTN) SmramProfileGetData.ProfileBuffer);\r
+  SmramProfileParameterGetData->Header.ReturnStatus = 0;\r
+\r
+Done:\r
+  mSmramProfileRecordingStatus = SmramProfileRecordingStatus;\r
+}\r
+\r
+/**\r
+  SMRAM profile handler to register SMM image.\r
+\r
+  @param SmramProfileParameterRegisterImage The parameter of SMM profile register image.\r
+\r
+**/\r
+VOID\r
+SmramProfileHandlerRegisterImage (\r
+  IN SMRAM_PROFILE_PARAMETER_REGISTER_IMAGE *SmramProfileParameterRegisterImage\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+  EFI_SMM_DRIVER_ENTRY              DriverEntry;\r
+  VOID                              *EntryPointInImage;\r
+  BOOLEAN                           Ret;\r
+\r
+  ZeroMem (&DriverEntry, sizeof (DriverEntry));\r
+  CopyMem (&DriverEntry.FileName, &SmramProfileParameterRegisterImage->FileName, sizeof(EFI_GUID));\r
+  DriverEntry.ImageBuffer = SmramProfileParameterRegisterImage->ImageBuffer;\r
+  DriverEntry.NumberOfPage = (UINTN) SmramProfileParameterRegisterImage->NumberOfPage;\r
+  Status = InternalPeCoffGetEntryPoint ((VOID *) (UINTN) DriverEntry.ImageBuffer, &EntryPointInImage);\r
+  ASSERT_EFI_ERROR (Status);\r
+  DriverEntry.ImageEntryPoint = (PHYSICAL_ADDRESS) (UINTN) EntryPointInImage;\r
+\r
+  Ret = RegisterSmramProfileImage (&DriverEntry, FALSE);\r
+  if (Ret) {\r
+    SmramProfileParameterRegisterImage->Header.ReturnStatus = 0;\r
+  }\r
+}\r
+\r
+/**\r
+  SMRAM profile handler to unregister SMM image.\r
+\r
+  @param SmramProfileParameterUnregisterImage The parameter of SMM profile unregister image.\r
+\r
+**/\r
+VOID\r
+SmramProfileHandlerUnregisterImage (\r
+  IN SMRAM_PROFILE_PARAMETER_UNREGISTER_IMAGE *SmramProfileParameterUnregisterImage\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+  EFI_SMM_DRIVER_ENTRY              DriverEntry;\r
+  VOID                              *EntryPointInImage;\r
+  BOOLEAN                           Ret;\r
+\r
+  ZeroMem (&DriverEntry, sizeof (DriverEntry));\r
+  CopyMem (&DriverEntry.FileName, &SmramProfileParameterUnregisterImage->FileName, sizeof (EFI_GUID));\r
+  DriverEntry.ImageBuffer = SmramProfileParameterUnregisterImage->ImageBuffer;\r
+  DriverEntry.NumberOfPage = (UINTN) SmramProfileParameterUnregisterImage->NumberOfPage;\r
+  Status = InternalPeCoffGetEntryPoint ((VOID *) (UINTN) DriverEntry.ImageBuffer, &EntryPointInImage);\r
+  ASSERT_EFI_ERROR (Status);\r
+  DriverEntry.ImageEntryPoint = (PHYSICAL_ADDRESS) (UINTN) EntryPointInImage;\r
+\r
+  Ret = UnregisterSmramProfileImage (&DriverEntry, FALSE);\r
+  if (Ret) {\r
+    SmramProfileParameterUnregisterImage->Header.ReturnStatus = 0;\r
+  }\r
+}\r
+\r
+/**\r
+  Dispatch function for a Software SMI handler.\r
+\r
+  Caution: This function may receive untrusted input.\r
+  Communicate buffer and buffer size are external input, so this function will do basic validation.\r
+\r
+  @param DispatchHandle  The unique handle assigned to this handler by SmiHandlerRegister().\r
+  @param Context         Points to an optional handler context which was specified when the\r
+                         handler was registered.\r
+  @param CommBuffer      A pointer to a collection of data in memory that will\r
+                         be conveyed from a non-SMM environment into an SMM environment.\r
+  @param CommBufferSize  The size of the CommBuffer.\r
+\r
+  @retval EFI_SUCCESS Command is handled successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SmramProfileHandler (\r
+  IN EFI_HANDLE  DispatchHandle,\r
+  IN CONST VOID  *Context         OPTIONAL,\r
+  IN OUT VOID    *CommBuffer      OPTIONAL,\r
+  IN OUT UINTN   *CommBufferSize  OPTIONAL\r
+  )\r
+{\r
+  SMRAM_PROFILE_PARAMETER_HEADER           *SmramProfileParameterHeader;\r
+  UINTN                                    TempCommBufferSize;\r
+\r
+  DEBUG ((EFI_D_ERROR, "SmramProfileHandler Enter\n"));\r
+\r
+  //\r
+  // If input is invalid, stop processing this SMI\r
+  //\r
+  if (CommBuffer == NULL || CommBufferSize == NULL) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  TempCommBufferSize = *CommBufferSize;\r
+\r
+  if (TempCommBufferSize < sizeof (SMRAM_PROFILE_PARAMETER_HEADER)) {\r
+    DEBUG ((EFI_D_ERROR, "SmramProfileHandler: SMM communication buffer size invalid!\n"));\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  if (mSmramReadyToLock && !InternalIsAddressValid ((UINTN)CommBuffer, TempCommBufferSize)) {\r
+    DEBUG ((EFI_D_ERROR, "SmramProfileHandler: SMM communication buffer in SMRAM or overflow!\n"));\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  SmramProfileParameterHeader = (SMRAM_PROFILE_PARAMETER_HEADER *) ((UINTN) CommBuffer);\r
+\r
+  SmramProfileParameterHeader->ReturnStatus = (UINT64)-1;\r
+\r
+  if (GetSmramProfileContext () == NULL) {\r
+    SmramProfileParameterHeader->ReturnStatus = (UINT64) (INT64) (INTN) EFI_UNSUPPORTED;\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  switch (SmramProfileParameterHeader->Command) {\r
+  case SMRAM_PROFILE_COMMAND_GET_PROFILE_INFO:\r
+    DEBUG ((EFI_D_ERROR, "SmramProfileHandlerGetInfo\n"));\r
+    if (TempCommBufferSize != sizeof (SMRAM_PROFILE_PARAMETER_GET_PROFILE_INFO)) {\r
+      DEBUG ((EFI_D_ERROR, "SmramProfileHandler: SMM communication buffer size invalid!\n"));\r
+      return EFI_SUCCESS;\r
+    }\r
+    SmramProfileHandlerGetInfo ((SMRAM_PROFILE_PARAMETER_GET_PROFILE_INFO *) (UINTN) CommBuffer);\r
+    break;\r
+  case SMRAM_PROFILE_COMMAND_GET_PROFILE_DATA:\r
+    DEBUG ((EFI_D_ERROR, "SmramProfileHandlerGetData\n"));\r
+    if (TempCommBufferSize != sizeof (SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA)) {\r
+      DEBUG ((EFI_D_ERROR, "SmramProfileHandler: SMM communication buffer size invalid!\n"));\r
+      return EFI_SUCCESS;\r
+    }\r
+    SmramProfileHandlerGetData ((SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA *) (UINTN) CommBuffer);\r
+    break;\r
+  case SMRAM_PROFILE_COMMAND_REGISTER_IMAGE:\r
+    DEBUG ((EFI_D_ERROR, "SmramProfileHandlerRegisterImage\n"));\r
+    if (TempCommBufferSize != sizeof (SMRAM_PROFILE_PARAMETER_REGISTER_IMAGE)) {\r
+      DEBUG ((EFI_D_ERROR, "SmramProfileHandler: SMM communication buffer size invalid!\n"));\r
+      return EFI_SUCCESS;\r
+    }\r
+    if (mSmramReadyToLock) {\r
+      return EFI_SUCCESS;\r
+    }\r
+    SmramProfileHandlerRegisterImage ((SMRAM_PROFILE_PARAMETER_REGISTER_IMAGE *) (UINTN) CommBuffer);\r
+    break;\r
+  case SMRAM_PROFILE_COMMAND_UNREGISTER_IMAGE:\r
+    DEBUG ((EFI_D_ERROR, "SmramProfileHandlerUnregisterImage\n"));\r
+    if (TempCommBufferSize != sizeof (SMRAM_PROFILE_PARAMETER_UNREGISTER_IMAGE)) {\r
+      DEBUG ((EFI_D_ERROR, "SmramProfileHandler: SMM communication buffer size invalid!\n"));\r
+      return EFI_SUCCESS;\r
+    }\r
+    if (mSmramReadyToLock) {\r
+      return EFI_SUCCESS;\r
+    }\r
+    SmramProfileHandlerUnregisterImage ((SMRAM_PROFILE_PARAMETER_UNREGISTER_IMAGE *) (UINTN) CommBuffer);\r
+    break;\r
+  default:\r
+    break;\r
+  }\r
+\r
+  DEBUG ((EFI_D_ERROR, "SmramProfileHandler Exit\n"));\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Register SMRAM profile handler.\r
+\r
+**/\r
+VOID\r
+RegisterSmramProfileHandler (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS    Status;\r
+  EFI_HANDLE    DispatchHandle;\r
+\r
+  if (!IS_SMRAM_PROFILE_ENABLED) {\r
+    return;\r
+  }\r
+\r
+  Status = SmiHandlerRegister (\r
+             SmramProfileHandler,\r
+             &gEdkiiMemoryProfileGuid,\r
+             &DispatchHandle\r
+             );\r
+  ASSERT_EFI_ERROR (Status);\r
+}\r
+\r
+////////////////////\r
+\r
+/**\r
+  Dump SMRAM range.\r
+\r
+**/\r
+VOID\r
+DumpSmramRange (\r
+  VOID\r
+  )\r
+{\r
+  UINTN                         Index;\r
+  MEMORY_PROFILE_CONTEXT_DATA   *ContextData;\r
+  BOOLEAN                       SmramProfileRecordingStatus;\r
+\r
+  ContextData = GetSmramProfileContext ();\r
+  if (ContextData == NULL) {\r
+    return ;\r
+  }\r
+\r
+  SmramProfileRecordingStatus = mSmramProfileRecordingStatus;\r
+  mSmramProfileRecordingStatus = FALSE;\r
+\r
+  DEBUG ((EFI_D_INFO, "FullSmramRange address - 0x%08x\n", mFullSmramRanges));\r
+\r
+  DEBUG ((EFI_D_INFO, "======= SmramProfile begin =======\n"));\r
+\r
+  DEBUG ((EFI_D_INFO, "FullSmramRange:\n"));\r
+  for (Index = 0; Index < mFullSmramRangeCount; Index++) {\r
+    DEBUG ((EFI_D_INFO, "  FullSmramRange (0x%x)\n", Index));\r
+    DEBUG ((EFI_D_INFO, "    PhysicalStart      - 0x%016lx\n", mFullSmramRanges[Index].PhysicalStart));\r
+    DEBUG ((EFI_D_INFO, "    CpuStart           - 0x%016lx\n", mFullSmramRanges[Index].CpuStart));\r
+    DEBUG ((EFI_D_INFO, "    PhysicalSize       - 0x%016lx\n", mFullSmramRanges[Index].PhysicalSize));\r
+    DEBUG ((EFI_D_INFO, "    RegionState        - 0x%016lx\n", mFullSmramRanges[Index].RegionState));\r
+  }\r
+\r
+  DEBUG ((EFI_D_INFO, "======= SmramProfile end =======\n"));\r
+\r
+  mSmramProfileRecordingStatus = SmramProfileRecordingStatus;\r
+}\r
+\r
+/**\r
+  Dump SMRAM free page list.\r
+\r
+**/\r
+VOID\r
+DumpFreePagesList (\r
+  VOID\r
+  )\r
+{\r
+  LIST_ENTRY                    *FreePageList;\r
+  LIST_ENTRY                    *Node;\r
+  FREE_PAGE_LIST                *Pages;\r
+  UINTN                         Index;\r
+  MEMORY_PROFILE_CONTEXT_DATA   *ContextData;\r
+  BOOLEAN                       SmramProfileRecordingStatus;\r
+\r
+  ContextData = GetSmramProfileContext ();\r
+  if (ContextData == NULL) {\r
+    return ;\r
+  }\r
+\r
+  SmramProfileRecordingStatus = mSmramProfileRecordingStatus;\r
+  mSmramProfileRecordingStatus = FALSE;\r
+\r
+  DEBUG ((EFI_D_INFO, "======= SmramProfile begin =======\n"));\r
+\r
+  DEBUG ((EFI_D_INFO, "FreePagesList:\n"));\r
+  FreePageList = &mSmmMemoryMap;\r
+  for (Node = FreePageList->BackLink, Index = 0;\r
+       Node != FreePageList;\r
+       Node = Node->BackLink, Index++) {\r
+    Pages = BASE_CR (Node, FREE_PAGE_LIST, Link);\r
+    DEBUG ((EFI_D_INFO, "  Index - 0x%x\n", Index));\r
+    DEBUG ((EFI_D_INFO, "    PhysicalStart - 0x%016lx\n", (PHYSICAL_ADDRESS) (UINTN) Pages));\r
+    DEBUG ((EFI_D_INFO, "    NumberOfPages - 0x%08x\n", Pages->NumberOfPages));\r
+  }\r
+\r
+  DEBUG ((EFI_D_INFO, "======= SmramProfile end =======\n"));\r
+\r
+  mSmramProfileRecordingStatus = SmramProfileRecordingStatus;\r
+}\r
+\r
+/**\r
+  Dump SMRAM free pool list.\r
+\r
+**/\r
+VOID\r
+DumpFreePoolList (\r
+  VOID\r
+  )\r
+{\r
+  LIST_ENTRY                     *FreePoolList;\r
+  LIST_ENTRY                     *Node;\r
+  FREE_POOL_HEADER               *Pool;\r
+  UINTN                          Index;\r
+  UINTN                          PoolListIndex;\r
+  MEMORY_PROFILE_CONTEXT_DATA   *ContextData;\r
+  BOOLEAN                       SmramProfileRecordingStatus;\r
+\r
+  ContextData = GetSmramProfileContext ();\r
+  if (ContextData == NULL) {\r
+    return ;\r
+  }\r
+\r
+  SmramProfileRecordingStatus = mSmramProfileRecordingStatus;\r
+  mSmramProfileRecordingStatus = FALSE;\r
+\r
+  DEBUG ((EFI_D_INFO, "======= SmramProfile begin =======\n"));\r
+\r
+  for (PoolListIndex = 0; PoolListIndex < MAX_POOL_INDEX; PoolListIndex++) {\r
+    DEBUG ((EFI_D_INFO, "FreePoolList (%d):\n", PoolListIndex));\r
+    FreePoolList = &mSmmPoolLists[PoolListIndex];\r
+    for (Node = FreePoolList->BackLink, Index = 0;\r
+         Node != FreePoolList;\r
+         Node = Node->BackLink, Index++) {\r
+      Pool = BASE_CR (Node, FREE_POOL_HEADER, Link);\r
+      DEBUG ((EFI_D_INFO, "  Index - 0x%x\n", Index));\r
+      DEBUG ((EFI_D_INFO, "    PhysicalStart - 0x%016lx\n", (PHYSICAL_ADDRESS) (UINTN) Pool));\r
+      DEBUG ((EFI_D_INFO, "    Size          - 0x%08x\n", Pool->Header.Size));\r
+      DEBUG ((EFI_D_INFO, "    Available     - 0x%02x\n", Pool->Header.Available));\r
+    }\r
+  }\r
+\r
+  DEBUG ((EFI_D_INFO, "======= SmramProfile end =======\n"));\r
+\r
+  mSmramProfileRecordingStatus = SmramProfileRecordingStatus;\r
+}\r
+\r
+GLOBAL_REMOVE_IF_UNREFERENCED CHAR16 *mActionString[] = {\r
+  L"Unknown",\r
+  L"AllocatePages",\r
+  L"FreePages",\r
+  L"AllocatePool",\r
+  L"FreePool",\r
+};\r
+\r
+GLOBAL_REMOVE_IF_UNREFERENCED CHAR16 *mMemoryTypeString[] = {\r
+  L"EfiReservedMemoryType",\r
+  L"EfiLoaderCode",\r
+  L"EfiLoaderData",\r
+  L"EfiBootServicesCode",\r
+  L"EfiBootServicesData",\r
+  L"EfiRuntimeServicesCode",\r
+  L"EfiRuntimeServicesData",\r
+  L"EfiConventionalMemory",\r
+  L"EfiUnusableMemory",\r
+  L"EfiACPIReclaimMemory",\r
+  L"EfiACPIMemoryNVS",\r
+  L"EfiMemoryMappedIO",\r
+  L"EfiMemoryMappedIOPortSpace",\r
+  L"EfiPalCode",\r
+  L"EfiOSReserved",\r
+};\r
+\r
+\r
+/**\r
+  Dump SMRAM profile.\r
+\r
+**/\r
+VOID\r
+DumpSmramProfile (\r
+  VOID\r
+  )\r
+{\r
+  MEMORY_PROFILE_CONTEXT            *Context;\r
+  MEMORY_PROFILE_DRIVER_INFO        *DriverInfo;\r
+  MEMORY_PROFILE_ALLOC_INFO         *AllocInfo;\r
+  MEMORY_PROFILE_CONTEXT_DATA       *ContextData;\r
+  MEMORY_PROFILE_DRIVER_INFO_DATA   *DriverInfoData;\r
+  MEMORY_PROFILE_ALLOC_INFO_DATA    *AllocInfoData;\r
+  LIST_ENTRY                        *SmramDriverInfoList;\r
+  UINTN                             DriverIndex;\r
+  LIST_ENTRY                        *DriverLink;\r
+  LIST_ENTRY                        *AllocInfoList;\r
+  UINTN                             AllocIndex;\r
+  LIST_ENTRY                        *AllocLink;\r
+  BOOLEAN                           SmramProfileRecordingStatus;\r
+  UINTN                             TypeIndex;\r
+\r
+  ContextData = GetSmramProfileContext ();\r
+  if (ContextData == NULL) {\r
+    return ;\r
+  }\r
+\r
+  SmramProfileRecordingStatus = mSmramProfileRecordingStatus;\r
+  mSmramProfileRecordingStatus = FALSE;\r
+\r
+  Context = &ContextData->Context;\r
+  DEBUG ((EFI_D_INFO, "======= SmramProfile begin =======\n"));\r
+  DEBUG ((EFI_D_INFO, "MEMORY_PROFILE_CONTEXT\n"));\r
+\r
+  DEBUG ((EFI_D_INFO, "  CurrentTotalUsage     - 0x%016lx\n", Context->CurrentTotalUsage));\r
+  DEBUG ((EFI_D_INFO, "  PeakTotalUsage        - 0x%016lx\n", Context->PeakTotalUsage));\r
+  for (TypeIndex = 0; TypeIndex <= EfiMaxMemoryType; TypeIndex++) {\r
+    if ((Context->CurrentTotalUsageByType[TypeIndex] != 0) ||\r
+        (Context->PeakTotalUsageByType[TypeIndex] != 0)) {\r
+      DEBUG ((EFI_D_INFO, "  CurrentTotalUsage[0x%02x]  - 0x%016lx (%s)\n", TypeIndex, Context->CurrentTotalUsageByType[TypeIndex], mMemoryTypeString[TypeIndex]));\r
+      DEBUG ((EFI_D_INFO, "  PeakTotalUsage[0x%02x]     - 0x%016lx (%s)\n", TypeIndex, Context->PeakTotalUsageByType[TypeIndex], mMemoryTypeString[TypeIndex]));\r
+    }\r
+  }\r
+  DEBUG ((EFI_D_INFO, "  TotalImageSize        - 0x%016lx\n", Context->TotalImageSize));\r
+  DEBUG ((EFI_D_INFO, "  ImageCount            - 0x%08x\n", Context->ImageCount));\r
+  DEBUG ((EFI_D_INFO, "  SequenceCount         - 0x%08x\n", Context->SequenceCount));\r
+\r
+  SmramDriverInfoList = ContextData->DriverInfoList;\r
+  for (DriverLink = SmramDriverInfoList->ForwardLink, DriverIndex = 0;\r
+       DriverLink != SmramDriverInfoList;\r
+       DriverLink = DriverLink->ForwardLink, DriverIndex++) {\r
+    DriverInfoData = CR (\r
+                   DriverLink,\r
+                   MEMORY_PROFILE_DRIVER_INFO_DATA,\r
+                   Link,\r
+                   MEMORY_PROFILE_DRIVER_INFO_SIGNATURE\r
+                   );\r
+    DriverInfo = &DriverInfoData->DriverInfo;\r
+    DEBUG ((EFI_D_INFO, "  MEMORY_PROFILE_DRIVER_INFO (0x%x)\n", DriverIndex));\r
+    DEBUG ((EFI_D_INFO, "    FileName            - %g\n", &DriverInfo->FileName));\r
+    DEBUG ((EFI_D_INFO, "    ImageBase           - 0x%016lx\n", DriverInfo->ImageBase));\r
+    DEBUG ((EFI_D_INFO, "    ImageSize           - 0x%016lx\n", DriverInfo->ImageSize));\r
+    DEBUG ((EFI_D_INFO, "    EntryPoint          - 0x%016lx\n", DriverInfo->EntryPoint));\r
+    DEBUG ((EFI_D_INFO, "    ImageSubsystem      - 0x%04x\n", DriverInfo->ImageSubsystem));\r
+    DEBUG ((EFI_D_INFO, "    FileType            - 0x%02x\n", DriverInfo->FileType));\r
+    DEBUG ((EFI_D_INFO, "    CurrentUsage        - 0x%016lx\n", DriverInfo->CurrentUsage));\r
+    DEBUG ((EFI_D_INFO, "    PeakUsage           - 0x%016lx\n", DriverInfo->PeakUsage));\r
+    for (TypeIndex = 0; TypeIndex <= EfiMaxMemoryType; TypeIndex++) {\r
+      if ((DriverInfo->CurrentUsageByType[TypeIndex] != 0) ||\r
+          (DriverInfo->PeakUsageByType[TypeIndex] != 0)) {\r
+        DEBUG ((EFI_D_INFO, "    CurrentUsage[0x%02x]     - 0x%016lx (%s)\n", TypeIndex, DriverInfo->CurrentUsageByType[TypeIndex], mMemoryTypeString[TypeIndex]));\r
+        DEBUG ((EFI_D_INFO, "    PeakUsage[0x%02x]        - 0x%016lx (%s)\n", TypeIndex, DriverInfo->PeakUsageByType[TypeIndex], mMemoryTypeString[TypeIndex]));\r
+      }\r
+    }\r
+    DEBUG ((EFI_D_INFO, "    AllocRecordCount    - 0x%08x\n", DriverInfo->AllocRecordCount));\r
+\r
+    AllocInfoList = DriverInfoData->AllocInfoList;\r
+    for (AllocLink = AllocInfoList->ForwardLink, AllocIndex = 0;\r
+         AllocLink != AllocInfoList;\r
+         AllocLink = AllocLink->ForwardLink, AllocIndex++) {\r
+      AllocInfoData = CR (\r
+                     AllocLink,\r
+                     MEMORY_PROFILE_ALLOC_INFO_DATA,\r
+                     Link,\r
+                     MEMORY_PROFILE_ALLOC_INFO_SIGNATURE\r
+                     );\r
+      AllocInfo = &AllocInfoData->AllocInfo;\r
+      DEBUG ((EFI_D_INFO, "    MEMORY_PROFILE_ALLOC_INFO (0x%x)\n", AllocIndex));\r
+      DEBUG ((EFI_D_INFO, "      CallerAddress  - 0x%016lx (Offset: 0x%08x)\n", AllocInfo->CallerAddress, AllocInfo->CallerAddress - DriverInfo->ImageBase));\r
+      DEBUG ((EFI_D_INFO, "      SequenceId     - 0x%08x\n", AllocInfo->SequenceId));\r
+      DEBUG ((EFI_D_INFO, "      Action         - 0x%08x (%s)\n", AllocInfo->Action, mActionString[(AllocInfo->Action < sizeof(mActionString)/sizeof(mActionString[0])) ? AllocInfo->Action : 0]));\r
+      DEBUG ((EFI_D_INFO, "      MemoryType     - 0x%08x\n", AllocInfo->MemoryType));\r
+      DEBUG ((EFI_D_INFO, "      Buffer         - 0x%016lx\n", AllocInfo->Buffer));\r
+      DEBUG ((EFI_D_INFO, "      Size           - 0x%016lx\n", AllocInfo->Size));\r
+    }\r
+  }\r
+\r
+  DEBUG ((EFI_D_INFO, "======= SmramProfile end =======\n"));\r
+\r
+  mSmramProfileRecordingStatus = SmramProfileRecordingStatus;\r
+}\r
+\r
+/**\r
+  Dump SMRAM infromation.\r
+\r
+**/\r
+VOID\r
+DumpSmramInfo (\r
+  VOID\r
+  )\r
+{\r
+  DEBUG_CODE (\r
+    if (IS_SMRAM_PROFILE_ENABLED) {\r
+      DumpSmramProfile ();\r
+      DumpFreePagesList ();\r
+      DumpFreePoolList ();\r
+      DumpSmramRange ();\r
+    }\r
+  );\r
+}\r
+\r
diff --git a/MdeModulePkg/Include/Guid/MemoryProfile.h b/MdeModulePkg/Include/Guid/MemoryProfile.h
new file mode 100644 (file)
index 0000000..3c1e5e7
--- /dev/null
@@ -0,0 +1,286 @@
+/** @file\r
+  Memory profile data structure.\r
+\r
+  Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>\r
+  This program and the accompanying materials\r
+  are licensed and made available under the terms and conditions of the BSD License\r
+  which accompanies this distribution.  The full text of the license may be found at\r
+  http://opensource.org/licenses/bsd-license.php\r
+\r
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _MEMORY_PROFILE_H_\r
+#define _MEMORY_PROFILE_H_\r
+\r
+//\r
+// For BIOS MemoryType (0 ~ EfiMaxMemoryType), it is recorded in UsageByType[MemoryType]. (Each valid entry has one entry)\r
+// For OS MemoryType (0x80000000 ~ 0xFFFFFFFF), it is recorded in UsageByType[EfiMaxMemoryType]. (All types are combined into one entry)\r
+//\r
+\r
+typedef struct {\r
+  UINT32                       Signature;\r
+  UINT16                       Length;\r
+  UINT16                       Revision;\r
+} MEMORY_PROFILE_COMMON_HEADER;\r
+\r
+#define MEMORY_PROFILE_CONTEXT_SIGNATURE SIGNATURE_32 ('M','P','C','T')\r
+#define MEMORY_PROFILE_CONTEXT_REVISION 0x0001\r
+\r
+typedef struct {\r
+  MEMORY_PROFILE_COMMON_HEADER  Header;\r
+  UINT64                        CurrentTotalUsage;\r
+  UINT64                        PeakTotalUsage;\r
+  UINT64                        CurrentTotalUsageByType[EfiMaxMemoryType + 1];\r
+  UINT64                        PeakTotalUsageByType[EfiMaxMemoryType + 1];\r
+  UINT64                        TotalImageSize;\r
+  UINT32                        ImageCount;\r
+  UINT32                        SequenceCount;\r
+} MEMORY_PROFILE_CONTEXT;\r
+\r
+#define MEMORY_PROFILE_DRIVER_INFO_SIGNATURE SIGNATURE_32 ('M','P','D','I')\r
+#define MEMORY_PROFILE_DRIVER_INFO_REVISION 0x0001\r
+\r
+typedef struct {\r
+  MEMORY_PROFILE_COMMON_HEADER  Header;\r
+  EFI_GUID                      FileName;\r
+  PHYSICAL_ADDRESS              ImageBase;\r
+  UINT64                        ImageSize;\r
+  PHYSICAL_ADDRESS              EntryPoint;\r
+  UINT16                        ImageSubsystem;\r
+  EFI_FV_FILETYPE               FileType;\r
+  UINT8                         Reserved[1];\r
+  UINT32                        AllocRecordCount;\r
+  UINT64                        CurrentUsage;\r
+  UINT64                        PeakUsage;\r
+  UINT64                        CurrentUsageByType[EfiMaxMemoryType + 1];\r
+  UINT64                        PeakUsageByType[EfiMaxMemoryType + 1];\r
+} MEMORY_PROFILE_DRIVER_INFO;\r
+\r
+typedef enum {\r
+  MemoryProfileActionAllocatePages = 1,\r
+  MemoryProfileActionFreePages = 2,\r
+  MemoryProfileActionAllocatePool = 3,\r
+  MemoryProfileActionFreePool = 4,\r
+} MEMORY_PROFILE_ACTION;\r
+\r
+#define MEMORY_PROFILE_ALLOC_INFO_SIGNATURE SIGNATURE_32 ('M','P','A','I')\r
+#define MEMORY_PROFILE_ALLOC_INFO_REVISION 0x0001\r
+\r
+typedef struct {\r
+  MEMORY_PROFILE_COMMON_HEADER  Header;\r
+  PHYSICAL_ADDRESS              CallerAddress;\r
+  UINT32                        SequenceId;\r
+  UINT8                         Reserved[4];\r
+  MEMORY_PROFILE_ACTION         Action;\r
+  EFI_MEMORY_TYPE               MemoryType;\r
+  PHYSICAL_ADDRESS              Buffer;\r
+  UINT64                        Size;\r
+} MEMORY_PROFILE_ALLOC_INFO;\r
+\r
+#define MEMORY_PROFILE_DESCRIPTOR_SIGNATURE SIGNATURE_32 ('M','P','D','R')\r
+#define MEMORY_PROFILE_DESCRIPTOR_REVISION 0x0001\r
+\r
+typedef struct {\r
+  MEMORY_PROFILE_COMMON_HEADER  Header;\r
+  PHYSICAL_ADDRESS              Address;\r
+  UINT64                        Size;\r
+} MEMORY_PROFILE_DESCRIPTOR;\r
+\r
+#define MEMORY_PROFILE_FREE_MEMORY_SIGNATURE SIGNATURE_32 ('M','P','R','M')\r
+#define MEMORY_PROFILE_FREE_MEMORY_REVISION 0x0001\r
+\r
+typedef struct {\r
+  MEMORY_PROFILE_COMMON_HEADER  Header;\r
+  UINT64                        TotalFreeMemoryPages;\r
+  UINT32                        FreeMemoryEntryCount;\r
+  UINT8                         Reserved[4];\r
+  //MEMORY_PROFILE_DESCRIPTOR     MemoryDescriptor[FreeMemoryEntryCount];\r
+} MEMORY_PROFILE_FREE_MEMORY;\r
+\r
+#define MEMORY_PROFILE_MEMORY_RANGE_SIGNATURE SIGNATURE_32 ('M','P','M','R')\r
+#define MEMORY_PROFILE_MEMORY_RANGE_REVISION 0x0001\r
+\r
+typedef struct {\r
+  MEMORY_PROFILE_COMMON_HEADER  Header;\r
+  UINT32                        MemoryRangeCount;\r
+  UINT8                         Reserved[4];\r
+  //MEMORY_PROFILE_DESCRIPTOR     MemoryDescriptor[MemoryRangeCount];\r
+} MEMORY_PROFILE_MEMORY_RANGE;\r
+\r
+//\r
+// UEFI memory profile layout:\r
+// +--------------------------------+\r
+// | CONTEXT                        |\r
+// +--------------------------------+\r
+// | DRIVER_INFO(1)                 |\r
+// +--------------------------------+\r
+// | ALLOC_INFO(1, 1)               |\r
+// +--------------------------------+\r
+// | ALLOC_INFO(1, m1)              |\r
+// +--------------------------------+\r
+// | DRIVER_INFO(n)                 |\r
+// +--------------------------------+\r
+// | ALLOC_INFO(n, 1)               |\r
+// +--------------------------------+\r
+// | ALLOC_INFO(n, mn)              |\r
+// +--------------------------------+\r
+//\r
+\r
+typedef struct _EDKII_MEMORY_PROFILE_PROTOCOL EDKII_MEMORY_PROFILE_PROTOCOL;\r
+\r
+/**\r
+  Get memory profile data.\r
+\r
+  @param[in]      This              The EDKII_MEMORY_PROFILE_PROTOCOL instance.\r
+  @param[in, out] ProfileSize       On entry, points to the size in bytes of the ProfileBuffer.\r
+                                    On return, points to the size of the data returned in ProfileBuffer.\r
+  @param[out]     ProfileBuffer     Profile buffer.\r
+                      \r
+  @return EFI_SUCCESS               Get the memory profile data successfully.\r
+  @return EFI_BUFFER_TO_SMALL       The ProfileSize is too small for the resulting data. \r
+                                    ProfileSize is updated with the size required.\r
+\r
+**/\r
+typedef\r
+EFI_STATUS\r
+(EFIAPI *EDKII_MEMORY_PROFILE_GET_DATA)(\r
+  IN     EDKII_MEMORY_PROFILE_PROTOCOL  *This,\r
+  IN OUT UINT64                         *ProfileSize,\r
+     OUT VOID                           *ProfileBuffer\r
+  );\r
+\r
+/**\r
+  Register image to memory profile.\r
+\r
+  @param[in] This               The EDKII_MEMORY_PROFILE_PROTOCOL instance.\r
+  @param[in] FilePath           File path of the image.\r
+  @param[in] ImageBase          Image base address.\r
+  @param[in] ImageSize          Image size.\r
+  @param[in] FileType           File type of the image.\r
+\r
+  @return EFI_SUCCESS           Register success.\r
+  @return EFI_OUT_OF_RESOURCE   No enough resource for this register.\r
+\r
+**/\r
+typedef\r
+EFI_STATUS\r
+(EFIAPI *EDKII_MEMORY_PROFILE_REGISTER_IMAGE)(\r
+  IN EDKII_MEMORY_PROFILE_PROTOCOL      *This,\r
+  IN EFI_DEVICE_PATH_PROTOCOL           *FilePath,\r
+  IN PHYSICAL_ADDRESS                   ImageBase,\r
+  IN UINT64                             ImageSize,\r
+  IN EFI_FV_FILETYPE                    FileType\r
+  );\r
+\r
+/**\r
+  Unregister image from memory profile.\r
+\r
+  @param[in] This               The EDKII_MEMORY_PROFILE_PROTOCOL instance.\r
+  @param[in] FilePath           File path of the image.\r
+  @param[in] ImageBase          Image base address.\r
+  @param[in] ImageSize          Image size.\r
+\r
+  @return EFI_SUCCESS           Unregister success.\r
+  @return EFI_NOT_FOUND         The image is not found.\r
+\r
+**/\r
+typedef\r
+EFI_STATUS\r
+(EFIAPI *EDKII_MEMORY_PROFILE_UNREGISTER_IMAGE)(\r
+  IN EDKII_MEMORY_PROFILE_PROTOCOL      *This,\r
+  IN EFI_DEVICE_PATH_PROTOCOL           *FilePath,\r
+  IN PHYSICAL_ADDRESS                   ImageBase,\r
+  IN UINT64                             ImageSize\r
+  );\r
+\r
+struct _EDKII_MEMORY_PROFILE_PROTOCOL {\r
+  EDKII_MEMORY_PROFILE_GET_DATA         GetData;\r
+  EDKII_MEMORY_PROFILE_REGISTER_IMAGE   RegisterImage;\r
+  EDKII_MEMORY_PROFILE_UNREGISTER_IMAGE UnregisterImage;\r
+};\r
+\r
+//\r
+// SMRAM profile layout:\r
+// +--------------------------------+\r
+// | CONTEXT                        |\r
+// +--------------------------------+\r
+// | DRIVER_INFO(1)                 |\r
+// +--------------------------------+\r
+// | ALLOC_INFO(1, 1)               |\r
+// +--------------------------------+\r
+// | ALLOC_INFO(1, m1)              |\r
+// +--------------------------------+\r
+// | DRIVER_INFO(n)                 |\r
+// +--------------------------------+\r
+// | ALLOC_INFO(n, 1)               |\r
+// +--------------------------------+\r
+// | ALLOC_INFO(n, mn)              |\r
+// +--------------------------------+\r
+// | FREE_MEMORY                    |\r
+// +--------------------------------+\r
+// | FREE MEMORY DESCRIPTOR(1)      |\r
+// +--------------------------------+\r
+// | FREE MEMORY DESCRIPTOR(p)      |\r
+// +--------------------------------+\r
+// | MEMORY_RANGE                   |\r
+// +--------------------------------+\r
+// | MEMORY RANGE DESCRIPTOR(1)     |\r
+// +--------------------------------+\r
+// | MEMORY RANGE DESCRIPTOR(q)     |\r
+// +--------------------------------+\r
+//\r
+\r
+//\r
+// SMRAM profile command\r
+//\r
+#define SMRAM_PROFILE_COMMAND_GET_PROFILE_INFO         0x1\r
+#define SMRAM_PROFILE_COMMAND_GET_PROFILE_DATA         0x2\r
+//\r
+// Below 2 commands are now used by ECP only and only valid before SmmReadyToLock\r
+//\r
+#define SMRAM_PROFILE_COMMAND_REGISTER_IMAGE           0x3\r
+#define SMRAM_PROFILE_COMMAND_UNREGISTER_IMAGE         0x4\r
+\r
+typedef struct {\r
+  UINT32                            Command;\r
+  UINT32                            DataLength;\r
+  UINT64                            ReturnStatus;\r
+} SMRAM_PROFILE_PARAMETER_HEADER;\r
+\r
+typedef struct {\r
+  SMRAM_PROFILE_PARAMETER_HEADER    Header;\r
+  UINT64                            ProfileSize;\r
+} SMRAM_PROFILE_PARAMETER_GET_PROFILE_INFO;\r
+\r
+typedef struct {\r
+  SMRAM_PROFILE_PARAMETER_HEADER    Header;\r
+  UINT64                            ProfileSize;\r
+  PHYSICAL_ADDRESS                  ProfileBuffer;\r
+} SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA;\r
+\r
+typedef struct {\r
+  SMRAM_PROFILE_PARAMETER_HEADER    Header;\r
+  EFI_GUID                          FileName;\r
+  PHYSICAL_ADDRESS                  ImageBuffer;\r
+  UINT64                            NumberOfPage;\r
+} SMRAM_PROFILE_PARAMETER_REGISTER_IMAGE;\r
+\r
+typedef struct {\r
+  SMRAM_PROFILE_PARAMETER_HEADER    Header;\r
+  EFI_GUID                          FileName;\r
+  PHYSICAL_ADDRESS                  ImageBuffer;\r
+  UINT64                            NumberOfPage;\r
+} SMRAM_PROFILE_PARAMETER_UNREGISTER_IMAGE;\r
+\r
+\r
+#define EDKII_MEMORY_PROFILE_GUID { \\r
+  0x821c9a09, 0x541a, 0x40f6, 0x9f, 0x43, 0xa, 0xd1, 0x93, 0xa1, 0x2c, 0xfe \\r
+}\r
+\r
+extern EFI_GUID gEdkiiMemoryProfileGuid;\r
+\r
+#endif\r
+\r
index 60fb20938591708ed13c0f543f475ef65f19e41f..0384e5614fa839aa7f9127c5c1eb6c6b5cd6a569 100644 (file)
 \r
   ## Include/Guid/StatusCodeDataTypeVariable.h\r
   gEdkiiStatusCodeDataTypeVariableGuid = { 0xf6ee6dbb, 0xd67f, 0x4ea0, { 0x8b, 0x96, 0x6a, 0x71, 0xb1, 0x9d, 0x84, 0xad }}\r
+  \r
+  ## Include/Guid/MemoryProfile.h\r
+  gEdkiiMemoryProfileGuid              = { 0x821c9a09, 0x541a, 0x40f6, { 0x9f, 0x43, 0xa, 0xd1, 0x93, 0xa1, 0x2c, 0xfe }}\r
 \r
 [Ppis]\r
   ## Include/Ppi/AtaController.h\r
   # @Prompt Default Creator Revision for ACPI table creation.\r
   gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultCreatorRevision|0x01000013|UINT32|0x30001038\r
 \r
+  ## The mask is used to control memory profile behavior.<BR><BR>\r
+  #  BIT0 - Enable UEFI memory profile.<BR>\r
+  #  BIT1 - Enable SMRAM profile.<BR>\r
+  # @Prompt Memory Profile Property.\r
+  # @Expression  0x80000002 | (gEfiMdeModulePkgTokenSpaceGuid.PcdMemoryProfilePropertyMask & 0xFC) == 0\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdMemoryProfilePropertyMask|0x0|UINT8|0x30001041\r
+\r
+  ## This flag is to control which memory types of alloc info will be recorded by DxeCore & SmmCore.<BR><BR>\r
+  # For SmmCore, only EfiRuntimeServicesCode and EfiRuntimeServicesData are valid.<BR>\r
+  #\r
+  # Below is bit mask for this PCD: (Order is same as UEFI spec)<BR>\r
+  #  EfiReservedMemoryType          0x0001<BR>\r
+  #  EfiLoaderCode                  0x0002<BR>\r
+  #  EfiLoaderData                  0x0004<BR>\r
+  #  EfiBootServicesCode            0x0008<BR>\r
+  #  EfiBootServicesData            0x0010<BR>\r
+  #  EfiRuntimeServicesCode         0x0020<BR>\r
+  #  EfiRuntimeServicesData         0x0040<BR>\r
+  #  EfiConventionalMemory          0x0080<BR>\r
+  #  EfiUnusableMemory              0x0100<BR>\r
+  #  EfiACPIReclaimMemory           0x0200<BR>\r
+  #  EfiACPIMemoryNVS               0x0400<BR>\r
+  #  EfiMemoryMappedIO              0x0800<BR>\r
+  #  EfiMemoryMappedIOPortSpace     0x1000<BR>\r
+  #  EfiPalCode                     0x2000<BR>\r
+  #  OS Reserved        0x8000000000000000<BR>\r
+  #\r
+  # e.g. Reserved+ACPINvs+ACPIReclaim+RuntimeCode+RuntimeData are needed, 0x661 should be used.<BR>\r
+  #\r
+  # @Prompt Memory profile memory type.\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdMemoryProfileMemoryType|0x0|UINT64|0x30001042\r
+\r
   ## UART clock frequency is for the baud rate configuration.\r
   # @Prompt Serial Port Clock Rate.\r
   gEfiMdeModulePkgTokenSpaceGuid.PcdSerialClockRate|1843200|UINT32|0x00010066\r
index f7a88ffb2b50b021cf70ee7c4abb03f5ecc50b4f..f15dfdf23e83c4254316d25d973a0e3043df20fe 100644 (file)
 \r
 [Components]\r
   MdeModulePkg/Application/HelloWorld/HelloWorld.inf\r
+  MdeModulePkg/Application/MemoryProfileInfo/MemoryProfileInfo.inf\r
 \r
   MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf\r
   MdeModulePkg/Bus/Pci/IncompatiblePciDeviceSupportDxe/IncompatiblePciDeviceSupportDxe.inf\r
index 30bc563e261ed5723923de9306c3ef3fe7b9dbd8..b6a80b4f6a86994569e75711222a1a8560ed0cc9 100644 (file)
Binary files a/MdeModulePkg/MdeModulePkg.uni and b/MdeModulePkg/MdeModulePkg.uni differ
index 2eba9d4263fbf8ced964ea6bb933d85bd2afc477..c761f609b9ddb7fa30f244f4e64f07e20b8cf98e 100644 (file)
   DebugAgentLib\r
   LockBoxLib\r
   CpuExceptionHandlerLib\r
+  DevicePathLib\r
 \r
 [Guids]\r
   gEfiBootScriptExecutorVariableGuid    ## PRODUCES ## UNDEFINED # SaveLockBox\r
   gEfiBootScriptExecutorContextGuid     ## PRODUCES ## UNDEFINED # SaveLockBox\r
+  gEdkiiMemoryProfileGuid               ## SOMETIMES_CONSUMES ## GUID # Locate protocol\r
 \r
 [Protocols]\r
   ## NOTIFY\r
@@ -78,7 +80,8 @@
   gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode  ## CONSUMES\r
 \r
 [Pcd]\r
-  gEfiMdeModulePkgTokenSpaceGuid.PcdUse1GPageTable          ## SOMETIMES_CONSUMES\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdUse1GPageTable              ## SOMETIMES_CONSUMES\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdMemoryProfilePropertyMask   ## CONSUMES\r
 \r
 [Depex]\r
   gEfiLockBoxProtocolGuid\r
index 6c1c304a150d5efd10bd5e4273c5ad169d1a1a3b..3fbdf5cd838e8e734d78521103fab2377621c02a 100644 (file)
@@ -208,6 +208,47 @@ S3BootScriptExecutorEntryFunction (
   return EFI_UNSUPPORTED;\r
 }\r
 \r
+/**\r
+  Register image to memory profile.\r
+\r
+  @param FileName       File name of the image.\r
+  @param ImageBase      Image base address.\r
+  @param ImageSize      Image size.\r
+  @param FileType       File type of the image.\r
+\r
+**/\r
+VOID\r
+RegisterMemoryProfileImage (\r
+  IN EFI_GUID                       *FileName,\r
+  IN PHYSICAL_ADDRESS               ImageBase,\r
+  IN UINT64                         ImageSize,\r
+  IN EFI_FV_FILETYPE                FileType\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+  EDKII_MEMORY_PROFILE_PROTOCOL     *ProfileProtocol;\r
+  MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FilePath;\r
+  UINT8                             TempBuffer[sizeof (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH) + sizeof (EFI_DEVICE_PATH_PROTOCOL)];\r
+\r
+  if ((PcdGet8 (PcdMemoryProfilePropertyMask) & BIT0) != 0) {\r
+\r
+    FilePath = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *)TempBuffer;\r
+    Status = gBS->LocateProtocol (&gEdkiiMemoryProfileGuid, NULL, (VOID **) &ProfileProtocol);\r
+    if (!EFI_ERROR (Status)) {\r
+      EfiInitializeFwVolDevicepathNode (FilePath, FileName);\r
+      SetDevicePathEndNode (FilePath + 1);\r
+\r
+      Status = ProfileProtocol->RegisterImage (\r
+                                  ProfileProtocol,\r
+                                  (EFI_DEVICE_PATH_PROTOCOL *) FilePath,\r
+                                  ImageBase,\r
+                                  ImageSize,\r
+                                  FileType\r
+                                  );\r
+    }\r
+  }\r
+}\r
+\r
 /**\r
   This is the Event notification function to reload BootScriptExecutor image\r
   to RESERVED mem and save it to LockBox.\r
@@ -302,6 +343,14 @@ ReadyToLockEventNotify (
   // Flush the instruction cache so the image data is written before we execute it\r
   //\r
   InvalidateInstructionCacheRange ((VOID *)(UINTN)ImageContext.ImageAddress, (UINTN)ImageContext.ImageSize);\r
+\r
+  RegisterMemoryProfileImage (\r
+    &gEfiCallerIdGuid,\r
+    ImageContext.ImageAddress,\r
+    ImageContext.ImageSize,\r
+    EFI_FV_FILETYPE_DRIVER\r
+    );\r
+\r
   Status = ((EFI_IMAGE_ENTRY_POINT)(UINTN)(ImageContext.EntryPoint)) (NewImageHandle, gST);\r
   ASSERT_EFI_ERROR (Status);\r
 \r
index a3522905a84fb06c79659a9a3bce8c10cffe16f8..772347a57e4a236a9a5fe4f023371b41f102d73a 100644 (file)
@@ -4,7 +4,7 @@
   This driver is dispatched by Dxe core and the driver will reload itself to ACPI reserved memory \r
   in the entry point. The functionality is to interpret and restore the S3 boot script \r
   \r
-Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>\r
 \r
 This program and the accompanying materials\r
 are licensed and made available under the terms and conditions of the BSD License\r
@@ -36,9 +36,12 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #include <Library/DebugAgentLib.h>\r
 #include <Library/LockBoxLib.h>\r
 #include <Library/CpuExceptionHandlerLib.h>\r
+#include <Library/DevicePathLib.h>\r
 \r
 #include <Guid/AcpiS3Context.h>\r
 #include <Guid/BootScriptExecutorVariable.h>\r
+#include <Guid/MemoryProfile.h>\r
+\r
 #include <Protocol/DxeSmmReadyToLock.h>\r
 #include <IndustryStandard/Acpi.h>\r
 /**\r