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
24 #include "SmmCorePerformanceLibInternal.h"
26 #define STRING_SIZE (FPDT_STRING_EVENT_RECORD_NAME_LENGTH * sizeof (CHAR8))
27 #define FIRMWARE_RECORD_BUFFER 0x1000
28 #define CACHE_HANDLE_GUID_COUNT 0x100
30 SMM_BOOT_PERFORMANCE_TABLE
*mSmmBootPerformanceTable
= NULL
;
34 CHAR8 NameString
[FPDT_STRING_EVENT_RECORD_NAME_LENGTH
];
38 HANDLE_GUID_MAP mCacheHandleGuidTable
[CACHE_HANDLE_GUID_COUNT
];
39 UINTN mCachePairCount
= 0;
41 UINT32 mPerformanceLength
= sizeof (SMM_BOOT_PERFORMANCE_TABLE
);
42 UINT32 mMaxPerformanceLength
= 0;
43 UINT32 mLoadImageCount
= 0;
44 BOOLEAN mFpdtDataIsReported
= FALSE
;
45 BOOLEAN mLackSpaceIsReport
= FALSE
;
46 CHAR8
*mPlatformLanguage
= NULL
;
47 SPIN_LOCK mSmmFpdtLock
;
48 PERFORMANCE_PROPERTY mPerformanceProperty
;
49 UINT32 mCachedLength
= 0;
50 UINT32 mBootRecordSize
= 0;
53 // Interfaces for SMM PerformanceMeasurement Protocol.
55 EDKII_PERFORMANCE_MEASUREMENT_PROTOCOL mPerformanceMeasurementInterface
= {
56 CreatePerformanceMeasurement
,
60 Return the pointer to the FPDT record in the allocated memory.
62 @param RecordSize The size of FPDT record.
63 @param FpdtRecordPtr Pointer the FPDT record in the allocated memory.
65 @retval EFI_SUCCESS Successfully get the pointer to the FPDT record.
66 @retval EFI_OUT_OF_RESOURCES Ran out of space to store the records.
71 IN OUT FPDT_RECORD_PTR
*FpdtRecordPtr
74 if (mFpdtDataIsReported
) {
76 // Append Boot records after Smm boot performance records have been reported.
78 if (mPerformanceLength
+ RecordSize
> mMaxPerformanceLength
) {
79 if (!mLackSpaceIsReport
) {
80 DEBUG ((DEBUG_INFO
, "SmmCorePerformanceLib: No enough space to save boot records\n"));
81 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
;
106 mSmmBootPerformanceTable
->Header
.Length
= mPerformanceLength
;
107 mMaxPerformanceLength
= mPerformanceLength
+ RecordSize
+ FIRMWARE_RECORD_BUFFER
;
111 // Covert buffer to FPDT Ptr Union type.
113 FpdtRecordPtr
->RecordHeader
= (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER
*)((UINT8
*)mSmmBootPerformanceTable
+ mSmmBootPerformanceTable
->Header
.Length
);
116 FpdtRecordPtr
->RecordHeader
->Length
= 0;
121 Check whether the Token is a known one which is uesed by core.
123 @param Token Pointer to a Null-terminated ASCII string
125 @retval TRUE Is a known one used by core.
126 @retval FALSE Not a known one.
131 IN CONST CHAR8
*Token
138 if ((AsciiStrCmp (Token
, SEC_TOK
) == 0) ||
139 (AsciiStrCmp (Token
, PEI_TOK
) == 0) ||
140 (AsciiStrCmp (Token
, DXE_TOK
) == 0) ||
141 (AsciiStrCmp (Token
, BDS_TOK
) == 0) ||
142 (AsciiStrCmp (Token
, DRIVERBINDING_START_TOK
) == 0) ||
143 (AsciiStrCmp (Token
, DRIVERBINDING_SUPPORT_TOK
) == 0) ||
144 (AsciiStrCmp (Token
, DRIVERBINDING_STOP_TOK
) == 0) ||
145 (AsciiStrCmp (Token
, LOAD_IMAGE_TOK
) == 0) ||
146 (AsciiStrCmp (Token
, START_IMAGE_TOK
) == 0) ||
147 (AsciiStrCmp (Token
, PEIM_TOK
) == 0))
156 Check whether the ID is a known one which map to the known Token.
158 @param Identifier 32-bit identifier.
160 @retval TRUE Is a known one used by core.
161 @retval FALSE Not a known one.
169 if ((Identifier
== MODULE_START_ID
) ||
170 (Identifier
== MODULE_END_ID
) ||
171 (Identifier
== MODULE_LOADIMAGE_START_ID
) ||
172 (Identifier
== MODULE_LOADIMAGE_END_ID
) ||
173 (Identifier
== MODULE_DB_START_ID
) ||
174 (Identifier
== MODULE_DB_END_ID
) ||
175 (Identifier
== MODULE_DB_SUPPORT_START_ID
) ||
176 (Identifier
== MODULE_DB_SUPPORT_END_ID
) ||
177 (Identifier
== MODULE_DB_STOP_START_ID
) ||
178 (Identifier
== MODULE_DB_STOP_END_ID
))
187 Get the FPDT record identifier.
189 @param Attribute The attribute of the Record.
190 PerfStartEntry: Start Record.
191 PerfEndEntry: End Record.
192 @param Handle Pointer to environment specific context used to identify the component being measured.
193 @param String Pointer to a Null-terminated ASCII string that identifies the component being measured.
194 @param ProgressID On return, pointer to the ProgressID.
196 @retval EFI_SUCCESS Get record info successfully.
197 @retval EFI_INVALID_PARAMETER No matched FPDT record.
202 IN PERF_MEASUREMENT_ATTRIBUTE Attribute
,
203 IN CONST VOID
*Handle
,
204 IN CONST CHAR8
*String
,
205 OUT UINT16
*ProgressID
211 if (String
!= NULL
) {
212 if (AsciiStrCmp (String
, START_IMAGE_TOK
) == 0) {
214 if (Attribute
== PerfStartEntry
) {
215 *ProgressID
= MODULE_START_ID
;
217 *ProgressID
= MODULE_END_ID
;
219 } else if (AsciiStrCmp (String
, LOAD_IMAGE_TOK
) == 0) {
221 if (Attribute
== PerfStartEntry
) {
222 *ProgressID
= MODULE_LOADIMAGE_START_ID
;
224 *ProgressID
= MODULE_LOADIMAGE_END_ID
;
227 // Pref used in Modules
228 if (Attribute
== PerfStartEntry
) {
229 *ProgressID
= PERF_INMODULE_START_ID
;
231 *ProgressID
= PERF_INMODULE_END_ID
;
234 } else if (Handle
!= NULL
) {
235 // Pref used in Modules
236 if (Attribute
== PerfStartEntry
) {
237 *ProgressID
= PERF_INMODULE_START_ID
;
239 *ProgressID
= PERF_INMODULE_END_ID
;
242 return EFI_UNSUPPORTED
;
249 Get a human readable module name and module guid for the given image handle.
250 If module name can't be found, "" string will return.
251 If module guid can't be found, Zero Guid will return.
253 @param Handle Image handle or Controller handle.
254 @param NameString The ascii string will be filled into it. If not found, null string will return.
255 @param BufferSize Size of the input NameString buffer.
256 @param ModuleGuid Point to the guid buffer to store the got module guid value.
258 @retval EFI_SUCCESS Successfully get module name and guid.
259 @retval EFI_INVALID_PARAMETER The input parameter NameString is NULL.
260 @retval other value Module Name can't be got.
264 GetModuleInfoFromHandle (
265 IN EFI_HANDLE Handle
,
266 OUT CHAR8
*NameString
,
268 OUT EFI_GUID
*ModuleGuid OPTIONAL
272 EFI_LOADED_IMAGE_PROTOCOL
*LoadedImage
;
273 EFI_DRIVER_BINDING_PROTOCOL
*DriverBinding
;
279 BOOLEAN ModuleGuidIsGet
;
282 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*FvFilePath
;
284 if ((NameString
== NULL
) || (BufferSize
== 0)) {
285 return EFI_INVALID_PARAMETER
;
289 // Try to get the ModuleGuid and name string form the caached array.
291 if (mCachePairCount
> 0) {
292 for (Count
= mCachePairCount
- 1; Count
>= 0; Count
--) {
293 if (Handle
== mCacheHandleGuidTable
[Count
].Handle
) {
294 CopyGuid (ModuleGuid
, &mCacheHandleGuidTable
[Count
].ModuleGuid
);
295 AsciiStrCpyS (NameString
, FPDT_STRING_EVENT_RECORD_NAME_LENGTH
, mCacheHandleGuidTable
[Count
].NameString
);
301 Status
= EFI_INVALID_PARAMETER
;
303 ModuleGuidIsGet
= FALSE
;
306 // Initialize GUID as zero value.
308 TempGuid
= &gZeroGuid
;
310 // Initialize it as "" string.
314 if (Handle
!= NULL
) {
316 // Try Handle as ImageHandle.
318 Status
= gBS
->HandleProtocol (
320 &gEfiLoadedImageProtocolGuid
,
321 (VOID
**)&LoadedImage
324 if (EFI_ERROR (Status
)) {
326 // Try Handle as Controller Handle
328 Status
= gBS
->OpenProtocol (
330 &gEfiDriverBindingProtocolGuid
,
331 (VOID
**)&DriverBinding
,
334 EFI_OPEN_PROTOCOL_GET_PROTOCOL
336 if (!EFI_ERROR (Status
)) {
338 // Get Image protocol from ImageHandle
340 Status
= gBS
->HandleProtocol (
341 DriverBinding
->ImageHandle
,
342 &gEfiLoadedImageProtocolGuid
,
343 (VOID
**)&LoadedImage
349 if (!EFI_ERROR (Status
) && (LoadedImage
!= NULL
)) {
351 // Get Module Guid from DevicePath.
353 if ((LoadedImage
->FilePath
!= NULL
) &&
354 (LoadedImage
->FilePath
->Type
== MEDIA_DEVICE_PATH
) &&
355 (LoadedImage
->FilePath
->SubType
== MEDIA_PIWG_FW_FILE_DP
)
359 // Determine GUID associated with module logging performance
361 ModuleGuidIsGet
= TRUE
;
362 FvFilePath
= (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*)LoadedImage
->FilePath
;
363 TempGuid
= &FvFilePath
->FvFileName
;
367 // Method 1 Get Module Name from PDB string.
369 PdbFileName
= PeCoffLoaderGetPdbPointer (LoadedImage
->ImageBase
);
370 if ((PdbFileName
!= NULL
) && (BufferSize
> 0)) {
372 for (Index
= 0; PdbFileName
[Index
] != 0; Index
++) {
373 if ((PdbFileName
[Index
] == '\\') || (PdbFileName
[Index
] == '/')) {
374 StartIndex
= Index
+ 1;
379 // Copy the PDB file name to our temporary string.
380 // If the length is bigger than BufferSize, trim the redudant characters to avoid overflow in array boundary.
382 for (Index
= 0; Index
< BufferSize
- 1; Index
++) {
383 NameString
[Index
] = PdbFileName
[Index
+ StartIndex
];
384 if ((NameString
[Index
] == 0) || (NameString
[Index
] == '.')) {
385 NameString
[Index
] = 0;
390 if (Index
== BufferSize
- 1) {
391 NameString
[Index
] = 0;
395 // Module Name is got.
401 if (ModuleGuidIsGet
) {
403 // Method 2 Try to get the image's FFS UI section by image GUID
407 Status
= GetSectionFromAnyFv (
409 EFI_SECTION_USER_INTERFACE
,
415 if (!EFI_ERROR (Status
)) {
417 // Method 3. Get the name string from FFS UI section
419 for (Index
= 0; Index
< BufferSize
- 1 && StringPtr
[Index
] != 0; Index
++) {
420 NameString
[Index
] = (CHAR8
)StringPtr
[Index
];
423 NameString
[Index
] = 0;
424 FreePool (StringPtr
);
432 if (ModuleGuid
!= NULL
) {
433 CopyGuid (ModuleGuid
, TempGuid
);
434 if (IsZeroGuid (TempGuid
) && (Handle
!= NULL
) && !ModuleGuidIsGet
) {
436 CopyGuid (ModuleGuid
, (EFI_GUID
*)Handle
);
441 // Cache the Handle and Guid pairs.
443 if (mCachePairCount
< CACHE_HANDLE_GUID_COUNT
) {
444 mCacheHandleGuidTable
[mCachePairCount
].Handle
= Handle
;
445 CopyGuid (&mCacheHandleGuidTable
[mCachePairCount
].ModuleGuid
, ModuleGuid
);
446 AsciiStrCpyS (mCacheHandleGuidTable
[mCachePairCount
].NameString
, FPDT_STRING_EVENT_RECORD_NAME_LENGTH
, NameString
);
454 Copies the string from Source into Destination and updates Length with the
457 @param Destination - destination of the string copy
458 @param Source - pointer to the source string which will get copied
459 @param Length - pointer to a length variable to be updated
463 CopyStringIntoPerfRecordAndUpdateLength (
464 IN OUT CHAR8
*Destination
,
465 IN CONST CHAR8
*Source
,
472 ASSERT (Source
!= NULL
);
474 if (PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly
)) {
475 DestMax
= STRING_SIZE
;
477 DestMax
= AsciiStrSize (Source
);
478 if (DestMax
> STRING_SIZE
) {
479 DestMax
= STRING_SIZE
;
483 StringLen
= AsciiStrLen (Source
);
484 if (StringLen
>= DestMax
) {
485 StringLen
= DestMax
-1;
488 AsciiStrnCpyS (Destination
, DestMax
, Source
, StringLen
);
489 *Length
+= (UINT8
)DestMax
;
495 Create performance record with event description and a timestamp.
497 @param CallerIdentifier - Image handle or pointer to caller ID GUID.
498 @param Guid - Pointer to a GUID.
499 @param String - Pointer to a string describing the measurement.
500 @param Ticker - 64-bit time stamp.
501 @param Address - Pointer to a location in memory relevant to the measurement.
502 @param PerfId - Performance identifier describing the type of measurement.
503 @param Attribute - The attribute of the measurement. According to attribute can create a start
504 record for PERF_START/PERF_START_EX, or a end record for PERF_END/PERF_END_EX,
505 or a general record for other Perf macros.
507 @retval EFI_SUCCESS - Successfully created performance record.
508 @retval EFI_OUT_OF_RESOURCES - Ran out of space to store the records.
509 @retval EFI_INVALID_PARAMETER - Invalid parameter passed to function - NULL
510 pointer or invalid PerfId.
512 @retval EFI_SUCCESS - Successfully created performance record
513 @retval EFI_OUT_OF_RESOURCES - Ran out of space to store the records
514 @retval EFI_INVALID_PARAMETER - Invalid parameter passed to function - NULL
515 pointer or invalid PerfId
520 IN CONST VOID
*CallerIdentifier OPTIONAL
,
521 IN CONST VOID
*Guid OPTIONAL
,
522 IN CONST CHAR8
*String OPTIONAL
,
524 IN UINT64 Address OPTIONAL
,
526 IN PERF_MEASUREMENT_ATTRIBUTE Attribute
532 CHAR8 ModuleName
[FPDT_STRING_EVENT_RECORD_NAME_LENGTH
];
533 FPDT_RECORD_PTR FpdtRecordPtr
;
534 FPDT_RECORD_PTR CachedFpdtRecordPtr
;
536 CONST CHAR8
*StringPtr
;
542 ZeroMem (ModuleName
, sizeof (ModuleName
));
545 // 1. Get the Perf Id for records from PERF_START/PERF_END, PERF_START_EX/PERF_END_EX.
546 // notes: For other Perf macros (Attribute == PerfEntry), their Id is known.
548 if (Attribute
!= PerfEntry
) {
550 // If PERF_START_EX()/PERF_END_EX() have specified the ProgressID,it has high priority.
551 // !!! Note: If the Perf is not the known Token used in the core but have same
552 // ID with the core Token, this case will not be supported.
553 // And in currtnt usage mode, for the unkown ID, there is a general rule:
554 // If it is start pref: the lower 4 bits of the ID should be 0.
555 // If it is end pref: the lower 4 bits of the ID should not be 0.
556 // If input ID doesn't follow the rule, we will adjust it.
558 if ((PerfId
!= 0) && (IsKnownID (PerfId
)) && (!IsKnownTokens (String
))) {
559 return EFI_INVALID_PARAMETER
;
560 } else if ((PerfId
!= 0) && (!IsKnownID (PerfId
)) && (!IsKnownTokens (String
))) {
561 if ((Attribute
== PerfStartEntry
) && ((PerfId
& 0x000F) != 0)) {
563 } else if ((Attribute
== PerfEndEntry
) && ((PerfId
& 0x000F) == 0)) {
570 // Get ProgressID form the String Token.
572 Status
= GetFpdtRecordId (Attribute
, CallerIdentifier
, String
, &ProgressId
);
573 if (EFI_ERROR (Status
)) {
582 // 2. Get the buffer to store the FPDT record.
584 Status
= GetFpdtRecordPtr (FPDT_MAX_PERF_RECORD_SIZE
, &FpdtRecordPtr
);
585 if (EFI_ERROR (Status
)) {
590 // 3. Get the TimeStamp.
593 Ticker
= GetPerformanceCounter ();
594 TimeStamp
= GetTimeInNanoSecond (Ticker
);
595 } else if (Ticker
== 1) {
598 TimeStamp
= GetTimeInNanoSecond (Ticker
);
602 // 4. Fill in the FPDT record according to different Performance Identifier.
605 case MODULE_START_ID
:
607 GetModuleInfoFromHandle ((EFI_HANDLE
)CallerIdentifier
, ModuleName
, sizeof (ModuleName
), &ModuleGuid
);
608 StringPtr
= ModuleName
;
610 // Cache the offset of start image start record and use to update the start image end record if needed.
612 if ((PerfId
== MODULE_START_ID
) && (Attribute
== PerfEntry
)) {
613 mCachedLength
= mSmmBootPerformanceTable
->Header
.Length
;
616 if (!PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly
)) {
617 FpdtRecordPtr
.GuidEvent
->Header
.Type
= FPDT_GUID_EVENT_TYPE
;
618 FpdtRecordPtr
.GuidEvent
->Header
.Length
= sizeof (FPDT_GUID_EVENT_RECORD
);
619 FpdtRecordPtr
.GuidEvent
->Header
.Revision
= FPDT_RECORD_REVISION_1
;
620 FpdtRecordPtr
.GuidEvent
->ProgressID
= PerfId
;
621 FpdtRecordPtr
.GuidEvent
->Timestamp
= TimeStamp
;
622 CopyMem (&FpdtRecordPtr
.GuidEvent
->Guid
, &ModuleGuid
, sizeof (FpdtRecordPtr
.GuidEvent
->Guid
));
623 if ((CallerIdentifier
== NULL
) && (PerfId
== MODULE_END_ID
) && (mCachedLength
!= 0)) {
624 CachedFpdtRecordPtr
.RecordHeader
= (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER
*)((UINT8
*)mSmmBootPerformanceTable
+ mCachedLength
);
625 CopyMem (&FpdtRecordPtr
.GuidEvent
->Guid
, &CachedFpdtRecordPtr
.GuidEvent
->Guid
, sizeof (FpdtRecordPtr
.GuidEvent
->Guid
));
632 case MODULE_LOADIMAGE_START_ID
:
633 case MODULE_LOADIMAGE_END_ID
:
634 GetModuleInfoFromHandle ((EFI_HANDLE
)CallerIdentifier
, ModuleName
, sizeof (ModuleName
), &ModuleGuid
);
635 StringPtr
= ModuleName
;
636 if (PerfId
== MODULE_LOADIMAGE_START_ID
) {
639 // Cache the offset of load image start record and use to be updated by the load image end record if needed.
641 if ((CallerIdentifier
== NULL
) && (Attribute
== PerfEntry
)) {
642 mCachedLength
= mSmmBootPerformanceTable
->Header
.Length
;
646 if (!PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly
)) {
647 FpdtRecordPtr
.GuidQwordEvent
->Header
.Type
= FPDT_GUID_QWORD_EVENT_TYPE
;
648 FpdtRecordPtr
.GuidQwordEvent
->Header
.Length
= sizeof (FPDT_GUID_QWORD_EVENT_RECORD
);
649 FpdtRecordPtr
.GuidQwordEvent
->Header
.Revision
= FPDT_RECORD_REVISION_1
;
650 FpdtRecordPtr
.GuidQwordEvent
->ProgressID
= PerfId
;
651 FpdtRecordPtr
.GuidQwordEvent
->Timestamp
= TimeStamp
;
652 FpdtRecordPtr
.GuidQwordEvent
->Qword
= mLoadImageCount
;
653 CopyMem (&FpdtRecordPtr
.GuidQwordEvent
->Guid
, &ModuleGuid
, sizeof (FpdtRecordPtr
.GuidQwordEvent
->Guid
));
654 if ((PerfId
== MODULE_LOADIMAGE_END_ID
) && (mCachedLength
!= 0)) {
655 CachedFpdtRecordPtr
.RecordHeader
= (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER
*)((UINT8
*)mSmmBootPerformanceTable
+ mCachedLength
);
656 CopyMem (&CachedFpdtRecordPtr
.GuidQwordEvent
->Guid
, &ModuleGuid
, sizeof (CachedFpdtRecordPtr
.GuidQwordEvent
->Guid
));
663 case PERF_EVENTSIGNAL_START_ID
:
664 case PERF_EVENTSIGNAL_END_ID
:
665 case PERF_CALLBACK_START_ID
:
666 case PERF_CALLBACK_END_ID
:
667 if ((String
== NULL
) || (Guid
== NULL
)) {
668 return EFI_INVALID_PARAMETER
;
672 if (AsciiStrLen (String
) == 0) {
673 StringPtr
= "unknown name";
676 if (!PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly
)) {
677 FpdtRecordPtr
.DualGuidStringEvent
->Header
.Type
= FPDT_DUAL_GUID_STRING_EVENT_TYPE
;
678 FpdtRecordPtr
.DualGuidStringEvent
->Header
.Length
= sizeof (FPDT_DUAL_GUID_STRING_EVENT_RECORD
);
679 FpdtRecordPtr
.DualGuidStringEvent
->Header
.Revision
= FPDT_RECORD_REVISION_1
;
680 FpdtRecordPtr
.DualGuidStringEvent
->ProgressID
= PerfId
;
681 FpdtRecordPtr
.DualGuidStringEvent
->Timestamp
= TimeStamp
;
682 CopyMem (&FpdtRecordPtr
.DualGuidStringEvent
->Guid1
, CallerIdentifier
, sizeof (FpdtRecordPtr
.DualGuidStringEvent
->Guid1
));
683 CopyMem (&FpdtRecordPtr
.DualGuidStringEvent
->Guid2
, Guid
, sizeof (FpdtRecordPtr
.DualGuidStringEvent
->Guid2
));
684 CopyStringIntoPerfRecordAndUpdateLength (FpdtRecordPtr
.DualGuidStringEvent
->String
, StringPtr
, &FpdtRecordPtr
.DualGuidStringEvent
->Header
.Length
);
690 case PERF_FUNCTION_START_ID
:
691 case PERF_FUNCTION_END_ID
:
692 case PERF_INMODULE_START_ID
:
693 case PERF_INMODULE_END_ID
:
694 case PERF_CROSSMODULE_START_ID
:
695 case PERF_CROSSMODULE_END_ID
:
696 GetModuleInfoFromHandle ((EFI_HANDLE
)CallerIdentifier
, ModuleName
, sizeof (ModuleName
), &ModuleGuid
);
697 if (String
!= NULL
) {
700 StringPtr
= ModuleName
;
703 if (AsciiStrLen (StringPtr
) == 0) {
704 StringPtr
= "unknown name";
707 if (!PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly
)) {
708 FpdtRecordPtr
.DynamicStringEvent
->Header
.Type
= FPDT_DYNAMIC_STRING_EVENT_TYPE
;
709 FpdtRecordPtr
.DynamicStringEvent
->Header
.Length
= sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD
);
710 FpdtRecordPtr
.DynamicStringEvent
->Header
.Revision
= FPDT_RECORD_REVISION_1
;
711 FpdtRecordPtr
.DynamicStringEvent
->ProgressID
= PerfId
;
712 FpdtRecordPtr
.DynamicStringEvent
->Timestamp
= TimeStamp
;
713 CopyMem (&FpdtRecordPtr
.DynamicStringEvent
->Guid
, &ModuleGuid
, sizeof (FpdtRecordPtr
.DynamicStringEvent
->Guid
));
714 CopyStringIntoPerfRecordAndUpdateLength (FpdtRecordPtr
.DynamicStringEvent
->String
, StringPtr
, &FpdtRecordPtr
.DynamicStringEvent
->Header
.Length
);
720 if (Attribute
!= PerfEntry
) {
721 GetModuleInfoFromHandle ((EFI_HANDLE
)CallerIdentifier
, ModuleName
, sizeof (ModuleName
), &ModuleGuid
);
722 if (String
!= NULL
) {
725 StringPtr
= ModuleName
;
728 if (AsciiStrLen (StringPtr
) == 0) {
729 StringPtr
= "unknown name";
732 if (!PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly
)) {
733 FpdtRecordPtr
.DynamicStringEvent
->Header
.Type
= FPDT_DYNAMIC_STRING_EVENT_TYPE
;
734 FpdtRecordPtr
.DynamicStringEvent
->Header
.Length
= sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD
);
735 FpdtRecordPtr
.DynamicStringEvent
->Header
.Revision
= FPDT_RECORD_REVISION_1
;
736 FpdtRecordPtr
.DynamicStringEvent
->ProgressID
= PerfId
;
737 FpdtRecordPtr
.DynamicStringEvent
->Timestamp
= TimeStamp
;
738 CopyMem (&FpdtRecordPtr
.DynamicStringEvent
->Guid
, &ModuleGuid
, sizeof (FpdtRecordPtr
.DynamicStringEvent
->Guid
));
739 CopyStringIntoPerfRecordAndUpdateLength (FpdtRecordPtr
.DynamicStringEvent
->String
, StringPtr
, &FpdtRecordPtr
.DynamicStringEvent
->Header
.Length
);
742 return EFI_INVALID_PARAMETER
;
749 // 4.2 When PcdEdkiiFpdtStringRecordEnableOnly==TRUE, create string record for all Perf entries.
751 if (PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly
)) {
752 if (StringPtr
== NULL
) {
753 return EFI_INVALID_PARAMETER
;
756 FpdtRecordPtr
.DynamicStringEvent
->Header
.Type
= FPDT_DYNAMIC_STRING_EVENT_TYPE
;
757 FpdtRecordPtr
.DynamicStringEvent
->Header
.Length
= sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD
);
758 FpdtRecordPtr
.DynamicStringEvent
->Header
.Revision
= FPDT_RECORD_REVISION_1
;
759 FpdtRecordPtr
.DynamicStringEvent
->ProgressID
= PerfId
;
760 FpdtRecordPtr
.DynamicStringEvent
->Timestamp
= TimeStamp
;
763 // Cache the event guid in string event record.
765 CopyMem (&FpdtRecordPtr
.DynamicStringEvent
->Guid
, Guid
, sizeof (FpdtRecordPtr
.DynamicStringEvent
->Guid
));
767 CopyMem (&FpdtRecordPtr
.DynamicStringEvent
->Guid
, &ModuleGuid
, sizeof (FpdtRecordPtr
.DynamicStringEvent
->Guid
));
770 if (AsciiStrLen (StringPtr
) == 0) {
771 StringPtr
= "unknown name";
774 CopyStringIntoPerfRecordAndUpdateLength (FpdtRecordPtr
.DynamicStringEvent
->String
, StringPtr
, &FpdtRecordPtr
.DynamicStringEvent
->Header
.Length
);
776 if ((PerfId
== MODULE_LOADIMAGE_START_ID
) || (PerfId
== MODULE_END_ID
)) {
777 FpdtRecordPtr
.DynamicStringEvent
->Header
.Length
= (UINT8
)(sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD
)+ STRING_SIZE
);
780 if (((PerfId
== MODULE_LOADIMAGE_END_ID
) || (PerfId
== MODULE_END_ID
)) && (mCachedLength
!= 0)) {
781 CachedFpdtRecordPtr
.RecordHeader
= (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER
*)((UINT8
*)mSmmBootPerformanceTable
+ mCachedLength
);
782 if (PerfId
== MODULE_LOADIMAGE_END_ID
) {
783 DestMax
= CachedFpdtRecordPtr
.DynamicStringEvent
->Header
.Length
- sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD
);
784 StringLen
= AsciiStrLen (StringPtr
);
785 if (StringLen
>= DestMax
) {
786 StringLen
= DestMax
-1;
789 CopyMem (&CachedFpdtRecordPtr
.DynamicStringEvent
->Guid
, &ModuleGuid
, sizeof (CachedFpdtRecordPtr
.DynamicStringEvent
->Guid
));
790 AsciiStrnCpyS (CachedFpdtRecordPtr
.DynamicStringEvent
->String
, DestMax
, StringPtr
, StringLen
);
791 } else if (PerfId
== MODULE_END_ID
) {
792 DestMax
= FpdtRecordPtr
.DynamicStringEvent
->Header
.Length
- sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD
);
793 StringLen
= AsciiStrLen (CachedFpdtRecordPtr
.DynamicStringEvent
->String
);
794 if (StringLen
>= DestMax
) {
795 StringLen
= DestMax
-1;
798 CopyMem (&FpdtRecordPtr
.DynamicStringEvent
->Guid
, &CachedFpdtRecordPtr
.DynamicStringEvent
->Guid
, sizeof (CachedFpdtRecordPtr
.DynamicStringEvent
->Guid
));
799 AsciiStrnCpyS (FpdtRecordPtr
.DynamicStringEvent
->String
, DestMax
, CachedFpdtRecordPtr
.DynamicStringEvent
->String
, StringLen
);
807 // 5. Update the length of the used buffer after fill in the record.
809 mPerformanceLength
+= FpdtRecordPtr
.RecordHeader
->Length
;
810 mSmmBootPerformanceTable
->Header
.Length
+= FpdtRecordPtr
.RecordHeader
->Length
;
816 Communication service SMI Handler entry.
818 This SMI handler provides services for report MM boot records.
820 Caution: This function may receive untrusted input.
821 Communicate buffer and buffer size are external input, so this function will do basic validation.
823 @param[in] DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().
824 @param[in] RegisterContext Points to an optional handler context which was specified when the
825 handler was registered.
826 @param[in, out] CommBuffer A pointer to a collection of data in memory that will
827 be conveyed from a non-MM environment into an MM environment.
828 @param[in, out] CommBufferSize The size of the CommBuffer.
830 @retval EFI_SUCCESS The interrupt was handled and quiesced. No other handlers
831 should still be called.
832 @retval EFI_WARN_INTERRUPT_SOURCE_QUIESCED The interrupt has been quiesced but other handlers should
834 @retval EFI_WARN_INTERRUPT_SOURCE_PENDING The interrupt is still pending and other handlers should still
836 @retval EFI_INTERRUPT_PENDING The interrupt could not be quiesced.
842 IN EFI_HANDLE DispatchHandle
,
843 IN CONST VOID
*RegisterContext
,
844 IN OUT VOID
*CommBuffer
,
845 IN OUT UINTN
*CommBufferSize
849 SMM_BOOT_RECORD_COMMUNICATE
*SmmCommData
;
850 UINTN BootRecordOffset
;
851 UINTN BootRecordSize
;
852 VOID
*BootRecordData
;
853 UINTN TempCommBufferSize
;
854 UINT8
*BootRecordBuffer
;
857 // If input is invalid, stop processing this SMI
859 if ((CommBuffer
== NULL
) || (CommBufferSize
== NULL
)) {
863 TempCommBufferSize
= *CommBufferSize
;
865 if (TempCommBufferSize
< sizeof (SMM_BOOT_RECORD_COMMUNICATE
)) {
869 if (!SmmIsBufferOutsideSmmValid ((UINTN
)CommBuffer
, TempCommBufferSize
)) {
870 DEBUG ((DEBUG_ERROR
, "FpdtSmiHandler: MM communication data buffer in MMRAM or overflow!\n"));
874 SmmCommData
= (SMM_BOOT_RECORD_COMMUNICATE
*)CommBuffer
;
876 Status
= EFI_SUCCESS
;
878 switch (SmmCommData
->Function
) {
879 case SMM_FPDT_FUNCTION_GET_BOOT_RECORD_SIZE
:
880 if (mSmmBootPerformanceTable
!= NULL
) {
881 mBootRecordSize
= mSmmBootPerformanceTable
->Header
.Length
- sizeof (SMM_BOOT_PERFORMANCE_TABLE
);
884 SmmCommData
->BootRecordSize
= mBootRecordSize
;
887 case SMM_FPDT_FUNCTION_GET_BOOT_RECORD_DATA
:
888 Status
= EFI_UNSUPPORTED
;
891 case SMM_FPDT_FUNCTION_GET_BOOT_RECORD_DATA_BY_OFFSET
:
892 BootRecordOffset
= SmmCommData
->BootRecordOffset
;
893 BootRecordData
= SmmCommData
->BootRecordData
;
894 BootRecordSize
= SmmCommData
->BootRecordSize
;
895 if ((BootRecordData
== NULL
) || (BootRecordOffset
>= mBootRecordSize
)) {
896 Status
= EFI_INVALID_PARAMETER
;
903 if (BootRecordSize
> mBootRecordSize
- BootRecordOffset
) {
904 BootRecordSize
= mBootRecordSize
- BootRecordOffset
;
907 SmmCommData
->BootRecordSize
= BootRecordSize
;
908 if (!SmmIsBufferOutsideSmmValid ((UINTN
)BootRecordData
, BootRecordSize
)) {
909 DEBUG ((DEBUG_ERROR
, "FpdtSmiHandler: MM Data buffer in MMRAM or overflow!\n"));
910 Status
= EFI_ACCESS_DENIED
;
914 BootRecordBuffer
= ((UINT8
*)(mSmmBootPerformanceTable
)) + sizeof (SMM_BOOT_PERFORMANCE_TABLE
);
916 (UINT8
*)BootRecordData
,
917 BootRecordBuffer
+ BootRecordOffset
,
920 mFpdtDataIsReported
= TRUE
;
924 Status
= EFI_UNSUPPORTED
;
927 SmmCommData
->ReturnStatus
= Status
;
933 SmmBase2 protocol notify callback function, when SMST and SMM memory service get initialized
934 this function is callbacked to initialize the Smm Performance Lib
936 @param Event The event of notify protocol.
937 @param Context Notify event context.
942 InitializeSmmCorePerformanceLib (
948 EFI_HANDLE SmiHandle
;
950 PERFORMANCE_PROPERTY
*PerformanceProperty
;
953 // Initialize spin lock
955 InitializeSpinLock (&mSmmFpdtLock
);
958 // Install the protocol interfaces for SMM performance library instance.
961 Status
= gSmst
->SmmInstallProtocolInterface (
963 &gEdkiiSmmPerformanceMeasurementProtocolGuid
,
964 EFI_NATIVE_INTERFACE
,
965 &mPerformanceMeasurementInterface
967 ASSERT_EFI_ERROR (Status
);
970 // Register SMI handler.
973 Status
= gSmst
->SmiHandlerRegister (FpdtSmiHandler
, &gEfiFirmwarePerformanceGuid
, &SmiHandle
);
974 ASSERT_EFI_ERROR (Status
);
976 Status
= EfiGetSystemConfigurationTable (&gPerformanceProtocolGuid
, (VOID
**)&PerformanceProperty
);
977 if (EFI_ERROR (Status
)) {
979 // Install configuration table for performance property.
981 mPerformanceProperty
.Revision
= PERFORMANCE_PROPERTY_REVISION
;
982 mPerformanceProperty
.Reserved
= 0;
983 mPerformanceProperty
.Frequency
= GetPerformanceCounterProperties (
984 &mPerformanceProperty
.TimerStartValue
,
985 &mPerformanceProperty
.TimerEndValue
987 Status
= gBS
->InstallConfigurationTable (&gPerformanceProtocolGuid
, &mPerformanceProperty
);
988 ASSERT_EFI_ERROR (Status
);
993 The constructor function initializes the Performance Measurement Enable flag and
994 registers SmmBase2 protocol notify callback.
995 It will ASSERT() if one of these operations fails and it will always return EFI_SUCCESS.
997 @param ImageHandle The firmware allocated handle for the EFI image.
998 @param SystemTable A pointer to the EFI System Table.
1000 @retval EFI_SUCCESS The constructor always returns EFI_SUCCESS.
1005 SmmCorePerformanceLibConstructor (
1006 IN EFI_HANDLE ImageHandle
,
1007 IN EFI_SYSTEM_TABLE
*SystemTable
1014 if (!PerformanceMeasurementEnabled ()) {
1016 // Do not initialize performance infrastructure if not required.
1022 // Create the events to do the library init.
1024 Status
= gBS
->CreateEvent (
1027 InitializeSmmCorePerformanceLib
,
1031 ASSERT_EFI_ERROR (Status
);
1034 // Register for protocol notifications on this event
1036 Status
= gBS
->RegisterProtocolNotify (
1037 &gEfiSmmBase2ProtocolGuid
,
1042 ASSERT_EFI_ERROR (Status
);
1048 Create performance record with event description and a timestamp.
1050 @param CallerIdentifier - Image handle or pointer to caller ID GUID.
1051 @param Guid - Pointer to a GUID.
1052 @param String - Pointer to a string describing the measurement.
1053 @param TimeStamp - 64-bit time stamp.
1054 @param Address - Pointer to a location in memory relevant to the measurement.
1055 @param Identifier - Performance identifier describing the type of measurement.
1056 @param Attribute - The attribute of the measurement. According to attribute can create a start
1057 record for PERF_START/PERF_START_EX, or a end record for PERF_END/PERF_END_EX,
1058 or a general record for other Perf macros.
1060 @retval EFI_SUCCESS - Successfully created performance record.
1061 @retval EFI_OUT_OF_RESOURCES - Ran out of space to store the records.
1062 @retval EFI_INVALID_PARAMETER - Invalid parameter passed to function - NULL
1063 pointer or invalid PerfId.
1067 CreatePerformanceMeasurement (
1068 IN CONST VOID
*CallerIdentifier OPTIONAL
,
1069 IN CONST VOID
*Guid OPTIONAL
,
1070 IN CONST CHAR8
*String OPTIONAL
,
1071 IN UINT64 TimeStamp OPTIONAL
,
1072 IN UINT64 Address OPTIONAL
,
1073 IN UINT32 Identifier
,
1074 IN PERF_MEASUREMENT_ATTRIBUTE Attribute
1079 Status
= EFI_SUCCESS
;
1081 AcquireSpinLock (&mSmmFpdtLock
);
1082 Status
= InsertFpdtRecord (CallerIdentifier
, Guid
, String
, TimeStamp
, Address
, (UINT16
)Identifier
, Attribute
);
1083 ReleaseSpinLock (&mSmmFpdtLock
);
1088 Adds a record at the end of the performance measurement log
1089 that records the start time of a performance measurement.
1091 Adds a record to the end of the performance measurement log
1092 that contains the Handle, Token, Module and Identifier.
1093 The end time of the new record must be set to zero.
1094 If TimeStamp is not zero, then TimeStamp is used to fill in the start time in the record.
1095 If TimeStamp is zero, the start time in the record is filled in with the value
1096 read from the current time stamp.
1098 @param Handle Pointer to environment specific context used
1099 to identify the component being measured.
1100 @param Token Pointer to a Null-terminated ASCII string
1101 that identifies the component being measured.
1102 @param Module Pointer to a Null-terminated ASCII string
1103 that identifies the module being measured.
1104 @param TimeStamp 64-bit time stamp.
1105 @param Identifier 32-bit identifier. If the value is 0, the created record
1106 is same as the one created by StartPerformanceMeasurement.
1108 @retval RETURN_SUCCESS The start of the measurement was recorded.
1109 @retval RETURN_OUT_OF_RESOURCES There are not enough resources to record the measurement.
1114 StartPerformanceMeasurementEx (
1115 IN CONST VOID
*Handle OPTIONAL
,
1116 IN CONST CHAR8
*Token OPTIONAL
,
1117 IN CONST CHAR8
*Module OPTIONAL
,
1118 IN UINT64 TimeStamp
,
1119 IN UINT32 Identifier
1122 CONST CHAR8
*String
;
1124 if (Token
!= NULL
) {
1126 } else if (Module
!= NULL
) {
1132 return (RETURN_STATUS
)CreatePerformanceMeasurement (Handle
, NULL
, String
, TimeStamp
, 0, Identifier
, PerfStartEntry
);
1136 Searches the performance measurement log from the beginning of the log
1137 for the first matching record that contains a zero end time and fills in a valid end time.
1139 Searches the performance measurement log from the beginning of the log
1140 for the first record that matches Handle, Token, Module and Identifier and has an end time value of zero.
1141 If the record can not be found then return RETURN_NOT_FOUND.
1142 If the record is found and TimeStamp is not zero,
1143 then the end time in the record is filled in with the value specified by TimeStamp.
1144 If the record is found and TimeStamp is zero, then the end time in the matching record
1145 is filled in with the current time stamp value.
1147 @param Handle Pointer to environment specific context used
1148 to identify the component being measured.
1149 @param Token Pointer to a Null-terminated ASCII string
1150 that identifies the component being measured.
1151 @param Module Pointer to a Null-terminated ASCII string
1152 that identifies the module being measured.
1153 @param TimeStamp 64-bit time stamp.
1154 @param Identifier 32-bit identifier. If the value is 0, the found record
1155 is same as the one found by EndPerformanceMeasurement.
1157 @retval RETURN_SUCCESS The end of the measurement was recorded.
1158 @retval RETURN_NOT_FOUND The specified measurement record could not be found.
1163 EndPerformanceMeasurementEx (
1164 IN CONST VOID
*Handle OPTIONAL
,
1165 IN CONST CHAR8
*Token OPTIONAL
,
1166 IN CONST CHAR8
*Module OPTIONAL
,
1167 IN UINT64 TimeStamp
,
1168 IN UINT32 Identifier
1171 CONST CHAR8
*String
;
1173 if (Token
!= NULL
) {
1175 } else if (Module
!= NULL
) {
1181 return (RETURN_STATUS
)CreatePerformanceMeasurement (Handle
, NULL
, String
, TimeStamp
, 0, Identifier
, PerfEndEntry
);
1185 Attempts to retrieve a performance measurement log entry from the performance measurement log.
1186 It can also retrieve the log created by StartPerformanceMeasurement and EndPerformanceMeasurement,
1187 and then assign the Identifier with 0.
1191 Attempts to retrieve the performance log entry specified by LogEntryKey. If LogEntryKey is
1192 zero on entry, then an attempt is made to retrieve the first entry from the performance log,
1193 and the key for the second entry in the log is returned. If the performance log is empty,
1194 then no entry is retrieved and zero is returned. If LogEntryKey is not zero, then the performance
1195 log entry associated with LogEntryKey is retrieved, and the key for the next entry in the log is
1196 returned. If LogEntryKey is the key for the last entry in the log, then the last log entry is
1197 retrieved and an implementation specific non-zero key value that specifies the end of the performance
1198 log is returned. If LogEntryKey is equal this implementation specific non-zero key value, then no entry
1199 is retrieved and zero is returned. In the cases where a performance log entry can be returned,
1200 the log entry is returned in Handle, Token, Module, StartTimeStamp, EndTimeStamp and Identifier.
1201 If LogEntryKey is not a valid log entry key for the performance measurement log, then ASSERT().
1202 If Handle is NULL, then ASSERT().
1203 If Token is NULL, then ASSERT().
1204 If Module is NULL, then ASSERT().
1205 If StartTimeStamp is NULL, then ASSERT().
1206 If EndTimeStamp is NULL, then ASSERT().
1207 If Identifier is NULL, then ASSERT().
1209 @param LogEntryKey On entry, the key of the performance measurement log entry to retrieve.
1210 0, then the first performance measurement log entry is retrieved.
1211 On exit, the key of the next performance log entry.
1212 @param Handle Pointer to environment specific context used to identify the component
1214 @param Token Pointer to a Null-terminated ASCII string that identifies the component
1216 @param Module Pointer to a Null-terminated ASCII string that identifies the module
1218 @param StartTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement
1220 @param EndTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement
1222 @param Identifier Pointer to the 32-bit identifier that was recorded.
1224 @return The key for the next performance log entry (in general case).
1229 GetPerformanceMeasurementEx (
1230 IN UINTN LogEntryKey
,
1231 OUT CONST VOID
**Handle
,
1232 OUT CONST CHAR8
**Token
,
1233 OUT CONST CHAR8
**Module
,
1234 OUT UINT64
*StartTimeStamp
,
1235 OUT UINT64
*EndTimeStamp
,
1236 OUT UINT32
*Identifier
1243 Adds a record at the end of the performance measurement log
1244 that records the start time of a performance measurement.
1246 Adds a record to the end of the performance measurement log
1247 that contains the Handle, Token, and Module.
1248 The end time of the new record must be set to zero.
1249 If TimeStamp is not zero, then TimeStamp is used to fill in the start time in the record.
1250 If TimeStamp is zero, the start time in the record is filled in with the value
1251 read from the current time stamp.
1253 @param Handle Pointer to environment specific context used
1254 to identify the component being measured.
1255 @param Token Pointer to a Null-terminated ASCII string
1256 that identifies the component being measured.
1257 @param Module Pointer to a Null-terminated ASCII string
1258 that identifies the module being measured.
1259 @param TimeStamp 64-bit time stamp.
1261 @retval RETURN_SUCCESS The start of the measurement was recorded.
1262 @retval RETURN_OUT_OF_RESOURCES There are not enough resources to record the measurement.
1267 StartPerformanceMeasurement (
1268 IN CONST VOID
*Handle OPTIONAL
,
1269 IN CONST CHAR8
*Token OPTIONAL
,
1270 IN CONST CHAR8
*Module OPTIONAL
,
1274 return StartPerformanceMeasurementEx (Handle
, Token
, Module
, TimeStamp
, 0);
1278 Searches the performance measurement log from the beginning of the log
1279 for the first matching record that contains a zero end time and fills in a valid end time.
1281 Searches the performance measurement log from the beginning of the log
1282 for the first record that matches Handle, Token, and Module and has an end time value of zero.
1283 If the record can not be found then return RETURN_NOT_FOUND.
1284 If the record is found and TimeStamp is not zero,
1285 then the end time in the record is filled in with the value specified by TimeStamp.
1286 If the record is found and TimeStamp is zero, then the end time in the matching record
1287 is filled in with the current time stamp value.
1289 @param Handle Pointer to environment specific context used
1290 to identify the component being measured.
1291 @param Token Pointer to a Null-terminated ASCII string
1292 that identifies the component being measured.
1293 @param Module Pointer to a Null-terminated ASCII string
1294 that identifies the module being measured.
1295 @param TimeStamp 64-bit time stamp.
1297 @retval RETURN_SUCCESS The end of the measurement was recorded.
1298 @retval RETURN_NOT_FOUND The specified measurement record could not be found.
1303 EndPerformanceMeasurement (
1304 IN CONST VOID
*Handle OPTIONAL
,
1305 IN CONST CHAR8
*Token OPTIONAL
,
1306 IN CONST CHAR8
*Module OPTIONAL
,
1310 return EndPerformanceMeasurementEx (Handle
, Token
, Module
, TimeStamp
, 0);
1314 Attempts to retrieve a performance measurement log entry from the performance measurement log.
1315 It can also retrieve the log created by StartPerformanceMeasurementEx and EndPerformanceMeasurementEx,
1316 and then eliminate the Identifier.
1320 Attempts to retrieve the performance log entry specified by LogEntryKey. If LogEntryKey is
1321 zero on entry, then an attempt is made to retrieve the first entry from the performance log,
1322 and the key for the second entry in the log is returned. If the performance log is empty,
1323 then no entry is retrieved and zero is returned. If LogEntryKey is not zero, then the performance
1324 log entry associated with LogEntryKey is retrieved, and the key for the next entry in the log is
1325 returned. If LogEntryKey is the key for the last entry in the log, then the last log entry is
1326 retrieved and an implementation specific non-zero key value that specifies the end of the performance
1327 log is returned. If LogEntryKey is equal this implementation specific non-zero key value, then no entry
1328 is retrieved and zero is returned. In the cases where a performance log entry can be returned,
1329 the log entry is returned in Handle, Token, Module, StartTimeStamp, and EndTimeStamp.
1330 If LogEntryKey is not a valid log entry key for the performance measurement log, then ASSERT().
1331 If Handle is NULL, then ASSERT().
1332 If Token is NULL, then ASSERT().
1333 If Module is NULL, then ASSERT().
1334 If StartTimeStamp is NULL, then ASSERT().
1335 If EndTimeStamp is NULL, then ASSERT().
1337 @param LogEntryKey On entry, the key of the performance measurement log entry to retrieve.
1338 0, then the first performance measurement log entry is retrieved.
1339 On exit, the key of the next performance log entry.
1340 @param Handle Pointer to environment specific context used to identify the component
1342 @param Token Pointer to a Null-terminated ASCII string that identifies the component
1344 @param Module Pointer to a Null-terminated ASCII string that identifies the module
1346 @param StartTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement
1348 @param EndTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement
1351 @return The key for the next performance log entry (in general case).
1356 GetPerformanceMeasurement (
1357 IN UINTN LogEntryKey
,
1358 OUT CONST VOID
**Handle
,
1359 OUT CONST CHAR8
**Token
,
1360 OUT CONST CHAR8
**Module
,
1361 OUT UINT64
*StartTimeStamp
,
1362 OUT UINT64
*EndTimeStamp
1369 Returns TRUE if the performance measurement macros are enabled.
1371 This function returns TRUE if the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of
1372 PcdPerformanceLibraryPropertyMask is set. Otherwise FALSE is returned.
1374 @retval TRUE The PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of
1375 PcdPerformanceLibraryPropertyMask is set.
1376 @retval FALSE The PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of
1377 PcdPerformanceLibraryPropertyMask is clear.
1382 PerformanceMeasurementEnabled (
1386 return (BOOLEAN
)((PcdGet8 (PcdPerformanceLibraryPropertyMask
) & PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED
) != 0);
1390 Create performance record with event description and a timestamp.
1392 @param CallerIdentifier - Image handle or pointer to caller ID GUID
1393 @param Guid - Pointer to a GUID
1394 @param String - Pointer to a string describing the measurement
1395 @param Address - Pointer to a location in memory relevant to the measurement
1396 @param Identifier - Performance identifier describing the type of measurement
1398 @retval RETURN_SUCCESS - Successfully created performance record
1399 @retval RETURN_OUT_OF_RESOURCES - Ran out of space to store the records
1400 @retval RETURN_INVALID_PARAMETER - Invalid parameter passed to function - NULL
1401 pointer or invalid PerfId
1406 LogPerformanceMeasurement (
1407 IN CONST VOID
*CallerIdentifier
,
1408 IN CONST VOID
*Guid OPTIONAL
,
1409 IN CONST CHAR8
*String OPTIONAL
,
1410 IN UINT64 Address OPTIONAL
,
1411 IN UINT32 Identifier
1414 return (RETURN_STATUS
)CreatePerformanceMeasurement (CallerIdentifier
, Guid
, String
, 0, Address
, Identifier
, PerfEntry
);
1418 Check whether the specified performance measurement can be logged.
1420 This function returns TRUE when the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of PcdPerformanceLibraryPropertyMask is set
1421 and the Type disable bit in PcdPerformanceLibraryPropertyMask is not set.
1423 @param Type - Type of the performance measurement entry.
1425 @retval TRUE The performance measurement can be logged.
1426 @retval FALSE The performance measurement can NOT be logged.
1431 LogPerformanceMeasurementEnabled (
1436 // When Performance measurement is enabled and the type is not filtered, the performance can be logged.
1438 if (PerformanceMeasurementEnabled () && ((PcdGet8 (PcdPerformanceLibraryPropertyMask
) & Type
) == 0)) {