+ //\r
+ // 3. Get the TimeStamp.\r
+ //\r
+ if (Ticker == 0) {\r
+ Ticker = GetPerformanceCounter ();\r
+ TimeStamp = GetTimeInNanoSecond (Ticker);\r
+ } else if (Ticker == 1) {\r
+ TimeStamp = 0;\r
+ } else {\r
+ TimeStamp = GetTimeInNanoSecond (Ticker);\r
+ }\r
+\r
+ //\r
+ // 4. 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
+ 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 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 (!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
+ }\r
+ break;\r
+\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
+ 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
+ // 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
+\r