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 Attempts to retrieve a performance measurement log entry from the performance measurement log.
537 Attempts to retrieve the performance log entry specified by LogEntryKey. If LogEntryKey is
538 zero on entry, then an attempt is made to retrieve the first entry from the performance log,
539 and the key for the second entry in the log is returned. If the performance log is empty,
540 then no entry is retrieved and zero is returned. If LogEntryKey is not zero, then the performance
541 log entry associated with LogEntryKey is retrieved, and the key for the next entry in the log is
542 returned. If LogEntryKey is the key for the last entry in the log, then the last log entry is
543 retrieved and an implementation specific non-zero key value that specifies the end of the performance
544 log is returned. If LogEntryKey is equal this implementation specific non-zero key value, then no entry
545 is retrieved and zero is returned. In the cases where a performance log entry can be returned,
546 the log entry is returned in Handle, Token, Module, StartTimeStamp, and EndTimeStamp.
547 If LogEntryKey is not a valid log entry key for the performance measurement log, then ASSERT().
548 If Handle is NULL, then ASSERT().
549 If Token is NULL, then ASSERT().
550 If Module is NULL, then ASSERT().
551 If StartTimeStamp is NULL, then ASSERT().
552 If EndTimeStamp is NULL, then ASSERT().
554 @param LogEntryKey On entry, the key of the performance measurement log entry to retrieve.
555 0, then the first performance measurement log entry is retrieved.
556 On exit, the key of the next performance lof entry entry.
557 @param Handle Pointer to environment specific context used to identify the component
559 @param Token Pointer to a Null-terminated ASCII string that identifies the component
561 @param Module Pointer to a Null-terminated ASCII string that identifies the module
563 @param StartTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement
565 @param EndTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement
568 @return The key for the next performance log entry (in general case).
573 GetPerformanceMeasurement (
574 IN UINTN LogEntryKey
,
575 OUT CONST VOID
**Handle
,
576 OUT CONST CHAR8
**Token
,
577 OUT CONST CHAR8
**Module
,
578 OUT UINT64
*StartTimeStamp
,
579 OUT UINT64
*EndTimeStamp
583 GAUGE_DATA_ENTRY
*GaugeData
;
585 ASSERT (Handle
!= NULL
);
586 ASSERT (Token
!= NULL
);
587 ASSERT (Module
!= NULL
);
588 ASSERT (StartTimeStamp
!= NULL
);
589 ASSERT (EndTimeStamp
!= NULL
);
591 Status
= GetGauge (LogEntryKey
++, &GaugeData
);
594 // Make sure that LogEntryKey is a valid log entry key,
596 ASSERT (Status
!= EFI_INVALID_PARAMETER
);
598 if (EFI_ERROR (Status
)) {
600 // The LogEntryKey is the last entry (equals to the total entry number).
605 ASSERT (GaugeData
!= NULL
);
607 *Handle
= (VOID
*) (UINTN
) GaugeData
->Handle
;
608 *Token
= GaugeData
->Token
;
609 *Module
= GaugeData
->Module
;
610 *StartTimeStamp
= GaugeData
->StartTimeStamp
;
611 *EndTimeStamp
= GaugeData
->EndTimeStamp
;
617 Returns TRUE if the performance measurement macros are enabled.
619 This function returns TRUE if the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of
620 PcdPerformanceLibraryPropertyMask is set. Otherwise FALSE is returned.
622 @retval TRUE The PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of
623 PcdPerformanceLibraryPropertyMask is set.
624 @retval FALSE The PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of
625 PcdPerformanceLibraryPropertyMask is clear.
630 PerformanceMeasurementEnabled (
634 return ((PcdGet8(PcdPerformanceLibraryPropertyMask
) & PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED
) != 0);