]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Core/PiSmmCore/SmramProfileRecord.c
MdeModulePkg-MemoryProfile(2): Add SMRAM_PROFILE_COMMAND_GET_PROFILE_DATA_BY_OFFSET...
[mirror_edk2.git] / MdeModulePkg / Core / PiSmmCore / SmramProfileRecord.c
index 72fd37ece5a9fd026a0591b5f5bc76afb8de2f38..57b34a018dc40e1a82dbbb6b14cf560e6887f996 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   Support routines for SMRAM profile.\r
 \r
-  Copyright (c) 2014 - 2015, 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
@@ -1256,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
@@ -1283,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
@@ -1303,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
@@ -1316,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
@@ -1348,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
@@ -1416,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
@@ -1449,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
@@ -1592,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