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
UINT32 mPerformanceLength = 0;\r
UINT32 mMaxPerformanceLength = 0;\r
UINT32 mBootRecordSize = 0;\r
-UINT32 mBootRecordMaxSize = 0;\r
+UINTN mBootRecordMaxSize = 0;\r
UINT32 mCachedLength = 0;\r
\r
BOOLEAN mFpdtBufferIsReported = FALSE;\r
}\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
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
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
}\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
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
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
}\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
{\r
EFI_STATUS Status;\r
EFI_HANDLE Handle;\r
+ EFI_EVENT EndOfDxeEvent;\r
EFI_EVENT ReadyToBootEvent;\r
PERFORMANCE_PROPERTY *PerformanceProperty;\r
\r
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