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
-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
-http://opensource.org/licenses/bsd-license.php\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
**/\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
ControllerNameStringSize = FPDT_MAX_PERF_RECORD_SIZE - (*Length) - 1;\r
}\r
\r
- UnicodeStrToAsciiStrS(StringPtr, ComponentNameString, ControllerNameStringSize);\r
+ UnicodeStrnToAsciiStrS(StringPtr, ControllerNameStringSize - 1, ComponentNameString, ControllerNameStringSize, &ControllerNameStringSize);\r
\r
//\r
// Add a space in the end of the ControllerName\r
AsciiStringPtr = ComponentNameString;\r
}\r
\r
- UnicodeStrToAsciiStrS(StringPtr, AsciiStringPtr, DevicePathStringSize);\r
+ UnicodeStrnToAsciiStrS(StringPtr, DevicePathStringSize - 1, AsciiStringPtr, DevicePathStringSize, &DevicePathStringSize);\r
*Length += (UINT8)DevicePathStringSize;\r
return EFI_SUCCESS;\r
}\r
**/\r
EFI_STATUS\r
InsertFpdtRecord (\r
- IN CONST VOID *CallerIdentifier, OPTIONAL\r
- IN CONST VOID *Guid, OPTIONAL\r
- IN CONST CHAR8 *String, OPTIONAL\r
+ IN CONST VOID *CallerIdentifier OPTIONAL,\r
+ IN CONST VOID *Guid OPTIONAL,\r
+ IN CONST CHAR8 *String OPTIONAL,\r
IN UINT64 Ticker,\r
- IN UINT64 Address, OPTIONAL\r
+ IN UINT64 Address OPTIONAL,\r
IN UINT16 PerfId,\r
IN PERF_MEASUREMENT_ATTRIBUTE Attribute\r
)\r
switch (PerfId) {\r
case MODULE_START_ID:\r
case MODULE_END_ID:\r
- GetModuleInfoFromHandle ((EFI_HANDLE *)CallerIdentifier, ModuleName, sizeof (ModuleName), &ModuleGuid);\r
+ GetModuleInfoFromHandle ((EFI_HANDLE)CallerIdentifier, ModuleName, sizeof (ModuleName), &ModuleGuid);\r
StringPtr = ModuleName;\r
//\r
// Cache the offset of start image start record and use to update the start image end record if needed.\r
\r
case MODULE_LOADIMAGE_START_ID:\r
case MODULE_LOADIMAGE_END_ID:\r
- GetModuleInfoFromHandle ((EFI_HANDLE *)CallerIdentifier, ModuleName, sizeof (ModuleName), &ModuleGuid);\r
+ GetModuleInfoFromHandle ((EFI_HANDLE)CallerIdentifier, ModuleName, sizeof (ModuleName), &ModuleGuid);\r
StringPtr = ModuleName;\r
if (PerfId == MODULE_LOADIMAGE_START_ID) {\r
mLoadImageCount ++;\r
case MODULE_DB_SUPPORT_END_ID:\r
case MODULE_DB_STOP_START_ID:\r
case MODULE_DB_STOP_END_ID:\r
- GetModuleInfoFromHandle ((EFI_HANDLE *)CallerIdentifier, ModuleName, sizeof (ModuleName), &ModuleGuid);\r
+ GetModuleInfoFromHandle ((EFI_HANDLE)CallerIdentifier, ModuleName, sizeof (ModuleName), &ModuleGuid);\r
StringPtr = ModuleName;\r
if (!PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {\r
FpdtRecordPtr.GuidQwordEvent->Header.Type = FPDT_GUID_QWORD_EVENT_TYPE;\r
break;\r
\r
case MODULE_DB_END_ID:\r
- GetModuleInfoFromHandle ((EFI_HANDLE *)CallerIdentifier, ModuleName, sizeof (ModuleName), &ModuleGuid);\r
+ GetModuleInfoFromHandle ((EFI_HANDLE)CallerIdentifier, ModuleName, sizeof (ModuleName), &ModuleGuid);\r
StringPtr = ModuleName;\r
if (!PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {\r
FpdtRecordPtr.GuidQwordStringEvent->Header.Type = FPDT_GUID_QWORD_STRING_EVENT_TYPE;\r
case PERF_EVENTSIGNAL_END_ID:\r
case PERF_CALLBACK_START_ID:\r
case PERF_CALLBACK_END_ID:\r
- if (String == NULL) {\r
+ if (String == NULL || Guid == NULL) {\r
return EFI_INVALID_PARAMETER;\r
}\r
- //\r
- // Cache the event guid in string event record when PcdEdkiiFpdtStringRecordEnableOnly == TRUE\r
- //\r
- CopyGuid (&ModuleGuid, Guid);\r
StringPtr = String;\r
+ if (AsciiStrLen (String) == 0) {\r
+ StringPtr = "unknown name";\r
+ }\r
if (!PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {\r
FpdtRecordPtr.DualGuidStringEvent->Header.Type = FPDT_DUAL_GUID_STRING_EVENT_TYPE;\r
FpdtRecordPtr.DualGuidStringEvent->Header.Length = sizeof (FPDT_DUAL_GUID_STRING_EVENT_RECORD);\r
case PERF_INMODULE_END_ID:\r
case PERF_CROSSMODULE_START_ID:\r
case PERF_CROSSMODULE_END_ID:\r
- GetModuleInfoFromHandle ((EFI_HANDLE *)CallerIdentifier, ModuleName, sizeof (ModuleName), &ModuleGuid);\r
+ GetModuleInfoFromHandle ((EFI_HANDLE)CallerIdentifier, ModuleName, sizeof (ModuleName), &ModuleGuid);\r
if (String != NULL) {\r
StringPtr = String;\r
} else {\r
\r
default:\r
if (Attribute != PerfEntry) {\r
- GetModuleInfoFromHandle ((EFI_HANDLE *)CallerIdentifier, ModuleName, sizeof (ModuleName), &ModuleGuid);\r
+ GetModuleInfoFromHandle ((EFI_HANDLE)CallerIdentifier, ModuleName, sizeof (ModuleName), &ModuleGuid);\r
if (String != NULL) {\r
StringPtr = String;\r
} else {\r
FpdtRecordPtr.DynamicStringEvent->Header.Revision = FPDT_RECORD_REVISION_1;\r
FpdtRecordPtr.DynamicStringEvent->ProgressID = PerfId;\r
FpdtRecordPtr.DynamicStringEvent->Timestamp = TimeStamp;\r
- CopyMem (&FpdtRecordPtr.DynamicStringEvent->Guid, &ModuleGuid, sizeof (FpdtRecordPtr.DynamicStringEvent->Guid));\r
+ if (Guid != NULL) {\r
+ //\r
+ // Cache the event guid in string event record.\r
+ //\r
+ CopyMem (&FpdtRecordPtr.DynamicStringEvent->Guid, Guid, sizeof (FpdtRecordPtr.DynamicStringEvent->Guid));\r
+ } else {\r
+ CopyMem (&FpdtRecordPtr.DynamicStringEvent->Guid, &ModuleGuid, sizeof (FpdtRecordPtr.DynamicStringEvent->Guid));\r
+ }\r
if (AsciiStrLen (StringPtr) == 0) {\r
StringPtr = "unknown name";\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
+ SmmBootRecordDataSize = 0;\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
EFIAPI\r
CreatePerformanceMeasurement (\r
IN CONST VOID *CallerIdentifier,\r
- IN CONST VOID *Guid, OPTIONAL\r
- IN CONST CHAR8 *String, OPTIONAL\r
+ IN CONST VOID *Guid OPTIONAL,\r
+ IN CONST CHAR8 *String OPTIONAL,\r
IN UINT64 TimeStamp,\r
- IN UINT64 Address, OPTIONAL\r
+ IN UINT64 Address OPTIONAL,\r
IN UINT32 Identifier,\r
IN PERF_MEASUREMENT_ATTRIBUTE Attribute\r
)\r
RETURN_STATUS\r
EFIAPI\r
StartPerformanceMeasurementEx (\r
- IN CONST VOID *Handle, OPTIONAL\r
- IN CONST CHAR8 *Token, OPTIONAL\r
- IN CONST CHAR8 *Module, OPTIONAL\r
+ IN CONST VOID *Handle OPTIONAL,\r
+ IN CONST CHAR8 *Token OPTIONAL,\r
+ IN CONST CHAR8 *Module OPTIONAL,\r
IN UINT64 TimeStamp,\r
IN UINT32 Identifier\r
)\r
RETURN_STATUS\r
EFIAPI\r
EndPerformanceMeasurementEx (\r
- IN CONST VOID *Handle, OPTIONAL\r
- IN CONST CHAR8 *Token, OPTIONAL\r
- IN CONST CHAR8 *Module, OPTIONAL\r
+ IN CONST VOID *Handle OPTIONAL,\r
+ IN CONST CHAR8 *Token OPTIONAL,\r
+ IN CONST CHAR8 *Module OPTIONAL,\r
IN UINT64 TimeStamp,\r
IN UINT32 Identifier\r
)\r
RETURN_STATUS\r
EFIAPI\r
StartPerformanceMeasurement (\r
- IN CONST VOID *Handle, OPTIONAL\r
- IN CONST CHAR8 *Token, OPTIONAL\r
- IN CONST CHAR8 *Module, OPTIONAL\r
+ IN CONST VOID *Handle OPTIONAL,\r
+ IN CONST CHAR8 *Token OPTIONAL,\r
+ IN CONST CHAR8 *Module OPTIONAL,\r
IN UINT64 TimeStamp\r
)\r
{\r
RETURN_STATUS\r
EFIAPI\r
EndPerformanceMeasurement (\r
- IN CONST VOID *Handle, OPTIONAL\r
- IN CONST CHAR8 *Token, OPTIONAL\r
- IN CONST CHAR8 *Module, OPTIONAL\r
+ IN CONST VOID *Handle OPTIONAL,\r
+ IN CONST CHAR8 *Token OPTIONAL,\r
+ IN CONST CHAR8 *Module OPTIONAL,\r
IN UINT64 TimeStamp\r
)\r
{\r
EFIAPI\r
LogPerformanceMeasurement (\r
IN CONST VOID *CallerIdentifier,\r
- IN CONST VOID *Guid, OPTIONAL\r
- IN CONST CHAR8 *String, OPTIONAL\r
- IN UINT64 Address, OPTIONAL\r
+ IN CONST VOID *Guid OPTIONAL,\r
+ IN CONST CHAR8 *String OPTIONAL,\r
+ IN UINT64 Address OPTIONAL,\r
IN UINT32 Identifier\r
)\r
{\r