]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Core/PiSmmCore/SmramProfileRecord.c
IntelFsp2WrapperPkg: Add error handling for possible NULL ptr dereference
[mirror_edk2.git] / MdeModulePkg / Core / PiSmmCore / SmramProfileRecord.c
index 24ab1b1de4ed3903d65645c097e86439e43cc632..57b34a018dc40e1a82dbbb6b14cf560e6887f996 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   Support routines for SMRAM profile.\r
 \r
-  Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2014 - 2016, 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
@@ -69,11 +69,20 @@ GLOBAL_REMOVE_IF_UNREFERENCED MEMORY_PROFILE_CONTEXT_DATA mSmramProfileContext =
   },\r
   &mImageQueue,\r
 };\r
-GLOBAL_REMOVE_IF_UNREFERENCED MEMORY_PROFILE_CONTEXT_DATA *mSmramProfileContextPtr;\r
+GLOBAL_REMOVE_IF_UNREFERENCED MEMORY_PROFILE_CONTEXT_DATA *mSmramProfileContextPtr = NULL;\r
 \r
 BOOLEAN mSmramReadyToLock;\r
 BOOLEAN mSmramProfileRecordingStatus = FALSE;\r
 \r
+/**\r
+  Dump SMRAM infromation.\r
+\r
+**/\r
+VOID\r
+DumpSmramInfo (\r
+  VOID\r
+  );\r
+\r
 /**\r
   Return SMRAM profile context.\r
 \r
@@ -710,8 +719,7 @@ UnregisterSmramProfileImage (
 \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
+  Only need to record EfiRuntimeServicesCode and EfiRuntimeServicesData for SMRAM profile.\r
 \r
   @param MemoryType     Memory type.\r
 \r
@@ -726,12 +734,13 @@ SmmCoreNeedRecordProfile (
 {\r
   UINT64 TestBit;\r
 \r
-  if ((UINT32) MemoryType >= 0x80000000) {\r
-    TestBit = BIT63;\r
-  } else {\r
-    TestBit = LShiftU64 (1, MemoryType);\r
+  if (MemoryType != EfiRuntimeServicesCode &&\r
+      MemoryType != EfiRuntimeServicesData) {\r
+    return FALSE;\r
   }\r
 \r
+  TestBit = LShiftU64 (1, MemoryType);\r
+\r
   if ((PcdGet64 (PcdMemoryProfileMemoryType) & TestBit) != 0) {\r
     return TRUE;\r
   } else {\r
@@ -741,8 +750,9 @@ SmmCoreNeedRecordProfile (
 \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
+  If BIOS memory type (0 ~ EfiMaxMemoryType - 1), ProfileMemoryIndex = MemoryType.\r
+  As SMRAM profile is only to record EfiRuntimeServicesCode and EfiRuntimeServicesData,\r
+  so return input memory type directly.\r
 \r
   @param MemoryType     Memory type.\r
 \r
@@ -754,11 +764,7 @@ GetProfileMemoryIndex (
   IN EFI_MEMORY_TYPE    MemoryType\r
   )\r
 {\r
-  if ((UINT32) MemoryType >= 0x80000000) {\r
-    return EfiMaxMemoryType;\r
-  } else {\r
-    return MemoryType;\r
-  }\r
+  return MemoryType;\r
 }\r
 \r
 /**\r
@@ -824,6 +830,8 @@ SmmCoreUpdateProfileAllocate (
   MEMORY_PROFILE_ALLOC_INFO_DATA    *AllocInfoData;\r
   EFI_MEMORY_TYPE                   ProfileMemoryIndex;\r
 \r
+  AllocInfoData = NULL;\r
+\r
   ContextData = GetSmramProfileContext ();\r
   if (ContextData == NULL) {\r
     return FALSE;\r
@@ -1173,61 +1181,6 @@ SmramProfileReadyToLock (
 \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
@@ -1303,11 +1256,17 @@ SmramProfileGetDataSize (
   Copy SMRAM profile data.\r
 \r
   @param ProfileBuffer  The buffer to hold SMRAM profile data.\r
+  @param ProfileSize    On input, profile buffer size.\r
+                        On output, actual profile data size copied.\r
+  @param ProfileOffset  On input, profile buffer offset to copy.\r
+                        On output, next time profile buffer offset to copy.\r
 \r
 **/\r
 VOID\r
 SmramProfileCopyData (\r
-  IN VOID   *ProfileBuffer\r
+  OUT VOID      *ProfileBuffer,\r
+  IN OUT UINT64 *ProfileSize,\r
+  IN OUT UINT64 *ProfileOffset\r
   )\r
 {\r
   MEMORY_PROFILE_CONTEXT           *Context;\r
@@ -1330,15 +1289,28 @@ SmramProfileCopyData (
   MEMORY_PROFILE_FREE_MEMORY      *FreeMemory;\r
   MEMORY_PROFILE_MEMORY_RANGE     *MemoryRange;\r
   MEMORY_PROFILE_DESCRIPTOR       *MemoryProfileDescriptor;\r
+  UINT64                          Offset;\r
+  UINT64                          RemainingSize;\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
+  RemainingSize = *ProfileSize;\r
+  Offset = 0;\r
+\r
+  if (*ProfileOffset < sizeof (MEMORY_PROFILE_CONTEXT)) {\r
+    if (RemainingSize >= sizeof (MEMORY_PROFILE_CONTEXT)) {\r
+      Context = ProfileBuffer;\r
+      CopyMem (Context, &ContextData->Context, sizeof (MEMORY_PROFILE_CONTEXT));\r
+      RemainingSize -= sizeof (MEMORY_PROFILE_CONTEXT);\r
+      ProfileBuffer = (UINT8 *) ProfileBuffer + sizeof (MEMORY_PROFILE_CONTEXT);\r
+    } else {\r
+      goto Done;\r
+    }\r
+  }\r
+  Offset += sizeof (MEMORY_PROFILE_CONTEXT);\r
 \r
   DriverInfoList = ContextData->DriverInfoList;\r
   for (DriverLink = DriverInfoList->ForwardLink;\r
@@ -1350,8 +1322,17 @@ SmramProfileCopyData (
                        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
+    if (*ProfileOffset < (Offset + sizeof (MEMORY_PROFILE_DRIVER_INFO))) {\r
+      if (RemainingSize >= sizeof (MEMORY_PROFILE_DRIVER_INFO)) {\r
+        DriverInfo = ProfileBuffer;\r
+        CopyMem (DriverInfo, &DriverInfoData->DriverInfo, sizeof (MEMORY_PROFILE_DRIVER_INFO));\r
+        RemainingSize -= sizeof (MEMORY_PROFILE_DRIVER_INFO);\r
+        ProfileBuffer = (UINT8 *) ProfileBuffer + sizeof (MEMORY_PROFILE_DRIVER_INFO);\r
+      } else {\r
+        goto Done;\r
+      }\r
+    }\r
+    Offset += sizeof (MEMORY_PROFILE_DRIVER_INFO);\r
 \r
     AllocInfoList = DriverInfoData->AllocInfoList;\r
     for (AllocLink = AllocInfoList->ForwardLink;\r
@@ -1363,30 +1344,73 @@ SmramProfileCopyData (
                         Link,\r
                         MEMORY_PROFILE_ALLOC_INFO_SIGNATURE\r
                         );\r
-      CopyMem (AllocInfo, &AllocInfoData->AllocInfo, sizeof (MEMORY_PROFILE_ALLOC_INFO));\r
-      AllocInfo += 1;\r
+      if (*ProfileOffset < (Offset + sizeof (MEMORY_PROFILE_ALLOC_INFO))) {\r
+        if (RemainingSize >= sizeof (MEMORY_PROFILE_ALLOC_INFO)) {\r
+          AllocInfo = ProfileBuffer;\r
+          CopyMem (AllocInfo, &AllocInfoData->AllocInfo, sizeof (MEMORY_PROFILE_ALLOC_INFO));\r
+          RemainingSize -= sizeof (MEMORY_PROFILE_ALLOC_INFO);\r
+          ProfileBuffer = (UINT8 *) ProfileBuffer + sizeof (MEMORY_PROFILE_ALLOC_INFO);\r
+        } else {\r
+          goto Done;\r
+        }\r
+      }\r
+      Offset += sizeof (MEMORY_PROFILE_ALLOC_INFO);\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
+  if (*ProfileOffset < (Offset + sizeof (MEMORY_PROFILE_FREE_MEMORY))) {\r
+    if (RemainingSize >= sizeof (MEMORY_PROFILE_FREE_MEMORY)) {\r
+      FreeMemory = ProfileBuffer;\r
+      CopyMem (FreeMemory, &mSmramFreeMemory, sizeof (MEMORY_PROFILE_FREE_MEMORY));\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[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
+            Index++;\r
+          }\r
+        }\r
+      }\r
+      FreeMemory->FreeMemoryEntryCount = Index;\r
+\r
+      RemainingSize -= sizeof (MEMORY_PROFILE_FREE_MEMORY);\r
+      ProfileBuffer = (UINT8 *) ProfileBuffer + sizeof (MEMORY_PROFILE_FREE_MEMORY);\r
+    } else {\r
+      goto Done;\r
+    }\r
+  }\r
+  Offset += sizeof (MEMORY_PROFILE_FREE_MEMORY);\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
+    if (*ProfileOffset < (Offset + sizeof (MEMORY_PROFILE_DESCRIPTOR))) {\r
+      if (RemainingSize >= sizeof (MEMORY_PROFILE_DESCRIPTOR)) {\r
+        Pages = BASE_CR (Node, FREE_PAGE_LIST, Link);\r
+        MemoryProfileDescriptor = ProfileBuffer;\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
+\r
+        RemainingSize -= sizeof (MEMORY_PROFILE_DESCRIPTOR);\r
+        ProfileBuffer = (UINT8 *) ProfileBuffer + sizeof (MEMORY_PROFILE_DESCRIPTOR);\r
+      } else {\r
+        goto Done;\r
+      }\r
+    }\r
+    Offset += sizeof (MEMORY_PROFILE_DESCRIPTOR);\r
   }\r
   for (PoolListIndex = 0; PoolListIndex < MAX_POOL_INDEX; PoolListIndex++) {\r
     FreePoolList = &mSmmPoolLists[MAX_POOL_INDEX - PoolListIndex - 1];\r
@@ -1395,32 +1419,69 @@ SmramProfileCopyData (
          Node = Node->BackLink) {\r
       Pool = BASE_CR (Node, FREE_POOL_HEADER, Link);\r
       if (Pool->Header.Available) {\r
+        if (*ProfileOffset < (Offset + sizeof (MEMORY_PROFILE_DESCRIPTOR))) {\r
+          if (RemainingSize >= sizeof (MEMORY_PROFILE_DESCRIPTOR)) {\r
+            MemoryProfileDescriptor = ProfileBuffer;\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
+\r
+            RemainingSize -= sizeof (MEMORY_PROFILE_DESCRIPTOR);\r
+            ProfileBuffer = (UINT8 *) ProfileBuffer + sizeof (MEMORY_PROFILE_DESCRIPTOR);\r
+          } else {\r
+            goto Done;\r
+          }\r
+        }\r
+        Offset += sizeof (MEMORY_PROFILE_DESCRIPTOR);\r
+      }\r
+    }\r
+  }\r
+\r
+  if (*ProfileOffset < (Offset + sizeof (MEMORY_PROFILE_MEMORY_RANGE))) {\r
+    if (RemainingSize >= sizeof (MEMORY_PROFILE_MEMORY_RANGE)) {\r
+      MemoryRange = ProfileBuffer;\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
+\r
+      RemainingSize -= sizeof (MEMORY_PROFILE_MEMORY_RANGE);\r
+      ProfileBuffer = (UINT8 *) ProfileBuffer + sizeof (MEMORY_PROFILE_MEMORY_RANGE);\r
+    } else {\r
+      goto Done;\r
+    }\r
+  }\r
+  Offset += sizeof (MEMORY_PROFILE_MEMORY_RANGE);\r
+  for (Index = 0; Index < mFullSmramRangeCount; Index++) {\r
+    if (*ProfileOffset < (Offset + sizeof (MEMORY_PROFILE_DESCRIPTOR))) {\r
+      if (RemainingSize >= sizeof (MEMORY_PROFILE_DESCRIPTOR)) {\r
+        MemoryProfileDescriptor = ProfileBuffer;\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
+        MemoryProfileDescriptor->Address = mFullSmramRanges[Index].PhysicalStart;\r
+        MemoryProfileDescriptor->Size = mFullSmramRanges[Index].PhysicalSize;\r
+\r
+        RemainingSize -= sizeof (MEMORY_PROFILE_DESCRIPTOR);\r
+        ProfileBuffer = (UINT8 *) ProfileBuffer + sizeof (MEMORY_PROFILE_DESCRIPTOR);\r
+      } else {\r
+        goto Done;\r
       }\r
     }\r
+    Offset += sizeof (MEMORY_PROFILE_DESCRIPTOR);\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
+Done:\r
+  //\r
+  // On output, actual profile data size copied.\r
+  //\r
+  *ProfileSize -= RemainingSize;\r
+  //\r
+  // On output, next time profile buffer offset to copy.\r
+  //\r
+  *ProfileOffset = Offset;\r
 }\r
 \r
 /**\r
@@ -1463,6 +1524,7 @@ SmramProfileHandlerGetData (
   )\r
 {\r
   UINT64                                    ProfileSize;\r
+  UINT64                                    ProfileOffset;\r
   SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA  SmramProfileGetData;\r
   MEMORY_PROFILE_CONTEXT_DATA               *ContextData;\r
   BOOLEAN                                   SmramProfileRecordingStatus;\r
@@ -1483,7 +1545,7 @@ SmramProfileHandlerGetData (
   //\r
   // Sanity check\r
   //\r
-  if (!InternalIsAddressValid ((UINTN) SmramProfileGetData.ProfileBuffer, (UINTN) ProfileSize)) {\r
+  if (!SmmIsBufferOutsideSmmValid ((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
@@ -1496,14 +1558,58 @@ SmramProfileHandlerGetData (
     goto Done;\r
   }\r
 \r
+  ProfileOffset = 0;\r
+  SmramProfileCopyData ((VOID *) (UINTN) SmramProfileGetData.ProfileBuffer, &ProfileSize, &ProfileOffset);\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 get profile data by offset.\r
+\r
+  @param SmramProfileParameterGetDataByOffset   The parameter of SMM profile get data by offset.\r
+\r
+**/\r
+VOID\r
+SmramProfileHandlerGetDataByOffset (\r
+  IN SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA_BY_OFFSET     *SmramProfileParameterGetDataByOffset\r
+  )\r
+{\r
+  SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA_BY_OFFSET    SmramProfileGetDataByOffset;\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 (&SmramProfileGetDataByOffset, SmramProfileParameterGetDataByOffset, sizeof (SmramProfileGetDataByOffset));\r
+\r
+  //\r
+  // Sanity check\r
+  //\r
+  if (!SmmIsBufferOutsideSmmValid ((UINTN) SmramProfileGetDataByOffset.ProfileBuffer, (UINTN) SmramProfileGetDataByOffset.ProfileSize)) {\r
+    DEBUG ((EFI_D_ERROR, "SmramProfileHandlerGetDataByOffset: SMM ProfileBuffer in SMRAM or overflow!\n"));\r
+    SmramProfileParameterGetDataByOffset->Header.ReturnStatus = (UINT64) (INT64) (INTN) EFI_ACCESS_DENIED;\r
+    goto Done;\r
+  }\r
+\r
+  SmramProfileCopyData ((VOID *) (UINTN) SmramProfileGetDataByOffset.ProfileBuffer, &SmramProfileGetDataByOffset.ProfileSize, &SmramProfileGetDataByOffset.ProfileOffset);\r
+  CopyMem (SmramProfileParameterGetDataByOffset, &SmramProfileGetDataByOffset, sizeof (SmramProfileGetDataByOffset));\r
+  SmramProfileParameterGetDataByOffset->Header.ReturnStatus = 0;\r
+\r
+Done:\r
+  mSmramProfileRecordingStatus = SmramProfileRecordingStatus;\r
+}\r
+\r
 /**\r
   SMRAM profile handler to register SMM image.\r
 \r
@@ -1608,7 +1714,7 @@ SmramProfileHandler (
     return EFI_SUCCESS;\r
   }\r
 \r
-  if (mSmramReadyToLock && !InternalIsAddressValid ((UINTN)CommBuffer, TempCommBufferSize)) {\r
+  if (mSmramReadyToLock && !SmmIsBufferOutsideSmmValid ((UINTN)CommBuffer, TempCommBufferSize)) {\r
     DEBUG ((EFI_D_ERROR, "SmramProfileHandler: SMM communication buffer in SMRAM or overflow!\n"));\r
     return EFI_SUCCESS;\r
   }\r
@@ -1639,6 +1745,14 @@ SmramProfileHandler (
     }\r
     SmramProfileHandlerGetData ((SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA *) (UINTN) CommBuffer);\r
     break;\r
+  case SMRAM_PROFILE_COMMAND_GET_PROFILE_DATA_BY_OFFSET:\r
+    DEBUG ((EFI_D_ERROR, "SmramProfileHandlerGetDataByOffset\n"));\r
+    if (TempCommBufferSize != sizeof (SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA_BY_OFFSET)) {\r
+      DEBUG ((EFI_D_ERROR, "SmramProfileHandler: SMM communication buffer size invalid!\n"));\r
+      return EFI_SUCCESS;\r
+    }\r
+    SmramProfileHandlerGetDataByOffset ((SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA_BY_OFFSET *) (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
@@ -1831,24 +1945,38 @@ GLOBAL_REMOVE_IF_UNREFERENCED CHAR16 *mActionString[] = {
   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
+typedef struct {\r
+  EFI_MEMORY_TYPE   MemoryType;\r
+  CHAR16            *MemoryTypeStr;\r
+} PROFILE_MEMORY_TYPE_STRING;\r
+\r
+GLOBAL_REMOVE_IF_UNREFERENCED PROFILE_MEMORY_TYPE_STRING mMemoryTypeString[] = {\r
+  {EfiRuntimeServicesCode, L"EfiRuntimeServicesCode"},\r
+  {EfiRuntimeServicesData, L"EfiRuntimeServicesData"}\r
 };\r
 \r
+/**\r
+  Memory type to string.\r
+\r
+  @param[in] MemoryType Memory type.\r
+\r
+  @return Pointer to string.\r
+\r
+**/\r
+CHAR16 *\r
+ProfileMemoryTypeToStr (\r
+  IN EFI_MEMORY_TYPE    MemoryType\r
+  )\r
+{\r
+  UINTN     Index;\r
+  for (Index = 0; Index < sizeof (mMemoryTypeString) / sizeof (mMemoryTypeString[0]); Index++) {\r
+    if (mMemoryTypeString[Index].MemoryType == MemoryType) {\r
+      return mMemoryTypeString[Index].MemoryTypeStr;\r
+    }\r
+  }\r
+\r
+  return L"UnexpectedMemoryType";\r
+}\r
 \r
 /**\r
   Dump SMRAM profile.\r
@@ -1888,11 +2016,11 @@ DumpSmramProfile (
 \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
+  for (TypeIndex = 0; TypeIndex < sizeof (Context->CurrentTotalUsageByType) / sizeof (Context->CurrentTotalUsageByType[0]); 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
+      DEBUG ((EFI_D_INFO, "  CurrentTotalUsage[0x%02x]  - 0x%016lx (%s)\n", TypeIndex, Context->CurrentTotalUsageByType[TypeIndex], ProfileMemoryTypeToStr (TypeIndex)));\r
+      DEBUG ((EFI_D_INFO, "  PeakTotalUsage[0x%02x]     - 0x%016lx (%s)\n", TypeIndex, Context->PeakTotalUsageByType[TypeIndex], ProfileMemoryTypeToStr (TypeIndex)));\r
     }\r
   }\r
   DEBUG ((EFI_D_INFO, "  TotalImageSize        - 0x%016lx\n", Context->TotalImageSize));\r
@@ -1919,11 +2047,11 @@ DumpSmramProfile (
     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
+    for (TypeIndex = 0; TypeIndex < sizeof (DriverInfo->CurrentUsageByType) / sizeof (DriverInfo->CurrentUsageByType[0]); 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
+        DEBUG ((EFI_D_INFO, "    CurrentUsage[0x%02x]     - 0x%016lx (%s)\n", TypeIndex, DriverInfo->CurrentUsageByType[TypeIndex], ProfileMemoryTypeToStr (TypeIndex)));\r
+        DEBUG ((EFI_D_INFO, "    PeakUsage[0x%02x]        - 0x%016lx (%s)\n", TypeIndex, DriverInfo->PeakUsageByType[TypeIndex], ProfileMemoryTypeToStr (TypeIndex)));\r
       }\r
     }\r
     DEBUG ((EFI_D_INFO, "    AllocRecordCount    - 0x%08x\n", DriverInfo->AllocRecordCount));\r