• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /** @file
2   Performance library instance mainly used by DxeCore.
3 
4   This library provides the performance measurement interfaces and initializes performance
5   logging for DXE phase. It first initializes its private global data structure for
6   performance logging and saves the performance GUIDed HOB passed from PEI phase.
7   It initializes DXE phase performance logging by publishing the Performance and PerformanceEx Protocol,
8   which are consumed by DxePerformanceLib to logging performance data in DXE phase.
9 
10   This library is mainly used by DxeCore to start performance logging to ensure that
11   Performance Protocol is installed at the very beginning of DXE phase.
12 
13 Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
14 (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
15 This program and the accompanying materials
16 are licensed and made available under the terms and conditions of the BSD License
17 which accompanies this distribution.  The full text of the license may be found at
18 http://opensource.org/licenses/bsd-license.php
19 
20 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
21 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
22 
23 **/
24 
25 
26 #include "DxeCorePerformanceLibInternal.h"
27 
28 
29 //
30 // The data structure to hold global performance data.
31 //
32 GAUGE_DATA_HEADER    *mGaugeData;
33 
34 //
35 // The current maximum number of logging entries. If current number of
36 // entries exceeds this value, it will re-allocate a larger array and
37 // migration the old data to the larger array.
38 //
39 UINT32               mMaxGaugeRecords;
40 
41 //
42 // The handle to install Performance Protocol instance.
43 //
44 EFI_HANDLE           mHandle = NULL;
45 
46 //
47 // Interfaces for Performance Protocol.
48 //
49 PERFORMANCE_PROTOCOL mPerformanceInterface = {
50   StartGauge,
51   EndGauge,
52   GetGauge
53   };
54 
55 //
56 // Interfaces for PerformanceEx Protocol.
57 //
58 PERFORMANCE_EX_PROTOCOL mPerformanceExInterface = {
59   StartGaugeEx,
60   EndGaugeEx,
61   GetGaugeEx
62   };
63 
64 /**
65   Searches in the gauge array with keyword Handle, Token, Module and Identifier.
66 
67   This internal function searches for the gauge entry in the gauge array.
68   If there is an entry that exactly matches the given keywords
69   and its end time stamp is zero, then the index of that gauge entry is returned;
70   otherwise, the the number of gauge entries in the array is returned.
71 
72   @param  Handle                  Pointer to environment specific context used
73                                   to identify the component being measured.
74   @param  Token                   Pointer to a Null-terminated ASCII string
75                                   that identifies the component being measured.
76   @param  Module                  Pointer to a Null-terminated ASCII string
77                                   that identifies the module being measured.
78   @param  Identifier              32-bit identifier.
79 
80   @retval The index of gauge entry in the array.
81 
82 **/
83 UINT32
InternalSearchForGaugeEntry(IN CONST VOID * Handle,OPTIONAL IN CONST CHAR8 * Token,OPTIONAL IN CONST CHAR8 * Module,OPTIONAL IN UINT32 Identifier)84 InternalSearchForGaugeEntry (
85   IN CONST VOID                 *Handle,  OPTIONAL
86   IN CONST CHAR8                *Token,   OPTIONAL
87   IN CONST CHAR8                *Module,   OPTIONAL
88   IN UINT32                     Identifier
89   )
90 {
91   UINT32                    Index;
92   UINT32                    Index2;
93   UINT32                    NumberOfEntries;
94   GAUGE_DATA_ENTRY_EX       *GaugeEntryExArray;
95 
96   if (Token == NULL) {
97     Token = "";
98   }
99   if (Module == NULL) {
100     Module = "";
101   }
102 
103   NumberOfEntries = mGaugeData->NumberOfEntries;
104   GaugeEntryExArray = (GAUGE_DATA_ENTRY_EX *) (mGaugeData + 1);
105 
106   Index2 = 0;
107 
108   for (Index = 0; Index < NumberOfEntries; Index++) {
109     Index2 = NumberOfEntries - 1 - Index;
110     if (GaugeEntryExArray[Index2].EndTimeStamp == 0 &&
111         (GaugeEntryExArray[Index2].Handle == (EFI_PHYSICAL_ADDRESS) (UINTN) Handle) &&
112         AsciiStrnCmp (GaugeEntryExArray[Index2].Token, Token, DXE_PERFORMANCE_STRING_LENGTH) == 0 &&
113         AsciiStrnCmp (GaugeEntryExArray[Index2].Module, Module, DXE_PERFORMANCE_STRING_LENGTH) == 0) {
114       Index = Index2;
115       break;
116     }
117   }
118 
119   return Index;
120 }
121 
122 /**
123   Adds a record at the end of the performance measurement log
124   that records the start time of a performance measurement.
125 
126   Adds a record to the end of the performance measurement log
127   that contains the Handle, Token, Module and Identifier.
128   The end time of the new record must be set to zero.
129   If TimeStamp is not zero, then TimeStamp is used to fill in the start time in the record.
130   If TimeStamp is zero, the start time in the record is filled in with the value
131   read from the current time stamp.
132 
133   @param  Handle                  Pointer to environment specific context used
134                                   to identify the component being measured.
135   @param  Token                   Pointer to a Null-terminated ASCII string
136                                   that identifies the component being measured.
137   @param  Module                  Pointer to a Null-terminated ASCII string
138                                   that identifies the module being measured.
139   @param  TimeStamp               64-bit time stamp.
140   @param  Identifier              32-bit identifier. If the value is 0, the created record
141                                   is same as the one created by StartGauge of PERFORMANCE_PROTOCOL.
142 
143   @retval EFI_SUCCESS             The data was read correctly from the device.
144   @retval EFI_OUT_OF_RESOURCES    There are not enough resources to record the measurement.
145 
146 **/
147 EFI_STATUS
148 EFIAPI
StartGaugeEx(IN CONST VOID * Handle,OPTIONAL IN CONST CHAR8 * Token,OPTIONAL IN CONST CHAR8 * Module,OPTIONAL IN UINT64 TimeStamp,IN UINT32 Identifier)149 StartGaugeEx (
150   IN CONST VOID   *Handle,  OPTIONAL
151   IN CONST CHAR8  *Token,   OPTIONAL
152   IN CONST CHAR8  *Module,  OPTIONAL
153   IN UINT64       TimeStamp,
154   IN UINT32       Identifier
155   )
156 {
157   GAUGE_DATA_ENTRY_EX       *GaugeEntryExArray;
158   UINTN                     GaugeDataSize;
159   GAUGE_DATA_HEADER         *NewGaugeData;
160   UINTN                     OldGaugeDataSize;
161   GAUGE_DATA_HEADER         *OldGaugeData;
162   UINT32                    Index;
163 
164   Index = mGaugeData->NumberOfEntries;
165   if (Index >= mMaxGaugeRecords) {
166     //
167     // Try to enlarge the scale of gauge array.
168     //
169     OldGaugeData      = mGaugeData;
170     OldGaugeDataSize  = sizeof (GAUGE_DATA_HEADER) + sizeof (GAUGE_DATA_ENTRY_EX) * mMaxGaugeRecords;
171 
172     GaugeDataSize     = sizeof (GAUGE_DATA_HEADER) + sizeof (GAUGE_DATA_ENTRY_EX) * mMaxGaugeRecords * 2;
173 
174     NewGaugeData = AllocateZeroPool (GaugeDataSize);
175     if (NewGaugeData == NULL) {
176       return EFI_OUT_OF_RESOURCES;
177     }
178 
179     mGaugeData = NewGaugeData;
180     mMaxGaugeRecords *= 2;
181 
182     //
183     // Initialize new data array and migrate old data one.
184     //
185     mGaugeData = CopyMem (mGaugeData, OldGaugeData, OldGaugeDataSize);
186 
187     FreePool (OldGaugeData);
188   }
189 
190   GaugeEntryExArray               = (GAUGE_DATA_ENTRY_EX *) (mGaugeData + 1);
191   GaugeEntryExArray[Index].Handle = (EFI_PHYSICAL_ADDRESS) (UINTN) Handle;
192 
193   if (Token != NULL) {
194     AsciiStrnCpyS (GaugeEntryExArray[Index].Token, DXE_PERFORMANCE_STRING_SIZE, Token, DXE_PERFORMANCE_STRING_LENGTH);
195   }
196   if (Module != NULL) {
197     AsciiStrnCpyS (GaugeEntryExArray[Index].Module, DXE_PERFORMANCE_STRING_SIZE, Module, DXE_PERFORMANCE_STRING_LENGTH);
198   }
199 
200   GaugeEntryExArray[Index].EndTimeStamp = 0;
201   GaugeEntryExArray[Index].Identifier = Identifier;
202 
203   if (TimeStamp == 0) {
204     TimeStamp = GetPerformanceCounter ();
205   }
206   GaugeEntryExArray[Index].StartTimeStamp = TimeStamp;
207 
208   mGaugeData->NumberOfEntries++;
209 
210   return EFI_SUCCESS;
211 }
212 
213 /**
214   Searches the performance measurement log from the beginning of the log
215   for the first matching record that contains a zero end time and fills in a valid end time.
216 
217   Searches the performance measurement log from the beginning of the log
218   for the first record that matches Handle, Token and Module and has an end time value of zero.
219   If the record can not be found then return EFI_NOT_FOUND.
220   If the record is found and TimeStamp is not zero,
221   then the end time in the record is filled in with the value specified by TimeStamp.
222   If the record is found and TimeStamp is zero, then the end time in the matching record
223   is filled in with the current time stamp value.
224 
225   @param  Handle                  Pointer to environment specific context used
226                                   to identify the component being measured.
227   @param  Token                   Pointer to a Null-terminated ASCII string
228                                   that identifies the component being measured.
229   @param  Module                  Pointer to a Null-terminated ASCII string
230                                   that identifies the module being measured.
231   @param  TimeStamp               64-bit time stamp.
232   @param  Identifier              32-bit identifier. If the value is 0, the found record
233                                   is same as the one found by EndGauge of PERFORMANCE_PROTOCOL.
234 
235   @retval EFI_SUCCESS             The end of  the measurement was recorded.
236   @retval EFI_NOT_FOUND           The specified measurement record could not be found.
237 
238 **/
239 EFI_STATUS
240 EFIAPI
EndGaugeEx(IN CONST VOID * Handle,OPTIONAL IN CONST CHAR8 * Token,OPTIONAL IN CONST CHAR8 * Module,OPTIONAL IN UINT64 TimeStamp,IN UINT32 Identifier)241 EndGaugeEx (
242   IN CONST VOID   *Handle,  OPTIONAL
243   IN CONST CHAR8  *Token,   OPTIONAL
244   IN CONST CHAR8  *Module,  OPTIONAL
245   IN UINT64       TimeStamp,
246   IN UINT32       Identifier
247   )
248 {
249   GAUGE_DATA_ENTRY_EX *GaugeEntryExArray;
250   UINT32              Index;
251 
252   if (TimeStamp == 0) {
253     TimeStamp = GetPerformanceCounter ();
254   }
255 
256   Index = InternalSearchForGaugeEntry (Handle, Token, Module, Identifier);
257   if (Index >= mGaugeData->NumberOfEntries) {
258     return EFI_NOT_FOUND;
259   }
260   GaugeEntryExArray = (GAUGE_DATA_ENTRY_EX *) (mGaugeData + 1);
261   GaugeEntryExArray[Index].EndTimeStamp = TimeStamp;
262 
263   return EFI_SUCCESS;
264 }
265 
266 /**
267   Retrieves a previously logged performance measurement.
268   It can also retrieve the log created by StartGauge and EndGauge of PERFORMANCE_PROTOCOL,
269   and then assign the Identifier with 0.
270 
271   Retrieves the performance log entry from the performance log specified by LogEntryKey.
272   If it stands for a valid entry, then EFI_SUCCESS is returned and
273   GaugeDataEntryEx stores the pointer to that entry.
274 
275   @param  LogEntryKey             The key for the previous performance measurement log entry.
276                                   If 0, then the first performance measurement log entry is retrieved.
277   @param  GaugeDataEntryEx        The indirect pointer to the extended gauge data entry specified by LogEntryKey
278                                   if the retrieval is successful.
279 
280   @retval EFI_SUCCESS             The GuageDataEntryEx is successfully found based on LogEntryKey.
281   @retval EFI_NOT_FOUND           The LogEntryKey is the last entry (equals to the total entry number).
282   @retval EFI_INVALIDE_PARAMETER  The LogEntryKey is not a valid entry (greater than the total entry number).
283   @retval EFI_INVALIDE_PARAMETER  GaugeDataEntryEx is NULL.
284 
285 **/
286 EFI_STATUS
287 EFIAPI
GetGaugeEx(IN UINTN LogEntryKey,OUT GAUGE_DATA_ENTRY_EX ** GaugeDataEntryEx)288 GetGaugeEx (
289   IN  UINTN                 LogEntryKey,
290   OUT GAUGE_DATA_ENTRY_EX   **GaugeDataEntryEx
291   )
292 {
293   UINTN               NumberOfEntries;
294   GAUGE_DATA_ENTRY_EX *GaugeEntryExArray;
295 
296   NumberOfEntries = (UINTN) (mGaugeData->NumberOfEntries);
297   if (LogEntryKey > NumberOfEntries) {
298     return EFI_INVALID_PARAMETER;
299   }
300   if (LogEntryKey == NumberOfEntries) {
301     return EFI_NOT_FOUND;
302   }
303 
304   GaugeEntryExArray = (GAUGE_DATA_ENTRY_EX *) (mGaugeData + 1);
305 
306   if (GaugeDataEntryEx == NULL) {
307     return EFI_INVALID_PARAMETER;
308   }
309   *GaugeDataEntryEx = &GaugeEntryExArray[LogEntryKey];
310 
311   return EFI_SUCCESS;
312 }
313 
314 /**
315   Adds a record at the end of the performance measurement log
316   that records the start time of a performance measurement.
317 
318   Adds a record to the end of the performance measurement log
319   that contains the Handle, Token, and Module.
320   The end time of the new record must be set to zero.
321   If TimeStamp is not zero, then TimeStamp is used to fill in the start time in the record.
322   If TimeStamp is zero, the start time in the record is filled in with the value
323   read from the current time stamp.
324 
325   @param  Handle                  Pointer to environment specific context used
326                                   to identify the component being measured.
327   @param  Token                   Pointer to a Null-terminated ASCII string
328                                   that identifies the component being measured.
329   @param  Module                  Pointer to a Null-terminated ASCII string
330                                   that identifies the module being measured.
331   @param  TimeStamp               64-bit time stamp.
332 
333   @retval EFI_SUCCESS             The data was read correctly from the device.
334   @retval EFI_OUT_OF_RESOURCES    There are not enough resources to record the measurement.
335 
336 **/
337 EFI_STATUS
338 EFIAPI
StartGauge(IN CONST VOID * Handle,OPTIONAL IN CONST CHAR8 * Token,OPTIONAL IN CONST CHAR8 * Module,OPTIONAL IN UINT64 TimeStamp)339 StartGauge (
340   IN CONST VOID   *Handle,  OPTIONAL
341   IN CONST CHAR8  *Token,   OPTIONAL
342   IN CONST CHAR8  *Module,  OPTIONAL
343   IN UINT64       TimeStamp
344   )
345 {
346   return StartGaugeEx (Handle, Token, Module, TimeStamp, 0);
347 }
348 
349 /**
350   Searches the performance measurement log from the beginning of the log
351   for the first matching record that contains a zero end time and fills in a valid end time.
352 
353   Searches the performance measurement log from the beginning of the log
354   for the first record that matches Handle, Token, and Module and has an end time value of zero.
355   If the record can not be found then return EFI_NOT_FOUND.
356   If the record is found and TimeStamp is not zero,
357   then the end time in the record is filled in with the value specified by TimeStamp.
358   If the record is found and TimeStamp is zero, then the end time in the matching record
359   is filled in with the current time stamp value.
360 
361   @param  Handle                  Pointer to environment specific context used
362                                   to identify the component being measured.
363   @param  Token                   Pointer to a Null-terminated ASCII string
364                                   that identifies the component being measured.
365   @param  Module                  Pointer to a Null-terminated ASCII string
366                                   that identifies the module being measured.
367   @param  TimeStamp               64-bit time stamp.
368 
369   @retval EFI_SUCCESS             The end of  the measurement was recorded.
370   @retval EFI_NOT_FOUND           The specified measurement record could not be found.
371 
372 **/
373 EFI_STATUS
374 EFIAPI
EndGauge(IN CONST VOID * Handle,OPTIONAL IN CONST CHAR8 * Token,OPTIONAL IN CONST CHAR8 * Module,OPTIONAL IN UINT64 TimeStamp)375 EndGauge (
376   IN CONST VOID   *Handle,  OPTIONAL
377   IN CONST CHAR8  *Token,   OPTIONAL
378   IN CONST CHAR8  *Module,  OPTIONAL
379   IN UINT64       TimeStamp
380   )
381 {
382   return EndGaugeEx (Handle, Token, Module, TimeStamp, 0);
383 }
384 
385 /**
386   Retrieves a previously logged performance measurement.
387   It can also retrieve the log created by StartGaugeEx and EndGaugeEx of PERFORMANCE_EX_PROTOCOL,
388   and then eliminate the Identifier.
389 
390   Retrieves the performance log entry from the performance log specified by LogEntryKey.
391   If it stands for a valid entry, then EFI_SUCCESS is returned and
392   GaugeDataEntry stores the pointer to that entry.
393 
394   @param  LogEntryKey             The key for the previous performance measurement log entry.
395                                   If 0, then the first performance measurement log entry is retrieved.
396   @param  GaugeDataEntry          The indirect pointer to the gauge data entry specified by LogEntryKey
397                                   if the retrieval is successful.
398 
399   @retval EFI_SUCCESS             The GuageDataEntry is successfully found based on LogEntryKey.
400   @retval EFI_NOT_FOUND           The LogEntryKey is the last entry (equals to the total entry number).
401   @retval EFI_INVALIDE_PARAMETER  The LogEntryKey is not a valid entry (greater than the total entry number).
402   @retval EFI_INVALIDE_PARAMETER  GaugeDataEntry is NULL.
403 
404 **/
405 EFI_STATUS
406 EFIAPI
GetGauge(IN UINTN LogEntryKey,OUT GAUGE_DATA_ENTRY ** GaugeDataEntry)407 GetGauge (
408   IN  UINTN               LogEntryKey,
409   OUT GAUGE_DATA_ENTRY    **GaugeDataEntry
410   )
411 {
412   EFI_STATUS          Status;
413   GAUGE_DATA_ENTRY_EX *GaugeEntryEx;
414 
415   GaugeEntryEx = NULL;
416 
417   Status = GetGaugeEx (LogEntryKey, &GaugeEntryEx);
418   if (EFI_ERROR (Status)) {
419     return Status;
420   }
421 
422   if (GaugeDataEntry == NULL) {
423     return EFI_INVALID_PARAMETER;
424   }
425 
426   *GaugeDataEntry = (GAUGE_DATA_ENTRY *) GaugeEntryEx;
427 
428   return EFI_SUCCESS;
429 }
430 
431 /**
432   Dumps all the PEI performance log to DXE performance gauge array.
433 
434   This internal function dumps all the PEI performance log to the DXE performance gauge array.
435   It retrieves the optional GUID HOB for PEI performance and then saves the performance data
436   to DXE performance data structures.
437 
438 **/
439 VOID
InternalGetPeiPerformance(VOID)440 InternalGetPeiPerformance (
441   VOID
442   )
443 {
444   EFI_HOB_GUID_TYPE                 *GuidHob;
445   PEI_PERFORMANCE_LOG_HEADER        *LogHob;
446   PEI_PERFORMANCE_LOG_ENTRY         *LogEntryArray;
447   UINT32                            *LogIdArray;
448   GAUGE_DATA_ENTRY_EX               *GaugeEntryExArray;
449   UINT32                            Index;
450   UINT32                            NumberOfEntries;
451 
452   NumberOfEntries = 0;
453   GaugeEntryExArray = (GAUGE_DATA_ENTRY_EX *) (mGaugeData + 1);
454 
455   //
456   // Dump PEI Log Entries to DXE Guage Data structure.
457   //
458   GuidHob = GetFirstGuidHob (&gPerformanceProtocolGuid);
459   if (GuidHob != NULL) {
460     LogHob          = GET_GUID_HOB_DATA (GuidHob);
461     LogEntryArray   = (PEI_PERFORMANCE_LOG_ENTRY *) (LogHob + 1);
462 
463     NumberOfEntries = LogHob->NumberOfEntries;
464     for (Index = 0; Index < NumberOfEntries; Index++) {
465       GaugeEntryExArray[Index].Handle         = LogEntryArray[Index].Handle;
466       AsciiStrCpyS (GaugeEntryExArray[Index].Token,  DXE_PERFORMANCE_STRING_SIZE, LogEntryArray[Index].Token);
467       AsciiStrCpyS (GaugeEntryExArray[Index].Module, DXE_PERFORMANCE_STRING_SIZE, LogEntryArray[Index].Module);
468       GaugeEntryExArray[Index].StartTimeStamp = LogEntryArray[Index].StartTimeStamp;
469       GaugeEntryExArray[Index].EndTimeStamp   = LogEntryArray[Index].EndTimeStamp;
470       GaugeEntryExArray[Index].Identifier     = 0;
471     }
472 
473     GuidHob = GetFirstGuidHob (&gPerformanceExProtocolGuid);
474     if (GuidHob != NULL) {
475       LogIdArray    = GET_GUID_HOB_DATA (GuidHob);
476       for (Index = 0; Index < NumberOfEntries; Index++) {
477         GaugeEntryExArray[Index].Identifier   = LogIdArray[Index];
478       }
479     }
480   }
481   mGaugeData->NumberOfEntries = NumberOfEntries;
482 }
483 
484 /**
485   The constructor function initializes Performance infrastructure for DXE phase.
486 
487   The constructor function publishes Performance and PerformanceEx protocol, allocates memory to log DXE performance
488   and merges PEI performance data to DXE performance log.
489   It will ASSERT() if one of these operations fails and it will always return EFI_SUCCESS.
490 
491   @param  ImageHandle   The firmware allocated handle for the EFI image.
492   @param  SystemTable   A pointer to the EFI System Table.
493 
494   @retval EFI_SUCCESS   The constructor always returns EFI_SUCCESS.
495 
496 **/
497 EFI_STATUS
498 EFIAPI
DxeCorePerformanceLibConstructor(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)499 DxeCorePerformanceLibConstructor (
500   IN EFI_HANDLE        ImageHandle,
501   IN EFI_SYSTEM_TABLE  *SystemTable
502   )
503 {
504   EFI_STATUS                Status;
505 
506   if (!PerformanceMeasurementEnabled ()) {
507     //
508     // Do not initialize performance infrastructure if not required.
509     //
510     return EFI_SUCCESS;
511   }
512   //
513   // Install the protocol interfaces.
514   //
515   Status = gBS->InstallMultipleProtocolInterfaces (
516                   &mHandle,
517                   &gPerformanceProtocolGuid,
518                   &mPerformanceInterface,
519                   &gPerformanceExProtocolGuid,
520                   &mPerformanceExInterface,
521                   NULL
522                   );
523   ASSERT_EFI_ERROR (Status);
524 
525   mMaxGaugeRecords = INIT_DXE_GAUGE_DATA_ENTRIES + (UINT16) (PcdGet16 (PcdMaxPeiPerformanceLogEntries16) != 0 ?
526                                                              PcdGet16 (PcdMaxPeiPerformanceLogEntries16) :
527                                                              PcdGet8 (PcdMaxPeiPerformanceLogEntries));
528 
529   mGaugeData = AllocateZeroPool (sizeof (GAUGE_DATA_HEADER) + (sizeof (GAUGE_DATA_ENTRY_EX) * mMaxGaugeRecords));
530   ASSERT (mGaugeData != NULL);
531 
532   InternalGetPeiPerformance ();
533 
534   return Status;
535 }
536 
537 /**
538   Adds a record at the end of the performance measurement log
539   that records the start time of a performance measurement.
540 
541   Adds a record to the end of the performance measurement log
542   that contains the Handle, Token, Module and Identifier.
543   The end time of the new record must be set to zero.
544   If TimeStamp is not zero, then TimeStamp is used to fill in the start time in the record.
545   If TimeStamp is zero, the start time in the record is filled in with the value
546   read from the current time stamp.
547 
548   @param  Handle                  Pointer to environment specific context used
549                                   to identify the component being measured.
550   @param  Token                   Pointer to a Null-terminated ASCII string
551                                   that identifies the component being measured.
552   @param  Module                  Pointer to a Null-terminated ASCII string
553                                   that identifies the module being measured.
554   @param  TimeStamp               64-bit time stamp.
555   @param  Identifier              32-bit identifier. If the value is 0, the created record
556                                   is same as the one created by StartPerformanceMeasurement.
557 
558   @retval RETURN_SUCCESS          The start of the measurement was recorded.
559   @retval RETURN_OUT_OF_RESOURCES There are not enough resources to record the measurement.
560 
561 **/
562 RETURN_STATUS
563 EFIAPI
StartPerformanceMeasurementEx(IN CONST VOID * Handle,OPTIONAL IN CONST CHAR8 * Token,OPTIONAL IN CONST CHAR8 * Module,OPTIONAL IN UINT64 TimeStamp,IN UINT32 Identifier)564 StartPerformanceMeasurementEx (
565   IN CONST VOID   *Handle,  OPTIONAL
566   IN CONST CHAR8  *Token,   OPTIONAL
567   IN CONST CHAR8  *Module,  OPTIONAL
568   IN UINT64       TimeStamp,
569   IN UINT32       Identifier
570   )
571 {
572   return (RETURN_STATUS) StartGaugeEx (Handle, Token, Module, TimeStamp, Identifier);
573 }
574 
575 /**
576   Searches the performance measurement log from the beginning of the log
577   for the first matching record that contains a zero end time and fills in a valid end time.
578 
579   Searches the performance measurement log from the beginning of the log
580   for the first record that matches Handle, Token and Module and has an end time value of zero.
581   If the record can not be found then return RETURN_NOT_FOUND.
582   If the record is found and TimeStamp is not zero,
583   then the end time in the record is filled in with the value specified by TimeStamp.
584   If the record is found and TimeStamp is zero, then the end time in the matching record
585   is filled in with the current time stamp value.
586 
587   @param  Handle                  Pointer to environment specific context used
588                                   to identify the component being measured.
589   @param  Token                   Pointer to a Null-terminated ASCII string
590                                   that identifies the component being measured.
591   @param  Module                  Pointer to a Null-terminated ASCII string
592                                   that identifies the module being measured.
593   @param  TimeStamp               64-bit time stamp.
594   @param  Identifier              32-bit identifier. If the value is 0, the found record
595                                   is same as the one found by EndPerformanceMeasurement.
596 
597   @retval RETURN_SUCCESS          The end of  the measurement was recorded.
598   @retval RETURN_NOT_FOUND        The specified measurement record could not be found.
599 
600 **/
601 RETURN_STATUS
602 EFIAPI
EndPerformanceMeasurementEx(IN CONST VOID * Handle,OPTIONAL IN CONST CHAR8 * Token,OPTIONAL IN CONST CHAR8 * Module,OPTIONAL IN UINT64 TimeStamp,IN UINT32 Identifier)603 EndPerformanceMeasurementEx (
604   IN CONST VOID   *Handle,  OPTIONAL
605   IN CONST CHAR8  *Token,   OPTIONAL
606   IN CONST CHAR8  *Module,  OPTIONAL
607   IN UINT64       TimeStamp,
608   IN UINT32       Identifier
609   )
610 {
611   return (RETURN_STATUS) EndGaugeEx (Handle, Token, Module, TimeStamp, Identifier);
612 }
613 
614 /**
615   Attempts to retrieve a performance measurement log entry from the performance measurement log.
616   It can also retrieve the log created by StartPerformanceMeasurement and EndPerformanceMeasurement,
617   and then assign the Identifier with 0.
618 
619   Attempts to retrieve the performance log entry specified by LogEntryKey.  If LogEntryKey is
620   zero on entry, then an attempt is made to retrieve the first entry from the performance log,
621   and the key for the second entry in the log is returned.  If the performance log is empty,
622   then no entry is retrieved and zero is returned.  If LogEntryKey is not zero, then the performance
623   log entry associated with LogEntryKey is retrieved, and the key for the next entry in the log is
624   returned.  If LogEntryKey is the key for the last entry in the log, then the last log entry is
625   retrieved and an implementation specific non-zero key value that specifies the end of the performance
626   log is returned.  If LogEntryKey is equal this implementation specific non-zero key value, then no entry
627   is retrieved and zero is returned.  In the cases where a performance log entry can be returned,
628   the log entry is returned in Handle, Token, Module, StartTimeStamp, EndTimeStamp and Identifier.
629   If LogEntryKey is not a valid log entry key for the performance measurement log, then ASSERT().
630   If Handle is NULL, then ASSERT().
631   If Token is NULL, then ASSERT().
632   If Module is NULL, then ASSERT().
633   If StartTimeStamp is NULL, then ASSERT().
634   If EndTimeStamp is NULL, then ASSERT().
635   If Identifier is NULL, then ASSERT().
636 
637   @param  LogEntryKey             On entry, the key of the performance measurement log entry to retrieve.
638                                   0, then the first performance measurement log entry is retrieved.
639                                   On exit, the key of the next performance log entry.
640   @param  Handle                  Pointer to environment specific context used to identify the component
641                                   being measured.
642   @param  Token                   Pointer to a Null-terminated ASCII string that identifies the component
643                                   being measured.
644   @param  Module                  Pointer to a Null-terminated ASCII string that identifies the module
645                                   being measured.
646   @param  StartTimeStamp          Pointer to the 64-bit time stamp that was recorded when the measurement
647                                   was started.
648   @param  EndTimeStamp            Pointer to the 64-bit time stamp that was recorded when the measurement
649                                   was ended.
650   @param  Identifier              Pointer to the 32-bit identifier that was recorded.
651 
652   @return The key for the next performance log entry (in general case).
653 
654 **/
655 UINTN
656 EFIAPI
GetPerformanceMeasurementEx(IN UINTN LogEntryKey,OUT CONST VOID ** Handle,OUT CONST CHAR8 ** Token,OUT CONST CHAR8 ** Module,OUT UINT64 * StartTimeStamp,OUT UINT64 * EndTimeStamp,OUT UINT32 * Identifier)657 GetPerformanceMeasurementEx (
658   IN  UINTN       LogEntryKey,
659   OUT CONST VOID  **Handle,
660   OUT CONST CHAR8 **Token,
661   OUT CONST CHAR8 **Module,
662   OUT UINT64      *StartTimeStamp,
663   OUT UINT64      *EndTimeStamp,
664   OUT UINT32      *Identifier
665   )
666 {
667   EFI_STATUS           Status;
668   GAUGE_DATA_ENTRY_EX  *GaugeData;
669 
670   GaugeData = NULL;
671 
672   ASSERT (Handle != NULL);
673   ASSERT (Token != NULL);
674   ASSERT (Module != NULL);
675   ASSERT (StartTimeStamp != NULL);
676   ASSERT (EndTimeStamp != NULL);
677   ASSERT (Identifier != NULL);
678 
679   Status = GetGaugeEx (LogEntryKey++, &GaugeData);
680 
681   //
682   // Make sure that LogEntryKey is a valid log entry key,
683   //
684   ASSERT (Status != EFI_INVALID_PARAMETER);
685 
686   if (EFI_ERROR (Status)) {
687     //
688     // The LogEntryKey is the last entry (equals to the total entry number).
689     //
690     return 0;
691   }
692 
693   ASSERT (GaugeData != NULL);
694 
695   *Handle         = (VOID *) (UINTN) GaugeData->Handle;
696   *Token          = GaugeData->Token;
697   *Module         = GaugeData->Module;
698   *StartTimeStamp = GaugeData->StartTimeStamp;
699   *EndTimeStamp   = GaugeData->EndTimeStamp;
700   *Identifier     = GaugeData->Identifier;
701 
702   return LogEntryKey;
703 }
704 
705 /**
706   Adds a record at the end of the performance measurement log
707   that records the start time of a performance measurement.
708 
709   Adds a record to the end of the performance measurement log
710   that contains the Handle, Token, and Module.
711   The end time of the new record must be set to zero.
712   If TimeStamp is not zero, then TimeStamp is used to fill in the start time in the record.
713   If TimeStamp is zero, the start time in the record is filled in with the value
714   read from the current time stamp.
715 
716   @param  Handle                  Pointer to environment specific context used
717                                   to identify the component being measured.
718   @param  Token                   Pointer to a Null-terminated ASCII string
719                                   that identifies the component being measured.
720   @param  Module                  Pointer to a Null-terminated ASCII string
721                                   that identifies the module being measured.
722   @param  TimeStamp               64-bit time stamp.
723 
724   @retval RETURN_SUCCESS          The start of the measurement was recorded.
725   @retval RETURN_OUT_OF_RESOURCES There are not enough resources to record the measurement.
726 
727 **/
728 RETURN_STATUS
729 EFIAPI
StartPerformanceMeasurement(IN CONST VOID * Handle,OPTIONAL IN CONST CHAR8 * Token,OPTIONAL IN CONST CHAR8 * Module,OPTIONAL IN UINT64 TimeStamp)730 StartPerformanceMeasurement (
731   IN CONST VOID   *Handle,  OPTIONAL
732   IN CONST CHAR8  *Token,   OPTIONAL
733   IN CONST CHAR8  *Module,  OPTIONAL
734   IN UINT64       TimeStamp
735   )
736 {
737   return StartPerformanceMeasurementEx (Handle, Token, Module, TimeStamp, 0);
738 }
739 
740 /**
741   Searches the performance measurement log from the beginning of the log
742   for the first matching record that contains a zero end time and fills in a valid end time.
743 
744   Searches the performance measurement log from the beginning of the log
745   for the first record that matches Handle, Token, and Module and has an end time value of zero.
746   If the record can not be found then return RETURN_NOT_FOUND.
747   If the record is found and TimeStamp is not zero,
748   then the end time in the record is filled in with the value specified by TimeStamp.
749   If the record is found and TimeStamp is zero, then the end time in the matching record
750   is filled in with the current time stamp value.
751 
752   @param  Handle                  Pointer to environment specific context used
753                                   to identify the component being measured.
754   @param  Token                   Pointer to a Null-terminated ASCII string
755                                   that identifies the component being measured.
756   @param  Module                  Pointer to a Null-terminated ASCII string
757                                   that identifies the module being measured.
758   @param  TimeStamp               64-bit time stamp.
759 
760   @retval RETURN_SUCCESS          The end of  the measurement was recorded.
761   @retval RETURN_NOT_FOUND        The specified measurement record could not be found.
762 
763 **/
764 RETURN_STATUS
765 EFIAPI
EndPerformanceMeasurement(IN CONST VOID * Handle,OPTIONAL IN CONST CHAR8 * Token,OPTIONAL IN CONST CHAR8 * Module,OPTIONAL IN UINT64 TimeStamp)766 EndPerformanceMeasurement (
767   IN CONST VOID   *Handle,  OPTIONAL
768   IN CONST CHAR8  *Token,   OPTIONAL
769   IN CONST CHAR8  *Module,  OPTIONAL
770   IN UINT64       TimeStamp
771   )
772 {
773   return EndPerformanceMeasurementEx (Handle, Token, Module, TimeStamp, 0);
774 }
775 
776 /**
777   Attempts to retrieve a performance measurement log entry from the performance measurement log.
778   It can also retrieve the log created by StartPerformanceMeasurementEx and EndPerformanceMeasurementEx,
779   and then eliminate the Identifier.
780 
781   Attempts to retrieve the performance log entry specified by LogEntryKey.  If LogEntryKey is
782   zero on entry, then an attempt is made to retrieve the first entry from the performance log,
783   and the key for the second entry in the log is returned.  If the performance log is empty,
784   then no entry is retrieved and zero is returned.  If LogEntryKey is not zero, then the performance
785   log entry associated with LogEntryKey is retrieved, and the key for the next entry in the log is
786   returned.  If LogEntryKey is the key for the last entry in the log, then the last log entry is
787   retrieved and an implementation specific non-zero key value that specifies the end of the performance
788   log is returned.  If LogEntryKey is equal this implementation specific non-zero key value, then no entry
789   is retrieved and zero is returned.  In the cases where a performance log entry can be returned,
790   the log entry is returned in Handle, Token, Module, StartTimeStamp, and EndTimeStamp.
791   If LogEntryKey is not a valid log entry key for the performance measurement log, then ASSERT().
792   If Handle is NULL, then ASSERT().
793   If Token is NULL, then ASSERT().
794   If Module is NULL, then ASSERT().
795   If StartTimeStamp is NULL, then ASSERT().
796   If EndTimeStamp is NULL, then ASSERT().
797 
798   @param  LogEntryKey             On entry, the key of the performance measurement log entry to retrieve.
799                                   0, then the first performance measurement log entry is retrieved.
800                                   On exit, the key of the next performance log entry.
801   @param  Handle                  Pointer to environment specific context used to identify the component
802                                   being measured.
803   @param  Token                   Pointer to a Null-terminated ASCII string that identifies the component
804                                   being measured.
805   @param  Module                  Pointer to a Null-terminated ASCII string that identifies the module
806                                   being measured.
807   @param  StartTimeStamp          Pointer to the 64-bit time stamp that was recorded when the measurement
808                                   was started.
809   @param  EndTimeStamp            Pointer to the 64-bit time stamp that was recorded when the measurement
810                                   was ended.
811 
812   @return The key for the next performance log entry (in general case).
813 
814 **/
815 UINTN
816 EFIAPI
GetPerformanceMeasurement(IN UINTN LogEntryKey,OUT CONST VOID ** Handle,OUT CONST CHAR8 ** Token,OUT CONST CHAR8 ** Module,OUT UINT64 * StartTimeStamp,OUT UINT64 * EndTimeStamp)817 GetPerformanceMeasurement (
818   IN  UINTN       LogEntryKey,
819   OUT CONST VOID  **Handle,
820   OUT CONST CHAR8 **Token,
821   OUT CONST CHAR8 **Module,
822   OUT UINT64      *StartTimeStamp,
823   OUT UINT64      *EndTimeStamp
824   )
825 {
826   UINT32 Identifier;
827   return GetPerformanceMeasurementEx (LogEntryKey, Handle, Token, Module, StartTimeStamp, EndTimeStamp, &Identifier);
828 }
829 
830 /**
831   Returns TRUE if the performance measurement macros are enabled.
832 
833   This function returns TRUE if the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of
834   PcdPerformanceLibraryPropertyMask is set.  Otherwise FALSE is returned.
835 
836   @retval TRUE                    The PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of
837                                   PcdPerformanceLibraryPropertyMask is set.
838   @retval FALSE                   The PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of
839                                   PcdPerformanceLibraryPropertyMask is clear.
840 
841 **/
842 BOOLEAN
843 EFIAPI
PerformanceMeasurementEnabled(VOID)844 PerformanceMeasurementEnabled (
845   VOID
846   )
847 {
848   return (BOOLEAN) ((PcdGet8(PcdPerformanceLibraryPropertyMask) & PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED) != 0);
849 }
850