#include <PiPei.h>\r
\r
#include <Guid/ExtendedFirmwarePerformance.h>\r
+#include <Guid/PerformanceMeasurement.h>\r
\r
#include <Library/PerformanceLib.h>\r
#include <Library/DebugLib.h>\r
#include <Library/BaseMemoryLib.h>\r
\r
#define STRING_SIZE (FPDT_STRING_EVENT_RECORD_NAME_LENGTH * sizeof (CHAR8))\r
-#define MAX_RECORD_SIZE (sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD) + STRING_SIZE)\r
+#define PEI_MAX_RECORD_SIZE (sizeof (FPDT_DUAL_GUID_STRING_EVENT_RECORD) + STRING_SIZE)\r
+\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
+ @param PeiPerformanceLogHeader Pointer to the header of the PEI Performance records in the GUID Hob.\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
+ IN OUT FPDT_PEI_EXT_PERF_HEADER **PeiPerformanceLogHeader\r
+)\r
+{\r
+ UINT16 PeiPerformanceLogEntries;\r
+ UINTN PeiPerformanceSize;\r
+ UINT8 *PeiFirmwarePerformance;\r
+ EFI_HOB_GUID_TYPE *GuidHob;\r
+\r
+ //\r
+ // Get the number of PeiPerformanceLogEntries form PCD.\r
+ //\r
+ PeiPerformanceLogEntries = (UINT16) (PcdGet16 (PcdMaxPeiPerformanceLogEntries16) != 0 ?\r
+ PcdGet16 (PcdMaxPeiPerformanceLogEntries16) :\r
+ PcdGet8 (PcdMaxPeiPerformanceLogEntries));\r
+\r
+ //\r
+ // Create GUID HOB Data.\r
+ //\r
+ GuidHob = GetFirstGuidHob (&gEdkiiFpdtExtendedFirmwarePerformanceGuid);\r
+ PeiFirmwarePerformance = NULL;\r
+ while (GuidHob != NULL) {\r
+ //\r
+ // PEI Performance HOB was found, then return the existing one.\r
+ //\r
+ PeiFirmwarePerformance = (UINT8*)GET_GUID_HOB_DATA (GuidHob);\r
+ *PeiPerformanceLogHeader = (FPDT_PEI_EXT_PERF_HEADER *)PeiFirmwarePerformance;\r
+ if (!(*PeiPerformanceLogHeader)->HobIsFull && (*PeiPerformanceLogHeader)->SizeOfAllEntries + RecordSize > (UINTN)(PeiPerformanceLogEntries * PEI_MAX_RECORD_SIZE)) {\r
+ (*PeiPerformanceLogHeader)->HobIsFull = TRUE;\r
+ }\r
+ if (!(*PeiPerformanceLogHeader)->HobIsFull && (*PeiPerformanceLogHeader)->SizeOfAllEntries + RecordSize <= (UINTN)(PeiPerformanceLogEntries * PEI_MAX_RECORD_SIZE)) {\r
+ FpdtRecordPtr->RecordHeader = (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER *)(PeiFirmwarePerformance + sizeof (FPDT_PEI_EXT_PERF_HEADER) + (*PeiPerformanceLogHeader)->SizeOfAllEntries);\r
+ break;\r
+ }\r
+ //\r
+ // Previous HOB is used, then find next one.\r
+ //\r
+ GuidHob = GetNextGuidHob (&gEdkiiFpdtExtendedFirmwarePerformanceGuid, GET_NEXT_HOB (GuidHob));\r
+ }\r
+\r
+ if (GuidHob == NULL) {\r
+ //\r
+ // PEI Performance HOB was not found, then build one.\r
+ //\r
+ PeiPerformanceSize = sizeof (FPDT_PEI_EXT_PERF_HEADER) +\r
+ PEI_MAX_RECORD_SIZE * PeiPerformanceLogEntries;\r
+ PeiFirmwarePerformance = (UINT8*)BuildGuidHob (&gEdkiiFpdtExtendedFirmwarePerformanceGuid, PeiPerformanceSize);\r
+ if (PeiFirmwarePerformance != NULL) {\r
+ ZeroMem (PeiFirmwarePerformance, PeiPerformanceSize);\r
+ (*PeiPerformanceLogHeader) = (FPDT_PEI_EXT_PERF_HEADER *)PeiFirmwarePerformance;\r
+ FpdtRecordPtr->RecordHeader = (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER *)(PeiFirmwarePerformance + sizeof (FPDT_PEI_EXT_PERF_HEADER));\r
+ }\r
+ }\r
+\r
+ if (PeiFirmwarePerformance == NULL) {\r
+ //\r
+ // there is no enough resource to store performance data\r
+ //\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ return EFI_SUCCESS;\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 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
+GetFpdtRecordId (\r
+ IN BOOLEAN Attribute,\r
IN CONST VOID *Handle,\r
- IN CONST CHAR8 *Token,\r
- IN CONST CHAR8 *Module,\r
- OUT FPDT_BASIC_RECORD_INFO *RecordInfo\r
+ IN CONST CHAR8 *String,\r
+ OUT UINT16 *ProgressID\r
)\r
{\r
- UINTN StringSize;\r
- UINT16 RecordType;\r
-\r
- RecordType = FPDT_DYNAMIC_STRING_EVENT_TYPE;\r
-\r
//\r
// Get the ProgressID based on the Token.\r
// When PcdEdkiiFpdtStringRecordEnableOnly is TRUE, all records are with type of FPDT_DYNAMIC_STRING_EVENT_TYPE.\r
//\r
- if (Token != NULL) {\r
- if (AsciiStrCmp (Token, LOAD_IMAGE_TOK) == 0) { // "LoadImage:"\r
- if (IsStart) {\r
- RecordInfo->ProgressID = MODULE_LOADIMAGE_START_ID;\r
+ if (String != NULL) {\r
+ 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
- if(!PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {\r
- RecordType = FPDT_GUID_QWORD_EVENT_TYPE;\r
- }\r
- } else if (AsciiStrCmp (Token, SEC_TOK) == 0 || // "SEC"\r
- AsciiStrCmp (Token, PEI_TOK) == 0) { // "PEI"\r
- if (IsStart) {\r
- RecordInfo->ProgressID = PERF_CROSSMODULE_START_ID;\r
+ } else if (AsciiStrCmp (String, SEC_TOK) == 0 || // "SEC"\r
+ AsciiStrCmp (String, PEI_TOK) == 0) { // "PEI"\r
+ if (Attribute == PerfStartEntry) {\r
+ *ProgressID = PERF_CROSSMODULE_START_ID;\r
} else {\r
- RecordInfo->ProgressID = PERF_CROSSMODULE_END_ID;\r
+ *ProgressID = PERF_CROSSMODULE_END_ID;\r
}\r
- } else if (AsciiStrCmp (Token, PEIM_TOK) == 0) { // "PEIM"\r
- if (IsStart) {\r
- RecordInfo->ProgressID = MODULE_START_ID;\r
+ } else if (AsciiStrCmp (String, PEIM_TOK) == 0) { // "PEIM"\r
+ if (Attribute == PerfStartEntry) {\r
+ *ProgressID = MODULE_START_ID;\r
} else {\r
- RecordInfo->ProgressID = MODULE_END_ID;\r
- }\r
- if(!PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {\r
- RecordType = FPDT_GUID_EVENT_TYPE;\r
+ *ProgressID = MODULE_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 (Module != NULL || Handle != 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
+ return EFI_INVALID_PARAMETER;\r
}\r
\r
- //\r
- // Get the Guid and string.\r
- //\r
- if(PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {\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
+ return EFI_SUCCESS;\r
+}\r
\r
- case FPDT_GUID_QWORD_EVENT_TYPE:\r
- RecordInfo->RecordSize = sizeof (FPDT_GUID_QWORD_EVENT_RECORD);\r
- break;\r
+/**\r
+ Copies the string from Source into Destination and updates Length with the\r
+ size of the string.\r
\r
- case FPDT_DYNAMIC_STRING_EVENT_TYPE:\r
- if (Token != NULL) {\r
- StringSize = AsciiStrSize (Token);\r
- } else if (Module != NULL) {\r
- StringSize = AsciiStrSize (Module);\r
- } else {\r
- StringSize = STRING_SIZE;\r
- }\r
- RecordInfo->RecordSize = (UINT8)(sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD) + StringSize);\r
- break;\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
- default:\r
- //\r
- // Other type is unsupported in PEI phase yet, return EFI_UNSUPPORTED\r
- //\r
- return EFI_UNSUPPORTED;\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
- RecordInfo->Type = RecordType;\r
- return EFI_SUCCESS;\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
/**\r
Convert PEI performance log to FPDT String boot record.\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
-\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
+ @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
**/\r
EFI_STATUS\r
-InsertPeiFpdtMeasurement (\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
- EFI_HOB_GUID_TYPE *GuidHob;\r
- UINTN PeiPerformanceSize;\r
- UINT8 *PeiFirmwarePerformance;\r
- FPDT_PEI_EXT_PERF_HEADER *PeiPerformanceLogHeader;\r
FPDT_RECORD_PTR FpdtRecordPtr;\r
- FPDT_BASIC_RECORD_INFO RecordInfo;\r
CONST VOID *ModuleGuid;\r
- UINTN DestMax;\r
- UINTN StrLength;\r
CONST CHAR8 *StringPtr;\r
EFI_STATUS Status;\r
- UINT16 PeiPerformanceLogEntries;\r
UINT64 TimeStamp;\r
+ FPDT_PEI_EXT_PERF_HEADER *PeiPerformanceLogHeader;\r
\r
StringPtr = NULL;\r
FpdtRecordPtr.RecordHeader = NULL;\r
PeiPerformanceLogHeader = NULL;\r
\r
//\r
- // Get record info (type, size, ProgressID and Module Guid).\r
- //\r
- Status = GetFpdtRecordInfo (IsStart, Handle, Token, Module, &RecordInfo);\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
+ // 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
- 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
- //\r
- // Get the number of PeiPerformanceLogEntries form PCD.\r
- //\r
- PeiPerformanceLogEntries = (UINT16) (PcdGet16 (PcdMaxPeiPerformanceLogEntries16) != 0 ?\r
- PcdGet16 (PcdMaxPeiPerformanceLogEntries16) :\r
- PcdGet8 (PcdMaxPeiPerformanceLogEntries));\r
-\r
- //\r
- // Create GUID HOB Data.\r
- //\r
- GuidHob = GetFirstGuidHob (&gEdkiiFpdtExtendedFirmwarePerformanceGuid);\r
- PeiFirmwarePerformance = NULL;\r
- while (GuidHob != NULL) {\r
- //\r
- // PEI Performance HOB was found, then return the existing one.\r
- //\r
- PeiFirmwarePerformance = (UINT8*)GET_GUID_HOB_DATA (GuidHob);\r
- PeiPerformanceLogHeader = (FPDT_PEI_EXT_PERF_HEADER *)PeiFirmwarePerformance;\r
- if (!PeiPerformanceLogHeader->HobIsFull && PeiPerformanceLogHeader->SizeOfAllEntries + RecordInfo.RecordSize > PeiPerformanceLogEntries * MAX_RECORD_SIZE) {\r
- PeiPerformanceLogHeader->HobIsFull = TRUE;\r
- }\r
- if (!PeiPerformanceLogHeader->HobIsFull && PeiPerformanceLogHeader->SizeOfAllEntries + RecordInfo.RecordSize <= PeiPerformanceLogEntries * MAX_RECORD_SIZE) {\r
- FpdtRecordPtr.RecordHeader = (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER *)(PeiFirmwarePerformance + sizeof (FPDT_PEI_EXT_PERF_HEADER) + PeiPerformanceLogHeader->SizeOfAllEntries);\r
- break;\r
- }\r
- //\r
- // Previous HOB is used, then find next one.\r
- //\r
- GuidHob = GetNextGuidHob (&gEdkiiFpdtExtendedFirmwarePerformanceGuid, GET_NEXT_HOB (GuidHob));\r
- }\r
-\r
- if (GuidHob == NULL) {\r
+ if (Attribute != PerfEntry) {\r
//\r
- // PEI Performance HOB was not found, then build one.\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
- PeiPerformanceSize = sizeof (FPDT_PEI_EXT_PERF_HEADER) +\r
- MAX_RECORD_SIZE * PeiPerformanceLogEntries;\r
- PeiFirmwarePerformance = (UINT8*)BuildGuidHob (&gEdkiiFpdtExtendedFirmwarePerformanceGuid, PeiPerformanceSize);\r
- if (PeiFirmwarePerformance != NULL) {\r
- ZeroMem (PeiFirmwarePerformance, PeiPerformanceSize);\r
+ if ((PerfId != 0) && (IsKnownID (PerfId)) && (!IsKnownTokens (String))) {\r
+ return EFI_UNSUPPORTED;\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
+ } else if (PerfId == 0) {\r
+ Status = GetFpdtRecordId (Attribute, CallerIdentifier, String, &PerfId);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
}\r
- PeiPerformanceLogHeader = (FPDT_PEI_EXT_PERF_HEADER *)PeiFirmwarePerformance;\r
- FpdtRecordPtr.RecordHeader = (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER *)(PeiFirmwarePerformance + sizeof (FPDT_PEI_EXT_PERF_HEADER));\r
}\r
\r
- if (PeiFirmwarePerformance == NULL) {\r
- //\r
- // there is no enough resource to store performance data\r
- //\r
- return EFI_OUT_OF_RESOURCES;\r
+ //\r
+ // 2. Get the buffer to store the FPDT record.\r
+ //\r
+ Status = GetFpdtRecordPtr (PEI_MAX_RECORD_SIZE, &FpdtRecordPtr, &PeiPerformanceLogHeader);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
}\r
\r
//\r
- // Get the TimeStamp.\r
+ // 3 Get the TimeStamp.\r
//\r
if (Ticker == 0) {\r
Ticker = GetPerformanceCounter ();\r
}\r
\r
//\r
- // Get the ModuleGuid.\r
+ // 4.Get the ModuleGuid.\r
//\r
- if (Handle != NULL) {\r
- ModuleGuid = Handle;\r
+ if (CallerIdentifier != NULL) {\r
+ ModuleGuid = CallerIdentifier;\r
} else {\r
ModuleGuid = &gEfiCallerIdGuid;\r
}\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 (EFI_GUID));\r
- PeiPerformanceLogHeader->SizeOfAllEntries += RecordInfo.RecordSize;\r
+ //\r
+ // 5. Fill in the FPDT record according to different Performance Identifier.\r
+ //\r
+ switch (PerfId) {\r
+ case MODULE_START_ID:\r
+ case MODULE_END_ID:\r
+ StringPtr = PEIM_TOK;\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 (EFI_GUID));\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
- PeiPerformanceLogHeader->LoadImageCount++;\r
- FpdtRecordPtr.GuidQwordEvent->Qword = PeiPerformanceLogHeader->LoadImageCount;\r
- CopyMem (&FpdtRecordPtr.GuidQwordEvent->Guid, ModuleGuid, sizeof (EFI_GUID));\r
- PeiPerformanceLogHeader->SizeOfAllEntries += RecordInfo.RecordSize;\r
+ case MODULE_LOADIMAGE_START_ID:\r
+ case MODULE_LOADIMAGE_END_ID:\r
+ StringPtr = LOAD_IMAGE_TOK;\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
+ if (PerfId == MODULE_LOADIMAGE_START_ID) {\r
+ PeiPerformanceLogHeader->LoadImageCount++;\r
+ }\r
+ FpdtRecordPtr.GuidQwordEvent->Qword = PeiPerformanceLogHeader->LoadImageCount;\r
+ CopyMem (&FpdtRecordPtr.GuidQwordEvent->Guid, ModuleGuid, sizeof (EFI_GUID));\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 (EFI_GUID));\r
- PeiPerformanceLogHeader->SizeOfAllEntries += RecordInfo.RecordSize;\r
-\r
- if (Token != NULL) {\r
- StringPtr = Token;\r
- } else if (Module != NULL) {\r
- StringPtr = Module;\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 && AsciiStrLen (String) != 0) {\r
+ StringPtr = String;\r
+ } else {\r
+ StringPtr = "unknown name";\r
}\r
- if (StringPtr != NULL && AsciiStrLen (StringPtr) != 0) {\r
- DestMax = (RecordInfo.RecordSize - sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD)) / sizeof (CHAR8);\r
- StrLength = AsciiStrLen (StringPtr);\r
- if (StrLength >= DestMax) {\r
- StrLength = DestMax -1;\r
- }\r
- AsciiStrnCpyS (FpdtRecordPtr.DynamicStringEvent->String, DestMax, StringPtr, StrLength);\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, ModuleGuid, sizeof (FpdtRecordPtr.DualGuidStringEvent->Guid1));\r
+ CopyMem (&FpdtRecordPtr.DualGuidStringEvent->Guid2, Guid, sizeof (FpdtRecordPtr.DualGuidStringEvent->Guid2));\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
+ if (String != NULL && AsciiStrLen (String) != 0) {\r
+ StringPtr = String;\r
} else {\r
- AsciiStrCpyS (FpdtRecordPtr.DynamicStringEvent->String, FPDT_STRING_EVENT_RECORD_NAME_LENGTH, "unknown name");\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 (EFI_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 PEI phase, return EFI_ABORTED\r
- //\r
- return EFI_UNSUPPORTED;\r
+ if (Attribute != PerfEntry) {\r
+ if (String != NULL && AsciiStrLen (String) != 0) {\r
+ StringPtr = String;\r
+ } else {\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
+ // 5.2 When PcdEdkiiFpdtStringRecordEnableOnly==TRUE, create string record for all Perf entries.\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
+ if (Guid != NULL) {\r
+ //\r
+ // Cache the event guid in string event record.\r
+ //\r
+ CopyMem (&FpdtRecordPtr.DynamicStringEvent->Guid, Guid, sizeof (EFI_GUID));\r
+ } else {\r
+ CopyMem (&FpdtRecordPtr.DynamicStringEvent->Guid, ModuleGuid, sizeof (EFI_GUID));\r
+ }\r
+ CopyStringIntoPerfRecordAndUpdateLength (FpdtRecordPtr.DynamicStringEvent->String, StringPtr, &FpdtRecordPtr.DynamicStringEvent->Header.Length);\r
}\r
\r
+ //\r
+ // 6. Update the length of the used buffer after fill in the record.\r
+ //\r
+ PeiPerformanceLogHeader->SizeOfAllEntries += FpdtRecordPtr.RecordHeader->Length;\r
+\r
return EFI_SUCCESS;\r
}\r
\r
IN UINT32 Identifier\r
)\r
{\r
- return InsertPeiFpdtMeasurement (TRUE, 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)InsertFpdtRecord (Handle, NULL, String, TimeStamp, 0, (UINT16)Identifier, PerfStartEntry);\r
+\r
}\r
\r
/**\r
IN UINT32 Identifier\r
)\r
{\r
- return InsertPeiFpdtMeasurement (FALSE, 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)InsertFpdtRecord (Handle, NULL, String, TimeStamp, 0, (UINT16)Identifier, PerfEndEntry);\r
}\r
\r
/**\r
IN UINT64 TimeStamp\r
)\r
{\r
- return InsertPeiFpdtMeasurement (TRUE, Handle, Token, Module, TimeStamp, 0);\r
+ return StartPerformanceMeasurementEx (Handle, Token, Module, TimeStamp, 0);\r
}\r
\r
/**\r
IN UINT64 TimeStamp\r
)\r
{\r
- return InsertPeiFpdtMeasurement (FALSE, 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)InsertFpdtRecord (CallerIdentifier, Guid, String, 0, Address, (UINT16)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