SmmPerformanceHandlerEx(), SmmPerformanceHandler() will receive untrusted input and do basic validation.\r
\r
Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>\r
-This program and the accompanying materials\r
-are licensed and made available under the terms and conditions of the BSD License\r
-which accompanies this distribution. The full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
**/\r
\r
HANDLE_GUID_MAP mCacheHandleGuidTable[CACHE_HANDLE_GUID_COUNT];\r
UINTN mCachePairCount = 0;\r
\r
-UINT32 mPerformanceLength = 0;\r
+UINT32 mPerformanceLength = sizeof (SMM_BOOT_PERFORMANCE_TABLE);\r
UINT32 mMaxPerformanceLength = 0;\r
+UINT32 mLoadImageCount = 0;\r
BOOLEAN mFpdtDataIsReported = FALSE;\r
BOOLEAN mLackSpaceIsReport = FALSE;\r
CHAR8 *mPlatformLanguage = NULL;\r
SPIN_LOCK mSmmFpdtLock;\r
PERFORMANCE_PROPERTY mPerformanceProperty;\r
+UINT32 mCachedLength = 0;\r
\r
//\r
-// Interfaces for SMM Performance Protocol.\r
+// Interfaces for SMM PerformanceMeasurement Protocol.\r
//\r
-PERFORMANCE_PROTOCOL mPerformanceInterface = {\r
- StartGauge,\r
- EndGauge,\r
- GetGauge\r
+EDKII_PERFORMANCE_MEASUREMENT_PROTOCOL mPerformanceMeasurementInterface = {\r
+ CreatePerformanceMeasurement,\r
};\r
\r
-//\r
-// Interfaces for SMM PerformanceEx Protocol.\r
-//\r
-PERFORMANCE_EX_PROTOCOL mPerformanceExInterface = {\r
- StartGaugeEx,\r
- EndGaugeEx,\r
- GetGaugeEx\r
-};\r
+/**\r
+ Return the pointer to the FPDT record in the allocated memory.\r
+\r
+ @param RecordSize The size of FPDT record.\r
+ @param FpdtRecordPtr Pointer the FPDT record in the allocated memory.\r
+\r
+ @retval EFI_SUCCESS Successfully get the pointer to the FPDT record.\r
+ @retval EFI_OUT_OF_RESOURCES Ran out of space to store the records.\r
+**/\r
+EFI_STATUS\r
+GetFpdtRecordPtr (\r
+ IN UINT8 RecordSize,\r
+ IN OUT FPDT_RECORD_PTR *FpdtRecordPtr\r
+)\r
+{\r
+ if (mFpdtDataIsReported) {\r
+ //\r
+ // Append Boot records after Smm boot performance records have been reported.\r
+ //\r
+ if (mPerformanceLength + RecordSize > mMaxPerformanceLength) {\r
+ if (!mLackSpaceIsReport) {\r
+ DEBUG ((DEBUG_INFO, "SmmCorePerformanceLib: No enough space to save boot records\n"));\r
+ mLackSpaceIsReport = TRUE;\r
+ }\r
+ return EFI_OUT_OF_RESOURCES;\r
+ } else {\r
+ //\r
+ // Covert buffer to FPDT Ptr Union type.\r
+ //\r
+ FpdtRecordPtr->RecordHeader = (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER *)((UINT8*)mSmmBootPerformanceTable + mSmmBootPerformanceTable->Header.Length);\r
+ }\r
+ } else {\r
+ //\r
+ // Check if pre-allocated buffer is full\r
+ //\r
+ if (mPerformanceLength + RecordSize > mMaxPerformanceLength) {\r
+ mSmmBootPerformanceTable = ReallocatePool (\r
+ mPerformanceLength,\r
+ mPerformanceLength + RecordSize + FIRMWARE_RECORD_BUFFER,\r
+ mSmmBootPerformanceTable\r
+ );\r
+\r
+ if (mSmmBootPerformanceTable == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ mSmmBootPerformanceTable->Header.Length = mPerformanceLength;\r
+ mMaxPerformanceLength = mPerformanceLength + RecordSize + FIRMWARE_RECORD_BUFFER;\r
+ }\r
+ //\r
+ // Covert buffer to FPDT Ptr Union type.\r
+ //\r
+ FpdtRecordPtr->RecordHeader = (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER *)((UINT8*)mSmmBootPerformanceTable + mSmmBootPerformanceTable->Header.Length);\r
+ }\r
+ FpdtRecordPtr->RecordHeader->Length = 0;\r
+ return EFI_SUCCESS;\r
+}\r
+\r
\r
/**\r
Check whether the Token is a known one which is uesed by core.\r
}\r
\r
/**\r
- Get the FPDT record info.\r
+ Get the FPDT record identifier.\r
\r
- @param IsStart TRUE if the performance log is start log.\r
- @param Handle Pointer to environment specific context used\r
- to identify the component being measured.\r
- @param Token Pointer to a Null-terminated ASCII string\r
- that identifies the component being measured.\r
- @param Module Pointer to a Null-terminated ASCII string\r
- that identifies the module being measured.\r
- @param RecordInfo On return, pointer to the info of the record.\r
- @param UseModuleName Only useful for FPDT_DYNAMIC_STRING_EVENT_TYPE, indicate that whether need use\r
- Module name to fill the string field in the FPDT_DYNAMIC_STRING_EVENT_RECORD.\r
+ @param Attribute The attribute of the Record.\r
+ PerfStartEntry: Start Record.\r
+ PerfEndEntry: End Record.\r
+ @param Handle Pointer to environment specific context used to identify the component being measured.\r
+ @param String Pointer to a Null-terminated ASCII string that identifies the component being measured.\r
+ @param ProgressID On return, pointer to the ProgressID.\r
\r
- @retval EFI_SUCCESS Get record info successfully.\r
- @retval EFI_UNSUPPORTED No matched FPDT record.\r
+ @retval EFI_SUCCESS Get record info successfully.\r
+ @retval EFI_INVALID_PARAMETER No matched FPDT record.\r
\r
**/\r
EFI_STATUS\r
-GetFpdtRecordInfo (\r
- IN BOOLEAN IsStart,\r
- IN CONST VOID *Handle,\r
- IN CONST CHAR8 *Token,\r
- IN CONST CHAR8 *Module,\r
- OUT FPDT_BASIC_RECORD_INFO *RecordInfo,\r
- IN OUT BOOLEAN *UseModuleName\r
+GetFpdtRecordId (\r
+ IN PERF_MEASUREMENT_ATTRIBUTE Attribute,\r
+ IN CONST VOID *Handle,\r
+ IN CONST CHAR8 *String,\r
+ OUT UINT16 *ProgressID\r
)\r
{\r
- UINT16 RecordType;\r
- UINTN StringSize;\r
-\r
- RecordType = FPDT_DYNAMIC_STRING_EVENT_TYPE;\r
-\r
//\r
- // Token to Type and Id.\r
+ // Token to Id.\r
//\r
- if (Token != NULL) {\r
- if (AsciiStrCmp (Token, START_IMAGE_TOK) == 0) { // "StartImage:"\r
- *UseModuleName = TRUE;\r
- RecordType = FPDT_GUID_EVENT_TYPE;\r
- if (IsStart) {\r
- RecordInfo->ProgressID = MODULE_START_ID;\r
+ if (String != NULL) {\r
+ if (AsciiStrCmp (String, START_IMAGE_TOK) == 0) { // "StartImage:"\r
+ if (Attribute == PerfStartEntry) {\r
+ *ProgressID = MODULE_START_ID;\r
} else {\r
- RecordInfo->ProgressID = MODULE_END_ID;\r
+ *ProgressID = MODULE_END_ID;\r
}\r
- } else if (AsciiStrCmp (Token, LOAD_IMAGE_TOK) == 0) { // "LoadImage:"\r
- *UseModuleName = TRUE;\r
- RecordType = FPDT_GUID_QWORD_EVENT_TYPE;\r
- if (IsStart) {\r
- RecordInfo->ProgressID = MODULE_LOADIMAGE_START_ID;\r
+ } else if (AsciiStrCmp (String, LOAD_IMAGE_TOK) == 0) { // "LoadImage:"\r
+ if (Attribute == PerfStartEntry) {\r
+ *ProgressID = MODULE_LOADIMAGE_START_ID;\r
} else {\r
- RecordInfo->ProgressID = MODULE_LOADIMAGE_END_ID;\r
+ *ProgressID = MODULE_LOADIMAGE_END_ID;\r
}\r
} else { // Pref used in Modules\r
- if (IsStart) {\r
- RecordInfo->ProgressID = PERF_INMODULE_START_ID;\r
+ if (Attribute == PerfStartEntry) {\r
+ *ProgressID = PERF_INMODULE_START_ID;\r
} else {\r
- RecordInfo->ProgressID = PERF_INMODULE_END_ID;\r
+ *ProgressID = PERF_INMODULE_END_ID;\r
}\r
}\r
- } else if (Handle != NULL || Module != NULL) { // Pref used in Modules\r
- if (IsStart) {\r
- RecordInfo->ProgressID = PERF_INMODULE_START_ID;\r
+ } else if (Handle != NULL) { // Pref used in Modules\r
+ if (Attribute == PerfStartEntry) {\r
+ *ProgressID = PERF_INMODULE_START_ID;\r
} else {\r
- RecordInfo->ProgressID = PERF_INMODULE_END_ID;\r
+ *ProgressID = PERF_INMODULE_END_ID;\r
}\r
} else {\r
return EFI_UNSUPPORTED;\r
}\r
-\r
- if (PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {\r
- RecordType = FPDT_DYNAMIC_STRING_EVENT_TYPE;\r
- RecordInfo->RecordSize = sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD) + STRING_SIZE;\r
- } else {\r
- switch (RecordType) {\r
- case FPDT_GUID_EVENT_TYPE:\r
- RecordInfo->RecordSize = sizeof (FPDT_GUID_EVENT_RECORD);\r
- break;\r
-\r
- case FPDT_DYNAMIC_STRING_EVENT_TYPE:\r
- if (*UseModuleName) {\r
- StringSize = STRING_SIZE;\r
- } else if (Token != NULL) {\r
- StringSize = AsciiStrSize (Token);\r
- } else if (Module != NULL) {\r
- StringSize = AsciiStrSize (Module);\r
- } else {\r
- StringSize = STRING_SIZE;\r
- }\r
- if (StringSize > STRING_SIZE) {\r
- StringSize = STRING_SIZE;\r
- }\r
- RecordInfo->RecordSize = (UINT8)(sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD) + StringSize);\r
- break;\r
-\r
- case FPDT_GUID_QWORD_EVENT_TYPE:\r
- RecordInfo->RecordSize = (UINT8)sizeof (FPDT_GUID_QWORD_EVENT_RECORD);\r
- break;\r
-\r
- default:\r
- //\r
- // Record type is unsupported in SMM phase.\r
- //\r
- return EFI_UNSUPPORTED;\r
- }\r
- }\r
-\r
- RecordInfo->Type = RecordType;\r
return EFI_SUCCESS;\r
}\r
\r
}\r
\r
/**\r
- Add performance log to FPDT boot record table.\r
+ Copies the string from Source into Destination and updates Length with the\r
+ size of the string.\r
\r
- @param IsStart TRUE if the performance log is start log.\r
- @param Handle Pointer to environment specific context used\r
- to identify the component being measured.\r
- @param Token Pointer to a Null-terminated ASCII string\r
- that identifies the component being measured.\r
- @param Module Pointer to a Null-terminated ASCII string\r
- that identifies the module being measured.\r
- @param Ticker 64-bit time stamp.\r
- @param Identifier 32-bit identifier. If the value is 0, the created record\r
- is same as the one created by StartGauge of PERFORMANCE_PROTOCOL.\r
+ @param Destination - destination of the string copy\r
+ @param Source - pointer to the source string which will get copied\r
+ @param Length - pointer to a length variable to be updated\r
\r
- @retval EFI_SUCCESS Add FPDT boot record.\r
- @retval EFI_OUT_OF_RESOURCES There are not enough resources to record the measurement.\r
- @retval EFI_UNSUPPORTED No matched FPDT record.\r
+**/\r
+VOID\r
+CopyStringIntoPerfRecordAndUpdateLength (\r
+ IN OUT CHAR8 *Destination,\r
+ IN CONST CHAR8 *Source,\r
+ IN OUT UINT8 *Length\r
+ )\r
+{\r
+ UINTN StringLen;\r
+ UINTN DestMax;\r
+\r
+ ASSERT (Source != NULL);\r
+\r
+ if (PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {\r
+ DestMax = STRING_SIZE;\r
+ } else {\r
+ DestMax = AsciiStrSize (Source);\r
+ if (DestMax > STRING_SIZE) {\r
+ DestMax = STRING_SIZE;\r
+ }\r
+ }\r
+ StringLen = AsciiStrLen (Source);\r
+ if (StringLen >= DestMax) {\r
+ StringLen = DestMax -1;\r
+ }\r
+\r
+ AsciiStrnCpyS(Destination, DestMax, Source, StringLen);\r
+ *Length += (UINT8)DestMax;\r
+\r
+ return;\r
+}\r
+\r
+/**\r
+ Create performance record with event description and a timestamp.\r
+\r
+ @param CallerIdentifier - Image handle or pointer to caller ID GUID.\r
+ @param Guid - Pointer to a GUID.\r
+ @param String - Pointer to a string describing the measurement.\r
+ @param Ticker - 64-bit time stamp.\r
+ @param Address - Pointer to a location in memory relevant to the measurement.\r
+ @param PerfId - Performance identifier describing the type of measurement.\r
+ @param Attribute - The attribute of the measurement. According to attribute can create a start\r
+ record for PERF_START/PERF_START_EX, or a end record for PERF_END/PERF_END_EX,\r
+ or a general record for other Perf macros.\r
+\r
+ @retval EFI_SUCCESS - Successfully created performance record.\r
+ @retval EFI_OUT_OF_RESOURCES - Ran out of space to store the records.\r
+ @retval EFI_INVALID_PARAMETER - Invalid parameter passed to function - NULL\r
+ pointer or invalid PerfId.\r
+\r
+ @retval EFI_SUCCESS - Successfully created performance record\r
+ @retval EFI_OUT_OF_RESOURCES - Ran out of space to store the records\r
+ @retval EFI_INVALID_PARAMETER - Invalid parameter passed to function - NULL\r
+ pointer or invalid PerfId\r
\r
**/\r
EFI_STATUS\r
-InsertFpdtMeasurement (\r
- IN BOOLEAN IsStart,\r
- IN CONST VOID *Handle, OPTIONAL\r
- IN CONST CHAR8 *Token, OPTIONAL\r
- IN CONST CHAR8 *Module, OPTIONAL\r
- IN UINT64 Ticker,\r
- IN UINT32 Identifier\r
+InsertFpdtRecord (\r
+ IN CONST VOID *CallerIdentifier, OPTIONAL\r
+ IN CONST VOID *Guid, OPTIONAL\r
+ IN CONST CHAR8 *String, OPTIONAL\r
+ IN UINT64 Ticker,\r
+ IN UINT64 Address, OPTIONAL\r
+ IN UINT16 PerfId,\r
+ IN PERF_MEASUREMENT_ATTRIBUTE Attribute\r
)\r
+\r
{\r
+ EFI_STATUS Status;\r
EFI_GUID ModuleGuid;\r
CHAR8 ModuleName[FPDT_STRING_EVENT_RECORD_NAME_LENGTH];\r
- EFI_STATUS Status;\r
FPDT_RECORD_PTR FpdtRecordPtr;\r
+ FPDT_RECORD_PTR CachedFpdtRecordPtr;\r
UINT64 TimeStamp;\r
- FPDT_BASIC_RECORD_INFO RecordInfo;\r
- UINTN DestMax;\r
- UINTN StrLength;\r
CONST CHAR8 *StringPtr;\r
- BOOLEAN UseModuleName;\r
+ UINTN DestMax;\r
+ UINTN StringLen;\r
+ UINT16 ProgressId;\r
\r
StringPtr = NULL;\r
- UseModuleName = FALSE;\r
ZeroMem (ModuleName, sizeof (ModuleName));\r
\r
//\r
- // Get record info includes type, size, ProgressID.\r
+ // 1. Get the Perf Id for records from PERF_START/PERF_END, PERF_START_EX/PERF_END_EX.\r
+ // notes: For other Perf macros (Attribute == PerfEntry), their Id is known.\r
//\r
- Status = GetFpdtRecordInfo (IsStart, Handle, Token, Module, &RecordInfo, &UseModuleName);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- //\r
- // If PERF_START()/PERF_END() have specified the ProgressID,it has high priority.\r
- // !!! Note: If the Perf is not the known Token used in the core but have same\r
- // ID with the core Token, this case will not be supported.\r
- // And in currtnt usage mode, for the unkown ID, there is a general rule:\r
- // If it is start pref: the lower 4 bits of the ID should be 0.\r
- // If it is end pref: the lower 4 bits of the ID should not be 0.\r
- // If input ID doesn't follow the rule, we will adjust it.\r
- //\r
- if ((Identifier != 0) && (IsKnownID (Identifier)) && (!IsKnownTokens (Token))) {\r
- return EFI_UNSUPPORTED;\r
- } else if ((Identifier != 0) && (!IsKnownID (Identifier)) && (!IsKnownTokens (Token))) {\r
- if (IsStart && ((Identifier & 0x000F) != 0)) {\r
- Identifier &= 0xFFF0;\r
- } else if ((!IsStart) && ((Identifier & 0x000F) == 0)) {\r
- Identifier += 1;\r
- }\r
- RecordInfo.ProgressID = (UINT16)Identifier;\r
- }\r
-\r
- if (mFpdtDataIsReported) {\r
+ if (Attribute != PerfEntry) {\r
//\r
- // Append Boot records after Smm boot performance records have been reported.\r
+ // If PERF_START_EX()/PERF_END_EX() have specified the ProgressID,it has high priority.\r
+ // !!! Note: If the Perf is not the known Token used in the core but have same\r
+ // ID with the core Token, this case will not be supported.\r
+ // And in currtnt usage mode, for the unkown ID, there is a general rule:\r
+ // If it is start pref: the lower 4 bits of the ID should be 0.\r
+ // If it is end pref: the lower 4 bits of the ID should not be 0.\r
+ // If input ID doesn't follow the rule, we will adjust it.\r
//\r
- if (mPerformanceLength + RecordInfo.RecordSize > mMaxPerformanceLength) {\r
- if (!mLackSpaceIsReport) {\r
- DEBUG ((DEBUG_INFO, "SmmCorePerformanceLib: No enough space to save boot records\n"));\r
- mLackSpaceIsReport = TRUE;\r
+ if ((PerfId != 0) && (IsKnownID (PerfId)) && (!IsKnownTokens (String))) {\r
+ return EFI_INVALID_PARAMETER;\r
+ } else if ((PerfId != 0) && (!IsKnownID (PerfId)) && (!IsKnownTokens (String))) {\r
+ if ((Attribute == PerfStartEntry) && ((PerfId & 0x000F) != 0)) {\r
+ PerfId &= 0xFFF0;\r
+ } else if ((Attribute == PerfEndEntry) && ((PerfId & 0x000F) == 0)) {\r
+ PerfId += 1;\r
}\r
- return EFI_OUT_OF_RESOURCES;\r
- } else {\r
+ }\r
+ if (PerfId == 0) {\r
//\r
- // Covert buffer to FPDT Ptr Union type.\r
+ // Get ProgressID form the String Token.\r
//\r
- FpdtRecordPtr.RecordHeader = (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER *)((UINT8*)mSmmBootPerformanceTable + mSmmBootPerformanceTable->Header.Length);\r
- }\r
- } else {\r
- //\r
- // Check if pre-allocated buffer is full\r
- //\r
- if (mPerformanceLength + RecordInfo.RecordSize > mMaxPerformanceLength) {\r
- mSmmBootPerformanceTable = ReallocatePool (\r
- mPerformanceLength,\r
- mPerformanceLength + sizeof (SMM_BOOT_PERFORMANCE_TABLE) + RecordInfo.RecordSize + FIRMWARE_RECORD_BUFFER,\r
- mSmmBootPerformanceTable\r
- );\r
-\r
- if (mSmmBootPerformanceTable == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
+ Status = GetFpdtRecordId (Attribute, CallerIdentifier, String, &ProgressId);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
}\r
- mSmmBootPerformanceTable->Header.Length = sizeof (SMM_BOOT_PERFORMANCE_TABLE) + mPerformanceLength;\r
- mMaxPerformanceLength = mPerformanceLength + sizeof (SMM_BOOT_PERFORMANCE_TABLE) + RecordInfo.RecordSize + FIRMWARE_RECORD_BUFFER;\r
+ PerfId = ProgressId;\r
}\r
- //\r
- // Covert buffer to FPDT Ptr Union type.\r
- //\r
- FpdtRecordPtr.RecordHeader = (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER *)((UINT8*)mSmmBootPerformanceTable + mSmmBootPerformanceTable->Header.Length);\r
}\r
- FpdtRecordPtr.RecordHeader->Length = 0;\r
\r
//\r
- // Get the TimeStamp.\r
+ // 2. Get the buffer to store the FPDT record.\r
+ //\r
+ Status = GetFpdtRecordPtr (FPDT_MAX_PERF_RECORD_SIZE, &FpdtRecordPtr);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // 3. Get the TimeStamp.\r
//\r
if (Ticker == 0) {\r
Ticker = GetPerformanceCounter ();\r
}\r
\r
//\r
- // Get the ModuleName and ModuleGuid form the handle.\r
- //\r
- GetModuleInfoFromHandle ((EFI_HANDLE *)Handle, ModuleName, sizeof (ModuleName), &ModuleGuid);\r
-\r
+ // 4. Fill in the FPDT record according to different Performance Identifier.\r
//\r
- // Fill in the record information.\r
- //\r
- switch (RecordInfo.Type) {\r
- case FPDT_GUID_EVENT_TYPE:\r
- FpdtRecordPtr.GuidEvent->Header.Type = FPDT_GUID_EVENT_TYPE;\r
- FpdtRecordPtr.GuidEvent->Header.Length = RecordInfo.RecordSize;\r
- FpdtRecordPtr.GuidEvent->Header.Revision = FPDT_RECORD_REVISION_1;\r
- FpdtRecordPtr.GuidEvent->ProgressID = RecordInfo.ProgressID;\r
- FpdtRecordPtr.GuidEvent->Timestamp = TimeStamp;\r
- CopyMem (&FpdtRecordPtr.GuidEvent->Guid, &ModuleGuid, sizeof (FpdtRecordPtr.GuidEvent->Guid));\r
+ switch (PerfId) {\r
+ case MODULE_START_ID:\r
+ case MODULE_END_ID:\r
+ GetModuleInfoFromHandle ((EFI_HANDLE)CallerIdentifier, ModuleName, sizeof (ModuleName), &ModuleGuid);\r
+ StringPtr = ModuleName;\r
+ //\r
+ // Cache the offset of start image start record and use to update the start image end record if needed.\r
+ //\r
+ if (PerfId == MODULE_START_ID && Attribute == PerfEntry) {\r
+ mCachedLength = mSmmBootPerformanceTable->Header.Length;\r
+ }\r
+ if (!PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {\r
+ FpdtRecordPtr.GuidEvent->Header.Type = FPDT_GUID_EVENT_TYPE;\r
+ FpdtRecordPtr.GuidEvent->Header.Length = sizeof (FPDT_GUID_EVENT_RECORD);\r
+ FpdtRecordPtr.GuidEvent->Header.Revision = FPDT_RECORD_REVISION_1;\r
+ FpdtRecordPtr.GuidEvent->ProgressID = PerfId;\r
+ FpdtRecordPtr.GuidEvent->Timestamp = TimeStamp;\r
+ CopyMem (&FpdtRecordPtr.GuidEvent->Guid, &ModuleGuid, sizeof (FpdtRecordPtr.GuidEvent->Guid));\r
+ if (CallerIdentifier == NULL && PerfId == MODULE_END_ID && mCachedLength != 0) {\r
+ CachedFpdtRecordPtr.RecordHeader = (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER *)((UINT8*)mSmmBootPerformanceTable + mCachedLength);\r
+ CopyMem (&FpdtRecordPtr.GuidEvent->Guid, &CachedFpdtRecordPtr.GuidEvent->Guid, sizeof (FpdtRecordPtr.GuidEvent->Guid));\r
+ mCachedLength = 0;\r
+ }\r
+ }\r
break;\r
\r
- case FPDT_DYNAMIC_STRING_EVENT_TYPE:\r
- FpdtRecordPtr.DynamicStringEvent->Header.Type = FPDT_DYNAMIC_STRING_EVENT_TYPE;\r
- FpdtRecordPtr.DynamicStringEvent->Header.Length = RecordInfo.RecordSize;\r
- FpdtRecordPtr.DynamicStringEvent->Header.Revision = FPDT_RECORD_REVISION_1;\r
- FpdtRecordPtr.DynamicStringEvent->ProgressID = RecordInfo.ProgressID;\r
- FpdtRecordPtr.DynamicStringEvent->Timestamp = TimeStamp;\r
- CopyMem (&FpdtRecordPtr.DynamicStringEvent->Guid, &ModuleGuid, sizeof (FpdtRecordPtr.DynamicStringEvent->Guid));\r
-\r
- if (UseModuleName) {\r
- StringPtr = ModuleName;\r
- } else if (Token != NULL) {\r
- StringPtr = Token;\r
- } else if (Module != NULL) {\r
- StringPtr = Module;\r
- } else if (ModuleName != NULL) {\r
- StringPtr = ModuleName;\r
+ case MODULE_LOADIMAGE_START_ID:\r
+ case MODULE_LOADIMAGE_END_ID:\r
+ GetModuleInfoFromHandle ((EFI_HANDLE)CallerIdentifier, ModuleName, sizeof (ModuleName), &ModuleGuid);\r
+ StringPtr = ModuleName;\r
+ if (PerfId == MODULE_LOADIMAGE_START_ID) {\r
+ mLoadImageCount++;\r
+ //\r
+ // Cache the offset of load image start record and use to be updated by the load image end record if needed.\r
+ //\r
+ if (CallerIdentifier == NULL && Attribute == PerfEntry) {\r
+ mCachedLength = mSmmBootPerformanceTable->Header.Length;\r
+ }\r
}\r
- if (StringPtr != NULL && AsciiStrLen (StringPtr) != 0) {\r
- StrLength = AsciiStrLen (StringPtr);\r
- DestMax = (RecordInfo.RecordSize - sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD)) / sizeof (CHAR8);\r
- if (StrLength >= DestMax) {\r
- StrLength = DestMax -1;\r
+ if (!PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {\r
+ FpdtRecordPtr.GuidQwordEvent->Header.Type = FPDT_GUID_QWORD_EVENT_TYPE;\r
+ FpdtRecordPtr.GuidQwordEvent->Header.Length = sizeof (FPDT_GUID_QWORD_EVENT_RECORD);\r
+ FpdtRecordPtr.GuidQwordEvent->Header.Revision = FPDT_RECORD_REVISION_1;\r
+ FpdtRecordPtr.GuidQwordEvent->ProgressID = PerfId;\r
+ FpdtRecordPtr.GuidQwordEvent->Timestamp = TimeStamp;\r
+ FpdtRecordPtr.GuidQwordEvent->Qword = mLoadImageCount;\r
+ CopyMem (&FpdtRecordPtr.GuidQwordEvent->Guid, &ModuleGuid, sizeof (FpdtRecordPtr.GuidQwordEvent->Guid));\r
+ if (PerfId == MODULE_LOADIMAGE_END_ID && mCachedLength != 0) {\r
+ CachedFpdtRecordPtr.RecordHeader = (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER *)((UINT8*)mSmmBootPerformanceTable + mCachedLength);\r
+ CopyMem (&CachedFpdtRecordPtr.GuidQwordEvent->Guid, &ModuleGuid, sizeof (CachedFpdtRecordPtr.GuidQwordEvent->Guid));\r
+ mCachedLength = 0;\r
}\r
- AsciiStrnCpyS (FpdtRecordPtr.DynamicStringEvent->String, DestMax, StringPtr, StrLength);\r
- } else {\r
- AsciiStrCpyS (FpdtRecordPtr.DynamicStringEvent->String, FPDT_STRING_EVENT_RECORD_NAME_LENGTH, "unknown name");\r
}\r
break;\r
\r
- case FPDT_GUID_QWORD_EVENT_TYPE:\r
- FpdtRecordPtr.GuidQwordEvent->Header.Type = FPDT_GUID_QWORD_EVENT_TYPE;\r
- FpdtRecordPtr.GuidQwordEvent->Header.Length = RecordInfo.RecordSize;\r
- FpdtRecordPtr.GuidQwordEvent->Header.Revision = FPDT_RECORD_REVISION_1;\r
- FpdtRecordPtr.GuidQwordEvent->ProgressID = RecordInfo.ProgressID;\r
- FpdtRecordPtr.GuidQwordEvent->Timestamp = TimeStamp;\r
- CopyMem (&FpdtRecordPtr.GuidQwordEvent->Guid, &ModuleGuid, sizeof (FpdtRecordPtr.GuidQwordEvent->Guid));\r
+ case PERF_EVENTSIGNAL_START_ID:\r
+ case PERF_EVENTSIGNAL_END_ID:\r
+ case PERF_CALLBACK_START_ID:\r
+ case PERF_CALLBACK_END_ID:\r
+ if (String == NULL || Guid == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ StringPtr = String;\r
+ if (AsciiStrLen (String) == 0) {\r
+ StringPtr = "unknown name";\r
+ }\r
+ if (!PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {\r
+ FpdtRecordPtr.DualGuidStringEvent->Header.Type = FPDT_DUAL_GUID_STRING_EVENT_TYPE;\r
+ FpdtRecordPtr.DualGuidStringEvent->Header.Length = sizeof (FPDT_DUAL_GUID_STRING_EVENT_RECORD);\r
+ FpdtRecordPtr.DualGuidStringEvent->Header.Revision = FPDT_RECORD_REVISION_1;\r
+ FpdtRecordPtr.DualGuidStringEvent->ProgressID = PerfId;\r
+ FpdtRecordPtr.DualGuidStringEvent->Timestamp = TimeStamp;\r
+ CopyMem (&FpdtRecordPtr.DualGuidStringEvent->Guid1, CallerIdentifier, sizeof (FpdtRecordPtr.DualGuidStringEvent->Guid1));\r
+ CopyMem (&FpdtRecordPtr.DualGuidStringEvent->Guid2, Guid, sizeof (FpdtRecordPtr.DualGuidStringEvent->Guid2));\r
+ CopyStringIntoPerfRecordAndUpdateLength (FpdtRecordPtr.DualGuidStringEvent->String, StringPtr, &FpdtRecordPtr.DualGuidStringEvent->Header.Length);\r
+ }\r
+ break;\r
+\r
+ case PERF_EVENT_ID:\r
+ case PERF_FUNCTION_START_ID:\r
+ case PERF_FUNCTION_END_ID:\r
+ case PERF_INMODULE_START_ID:\r
+ case PERF_INMODULE_END_ID:\r
+ case PERF_CROSSMODULE_START_ID:\r
+ case PERF_CROSSMODULE_END_ID:\r
+ GetModuleInfoFromHandle ((EFI_HANDLE)CallerIdentifier, ModuleName, sizeof (ModuleName), &ModuleGuid);\r
+ if (String != NULL) {\r
+ StringPtr = String;\r
+ } else {\r
+ StringPtr = ModuleName;\r
+ }\r
+ if (AsciiStrLen (StringPtr) == 0) {\r
+ StringPtr = "unknown name";\r
+ }\r
+ if (!PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {\r
+ FpdtRecordPtr.DynamicStringEvent->Header.Type = FPDT_DYNAMIC_STRING_EVENT_TYPE;\r
+ FpdtRecordPtr.DynamicStringEvent->Header.Length = sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD);\r
+ FpdtRecordPtr.DynamicStringEvent->Header.Revision = FPDT_RECORD_REVISION_1;\r
+ FpdtRecordPtr.DynamicStringEvent->ProgressID = PerfId;\r
+ FpdtRecordPtr.DynamicStringEvent->Timestamp = TimeStamp;\r
+ CopyMem (&FpdtRecordPtr.DynamicStringEvent->Guid, &ModuleGuid, sizeof (FpdtRecordPtr.DynamicStringEvent->Guid));\r
+ CopyStringIntoPerfRecordAndUpdateLength (FpdtRecordPtr.DynamicStringEvent->String, StringPtr, &FpdtRecordPtr.DynamicStringEvent->Header.Length);\r
+ }\r
break;\r
\r
default:\r
- //\r
- // Record is not supported in current SMM phase, return EFI_UNSUPPORTED\r
- //\r
- return EFI_UNSUPPORTED;\r
+ if (Attribute != PerfEntry) {\r
+ GetModuleInfoFromHandle ((EFI_HANDLE)CallerIdentifier, ModuleName, sizeof (ModuleName), &ModuleGuid);\r
+ if (String != NULL) {\r
+ StringPtr = String;\r
+ } else {\r
+ StringPtr = ModuleName;\r
+ }\r
+ if (AsciiStrLen (StringPtr) == 0) {\r
+ StringPtr = "unknown name";\r
+ }\r
+ if (!PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {\r
+ FpdtRecordPtr.DynamicStringEvent->Header.Type = FPDT_DYNAMIC_STRING_EVENT_TYPE;\r
+ FpdtRecordPtr.DynamicStringEvent->Header.Length = sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD);\r
+ FpdtRecordPtr.DynamicStringEvent->Header.Revision = FPDT_RECORD_REVISION_1;\r
+ FpdtRecordPtr.DynamicStringEvent->ProgressID = PerfId;\r
+ FpdtRecordPtr.DynamicStringEvent->Timestamp = TimeStamp;\r
+ CopyMem (&FpdtRecordPtr.DynamicStringEvent->Guid, &ModuleGuid, sizeof (FpdtRecordPtr.DynamicStringEvent->Guid));\r
+ CopyStringIntoPerfRecordAndUpdateLength (FpdtRecordPtr.DynamicStringEvent->String, StringPtr, &FpdtRecordPtr.DynamicStringEvent->Header.Length);\r
+ }\r
+ } else {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ break;\r
+ }\r
+\r
+ //\r
+ // 4.2 When PcdEdkiiFpdtStringRecordEnableOnly==TRUE, create string record for all Perf entries.\r
+ //\r
+ if (PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {\r
+ if (StringPtr == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ FpdtRecordPtr.DynamicStringEvent->Header.Type = FPDT_DYNAMIC_STRING_EVENT_TYPE;\r
+ FpdtRecordPtr.DynamicStringEvent->Header.Length = sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD);\r
+ FpdtRecordPtr.DynamicStringEvent->Header.Revision = FPDT_RECORD_REVISION_1;\r
+ FpdtRecordPtr.DynamicStringEvent->ProgressID = PerfId;\r
+ FpdtRecordPtr.DynamicStringEvent->Timestamp = TimeStamp;\r
+ if (Guid != NULL) {\r
+ //\r
+ // Cache the event guid in string event record.\r
+ //\r
+ CopyMem (&FpdtRecordPtr.DynamicStringEvent->Guid, Guid, sizeof (FpdtRecordPtr.DynamicStringEvent->Guid));\r
+ } else {\r
+ CopyMem (&FpdtRecordPtr.DynamicStringEvent->Guid, &ModuleGuid, sizeof (FpdtRecordPtr.DynamicStringEvent->Guid));\r
+ }\r
+ if (AsciiStrLen (StringPtr) == 0) {\r
+ StringPtr = "unknown name";\r
+ }\r
+ CopyStringIntoPerfRecordAndUpdateLength (FpdtRecordPtr.DynamicStringEvent->String, StringPtr, &FpdtRecordPtr.DynamicStringEvent->Header.Length);\r
+\r
+ if ((PerfId == MODULE_LOADIMAGE_START_ID) || (PerfId == MODULE_END_ID)) {\r
+ FpdtRecordPtr.DynamicStringEvent->Header.Length = (UINT8)(sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD)+ STRING_SIZE);\r
+ }\r
+ if ((PerfId == MODULE_LOADIMAGE_END_ID || PerfId == MODULE_END_ID) && mCachedLength != 0) {\r
+ CachedFpdtRecordPtr.RecordHeader = (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER *)((UINT8*)mSmmBootPerformanceTable + mCachedLength);\r
+ if (PerfId == MODULE_LOADIMAGE_END_ID) {\r
+ DestMax = CachedFpdtRecordPtr.DynamicStringEvent->Header.Length - sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD);\r
+ StringLen = AsciiStrLen (StringPtr);\r
+ if (StringLen >= DestMax) {\r
+ StringLen = DestMax -1;\r
+ }\r
+ CopyMem (&CachedFpdtRecordPtr.DynamicStringEvent->Guid, &ModuleGuid, sizeof (CachedFpdtRecordPtr.DynamicStringEvent->Guid));\r
+ AsciiStrnCpyS (CachedFpdtRecordPtr.DynamicStringEvent->String, DestMax, StringPtr, StringLen);\r
+ } else if (PerfId == MODULE_END_ID) {\r
+ DestMax = FpdtRecordPtr.DynamicStringEvent->Header.Length - sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD);\r
+ StringLen = AsciiStrLen (CachedFpdtRecordPtr.DynamicStringEvent->String);\r
+ if (StringLen >= DestMax) {\r
+ StringLen = DestMax -1;\r
+ }\r
+ CopyMem (&FpdtRecordPtr.DynamicStringEvent->Guid, &CachedFpdtRecordPtr.DynamicStringEvent->Guid, sizeof (CachedFpdtRecordPtr.DynamicStringEvent->Guid));\r
+ AsciiStrnCpyS (FpdtRecordPtr.DynamicStringEvent->String, DestMax, CachedFpdtRecordPtr.DynamicStringEvent->String, StringLen);\r
+ }\r
+ mCachedLength = 0;\r
+ }\r
}\r
\r
//\r
- // Update the cached FPDT record buffer.\r
+ // 5. Update the length of the used buffer after fill in the record.\r
//\r
mPerformanceLength += FpdtRecordPtr.RecordHeader->Length;\r
mSmmBootPerformanceTable->Header.Length += FpdtRecordPtr.RecordHeader->Length;\r
return EFI_SUCCESS;\r
}\r
\r
-/**\r
- Adds a record at the end of the performance measurement log\r
- that records the start time of a performance measurement.\r
-\r
- Adds a record to the end of the performance measurement log\r
- that contains the Handle, Token, Module and Identifier.\r
- The end time of the new record must be set to zero.\r
- If TimeStamp is not zero, then TimeStamp is used to fill in the start time in the record.\r
- If TimeStamp is zero, the start time in the record is filled in with the value\r
- read from the current time stamp.\r
-\r
- @param Handle Pointer to environment specific context used\r
- to identify the component being measured.\r
- @param Token Pointer to a Null-terminated ASCII string\r
- that identifies the component being measured.\r
- @param Module Pointer to a Null-terminated ASCII string\r
- that identifies the module being measured.\r
- @param TimeStamp 64-bit time stamp.\r
- @param Identifier 32-bit identifier. If the value is 0, the created record\r
- is same as the one created by StartGauge of PERFORMANCE_PROTOCOL.\r
-\r
- @retval EFI_SUCCESS The data was read correctly from the device.\r
- @retval EFI_OUT_OF_RESOURCES There are not enough resources to record the measurement.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-StartGaugeEx (\r
- IN CONST VOID *Handle, OPTIONAL\r
- IN CONST CHAR8 *Token, OPTIONAL\r
- IN CONST CHAR8 *Module, OPTIONAL\r
- IN UINT64 TimeStamp,\r
- IN UINT32 Identifier\r
- )\r
-{\r
- EFI_STATUS Status;\r
-\r
- AcquireSpinLock (&mSmmFpdtLock);\r
-\r
- Status = InsertFpdtMeasurement (TRUE, Handle, Token, Module, TimeStamp, Identifier);\r
-\r
- ReleaseSpinLock (&mSmmFpdtLock);\r
-\r
- return Status;\r
-}\r
-\r
-/**\r
- Searches the performance measurement log from the beginning of the log\r
- for the first matching record that contains a zero end time and fills in a valid end time.\r
-\r
- Searches the performance measurement log from the beginning of the log\r
- for the first record that matches Handle, Token, Module and Identifier and has an end time value of zero.\r
- If the record can not be found then return EFI_NOT_FOUND.\r
- If the record is found and TimeStamp is not zero,\r
- then the end time in the record is filled in with the value specified by TimeStamp.\r
- If the record is found and TimeStamp is zero, then the end time in the matching record\r
- is filled in with the current time stamp value.\r
-\r
- @param Handle Pointer to environment specific context used\r
- to identify the component being measured.\r
- @param Token Pointer to a Null-terminated ASCII string\r
- that identifies the component being measured.\r
- @param Module Pointer to a Null-terminated ASCII string\r
- that identifies the module being measured.\r
- @param TimeStamp 64-bit time stamp.\r
- @param Identifier 32-bit identifier. If the value is 0, the found record\r
- is same as the one found by EndGauge of PERFORMANCE_PROTOCOL.\r
-\r
- @retval EFI_SUCCESS The end of the measurement was recorded.\r
- @retval EFI_NOT_FOUND The specified measurement record could not be found.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-EndGaugeEx (\r
- IN CONST VOID *Handle, OPTIONAL\r
- IN CONST CHAR8 *Token, OPTIONAL\r
- IN CONST CHAR8 *Module, OPTIONAL\r
- IN UINT64 TimeStamp,\r
- IN UINT32 Identifier\r
- )\r
-{\r
- EFI_STATUS Status;\r
-\r
- AcquireSpinLock (&mSmmFpdtLock);\r
-\r
- Status = InsertFpdtMeasurement (FALSE, Handle, Token, Module, TimeStamp, Identifier);\r
-\r
- ReleaseSpinLock (&mSmmFpdtLock);\r
-\r
- return Status;\r
-}\r
-\r
-/**\r
- Retrieves a previously logged performance measurement.\r
- It can also retrieve the log created by StartGauge and EndGauge of PERFORMANCE_PROTOCOL,\r
- and then assign the Identifier with 0.\r
-\r
- !!! Not Support!!!\r
-\r
- Retrieves the performance log entry from the performance log specified by LogEntryKey.\r
- If it stands for a valid entry, then EFI_SUCCESS is returned and\r
- GaugeDataEntryEx stores the pointer to that entry.\r
-\r
- @param LogEntryKey The key for the previous performance measurement log entry.\r
- If 0, then the first performance measurement log entry is retrieved.\r
- @param GaugeDataEntryEx The indirect pointer to the extended gauge data entry specified by LogEntryKey\r
- if the retrieval is successful.\r
-\r
- @retval EFI_SUCCESS The GuageDataEntryEx is successfully found based on LogEntryKey.\r
- @retval EFI_NOT_FOUND The LogEntryKey is the last entry (equals to the total entry number).\r
- @retval EFI_INVALIDE_PARAMETER The LogEntryKey is not a valid entry (greater than the total entry number).\r
- @retval EFI_INVALIDE_PARAMETER GaugeDataEntryEx is NULL.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-GetGaugeEx (\r
- IN UINTN LogEntryKey,\r
- OUT GAUGE_DATA_ENTRY_EX **GaugeDataEntryEx\r
- )\r
-{\r
- return EFI_UNSUPPORTED;\r
-}\r
-\r
-/**\r
- Adds a record at the end of the performance measurement log\r
- that records the start time of a performance measurement.\r
-\r
- Adds a record to the end of the performance measurement log\r
- that contains the Handle, Token, and Module.\r
- The end time of the new record must be set to zero.\r
- If TimeStamp is not zero, then TimeStamp is used to fill in the start time in the record.\r
- If TimeStamp is zero, the start time in the record is filled in with the value\r
- read from the current time stamp.\r
-\r
- @param Handle Pointer to environment specific context used\r
- to identify the component being measured.\r
- @param Token Pointer to a Null-terminated ASCII string\r
- that identifies the component being measured.\r
- @param Module Pointer to a Null-terminated ASCII string\r
- that identifies the module being measured.\r
- @param TimeStamp 64-bit time stamp.\r
-\r
- @retval EFI_SUCCESS The data was read correctly from the device.\r
- @retval EFI_OUT_OF_RESOURCES There are not enough resources to record the measurement.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-StartGauge (\r
- IN CONST VOID *Handle, OPTIONAL\r
- IN CONST CHAR8 *Token, OPTIONAL\r
- IN CONST CHAR8 *Module, OPTIONAL\r
- IN UINT64 TimeStamp\r
- )\r
-{\r
- return StartGaugeEx (Handle, Token, Module, TimeStamp, 0);\r
-}\r
-\r
-/**\r
- Searches the performance measurement log from the beginning of the log\r
- for the first matching record that contains a zero end time and fills in a valid end time.\r
-\r
- Searches the performance measurement log from the beginning of the log\r
- for the first record that matches Handle, Token, and Module and has an end time value of zero.\r
- If the record can not be found then return EFI_NOT_FOUND.\r
- If the record is found and TimeStamp is not zero,\r
- then the end time in the record is filled in with the value specified by TimeStamp.\r
- If the record is found and TimeStamp is zero, then the end time in the matching record\r
- is filled in with the current time stamp value.\r
-\r
- @param Handle Pointer to environment specific context used\r
- to identify the component being measured.\r
- @param Token Pointer to a Null-terminated ASCII string\r
- that identifies the component being measured.\r
- @param Module Pointer to a Null-terminated ASCII string\r
- that identifies the module being measured.\r
- @param TimeStamp 64-bit time stamp.\r
-\r
- @retval EFI_SUCCESS The end of the measurement was recorded.\r
- @retval EFI_NOT_FOUND The specified measurement record could not be found.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-EndGauge (\r
- IN CONST VOID *Handle, OPTIONAL\r
- IN CONST CHAR8 *Token, OPTIONAL\r
- IN CONST CHAR8 *Module, OPTIONAL\r
- IN UINT64 TimeStamp\r
- )\r
-{\r
- return EndGaugeEx (Handle, Token, Module, TimeStamp, 0);\r
-}\r
-\r
-/**\r
- Retrieves a previously logged performance measurement.\r
- It can also retrieve the log created by StartGaugeEx and EndGaugeEx of PERFORMANCE_EX_PROTOCOL,\r
- and then eliminate the Identifier.\r
-\r
- !!! Not Support!!!\r
-\r
- Retrieves the performance log entry from the performance log specified by LogEntryKey.\r
- If it stands for a valid entry, then EFI_SUCCESS is returned and\r
- GaugeDataEntry stores the pointer to that entry.\r
-\r
- @param LogEntryKey The key for the previous performance measurement log entry.\r
- If 0, then the first performance measurement log entry is retrieved.\r
- @param GaugeDataEntry The indirect pointer to the gauge data entry specified by LogEntryKey\r
- if the retrieval is successful.\r
-\r
- @retval EFI_SUCCESS The GuageDataEntry is successfully found based on LogEntryKey.\r
- @retval EFI_NOT_FOUND The LogEntryKey is the last entry (equals to the total entry number).\r
- @retval EFI_INVALIDE_PARAMETER The LogEntryKey is not a valid entry (greater than the total entry number).\r
- @retval EFI_INVALIDE_PARAMETER GaugeDataEntry is NULL.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-GetGauge (\r
- IN UINTN LogEntryKey,\r
- OUT GAUGE_DATA_ENTRY **GaugeDataEntry\r
- )\r
-{\r
- return EFI_UNSUPPORTED;\r
-}\r
-\r
-\r
/**\r
SmmReadyToBoot protocol notification event handler.\r
\r
Handle = NULL;\r
Status = gSmst->SmmInstallProtocolInterface (\r
&Handle,\r
- &gSmmPerformanceProtocolGuid,\r
- EFI_NATIVE_INTERFACE,\r
- &mPerformanceInterface\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
- Status = gSmst->SmmInstallProtocolInterface (\r
- &Handle,\r
- &gSmmPerformanceExProtocolGuid,\r
+ &gEdkiiSmmPerformanceMeasurementProtocolGuid,\r
EFI_NATIVE_INTERFACE,\r
- &mPerformanceExInterface\r
+ &mPerformanceMeasurementInterface\r
);\r
ASSERT_EFI_ERROR (Status);\r
\r
return EFI_SUCCESS;\r
}\r
\r
+/**\r
+ Create performance record with event description and a timestamp.\r
+\r
+ @param CallerIdentifier - Image handle or pointer to caller ID GUID.\r
+ @param Guid - Pointer to a GUID.\r
+ @param String - Pointer to a string describing the measurement.\r
+ @param TimeStamp - 64-bit time stamp.\r
+ @param Address - Pointer to a location in memory relevant to the measurement.\r
+ @param Identifier - Performance identifier describing the type of measurement.\r
+ @param Attribute - The attribute of the measurement. According to attribute can create a start\r
+ record for PERF_START/PERF_START_EX, or a end record for PERF_END/PERF_END_EX,\r
+ or a general record for other Perf macros.\r
+\r
+ @retval EFI_SUCCESS - Successfully created performance record.\r
+ @retval EFI_OUT_OF_RESOURCES - Ran out of space to store the records.\r
+ @retval EFI_INVALID_PARAMETER - Invalid parameter passed to function - NULL\r
+ pointer or invalid PerfId.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+CreatePerformanceMeasurement(\r
+ IN CONST VOID *CallerIdentifier, OPTIONAL\r
+ IN CONST VOID *Guid, OPTIONAL\r
+ IN CONST CHAR8 *String, OPTIONAL\r
+ IN UINT64 TimeStamp, OPTIONAL\r
+ IN UINT64 Address, OPTIONAL\r
+ IN UINT32 Identifier,\r
+ IN PERF_MEASUREMENT_ATTRIBUTE Attribute\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ Status = EFI_SUCCESS;\r
+\r
+ AcquireSpinLock (&mSmmFpdtLock);\r
+ Status = InsertFpdtRecord (CallerIdentifier, Guid, String, TimeStamp, Address, (UINT16)Identifier, Attribute);\r
+ ReleaseSpinLock (&mSmmFpdtLock);\r
+ return Status;\r
+}\r
+\r
/**\r
Adds a record at the end of the performance measurement log\r
that records the start time of a performance measurement.\r
IN UINT32 Identifier\r
)\r
{\r
- return (RETURN_STATUS) StartGaugeEx (Handle, Token, Module, TimeStamp, Identifier);\r
+ CONST CHAR8 *String;\r
+\r
+ if (Token != NULL) {\r
+ String = Token;\r
+ } else if (Module != NULL) {\r
+ String = Module;\r
+ } else {\r
+ String = NULL;\r
+ }\r
+\r
+ return (RETURN_STATUS)CreatePerformanceMeasurement (Handle, NULL, String, TimeStamp, 0, Identifier, PerfStartEntry);\r
}\r
\r
/**\r
IN UINT32 Identifier\r
)\r
{\r
- return (RETURN_STATUS) EndGaugeEx (Handle, Token, Module, TimeStamp, Identifier);\r
+ CONST CHAR8 *String;\r
+\r
+ if (Token != NULL) {\r
+ String = Token;\r
+ } else if (Module != NULL) {\r
+ String = Module;\r
+ } else {\r
+ String = NULL;\r
+ }\r
+\r
+ return (RETURN_STATUS)CreatePerformanceMeasurement (Handle, NULL, String, TimeStamp, 0, Identifier, PerfEndEntry);\r
}\r
\r
/**\r
IN UINT64 TimeStamp\r
)\r
{\r
- return StartGaugeEx (Handle, Token, Module, TimeStamp, 0);\r
+ return StartPerformanceMeasurementEx (Handle, Token, Module, TimeStamp, 0);\r
}\r
\r
/**\r
IN UINT64 TimeStamp\r
)\r
{\r
- return EndGaugeEx (Handle, Token, Module, TimeStamp, 0);\r
+ return EndPerformanceMeasurementEx (Handle, Token, Module, TimeStamp, 0);\r
}\r
\r
/**\r
{\r
return (BOOLEAN) ((PcdGet8(PcdPerformanceLibraryPropertyMask) & PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED) != 0);\r
}\r
+\r
+/**\r
+ Create performance record with event description and a timestamp.\r
+\r
+ @param CallerIdentifier - Image handle or pointer to caller ID GUID\r
+ @param Guid - Pointer to a GUID\r
+ @param String - Pointer to a string describing the measurement\r
+ @param Address - Pointer to a location in memory relevant to the measurement\r
+ @param Identifier - Performance identifier describing the type of measurement\r
+\r
+ @retval RETURN_SUCCESS - Successfully created performance record\r
+ @retval RETURN_OUT_OF_RESOURCES - Ran out of space to store the records\r
+ @retval RETURN_INVALID_PARAMETER - Invalid parameter passed to function - NULL\r
+ pointer or invalid PerfId\r
+\r
+**/\r
+RETURN_STATUS\r
+EFIAPI\r
+LogPerformanceMeasurement (\r
+ IN CONST VOID *CallerIdentifier,\r
+ IN CONST VOID *Guid, OPTIONAL\r
+ IN CONST CHAR8 *String, OPTIONAL\r
+ IN UINT64 Address, OPTIONAL\r
+ IN UINT32 Identifier\r
+ )\r
+{\r
+ return (RETURN_STATUS)CreatePerformanceMeasurement (CallerIdentifier, Guid, String, 0, Address, Identifier, PerfEntry);\r
+}\r
+\r
+/**\r
+ Check whether the specified performance measurement can be logged.\r
+\r
+ This function returns TRUE when the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of PcdPerformanceLibraryPropertyMask is set\r
+ and the Type disable bit in PcdPerformanceLibraryPropertyMask is not set.\r
+\r
+ @param Type - Type of the performance measurement entry.\r
+\r
+ @retval TRUE The performance measurement can be logged.\r
+ @retval FALSE The performance measurement can NOT be logged.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+LogPerformanceMeasurementEnabled (\r
+ IN CONST UINTN Type\r
+ )\r
+{\r
+ //\r
+ // When Performance measurement is enabled and the type is not filtered, the performance can be logged.\r
+ //\r
+ if (PerformanceMeasurementEnabled () && (PcdGet8(PcdPerformanceLibraryPropertyMask) & Type) == 0) {\r
+ return TRUE;\r
+ }\r
+ return FALSE;\r
+}\r
+\r