3 Copyright (c) 2006, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 Support for measurement of DXE performance
23 // Interface declarations for Performance Protocol.
26 Adds a record at the end of the performance measurement log
27 that records the start time of a performance measurement.
29 Adds a record to the end of the performance measurement log
30 that contains the Handle, Token, and Module.
31 The end time of the new record must be set to zero.
32 If TimeStamp is not zero, then TimeStamp is used to fill in the start time in the record.
33 If TimeStamp is zero, the start time in the record is filled in with the value
34 read from the current time stamp.
36 @param Handle Pointer to environment specific context used
37 to identify the component being measured.
38 @param Token Pointer to a Null-terminated ASCII string
39 that identifies the component being measured.
40 @param Module Pointer to a Null-terminated ASCII string
41 that identifies the module being measured.
42 @param TimeStamp 64-bit time stamp.
44 @retval EFI_SUCCESS The data was read correctly from the device.
45 @retval EFI_OUT_OF_RESOURCES There are not enough resources to record the measurement.
51 IN CONST VOID
*Handle
, OPTIONAL
52 IN CONST CHAR8
*Token
, OPTIONAL
53 IN CONST CHAR8
*Module
, OPTIONAL
58 Searches the performance measurement log from the beginning of the log
59 for the first matching record that contains a zero end time and fills in a valid end time.
61 Searches the performance measurement log from the beginning of the log
62 for the first record that matches Handle, Token, and Module and has an end time value of zero.
63 If the record can not be found then return EFI_NOT_FOUND.
64 If the record is found and TimeStamp is not zero,
65 then the end time in the record is filled in with the value specified by TimeStamp.
66 If the record is found and TimeStamp is zero, then the end time in the matching record
67 is filled in with the current time stamp value.
69 @param Handle Pointer to environment specific context used
70 to identify the component being measured.
71 @param Token Pointer to a Null-terminated ASCII string
72 that identifies the component being measured.
73 @param Module Pointer to a Null-terminated ASCII string
74 that identifies the module being measured.
75 @param TimeStamp 64-bit time stamp.
77 @retval EFI_SUCCESS The end of the measurement was recorded.
78 @retval EFI_NOT_FOUND The specified measurement record could not be found.
84 IN CONST VOID
*Handle
, OPTIONAL
85 IN CONST CHAR8
*Token
, OPTIONAL
86 IN CONST CHAR8
*Module
, OPTIONAL
91 Retrieves a previously logged performance measurement.
93 Retrieves the performance log entry from the performance log specified by LogEntryKey.
94 If it stands for a valid entry, then EFI_SUCCESS is returned and
95 GaugeDataEntry stores the pointer to that entry.
97 @param LogEntryKey The key for the previous performance measurement log entry.
98 If 0, then the first performance measurement log entry is retrieved.
99 @param GaugeDataEntry The indirect pointer to the gauge data entry specified by LogEntryKey
100 if the retrieval is successful.
102 @retval EFI_SUCCESS The GuageDataEntry is successfuly found based on LogEntryKey.
103 @retval EFI_NOT_FOUND The LogEntryKey is the last entry (equals to the total entry number).
104 @retval EFI_INVALIDE_PARAMETER The LogEntryKey is not a valid entry (greater than the total entry number).
105 @retval EFI_INVALIDE_PARAMETER GaugeDataEntry is NULL.
111 IN UINTN LogEntryKey
,
112 OUT GAUGE_DATA_ENTRY
**GaugeDataEntry
116 // Definition for global variables.
118 STATIC GAUGE_DATA_HEADER
*mGaugeData
;
119 STATIC UINT32 mMaxGaugeRecords
;
121 PERFORMANCE_PROTOCOL PerformanceInterface
= {
129 Searches in the gauge array with keyword Handle, Token and Module.
131 This internal function searches for the gauge entry in the gauge array.
132 If there is an entry that exactly matches the given key word triple
133 and its end time stamp is zero, then the index of that gauge entry is returned;
134 otherwise, the the number of gauge entries in the array is returned.
136 @param Handle Pointer to environment specific context used
137 to identify the component being measured.
138 @param Token Pointer to a Null-terminated ASCII string
139 that identifies the component being measured.
140 @param Module Pointer to a Null-terminated ASCII string
141 that identifies the module being measured.
143 @retval The index of gauge entry in the array.
147 InternalSearchForGaugeEntry (
148 IN CONST VOID
*Handle
, OPTIONAL
149 IN CONST CHAR8
*Token
, OPTIONAL
150 IN CONST CHAR8
*Module OPTIONAL
154 UINT32 NumberOfEntries
;
155 GAUGE_DATA_ENTRY
*GaugeEntryArray
;
160 if (Module
== NULL
) {
164 NumberOfEntries
= mGaugeData
->NumberOfEntries
;
165 GaugeEntryArray
= (GAUGE_DATA_ENTRY
*) (mGaugeData
+ 1);
167 for (Index
= 0; Index
< NumberOfEntries
; Index
++) {
168 if ((GaugeEntryArray
[Index
].Handle
== (EFI_PHYSICAL_ADDRESS
) (UINTN
) Handle
) &&
169 AsciiStrnCmp (GaugeEntryArray
[Index
].Token
, Token
, PEI_PERFORMANCE_STRING_LENGTH
) == 0 &&
170 AsciiStrnCmp (GaugeEntryArray
[Index
].Module
, Module
, PEI_PERFORMANCE_STRING_LENGTH
) == 0 &&
171 GaugeEntryArray
[Index
].EndTimeStamp
== 0
181 Adds a record at the end of the performance measurement log
182 that records the start time of a performance measurement.
184 Adds a record to the end of the performance measurement log
185 that contains the Handle, Token, and Module.
186 The end time of the new record must be set to zero.
187 If TimeStamp is not zero, then TimeStamp is used to fill in the start time in the record.
188 If TimeStamp is zero, the start time in the record is filled in with the value
189 read from the current time stamp.
191 @param Handle Pointer to environment specific context used
192 to identify the component being measured.
193 @param Token Pointer to a Null-terminated ASCII string
194 that identifies the component being measured.
195 @param Module Pointer to a Null-terminated ASCII string
196 that identifies the module being measured.
197 @param TimeStamp 64-bit time stamp.
199 @retval EFI_SUCCESS The data was read correctly from the device.
200 @retval EFI_OUT_OF_RESOURCES There are not enough resources to record the measurement.
206 IN CONST VOID
*Handle
, OPTIONAL
207 IN CONST CHAR8
*Token
, OPTIONAL
208 IN CONST CHAR8
*Module
, OPTIONAL
212 GAUGE_DATA_ENTRY
*GaugeEntryArray
;
214 UINTN OldGaugeDataSize
;
215 GAUGE_DATA_HEADER
*OldGaugeData
;
219 Index
= mGaugeData
->NumberOfEntries
;
220 if (Index
>= mMaxGaugeRecords
) {
222 // Try to enlarge the scale of gauge arrary.
224 OldGaugeData
= mGaugeData
;
225 OldGaugeDataSize
= sizeof (GAUGE_DATA_HEADER
) + sizeof (GAUGE_DATA_ENTRY
) * mMaxGaugeRecords
;
226 mMaxGaugeRecords
*= 2;
227 GaugeDataSize
= sizeof (GAUGE_DATA_HEADER
) + sizeof (GAUGE_DATA_ENTRY
) * mMaxGaugeRecords
;
228 Status
= gBS
->AllocatePool (
231 (VOID
**) &mGaugeData
233 if (EFI_ERROR (Status
)) {
237 // Initialize new data arry and migrate old data one.
239 mGaugeData
= ZeroMem (mGaugeData
, GaugeDataSize
);
240 mGaugeData
= CopyMem (mGaugeData
, OldGaugeData
, OldGaugeDataSize
);
242 gBS
->FreePool (OldGaugeData
);
245 GaugeEntryArray
= (GAUGE_DATA_ENTRY
*) (mGaugeData
+ 1);
246 GaugeEntryArray
[Index
].Handle
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) Handle
;
249 AsciiStrnCpy (GaugeEntryArray
[Index
].Token
, Token
, DXE_PERFORMANCE_STRING_LENGTH
);
251 if (Module
!= NULL
) {
252 AsciiStrnCpy (GaugeEntryArray
[Index
].Module
, Module
, DXE_PERFORMANCE_STRING_LENGTH
);
255 if (TimeStamp
== 0) {
256 TimeStamp
= GetPerformanceCounter ();
258 GaugeEntryArray
[Index
].StartTimeStamp
= TimeStamp
;
260 mGaugeData
->NumberOfEntries
++;
266 Searches the performance measurement log from the beginning of the log
267 for the first matching record that contains a zero end time and fills in a valid end time.
269 Searches the performance measurement log from the beginning of the log
270 for the first record that matches Handle, Token, and Module and has an end time value of zero.
271 If the record can not be found then return EFI_NOT_FOUND.
272 If the record is found and TimeStamp is not zero,
273 then the end time in the record is filled in with the value specified by TimeStamp.
274 If the record is found and TimeStamp is zero, then the end time in the matching record
275 is filled in with the current time stamp value.
277 @param Handle Pointer to environment specific context used
278 to identify the component being measured.
279 @param Token Pointer to a Null-terminated ASCII string
280 that identifies the component being measured.
281 @param Module Pointer to a Null-terminated ASCII string
282 that identifies the module being measured.
283 @param TimeStamp 64-bit time stamp.
285 @retval EFI_SUCCESS The end of the measurement was recorded.
286 @retval EFI_NOT_FOUND The specified measurement record could not be found.
292 IN CONST VOID
*Handle
, OPTIONAL
293 IN CONST CHAR8
*Token
, OPTIONAL
294 IN CONST CHAR8
*Module
, OPTIONAL
298 GAUGE_DATA_ENTRY
*GaugeEntryArray
;
301 if (TimeStamp
== 0) {
302 TimeStamp
= GetPerformanceCounter ();
305 Index
= InternalSearchForGaugeEntry (Handle
, Token
, Module
);
306 if (Index
>= mGaugeData
->NumberOfEntries
) {
307 return EFI_NOT_FOUND
;
309 GaugeEntryArray
= (GAUGE_DATA_ENTRY
*) (mGaugeData
+ 1);
310 GaugeEntryArray
[Index
].EndTimeStamp
= TimeStamp
;
316 Retrieves a previously logged performance measurement.
318 Retrieves the performance log entry from the performance log specified by LogEntryKey.
319 If it stands for a valid entry, then EFI_SUCCESS is returned and
320 GaugeDataEntry stores the pointer to that entry.
322 @param LogEntryKey The key for the previous performance measurement log entry.
323 If 0, then the first performance measurement log entry is retrieved.
324 @param GaugeDataEntry The indirect pointer to the gauge data entry specified by LogEntryKey
325 if the retrieval is successful.
327 @retval EFI_SUCCESS The GuageDataEntry is successfuly found based on LogEntryKey.
328 @retval EFI_NOT_FOUND The LogEntryKey is the last entry (equals to the total entry number).
329 @retval EFI_INVALIDE_PARAMETER The LogEntryKey is not a valid entry (greater than the total entry number).
330 @retval EFI_INVALIDE_PARAMETER GaugeDataEntry is NULL.
336 IN UINTN LogEntryKey
,
337 OUT GAUGE_DATA_ENTRY
**GaugeDataEntry
340 UINTN NumberOfEntries
;
341 GAUGE_DATA_ENTRY
*LogEntryArray
;
343 NumberOfEntries
= (UINTN
) (mGaugeData
->NumberOfEntries
);
344 if (LogEntryKey
> NumberOfEntries
) {
345 return EFI_INVALID_PARAMETER
;
347 if (LogEntryKey
== NumberOfEntries
) {
348 return EFI_NOT_FOUND
;
351 LogEntryArray
= (GAUGE_DATA_ENTRY
*) (mGaugeData
+ 1);
353 if (GaugeDataEntry
== NULL
) {
354 return EFI_INVALID_PARAMETER
;
356 *GaugeDataEntry
= &LogEntryArray
[LogEntryKey
];
362 Dumps all the PEI performance log to DXE performance gauge array.
364 This internal function dumps all the PEI performance log to the DXE performance gauge array.
365 It retrieves the optional GUID HOB for PEI performance and then saves the performance data
366 to DXE performance data structures.
370 InternalGetPeiPerformance (
374 EFI_HOB_GUID_TYPE
*GuidHob
;
375 PEI_PERFORMANCE_LOG_HEADER
*LogHob
;
376 PEI_PERFORMANCE_LOG_ENTRY
*LogEntryArray
;
377 GAUGE_DATA_ENTRY
*GaugeEntryArray
;
379 UINT32 NumberOfEntries
;
382 GaugeEntryArray
= (GAUGE_DATA_ENTRY
*) (mGaugeData
+ 1);
385 // Dump PEI Log Entries to DXE Guage Data structure.
387 GuidHob
= GetFirstGuidHob (&gPeiPerformanceHobGuid
);
388 if (GuidHob
!= NULL
) {
389 LogHob
= GET_GUID_HOB_DATA (GuidHob
);
390 LogEntryArray
= (PEI_PERFORMANCE_LOG_ENTRY
*) (LogHob
+ 1);
391 GaugeEntryArray
= (GAUGE_DATA_ENTRY
*) (mGaugeData
+ 1);
393 NumberOfEntries
= LogHob
->NumberOfEntries
;
394 for (Index
= 0; Index
< NumberOfEntries
; Index
++) {
395 GaugeEntryArray
[Index
].Handle
= LogEntryArray
[Index
].Handle
;
396 AsciiStrnCpy (GaugeEntryArray
[Index
].Token
, LogEntryArray
[Index
].Token
, DXE_PERFORMANCE_STRING_LENGTH
);
397 AsciiStrnCpy (GaugeEntryArray
[Index
].Module
, LogEntryArray
[Index
].Module
, DXE_PERFORMANCE_STRING_LENGTH
);
398 GaugeEntryArray
[Index
].StartTimeStamp
= LogEntryArray
[Index
].StartTimeStamp
;
399 GaugeEntryArray
[Index
].EndTimeStamp
= LogEntryArray
[Index
].EndTimeStamp
;
402 mGaugeData
->NumberOfEntries
= NumberOfEntries
;
406 The constructor function initializes Performance infrastructure for DXE phase.
408 The constructor function publishes Performance protocol, allocates memory to log DXE performance
409 and merges PEI performance data to DXE performance log.
410 It will ASSERT() if one of these operations fails and it will always return EFI_SUCCESS.
412 @param ImageHandle The firmware allocated handle for the EFI image.
413 @param SystemTable A pointer to the EFI System Table.
415 @retval EFI_SUCCESS The constructor always returns EFI_SUCCESS.
420 DxeCorePerformanceLibConstructor (
421 IN EFI_HANDLE ImageHandle
,
422 IN EFI_SYSTEM_TABLE
*SystemTable
430 // Install the protocol interfaces.
433 Status
= gBS
->InstallProtocolInterface (
435 &gPerformanceProtocolGuid
,
436 EFI_NATIVE_INTERFACE
,
437 &PerformanceInterface
439 ASSERT_EFI_ERROR (Status
);
441 mMaxGaugeRecords
= INIT_DXE_GAUGE_DATA_ENTRIES
+ MAX_PEI_PERFORMANCE_LOG_ENTRIES
;
442 GaugeDataSize
= sizeof (GAUGE_DATA_HEADER
) + sizeof (GAUGE_DATA_ENTRY
) * mMaxGaugeRecords
;
443 Status
= gBS
->AllocatePool (
446 (VOID
**) &mGaugeData
448 ASSERT_EFI_ERROR (Status
);
450 ZeroMem (mGaugeData
, GaugeDataSize
);
452 InternalGetPeiPerformance ();
458 Adds a record at the end of the performance measurement log
459 that records the start time of a performance measurement.
461 Adds a record to the end of the performance measurement log
462 that contains the Handle, Token, and Module.
463 The end time of the new record must be set to zero.
464 If TimeStamp is not zero, then TimeStamp is used to fill in the start time in the record.
465 If TimeStamp is zero, the start time in the record is filled in with the value
466 read from the current time stamp.
468 @param Handle Pointer to environment specific context used
469 to identify the component being measured.
470 @param Token Pointer to a Null-terminated ASCII string
471 that identifies the component being measured.
472 @param Module Pointer to a Null-terminated ASCII string
473 that identifies the module being measured.
474 @param TimeStamp 64-bit time stamp.
476 @retval RETURN_SUCCESS The start of the measurement was recorded.
477 @retval RETURN_OUT_OF_RESOURCES There are not enough resources to record the measurement.
482 StartPerformanceMeasurement (
483 IN CONST VOID
*Handle
, OPTIONAL
484 IN CONST CHAR8
*Token
, OPTIONAL
485 IN CONST CHAR8
*Module
, OPTIONAL
491 Status
= StartGauge (Handle
, Token
, Module
, TimeStamp
);
492 return (RETURN_STATUS
) Status
;
496 Searches the performance measurement log from the beginning of the log
497 for the first matching record that contains a zero end time and fills in a valid end time.
499 Searches the performance measurement log from the beginning of the log
500 for the first record that matches Handle, Token, and Module and has an end time value of zero.
501 If the record can not be found then return RETURN_NOT_FOUND.
502 If the record is found and TimeStamp is not zero,
503 then the end time in the record is filled in with the value specified by TimeStamp.
504 If the record is found and TimeStamp is zero, then the end time in the matching record
505 is filled in with the current time stamp value.
507 @param Handle Pointer to environment specific context used
508 to identify the component being measured.
509 @param Token Pointer to a Null-terminated ASCII string
510 that identifies the component being measured.
511 @param Module Pointer to a Null-terminated ASCII string
512 that identifies the module being measured.
513 @param TimeStamp 64-bit time stamp.
515 @retval RETURN_SUCCESS The end of the measurement was recorded.
516 @retval RETURN_NOT_FOUND The specified measurement record could not be found.
521 EndPerformanceMeasurement (
522 IN CONST VOID
*Handle
, OPTIONAL
523 IN CONST CHAR8
*Token
, OPTIONAL
524 IN CONST CHAR8
*Module
, OPTIONAL
530 Status
= EndGauge (Handle
, Token
, Module
, TimeStamp
);
531 return (RETURN_STATUS
) Status
;
535 Retrieves a previously logged performance measurement.
537 Retrieves the performance log entry from the performance log
538 that immediately follows the log entry specified by LogEntryKey.
539 If LogEntryKey is zero, then the first entry from the performance log is returned.
540 If the log entry specified by LogEntryKey is the last entry in the performance log,
541 then 0 is returned. Otherwise, the performance log entry is returned in Handle,
542 Token, Module, StartTimeStamp, and EndTimeStamp.
543 The key for the current performance log entry is returned.
545 @param LogEntryKey The key for the previous performance measurement log entry.
546 If 0, then the first performance measurement log entry is retrieved.
547 @param Handle Pointer to environment specific context used
548 to identify the component being measured.
549 @param Token Pointer to a Null-terminated ASCII string
550 that identifies the component being measured.
551 @param Module Pointer to a Null-terminated ASCII string
552 that identifies the module being measured.
553 @param StartTimeStamp The 64-bit time stamp that was recorded when the measurement was started.
554 @param EndTimeStamp The 64-bit time stamp that was recorded when the measurement was ended.
556 @return The key for the current performance log entry.
561 GetPerformanceMeasurement (
563 OUT CONST VOID
**Handle
,
564 OUT CONST CHAR8
**Token
,
565 OUT CONST CHAR8
**Module
,
566 OUT UINT64
*StartTimeStamp
,
567 OUT UINT64
*EndTimeStamp
571 GAUGE_DATA_ENTRY
*GaugeData
;
573 ASSERT (Handle
!= NULL
);
574 ASSERT (Token
!= NULL
);
575 ASSERT (Module
!= NULL
);
576 ASSERT (StartTimeStamp
!= NULL
);
577 ASSERT (EndTimeStamp
!= NULL
);
579 Status
= GetGauge (LogEntryKey
++, &GaugeData
);
582 // Make sure that LogEntryKey is a valid log entry key,
584 ASSERT (Status
!= EFI_INVALID_PARAMETER
);
586 if (EFI_ERROR (Status
)) {
588 // The LogEntryKey is the last entry (equals to the total entry number).
593 ASSERT (GaugeData
!= NULL
);
595 *Handle
= (VOID
*) (UINTN
) GaugeData
->Handle
;
596 *Token
= GaugeData
->Token
;
597 *Module
= GaugeData
->Module
;
598 *StartTimeStamp
= GaugeData
->StartTimeStamp
;
599 *EndTimeStamp
= GaugeData
->EndTimeStamp
;
605 Returns TRUE if the performance measurement macros are enabled.
607 This function returns TRUE if the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of
608 PcdPerformanceLibraryPropertyMask is set. Otherwise FALSE is returned.
610 @retval TRUE The PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of
611 PcdPerformanceLibraryPropertyMask is set.
612 @retval FALSE The PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of
613 PcdPerformanceLibraryPropertyMask is clear.
618 PerformanceMeasurementEnabled (
622 return ((PcdGet8(PcdPerformanceLibraryPropertyMask
) & PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED
) != 0);