MdeModulePkg-FPDT(4): Use fixed buffer for SMM_PERF_COMMUNICATE in PerfLib.
[mirror_edk2.git] / MdeModulePkg / Library / DxeSmmPerformanceLib / DxeSmmPerformanceLib.c
index 218cf8b4a7977ab5b86c4e7c5049b5a074e51b85..d8d06842734570df03bc933c386c2972c248b456 100644 (file)
@@ -32,10 +32,13 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 \r
 #include <Protocol/SmmCommunication.h>\r
 \r
+#include <Guid/PiSmmCommunicationRegionTable.h>\r
+#include <Library/UefiLib.h>\r
+\r
 #define SMM_PERFORMANCE_COMMUNICATION_BUFFER_SIZE (OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data)  + sizeof (SMM_PERF_COMMUNICATE))\r
 \r
 EFI_SMM_COMMUNICATION_PROTOCOL  *mSmmCommunication = NULL;\r
-UINT8                           mSmmPerformanceBuffer[SMM_PERFORMANCE_COMMUNICATION_BUFFER_SIZE];\r
+UINT8                           *mSmmPerformanceBuffer;\r
 GAUGE_DATA_ENTRY                *mGaugeData = NULL;\r
 UINTN                           mGaugeNumberOfEntries = 0;\r
 GAUGE_DATA_ENTRY_EX             *mGaugeDataEx = NULL;\r
@@ -383,11 +386,18 @@ GetAllSmmGaugeData (
   IN UINTN      LogEntryKey\r
   )\r
 {\r
-  EFI_STATUS                  Status;\r
-  EFI_SMM_COMMUNICATE_HEADER  *SmmCommBufferHeader;\r
-  SMM_PERF_COMMUNICATE        *SmmPerfCommData;\r
-  UINTN                       CommSize;\r
-  UINTN                       DataSize;\r
+  EFI_STATUS                                Status;\r
+  EFI_SMM_COMMUNICATE_HEADER                *SmmCommBufferHeader;\r
+  SMM_PERF_COMMUNICATE                      *SmmPerfCommData;\r
+  UINTN                                     CommSize;\r
+  UINTN                                     DataSize;\r
+  EDKII_PI_SMM_COMMUNICATION_REGION_TABLE   *PiSmmCommunicationRegionTable;\r
+  UINT32                                    Index;\r
+  EFI_MEMORY_DESCRIPTOR                     *Entry;\r
+  UINT8                                     *Buffer;\r
+  UINTN                                     Size;\r
+  UINTN                                     NumberOfEntries;\r
+  UINTN                                     EntriesGot;\r
 \r
   if (mNoSmmPerfHandler) {\r
     //\r
@@ -417,6 +427,28 @@ GetAllSmmGaugeData (
     return NULL;\r
   }\r
 \r
+  Status = EfiGetSystemConfigurationTable (\r
+             &gEdkiiPiSmmCommunicationRegionTableGuid,\r
+             (VOID **) &PiSmmCommunicationRegionTable\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    return NULL;\r
+  }\r
+  ASSERT (PiSmmCommunicationRegionTable != NULL);\r
+  Entry = (EFI_MEMORY_DESCRIPTOR *) (PiSmmCommunicationRegionTable + 1);\r
+  Size = 0;\r
+  for (Index = 0; Index < PiSmmCommunicationRegionTable->NumberOfEntries; Index++) {\r
+    if (Entry->Type == EfiConventionalMemory) {\r
+      Size = EFI_PAGES_TO_SIZE ((UINTN) Entry->NumberOfPages);\r
+      if (Size >= (SMM_PERFORMANCE_COMMUNICATION_BUFFER_SIZE + sizeof (GAUGE_DATA_ENTRY))) {\r
+        break;\r
+      }\r
+    }\r
+    Entry = (EFI_MEMORY_DESCRIPTOR *) ((UINT8 *) Entry + PiSmmCommunicationRegionTable->DescriptorSize);\r
+  }\r
+  ASSERT (Index < PiSmmCommunicationRegionTable->NumberOfEntries);\r
+  mSmmPerformanceBuffer = (UINT8 *) (UINTN) Entry->PhysicalStart;\r
+\r
   //\r
   // Initialize communicate buffer \r
   //\r
@@ -441,24 +473,37 @@ GetAllSmmGaugeData (
   }\r
 \r
   mGaugeNumberOfEntries = SmmPerfCommData->NumberOfEntries;\r
-  \r
+\r
+  Buffer = mSmmPerformanceBuffer + SMM_PERFORMANCE_COMMUNICATION_BUFFER_SIZE;\r
+  NumberOfEntries = (Size - SMM_PERFORMANCE_COMMUNICATION_BUFFER_SIZE) / sizeof (GAUGE_DATA_ENTRY);\r
   DataSize = mGaugeNumberOfEntries * sizeof(GAUGE_DATA_ENTRY);\r
   mGaugeData = AllocateZeroPool(DataSize);\r
   ASSERT (mGaugeData != NULL);\r
-  \r
+\r
   //\r
   // Get all SMM gauge data\r
   //  \r
   SmmPerfCommData->Function = SMM_PERF_FUNCTION_GET_GAUGE_DATA;\r
-  SmmPerfCommData->LogEntryKey = 0;\r
-  SmmPerfCommData->NumberOfEntries = mGaugeNumberOfEntries;\r
-  SmmPerfCommData->GaugeData = mGaugeData;\r
-  Status = mSmmCommunication->Communicate (mSmmCommunication, mSmmPerformanceBuffer, &CommSize);\r
-  if (EFI_ERROR (Status) || EFI_ERROR (SmmPerfCommData->ReturnStatus)) {\r
-    FreePool (mGaugeData);\r
-    mGaugeData = NULL;\r
-    mGaugeNumberOfEntries = 0;\r
-  }\r
+  SmmPerfCommData->GaugeData = (GAUGE_DATA_ENTRY *) Buffer;\r
+  EntriesGot = 0;\r
+  do {\r
+    SmmPerfCommData->LogEntryKey = EntriesGot;\r
+    if ((mGaugeNumberOfEntries - EntriesGot) >= NumberOfEntries) {\r
+      SmmPerfCommData->NumberOfEntries = NumberOfEntries;\r
+    } else {\r
+      SmmPerfCommData->NumberOfEntries = mGaugeNumberOfEntries - EntriesGot;\r
+    }\r
+    Status = mSmmCommunication->Communicate (mSmmCommunication, mSmmPerformanceBuffer, &CommSize);\r
+    if (EFI_ERROR (Status) || EFI_ERROR (SmmPerfCommData->ReturnStatus)) {\r
+      FreePool (mGaugeData);\r
+      mGaugeData = NULL;\r
+      mGaugeNumberOfEntries = 0;\r
+      return NULL;\r
+    } else {\r
+      CopyMem (&mGaugeData[EntriesGot], Buffer, SmmPerfCommData->NumberOfEntries * sizeof (GAUGE_DATA_ENTRY));\r
+    }\r
+    EntriesGot += SmmPerfCommData->NumberOfEntries;\r
+  } while (EntriesGot < mGaugeNumberOfEntries);\r
 \r
   return mGaugeData;\r
 }\r
@@ -481,11 +526,18 @@ GetAllSmmGaugeDataEx (
   IN UINTN      LogEntryKey\r
   )\r
 {\r
-  EFI_STATUS                  Status;\r
-  EFI_SMM_COMMUNICATE_HEADER  *SmmCommBufferHeader;\r
-  SMM_PERF_COMMUNICATE_EX     *SmmPerfCommData;\r
-  UINTN                       CommSize;\r
-  UINTN                       DataSize;\r
+  EFI_STATUS                                Status;\r
+  EFI_SMM_COMMUNICATE_HEADER                *SmmCommBufferHeader;\r
+  SMM_PERF_COMMUNICATE_EX                   *SmmPerfCommData;\r
+  UINTN                                     CommSize;\r
+  UINTN                                     DataSize;\r
+  EDKII_PI_SMM_COMMUNICATION_REGION_TABLE   *PiSmmCommunicationRegionTable;\r
+  UINT32                                    Index;\r
+  EFI_MEMORY_DESCRIPTOR                     *Entry;\r
+  UINT8                                     *Buffer;\r
+  UINTN                                     Size;\r
+  UINTN                                     NumberOfEntries;\r
+  UINTN                                     EntriesGot;\r
 \r
   if (mNoSmmPerfExHandler) {\r
     //\r
@@ -515,6 +567,27 @@ GetAllSmmGaugeDataEx (
     return NULL;\r
   }\r
 \r
+  Status = EfiGetSystemConfigurationTable (\r
+             &gEdkiiPiSmmCommunicationRegionTableGuid,\r
+             (VOID **) &PiSmmCommunicationRegionTable\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    return NULL;\r
+  }\r
+  ASSERT (PiSmmCommunicationRegionTable != NULL);\r
+  Entry = (EFI_MEMORY_DESCRIPTOR *) (PiSmmCommunicationRegionTable + 1);\r
+  Size = 0;\r
+  for (Index = 0; Index < PiSmmCommunicationRegionTable->NumberOfEntries; Index++) {\r
+    if (Entry->Type == EfiConventionalMemory) {\r
+      Size = EFI_PAGES_TO_SIZE ((UINTN) Entry->NumberOfPages);\r
+      if (Size >= (SMM_PERFORMANCE_COMMUNICATION_BUFFER_SIZE + sizeof (GAUGE_DATA_ENTRY_EX))) {\r
+        break;\r
+      }\r
+    }\r
+    Entry = (EFI_MEMORY_DESCRIPTOR *) ((UINT8 *) Entry + PiSmmCommunicationRegionTable->DescriptorSize);\r
+  }\r
+  ASSERT (Index < PiSmmCommunicationRegionTable->NumberOfEntries);\r
+  mSmmPerformanceBuffer = (UINT8 *) (UINTN) Entry->PhysicalStart;\r
   //\r
   // Initialize communicate buffer \r
   //\r
@@ -539,25 +612,38 @@ GetAllSmmGaugeDataEx (
   }\r
 \r
   mGaugeNumberOfEntriesEx = SmmPerfCommData->NumberOfEntries;\r
-  \r
+\r
+  Buffer = mSmmPerformanceBuffer + SMM_PERFORMANCE_COMMUNICATION_BUFFER_SIZE;\r
+  NumberOfEntries = (Size - SMM_PERFORMANCE_COMMUNICATION_BUFFER_SIZE) / sizeof (GAUGE_DATA_ENTRY_EX);\r
   DataSize = mGaugeNumberOfEntriesEx * sizeof(GAUGE_DATA_ENTRY_EX);\r
   mGaugeDataEx = AllocateZeroPool(DataSize);\r
   ASSERT (mGaugeDataEx != NULL);\r
-  \r
+\r
   //\r
   // Get all SMM gauge data\r
   //  \r
   SmmPerfCommData->Function = SMM_PERF_FUNCTION_GET_GAUGE_DATA;\r
-  SmmPerfCommData->LogEntryKey = 0;\r
-  SmmPerfCommData->NumberOfEntries = mGaugeNumberOfEntriesEx;\r
-  SmmPerfCommData->GaugeDataEx = mGaugeDataEx;\r
-  Status = mSmmCommunication->Communicate (mSmmCommunication, mSmmPerformanceBuffer, &CommSize);\r
-  if (EFI_ERROR (Status) || EFI_ERROR (SmmPerfCommData->ReturnStatus)) {\r
-    FreePool (mGaugeDataEx);\r
-    mGaugeDataEx = NULL;\r
-    mGaugeNumberOfEntriesEx = 0;\r
-  }\r
\r
+  SmmPerfCommData->GaugeDataEx = (GAUGE_DATA_ENTRY_EX *) Buffer;\r
+  EntriesGot = 0;\r
+  do {\r
+    SmmPerfCommData->LogEntryKey = EntriesGot;\r
+    if ((mGaugeNumberOfEntriesEx - EntriesGot) >= NumberOfEntries) {\r
+      SmmPerfCommData->NumberOfEntries = NumberOfEntries;\r
+    } else {\r
+      SmmPerfCommData->NumberOfEntries = mGaugeNumberOfEntriesEx - EntriesGot;\r
+    }\r
+    Status = mSmmCommunication->Communicate (mSmmCommunication, mSmmPerformanceBuffer, &CommSize);\r
+    if (EFI_ERROR (Status) || EFI_ERROR (SmmPerfCommData->ReturnStatus)) {\r
+      FreePool (mGaugeDataEx);\r
+      mGaugeDataEx = NULL;\r
+      mGaugeNumberOfEntriesEx = 0;\r
+      return NULL;\r
+    } else {\r
+      CopyMem (&mGaugeDataEx[EntriesGot], Buffer, SmmPerfCommData->NumberOfEntries * sizeof (GAUGE_DATA_ENTRY_EX));\r
+    }\r
+    EntriesGot += SmmPerfCommData->NumberOfEntries;\r
+  } while (EntriesGot < mGaugeNumberOfEntriesEx);\r
+\r
   return mGaugeDataEx;\r
 }\r
 \r