From: Dandan Bi <dandan.bi@intel.com>
To: edk2-devel@lists.01.org
Cc: Liming Gao <liming.gao@intel.com>, Star Zeng <star.zeng@intel.com>
Subject: [patch V2 5/9] MdeModulePkg: Update performance library instances
Date: Fri, 22 Jun 2018 16:56:19 +0800 [thread overview]
Message-ID: <20180622085623.154924-6-dandan.bi@intel.com> (raw)
In-Reply-To: <20180622085623.154924-1-dandan.bi@intel.com>
Update the performance library instances in MdeModulePkg
to implement the APIs used for new added Perf macros.
V2:
Share the common logics of creating FPDT record for
new added Perf macros and existing Perf macros.
Cc: Liming Gao <liming.gao@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Dandan Bi <dandan.bi@intel.com>
---
.../Include/Guid/ExtendedFirmwarePerformance.h | 6 -
.../DxeCorePerformanceLib/DxeCorePerformanceLib.c | 864 +++++++++++++++------
.../DxeCorePerformanceLib.inf | 1 +
.../DxeCorePerformanceLibInternal.h | 1 +
.../Library/DxePerformanceLib/DxePerformanceLib.c | 68 ++
.../Library/PeiPerformanceLib/PeiPerformanceLib.c | 632 +++++++++------
.../SmmCorePerformanceLib/SmmCorePerformanceLib.c | 645 +++++++++------
.../Library/SmmPerformanceLib/SmmPerformanceLib.c | 68 ++
8 files changed, 1565 insertions(+), 720 deletions(-)
diff --git a/MdeModulePkg/Include/Guid/ExtendedFirmwarePerformance.h b/MdeModulePkg/Include/Guid/ExtendedFirmwarePerformance.h
index 465b4082750..dedb0b82f0d 100644
--- a/MdeModulePkg/Include/Guid/ExtendedFirmwarePerformance.h
+++ b/MdeModulePkg/Include/Guid/ExtendedFirmwarePerformance.h
@@ -218,16 +218,10 @@ typedef struct {
CHAR8 String[0];
} FPDT_GUID_QWORD_STRING_EVENT_RECORD;
#pragma pack()
-typedef struct {
- UINT16 ProgressID;
- UINT16 Type;
- UINT8 RecordSize;
-} FPDT_BASIC_RECORD_INFO;
-
//
// Union of all FPDT records
//
typedef union {
EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER RecordHeader;
diff --git a/MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLib.c b/MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLib.c
index 79820605184..efff5134c7b 100644
--- a/MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLib.c
+++ b/MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLib.c
@@ -69,17 +69,19 @@ UINTN mCachePairCount = 0;
UINT32 mLoadImageCount = 0;
UINT32 mPerformanceLength = 0;
UINT32 mMaxPerformanceLength = 0;
UINT32 mBootRecordSize = 0;
UINT32 mBootRecordMaxSize = 0;
+UINT32 mCachedLength = 0;
BOOLEAN mFpdtBufferIsReported = FALSE;
BOOLEAN mLackSpaceIsReported = FALSE;
CHAR8 *mPlatformLanguage = NULL;
UINT8 *mPerformancePointer = NULL;
UINT8 *mBootRecordBuffer = NULL;
BOOLEAN mLockInsertRecord = FALSE;
+CHAR8 *mDevicePathString = NULL;
EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *mDevicePathToText = NULL;
//
// Interfaces for PerformanceMeasurement Protocol.
@@ -88,10 +90,64 @@ EDKII_PERFORMANCE_MEASUREMENT_PROTOCOL mPerformanceMeasurementInterface = {
CreatePerformanceMeasurement,
};
PERFORMANCE_PROPERTY mPerformanceProperty;
+/**
+ Return the pointer to the FPDT record in the allocated memory.
+
+ @param RecordSize The size of FPDT record.
+ @param FpdtRecordPtr Pointer the FPDT record in the allocated memory.
+
+ @retval EFI_SUCCESS Successfully get the pointer to the FPDT record.
+ @retval EFI_OUT_OF_RESOURCES Ran out of space to store the records.
+**/
+EFI_STATUS
+GetFpdtRecordPtr (
+ IN UINT8 RecordSize,
+ IN OUT FPDT_RECORD_PTR *FpdtRecordPtr
+)
+{
+ if (mFpdtBufferIsReported) {
+ //
+ // Append Boot records to the boot performance table.
+ //
+ if (mBootRecordSize + RecordSize > mBootRecordMaxSize) {
+ if (!mLackSpaceIsReported) {
+ DEBUG ((DEBUG_INFO, "DxeCorePerformanceLib: No enough space to save boot records\n"));
+ mLackSpaceIsReported = TRUE;
+ }
+ return EFI_OUT_OF_RESOURCES;
+ } else {
+ //
+ // Save boot record into BootPerformance table
+ //
+ FpdtRecordPtr->RecordHeader = (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER *)(mBootRecordBuffer + mBootRecordSize);
+ }
+ } else {
+ //
+ // Check if pre-allocated buffer is full
+ //
+ if (mPerformanceLength + RecordSize > mMaxPerformanceLength) {
+ mPerformancePointer = ReallocatePool (
+ mPerformanceLength,
+ mPerformanceLength + RecordSize + FIRMWARE_RECORD_BUFFER,
+ mPerformancePointer
+ );
+ if (mPerformancePointer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ mMaxPerformanceLength = mPerformanceLength + RecordSize + FIRMWARE_RECORD_BUFFER;
+ }
+ //
+ // Covert buffer to FPDT Ptr Union type.
+ //
+ FpdtRecordPtr->RecordHeader = (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER *)(mPerformancePointer + mPerformanceLength);
+ }
+ return EFI_SUCCESS;
+}
+
/**
Check whether the Token is a known one which is uesed by core.
@param Token Pointer to a Null-terminated ASCII string
@@ -585,282 +641,355 @@ Done:
return Status;
}
/**
- Get the FPDT record info.
+ Get the FPDT record identifier.
- @param IsStart TRUE if the performance log is start log.
- @param Handle Pointer to environment specific context used
- to identify the component being measured.
- @param Token Pointer to a Null-terminated ASCII string
- that identifies the component being measured.
- @param Module Pointer to a Null-terminated ASCII string
- that identifies the module being measured.
- @param RecordInfo On return, pointer to the info of the record.
- @param UseModuleName Only useful for FPDT_DYNAMIC_STRING_EVENT_TYPE, indicate that whether need use
- Module name to fill the string field in the FPDT_DYNAMIC_STRING_EVENT_RECORD.
+ @param Attribute The attribute of the Record.
+ PerfStartEntry: Start Record.
+ PerfEndEntry: End Record.
+ @param Handle Pointer to environment specific context used to identify the component being measured.
+ @param String Pointer to a Null-terminated ASCII string that identifies the component being measured.
+ @param ProgressID On return, pointer to the ProgressID.
- @retval EFI_SUCCESS Get record info successfully.
- @retval EFI_UNSUPPORTED No matched FPDT record.
+ @retval EFI_SUCCESS Get record info successfully.
+ @retval EFI_INVALID_PARAMETER No matched FPDT record.
**/
EFI_STATUS
-GetFpdtRecordInfo (
- IN BOOLEAN IsStart,
- IN CONST VOID *Handle,
- IN CONST CHAR8 *Token,
- IN CONST CHAR8 *Module,
- OUT FPDT_BASIC_RECORD_INFO *RecordInfo,
- IN OUT BOOLEAN *UseModuleName
+GetFpdtRecordId (
+ IN PERF_MEASUREMENT_ATTRIBUTE Attribute,
+ IN CONST VOID *Handle,
+ IN CONST CHAR8 *String,
+ OUT UINT16 *ProgressID
)
{
- UINT16 RecordType;
- UINTN StringSize;
-
- RecordType = FPDT_DYNAMIC_STRING_EVENT_TYPE;
-
//
- // Token to Type and Id.
+ // Token to PerfId.
//
- if (Token != NULL) {
- if (AsciiStrCmp (Token, START_IMAGE_TOK) == 0) { // "StartImage:"
- *UseModuleName = TRUE;
- RecordType = FPDT_GUID_EVENT_TYPE;
- if (IsStart) {
- RecordInfo->ProgressID = MODULE_START_ID;
+ if (String != NULL) {
+ if (AsciiStrCmp (String, START_IMAGE_TOK) == 0) { // "StartImage:"
+ if (Attribute == PerfStartEntry) {
+ *ProgressID = MODULE_START_ID;
} else {
- RecordInfo->ProgressID = MODULE_END_ID;
+ *ProgressID = MODULE_END_ID;
}
- } else if (AsciiStrCmp (Token, LOAD_IMAGE_TOK) == 0) { // "LoadImage:"
- *UseModuleName = TRUE;
- RecordType = FPDT_GUID_QWORD_EVENT_TYPE;
- if (IsStart) {
- RecordInfo->ProgressID = MODULE_LOADIMAGE_START_ID;
+ } else if (AsciiStrCmp (String, LOAD_IMAGE_TOK) == 0) { // "LoadImage:"
+ if (Attribute == PerfStartEntry) {
+ *ProgressID = MODULE_LOADIMAGE_START_ID;
} else {
- RecordInfo->ProgressID = MODULE_LOADIMAGE_END_ID;
+ *ProgressID = MODULE_LOADIMAGE_END_ID;
}
- } else if (AsciiStrCmp (Token, DRIVERBINDING_START_TOK) == 0) { // "DB:Start:"
- *UseModuleName = TRUE;
- if (IsStart) {
- RecordInfo->ProgressID = MODULE_DB_START_ID;
- RecordType = FPDT_GUID_QWORD_EVENT_TYPE;
+ } else if (AsciiStrCmp (String, DRIVERBINDING_START_TOK) == 0) { // "DB:Start:"
+ if (Attribute == PerfStartEntry) {
+ *ProgressID = MODULE_DB_START_ID;
} else {
- RecordInfo->ProgressID = MODULE_DB_END_ID;
- RecordType = FPDT_GUID_QWORD_STRING_EVENT_TYPE;
+ *ProgressID = MODULE_DB_END_ID;
}
- } else if (AsciiStrCmp (Token, DRIVERBINDING_SUPPORT_TOK) == 0) { // "DB:Support:"
- *UseModuleName = TRUE;
+ } else if (AsciiStrCmp (String, DRIVERBINDING_SUPPORT_TOK) == 0) { // "DB:Support:"
if (PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {
return RETURN_UNSUPPORTED;
}
- RecordType = FPDT_GUID_QWORD_EVENT_TYPE;
- if (IsStart) {
- RecordInfo->ProgressID = MODULE_DB_SUPPORT_START_ID;
+ if (Attribute == PerfStartEntry) {
+ *ProgressID = MODULE_DB_SUPPORT_START_ID;
} else {
- RecordInfo->ProgressID = MODULE_DB_SUPPORT_END_ID;
+ *ProgressID = MODULE_DB_SUPPORT_END_ID;
}
- } else if (AsciiStrCmp (Token, DRIVERBINDING_STOP_TOK) == 0) { // "DB:Stop:"
- *UseModuleName = TRUE;
+ } else if (AsciiStrCmp (String, DRIVERBINDING_STOP_TOK) == 0) { // "DB:Stop:"
if (PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {
return RETURN_UNSUPPORTED;
}
- RecordType = FPDT_GUID_QWORD_EVENT_TYPE;
- if (IsStart) {
- RecordInfo->ProgressID = MODULE_DB_STOP_START_ID;
+ if (Attribute == PerfStartEntry) {
+ *ProgressID = MODULE_DB_STOP_START_ID;
} else {
- RecordInfo->ProgressID = MODULE_DB_STOP_END_ID;
+ *ProgressID = MODULE_DB_STOP_END_ID;
}
- } else if (AsciiStrCmp (Token, PEI_TOK) == 0 || // "PEI"
- AsciiStrCmp (Token, DXE_TOK) == 0 || // "DXE"
- AsciiStrCmp (Token, BDS_TOK) == 0) { // "BDS"
- if (IsStart) {
- RecordInfo->ProgressID = PERF_CROSSMODULE_START_ID;
+ } else if (AsciiStrCmp (String, PEI_TOK) == 0 || // "PEI"
+ AsciiStrCmp (String, DXE_TOK) == 0 || // "DXE"
+ AsciiStrCmp (String, BDS_TOK) == 0) { // "BDS"
+ if (Attribute == PerfStartEntry) {
+ *ProgressID = PERF_CROSSMODULE_START_ID;
} else {
- RecordInfo->ProgressID = PERF_CROSSMODULE_END_ID;
+ *ProgressID = PERF_CROSSMODULE_END_ID;
}
} else { // Pref used in Modules.
- if (IsStart) {
- RecordInfo->ProgressID = PERF_INMODULE_START_ID;
+ if (Attribute == PerfStartEntry) {
+ *ProgressID = PERF_INMODULE_START_ID;
} else {
- RecordInfo->ProgressID = PERF_INMODULE_END_ID;
+ *ProgressID = PERF_INMODULE_END_ID;
}
}
- } else if (Handle!= NULL || Module != NULL) { // Pref used in Modules.
- if (IsStart) {
- RecordInfo->ProgressID = PERF_INMODULE_START_ID;
+ } else if (Handle!= NULL) { // Pref used in Modules.
+ if (Attribute == PerfStartEntry) {
+ *ProgressID = PERF_INMODULE_START_ID;
} else {
- RecordInfo->ProgressID = PERF_INMODULE_END_ID;
+ *ProgressID = PERF_INMODULE_END_ID;
}
} else {
- return EFI_UNSUPPORTED;
+ return EFI_INVALID_PARAMETER;
}
+ return EFI_SUCCESS;
+}
+
+/**
+ Copies the string from Source into Destination and updates Length with the
+ size of the string.
+
+ @param Destination - destination of the string copy
+ @param Source - pointer to the source string which will get copied
+ @param Length - pointer to a length variable to be updated
+
+**/
+VOID
+CopyStringIntoPerfRecordAndUpdateLength (
+ IN OUT CHAR8 *Destination,
+ IN CONST CHAR8 *Source,
+ IN OUT UINT8 *Length
+ )
+{
+ UINTN StringLen;
+ UINTN DestMax;
+
+ ASSERT (Source != NULL);
- //
- // Get Record size baesed on the record type.
- // When PcdEdkiiFpdtStringRecordEnableOnly is TRUE, all records are with type of FPDT_DYNAMIC_STRING_EVENT_TYPE.
- //
if (PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {
- RecordType = FPDT_DYNAMIC_STRING_EVENT_TYPE;
- RecordInfo->RecordSize = sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD) + STRING_SIZE;
+ DestMax = STRING_SIZE;
} else {
- switch (RecordType) {
- case FPDT_GUID_EVENT_TYPE:
- RecordInfo->RecordSize = sizeof (FPDT_GUID_EVENT_RECORD);
- break;
-
- case FPDT_DYNAMIC_STRING_EVENT_TYPE:
- if (*UseModuleName) {
- StringSize = STRING_SIZE;
- } else if (Token != NULL) {
- StringSize = AsciiStrSize (Token);
- } else if (Module != NULL) {
- StringSize = AsciiStrSize (Module);
- } else {
- StringSize = STRING_SIZE;
- }
- if (StringSize > STRING_SIZE) {
- StringSize = STRING_SIZE;
- }
- RecordInfo->RecordSize = (UINT8)(sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD) + StringSize);
- break;
+ DestMax = AsciiStrSize (Source);
+ if (DestMax > STRING_SIZE) {
+ DestMax = STRING_SIZE;
+ }
+ }
+ StringLen = AsciiStrLen (Source);
+ if (StringLen >= DestMax) {
+ StringLen = DestMax -1;
+ }
+
+ AsciiStrnCpyS(Destination, DestMax, Source, StringLen);
+ *Length += (UINT8)DestMax;
+
+ return;
+}
+
+/**
+ Get a string description for device for the given controller handle and update record
+ length. If ComponentName2 GetControllerName is supported, the value is included in the string,
+ followed by device path, otherwise just device path.
- case FPDT_GUID_QWORD_EVENT_TYPE:
- RecordInfo->RecordSize = (UINT8)sizeof (FPDT_GUID_QWORD_EVENT_RECORD);
- break;
+ @param Handle - Image handle
+ @param ControllerHandle - Controller handle.
+ @param ComponentNameString - Pointer to a location where the string will be saved
+ @param Length - Pointer to record length to be updated
- case FPDT_GUID_QWORD_STRING_EVENT_TYPE:
- RecordInfo->RecordSize = (UINT8)sizeof (FPDT_GUID_QWORD_STRING_EVENT_RECORD);
- break;
+ @retval EFI_SUCCESS - Successfully got string description for device
+ @retval EFI_UNSUPPORTED - Neither ComponentName2 ControllerName nor DevicePath were found
- default:
+**/
+EFI_STATUS
+GetDeviceInfoFromHandleAndUpdateLength (
+ IN CONST VOID *Handle,
+ IN EFI_HANDLE ControllerHandle,
+ OUT CHAR8 *ComponentNameString,
+ IN OUT UINT8 *Length
+ )
+{
+ EFI_DEVICE_PATH_PROTOCOL *DevicePathProtocol;
+ EFI_COMPONENT_NAME2_PROTOCOL *ComponentName2;
+ EFI_STATUS Status;
+ CHAR16 *StringPtr;
+ CHAR8 *AsciiStringPtr;
+ UINTN ControllerNameStringSize;
+ UINTN DevicePathStringSize;
+
+ ControllerNameStringSize = 0;
+
+ Status = gBS->HandleProtocol (
+ (EFI_HANDLE) Handle,
+ &gEfiComponentName2ProtocolGuid,
+ (VOID **) &ComponentName2
+ );
+
+ if (!EFI_ERROR(Status)) {
+ //
+ // Get the current platform language setting
+ //
+ if (mPlatformLanguage == NULL) {
+ GetEfiGlobalVariable2 (L"PlatformLang", (VOID **)&mPlatformLanguage, NULL);
+ }
+
+ Status = ComponentName2->GetControllerName (
+ ComponentName2,
+ ControllerHandle,
+ NULL,
+ mPlatformLanguage != NULL ? mPlatformLanguage : "en-US",
+ &StringPtr
+ );
+ }
+
+ if (!EFI_ERROR (Status)) {
+ //
+ // This will produce the size of the unicode string, which is twice as large as the ASCII one
+ // This must be an even number, so ok to divide by 2
+ //
+ ControllerNameStringSize = StrSize(StringPtr) / 2;
+
+ //
+ // The + 1 is because we want to add a space between the ControllerName and the device path
+ //
+ if ((ControllerNameStringSize + (*Length) + 1) > FPDT_MAX_PERF_RECORD_SIZE) {
//
- // Record is unsupported yet, return EFI_UNSUPPORTED
+ // Only copy enough to fill FPDT_MAX_PERF_RECORD_SIZE worth of the record
//
- return EFI_UNSUPPORTED;
+ ControllerNameStringSize = FPDT_MAX_PERF_RECORD_SIZE - (*Length) - 1;
}
+
+ UnicodeStrToAsciiStrS(StringPtr, ComponentNameString, ControllerNameStringSize);
+
+ //
+ // Add a space in the end of the ControllerName
+ //
+ AsciiStringPtr = ComponentNameString + ControllerNameStringSize - 1;
+ *AsciiStringPtr = 0x20;
+ AsciiStringPtr++;
+ *AsciiStringPtr = 0;
+ ControllerNameStringSize++;
+
+ *Length += (UINT8)ControllerNameStringSize;
}
- RecordInfo->Type = RecordType;
- return EFI_SUCCESS;
+ //
+ // This function returns the device path protocol from the handle specified by Handle. If Handle is
+ // NULL or Handle does not contain a device path protocol, then NULL is returned.
+ //
+ DevicePathProtocol = DevicePathFromHandle(ControllerHandle);
+
+ if (DevicePathProtocol != NULL) {
+ StringPtr = ConvertDevicePathToText (DevicePathProtocol, TRUE, FALSE);
+ if (StringPtr != NULL) {
+ //
+ // This will produce the size of the unicode string, which is twice as large as the ASCII one
+ // This must be an even number, so ok to divide by 2
+ //
+ DevicePathStringSize = StrSize(StringPtr) / 2;
+
+ if ((DevicePathStringSize + (*Length)) > FPDT_MAX_PERF_RECORD_SIZE) {
+ //
+ // Only copy enough to fill FPDT_MAX_PERF_RECORD_SIZE worth of the record
+ //
+ DevicePathStringSize = FPDT_MAX_PERF_RECORD_SIZE - (*Length);
+ }
+
+ if (ControllerNameStringSize != 0) {
+ AsciiStringPtr = ComponentNameString + ControllerNameStringSize - 1;
+ } else {
+ AsciiStringPtr = ComponentNameString;
+ }
+
+ UnicodeStrToAsciiStrS(StringPtr, AsciiStringPtr, DevicePathStringSize);
+ *Length += (UINT8)DevicePathStringSize;
+ return EFI_SUCCESS;
+ }
+ }
+
+ return EFI_UNSUPPORTED;
}
/**
- Add performance log to FPDT boot record table.
+ Create performance record with event description and a timestamp.
- @param IsStart TRUE if the performance log is start log.
- @param Handle Pointer to environment specific context used
- to identify the component being measured.
- @param Token Pointer to a Null-terminated ASCII string
- that identifies the component being measured.
- @param Module Pointer to a Null-terminated ASCII string
- that identifies the module being measured.
- @param Ticker 64-bit time stamp.
- @param Identifier 32-bit identifier. If the value is 0, the created record
- is same as the one created by StartGauge of PERFORMANCE_PROTOCOL.
+ @param CallerIdentifier - Image handle or pointer to caller ID GUID.
+ @param Guid - Pointer to a GUID.
+ @param String - Pointer to a string describing the measurement.
+ @param Ticker - 64-bit time stamp.
+ @param Address - Pointer to a location in memory relevant to the measurement.
+ @param PerfId - Performance identifier describing the type of measurement.
+ @param Attribute - The attribute of the measurement. According to attribute can create a start
+ record for PERF_START/PERF_START_EX, or a end record for PERF_END/PERF_END_EX,
+ or a general record for other Perf macros.
- @retval EFI_SUCCESS Add FPDT boot record.
- @retval EFI_OUT_OF_RESOURCES There are not enough resources to record the measurement.
- @retval EFI_UNSUPPORTED No matched FPDT record.
+ @retval EFI_SUCCESS - Successfully created performance record.
+ @retval EFI_OUT_OF_RESOURCES - Ran out of space to store the records.
+ @retval EFI_INVALID_PARAMETER - Invalid parameter passed to function - NULL
+ pointer or invalid PerfId.
+
+ @retval EFI_SUCCESS - Successfully created performance record
+ @retval EFI_OUT_OF_RESOURCES - Ran out of space to store the records
+ @retval EFI_INVALID_PARAMETER - Invalid parameter passed to function - NULL
+ pointer or invalid PerfId
**/
EFI_STATUS
-InsertFpdtMeasurement (
- IN BOOLEAN IsStart,
- IN CONST VOID *Handle, OPTIONAL
- IN CONST CHAR8 *Token, OPTIONAL
- IN CONST CHAR8 *Module, OPTIONAL
- IN UINT64 Ticker,
- IN UINT32 Identifier
+InsertFpdtRecord (
+ IN CONST VOID *CallerIdentifier, OPTIONAL
+ IN CONST VOID *Guid, OPTIONAL
+ IN CONST CHAR8 *String, OPTIONAL
+ IN UINT64 Ticker,
+ IN UINT64 Address, OPTIONAL
+ IN UINT16 PerfId,
+ IN PERF_MEASUREMENT_ATTRIBUTE Attribute
)
{
EFI_GUID ModuleGuid;
CHAR8 ModuleName[FPDT_STRING_EVENT_RECORD_NAME_LENGTH];
- EFI_STATUS Status;
FPDT_RECORD_PTR FpdtRecordPtr;
- FPDT_BASIC_RECORD_INFO RecordInfo;
+ FPDT_RECORD_PTR CachedFpdtRecordPtr;
UINT64 TimeStamp;
- UINTN DestMax;
- UINTN StrLength;
CONST CHAR8 *StringPtr;
- BOOLEAN UseModuleName;
+ UINTN DestMax;
+ UINTN StringLen;
+ EFI_STATUS Status;
+ UINT16 ProgressId;
StringPtr = NULL;
- UseModuleName = FALSE;
+ ProgressId = 0;
ZeroMem (ModuleName, sizeof (ModuleName));
//
- // Get record info (type, size, ProgressID and Module Guid).
- //
- Status = GetFpdtRecordInfo (IsStart, Handle, Token, Module, &RecordInfo, &UseModuleName);
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- //
- // If PERF_START()/PERF_END() have specified the ProgressID,it has high priority.
- // !!! Note: If the Perf is not the known Token used in the core but have same
- // ID with the core Token, this case will not be supported.
- // And in currtnt usage mode, for the unkown ID, there is a general rule:
- // If it is start pref: the lower 4 bits of the ID should be 0.
- // If it is end pref: the lower 4 bits of the ID should not be 0.
- // If input ID doesn't follow the rule, we will adjust it.
+ // 1. Get the Perf Id for records from PERF_START/PERF_END, PERF_START_EX/PERF_END_EX.
+ // notes: For other Perf macros (Attribute == PerfEntry), their Id is known.
//
- if ((Identifier != 0) && (IsKnownID (Identifier)) && (!IsKnownTokens (Token))) {
- return EFI_UNSUPPORTED;
- } else if ((Identifier != 0) && (!IsKnownID (Identifier)) && (!IsKnownTokens (Token))) {
- if (IsStart && ((Identifier & 0x000F) != 0)) {
- Identifier &= 0xFFF0;
- } else if ((!IsStart) && ((Identifier & 0x000F) == 0)) {
- Identifier += 1;
- }
- RecordInfo.ProgressID = (UINT16)Identifier;
- }
-
- if (mFpdtBufferIsReported) {
+ if (Attribute != PerfEntry) {
//
- // Append Boot records to the boot performance table.
+ // If PERF_START_EX()/PERF_END_EX() have specified the ProgressID,it has high priority.
+ // !!! Note: If the Perf is not the known Token used in the core but have same
+ // ID with the core Token, this case will not be supported.
+ // And in currtnt usage mode, for the unkown ID, there is a general rule:
+ // If it is start pref: the lower 4 bits of the ID should be 0.
+ // If it is end pref: the lower 4 bits of the ID should not be 0.
+ // If input ID doesn't follow the rule, we will adjust it.
//
- if (mBootRecordSize + RecordInfo.RecordSize > mBootRecordMaxSize) {
- if (!mLackSpaceIsReported) {
- DEBUG ((DEBUG_INFO, "DxeCorePerformanceLib: No enough space to save boot records\n"));
- mLackSpaceIsReported = TRUE;
+ if ((PerfId != 0) && (IsKnownID (PerfId)) && (!IsKnownTokens (String))) {
+ return EFI_INVALID_PARAMETER;
+ } else if ((PerfId != 0) && (!IsKnownID (PerfId)) && (!IsKnownTokens (String))) {
+ if ((Attribute == PerfStartEntry) && ((PerfId & 0x000F) != 0)) {
+ PerfId &= 0xFFF0;
+ } else if ((Attribute == PerfEndEntry) && ((PerfId & 0x000F) == 0)) {
+ PerfId += 1;
}
- return EFI_OUT_OF_RESOURCES;
- } else {
+ } else if (PerfId == 0) {
//
- // Save boot record into BootPerformance table
+ // Get ProgressID form the String Token.
//
- FpdtRecordPtr.RecordHeader = (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER *)(mBootRecordBuffer + mBootRecordSize);
- mBootRecordSize += RecordInfo.RecordSize;
- mAcpiBootPerformanceTable->Header.Length += RecordInfo.RecordSize;
- }
- } else {
- //
- // Check if pre-allocated buffer is full
- //
- if (mPerformanceLength + RecordInfo.RecordSize > mMaxPerformanceLength) {
- mPerformancePointer = ReallocatePool (
- mPerformanceLength,
- mPerformanceLength + RecordInfo.RecordSize + FIRMWARE_RECORD_BUFFER,
- mPerformancePointer
- );
-
- if (mPerformancePointer == NULL) {
- return EFI_OUT_OF_RESOURCES;
+ Status = GetFpdtRecordId (Attribute, CallerIdentifier, String, &ProgressId);
+ if (EFI_ERROR (Status)) {
+ return Status;
}
- mMaxPerformanceLength = mPerformanceLength + RecordInfo.RecordSize + FIRMWARE_RECORD_BUFFER;
+ PerfId = ProgressId;
}
- //
- // Covert buffer to FPDT Ptr Union type.
- //
- FpdtRecordPtr.RecordHeader = (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER *)(mPerformancePointer + mPerformanceLength);
- mPerformanceLength += RecordInfo.RecordSize;
}
//
- // Get the TimeStamp.
+ // 2. Get the buffer to store the FPDT record.
+ //
+ Status = GetFpdtRecordPtr (FPDT_MAX_PERF_RECORD_SIZE, &FpdtRecordPtr);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ //3. Get the TimeStamp.
//
if (Ticker == 0) {
Ticker = GetPerformanceCounter ();
TimeStamp = GetTimeInNanoSecond (Ticker);
} else if (Ticker == 1) {
@@ -868,85 +997,252 @@ InsertFpdtMeasurement (
} else {
TimeStamp = GetTimeInNanoSecond (Ticker);
}
//
- // Get the ModuleName and ModuleGuid form the handle.
- //
- GetModuleInfoFromHandle ((EFI_HANDLE *)Handle, ModuleName, sizeof (ModuleName), &ModuleGuid);
-
- //
- // Fill in the record information.
+ // 4. Fill in the FPDT record according to different Performance Identifier.
//
- switch (RecordInfo.Type) {
- case FPDT_GUID_EVENT_TYPE:
- FpdtRecordPtr.GuidEvent->Header.Type = FPDT_GUID_EVENT_TYPE;
- FpdtRecordPtr.GuidEvent->Header.Length = RecordInfo.RecordSize;
- FpdtRecordPtr.GuidEvent->Header.Revision = FPDT_RECORD_REVISION_1;
- FpdtRecordPtr.GuidEvent->ProgressID = RecordInfo.ProgressID;
- FpdtRecordPtr.GuidEvent->Timestamp = TimeStamp;
- CopyMem (&FpdtRecordPtr.GuidEvent->Guid, &ModuleGuid, sizeof (FpdtRecordPtr.GuidEvent->Guid));
+ switch (PerfId) {
+ case MODULE_START_ID:
+ case MODULE_END_ID:
+ GetModuleInfoFromHandle ((EFI_HANDLE *)CallerIdentifier, ModuleName, sizeof (ModuleName), &ModuleGuid);
+ StringPtr = ModuleName;
+ //
+ // Cache the offset of start image start record and use to update the start image end record if needed.
+ //
+ if (Attribute == PerfEntry && PerfId == MODULE_START_ID) {
+ if (mFpdtBufferIsReported) {
+ mCachedLength = mBootRecordSize;
+ } else {
+ mCachedLength = mPerformanceLength;
+ }
+ }
+ if (!PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {
+ FpdtRecordPtr.GuidEvent->Header.Type = FPDT_GUID_EVENT_TYPE;
+ FpdtRecordPtr.GuidEvent->Header.Length = sizeof (FPDT_GUID_EVENT_RECORD);
+ FpdtRecordPtr.GuidEvent->Header.Revision = FPDT_RECORD_REVISION_1;
+ FpdtRecordPtr.GuidEvent->ProgressID = PerfId;
+ FpdtRecordPtr.GuidEvent->Timestamp = TimeStamp;
+ CopyMem (&FpdtRecordPtr.GuidEvent->Guid, &ModuleGuid, sizeof (FpdtRecordPtr.GuidEvent->Guid));
+ if (CallerIdentifier == NULL && PerfId == MODULE_END_ID && mCachedLength != 0) {
+ if (mFpdtBufferIsReported) {
+ CachedFpdtRecordPtr.RecordHeader = (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER *)(mBootRecordBuffer + mCachedLength);
+ } else {
+ CachedFpdtRecordPtr.RecordHeader = (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER *)(mPerformancePointer + mCachedLength);
+ }
+ CopyMem (&FpdtRecordPtr.GuidEvent->Guid, &CachedFpdtRecordPtr.GuidEvent->Guid, sizeof (FpdtRecordPtr.GuidEvent->Guid));
+ mCachedLength = 0;
+ }
+ }
break;
- case FPDT_DYNAMIC_STRING_EVENT_TYPE:
- FpdtRecordPtr.DynamicStringEvent->Header.Type = FPDT_DYNAMIC_STRING_EVENT_TYPE;
- FpdtRecordPtr.DynamicStringEvent->Header.Length = RecordInfo.RecordSize;
- FpdtRecordPtr.DynamicStringEvent->Header.Revision = FPDT_RECORD_REVISION_1;
- FpdtRecordPtr.DynamicStringEvent->ProgressID = RecordInfo.ProgressID;
- FpdtRecordPtr.DynamicStringEvent->Timestamp = TimeStamp;
- CopyMem (&FpdtRecordPtr.DynamicStringEvent->Guid, &ModuleGuid, sizeof (FpdtRecordPtr.DynamicStringEvent->Guid));
-
- if (UseModuleName) {
- StringPtr = ModuleName;
- } else if (Token != NULL) {
- StringPtr = Token;
- } else if (Module != NULL) {
- StringPtr = Module;
- } else if (ModuleName != NULL) {
- StringPtr = ModuleName;
+ case MODULE_LOADIMAGE_START_ID:
+ case MODULE_LOADIMAGE_END_ID:
+ GetModuleInfoFromHandle ((EFI_HANDLE *)CallerIdentifier, ModuleName, sizeof (ModuleName), &ModuleGuid);
+ StringPtr = ModuleName;
+ if (PerfId == MODULE_LOADIMAGE_START_ID) {
+ mLoadImageCount ++;
+ //
+ // Cache the offset of load image start record and use to be updated by the load image end record if needed.
+ //
+ if (CallerIdentifier == NULL && Attribute == PerfEntry) {
+ if (mFpdtBufferIsReported) {
+ mCachedLength = mBootRecordSize;
+ } else {
+ mCachedLength = mPerformanceLength;
+ }
+ }
}
- if (StringPtr != NULL && AsciiStrLen (StringPtr) != 0) {
- StrLength = AsciiStrLen (StringPtr);
- DestMax = (RecordInfo.RecordSize - sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD)) / sizeof (CHAR8);
- if (StrLength >= DestMax) {
- StrLength = DestMax -1;
+ if (!PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {
+ FpdtRecordPtr.GuidQwordEvent->Header.Type = FPDT_GUID_QWORD_EVENT_TYPE;
+ FpdtRecordPtr.GuidQwordEvent->Header.Length = sizeof (FPDT_GUID_QWORD_EVENT_RECORD);
+ FpdtRecordPtr.GuidQwordEvent->Header.Revision = FPDT_RECORD_REVISION_1;
+ FpdtRecordPtr.GuidQwordEvent->ProgressID = PerfId;
+ FpdtRecordPtr.GuidQwordEvent->Timestamp = TimeStamp;
+ FpdtRecordPtr.GuidQwordEvent->Qword = mLoadImageCount;
+ CopyMem (&FpdtRecordPtr.GuidQwordEvent->Guid, &ModuleGuid, sizeof (FpdtRecordPtr.GuidQwordEvent->Guid));
+ if (PerfId == MODULE_LOADIMAGE_END_ID && mCachedLength != 0) {
+ if (mFpdtBufferIsReported) {
+ CachedFpdtRecordPtr.RecordHeader = (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER *)(mBootRecordBuffer + mCachedLength);
+ } else {
+ CachedFpdtRecordPtr.RecordHeader = (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER *)(mPerformancePointer + mCachedLength);
+ }
+ CopyMem (&CachedFpdtRecordPtr.GuidQwordEvent->Guid, &ModuleGuid, sizeof (CachedFpdtRecordPtr.GuidQwordEvent->Guid));
+ mCachedLength = 0;
}
- AsciiStrnCpyS (FpdtRecordPtr.DynamicStringEvent->String, DestMax, StringPtr, StrLength);
- } else {
- AsciiStrCpyS (FpdtRecordPtr.DynamicStringEvent->String, FPDT_STRING_EVENT_RECORD_NAME_LENGTH, "unknown name");
}
break;
- case FPDT_GUID_QWORD_EVENT_TYPE:
- FpdtRecordPtr.GuidQwordEvent->Header.Type = FPDT_GUID_QWORD_EVENT_TYPE;
- FpdtRecordPtr.GuidQwordEvent->Header.Length = RecordInfo.RecordSize;
- FpdtRecordPtr.GuidQwordEvent->Header.Revision = FPDT_RECORD_REVISION_1;
- FpdtRecordPtr.GuidQwordEvent->ProgressID = RecordInfo.ProgressID;
- FpdtRecordPtr.GuidQwordEvent->Timestamp = TimeStamp;
- CopyMem (&FpdtRecordPtr.GuidQwordEvent->Guid, &ModuleGuid, sizeof (FpdtRecordPtr.GuidQwordEvent->Guid));
- if ((MODULE_LOADIMAGE_START_ID == RecordInfo.ProgressID) && AsciiStrCmp (Token, LOAD_IMAGE_TOK) == 0) {
- mLoadImageCount++;
- FpdtRecordPtr.GuidQwordEvent->Qword = mLoadImageCount;
+ case MODULE_DB_START_ID:
+ case MODULE_DB_SUPPORT_START_ID:
+ case MODULE_DB_SUPPORT_END_ID:
+ case MODULE_DB_STOP_START_ID:
+ case MODULE_DB_STOP_END_ID:
+ GetModuleInfoFromHandle ((EFI_HANDLE *)CallerIdentifier, ModuleName, sizeof (ModuleName), &ModuleGuid);
+ StringPtr = ModuleName;
+ if (!PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {
+ FpdtRecordPtr.GuidQwordEvent->Header.Type = FPDT_GUID_QWORD_EVENT_TYPE;
+ FpdtRecordPtr.GuidQwordEvent->Header.Length = sizeof (FPDT_GUID_QWORD_EVENT_RECORD);
+ FpdtRecordPtr.GuidQwordEvent->Header.Revision = FPDT_RECORD_REVISION_1;
+ FpdtRecordPtr.GuidQwordEvent->ProgressID = PerfId;
+ FpdtRecordPtr.GuidQwordEvent->Timestamp = TimeStamp;
+ FpdtRecordPtr.GuidQwordEvent->Qword = Address;
+ CopyMem (&FpdtRecordPtr.GuidQwordEvent->Guid, &ModuleGuid, sizeof (FpdtRecordPtr.GuidQwordEvent->Guid));
}
break;
- case FPDT_GUID_QWORD_STRING_EVENT_TYPE:
- FpdtRecordPtr.GuidQwordStringEvent->Header.Type = FPDT_GUID_QWORD_STRING_EVENT_TYPE;
- FpdtRecordPtr.GuidQwordStringEvent->Header.Length = RecordInfo.RecordSize;
- FpdtRecordPtr.GuidQwordStringEvent->Header.Revision = FPDT_RECORD_REVISION_1;
- FpdtRecordPtr.GuidQwordStringEvent->ProgressID = RecordInfo.ProgressID;
- FpdtRecordPtr.GuidQwordStringEvent->Timestamp = TimeStamp;
- CopyMem (&FpdtRecordPtr.GuidQwordStringEvent->Guid, &ModuleGuid, sizeof (FpdtRecordPtr.GuidQwordStringEvent->Guid));
+ case MODULE_DB_END_ID:
+ GetModuleInfoFromHandle ((EFI_HANDLE *)CallerIdentifier, ModuleName, sizeof (ModuleName), &ModuleGuid);
+ StringPtr = ModuleName;
+ if (!PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {
+ FpdtRecordPtr.GuidQwordStringEvent->Header.Type = FPDT_GUID_QWORD_STRING_EVENT_TYPE;
+ FpdtRecordPtr.GuidQwordStringEvent->Header.Length = sizeof (FPDT_GUID_QWORD_STRING_EVENT_RECORD);;
+ FpdtRecordPtr.GuidQwordStringEvent->Header.Revision = FPDT_RECORD_REVISION_1;
+ FpdtRecordPtr.GuidQwordStringEvent->ProgressID = PerfId;
+ FpdtRecordPtr.GuidQwordStringEvent->Timestamp = TimeStamp;
+ FpdtRecordPtr.GuidQwordStringEvent->Qword = Address;
+ CopyMem (&FpdtRecordPtr.GuidQwordStringEvent->Guid, &ModuleGuid, sizeof (FpdtRecordPtr.GuidQwordStringEvent->Guid));
+ if (Address != 0) {
+ GetDeviceInfoFromHandleAndUpdateLength(CallerIdentifier, (EFI_HANDLE)(UINTN)Address, FpdtRecordPtr.GuidQwordStringEvent->String, &FpdtRecordPtr.GuidQwordStringEvent->Header.Length);
+ }
+ }
break;
- default:
+ case PERF_EVENTSIGNAL_START_ID:
+ case PERF_EVENTSIGNAL_END_ID:
+ case PERF_CALLBACK_START_ID:
+ case PERF_CALLBACK_END_ID:
+ if (String == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
//
- // Record is not supported in current DXE phase, return EFI_ABORTED
+ // Cache the event guid in string event record when PcdEdkiiFpdtStringRecordEnableOnly == TRUE
//
- return EFI_UNSUPPORTED;
+ CopyGuid (&ModuleGuid, Guid);
+ StringPtr = String;
+ if (!PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {
+ FpdtRecordPtr.DualGuidStringEvent->Header.Type = FPDT_DUAL_GUID_STRING_EVENT_TYPE;
+ FpdtRecordPtr.DualGuidStringEvent->Header.Length = sizeof (FPDT_DUAL_GUID_STRING_EVENT_RECORD);
+ FpdtRecordPtr.DualGuidStringEvent->Header.Revision = FPDT_RECORD_REVISION_1;
+ FpdtRecordPtr.DualGuidStringEvent->ProgressID = PerfId;
+ FpdtRecordPtr.DualGuidStringEvent->Timestamp = TimeStamp;
+ CopyMem (&FpdtRecordPtr.DualGuidStringEvent->Guid1, CallerIdentifier, sizeof (FpdtRecordPtr.DualGuidStringEvent->Guid1));
+ CopyMem (&FpdtRecordPtr.DualGuidStringEvent->Guid2, Guid, sizeof (FpdtRecordPtr.DualGuidStringEvent->Guid2));
+ CopyStringIntoPerfRecordAndUpdateLength (FpdtRecordPtr.DualGuidStringEvent->String, StringPtr, &FpdtRecordPtr.DualGuidStringEvent->Header.Length);
+ }
+ break;
+
+ case PERF_EVENT_ID:
+ case PERF_FUNCTION_START_ID:
+ case PERF_FUNCTION_END_ID:
+ case PERF_INMODULE_START_ID:
+ case PERF_INMODULE_END_ID:
+ case PERF_CROSSMODULE_START_ID:
+ case PERF_CROSSMODULE_END_ID:
+ GetModuleInfoFromHandle ((EFI_HANDLE *)CallerIdentifier, ModuleName, sizeof (ModuleName), &ModuleGuid);
+ if (String != NULL) {
+ StringPtr = String;
+ } else {
+ StringPtr = ModuleName;
+ }
+ if (AsciiStrLen (StringPtr) == 0) {
+ StringPtr = "unknown name";
+ }
+ if (!PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {
+ FpdtRecordPtr.DynamicStringEvent->Header.Type = FPDT_DYNAMIC_STRING_EVENT_TYPE;
+ FpdtRecordPtr.DynamicStringEvent->Header.Length = sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD);
+ FpdtRecordPtr.DynamicStringEvent->Header.Revision = FPDT_RECORD_REVISION_1;
+ FpdtRecordPtr.DynamicStringEvent->ProgressID = PerfId;
+ FpdtRecordPtr.DynamicStringEvent->Timestamp = TimeStamp;
+ CopyMem (&FpdtRecordPtr.DynamicStringEvent->Guid, &ModuleGuid, sizeof (FpdtRecordPtr.DynamicStringEvent->Guid));
+ CopyStringIntoPerfRecordAndUpdateLength (FpdtRecordPtr.DynamicStringEvent->String, StringPtr, &FpdtRecordPtr.DynamicStringEvent->Header.Length);
+ }
+ break;
+
+ default:
+ if (Attribute != PerfEntry) {
+ GetModuleInfoFromHandle ((EFI_HANDLE *)CallerIdentifier, ModuleName, sizeof (ModuleName), &ModuleGuid);
+ if (String != NULL) {
+ StringPtr = String;
+ } else {
+ StringPtr = ModuleName;
+ }
+ if (AsciiStrLen (StringPtr) == 0) {
+ StringPtr = "unknown name";
+ }
+ if (!PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {
+ FpdtRecordPtr.DynamicStringEvent->Header.Type = FPDT_DYNAMIC_STRING_EVENT_TYPE;
+ FpdtRecordPtr.DynamicStringEvent->Header.Length = sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD);
+ FpdtRecordPtr.DynamicStringEvent->Header.Revision = FPDT_RECORD_REVISION_1;
+ FpdtRecordPtr.DynamicStringEvent->ProgressID = PerfId;
+ FpdtRecordPtr.DynamicStringEvent->Timestamp = TimeStamp;
+ CopyMem (&FpdtRecordPtr.DynamicStringEvent->Guid, &ModuleGuid, sizeof (FpdtRecordPtr.DynamicStringEvent->Guid));
+ CopyStringIntoPerfRecordAndUpdateLength (FpdtRecordPtr.DynamicStringEvent->String, StringPtr, &FpdtRecordPtr.DynamicStringEvent->Header.Length);
+ }
+ } else {
+ return EFI_INVALID_PARAMETER;
+ }
+ break;
+ }
+
+ //
+ // 4.2 When PcdEdkiiFpdtStringRecordEnableOnly==TRUE, create string record for all Perf entries.
+ //
+ if (PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {
+ if (StringPtr == NULL ||PerfId == MODULE_DB_SUPPORT_START_ID || PerfId == MODULE_DB_SUPPORT_END_ID) {
+ return EFI_INVALID_PARAMETER;
+ }
+ FpdtRecordPtr.DynamicStringEvent->Header.Type = FPDT_DYNAMIC_STRING_EVENT_TYPE;
+ FpdtRecordPtr.DynamicStringEvent->Header.Length = sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD);
+ FpdtRecordPtr.DynamicStringEvent->Header.Revision = FPDT_RECORD_REVISION_1;
+ FpdtRecordPtr.DynamicStringEvent->ProgressID = PerfId;
+ FpdtRecordPtr.DynamicStringEvent->Timestamp = TimeStamp;
+ CopyMem (&FpdtRecordPtr.DynamicStringEvent->Guid, &ModuleGuid, sizeof (FpdtRecordPtr.DynamicStringEvent->Guid));
+ if (AsciiStrLen (StringPtr) == 0) {
+ StringPtr = "unknown name";
+ }
+ CopyStringIntoPerfRecordAndUpdateLength (FpdtRecordPtr.DynamicStringEvent->String, StringPtr, &FpdtRecordPtr.DynamicStringEvent->Header.Length);
+
+ if ((PerfId == MODULE_LOADIMAGE_START_ID) || (PerfId == MODULE_END_ID)) {
+ FpdtRecordPtr.DynamicStringEvent->Header.Length = (UINT8)(sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD)+ STRING_SIZE);
+ }
+ if ((PerfId == MODULE_LOADIMAGE_END_ID || PerfId == MODULE_END_ID) && mCachedLength != 0) {
+ if (mFpdtBufferIsReported) {
+ CachedFpdtRecordPtr.RecordHeader = (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER *)(mBootRecordBuffer + mCachedLength);
+ } else {
+ CachedFpdtRecordPtr.RecordHeader = (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER *)(mPerformancePointer + mCachedLength);
+ }
+ if (PerfId == MODULE_LOADIMAGE_END_ID) {
+ DestMax = CachedFpdtRecordPtr.DynamicStringEvent->Header.Length - sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD);
+ StringLen = AsciiStrLen (StringPtr);
+ if (StringLen >= DestMax) {
+ StringLen = DestMax -1;
+ }
+ CopyMem (&CachedFpdtRecordPtr.DynamicStringEvent->Guid, &ModuleGuid, sizeof (CachedFpdtRecordPtr.DynamicStringEvent->Guid));
+ AsciiStrnCpyS (CachedFpdtRecordPtr.DynamicStringEvent->String, DestMax, StringPtr, StringLen);
+ } else if (PerfId == MODULE_END_ID) {
+ DestMax = FpdtRecordPtr.DynamicStringEvent->Header.Length - sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD);
+ StringLen = AsciiStrLen (CachedFpdtRecordPtr.DynamicStringEvent->String);
+ if (StringLen >= DestMax) {
+ StringLen = DestMax -1;
+ }
+ CopyMem (&FpdtRecordPtr.DynamicStringEvent->Guid, &CachedFpdtRecordPtr.DynamicStringEvent->Guid, sizeof (CachedFpdtRecordPtr.DynamicStringEvent->Guid));
+ AsciiStrnCpyS (FpdtRecordPtr.DynamicStringEvent->String, DestMax, CachedFpdtRecordPtr.DynamicStringEvent->String, StringLen);
+ }
+ mCachedLength = 0;
+ }
}
+ //
+ // 5. Update the length of the used buffer after fill in the record.
+ //
+ if (mFpdtBufferIsReported) {
+ mBootRecordSize += FpdtRecordPtr.RecordHeader->Length;
+ mAcpiBootPerformanceTable->Header.Length += FpdtRecordPtr.RecordHeader->Length;
+ } else {
+ mPerformanceLength += FpdtRecordPtr.RecordHeader->Length;
+ }
return EFI_SUCCESS;
}
/**
Dumps all the PEI performance.
@@ -1158,15 +1454,12 @@ CreatePerformanceMeasurement (
if (mLockInsertRecord) {
return EFI_INVALID_PARAMETER;
}
mLockInsertRecord = TRUE;
- if (Attribute == PerfStartEntry) {
- Status = InsertFpdtMeasurement (TRUE, CallerIdentifier, String, String, TimeStamp, Identifier);
- } else if (Attribute == PerfEndEntry) {
- Status = InsertFpdtMeasurement (FALSE, CallerIdentifier, String, String, TimeStamp, Identifier);
- }
+ Status = InsertFpdtRecord (CallerIdentifier, Guid, String, TimeStamp, Address, (UINT16)Identifier, Attribute);
+
mLockInsertRecord = FALSE;
return Status;
}
@@ -1470,5 +1763,60 @@ PerformanceMeasurementEnabled (
VOID
)
{
return (BOOLEAN) ((PcdGet8(PcdPerformanceLibraryPropertyMask) & PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED) != 0);
}
+
+/**
+ Create performance record with event description and a timestamp.
+
+ @param CallerIdentifier - Image handle or pointer to caller ID GUID
+ @param Guid - Pointer to a GUID
+ @param String - Pointer to a string describing the measurement
+ @param Address - Pointer to a location in memory relevant to the measurement
+ @param Identifier - Performance identifier describing the type of measurement
+
+ @retval RETURN_SUCCESS - Successfully created performance record
+ @retval RETURN_OUT_OF_RESOURCES - Ran out of space to store the records
+ @retval RETURN_INVALID_PARAMETER - Invalid parameter passed to function - NULL
+ pointer or invalid PerfId
+
+**/
+RETURN_STATUS
+EFIAPI
+LogPerformanceMeasurement (
+ IN CONST VOID *CallerIdentifier,
+ IN CONST VOID *Guid, OPTIONAL
+ IN CONST CHAR8 *String, OPTIONAL
+ IN UINT64 Address, OPTIONAL
+ IN UINT32 Identifier
+ )
+{
+ return (RETURN_STATUS)CreatePerformanceMeasurement (CallerIdentifier, Guid, String, 0, Address, Identifier, PerfEntry);
+}
+
+/**
+ Check whether the specified performance measurement can be logged.
+
+ This function returns TRUE when the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of PcdPerformanceLibraryPropertyMask is set
+ and the Type disable bit in PcdPerformanceLibraryPropertyMask is not set.
+
+ @param Type - Type of the performance measurement entry.
+
+ @retval TRUE The performance measurement can be logged.
+ @retval FALSE The performance measurement can NOT be logged.
+
+**/
+BOOLEAN
+EFIAPI
+LogPerformanceMeasurementEnabled (
+ IN CONST UINTN Type
+ )
+{
+ //
+ // When Performance measurement is enabled and the type is not filtered, the performance can be logged.
+ //
+ if (PerformanceMeasurementEnabled () && (PcdGet8(PcdPerformanceLibraryPropertyMask) & Type) == 0) {
+ return TRUE;
+ }
+ return FALSE;
+}
diff --git a/MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLib.inf b/MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLib.inf
index 68cd76da5b3..3e77f9cd57a 100644
--- a/MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLib.inf
+++ b/MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLib.inf
@@ -59,10 +59,11 @@
DebugLib
UefiLib
ReportStatusCodeLib
DxeServicesLib
PeCoffGetEntryPointLib
+ DevicePathLib
[Protocols]
gEfiSmmCommunicationProtocolGuid ## SOMETIMES_CONSUMES
diff --git a/MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLibInternal.h b/MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLibInternal.h
index f9800e34941..a96f4081503 100644
--- a/MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLibInternal.h
+++ b/MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLibInternal.h
@@ -40,10 +40,11 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include <Library/HobLib.h>
#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/TimerLib.h>
#include <Library/PcdLib.h>
+#include <Library/DevicePathLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiRuntimeServicesTableLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/UefiLib.h>
#include <Library/ReportStatusCodeLib.h>
diff --git a/MdeModulePkg/Library/DxePerformanceLib/DxePerformanceLib.c b/MdeModulePkg/Library/DxePerformanceLib/DxePerformanceLib.c
index 9ed50d22b8d..664e8261af9 100644
--- a/MdeModulePkg/Library/DxePerformanceLib/DxePerformanceLib.c
+++ b/MdeModulePkg/Library/DxePerformanceLib/DxePerformanceLib.c
@@ -376,5 +376,73 @@ PerformanceMeasurementEnabled (
VOID
)
{
return (BOOLEAN) ((PcdGet8(PcdPerformanceLibraryPropertyMask) & PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED) != 0);
}
+
+/**
+ Create performance record with event description and a timestamp.
+
+ @param CallerIdentifier - Image handle or pointer to caller ID GUID
+ @param Guid - Pointer to a GUID
+ @param String - Pointer to a string describing the measurement
+ @param Address - Pointer to a location in memory relevant to the measurement
+ @param Identifier - Performance identifier describing the type of measurement
+
+ @retval RETURN_SUCCESS - Successfully created performance record
+ @retval RETURN_OUT_OF_RESOURCES - Ran out of space to store the records
+ @retval RETURN_INVALID_PARAMETER - Invalid parameter passed to function - NULL
+ pointer or invalid PerfId
+
+**/
+RETURN_STATUS
+EFIAPI
+LogPerformanceMeasurement (
+ IN CONST VOID *CallerIdentifier,
+ IN CONST VOID *Guid, OPTIONAL
+ IN CONST CHAR8 *String, OPTIONAL
+ IN UINT64 Address, OPTIONAL
+ IN UINT32 Identifier
+ )
+{
+ EFI_STATUS Status;
+
+ Status = GetPerformanceMeasurementProtocol ();
+ if (EFI_ERROR (Status)) {
+ return RETURN_OUT_OF_RESOURCES;
+ }
+
+ if (mPerformanceMeasurement != NULL) {
+ Status = mPerformanceMeasurement->CreatePerformanceMeasurement (CallerIdentifier, Guid, String, 0, Address, Identifier, PerfEntry);
+ } else {
+ ASSERT (FALSE);
+ }
+
+ return (RETURN_STATUS) Status;
+}
+
+/**
+ Check whether the specified performance measurement can be logged.
+
+ This function returns TRUE when the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of PcdPerformanceLibraryPropertyMask is set
+ and the Type disable bit in PcdPerformanceLibraryPropertyMask is not set.
+
+ @param Type - Type of the performance measurement entry.
+
+ @retval TRUE The performance measurement can be logged.
+ @retval FALSE The performance measurement can NOT be logged.
+
+**/
+BOOLEAN
+EFIAPI
+LogPerformanceMeasurementEnabled (
+ IN CONST UINTN Type
+ )
+{
+ //
+ // When Performance measurement is enabled and the type is not filtered, the performance can be logged.
+ //
+ if (PerformanceMeasurementEnabled () && (PcdGet8(PcdPerformanceLibraryPropertyMask) & Type) == 0) {
+ return TRUE;
+ }
+ return FALSE;
+}
diff --git a/MdeModulePkg/Library/PeiPerformanceLib/PeiPerformanceLib.c b/MdeModulePkg/Library/PeiPerformanceLib/PeiPerformanceLib.c
index f770a35a995..cd1b0e34ef7 100644
--- a/MdeModulePkg/Library/PeiPerformanceLib/PeiPerformanceLib.c
+++ b/MdeModulePkg/Library/PeiPerformanceLib/PeiPerformanceLib.c
@@ -21,21 +21,100 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include <PiPei.h>
#include <Guid/ExtendedFirmwarePerformance.h>
+#include <Guid/PerformanceMeasurement.h>
#include <Library/PerformanceLib.h>
#include <Library/DebugLib.h>
#include <Library/HobLib.h>
#include <Library/BaseLib.h>
#include <Library/TimerLib.h>
#include <Library/PcdLib.h>
#include <Library/BaseMemoryLib.h>
#define STRING_SIZE (FPDT_STRING_EVENT_RECORD_NAME_LENGTH * sizeof (CHAR8))
-#define MAX_RECORD_SIZE (sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD) + STRING_SIZE)
+#define PEI_MAX_RECORD_SIZE (sizeof (FPDT_DUAL_GUID_STRING_EVENT_RECORD) + STRING_SIZE)
+
+
+/**
+ Return the pointer to the FPDT record in the allocated memory.
+
+ @param RecordSize The size of FPDT record.
+ @param FpdtRecordPtr Pointer the FPDT record in the allocated memory.
+ @param PeiPerformanceLogHeader Pointer to the header of the PEI Performance records in the GUID Hob.
+
+ @retval EFI_SUCCESS Successfully get the pointer to the FPDT record.
+ @retval EFI_OUT_OF_RESOURCES Ran out of space to store the records.
+**/
+EFI_STATUS
+GetFpdtRecordPtr (
+ IN UINT8 RecordSize,
+ IN OUT FPDT_RECORD_PTR *FpdtRecordPtr,
+ IN OUT FPDT_PEI_EXT_PERF_HEADER **PeiPerformanceLogHeader
+)
+{
+ UINT16 PeiPerformanceLogEntries;
+ UINTN PeiPerformanceSize;
+ UINT8 *PeiFirmwarePerformance;
+ EFI_HOB_GUID_TYPE *GuidHob;
+
+ //
+ // Get the number of PeiPerformanceLogEntries form PCD.
+ //
+ PeiPerformanceLogEntries = (UINT16) (PcdGet16 (PcdMaxPeiPerformanceLogEntries16) != 0 ?
+ PcdGet16 (PcdMaxPeiPerformanceLogEntries16) :
+ PcdGet8 (PcdMaxPeiPerformanceLogEntries));
+
+ //
+ // Create GUID HOB Data.
+ //
+ GuidHob = GetFirstGuidHob (&gEdkiiFpdtExtendedFirmwarePerformanceGuid);
+ PeiFirmwarePerformance = NULL;
+ while (GuidHob != NULL) {
+ //
+ // PEI Performance HOB was found, then return the existing one.
+ //
+ PeiFirmwarePerformance = (UINT8*)GET_GUID_HOB_DATA (GuidHob);
+ *PeiPerformanceLogHeader = (FPDT_PEI_EXT_PERF_HEADER *)PeiFirmwarePerformance;
+ if (!(*PeiPerformanceLogHeader)->HobIsFull && (*PeiPerformanceLogHeader)->SizeOfAllEntries + RecordSize > (UINTN)(PeiPerformanceLogEntries * PEI_MAX_RECORD_SIZE)) {
+ (*PeiPerformanceLogHeader)->HobIsFull = TRUE;
+ }
+ if (!(*PeiPerformanceLogHeader)->HobIsFull && (*PeiPerformanceLogHeader)->SizeOfAllEntries + RecordSize <= (UINTN)(PeiPerformanceLogEntries * PEI_MAX_RECORD_SIZE)) {
+ FpdtRecordPtr->RecordHeader = (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER *)(PeiFirmwarePerformance + sizeof (FPDT_PEI_EXT_PERF_HEADER) + (*PeiPerformanceLogHeader)->SizeOfAllEntries);
+ break;
+ }
+ //
+ // Previous HOB is used, then find next one.
+ //
+ GuidHob = GetNextGuidHob (&gEdkiiFpdtExtendedFirmwarePerformanceGuid, GET_NEXT_HOB (GuidHob));
+ }
+
+ if (GuidHob == NULL) {
+ //
+ // PEI Performance HOB was not found, then build one.
+ //
+ PeiPerformanceSize = sizeof (FPDT_PEI_EXT_PERF_HEADER) +
+ PEI_MAX_RECORD_SIZE * PeiPerformanceLogEntries;
+ PeiFirmwarePerformance = (UINT8*)BuildGuidHob (&gEdkiiFpdtExtendedFirmwarePerformanceGuid, PeiPerformanceSize);
+ if (PeiFirmwarePerformance != NULL) {
+ ZeroMem (PeiFirmwarePerformance, PeiPerformanceSize);
+ (*PeiPerformanceLogHeader) = (FPDT_PEI_EXT_PERF_HEADER *)PeiFirmwarePerformance;
+ FpdtRecordPtr->RecordHeader = (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER *)(PeiFirmwarePerformance + sizeof (FPDT_PEI_EXT_PERF_HEADER));
+ }
+ }
+
+ if (PeiFirmwarePerformance == NULL) {
+ //
+ // there is no enough resource to store performance data
+ //
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ return EFI_SUCCESS;
+}
/**
Check whether the Token is a known one which is uesed by core.
@param Token Pointer to a Null-terminated ASCII string
@@ -98,252 +177,197 @@ IsKnownID (
return FALSE;
}
}
/**
- Get the FPDT record info.
+ Get the FPDT record identifier.
- @param IsStart TRUE if the performance log is start log.
- @param Handle Pointer to environment specific context used
- to identify the component being measured.
- @param Token Pointer to a Null-terminated ASCII string
- that identifies the component being measured.
- @param Module Pointer to a Null-terminated ASCII string
- that identifies the module being measured.
- @param RecordInfo On return, pointer to the info of the record.
+ @param Attribute The attribute of the Record.
+ PerfStartEntry: Start Record.
+ PerfEndEntry: End Record.
+ @param Handle Pointer to environment specific context used to identify the component being measured.
+ @param String Pointer to a Null-terminated ASCII string that identifies the component being measured.
+ @param ProgressID On return, pointer to the ProgressID.
- @retval EFI_SUCCESS Get record info successfully.
- @retval EFI_UNSUPPORTED No matched FPDT record.
+ @retval EFI_SUCCESS Get record info successfully.
+ @retval EFI_INVALID_PARAMETER No matched FPDT record.
**/
EFI_STATUS
-GetFpdtRecordInfo (
- IN BOOLEAN IsStart,
+GetFpdtRecordId (
+ IN BOOLEAN Attribute,
IN CONST VOID *Handle,
- IN CONST CHAR8 *Token,
- IN CONST CHAR8 *Module,
- OUT FPDT_BASIC_RECORD_INFO *RecordInfo
+ IN CONST CHAR8 *String,
+ OUT UINT16 *ProgressID
)
{
- UINTN StringSize;
- UINT16 RecordType;
-
- RecordType = FPDT_DYNAMIC_STRING_EVENT_TYPE;
-
//
// Get the ProgressID based on the Token.
// When PcdEdkiiFpdtStringRecordEnableOnly is TRUE, all records are with type of FPDT_DYNAMIC_STRING_EVENT_TYPE.
//
- if (Token != NULL) {
- if (AsciiStrCmp (Token, LOAD_IMAGE_TOK) == 0) { // "LoadImage:"
- if (IsStart) {
- RecordInfo->ProgressID = MODULE_LOADIMAGE_START_ID;
+ if (String != NULL) {
+ if (AsciiStrCmp (String, LOAD_IMAGE_TOK) == 0) { // "LoadImage:"
+ if (Attribute == PerfStartEntry) {
+ *ProgressID = MODULE_LOADIMAGE_START_ID;
} else {
- RecordInfo->ProgressID = MODULE_LOADIMAGE_END_ID;
+ *ProgressID = MODULE_LOADIMAGE_END_ID;
}
- if(!PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {
- RecordType = FPDT_GUID_QWORD_EVENT_TYPE;
- }
- } else if (AsciiStrCmp (Token, SEC_TOK) == 0 || // "SEC"
- AsciiStrCmp (Token, PEI_TOK) == 0) { // "PEI"
- if (IsStart) {
- RecordInfo->ProgressID = PERF_CROSSMODULE_START_ID;
+ } else if (AsciiStrCmp (String, SEC_TOK) == 0 || // "SEC"
+ AsciiStrCmp (String, PEI_TOK) == 0) { // "PEI"
+ if (Attribute == PerfStartEntry) {
+ *ProgressID = PERF_CROSSMODULE_START_ID;
} else {
- RecordInfo->ProgressID = PERF_CROSSMODULE_END_ID;
+ *ProgressID = PERF_CROSSMODULE_END_ID;
}
- } else if (AsciiStrCmp (Token, PEIM_TOK) == 0) { // "PEIM"
- if (IsStart) {
- RecordInfo->ProgressID = MODULE_START_ID;
+ } else if (AsciiStrCmp (String, PEIM_TOK) == 0) { // "PEIM"
+ if (Attribute == PerfStartEntry) {
+ *ProgressID = MODULE_START_ID;
} else {
- RecordInfo->ProgressID = MODULE_END_ID;
- }
- if(!PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {
- RecordType = FPDT_GUID_EVENT_TYPE;
+ *ProgressID = MODULE_END_ID;
}
} else { //Pref used in Modules.
- if (IsStart) {
- RecordInfo->ProgressID = PERF_INMODULE_START_ID;
+ if (Attribute == PerfStartEntry) {
+ *ProgressID = PERF_INMODULE_START_ID;
} else {
- RecordInfo->ProgressID = PERF_INMODULE_END_ID;
+ *ProgressID = PERF_INMODULE_END_ID;
}
}
- } else if (Module != NULL || Handle != NULL) { //Pref used in Modules.
- if (IsStart) {
- RecordInfo->ProgressID = PERF_INMODULE_START_ID;
+ } else if (Handle != NULL) { //Pref used in Modules.
+ if (Attribute == PerfStartEntry) {
+ *ProgressID = PERF_INMODULE_START_ID;
} else {
- RecordInfo->ProgressID = PERF_INMODULE_END_ID;
+ *ProgressID = PERF_INMODULE_END_ID;
}
} else {
- return EFI_UNSUPPORTED;
+ return EFI_INVALID_PARAMETER;
}
- //
- // Get the Guid and string.
- //
- if(PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {
- RecordInfo->RecordSize = sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD) + STRING_SIZE;
- } else {
- switch (RecordType) {
- case FPDT_GUID_EVENT_TYPE:
- RecordInfo->RecordSize = sizeof (FPDT_GUID_EVENT_RECORD);
- break;
+ return EFI_SUCCESS;
+}
- case FPDT_GUID_QWORD_EVENT_TYPE:
- RecordInfo->RecordSize = sizeof (FPDT_GUID_QWORD_EVENT_RECORD);
- break;
+/**
+ Copies the string from Source into Destination and updates Length with the
+ size of the string.
- case FPDT_DYNAMIC_STRING_EVENT_TYPE:
- if (Token != NULL) {
- StringSize = AsciiStrSize (Token);
- } else if (Module != NULL) {
- StringSize = AsciiStrSize (Module);
- } else {
- StringSize = STRING_SIZE;
- }
- RecordInfo->RecordSize = (UINT8)(sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD) + StringSize);
- break;
+ @param Destination - destination of the string copy
+ @param Source - pointer to the source string which will get copied
+ @param Length - pointer to a length variable to be updated
- default:
- //
- // Other type is unsupported in PEI phase yet, return EFI_UNSUPPORTED
- //
- return EFI_UNSUPPORTED;
+**/
+VOID
+CopyStringIntoPerfRecordAndUpdateLength (
+ IN OUT CHAR8 *Destination,
+ IN CONST CHAR8 *Source,
+ IN OUT UINT8 *Length
+ )
+{
+ UINTN StringLen;
+ UINTN DestMax;
+
+ ASSERT (Source != NULL);
+
+ if (PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {
+ DestMax = STRING_SIZE;
+ } else {
+ DestMax = AsciiStrSize (Source);
+ if (DestMax > STRING_SIZE) {
+ DestMax = STRING_SIZE;
}
}
- RecordInfo->Type = RecordType;
- return EFI_SUCCESS;
+ StringLen = AsciiStrLen (Source);
+ if (StringLen >= DestMax) {
+ StringLen = DestMax -1;
+ }
+
+ AsciiStrnCpyS(Destination, DestMax, Source, StringLen);
+ *Length += (UINT8)DestMax;
+
+ return;
}
+
/**
Convert PEI performance log to FPDT String boot record.
- @param IsStart TRUE if the performance log is start log.
- @param Handle Pointer to environment specific context used
- to identify the component being measured.
- @param Token Pointer to a Null-terminated ASCII string
- that identifies the component being measured.
- @param Module Pointer to a Null-terminated ASCII string
- that identifies the module being measured.
- @param Ticker 64-bit time stamp.
- @param Identifier 32-bit identifier. If the value is 0, the created record
- is same as the one created by StartGauge of PERFORMANCE_PROTOCOL.
-
- @retval EFI_SUCCESS Add FPDT boot record.
- @retval EFI_OUT_OF_RESOURCES There are not enough resources to record the measurement.
- @retval EFI_UNSUPPORTED No matched FPDT record.
+ @param CallerIdentifier - Image handle or pointer to caller ID GUID.
+ @param Guid - Pointer to a GUID.
+ @param String - Pointer to a string describing the measurement.
+ @param Ticker - 64-bit time stamp.
+ @param Address - Pointer to a location in memory relevant to the measurement.
+ @param PerfId - Performance identifier describing the type of measurement.
+ @param Attribute - The attribute of the measurement. According to attribute can create a start
+ record for PERF_START/PERF_START_EX, or a end record for PERF_END/PERF_END_EX,
+ or a general record for other Perf macros.
+
+ @retval EFI_SUCCESS - Successfully created performance record.
+ @retval EFI_OUT_OF_RESOURCES - Ran out of space to store the records.
+ @retval EFI_INVALID_PARAMETER - Invalid parameter passed to function - NULL
+ pointer or invalid PerfId.
**/
EFI_STATUS
-InsertPeiFpdtMeasurement (
- IN BOOLEAN IsStart,
- IN CONST VOID *Handle, OPTIONAL
- IN CONST CHAR8 *Token, OPTIONAL
- IN CONST CHAR8 *Module, OPTIONAL
- IN UINT64 Ticker,
- IN UINT32 Identifier
+InsertFpdtRecord (
+ IN CONST VOID *CallerIdentifier, OPTIONAL
+ IN CONST VOID *Guid, OPTIONAL
+ IN CONST CHAR8 *String, OPTIONAL
+ IN UINT64 Ticker,
+ IN UINT64 Address, OPTIONAL
+ IN UINT16 PerfId,
+ IN PERF_MEASUREMENT_ATTRIBUTE Attribute
)
{
- EFI_HOB_GUID_TYPE *GuidHob;
- UINTN PeiPerformanceSize;
- UINT8 *PeiFirmwarePerformance;
- FPDT_PEI_EXT_PERF_HEADER *PeiPerformanceLogHeader;
FPDT_RECORD_PTR FpdtRecordPtr;
- FPDT_BASIC_RECORD_INFO RecordInfo;
CONST VOID *ModuleGuid;
- UINTN DestMax;
- UINTN StrLength;
CONST CHAR8 *StringPtr;
EFI_STATUS Status;
- UINT16 PeiPerformanceLogEntries;
UINT64 TimeStamp;
+ FPDT_PEI_EXT_PERF_HEADER *PeiPerformanceLogHeader;
StringPtr = NULL;
FpdtRecordPtr.RecordHeader = NULL;
PeiPerformanceLogHeader = NULL;
//
- // Get record info (type, size, ProgressID and Module Guid).
- //
- Status = GetFpdtRecordInfo (IsStart, Handle, Token, Module, &RecordInfo);
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- //
- // If PERF_START()/PERF_END() have specified the ProgressID,it has high priority.
- // !!! Note: If the Perf is not the known Token used in the core but have same
- // ID with the core Token, this case will not be supported.
- // And in currtnt usage mode, for the unkown ID, there is a general rule:
- // If it is start pref: the lower 4 bits of the ID should be 0.
- // If it is end pref: the lower 4 bits of the ID should not be 0.
- // If input ID doesn't follow the rule, we will adjust it.
+ // 1. Get the Perf Id for records from PERF_START/PERF_END, PERF_START_EX/PERF_END_EX.
+ // notes: For other Perf macros (Attribute == PerfEntry), their Id is known.
//
- if ((Identifier != 0) && (IsKnownID (Identifier)) && (!IsKnownTokens (Token))) {
- return EFI_UNSUPPORTED;
- } else if ((Identifier != 0) && (!IsKnownID (Identifier)) && (!IsKnownTokens (Token))) {
- if (IsStart && ((Identifier & 0x000F) != 0)) {
- Identifier &= 0xFFF0;
- } else if ((!IsStart) && ((Identifier & 0x000F) == 0)) {
- Identifier += 1;
- }
- RecordInfo.ProgressID = (UINT16)Identifier;
- }
-
- //
- // Get the number of PeiPerformanceLogEntries form PCD.
- //
- PeiPerformanceLogEntries = (UINT16) (PcdGet16 (PcdMaxPeiPerformanceLogEntries16) != 0 ?
- PcdGet16 (PcdMaxPeiPerformanceLogEntries16) :
- PcdGet8 (PcdMaxPeiPerformanceLogEntries));
-
- //
- // Create GUID HOB Data.
- //
- GuidHob = GetFirstGuidHob (&gEdkiiFpdtExtendedFirmwarePerformanceGuid);
- PeiFirmwarePerformance = NULL;
- while (GuidHob != NULL) {
- //
- // PEI Performance HOB was found, then return the existing one.
- //
- PeiFirmwarePerformance = (UINT8*)GET_GUID_HOB_DATA (GuidHob);
- PeiPerformanceLogHeader = (FPDT_PEI_EXT_PERF_HEADER *)PeiFirmwarePerformance;
- if (!PeiPerformanceLogHeader->HobIsFull && PeiPerformanceLogHeader->SizeOfAllEntries + RecordInfo.RecordSize > PeiPerformanceLogEntries * MAX_RECORD_SIZE) {
- PeiPerformanceLogHeader->HobIsFull = TRUE;
- }
- if (!PeiPerformanceLogHeader->HobIsFull && PeiPerformanceLogHeader->SizeOfAllEntries + RecordInfo.RecordSize <= PeiPerformanceLogEntries * MAX_RECORD_SIZE) {
- FpdtRecordPtr.RecordHeader = (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER *)(PeiFirmwarePerformance + sizeof (FPDT_PEI_EXT_PERF_HEADER) + PeiPerformanceLogHeader->SizeOfAllEntries);
- break;
- }
- //
- // Previous HOB is used, then find next one.
- //
- GuidHob = GetNextGuidHob (&gEdkiiFpdtExtendedFirmwarePerformanceGuid, GET_NEXT_HOB (GuidHob));
- }
-
- if (GuidHob == NULL) {
+ if (Attribute != PerfEntry) {
//
- // PEI Performance HOB was not found, then build one.
+ // If PERF_START_EX()/PERF_END_EX() have specified the ProgressID,it has high priority.
+ // !!! Note: If the Perf is not the known Token used in the core but have same
+ // ID with the core Token, this case will not be supported.
+ // And in currtnt usage mode, for the unkown ID, there is a general rule:
+ // If it is start pref: the lower 4 bits of the ID should be 0.
+ // If it is end pref: the lower 4 bits of the ID should not be 0.
+ // If input ID doesn't follow the rule, we will adjust it.
//
- PeiPerformanceSize = sizeof (FPDT_PEI_EXT_PERF_HEADER) +
- MAX_RECORD_SIZE * PeiPerformanceLogEntries;
- PeiFirmwarePerformance = (UINT8*)BuildGuidHob (&gEdkiiFpdtExtendedFirmwarePerformanceGuid, PeiPerformanceSize);
- if (PeiFirmwarePerformance != NULL) {
- ZeroMem (PeiFirmwarePerformance, PeiPerformanceSize);
+ if ((PerfId != 0) && (IsKnownID (PerfId)) && (!IsKnownTokens (String))) {
+ return EFI_UNSUPPORTED;
+ } else if ((PerfId != 0) && (!IsKnownID (PerfId)) && (!IsKnownTokens (String))) {
+ if (Attribute == PerfStartEntry && ((PerfId & 0x000F) != 0)) {
+ PerfId &= 0xFFF0;
+ } else if ((Attribute == PerfEndEntry) && ((PerfId & 0x000F) == 0)) {
+ PerfId += 1;
+ }
+ } else if (PerfId == 0) {
+ Status = GetFpdtRecordId (Attribute, CallerIdentifier, String, &PerfId);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
}
- PeiPerformanceLogHeader = (FPDT_PEI_EXT_PERF_HEADER *)PeiFirmwarePerformance;
- FpdtRecordPtr.RecordHeader = (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER *)(PeiFirmwarePerformance + sizeof (FPDT_PEI_EXT_PERF_HEADER));
}
- if (PeiFirmwarePerformance == NULL) {
- //
- // there is no enough resource to store performance data
- //
- return EFI_OUT_OF_RESOURCES;
+ //
+ // 2. Get the buffer to store the FPDT record.
+ //
+ Status = GetFpdtRecordPtr (PEI_MAX_RECORD_SIZE, &FpdtRecordPtr, &PeiPerformanceLogHeader);
+ if (EFI_ERROR (Status)) {
+ return Status;
}
//
- // Get the TimeStamp.
+ // 3 Get the TimeStamp.
//
if (Ticker == 0) {
Ticker = GetPerformanceCounter ();
TimeStamp = GetTimeInNanoSecond (Ticker);
} else if (Ticker == 1) {
@@ -351,74 +375,142 @@ InsertPeiFpdtMeasurement (
} else {
TimeStamp = GetTimeInNanoSecond (Ticker);
}
//
- // Get the ModuleGuid.
+ // 4.Get the ModuleGuid.
//
- if (Handle != NULL) {
- ModuleGuid = Handle;
+ if (CallerIdentifier != NULL) {
+ ModuleGuid = CallerIdentifier;
} else {
ModuleGuid = &gEfiCallerIdGuid;
}
- switch (RecordInfo.Type) {
- case FPDT_GUID_EVENT_TYPE:
- FpdtRecordPtr.GuidEvent->Header.Type = FPDT_GUID_EVENT_TYPE;
- FpdtRecordPtr.GuidEvent->Header.Length = RecordInfo.RecordSize;;
- FpdtRecordPtr.GuidEvent->Header.Revision = FPDT_RECORD_REVISION_1;
- FpdtRecordPtr.GuidEvent->ProgressID = RecordInfo.ProgressID;
- FpdtRecordPtr.GuidEvent->Timestamp = TimeStamp;
- CopyMem (&FpdtRecordPtr.GuidEvent->Guid, ModuleGuid, sizeof (EFI_GUID));
- PeiPerformanceLogHeader->SizeOfAllEntries += RecordInfo.RecordSize;
+ //
+ // 5. Fill in the FPDT record according to different Performance Identifier.
+ //
+ switch (PerfId) {
+ case MODULE_START_ID:
+ case MODULE_END_ID:
+ StringPtr = PEIM_TOK;
+ if (!PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {
+ FpdtRecordPtr.GuidEvent->Header.Type = FPDT_GUID_EVENT_TYPE;
+ FpdtRecordPtr.GuidEvent->Header.Length = sizeof (FPDT_GUID_EVENT_RECORD);
+ FpdtRecordPtr.GuidEvent->Header.Revision = FPDT_RECORD_REVISION_1;
+ FpdtRecordPtr.GuidEvent->ProgressID = PerfId;
+ FpdtRecordPtr.GuidEvent->Timestamp = TimeStamp;
+ CopyMem (&FpdtRecordPtr.GuidEvent->Guid, ModuleGuid, sizeof (EFI_GUID));
+ }
break;
- case FPDT_GUID_QWORD_EVENT_TYPE:
- FpdtRecordPtr.GuidQwordEvent->Header.Type = FPDT_GUID_QWORD_EVENT_TYPE;
- FpdtRecordPtr.GuidQwordEvent->Header.Length = RecordInfo.RecordSize;;
- FpdtRecordPtr.GuidQwordEvent->Header.Revision = FPDT_RECORD_REVISION_1;
- FpdtRecordPtr.GuidQwordEvent->ProgressID = RecordInfo.ProgressID;
- FpdtRecordPtr.GuidQwordEvent->Timestamp = TimeStamp;
- PeiPerformanceLogHeader->LoadImageCount++;
- FpdtRecordPtr.GuidQwordEvent->Qword = PeiPerformanceLogHeader->LoadImageCount;
- CopyMem (&FpdtRecordPtr.GuidQwordEvent->Guid, ModuleGuid, sizeof (EFI_GUID));
- PeiPerformanceLogHeader->SizeOfAllEntries += RecordInfo.RecordSize;
+ case MODULE_LOADIMAGE_START_ID:
+ case MODULE_LOADIMAGE_END_ID:
+ StringPtr = LOAD_IMAGE_TOK;
+ if (!PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {
+ FpdtRecordPtr.GuidQwordEvent->Header.Type = FPDT_GUID_QWORD_EVENT_TYPE;
+ FpdtRecordPtr.GuidQwordEvent->Header.Length = sizeof (FPDT_GUID_QWORD_EVENT_RECORD);
+ FpdtRecordPtr.GuidQwordEvent->Header.Revision = FPDT_RECORD_REVISION_1;
+ FpdtRecordPtr.GuidQwordEvent->ProgressID = PerfId;
+ FpdtRecordPtr.GuidQwordEvent->Timestamp = TimeStamp;
+ if (PerfId == MODULE_LOADIMAGE_START_ID) {
+ PeiPerformanceLogHeader->LoadImageCount++;
+ }
+ FpdtRecordPtr.GuidQwordEvent->Qword = PeiPerformanceLogHeader->LoadImageCount;
+ CopyMem (&FpdtRecordPtr.GuidQwordEvent->Guid, ModuleGuid, sizeof (EFI_GUID));
+ }
break;
- case FPDT_DYNAMIC_STRING_EVENT_TYPE:
- FpdtRecordPtr.DynamicStringEvent->Header.Type = FPDT_DYNAMIC_STRING_EVENT_TYPE;
- FpdtRecordPtr.DynamicStringEvent->Header.Length = RecordInfo.RecordSize;
- FpdtRecordPtr.DynamicStringEvent->Header.Revision = FPDT_RECORD_REVISION_1;
- FpdtRecordPtr.DynamicStringEvent->ProgressID = RecordInfo.ProgressID;
- FpdtRecordPtr.DynamicStringEvent->Timestamp = TimeStamp;
- CopyMem (&FpdtRecordPtr.DynamicStringEvent->Guid, ModuleGuid, sizeof (EFI_GUID));
- PeiPerformanceLogHeader->SizeOfAllEntries += RecordInfo.RecordSize;
-
- if (Token != NULL) {
- StringPtr = Token;
- } else if (Module != NULL) {
- StringPtr = Module;
+ case PERF_EVENTSIGNAL_START_ID:
+ case PERF_EVENTSIGNAL_END_ID:
+ case PERF_CALLBACK_START_ID:
+ case PERF_CALLBACK_END_ID:
+ if (String != NULL && AsciiStrLen (String) != 0) {
+ StringPtr = String;
+ } else {
+ StringPtr = "unknown name";
}
- if (StringPtr != NULL && AsciiStrLen (StringPtr) != 0) {
- DestMax = (RecordInfo.RecordSize - sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD)) / sizeof (CHAR8);
- StrLength = AsciiStrLen (StringPtr);
- if (StrLength >= DestMax) {
- StrLength = DestMax -1;
- }
- AsciiStrnCpyS (FpdtRecordPtr.DynamicStringEvent->String, DestMax, StringPtr, StrLength);
+ if (!PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {
+ FpdtRecordPtr.DualGuidStringEvent->Header.Type = FPDT_DUAL_GUID_STRING_EVENT_TYPE;
+ FpdtRecordPtr.DualGuidStringEvent->Header.Length = sizeof (FPDT_DUAL_GUID_STRING_EVENT_RECORD);
+ FpdtRecordPtr.DualGuidStringEvent->Header.Revision = FPDT_RECORD_REVISION_1;
+ FpdtRecordPtr.DualGuidStringEvent->ProgressID = PerfId;
+ FpdtRecordPtr.DualGuidStringEvent->Timestamp = TimeStamp;
+ CopyMem (&FpdtRecordPtr.DualGuidStringEvent->Guid1, ModuleGuid, sizeof (FpdtRecordPtr.DualGuidStringEvent->Guid1));
+ CopyMem (&FpdtRecordPtr.DualGuidStringEvent->Guid2, Guid, sizeof (FpdtRecordPtr.DualGuidStringEvent->Guid2));
+ }
+ break;
+
+ case PERF_EVENT_ID:
+ case PERF_FUNCTION_START_ID:
+ case PERF_FUNCTION_END_ID:
+ case PERF_INMODULE_START_ID:
+ case PERF_INMODULE_END_ID:
+ case PERF_CROSSMODULE_START_ID:
+ case PERF_CROSSMODULE_END_ID:
+ if (String != NULL && AsciiStrLen (String) != 0) {
+ StringPtr = String;
} else {
- AsciiStrCpyS (FpdtRecordPtr.DynamicStringEvent->String, FPDT_STRING_EVENT_RECORD_NAME_LENGTH, "unknown name");
+ StringPtr = "unknown name";
+ }
+ if (!PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {
+ FpdtRecordPtr.DynamicStringEvent->Header.Type = FPDT_DYNAMIC_STRING_EVENT_TYPE;
+ FpdtRecordPtr.DynamicStringEvent->Header.Length = sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD);
+ FpdtRecordPtr.DynamicStringEvent->Header.Revision = FPDT_RECORD_REVISION_1;
+ FpdtRecordPtr.DynamicStringEvent->ProgressID = PerfId;
+ FpdtRecordPtr.DynamicStringEvent->Timestamp = TimeStamp;
+ CopyMem (&FpdtRecordPtr.DynamicStringEvent->Guid, ModuleGuid, sizeof (EFI_GUID));
+ CopyStringIntoPerfRecordAndUpdateLength (FpdtRecordPtr.DynamicStringEvent->String, StringPtr, &FpdtRecordPtr.DynamicStringEvent->Header.Length);
}
break;
default:
- //
- // Record is not supported in current PEI phase, return EFI_ABORTED
- //
- return EFI_UNSUPPORTED;
+ if (Attribute != PerfEntry) {
+ if (String != NULL && AsciiStrLen (String) != 0) {
+ StringPtr = String;
+ } else {
+ StringPtr = "unknown name";
+ }
+ if (!PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {
+ FpdtRecordPtr.DynamicStringEvent->Header.Type = FPDT_DYNAMIC_STRING_EVENT_TYPE;
+ FpdtRecordPtr.DynamicStringEvent->Header.Length = sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD);
+ FpdtRecordPtr.DynamicStringEvent->Header.Revision = FPDT_RECORD_REVISION_1;
+ FpdtRecordPtr.DynamicStringEvent->ProgressID = PerfId;
+ FpdtRecordPtr.DynamicStringEvent->Timestamp = TimeStamp;
+ CopyMem (&FpdtRecordPtr.DynamicStringEvent->Guid, ModuleGuid, sizeof (FpdtRecordPtr.DynamicStringEvent->Guid));
+ CopyStringIntoPerfRecordAndUpdateLength (FpdtRecordPtr.DynamicStringEvent->String, StringPtr, &FpdtRecordPtr.DynamicStringEvent->Header.Length);
+ }
+ } else {
+ return EFI_INVALID_PARAMETER;
+ }
+ break;
+ }
+
+ //
+ // 5.2 When PcdEdkiiFpdtStringRecordEnableOnly==TRUE, create string record for all Perf entries.
+ //
+ if (PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {
+ FpdtRecordPtr.DynamicStringEvent->Header.Type = FPDT_DYNAMIC_STRING_EVENT_TYPE;
+ FpdtRecordPtr.DynamicStringEvent->Header.Length = sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD);
+ FpdtRecordPtr.DynamicStringEvent->Header.Revision = FPDT_RECORD_REVISION_1;
+ FpdtRecordPtr.DynamicStringEvent->ProgressID = PerfId;
+ FpdtRecordPtr.DynamicStringEvent->Timestamp = TimeStamp;
+ if (Guid != NULL) {
+ //
+ // Cache the event guid in string event record.
+ //
+ CopyMem (&FpdtRecordPtr.DynamicStringEvent->Guid, Guid, sizeof (EFI_GUID));
+ } else {
+ CopyMem (&FpdtRecordPtr.DynamicStringEvent->Guid, ModuleGuid, sizeof (EFI_GUID));
+ }
+ CopyStringIntoPerfRecordAndUpdateLength (FpdtRecordPtr.DynamicStringEvent->String, StringPtr, &FpdtRecordPtr.DynamicStringEvent->Header.Length);
}
+ //
+ // 6. Update the length of the used buffer after fill in the record.
+ //
+ PeiPerformanceLogHeader->SizeOfAllEntries += FpdtRecordPtr.RecordHeader->Length;
+
return EFI_SUCCESS;
}
/**
Creates a record for the beginning of a performance measurement.
@@ -452,11 +544,22 @@ StartPerformanceMeasurementEx (
IN CONST CHAR8 *Module, OPTIONAL
IN UINT64 TimeStamp,
IN UINT32 Identifier
)
{
- return InsertPeiFpdtMeasurement (TRUE, Handle, Token, Module, TimeStamp, Identifier);
+ CONST CHAR8 *String;
+
+ if (Token != NULL) {
+ String = Token;
+ } else if (Module != NULL) {
+ String = Module;
+ } else {
+ String = NULL;
+ }
+
+ return (RETURN_STATUS)InsertFpdtRecord (Handle, NULL, String, TimeStamp, 0, (UINT16)Identifier, PerfStartEntry);
+
}
/**
Creates a record for the end of a performance measurement.
@@ -487,11 +590,21 @@ EndPerformanceMeasurementEx (
IN CONST CHAR8 *Module, OPTIONAL
IN UINT64 TimeStamp,
IN UINT32 Identifier
)
{
- return InsertPeiFpdtMeasurement (FALSE, Handle, Token, Module, TimeStamp, Identifier);
+ CONST CHAR8 *String;
+
+ if (Token != NULL) {
+ String = Token;
+ } else if (Module != NULL) {
+ String = Module;
+ } else {
+ String = NULL;
+ }
+
+ return (RETURN_STATUS)InsertFpdtRecord (Handle, NULL, String, TimeStamp, 0, (UINT16)Identifier, PerfEndEntry);
}
/**
Attempts to retrieve a performance measurement log entry from the performance measurement log.
It can also retrieve the log created by StartPerformanceMeasurement and EndPerformanceMeasurement,
@@ -580,11 +693,11 @@ StartPerformanceMeasurement (
IN CONST CHAR8 *Token, OPTIONAL
IN CONST CHAR8 *Module, OPTIONAL
IN UINT64 TimeStamp
)
{
- return InsertPeiFpdtMeasurement (TRUE, Handle, Token, Module, TimeStamp, 0);
+ return StartPerformanceMeasurementEx (Handle, Token, Module, TimeStamp, 0);
}
/**
Creates a record for the end of a performance measurement.
@@ -612,11 +725,11 @@ EndPerformanceMeasurement (
IN CONST CHAR8 *Token, OPTIONAL
IN CONST CHAR8 *Module, OPTIONAL
IN UINT64 TimeStamp
)
{
- return InsertPeiFpdtMeasurement (FALSE, Handle, Token, Module, TimeStamp, 0);
+ return EndPerformanceMeasurementEx (Handle, Token, Module, TimeStamp, 0);
}
/**
Attempts to retrieve a performance measurement log entry from the performance measurement log.
It can also retrieve the log created by StartPerformanceMeasurementEx and EndPerformanceMeasurementEx,
@@ -690,5 +803,60 @@ PerformanceMeasurementEnabled (
VOID
)
{
return (BOOLEAN) ((PcdGet8(PcdPerformanceLibraryPropertyMask) & PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED) != 0);
}
+
+/**
+ Create performance record with event description and a timestamp.
+
+ @param CallerIdentifier - Image handle or pointer to caller ID GUID
+ @param Guid - Pointer to a GUID
+ @param String - Pointer to a string describing the measurement
+ @param Address - Pointer to a location in memory relevant to the measurement
+ @param Identifier - Performance identifier describing the type of measurement
+
+ @retval RETURN_SUCCESS - Successfully created performance record
+ @retval RETURN_OUT_OF_RESOURCES - Ran out of space to store the records
+ @retval RETURN_INVALID_PARAMETER - Invalid parameter passed to function - NULL
+ pointer or invalid PerfId
+
+**/
+RETURN_STATUS
+EFIAPI
+LogPerformanceMeasurement (
+ IN CONST VOID *CallerIdentifier,
+ IN CONST VOID *Guid, OPTIONAL
+ IN CONST CHAR8 *String, OPTIONAL
+ IN UINT64 Address, OPTIONAL
+ IN UINT32 Identifier
+ )
+{
+ return (RETURN_STATUS)InsertFpdtRecord (CallerIdentifier, Guid, String, 0, Address, (UINT16)Identifier, PerfEntry);
+}
+
+/**
+ Check whether the specified performance measurement can be logged.
+
+ This function returns TRUE when the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of PcdPerformanceLibraryPropertyMask is set
+ and the Type disable bit in PcdPerformanceLibraryPropertyMask is not set.
+
+ @param Type - Type of the performance measurement entry.
+
+ @retval TRUE The performance measurement can be logged.
+ @retval FALSE The performance measurement can NOT be logged.
+
+**/
+BOOLEAN
+EFIAPI
+LogPerformanceMeasurementEnabled (
+ IN CONST UINTN Type
+ )
+{
+ //
+ // When Performance measurement is enabled and the type is not filtered, the performance can be logged.
+ //
+ if (PerformanceMeasurementEnabled () && (PcdGet8(PcdPerformanceLibraryPropertyMask) & Type) == 0) {
+ return TRUE;
+ }
+ return FALSE;
+}
diff --git a/MdeModulePkg/Library/SmmCorePerformanceLib/SmmCorePerformanceLib.c b/MdeModulePkg/Library/SmmCorePerformanceLib/SmmCorePerformanceLib.c
index e630773562f..0c00fb51e82 100644
--- a/MdeModulePkg/Library/SmmCorePerformanceLib/SmmCorePerformanceLib.c
+++ b/MdeModulePkg/Library/SmmCorePerformanceLib/SmmCorePerformanceLib.c
@@ -45,23 +45,83 @@ typedef struct {
HANDLE_GUID_MAP mCacheHandleGuidTable[CACHE_HANDLE_GUID_COUNT];
UINTN mCachePairCount = 0;
UINT32 mPerformanceLength = 0;
UINT32 mMaxPerformanceLength = 0;
+UINT32 mLoadImageCount = 0;
BOOLEAN mFpdtDataIsReported = FALSE;
BOOLEAN mLackSpaceIsReport = FALSE;
CHAR8 *mPlatformLanguage = NULL;
SPIN_LOCK mSmmFpdtLock;
PERFORMANCE_PROPERTY mPerformanceProperty;
+UINT32 mCachedLength = 0;
//
// Interfaces for SMM PerformanceMeasurement Protocol.
//
EDKII_PERFORMANCE_MEASUREMENT_PROTOCOL mPerformanceMeasurementInterface = {
CreatePerformanceMeasurement,
};
+/**
+ Return the pointer to the FPDT record in the allocated memory.
+
+ @param RecordSize The size of FPDT record.
+ @param FpdtRecordPtr Pointer the FPDT record in the allocated memory.
+
+ @retval EFI_SUCCESS Successfully get the pointer to the FPDT record.
+ @retval EFI_OUT_OF_RESOURCES Ran out of space to store the records.
+**/
+EFI_STATUS
+GetFpdtRecordPtr (
+ IN UINT8 RecordSize,
+ IN OUT FPDT_RECORD_PTR *FpdtRecordPtr
+)
+{
+ if (mFpdtDataIsReported) {
+ //
+ // Append Boot records after Smm boot performance records have been reported.
+ //
+ if (mPerformanceLength + RecordSize > mMaxPerformanceLength) {
+ if (!mLackSpaceIsReport) {
+ DEBUG ((DEBUG_INFO, "SmmCorePerformanceLib: No enough space to save boot records\n"));
+ mLackSpaceIsReport = TRUE;
+ }
+ return EFI_OUT_OF_RESOURCES;
+ } else {
+ //
+ // Covert buffer to FPDT Ptr Union type.
+ //
+ FpdtRecordPtr->RecordHeader = (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER *)((UINT8*)mSmmBootPerformanceTable + mSmmBootPerformanceTable->Header.Length);
+ }
+ } else {
+ //
+ // Check if pre-allocated buffer is full
+ //
+ if (mPerformanceLength + RecordSize > mMaxPerformanceLength) {
+ mSmmBootPerformanceTable = ReallocatePool (
+ mPerformanceLength,
+ mPerformanceLength + sizeof (SMM_BOOT_PERFORMANCE_TABLE) + RecordSize + FIRMWARE_RECORD_BUFFER,
+ mSmmBootPerformanceTable
+ );
+
+ if (mSmmBootPerformanceTable == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ mSmmBootPerformanceTable->Header.Length = sizeof (SMM_BOOT_PERFORMANCE_TABLE) + mPerformanceLength;
+ mMaxPerformanceLength = mPerformanceLength + sizeof (SMM_BOOT_PERFORMANCE_TABLE) + RecordSize + FIRMWARE_RECORD_BUFFER;
+ }
+ //
+ // Covert buffer to FPDT Ptr Union type.
+ //
+ FpdtRecordPtr->RecordHeader = (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER *)((UINT8*)mSmmBootPerformanceTable + mSmmBootPerformanceTable->Header.Length);
+ }
+ FpdtRecordPtr->RecordHeader->Length = 0;
+ return EFI_SUCCESS;
+}
+
+
/**
Check whether the Token is a known one which is uesed by core.
@param Token Pointer to a Null-terminated ASCII string
@@ -123,117 +183,63 @@ IsKnownID (
return FALSE;
}
}
/**
- Get the FPDT record info.
+ Get the FPDT record identifier.
- @param IsStart TRUE if the performance log is start log.
- @param Handle Pointer to environment specific context used
- to identify the component being measured.
- @param Token Pointer to a Null-terminated ASCII string
- that identifies the component being measured.
- @param Module Pointer to a Null-terminated ASCII string
- that identifies the module being measured.
- @param RecordInfo On return, pointer to the info of the record.
- @param UseModuleName Only useful for FPDT_DYNAMIC_STRING_EVENT_TYPE, indicate that whether need use
- Module name to fill the string field in the FPDT_DYNAMIC_STRING_EVENT_RECORD.
+ @param Attribute The attribute of the Record.
+ PerfStartEntry: Start Record.
+ PerfEndEntry: End Record.
+ @param Handle Pointer to environment specific context used to identify the component being measured.
+ @param String Pointer to a Null-terminated ASCII string that identifies the component being measured.
+ @param ProgressID On return, pointer to the ProgressID.
- @retval EFI_SUCCESS Get record info successfully.
- @retval EFI_UNSUPPORTED No matched FPDT record.
+ @retval EFI_SUCCESS Get record info successfully.
+ @retval EFI_INVALID_PARAMETER No matched FPDT record.
**/
EFI_STATUS
-GetFpdtRecordInfo (
- IN BOOLEAN IsStart,
- IN CONST VOID *Handle,
- IN CONST CHAR8 *Token,
- IN CONST CHAR8 *Module,
- OUT FPDT_BASIC_RECORD_INFO *RecordInfo,
- IN OUT BOOLEAN *UseModuleName
+GetFpdtRecordId (
+ IN PERF_MEASUREMENT_ATTRIBUTE Attribute,
+ IN CONST VOID *Handle,
+ IN CONST CHAR8 *String,
+ OUT UINT16 *ProgressID
)
{
- UINT16 RecordType;
- UINTN StringSize;
-
- RecordType = FPDT_DYNAMIC_STRING_EVENT_TYPE;
-
//
- // Token to Type and Id.
+ // Token to Id.
//
- if (Token != NULL) {
- if (AsciiStrCmp (Token, START_IMAGE_TOK) == 0) { // "StartImage:"
- *UseModuleName = TRUE;
- RecordType = FPDT_GUID_EVENT_TYPE;
- if (IsStart) {
- RecordInfo->ProgressID = MODULE_START_ID;
+ if (String != NULL) {
+ if (AsciiStrCmp (String, START_IMAGE_TOK) == 0) { // "StartImage:"
+ if (Attribute == PerfStartEntry) {
+ *ProgressID = MODULE_START_ID;
} else {
- RecordInfo->ProgressID = MODULE_END_ID;
+ *ProgressID = MODULE_END_ID;
}
- } else if (AsciiStrCmp (Token, LOAD_IMAGE_TOK) == 0) { // "LoadImage:"
- *UseModuleName = TRUE;
- RecordType = FPDT_GUID_QWORD_EVENT_TYPE;
- if (IsStart) {
- RecordInfo->ProgressID = MODULE_LOADIMAGE_START_ID;
+ } else if (AsciiStrCmp (String, LOAD_IMAGE_TOK) == 0) { // "LoadImage:"
+ if (Attribute == PerfStartEntry) {
+ *ProgressID = MODULE_LOADIMAGE_START_ID;
} else {
- RecordInfo->ProgressID = MODULE_LOADIMAGE_END_ID;
+ *ProgressID = MODULE_LOADIMAGE_END_ID;
}
} else { // Pref used in Modules
- if (IsStart) {
- RecordInfo->ProgressID = PERF_INMODULE_START_ID;
+ if (Attribute == PerfStartEntry) {
+ *ProgressID = PERF_INMODULE_START_ID;
} else {
- RecordInfo->ProgressID = PERF_INMODULE_END_ID;
+ *ProgressID = PERF_INMODULE_END_ID;
}
}
- } else if (Handle != NULL || Module != NULL) { // Pref used in Modules
- if (IsStart) {
- RecordInfo->ProgressID = PERF_INMODULE_START_ID;
+ } else if (Handle != NULL) { // Pref used in Modules
+ if (Attribute == PerfStartEntry) {
+ *ProgressID = PERF_INMODULE_START_ID;
} else {
- RecordInfo->ProgressID = PERF_INMODULE_END_ID;
+ *ProgressID = PERF_INMODULE_END_ID;
}
} else {
return EFI_UNSUPPORTED;
}
-
- if (PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {
- RecordType = FPDT_DYNAMIC_STRING_EVENT_TYPE;
- RecordInfo->RecordSize = sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD) + STRING_SIZE;
- } else {
- switch (RecordType) {
- case FPDT_GUID_EVENT_TYPE:
- RecordInfo->RecordSize = sizeof (FPDT_GUID_EVENT_RECORD);
- break;
-
- case FPDT_DYNAMIC_STRING_EVENT_TYPE:
- if (*UseModuleName) {
- StringSize = STRING_SIZE;
- } else if (Token != NULL) {
- StringSize = AsciiStrSize (Token);
- } else if (Module != NULL) {
- StringSize = AsciiStrSize (Module);
- } else {
- StringSize = STRING_SIZE;
- }
- if (StringSize > STRING_SIZE) {
- StringSize = STRING_SIZE;
- }
- RecordInfo->RecordSize = (UINT8)(sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD) + StringSize);
- break;
-
- case FPDT_GUID_QWORD_EVENT_TYPE:
- RecordInfo->RecordSize = (UINT8)sizeof (FPDT_GUID_QWORD_EVENT_RECORD);
- break;
-
- default:
- //
- // Record type is unsupported in SMM phase.
- //
- return EFI_UNSUPPORTED;
- }
- }
-
- RecordInfo->Type = RecordType;
return EFI_SUCCESS;
}
/**
Get a human readable module name and module guid for the given image handle.
@@ -435,123 +441,144 @@ Done:
return Status;
}
/**
- Add performance log to FPDT boot record table.
+ Copies the string from Source into Destination and updates Length with the
+ size of the string.
- @param IsStart TRUE if the performance log is start log.
- @param Handle Pointer to environment specific context used
- to identify the component being measured.
- @param Token Pointer to a Null-terminated ASCII string
- that identifies the component being measured.
- @param Module Pointer to a Null-terminated ASCII string
- that identifies the module being measured.
- @param Ticker 64-bit time stamp.
- @param Identifier 32-bit identifier. If the value is 0, the created record
- is same as the one created by StartGauge of PERFORMANCE_PROTOCOL.
+ @param Destination - destination of the string copy
+ @param Source - pointer to the source string which will get copied
+ @param Length - pointer to a length variable to be updated
+
+**/
+VOID
+CopyStringIntoPerfRecordAndUpdateLength (
+ IN OUT CHAR8 *Destination,
+ IN CONST CHAR8 *Source,
+ IN OUT UINT8 *Length
+ )
+{
+ UINTN StringLen;
+ UINTN DestMax;
+
+ ASSERT (Source != NULL);
+
+ if (PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {
+ DestMax = STRING_SIZE;
+ } else {
+ DestMax = AsciiStrSize (Source);
+ if (DestMax > STRING_SIZE) {
+ DestMax = STRING_SIZE;
+ }
+ }
+ StringLen = AsciiStrLen (Source);
+ if (StringLen >= DestMax) {
+ StringLen = DestMax -1;
+ }
- @retval EFI_SUCCESS Add FPDT boot record.
- @retval EFI_OUT_OF_RESOURCES There are not enough resources to record the measurement.
- @retval EFI_UNSUPPORTED No matched FPDT record.
+ AsciiStrnCpyS(Destination, DestMax, Source, StringLen);
+ *Length += (UINT8)DestMax;
+
+ return;
+}
+
+/**
+ Create performance record with event description and a timestamp.
+
+ @param CallerIdentifier - Image handle or pointer to caller ID GUID.
+ @param Guid - Pointer to a GUID.
+ @param String - Pointer to a string describing the measurement.
+ @param Ticker - 64-bit time stamp.
+ @param Address - Pointer to a location in memory relevant to the measurement.
+ @param PerfId - Performance identifier describing the type of measurement.
+ @param Attribute - The attribute of the measurement. According to attribute can create a start
+ record for PERF_START/PERF_START_EX, or a end record for PERF_END/PERF_END_EX,
+ or a general record for other Perf macros.
+
+ @retval EFI_SUCCESS - Successfully created performance record.
+ @retval EFI_OUT_OF_RESOURCES - Ran out of space to store the records.
+ @retval EFI_INVALID_PARAMETER - Invalid parameter passed to function - NULL
+ pointer or invalid PerfId.
+
+ @retval EFI_SUCCESS - Successfully created performance record
+ @retval EFI_OUT_OF_RESOURCES - Ran out of space to store the records
+ @retval EFI_INVALID_PARAMETER - Invalid parameter passed to function - NULL
+ pointer or invalid PerfId
**/
EFI_STATUS
-InsertFpdtMeasurement (
- IN BOOLEAN IsStart,
- IN CONST VOID *Handle, OPTIONAL
- IN CONST CHAR8 *Token, OPTIONAL
- IN CONST CHAR8 *Module, OPTIONAL
- IN UINT64 Ticker,
- IN UINT32 Identifier
+InsertFpdtRecord (
+ IN CONST VOID *CallerIdentifier, OPTIONAL
+ IN CONST VOID *Guid, OPTIONAL
+ IN CONST CHAR8 *String, OPTIONAL
+ IN UINT64 Ticker,
+ IN UINT64 Address, OPTIONAL
+ IN UINT16 PerfId,
+ IN PERF_MEASUREMENT_ATTRIBUTE Attribute
)
+
{
+ EFI_STATUS Status;
EFI_GUID ModuleGuid;
CHAR8 ModuleName[FPDT_STRING_EVENT_RECORD_NAME_LENGTH];
- EFI_STATUS Status;
FPDT_RECORD_PTR FpdtRecordPtr;
+ FPDT_RECORD_PTR CachedFpdtRecordPtr;
UINT64 TimeStamp;
- FPDT_BASIC_RECORD_INFO RecordInfo;
- UINTN DestMax;
- UINTN StrLength;
CONST CHAR8 *StringPtr;
- BOOLEAN UseModuleName;
+ UINTN DestMax;
+ UINTN StringLen;
+ UINT16 ProgressId;
StringPtr = NULL;
- UseModuleName = FALSE;
ZeroMem (ModuleName, sizeof (ModuleName));
//
- // Get record info includes type, size, ProgressID.
- //
- Status = GetFpdtRecordInfo (IsStart, Handle, Token, Module, &RecordInfo, &UseModuleName);
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- //
- // If PERF_START()/PERF_END() have specified the ProgressID,it has high priority.
- // !!! Note: If the Perf is not the known Token used in the core but have same
- // ID with the core Token, this case will not be supported.
- // And in currtnt usage mode, for the unkown ID, there is a general rule:
- // If it is start pref: the lower 4 bits of the ID should be 0.
- // If it is end pref: the lower 4 bits of the ID should not be 0.
- // If input ID doesn't follow the rule, we will adjust it.
+ // 1. Get the Perf Id for records from PERF_START/PERF_END, PERF_START_EX/PERF_END_EX.
+ // notes: For other Perf macros (Attribute == PerfEntry), their Id is known.
//
- if ((Identifier != 0) && (IsKnownID (Identifier)) && (!IsKnownTokens (Token))) {
- return EFI_UNSUPPORTED;
- } else if ((Identifier != 0) && (!IsKnownID (Identifier)) && (!IsKnownTokens (Token))) {
- if (IsStart && ((Identifier & 0x000F) != 0)) {
- Identifier &= 0xFFF0;
- } else if ((!IsStart) && ((Identifier & 0x000F) == 0)) {
- Identifier += 1;
- }
- RecordInfo.ProgressID = (UINT16)Identifier;
- }
-
- if (mFpdtDataIsReported) {
+ if (Attribute != PerfEntry) {
//
- // Append Boot records after Smm boot performance records have been reported.
+ // If PERF_START_EX()/PERF_END_EX() have specified the ProgressID,it has high priority.
+ // !!! Note: If the Perf is not the known Token used in the core but have same
+ // ID with the core Token, this case will not be supported.
+ // And in currtnt usage mode, for the unkown ID, there is a general rule:
+ // If it is start pref: the lower 4 bits of the ID should be 0.
+ // If it is end pref: the lower 4 bits of the ID should not be 0.
+ // If input ID doesn't follow the rule, we will adjust it.
//
- if (mPerformanceLength + RecordInfo.RecordSize > mMaxPerformanceLength) {
- if (!mLackSpaceIsReport) {
- DEBUG ((DEBUG_INFO, "SmmCorePerformanceLib: No enough space to save boot records\n"));
- mLackSpaceIsReport = TRUE;
+ if ((PerfId != 0) && (IsKnownID (PerfId)) && (!IsKnownTokens (String))) {
+ return EFI_INVALID_PARAMETER;
+ } else if ((PerfId != 0) && (!IsKnownID (PerfId)) && (!IsKnownTokens (String))) {
+ if ((Attribute == PerfStartEntry) && ((PerfId & 0x000F) != 0)) {
+ PerfId &= 0xFFF0;
+ } else if ((Attribute == PerfEndEntry) && ((PerfId & 0x000F) == 0)) {
+ PerfId += 1;
}
- return EFI_OUT_OF_RESOURCES;
- } else {
+ }
+ if (PerfId == 0) {
//
- // Covert buffer to FPDT Ptr Union type.
+ // Get ProgressID form the String Token.
//
- FpdtRecordPtr.RecordHeader = (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER *)((UINT8*)mSmmBootPerformanceTable + mSmmBootPerformanceTable->Header.Length);
- }
- } else {
- //
- // Check if pre-allocated buffer is full
- //
- if (mPerformanceLength + RecordInfo.RecordSize > mMaxPerformanceLength) {
- mSmmBootPerformanceTable = ReallocatePool (
- mPerformanceLength,
- mPerformanceLength + sizeof (SMM_BOOT_PERFORMANCE_TABLE) + RecordInfo.RecordSize + FIRMWARE_RECORD_BUFFER,
- mSmmBootPerformanceTable
- );
-
- if (mSmmBootPerformanceTable == NULL) {
- return EFI_OUT_OF_RESOURCES;
+ Status = GetFpdtRecordId (Attribute, CallerIdentifier, String, &ProgressId);
+ if (EFI_ERROR (Status)) {
+ return Status;
}
- mSmmBootPerformanceTable->Header.Length = sizeof (SMM_BOOT_PERFORMANCE_TABLE) + mPerformanceLength;
- mMaxPerformanceLength = mPerformanceLength + sizeof (SMM_BOOT_PERFORMANCE_TABLE) + RecordInfo.RecordSize + FIRMWARE_RECORD_BUFFER;
+ PerfId = ProgressId;
}
- //
- // Covert buffer to FPDT Ptr Union type.
- //
- FpdtRecordPtr.RecordHeader = (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER *)((UINT8*)mSmmBootPerformanceTable + mSmmBootPerformanceTable->Header.Length);
}
- FpdtRecordPtr.RecordHeader->Length = 0;
//
- // Get the TimeStamp.
+ // 2. Get the buffer to store the FPDT record.
+ //
+ Status = GetFpdtRecordPtr (FPDT_MAX_PERF_RECORD_SIZE, &FpdtRecordPtr);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // 3. Get the TimeStamp.
//
if (Ticker == 0) {
Ticker = GetPerformanceCounter ();
TimeStamp = GetTimeInNanoSecond (Ticker);
} else if (Ticker == 1) {
@@ -559,74 +586,190 @@ InsertFpdtMeasurement (
} else {
TimeStamp = GetTimeInNanoSecond (Ticker);
}
//
- // Get the ModuleName and ModuleGuid form the handle.
+ // 4. Fill in the FPDT record according to different Performance Identifier.
//
- GetModuleInfoFromHandle ((EFI_HANDLE *)Handle, ModuleName, sizeof (ModuleName), &ModuleGuid);
+ switch (PerfId) {
+ case MODULE_START_ID:
+ case MODULE_END_ID:
+ GetModuleInfoFromHandle ((EFI_HANDLE *)CallerIdentifier, ModuleName, sizeof (ModuleName), &ModuleGuid);
+ StringPtr = ModuleName;
+ //
+ // Cache the offset of start image start record and use to update the start image end record if needed.
+ //
+ if (PerfId == MODULE_START_ID && Attribute == PerfEntry) {
+ mCachedLength = mSmmBootPerformanceTable->Header.Length;
+ }
+ if (!PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {
+ FpdtRecordPtr.GuidEvent->Header.Type = FPDT_GUID_EVENT_TYPE;
+ FpdtRecordPtr.GuidEvent->Header.Length = sizeof (FPDT_GUID_EVENT_RECORD);
+ FpdtRecordPtr.GuidEvent->Header.Revision = FPDT_RECORD_REVISION_1;
+ FpdtRecordPtr.GuidEvent->ProgressID = PerfId;
+ FpdtRecordPtr.GuidEvent->Timestamp = TimeStamp;
+ CopyMem (&FpdtRecordPtr.GuidEvent->Guid, &ModuleGuid, sizeof (FpdtRecordPtr.GuidEvent->Guid));
+ if (CallerIdentifier == NULL && PerfId == MODULE_END_ID && mCachedLength != 0) {
+ CachedFpdtRecordPtr.RecordHeader = (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER *)((UINT8*)mSmmBootPerformanceTable + mCachedLength);
+ CopyMem (&FpdtRecordPtr.GuidEvent->Guid, &CachedFpdtRecordPtr.GuidEvent->Guid, sizeof (FpdtRecordPtr.GuidEvent->Guid));
+ mCachedLength = 0;
+ }
+ }
+ break;
- //
- // Fill in the record information.
- //
- switch (RecordInfo.Type) {
- case FPDT_GUID_EVENT_TYPE:
- FpdtRecordPtr.GuidEvent->Header.Type = FPDT_GUID_EVENT_TYPE;
- FpdtRecordPtr.GuidEvent->Header.Length = RecordInfo.RecordSize;
- FpdtRecordPtr.GuidEvent->Header.Revision = FPDT_RECORD_REVISION_1;
- FpdtRecordPtr.GuidEvent->ProgressID = RecordInfo.ProgressID;
- FpdtRecordPtr.GuidEvent->Timestamp = TimeStamp;
- CopyMem (&FpdtRecordPtr.GuidEvent->Guid, &ModuleGuid, sizeof (FpdtRecordPtr.GuidEvent->Guid));
+ case MODULE_LOADIMAGE_START_ID:
+ case MODULE_LOADIMAGE_END_ID:
+ GetModuleInfoFromHandle ((EFI_HANDLE *)CallerIdentifier, ModuleName, sizeof (ModuleName), &ModuleGuid);
+ StringPtr = ModuleName;
+ if (PerfId == MODULE_LOADIMAGE_START_ID) {
+ mLoadImageCount++;
+ //
+ // Cache the offset of load image start record and use to be updated by the load image end record if needed.
+ //
+ if (CallerIdentifier == NULL && Attribute == PerfEntry) {
+ mCachedLength = mSmmBootPerformanceTable->Header.Length;
+ }
+ }
+ if (!PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {
+ FpdtRecordPtr.GuidQwordEvent->Header.Type = FPDT_GUID_QWORD_EVENT_TYPE;
+ FpdtRecordPtr.GuidQwordEvent->Header.Length = sizeof (FPDT_GUID_QWORD_EVENT_RECORD);
+ FpdtRecordPtr.GuidQwordEvent->Header.Revision = FPDT_RECORD_REVISION_1;
+ FpdtRecordPtr.GuidQwordEvent->ProgressID = PerfId;
+ FpdtRecordPtr.GuidQwordEvent->Timestamp = TimeStamp;
+ FpdtRecordPtr.GuidQwordEvent->Qword = mLoadImageCount;
+ CopyMem (&FpdtRecordPtr.GuidQwordEvent->Guid, &ModuleGuid, sizeof (FpdtRecordPtr.GuidQwordEvent->Guid));
+ if (PerfId == MODULE_LOADIMAGE_END_ID && mCachedLength != 0) {
+ CachedFpdtRecordPtr.RecordHeader = (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER *)((UINT8*)mSmmBootPerformanceTable + mCachedLength);
+ CopyMem (&CachedFpdtRecordPtr.GuidQwordEvent->Guid, &ModuleGuid, sizeof (CachedFpdtRecordPtr.GuidQwordEvent->Guid));
+ mCachedLength = 0;
+ }
+ }
break;
- case FPDT_DYNAMIC_STRING_EVENT_TYPE:
- FpdtRecordPtr.DynamicStringEvent->Header.Type = FPDT_DYNAMIC_STRING_EVENT_TYPE;
- FpdtRecordPtr.DynamicStringEvent->Header.Length = RecordInfo.RecordSize;
- FpdtRecordPtr.DynamicStringEvent->Header.Revision = FPDT_RECORD_REVISION_1;
- FpdtRecordPtr.DynamicStringEvent->ProgressID = RecordInfo.ProgressID;
- FpdtRecordPtr.DynamicStringEvent->Timestamp = TimeStamp;
- CopyMem (&FpdtRecordPtr.DynamicStringEvent->Guid, &ModuleGuid, sizeof (FpdtRecordPtr.DynamicStringEvent->Guid));
+ case PERF_EVENTSIGNAL_START_ID:
+ case PERF_EVENTSIGNAL_END_ID:
+ case PERF_CALLBACK_START_ID:
+ case PERF_CALLBACK_END_ID:
+ if (String == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Cache the event guid in string event record when PcdEdkiiFpdtStringRecordEnableOnly == TRUE
+ //
+ CopyGuid (&ModuleGuid, Guid);
+ StringPtr = String;
+ if (!PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {
+ FpdtRecordPtr.DualGuidStringEvent->Header.Type = FPDT_DUAL_GUID_STRING_EVENT_TYPE;
+ FpdtRecordPtr.DualGuidStringEvent->Header.Length = sizeof (FPDT_DUAL_GUID_STRING_EVENT_RECORD);
+ FpdtRecordPtr.DualGuidStringEvent->Header.Revision = FPDT_RECORD_REVISION_1;
+ FpdtRecordPtr.DualGuidStringEvent->ProgressID = PerfId;
+ FpdtRecordPtr.DualGuidStringEvent->Timestamp = TimeStamp;
+ CopyMem (&FpdtRecordPtr.DualGuidStringEvent->Guid1, CallerIdentifier, sizeof (FpdtRecordPtr.DualGuidStringEvent->Guid1));
+ CopyMem (&FpdtRecordPtr.DualGuidStringEvent->Guid2, Guid, sizeof (FpdtRecordPtr.DualGuidStringEvent->Guid2));
+ CopyStringIntoPerfRecordAndUpdateLength (FpdtRecordPtr.DualGuidStringEvent->String, StringPtr, &FpdtRecordPtr.DualGuidStringEvent->Header.Length);
+ }
+ break;
- if (UseModuleName) {
- StringPtr = ModuleName;
- } else if (Token != NULL) {
- StringPtr = Token;
- } else if (Module != NULL) {
- StringPtr = Module;
- } else if (ModuleName != NULL) {
- StringPtr = ModuleName;
+ case PERF_EVENT_ID:
+ case PERF_FUNCTION_START_ID:
+ case PERF_FUNCTION_END_ID:
+ case PERF_INMODULE_START_ID:
+ case PERF_INMODULE_END_ID:
+ case PERF_CROSSMODULE_START_ID:
+ case PERF_CROSSMODULE_END_ID:
+ GetModuleInfoFromHandle ((EFI_HANDLE *)CallerIdentifier, ModuleName, sizeof (ModuleName), &ModuleGuid);
+ if (String != NULL) {
+ StringPtr = String;
+ } else {
+ StringPtr = ModuleName;
+ }
+ if (AsciiStrLen (StringPtr) == 0) {
+ StringPtr = "unknown name";
}
- if (StringPtr != NULL && AsciiStrLen (StringPtr) != 0) {
- StrLength = AsciiStrLen (StringPtr);
- DestMax = (RecordInfo.RecordSize - sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD)) / sizeof (CHAR8);
- if (StrLength >= DestMax) {
- StrLength = DestMax -1;
+ if (!PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {
+ FpdtRecordPtr.DynamicStringEvent->Header.Type = FPDT_DYNAMIC_STRING_EVENT_TYPE;
+ FpdtRecordPtr.DynamicStringEvent->Header.Length = sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD);
+ FpdtRecordPtr.DynamicStringEvent->Header.Revision = FPDT_RECORD_REVISION_1;
+ FpdtRecordPtr.DynamicStringEvent->ProgressID = PerfId;
+ FpdtRecordPtr.DynamicStringEvent->Timestamp = TimeStamp;
+ CopyMem (&FpdtRecordPtr.DynamicStringEvent->Guid, &ModuleGuid, sizeof (FpdtRecordPtr.DynamicStringEvent->Guid));
+ CopyStringIntoPerfRecordAndUpdateLength (FpdtRecordPtr.DynamicStringEvent->String, StringPtr, &FpdtRecordPtr.DynamicStringEvent->Header.Length);
+ }
+ break;
+
+ default:
+ if (Attribute != PerfEntry) {
+ GetModuleInfoFromHandle ((EFI_HANDLE *)CallerIdentifier, ModuleName, sizeof (ModuleName), &ModuleGuid);
+ if (String != NULL) {
+ StringPtr = String;
+ } else {
+ StringPtr = ModuleName;
+ }
+ if (AsciiStrLen (StringPtr) == 0) {
+ StringPtr = "unknown name";
+ }
+ if (!PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {
+ FpdtRecordPtr.DynamicStringEvent->Header.Type = FPDT_DYNAMIC_STRING_EVENT_TYPE;
+ FpdtRecordPtr.DynamicStringEvent->Header.Length = sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD);
+ FpdtRecordPtr.DynamicStringEvent->Header.Revision = FPDT_RECORD_REVISION_1;
+ FpdtRecordPtr.DynamicStringEvent->ProgressID = PerfId;
+ FpdtRecordPtr.DynamicStringEvent->Timestamp = TimeStamp;
+ CopyMem (&FpdtRecordPtr.DynamicStringEvent->Guid, &ModuleGuid, sizeof (FpdtRecordPtr.DynamicStringEvent->Guid));
+ CopyStringIntoPerfRecordAndUpdateLength (FpdtRecordPtr.DynamicStringEvent->String, StringPtr, &FpdtRecordPtr.DynamicStringEvent->Header.Length);
}
- AsciiStrnCpyS (FpdtRecordPtr.DynamicStringEvent->String, DestMax, StringPtr, StrLength);
} else {
- AsciiStrCpyS (FpdtRecordPtr.DynamicStringEvent->String, FPDT_STRING_EVENT_RECORD_NAME_LENGTH, "unknown name");
+ return EFI_INVALID_PARAMETER;
}
break;
+ }
- case FPDT_GUID_QWORD_EVENT_TYPE:
- FpdtRecordPtr.GuidQwordEvent->Header.Type = FPDT_GUID_QWORD_EVENT_TYPE;
- FpdtRecordPtr.GuidQwordEvent->Header.Length = RecordInfo.RecordSize;
- FpdtRecordPtr.GuidQwordEvent->Header.Revision = FPDT_RECORD_REVISION_1;
- FpdtRecordPtr.GuidQwordEvent->ProgressID = RecordInfo.ProgressID;
- FpdtRecordPtr.GuidQwordEvent->Timestamp = TimeStamp;
- CopyMem (&FpdtRecordPtr.GuidQwordEvent->Guid, &ModuleGuid, sizeof (FpdtRecordPtr.GuidQwordEvent->Guid));
- break;
+ //
+ // 4.2 When PcdEdkiiFpdtStringRecordEnableOnly==TRUE, create string record for all Perf entries.
+ //
+ if (PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {
+ if (StringPtr == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ FpdtRecordPtr.DynamicStringEvent->Header.Type = FPDT_DYNAMIC_STRING_EVENT_TYPE;
+ FpdtRecordPtr.DynamicStringEvent->Header.Length = sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD);
+ FpdtRecordPtr.DynamicStringEvent->Header.Revision = FPDT_RECORD_REVISION_1;
+ FpdtRecordPtr.DynamicStringEvent->ProgressID = PerfId;
+ FpdtRecordPtr.DynamicStringEvent->Timestamp = TimeStamp;
+ CopyMem (&FpdtRecordPtr.DynamicStringEvent->Guid, &ModuleGuid, sizeof (FpdtRecordPtr.DynamicStringEvent->Guid));
+ if (AsciiStrLen (StringPtr) == 0) {
+ StringPtr = "unknown name";
+ }
+ CopyStringIntoPerfRecordAndUpdateLength (FpdtRecordPtr.DynamicStringEvent->String, StringPtr, &FpdtRecordPtr.DynamicStringEvent->Header.Length);
- default:
- //
- // Record is not supported in current SMM phase, return EFI_UNSUPPORTED
- //
- return EFI_UNSUPPORTED;
+ if ((PerfId == MODULE_LOADIMAGE_START_ID) || (PerfId == MODULE_END_ID)) {
+ FpdtRecordPtr.DynamicStringEvent->Header.Length = (UINT8)(sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD)+ STRING_SIZE);
+ }
+ if ((PerfId == MODULE_LOADIMAGE_END_ID || PerfId == MODULE_END_ID) && mCachedLength != 0) {
+ CachedFpdtRecordPtr.RecordHeader = (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER *)((UINT8*)mSmmBootPerformanceTable + mCachedLength);
+ if (PerfId == MODULE_LOADIMAGE_END_ID) {
+ DestMax = CachedFpdtRecordPtr.DynamicStringEvent->Header.Length - sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD);
+ StringLen = AsciiStrLen (StringPtr);
+ if (StringLen >= DestMax) {
+ StringLen = DestMax -1;
+ }
+ CopyMem (&CachedFpdtRecordPtr.DynamicStringEvent->Guid, &ModuleGuid, sizeof (CachedFpdtRecordPtr.DynamicStringEvent->Guid));
+ AsciiStrnCpyS (CachedFpdtRecordPtr.DynamicStringEvent->String, DestMax, StringPtr, StringLen);
+ } else if (PerfId == MODULE_END_ID) {
+ DestMax = FpdtRecordPtr.DynamicStringEvent->Header.Length - sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD);
+ StringLen = AsciiStrLen (CachedFpdtRecordPtr.DynamicStringEvent->String);
+ if (StringLen >= DestMax) {
+ StringLen = DestMax -1;
+ }
+ CopyMem (&FpdtRecordPtr.DynamicStringEvent->Guid, &CachedFpdtRecordPtr.DynamicStringEvent->Guid, sizeof (CachedFpdtRecordPtr.DynamicStringEvent->Guid));
+ AsciiStrnCpyS (FpdtRecordPtr.DynamicStringEvent->String, DestMax, CachedFpdtRecordPtr.DynamicStringEvent->String, StringLen);
+ }
+ mCachedLength = 0;
+ }
}
//
- // Update the cached FPDT record buffer.
+ // 5. Update the length of the used buffer after fill in the record.
//
mPerformanceLength += FpdtRecordPtr.RecordHeader->Length;
mSmmBootPerformanceTable->Header.Length += FpdtRecordPtr.RecordHeader->Length;
return EFI_SUCCESS;
@@ -814,16 +957,14 @@ CreatePerformanceMeasurement(
IN PERF_MEASUREMENT_ATTRIBUTE Attribute
)
{
EFI_STATUS Status;
+ Status = EFI_SUCCESS;
+
AcquireSpinLock (&mSmmFpdtLock);
- if (Attribute == PerfStartEntry) {
- Status = InsertFpdtMeasurement (TRUE, CallerIdentifier, String, String, TimeStamp, Identifier);
- } else if (Attribute == PerfEndEntry) {
- Status = InsertFpdtMeasurement (FALSE, CallerIdentifier, String, String, TimeStamp, Identifier);
- }
+ Status = InsertFpdtRecord (CallerIdentifier, Guid, String, TimeStamp, Address, (UINT16)Identifier, Attribute);
ReleaseSpinLock (&mSmmFpdtLock);
return Status;
}
/**
@@ -1125,5 +1266,61 @@ PerformanceMeasurementEnabled (
VOID
)
{
return (BOOLEAN) ((PcdGet8(PcdPerformanceLibraryPropertyMask) & PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED) != 0);
}
+
+/**
+ Create performance record with event description and a timestamp.
+
+ @param CallerIdentifier - Image handle or pointer to caller ID GUID
+ @param Guid - Pointer to a GUID
+ @param String - Pointer to a string describing the measurement
+ @param Address - Pointer to a location in memory relevant to the measurement
+ @param Identifier - Performance identifier describing the type of measurement
+
+ @retval RETURN_SUCCESS - Successfully created performance record
+ @retval RETURN_OUT_OF_RESOURCES - Ran out of space to store the records
+ @retval RETURN_INVALID_PARAMETER - Invalid parameter passed to function - NULL
+ pointer or invalid PerfId
+
+**/
+RETURN_STATUS
+EFIAPI
+LogPerformanceMeasurement (
+ IN CONST VOID *CallerIdentifier,
+ IN CONST VOID *Guid, OPTIONAL
+ IN CONST CHAR8 *String, OPTIONAL
+ IN UINT64 Address, OPTIONAL
+ IN UINT32 Identifier
+ )
+{
+ return (RETURN_STATUS)CreatePerformanceMeasurement (CallerIdentifier, Guid, String, 0, Address, Identifier, PerfEntry);
+}
+
+/**
+ Check whether the specified performance measurement can be logged.
+
+ This function returns TRUE when the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of PcdPerformanceLibraryPropertyMask is set
+ and the Type disable bit in PcdPerformanceLibraryPropertyMask is not set.
+
+ @param Type - Type of the performance measurement entry.
+
+ @retval TRUE The performance measurement can be logged.
+ @retval FALSE The performance measurement can NOT be logged.
+
+**/
+BOOLEAN
+EFIAPI
+LogPerformanceMeasurementEnabled (
+ IN CONST UINTN Type
+ )
+{
+ //
+ // When Performance measurement is enabled and the type is not filtered, the performance can be logged.
+ //
+ if (PerformanceMeasurementEnabled () && (PcdGet8(PcdPerformanceLibraryPropertyMask) & Type) == 0) {
+ return TRUE;
+ }
+ return FALSE;
+}
+
diff --git a/MdeModulePkg/Library/SmmPerformanceLib/SmmPerformanceLib.c b/MdeModulePkg/Library/SmmPerformanceLib/SmmPerformanceLib.c
index fd820c0e49c..830037befa6 100644
--- a/MdeModulePkg/Library/SmmPerformanceLib/SmmPerformanceLib.c
+++ b/MdeModulePkg/Library/SmmPerformanceLib/SmmPerformanceLib.c
@@ -395,5 +395,73 @@ PerformanceMeasurementEnabled (
VOID
)
{
return mPerformanceMeasurementEnabled;
}
+
+/**
+ Create performance record with event description and a timestamp.
+
+ @param CallerIdentifier - Image handle or pointer to caller ID GUID
+ @param Guid - Pointer to a GUID
+ @param String - Pointer to a string describing the measurement
+ @param Address - Pointer to a location in memory relevant to the measurement
+ @param Identifier - Performance identifier describing the type of measurement
+
+ @retval RETURN_SUCCESS - Successfully created performance record
+ @retval RETURN_OUT_OF_RESOURCES - Ran out of space to store the records
+ @retval RETURN_INVALID_PARAMETER - Invalid parameter passed to function - NULL
+ pointer or invalid PerfId
+
+**/
+RETURN_STATUS
+EFIAPI
+LogPerformanceMeasurement (
+ IN CONST VOID *CallerIdentifier,
+ IN CONST VOID *Guid, OPTIONAL
+ IN CONST CHAR8 *String, OPTIONAL
+ IN UINT64 Address, OPTIONAL
+ IN UINT32 Identifier
+ )
+{
+ EFI_STATUS Status;
+
+ Status = GetPerformanceMeasurementProtocol ();
+ if (EFI_ERROR (Status)) {
+ return RETURN_OUT_OF_RESOURCES;
+ }
+
+ if (mPerformanceMeasurement != NULL) {
+ Status = mPerformanceMeasurement->CreatePerformanceMeasurement (CallerIdentifier, Guid, String, 0, Address, Identifier, PerfEntry);
+ } else {
+ ASSERT (FALSE);
+ }
+
+ return (RETURN_STATUS) Status;
+}
+
+/**
+ Check whether the specified performance measurement can be logged.
+
+ This function returns TRUE when the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of PcdPerformanceLibraryPropertyMask is set
+ and the Type disable bit in PcdPerformanceLibraryPropertyMask is not set.
+
+ @param Type - Type of the performance measurement entry.
+
+ @retval TRUE The performance measurement can be logged.
+ @retval FALSE The performance measurement can NOT be logged.
+
+**/
+BOOLEAN
+EFIAPI
+LogPerformanceMeasurementEnabled (
+ IN CONST UINTN Type
+ )
+{
+ //
+ // When Performance measurement is enabled and the type is not filtered, the performance can be logged.
+ //
+ if (PerformanceMeasurementEnabled () && (PcdGet8(PcdPerformanceLibraryPropertyMask) & Type) == 0) {
+ return TRUE;
+ }
+ return FALSE;
+}
--
2.14.3.windows.1
next prev parent reply other threads:[~2018-06-22 8:56 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-06-22 8:56 [patch V2 0/9] Add new Perf macros Dandan Bi
2018-06-22 8:56 ` [patch V2 1/9] MdeModulePkg: Add PERFORMANCE_MEASUREMENT_PROTOCOL Dandan Bi
2018-06-22 8:56 ` [patch V2 2/9] MdeModulePkg: Update Performance instances to use new protocol Dandan Bi
2018-06-22 8:56 ` [patch V2 3/9] MdePkg/PerformanceLib.h: Add new Perf macros Dandan Bi
2018-06-22 8:56 ` [patch V2 4/9] MdeModulePkg/ExtendedFirmwarePerf: Remove PerfId definitions Dandan Bi
2018-06-22 8:56 ` Dandan Bi [this message]
2018-06-22 8:56 ` [patch V2 6/9] ShellPkg/dp: Update dp tool to parse new Perf record Dandan Bi
2018-06-22 8:56 ` [patch V2 7/9] MdeModulePkg: Use new added Perf macros Dandan Bi
2018-06-22 8:56 ` [patch V2 8/9] SecurityPkg: " Dandan Bi
2018-07-03 23:29 ` Zhang, Chao B
2018-06-22 8:56 ` [patch V2 9/9] UefiCpuPkg: " Dandan Bi
2018-06-25 8:02 ` [patch V2 0/9] Add new " Gao, Liming
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20180622085623.154924-6-dandan.bi@intel.com \
--to=devel@edk2.groups.io \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox