2 Performance library instance used by SMM Core.
4 This library provides the performance measurement interfaces and initializes performance
5 logging for the SMM phase.
6 It initializes SMM phase performance logging by publishing the SMM Performance and PerformanceEx Protocol,
7 which is consumed by SmmPerformanceLib to logging performance data in SMM phase.
9 This library is mainly used by SMM Core to start performance logging to ensure that
10 SMM Performance and PerformanceEx Protocol are installed at the very beginning of SMM phase.
12 Caution: This module requires additional review when modified.
13 This driver will have external input - performance data and communicate buffer in SMM mode.
14 This external input must be validated carefully to avoid security issue like
15 buffer overflow, integer overflow.
17 SmmPerformanceHandlerEx(), SmmPerformanceHandler() will receive untrusted input and do basic validation.
19 Copyright (c) 2011 - 2021, Intel Corporation. All rights reserved.<BR>
20 SPDX-License-Identifier: BSD-2-Clause-Patent
25 #include "SmmCorePerformanceLibInternal.h"
27 #define STRING_SIZE (FPDT_STRING_EVENT_RECORD_NAME_LENGTH * sizeof (CHAR8))
28 #define FIRMWARE_RECORD_BUFFER 0x1000
29 #define CACHE_HANDLE_GUID_COUNT 0x100
31 SMM_BOOT_PERFORMANCE_TABLE
*mSmmBootPerformanceTable
= NULL
;
35 CHAR8 NameString
[FPDT_STRING_EVENT_RECORD_NAME_LENGTH
];
39 HANDLE_GUID_MAP mCacheHandleGuidTable
[CACHE_HANDLE_GUID_COUNT
];
40 UINTN mCachePairCount
= 0;
42 UINT32 mPerformanceLength
= sizeof (SMM_BOOT_PERFORMANCE_TABLE
);
43 UINT32 mMaxPerformanceLength
= 0;
44 UINT32 mLoadImageCount
= 0;
45 BOOLEAN mFpdtDataIsReported
= FALSE
;
46 BOOLEAN mLackSpaceIsReport
= FALSE
;
47 CHAR8
*mPlatformLanguage
= NULL
;
48 SPIN_LOCK mSmmFpdtLock
;
49 PERFORMANCE_PROPERTY mPerformanceProperty
;
50 UINT32 mCachedLength
= 0;
51 UINT32 mBootRecordSize
= 0;
54 // Interfaces for SMM PerformanceMeasurement Protocol.
56 EDKII_PERFORMANCE_MEASUREMENT_PROTOCOL mPerformanceMeasurementInterface
= {
57 CreatePerformanceMeasurement
,
61 Return the pointer to the FPDT record in the allocated memory.
63 @param RecordSize The size of FPDT record.
64 @param FpdtRecordPtr Pointer the FPDT record in the allocated memory.
66 @retval EFI_SUCCESS Successfully get the pointer to the FPDT record.
67 @retval EFI_OUT_OF_RESOURCES Ran out of space to store the records.
72 IN OUT FPDT_RECORD_PTR
*FpdtRecordPtr
75 if (mFpdtDataIsReported
) {
77 // Append Boot records after Smm boot performance records have been reported.
79 if (mPerformanceLength
+ RecordSize
> mMaxPerformanceLength
) {
80 if (!mLackSpaceIsReport
) {
81 DEBUG ((DEBUG_INFO
, "SmmCorePerformanceLib: No enough space to save boot records\n"));
82 mLackSpaceIsReport
= TRUE
;
84 return EFI_OUT_OF_RESOURCES
;
87 // Covert buffer to FPDT Ptr Union type.
89 FpdtRecordPtr
->RecordHeader
= (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER
*)((UINT8
*)mSmmBootPerformanceTable
+ mSmmBootPerformanceTable
->Header
.Length
);
93 // Check if pre-allocated buffer is full
95 if (mPerformanceLength
+ RecordSize
> mMaxPerformanceLength
) {
96 mSmmBootPerformanceTable
= ReallocatePool (
98 mPerformanceLength
+ RecordSize
+ FIRMWARE_RECORD_BUFFER
,
99 mSmmBootPerformanceTable
102 if (mSmmBootPerformanceTable
== NULL
) {
103 return EFI_OUT_OF_RESOURCES
;
105 mSmmBootPerformanceTable
->Header
.Length
= mPerformanceLength
;
106 mMaxPerformanceLength
= mPerformanceLength
+ RecordSize
+ FIRMWARE_RECORD_BUFFER
;
109 // Covert buffer to FPDT Ptr Union type.
111 FpdtRecordPtr
->RecordHeader
= (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER
*)((UINT8
*)mSmmBootPerformanceTable
+ mSmmBootPerformanceTable
->Header
.Length
);
113 FpdtRecordPtr
->RecordHeader
->Length
= 0;
119 Check whether the Token is a known one which is uesed by core.
121 @param Token Pointer to a Null-terminated ASCII string
123 @retval TRUE Is a known one used by core.
124 @retval FALSE Not a known one.
129 IN CONST CHAR8
*Token
136 if (AsciiStrCmp (Token
, SEC_TOK
) == 0 ||
137 AsciiStrCmp (Token
, PEI_TOK
) == 0 ||
138 AsciiStrCmp (Token
, DXE_TOK
) == 0 ||
139 AsciiStrCmp (Token
, BDS_TOK
) == 0 ||
140 AsciiStrCmp (Token
, DRIVERBINDING_START_TOK
) == 0 ||
141 AsciiStrCmp (Token
, DRIVERBINDING_SUPPORT_TOK
) == 0 ||
142 AsciiStrCmp (Token
, DRIVERBINDING_STOP_TOK
) == 0 ||
143 AsciiStrCmp (Token
, LOAD_IMAGE_TOK
) == 0 ||
144 AsciiStrCmp (Token
, START_IMAGE_TOK
) == 0 ||
145 AsciiStrCmp (Token
, PEIM_TOK
) == 0) {
153 Check whether the ID is a known one which map to the known Token.
155 @param Identifier 32-bit identifier.
157 @retval TRUE Is a known one used by core.
158 @retval FALSE Not a known one.
166 if (Identifier
== MODULE_START_ID
||
167 Identifier
== MODULE_END_ID
||
168 Identifier
== MODULE_LOADIMAGE_START_ID
||
169 Identifier
== MODULE_LOADIMAGE_END_ID
||
170 Identifier
== MODULE_DB_START_ID
||
171 Identifier
== MODULE_DB_END_ID
||
172 Identifier
== MODULE_DB_SUPPORT_START_ID
||
173 Identifier
== MODULE_DB_SUPPORT_END_ID
||
174 Identifier
== MODULE_DB_STOP_START_ID
||
175 Identifier
== MODULE_DB_STOP_END_ID
) {
183 Get the FPDT record identifier.
185 @param Attribute The attribute of the Record.
186 PerfStartEntry: Start Record.
187 PerfEndEntry: End Record.
188 @param Handle Pointer to environment specific context used to identify the component being measured.
189 @param String Pointer to a Null-terminated ASCII string that identifies the component being measured.
190 @param ProgressID On return, pointer to the ProgressID.
192 @retval EFI_SUCCESS Get record info successfully.
193 @retval EFI_INVALID_PARAMETER No matched FPDT record.
198 IN PERF_MEASUREMENT_ATTRIBUTE Attribute
,
199 IN CONST VOID
*Handle
,
200 IN CONST CHAR8
*String
,
201 OUT UINT16
*ProgressID
207 if (String
!= NULL
) {
208 if (AsciiStrCmp (String
, START_IMAGE_TOK
) == 0) { // "StartImage:"
209 if (Attribute
== PerfStartEntry
) {
210 *ProgressID
= MODULE_START_ID
;
212 *ProgressID
= MODULE_END_ID
;
214 } else if (AsciiStrCmp (String
, LOAD_IMAGE_TOK
) == 0) { // "LoadImage:"
215 if (Attribute
== PerfStartEntry
) {
216 *ProgressID
= MODULE_LOADIMAGE_START_ID
;
218 *ProgressID
= MODULE_LOADIMAGE_END_ID
;
220 } else { // Pref used in Modules
221 if (Attribute
== PerfStartEntry
) {
222 *ProgressID
= PERF_INMODULE_START_ID
;
224 *ProgressID
= PERF_INMODULE_END_ID
;
227 } else if (Handle
!= NULL
) { // Pref used in Modules
228 if (Attribute
== PerfStartEntry
) {
229 *ProgressID
= PERF_INMODULE_START_ID
;
231 *ProgressID
= PERF_INMODULE_END_ID
;
234 return EFI_UNSUPPORTED
;
240 Get a human readable module name and module guid for the given image handle.
241 If module name can't be found, "" string will return.
242 If module guid can't be found, Zero Guid will return.
244 @param Handle Image handle or Controller handle.
245 @param NameString The ascii string will be filled into it. If not found, null string will return.
246 @param BufferSize Size of the input NameString buffer.
247 @param ModuleGuid Point to the guid buffer to store the got module guid value.
249 @retval EFI_SUCCESS Successfully get module name and guid.
250 @retval EFI_INVALID_PARAMETER The input parameter NameString is NULL.
251 @retval other value Module Name can't be got.
255 GetModuleInfoFromHandle (
256 IN EFI_HANDLE Handle
,
257 OUT CHAR8
*NameString
,
259 OUT EFI_GUID
*ModuleGuid OPTIONAL
263 EFI_LOADED_IMAGE_PROTOCOL
*LoadedImage
;
264 EFI_DRIVER_BINDING_PROTOCOL
*DriverBinding
;
270 BOOLEAN ModuleGuidIsGet
;
273 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*FvFilePath
;
275 if (NameString
== NULL
|| BufferSize
== 0) {
276 return EFI_INVALID_PARAMETER
;
280 // Try to get the ModuleGuid and name string form the caached array.
282 if (mCachePairCount
> 0) {
283 for (Count
= mCachePairCount
- 1; Count
>= 0; Count
--) {
284 if (Handle
== mCacheHandleGuidTable
[Count
].Handle
) {
285 CopyGuid (ModuleGuid
, &mCacheHandleGuidTable
[Count
].ModuleGuid
);
286 AsciiStrCpyS (NameString
, FPDT_STRING_EVENT_RECORD_NAME_LENGTH
, mCacheHandleGuidTable
[Count
].NameString
);
292 Status
= EFI_INVALID_PARAMETER
;
294 ModuleGuidIsGet
= FALSE
;
297 // Initialize GUID as zero value.
299 TempGuid
= &gZeroGuid
;
301 // Initialize it as "" string.
305 if (Handle
!= NULL
) {
307 // Try Handle as ImageHandle.
309 Status
= gBS
->HandleProtocol (
311 &gEfiLoadedImageProtocolGuid
,
312 (VOID
**) &LoadedImage
315 if (EFI_ERROR (Status
)) {
317 // Try Handle as Controller Handle
319 Status
= gBS
->OpenProtocol (
321 &gEfiDriverBindingProtocolGuid
,
322 (VOID
**) &DriverBinding
,
325 EFI_OPEN_PROTOCOL_GET_PROTOCOL
327 if (!EFI_ERROR (Status
)) {
329 // Get Image protocol from ImageHandle
331 Status
= gBS
->HandleProtocol (
332 DriverBinding
->ImageHandle
,
333 &gEfiLoadedImageProtocolGuid
,
334 (VOID
**) &LoadedImage
340 if (!EFI_ERROR (Status
) && LoadedImage
!= NULL
) {
342 // Get Module Guid from DevicePath.
344 if (LoadedImage
->FilePath
!= NULL
&&
345 LoadedImage
->FilePath
->Type
== MEDIA_DEVICE_PATH
&&
346 LoadedImage
->FilePath
->SubType
== MEDIA_PIWG_FW_FILE_DP
349 // Determine GUID associated with module logging performance
351 ModuleGuidIsGet
= TRUE
;
352 FvFilePath
= (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*) LoadedImage
->FilePath
;
353 TempGuid
= &FvFilePath
->FvFileName
;
357 // Method 1 Get Module Name from PDB string.
359 PdbFileName
= PeCoffLoaderGetPdbPointer (LoadedImage
->ImageBase
);
360 if (PdbFileName
!= NULL
&& BufferSize
> 0) {
362 for (Index
= 0; PdbFileName
[Index
] != 0; Index
++) {
363 if ((PdbFileName
[Index
] == '\\') || (PdbFileName
[Index
] == '/')) {
364 StartIndex
= Index
+ 1;
368 // Copy the PDB file name to our temporary string.
369 // If the length is bigger than BufferSize, trim the redudant characters to avoid overflow in array boundary.
371 for (Index
= 0; Index
< BufferSize
- 1; Index
++) {
372 NameString
[Index
] = PdbFileName
[Index
+ StartIndex
];
373 if (NameString
[Index
] == 0 || NameString
[Index
] == '.') {
374 NameString
[Index
] = 0;
379 if (Index
== BufferSize
- 1) {
380 NameString
[Index
] = 0;
383 // Module Name is got.
389 if (ModuleGuidIsGet
) {
391 // Method 2 Try to get the image's FFS UI section by image GUID
395 Status
= GetSectionFromAnyFv (
397 EFI_SECTION_USER_INTERFACE
,
399 (VOID
**) &StringPtr
,
403 if (!EFI_ERROR (Status
)) {
405 // Method 3. Get the name string from FFS UI section
407 for (Index
= 0; Index
< BufferSize
- 1 && StringPtr
[Index
] != 0; Index
++) {
408 NameString
[Index
] = (CHAR8
) StringPtr
[Index
];
410 NameString
[Index
] = 0;
411 FreePool (StringPtr
);
419 if (ModuleGuid
!= NULL
) {
420 CopyGuid (ModuleGuid
, TempGuid
);
421 if (IsZeroGuid(TempGuid
) && (Handle
!= NULL
) && !ModuleGuidIsGet
) {
423 CopyGuid (ModuleGuid
, (EFI_GUID
*) Handle
);
428 // Cache the Handle and Guid pairs.
430 if (mCachePairCount
< CACHE_HANDLE_GUID_COUNT
) {
431 mCacheHandleGuidTable
[mCachePairCount
].Handle
= Handle
;
432 CopyGuid (&mCacheHandleGuidTable
[mCachePairCount
].ModuleGuid
, ModuleGuid
);
433 AsciiStrCpyS (mCacheHandleGuidTable
[mCachePairCount
].NameString
, FPDT_STRING_EVENT_RECORD_NAME_LENGTH
, NameString
);
441 Copies the string from Source into Destination and updates Length with the
444 @param Destination - destination of the string copy
445 @param Source - pointer to the source string which will get copied
446 @param Length - pointer to a length variable to be updated
450 CopyStringIntoPerfRecordAndUpdateLength (
451 IN OUT CHAR8
*Destination
,
452 IN CONST CHAR8
*Source
,
459 ASSERT (Source
!= NULL
);
461 if (PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly
)) {
462 DestMax
= STRING_SIZE
;
464 DestMax
= AsciiStrSize (Source
);
465 if (DestMax
> STRING_SIZE
) {
466 DestMax
= STRING_SIZE
;
469 StringLen
= AsciiStrLen (Source
);
470 if (StringLen
>= DestMax
) {
471 StringLen
= DestMax
-1;
474 AsciiStrnCpyS(Destination
, DestMax
, Source
, StringLen
);
475 *Length
+= (UINT8
)DestMax
;
481 Create performance record with event description and a timestamp.
483 @param CallerIdentifier - Image handle or pointer to caller ID GUID.
484 @param Guid - Pointer to a GUID.
485 @param String - Pointer to a string describing the measurement.
486 @param Ticker - 64-bit time stamp.
487 @param Address - Pointer to a location in memory relevant to the measurement.
488 @param PerfId - Performance identifier describing the type of measurement.
489 @param Attribute - The attribute of the measurement. According to attribute can create a start
490 record for PERF_START/PERF_START_EX, or a end record for PERF_END/PERF_END_EX,
491 or a general record for other Perf macros.
493 @retval EFI_SUCCESS - Successfully created performance record.
494 @retval EFI_OUT_OF_RESOURCES - Ran out of space to store the records.
495 @retval EFI_INVALID_PARAMETER - Invalid parameter passed to function - NULL
496 pointer or invalid PerfId.
498 @retval EFI_SUCCESS - Successfully created performance record
499 @retval EFI_OUT_OF_RESOURCES - Ran out of space to store the records
500 @retval EFI_INVALID_PARAMETER - Invalid parameter passed to function - NULL
501 pointer or invalid PerfId
506 IN CONST VOID
*CallerIdentifier OPTIONAL
,
507 IN CONST VOID
*Guid OPTIONAL
,
508 IN CONST CHAR8
*String OPTIONAL
,
510 IN UINT64 Address OPTIONAL
,
512 IN PERF_MEASUREMENT_ATTRIBUTE Attribute
518 CHAR8 ModuleName
[FPDT_STRING_EVENT_RECORD_NAME_LENGTH
];
519 FPDT_RECORD_PTR FpdtRecordPtr
;
520 FPDT_RECORD_PTR CachedFpdtRecordPtr
;
522 CONST CHAR8
*StringPtr
;
528 ZeroMem (ModuleName
, sizeof (ModuleName
));
531 // 1. Get the Perf Id for records from PERF_START/PERF_END, PERF_START_EX/PERF_END_EX.
532 // notes: For other Perf macros (Attribute == PerfEntry), their Id is known.
534 if (Attribute
!= PerfEntry
) {
536 // If PERF_START_EX()/PERF_END_EX() have specified the ProgressID,it has high priority.
537 // !!! Note: If the Perf is not the known Token used in the core but have same
538 // ID with the core Token, this case will not be supported.
539 // And in currtnt usage mode, for the unkown ID, there is a general rule:
540 // If it is start pref: the lower 4 bits of the ID should be 0.
541 // If it is end pref: the lower 4 bits of the ID should not be 0.
542 // If input ID doesn't follow the rule, we will adjust it.
544 if ((PerfId
!= 0) && (IsKnownID (PerfId
)) && (!IsKnownTokens (String
))) {
545 return EFI_INVALID_PARAMETER
;
546 } else if ((PerfId
!= 0) && (!IsKnownID (PerfId
)) && (!IsKnownTokens (String
))) {
547 if ((Attribute
== PerfStartEntry
) && ((PerfId
& 0x000F) != 0)) {
549 } else if ((Attribute
== PerfEndEntry
) && ((PerfId
& 0x000F) == 0)) {
555 // Get ProgressID form the String Token.
557 Status
= GetFpdtRecordId (Attribute
, CallerIdentifier
, String
, &ProgressId
);
558 if (EFI_ERROR (Status
)) {
566 // 2. Get the buffer to store the FPDT record.
568 Status
= GetFpdtRecordPtr (FPDT_MAX_PERF_RECORD_SIZE
, &FpdtRecordPtr
);
569 if (EFI_ERROR (Status
)) {
574 // 3. Get the TimeStamp.
577 Ticker
= GetPerformanceCounter ();
578 TimeStamp
= GetTimeInNanoSecond (Ticker
);
579 } else if (Ticker
== 1) {
582 TimeStamp
= GetTimeInNanoSecond (Ticker
);
586 // 4. Fill in the FPDT record according to different Performance Identifier.
589 case MODULE_START_ID
:
591 GetModuleInfoFromHandle ((EFI_HANDLE
)CallerIdentifier
, ModuleName
, sizeof (ModuleName
), &ModuleGuid
);
592 StringPtr
= ModuleName
;
594 // Cache the offset of start image start record and use to update the start image end record if needed.
596 if (PerfId
== MODULE_START_ID
&& Attribute
== PerfEntry
) {
597 mCachedLength
= mSmmBootPerformanceTable
->Header
.Length
;
599 if (!PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly
)) {
600 FpdtRecordPtr
.GuidEvent
->Header
.Type
= FPDT_GUID_EVENT_TYPE
;
601 FpdtRecordPtr
.GuidEvent
->Header
.Length
= sizeof (FPDT_GUID_EVENT_RECORD
);
602 FpdtRecordPtr
.GuidEvent
->Header
.Revision
= FPDT_RECORD_REVISION_1
;
603 FpdtRecordPtr
.GuidEvent
->ProgressID
= PerfId
;
604 FpdtRecordPtr
.GuidEvent
->Timestamp
= TimeStamp
;
605 CopyMem (&FpdtRecordPtr
.GuidEvent
->Guid
, &ModuleGuid
, sizeof (FpdtRecordPtr
.GuidEvent
->Guid
));
606 if (CallerIdentifier
== NULL
&& PerfId
== MODULE_END_ID
&& mCachedLength
!= 0) {
607 CachedFpdtRecordPtr
.RecordHeader
= (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER
*)((UINT8
*)mSmmBootPerformanceTable
+ mCachedLength
);
608 CopyMem (&FpdtRecordPtr
.GuidEvent
->Guid
, &CachedFpdtRecordPtr
.GuidEvent
->Guid
, sizeof (FpdtRecordPtr
.GuidEvent
->Guid
));
614 case MODULE_LOADIMAGE_START_ID
:
615 case MODULE_LOADIMAGE_END_ID
:
616 GetModuleInfoFromHandle ((EFI_HANDLE
)CallerIdentifier
, ModuleName
, sizeof (ModuleName
), &ModuleGuid
);
617 StringPtr
= ModuleName
;
618 if (PerfId
== MODULE_LOADIMAGE_START_ID
) {
621 // Cache the offset of load image start record and use to be updated by the load image end record if needed.
623 if (CallerIdentifier
== NULL
&& Attribute
== PerfEntry
) {
624 mCachedLength
= mSmmBootPerformanceTable
->Header
.Length
;
627 if (!PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly
)) {
628 FpdtRecordPtr
.GuidQwordEvent
->Header
.Type
= FPDT_GUID_QWORD_EVENT_TYPE
;
629 FpdtRecordPtr
.GuidQwordEvent
->Header
.Length
= sizeof (FPDT_GUID_QWORD_EVENT_RECORD
);
630 FpdtRecordPtr
.GuidQwordEvent
->Header
.Revision
= FPDT_RECORD_REVISION_1
;
631 FpdtRecordPtr
.GuidQwordEvent
->ProgressID
= PerfId
;
632 FpdtRecordPtr
.GuidQwordEvent
->Timestamp
= TimeStamp
;
633 FpdtRecordPtr
.GuidQwordEvent
->Qword
= mLoadImageCount
;
634 CopyMem (&FpdtRecordPtr
.GuidQwordEvent
->Guid
, &ModuleGuid
, sizeof (FpdtRecordPtr
.GuidQwordEvent
->Guid
));
635 if (PerfId
== MODULE_LOADIMAGE_END_ID
&& mCachedLength
!= 0) {
636 CachedFpdtRecordPtr
.RecordHeader
= (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER
*)((UINT8
*)mSmmBootPerformanceTable
+ mCachedLength
);
637 CopyMem (&CachedFpdtRecordPtr
.GuidQwordEvent
->Guid
, &ModuleGuid
, sizeof (CachedFpdtRecordPtr
.GuidQwordEvent
->Guid
));
643 case PERF_EVENTSIGNAL_START_ID
:
644 case PERF_EVENTSIGNAL_END_ID
:
645 case PERF_CALLBACK_START_ID
:
646 case PERF_CALLBACK_END_ID
:
647 if (String
== NULL
|| Guid
== NULL
) {
648 return EFI_INVALID_PARAMETER
;
651 if (AsciiStrLen (String
) == 0) {
652 StringPtr
= "unknown name";
654 if (!PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly
)) {
655 FpdtRecordPtr
.DualGuidStringEvent
->Header
.Type
= FPDT_DUAL_GUID_STRING_EVENT_TYPE
;
656 FpdtRecordPtr
.DualGuidStringEvent
->Header
.Length
= sizeof (FPDT_DUAL_GUID_STRING_EVENT_RECORD
);
657 FpdtRecordPtr
.DualGuidStringEvent
->Header
.Revision
= FPDT_RECORD_REVISION_1
;
658 FpdtRecordPtr
.DualGuidStringEvent
->ProgressID
= PerfId
;
659 FpdtRecordPtr
.DualGuidStringEvent
->Timestamp
= TimeStamp
;
660 CopyMem (&FpdtRecordPtr
.DualGuidStringEvent
->Guid1
, CallerIdentifier
, sizeof (FpdtRecordPtr
.DualGuidStringEvent
->Guid1
));
661 CopyMem (&FpdtRecordPtr
.DualGuidStringEvent
->Guid2
, Guid
, sizeof (FpdtRecordPtr
.DualGuidStringEvent
->Guid2
));
662 CopyStringIntoPerfRecordAndUpdateLength (FpdtRecordPtr
.DualGuidStringEvent
->String
, StringPtr
, &FpdtRecordPtr
.DualGuidStringEvent
->Header
.Length
);
667 case PERF_FUNCTION_START_ID
:
668 case PERF_FUNCTION_END_ID
:
669 case PERF_INMODULE_START_ID
:
670 case PERF_INMODULE_END_ID
:
671 case PERF_CROSSMODULE_START_ID
:
672 case PERF_CROSSMODULE_END_ID
:
673 GetModuleInfoFromHandle ((EFI_HANDLE
)CallerIdentifier
, ModuleName
, sizeof (ModuleName
), &ModuleGuid
);
674 if (String
!= NULL
) {
677 StringPtr
= ModuleName
;
679 if (AsciiStrLen (StringPtr
) == 0) {
680 StringPtr
= "unknown name";
682 if (!PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly
)) {
683 FpdtRecordPtr
.DynamicStringEvent
->Header
.Type
= FPDT_DYNAMIC_STRING_EVENT_TYPE
;
684 FpdtRecordPtr
.DynamicStringEvent
->Header
.Length
= sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD
);
685 FpdtRecordPtr
.DynamicStringEvent
->Header
.Revision
= FPDT_RECORD_REVISION_1
;
686 FpdtRecordPtr
.DynamicStringEvent
->ProgressID
= PerfId
;
687 FpdtRecordPtr
.DynamicStringEvent
->Timestamp
= TimeStamp
;
688 CopyMem (&FpdtRecordPtr
.DynamicStringEvent
->Guid
, &ModuleGuid
, sizeof (FpdtRecordPtr
.DynamicStringEvent
->Guid
));
689 CopyStringIntoPerfRecordAndUpdateLength (FpdtRecordPtr
.DynamicStringEvent
->String
, StringPtr
, &FpdtRecordPtr
.DynamicStringEvent
->Header
.Length
);
694 if (Attribute
!= PerfEntry
) {
695 GetModuleInfoFromHandle ((EFI_HANDLE
)CallerIdentifier
, ModuleName
, sizeof (ModuleName
), &ModuleGuid
);
696 if (String
!= NULL
) {
699 StringPtr
= ModuleName
;
701 if (AsciiStrLen (StringPtr
) == 0) {
702 StringPtr
= "unknown name";
704 if (!PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly
)) {
705 FpdtRecordPtr
.DynamicStringEvent
->Header
.Type
= FPDT_DYNAMIC_STRING_EVENT_TYPE
;
706 FpdtRecordPtr
.DynamicStringEvent
->Header
.Length
= sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD
);
707 FpdtRecordPtr
.DynamicStringEvent
->Header
.Revision
= FPDT_RECORD_REVISION_1
;
708 FpdtRecordPtr
.DynamicStringEvent
->ProgressID
= PerfId
;
709 FpdtRecordPtr
.DynamicStringEvent
->Timestamp
= TimeStamp
;
710 CopyMem (&FpdtRecordPtr
.DynamicStringEvent
->Guid
, &ModuleGuid
, sizeof (FpdtRecordPtr
.DynamicStringEvent
->Guid
));
711 CopyStringIntoPerfRecordAndUpdateLength (FpdtRecordPtr
.DynamicStringEvent
->String
, StringPtr
, &FpdtRecordPtr
.DynamicStringEvent
->Header
.Length
);
714 return EFI_INVALID_PARAMETER
;
720 // 4.2 When PcdEdkiiFpdtStringRecordEnableOnly==TRUE, create string record for all Perf entries.
722 if (PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly
)) {
723 if (StringPtr
== NULL
) {
724 return EFI_INVALID_PARAMETER
;
726 FpdtRecordPtr
.DynamicStringEvent
->Header
.Type
= FPDT_DYNAMIC_STRING_EVENT_TYPE
;
727 FpdtRecordPtr
.DynamicStringEvent
->Header
.Length
= sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD
);
728 FpdtRecordPtr
.DynamicStringEvent
->Header
.Revision
= FPDT_RECORD_REVISION_1
;
729 FpdtRecordPtr
.DynamicStringEvent
->ProgressID
= PerfId
;
730 FpdtRecordPtr
.DynamicStringEvent
->Timestamp
= TimeStamp
;
733 // Cache the event guid in string event record.
735 CopyMem (&FpdtRecordPtr
.DynamicStringEvent
->Guid
, Guid
, sizeof (FpdtRecordPtr
.DynamicStringEvent
->Guid
));
737 CopyMem (&FpdtRecordPtr
.DynamicStringEvent
->Guid
, &ModuleGuid
, sizeof (FpdtRecordPtr
.DynamicStringEvent
->Guid
));
739 if (AsciiStrLen (StringPtr
) == 0) {
740 StringPtr
= "unknown name";
742 CopyStringIntoPerfRecordAndUpdateLength (FpdtRecordPtr
.DynamicStringEvent
->String
, StringPtr
, &FpdtRecordPtr
.DynamicStringEvent
->Header
.Length
);
744 if ((PerfId
== MODULE_LOADIMAGE_START_ID
) || (PerfId
== MODULE_END_ID
)) {
745 FpdtRecordPtr
.DynamicStringEvent
->Header
.Length
= (UINT8
)(sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD
)+ STRING_SIZE
);
747 if ((PerfId
== MODULE_LOADIMAGE_END_ID
|| PerfId
== MODULE_END_ID
) && mCachedLength
!= 0) {
748 CachedFpdtRecordPtr
.RecordHeader
= (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER
*)((UINT8
*)mSmmBootPerformanceTable
+ mCachedLength
);
749 if (PerfId
== MODULE_LOADIMAGE_END_ID
) {
750 DestMax
= CachedFpdtRecordPtr
.DynamicStringEvent
->Header
.Length
- sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD
);
751 StringLen
= AsciiStrLen (StringPtr
);
752 if (StringLen
>= DestMax
) {
753 StringLen
= DestMax
-1;
755 CopyMem (&CachedFpdtRecordPtr
.DynamicStringEvent
->Guid
, &ModuleGuid
, sizeof (CachedFpdtRecordPtr
.DynamicStringEvent
->Guid
));
756 AsciiStrnCpyS (CachedFpdtRecordPtr
.DynamicStringEvent
->String
, DestMax
, StringPtr
, StringLen
);
757 } else if (PerfId
== MODULE_END_ID
) {
758 DestMax
= FpdtRecordPtr
.DynamicStringEvent
->Header
.Length
- sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD
);
759 StringLen
= AsciiStrLen (CachedFpdtRecordPtr
.DynamicStringEvent
->String
);
760 if (StringLen
>= DestMax
) {
761 StringLen
= DestMax
-1;
763 CopyMem (&FpdtRecordPtr
.DynamicStringEvent
->Guid
, &CachedFpdtRecordPtr
.DynamicStringEvent
->Guid
, sizeof (CachedFpdtRecordPtr
.DynamicStringEvent
->Guid
));
764 AsciiStrnCpyS (FpdtRecordPtr
.DynamicStringEvent
->String
, DestMax
, CachedFpdtRecordPtr
.DynamicStringEvent
->String
, StringLen
);
771 // 5. Update the length of the used buffer after fill in the record.
773 mPerformanceLength
+= FpdtRecordPtr
.RecordHeader
->Length
;
774 mSmmBootPerformanceTable
->Header
.Length
+= FpdtRecordPtr
.RecordHeader
->Length
;
780 Communication service SMI Handler entry.
782 This SMI handler provides services for report MM boot records.
784 Caution: This function may receive untrusted input.
785 Communicate buffer and buffer size are external input, so this function will do basic validation.
787 @param[in] DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().
788 @param[in] RegisterContext Points to an optional handler context which was specified when the
789 handler was registered.
790 @param[in, out] CommBuffer A pointer to a collection of data in memory that will
791 be conveyed from a non-MM environment into an MM environment.
792 @param[in, out] CommBufferSize The size of the CommBuffer.
794 @retval EFI_SUCCESS The interrupt was handled and quiesced. No other handlers
795 should still be called.
796 @retval EFI_WARN_INTERRUPT_SOURCE_QUIESCED The interrupt has been quiesced but other handlers should
798 @retval EFI_WARN_INTERRUPT_SOURCE_PENDING The interrupt is still pending and other handlers should still
800 @retval EFI_INTERRUPT_PENDING The interrupt could not be quiesced.
806 IN EFI_HANDLE DispatchHandle
,
807 IN CONST VOID
*RegisterContext
,
808 IN OUT VOID
*CommBuffer
,
809 IN OUT UINTN
*CommBufferSize
813 SMM_BOOT_RECORD_COMMUNICATE
*SmmCommData
;
814 UINTN BootRecordOffset
;
815 UINTN BootRecordSize
;
816 VOID
*BootRecordData
;
817 UINTN TempCommBufferSize
;
818 UINT8
*BootRecordBuffer
;
821 // If input is invalid, stop processing this SMI
823 if (CommBuffer
== NULL
|| CommBufferSize
== NULL
) {
827 TempCommBufferSize
= *CommBufferSize
;
829 if(TempCommBufferSize
< sizeof (SMM_BOOT_RECORD_COMMUNICATE
)) {
833 if (!SmmIsBufferOutsideSmmValid ((UINTN
)CommBuffer
, TempCommBufferSize
)) {
834 DEBUG ((DEBUG_ERROR
, "FpdtSmiHandler: MM communication data buffer in MMRAM or overflow!\n"));
838 SmmCommData
= (SMM_BOOT_RECORD_COMMUNICATE
*)CommBuffer
;
840 Status
= EFI_SUCCESS
;
842 switch (SmmCommData
->Function
) {
843 case SMM_FPDT_FUNCTION_GET_BOOT_RECORD_SIZE
:
844 if (mSmmBootPerformanceTable
!= NULL
) {
845 mBootRecordSize
= mSmmBootPerformanceTable
->Header
.Length
- sizeof (SMM_BOOT_PERFORMANCE_TABLE
);
847 SmmCommData
->BootRecordSize
= mBootRecordSize
;
850 case SMM_FPDT_FUNCTION_GET_BOOT_RECORD_DATA
:
851 Status
= EFI_UNSUPPORTED
;
854 case SMM_FPDT_FUNCTION_GET_BOOT_RECORD_DATA_BY_OFFSET
:
855 BootRecordOffset
= SmmCommData
->BootRecordOffset
;
856 BootRecordData
= SmmCommData
->BootRecordData
;
857 BootRecordSize
= SmmCommData
->BootRecordSize
;
858 if (BootRecordData
== NULL
|| BootRecordOffset
>= mBootRecordSize
) {
859 Status
= EFI_INVALID_PARAMETER
;
866 if (BootRecordSize
> mBootRecordSize
- BootRecordOffset
) {
867 BootRecordSize
= mBootRecordSize
- BootRecordOffset
;
869 SmmCommData
->BootRecordSize
= BootRecordSize
;
870 if (!SmmIsBufferOutsideSmmValid ((UINTN
)BootRecordData
, BootRecordSize
)) {
871 DEBUG ((DEBUG_ERROR
, "FpdtSmiHandler: MM Data buffer in MMRAM or overflow!\n"));
872 Status
= EFI_ACCESS_DENIED
;
875 BootRecordBuffer
= ((UINT8
*) (mSmmBootPerformanceTable
)) + sizeof (SMM_BOOT_PERFORMANCE_TABLE
);
877 (UINT8
*)BootRecordData
,
878 BootRecordBuffer
+ BootRecordOffset
,
881 mFpdtDataIsReported
= TRUE
;
885 Status
= EFI_UNSUPPORTED
;
888 SmmCommData
->ReturnStatus
= Status
;
894 SmmBase2 protocol notify callback function, when SMST and SMM memory service get initialized
895 this function is callbacked to initialize the Smm Performance Lib
897 @param Event The event of notify protocol.
898 @param Context Notify event context.
903 InitializeSmmCorePerformanceLib (
909 EFI_HANDLE SmiHandle
;
911 PERFORMANCE_PROPERTY
*PerformanceProperty
;
914 // Initialize spin lock
916 InitializeSpinLock (&mSmmFpdtLock
);
919 // Install the protocol interfaces for SMM performance library instance.
922 Status
= gSmst
->SmmInstallProtocolInterface (
924 &gEdkiiSmmPerformanceMeasurementProtocolGuid
,
925 EFI_NATIVE_INTERFACE
,
926 &mPerformanceMeasurementInterface
928 ASSERT_EFI_ERROR (Status
);
931 // Register SMI handler.
934 Status
= gSmst
->SmiHandlerRegister (FpdtSmiHandler
, &gEfiFirmwarePerformanceGuid
, &SmiHandle
);
935 ASSERT_EFI_ERROR (Status
);
937 Status
= EfiGetSystemConfigurationTable (&gPerformanceProtocolGuid
, (VOID
**) &PerformanceProperty
);
938 if (EFI_ERROR (Status
)) {
940 // Install configuration table for performance property.
942 mPerformanceProperty
.Revision
= PERFORMANCE_PROPERTY_REVISION
;
943 mPerformanceProperty
.Reserved
= 0;
944 mPerformanceProperty
.Frequency
= GetPerformanceCounterProperties (
945 &mPerformanceProperty
.TimerStartValue
,
946 &mPerformanceProperty
.TimerEndValue
948 Status
= gBS
->InstallConfigurationTable (&gPerformanceProtocolGuid
, &mPerformanceProperty
);
949 ASSERT_EFI_ERROR (Status
);
954 The constructor function initializes the Performance Measurement Enable flag and
955 registers SmmBase2 protocol notify callback.
956 It will ASSERT() if one of these operations fails and it will always return EFI_SUCCESS.
958 @param ImageHandle The firmware allocated handle for the EFI image.
959 @param SystemTable A pointer to the EFI System Table.
961 @retval EFI_SUCCESS The constructor always returns EFI_SUCCESS.
966 SmmCorePerformanceLibConstructor (
967 IN EFI_HANDLE ImageHandle
,
968 IN EFI_SYSTEM_TABLE
*SystemTable
975 if (!PerformanceMeasurementEnabled ()) {
977 // Do not initialize performance infrastructure if not required.
983 // Create the events to do the library init.
985 Status
= gBS
->CreateEvent (
988 InitializeSmmCorePerformanceLib
,
992 ASSERT_EFI_ERROR (Status
);
995 // Register for protocol notifications on this event
997 Status
= gBS
->RegisterProtocolNotify (
998 &gEfiSmmBase2ProtocolGuid
,
1003 ASSERT_EFI_ERROR (Status
);
1009 Create performance record with event description and a timestamp.
1011 @param CallerIdentifier - Image handle or pointer to caller ID GUID.
1012 @param Guid - Pointer to a GUID.
1013 @param String - Pointer to a string describing the measurement.
1014 @param TimeStamp - 64-bit time stamp.
1015 @param Address - Pointer to a location in memory relevant to the measurement.
1016 @param Identifier - Performance identifier describing the type of measurement.
1017 @param Attribute - The attribute of the measurement. According to attribute can create a start
1018 record for PERF_START/PERF_START_EX, or a end record for PERF_END/PERF_END_EX,
1019 or a general record for other Perf macros.
1021 @retval EFI_SUCCESS - Successfully created performance record.
1022 @retval EFI_OUT_OF_RESOURCES - Ran out of space to store the records.
1023 @retval EFI_INVALID_PARAMETER - Invalid parameter passed to function - NULL
1024 pointer or invalid PerfId.
1028 CreatePerformanceMeasurement(
1029 IN CONST VOID
*CallerIdentifier OPTIONAL
,
1030 IN CONST VOID
*Guid OPTIONAL
,
1031 IN CONST CHAR8
*String OPTIONAL
,
1032 IN UINT64 TimeStamp OPTIONAL
,
1033 IN UINT64 Address OPTIONAL
,
1034 IN UINT32 Identifier
,
1035 IN PERF_MEASUREMENT_ATTRIBUTE Attribute
1040 Status
= EFI_SUCCESS
;
1042 AcquireSpinLock (&mSmmFpdtLock
);
1043 Status
= InsertFpdtRecord (CallerIdentifier
, Guid
, String
, TimeStamp
, Address
, (UINT16
)Identifier
, Attribute
);
1044 ReleaseSpinLock (&mSmmFpdtLock
);
1049 Adds a record at the end of the performance measurement log
1050 that records the start time of a performance measurement.
1052 Adds a record to the end of the performance measurement log
1053 that contains the Handle, Token, Module and Identifier.
1054 The end time of the new record must be set to zero.
1055 If TimeStamp is not zero, then TimeStamp is used to fill in the start time in the record.
1056 If TimeStamp is zero, the start time in the record is filled in with the value
1057 read from the current time stamp.
1059 @param Handle Pointer to environment specific context used
1060 to identify the component being measured.
1061 @param Token Pointer to a Null-terminated ASCII string
1062 that identifies the component being measured.
1063 @param Module Pointer to a Null-terminated ASCII string
1064 that identifies the module being measured.
1065 @param TimeStamp 64-bit time stamp.
1066 @param Identifier 32-bit identifier. If the value is 0, the created record
1067 is same as the one created by StartPerformanceMeasurement.
1069 @retval RETURN_SUCCESS The start of the measurement was recorded.
1070 @retval RETURN_OUT_OF_RESOURCES There are not enough resources to record the measurement.
1075 StartPerformanceMeasurementEx (
1076 IN CONST VOID
*Handle OPTIONAL
,
1077 IN CONST CHAR8
*Token OPTIONAL
,
1078 IN CONST CHAR8
*Module OPTIONAL
,
1079 IN UINT64 TimeStamp
,
1080 IN UINT32 Identifier
1083 CONST CHAR8
*String
;
1085 if (Token
!= NULL
) {
1087 } else if (Module
!= NULL
) {
1093 return (RETURN_STATUS
)CreatePerformanceMeasurement (Handle
, NULL
, String
, TimeStamp
, 0, Identifier
, PerfStartEntry
);
1097 Searches the performance measurement log from the beginning of the log
1098 for the first matching record that contains a zero end time and fills in a valid end time.
1100 Searches the performance measurement log from the beginning of the log
1101 for the first record that matches Handle, Token, Module and Identifier and has an end time value of zero.
1102 If the record can not be found then return RETURN_NOT_FOUND.
1103 If the record is found and TimeStamp is not zero,
1104 then the end time in the record is filled in with the value specified by TimeStamp.
1105 If the record is found and TimeStamp is zero, then the end time in the matching record
1106 is filled in with the current time stamp value.
1108 @param Handle Pointer to environment specific context used
1109 to identify the component being measured.
1110 @param Token Pointer to a Null-terminated ASCII string
1111 that identifies the component being measured.
1112 @param Module Pointer to a Null-terminated ASCII string
1113 that identifies the module being measured.
1114 @param TimeStamp 64-bit time stamp.
1115 @param Identifier 32-bit identifier. If the value is 0, the found record
1116 is same as the one found by EndPerformanceMeasurement.
1118 @retval RETURN_SUCCESS The end of the measurement was recorded.
1119 @retval RETURN_NOT_FOUND The specified measurement record could not be found.
1124 EndPerformanceMeasurementEx (
1125 IN CONST VOID
*Handle OPTIONAL
,
1126 IN CONST CHAR8
*Token OPTIONAL
,
1127 IN CONST CHAR8
*Module OPTIONAL
,
1128 IN UINT64 TimeStamp
,
1129 IN UINT32 Identifier
1132 CONST CHAR8
*String
;
1134 if (Token
!= NULL
) {
1136 } else if (Module
!= NULL
) {
1142 return (RETURN_STATUS
)CreatePerformanceMeasurement (Handle
, NULL
, String
, TimeStamp
, 0, Identifier
, PerfEndEntry
);
1146 Attempts to retrieve a performance measurement log entry from the performance measurement log.
1147 It can also retrieve the log created by StartPerformanceMeasurement and EndPerformanceMeasurement,
1148 and then assign the Identifier with 0.
1152 Attempts to retrieve the performance log entry specified by LogEntryKey. If LogEntryKey is
1153 zero on entry, then an attempt is made to retrieve the first entry from the performance log,
1154 and the key for the second entry in the log is returned. If the performance log is empty,
1155 then no entry is retrieved and zero is returned. If LogEntryKey is not zero, then the performance
1156 log entry associated with LogEntryKey is retrieved, and the key for the next entry in the log is
1157 returned. If LogEntryKey is the key for the last entry in the log, then the last log entry is
1158 retrieved and an implementation specific non-zero key value that specifies the end of the performance
1159 log is returned. If LogEntryKey is equal this implementation specific non-zero key value, then no entry
1160 is retrieved and zero is returned. In the cases where a performance log entry can be returned,
1161 the log entry is returned in Handle, Token, Module, StartTimeStamp, EndTimeStamp and Identifier.
1162 If LogEntryKey is not a valid log entry key for the performance measurement log, then ASSERT().
1163 If Handle is NULL, then ASSERT().
1164 If Token is NULL, then ASSERT().
1165 If Module is NULL, then ASSERT().
1166 If StartTimeStamp is NULL, then ASSERT().
1167 If EndTimeStamp is NULL, then ASSERT().
1168 If Identifier is NULL, then ASSERT().
1170 @param LogEntryKey On entry, the key of the performance measurement log entry to retrieve.
1171 0, then the first performance measurement log entry is retrieved.
1172 On exit, the key of the next performance log entry.
1173 @param Handle Pointer to environment specific context used to identify the component
1175 @param Token Pointer to a Null-terminated ASCII string that identifies the component
1177 @param Module Pointer to a Null-terminated ASCII string that identifies the module
1179 @param StartTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement
1181 @param EndTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement
1183 @param Identifier Pointer to the 32-bit identifier that was recorded.
1185 @return The key for the next performance log entry (in general case).
1190 GetPerformanceMeasurementEx (
1191 IN UINTN LogEntryKey
,
1192 OUT CONST VOID
**Handle
,
1193 OUT CONST CHAR8
**Token
,
1194 OUT CONST CHAR8
**Module
,
1195 OUT UINT64
*StartTimeStamp
,
1196 OUT UINT64
*EndTimeStamp
,
1197 OUT UINT32
*Identifier
1204 Adds a record at the end of the performance measurement log
1205 that records the start time of a performance measurement.
1207 Adds a record to the end of the performance measurement log
1208 that contains the Handle, Token, and Module.
1209 The end time of the new record must be set to zero.
1210 If TimeStamp is not zero, then TimeStamp is used to fill in the start time in the record.
1211 If TimeStamp is zero, the start time in the record is filled in with the value
1212 read from the current time stamp.
1214 @param Handle Pointer to environment specific context used
1215 to identify the component being measured.
1216 @param Token Pointer to a Null-terminated ASCII string
1217 that identifies the component being measured.
1218 @param Module Pointer to a Null-terminated ASCII string
1219 that identifies the module being measured.
1220 @param TimeStamp 64-bit time stamp.
1222 @retval RETURN_SUCCESS The start of the measurement was recorded.
1223 @retval RETURN_OUT_OF_RESOURCES There are not enough resources to record the measurement.
1228 StartPerformanceMeasurement (
1229 IN CONST VOID
*Handle OPTIONAL
,
1230 IN CONST CHAR8
*Token OPTIONAL
,
1231 IN CONST CHAR8
*Module OPTIONAL
,
1235 return StartPerformanceMeasurementEx (Handle
, Token
, Module
, TimeStamp
, 0);
1239 Searches the performance measurement log from the beginning of the log
1240 for the first matching record that contains a zero end time and fills in a valid end time.
1242 Searches the performance measurement log from the beginning of the log
1243 for the first record that matches Handle, Token, and Module and has an end time value of zero.
1244 If the record can not be found then return RETURN_NOT_FOUND.
1245 If the record is found and TimeStamp is not zero,
1246 then the end time in the record is filled in with the value specified by TimeStamp.
1247 If the record is found and TimeStamp is zero, then the end time in the matching record
1248 is filled in with the current time stamp value.
1250 @param Handle Pointer to environment specific context used
1251 to identify the component being measured.
1252 @param Token Pointer to a Null-terminated ASCII string
1253 that identifies the component being measured.
1254 @param Module Pointer to a Null-terminated ASCII string
1255 that identifies the module being measured.
1256 @param TimeStamp 64-bit time stamp.
1258 @retval RETURN_SUCCESS The end of the measurement was recorded.
1259 @retval RETURN_NOT_FOUND The specified measurement record could not be found.
1264 EndPerformanceMeasurement (
1265 IN CONST VOID
*Handle OPTIONAL
,
1266 IN CONST CHAR8
*Token OPTIONAL
,
1267 IN CONST CHAR8
*Module OPTIONAL
,
1271 return EndPerformanceMeasurementEx (Handle
, Token
, Module
, TimeStamp
, 0);
1275 Attempts to retrieve a performance measurement log entry from the performance measurement log.
1276 It can also retrieve the log created by StartPerformanceMeasurementEx and EndPerformanceMeasurementEx,
1277 and then eliminate the Identifier.
1281 Attempts to retrieve the performance log entry specified by LogEntryKey. If LogEntryKey is
1282 zero on entry, then an attempt is made to retrieve the first entry from the performance log,
1283 and the key for the second entry in the log is returned. If the performance log is empty,
1284 then no entry is retrieved and zero is returned. If LogEntryKey is not zero, then the performance
1285 log entry associated with LogEntryKey is retrieved, and the key for the next entry in the log is
1286 returned. If LogEntryKey is the key for the last entry in the log, then the last log entry is
1287 retrieved and an implementation specific non-zero key value that specifies the end of the performance
1288 log is returned. If LogEntryKey is equal this implementation specific non-zero key value, then no entry
1289 is retrieved and zero is returned. In the cases where a performance log entry can be returned,
1290 the log entry is returned in Handle, Token, Module, StartTimeStamp, and EndTimeStamp.
1291 If LogEntryKey is not a valid log entry key for the performance measurement log, then ASSERT().
1292 If Handle is NULL, then ASSERT().
1293 If Token is NULL, then ASSERT().
1294 If Module is NULL, then ASSERT().
1295 If StartTimeStamp is NULL, then ASSERT().
1296 If EndTimeStamp is NULL, then ASSERT().
1298 @param LogEntryKey On entry, the key of the performance measurement log entry to retrieve.
1299 0, then the first performance measurement log entry is retrieved.
1300 On exit, the key of the next performance log entry.
1301 @param Handle Pointer to environment specific context used to identify the component
1303 @param Token Pointer to a Null-terminated ASCII string that identifies the component
1305 @param Module Pointer to a Null-terminated ASCII string that identifies the module
1307 @param StartTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement
1309 @param EndTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement
1312 @return The key for the next performance log entry (in general case).
1317 GetPerformanceMeasurement (
1318 IN UINTN LogEntryKey
,
1319 OUT CONST VOID
**Handle
,
1320 OUT CONST CHAR8
**Token
,
1321 OUT CONST CHAR8
**Module
,
1322 OUT UINT64
*StartTimeStamp
,
1323 OUT UINT64
*EndTimeStamp
1330 Returns TRUE if the performance measurement macros are enabled.
1332 This function returns TRUE if the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of
1333 PcdPerformanceLibraryPropertyMask is set. Otherwise FALSE is returned.
1335 @retval TRUE The PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of
1336 PcdPerformanceLibraryPropertyMask is set.
1337 @retval FALSE The PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of
1338 PcdPerformanceLibraryPropertyMask is clear.
1343 PerformanceMeasurementEnabled (
1347 return (BOOLEAN
) ((PcdGet8(PcdPerformanceLibraryPropertyMask
) & PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED
) != 0);
1351 Create performance record with event description and a timestamp.
1353 @param CallerIdentifier - Image handle or pointer to caller ID GUID
1354 @param Guid - Pointer to a GUID
1355 @param String - Pointer to a string describing the measurement
1356 @param Address - Pointer to a location in memory relevant to the measurement
1357 @param Identifier - Performance identifier describing the type of measurement
1359 @retval RETURN_SUCCESS - Successfully created performance record
1360 @retval RETURN_OUT_OF_RESOURCES - Ran out of space to store the records
1361 @retval RETURN_INVALID_PARAMETER - Invalid parameter passed to function - NULL
1362 pointer or invalid PerfId
1367 LogPerformanceMeasurement (
1368 IN CONST VOID
*CallerIdentifier
,
1369 IN CONST VOID
*Guid OPTIONAL
,
1370 IN CONST CHAR8
*String OPTIONAL
,
1371 IN UINT64 Address OPTIONAL
,
1372 IN UINT32 Identifier
1375 return (RETURN_STATUS
)CreatePerformanceMeasurement (CallerIdentifier
, Guid
, String
, 0, Address
, Identifier
, PerfEntry
);
1379 Check whether the specified performance measurement can be logged.
1381 This function returns TRUE when the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of PcdPerformanceLibraryPropertyMask is set
1382 and the Type disable bit in PcdPerformanceLibraryPropertyMask is not set.
1384 @param Type - Type of the performance measurement entry.
1386 @retval TRUE The performance measurement can be logged.
1387 @retval FALSE The performance measurement can NOT be logged.
1392 LogPerformanceMeasurementEnabled (
1397 // When Performance measurement is enabled and the type is not filtered, the performance can be logged.
1399 if (PerformanceMeasurementEnabled () && (PcdGet8(PcdPerformanceLibraryPropertyMask
) & Type
) == 0) {