]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLib.c
MdeModulePkg/FPDT: Lock boot performance table address variable at EndOfDxe
[mirror_edk2.git] / MdeModulePkg / Library / DxeCorePerformanceLib / DxeCorePerformanceLib.c
index d378c59dd9648e4af439f82a569b330ad450681d..532b3f8c90e26659470702379f360a14ab080bb8 100644 (file)
@@ -10,7 +10,7 @@
   This library is mainly used by DxeCore to start performance logging to ensure that\r
   Performance Protocol is installed at the very beginning of DXE phase.\r
 \r
-Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2006 - 2021, Intel Corporation. All rights reserved.<BR>\r
 (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>\r
 SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
@@ -64,7 +64,7 @@ UINT32  mLoadImageCount       = 0;
 UINT32  mPerformanceLength    = 0;\r
 UINT32  mMaxPerformanceLength = 0;\r
 UINT32  mBootRecordSize       = 0;\r
-UINT32  mBootRecordMaxSize    = 0;\r
+UINT  mBootRecordMaxSize    = 0;\r
 UINT32  mCachedLength         = 0;\r
 \r
 BOOLEAN mFpdtBufferIsReported = FALSE;\r
@@ -205,25 +205,26 @@ IsKnownID (
 }\r
 \r
 /**\r
-  Allocate buffer for Boot Performance table.\r
+  This internal function dumps all the SMM performance data and size.\r
 \r
-  @return Status code.\r
+  @param    SmmPerfData        Smm Performance data. The buffer contain the SMM perf data is allocated by this function and caller needs to free it.\r
+  @param    SmmPerfDataSize    Smm Performance data size.\r
+  @param    SkipGetPerfData    Skip to get performance data, just get the size.\r
 \r
 **/\r
-EFI_STATUS\r
-AllocateBootPerformanceTable (\r
+VOID\r
+InternalGetSmmPerfData (\r
+  OUT VOID      **SmmPerfData,\r
+  OUT UINTN     *SmmPerfDataSize,\r
+  IN  BOOLEAN   SkipGetPerfData\r
   )\r
 {\r
   EFI_STATUS                              Status;\r
-  UINTN                                   Size;\r
   UINT8                                   *SmmBootRecordCommBuffer;\r
   EFI_SMM_COMMUNICATE_HEADER              *SmmCommBufferHeader;\r
   SMM_BOOT_RECORD_COMMUNICATE             *SmmCommData;\r
   UINTN                                   CommSize;\r
-  UINTN                                   BootPerformanceDataSize;\r
-  UINT8                                   *BootPerformanceData;\r
   EFI_SMM_COMMUNICATION_PROTOCOL          *Communication;\r
-  FIRMWARE_PERFORMANCE_VARIABLE           PerformanceVariable;\r
   EDKII_PI_SMM_COMMUNICATION_REGION_TABLE *SmmCommRegionTable;\r
   EFI_MEMORY_DESCRIPTOR                   *SmmCommMemRegion;\r
   UINTN                                   Index;\r
@@ -237,7 +238,6 @@ AllocateBootPerformanceTable (
   SmmBootRecordCommBuffer = NULL;\r
   SmmCommData             = NULL;\r
   SmmBootRecordData       = NULL;\r
-  SmmBootRecordDataSize   = 0;\r
   ReservedMemSize         = 0;\r
   Status = gBS->LocateProtocol (&gEfiSmmCommunicationProtocolGuid, NULL, (VOID **) &Communication);\r
   if (!EFI_ERROR (Status)) {\r
@@ -284,6 +284,10 @@ AllocateBootPerformanceTable (
         Status = Communication->Communicate (Communication, SmmBootRecordCommBuffer, &CommSize);\r
 \r
         if (!EFI_ERROR (Status) && !EFI_ERROR (SmmCommData->ReturnStatus) && SmmCommData->BootRecordSize != 0) {\r
+          if (SkipGetPerfData) {\r
+            *SmmPerfDataSize = SmmCommData->BootRecordSize;\r
+            return;\r
+          }\r
           //\r
           // Get all boot records\r
           //\r
@@ -305,19 +309,45 @@ AllocateBootPerformanceTable (
             }\r
             SmmCommData->BootRecordOffset = SmmCommData->BootRecordOffset + SmmCommData->BootRecordSize;\r
           }\r
+          *SmmPerfData     = SmmBootRecordData;\r
+          *SmmPerfDataSize = SmmBootRecordDataSize;\r
         }\r
       }\r
     }\r
   }\r
+}\r
+\r
+/**\r
+  Allocate buffer for Boot Performance table.\r
+\r
+  @return Status code.\r
+\r
+**/\r
+EFI_STATUS\r
+AllocateBootPerformanceTable (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS                              Status;\r
+  UINTN                                   Size;\r
+  UINTN                                   BootPerformanceDataSize;\r
+  UINT8                                   *BootPerformanceData;\r
+  FIRMWARE_PERFORMANCE_VARIABLE           PerformanceVariable;\r
+  UINTN                                   SmmBootRecordDataSize;\r
+\r
+  SmmBootRecordDataSize = 0;\r
+\r
+  //\r
+  // Get SMM performance data size at the point of EndOfDxe in order to allocate the boot performance table.\r
+  // Will Get all the data at ReadyToBoot.\r
+  //\r
+  InternalGetSmmPerfData (NULL, &SmmBootRecordDataSize, TRUE);\r
 \r
   //\r
   // Prepare memory for Boot Performance table.\r
   // Boot Performance table includes BasicBoot record, and one or more appended Boot Records.\r
   //\r
-  BootPerformanceDataSize = sizeof (BOOT_PERFORMANCE_TABLE) + mPerformanceLength + PcdGet32 (PcdExtFpdtBootRecordPadSize);\r
-  if (SmmCommData != NULL && SmmBootRecordData != NULL) {\r
-    BootPerformanceDataSize += SmmBootRecordDataSize;\r
-  }\r
+  BootPerformanceDataSize = sizeof (BOOT_PERFORMANCE_TABLE) + mPerformanceLength + SmmBootRecordDataSize + PcdGet32 (PcdExtFpdtBootRecordPadSize);\r
 \r
   //\r
   // Try to allocate the same runtime buffer as last time boot.\r
@@ -358,9 +388,6 @@ AllocateBootPerformanceTable (
   DEBUG ((DEBUG_INFO, "DxeCorePerformanceLib: ACPI Boot Performance Table address = 0x%x\n", mAcpiBootPerformanceTable));\r
 \r
   if (mAcpiBootPerformanceTable == NULL) {\r
-    if (SmmCommData != NULL && SmmBootRecordData != NULL) {\r
-      FreePool (SmmBootRecordData);\r
-    }\r
     return EFI_OUT_OF_RESOURCES;\r
   }\r
 \r
@@ -385,19 +412,10 @@ AllocateBootPerformanceTable (
     mPerformanceLength    = 0;\r
     mMaxPerformanceLength = 0;\r
   }\r
-  if (SmmCommData != NULL && SmmBootRecordData != NULL) {\r
-    //\r
-    // Fill Boot records from SMM drivers.\r
-    //\r
-    CopyMem (BootPerformanceData, SmmBootRecordData, SmmBootRecordDataSize);\r
-    FreePool (SmmBootRecordData);\r
-    mAcpiBootPerformanceTable->Header.Length = (UINT32) (mAcpiBootPerformanceTable->Header.Length + SmmBootRecordDataSize);\r
-    BootPerformanceData = BootPerformanceData + SmmBootRecordDataSize;\r
-  }\r
 \r
   mBootRecordBuffer  = (UINT8 *) mAcpiBootPerformanceTable;\r
   mBootRecordSize    = mAcpiBootPerformanceTable->Header.Length;\r
-  mBootRecordMaxSize = mBootRecordSize + PcdGet32 (PcdExtFpdtBootRecordPadSize);\r
+  mBootRecordMaxSize = BootPerformanceDataSize;\r
 \r
   return EFI_SUCCESS;\r
 }\r
@@ -1336,6 +1354,47 @@ ReportFpdtRecordBuffer (
   }\r
 }\r
 \r
+/**\r
+  Update Boot Performance table.\r
+\r
+  @param  Event    The event of notify protocol.\r
+  @param  Context  Notify event context.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+UpdateBootPerformanceTable (\r
+  IN EFI_EVENT     Event,\r
+  IN VOID          *Context\r
+  )\r
+{\r
+  VOID                             *SmmBootRecordData;\r
+  UINTN                            SmmBootRecordDataSize;\r
+  UINTN                            AppendSize;\r
+  UINT8                            *FirmwarePerformanceTablePtr;\r
+\r
+  //\r
+  // Get SMM performance data.\r
+  //\r
+  SmmBootRecordData = NULL;\r
+  InternalGetSmmPerfData (&SmmBootRecordData, &SmmBootRecordDataSize, FALSE);\r
+\r
+  FirmwarePerformanceTablePtr = (UINT8 *) mAcpiBootPerformanceTable + mAcpiBootPerformanceTable->Header.Length;\r
+\r
+  if (mAcpiBootPerformanceTable->Header.Length + SmmBootRecordDataSize > mBootRecordMaxSize) {\r
+    DEBUG ((DEBUG_INFO, "DxeCorePerformanceLib: No enough space to save all SMM boot performance data\n"));\r
+    AppendSize = mBootRecordMaxSize - mAcpiBootPerformanceTable->Header.Length;\r
+  } else {\r
+    AppendSize = SmmBootRecordDataSize;\r
+  }\r
+  if (SmmBootRecordData != NULL) {\r
+    CopyMem (FirmwarePerformanceTablePtr, SmmBootRecordData, AppendSize);\r
+    mAcpiBootPerformanceTable->Header.Length += (UINT32) AppendSize;\r
+    mBootRecordSize +=  (UINT32) AppendSize;\r
+    FreePool (SmmBootRecordData);\r
+  }\r
+}\r
+\r
 /**\r
   The constructor function initializes Performance infrastructure for DXE phase.\r
 \r
@@ -1358,6 +1417,7 @@ DxeCorePerformanceLibConstructor (
 {\r
   EFI_STATUS                Status;\r
   EFI_HANDLE                Handle;\r
+  EFI_EVENT                 EndOfDxeEvent;\r
   EFI_EVENT                 ReadyToBootEvent;\r
   PERFORMANCE_PROPERTY      *PerformanceProperty;\r
 \r
@@ -1386,13 +1446,25 @@ DxeCorePerformanceLibConstructor (
   ASSERT_EFI_ERROR (Status);\r
 \r
   //\r
-  // Register ReadyToBoot event to report StatusCode data\r
+  // Register EndOfDxe event to allocate the boot performance table and report the table address through status code.\r
   //\r
   Status = gBS->CreateEventEx (\r
                   EVT_NOTIFY_SIGNAL,\r
-                  TPL_CALLBACK,\r
+                  TPL_NOTIFY,\r
                   ReportFpdtRecordBuffer,\r
                   NULL,\r
+                  &gEfiEndOfDxeEventGroupGuid,\r
+                  &EndOfDxeEvent\r
+                  );\r
+\r
+  //\r
+  // Register ReadyToBoot event to update the boot performance table for SMM performance data.\r
+  //\r
+  Status = gBS->CreateEventEx (\r
+                  EVT_NOTIFY_SIGNAL,\r
+                  TPL_CALLBACK,\r
+                  UpdateBootPerformanceTable,\r
+                  NULL,\r
                   &gEfiEventReadyToBootGuid,\r
                   &ReadyToBootEvent\r
                   );\r