• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /** @file
2   Trace reporting for the Dp utility.
3 
4   Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.<BR>
5   (C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
6   This program and the accompanying materials
7   are licensed and made available under the terms and conditions of the BSD License
8   which accompanies this distribution.  The full text of the license may be found at
9   http://opensource.org/licenses/bsd-license.php
10 
11   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13 **/
14 
15 #include <Library/BaseLib.h>
16 #include <Library/BaseMemoryLib.h>
17 #include <Library/MemoryAllocationLib.h>
18 #include <Library/DebugLib.h>
19 #include <Library/UefiBootServicesTableLib.h>
20 #include <Library/TimerLib.h>
21 #include <Library/PeCoffGetEntryPointLib.h>
22 #include <Library/PerformanceLib.h>
23 #include <Library/PrintLib.h>
24 #include <Library/HiiLib.h>
25 #include <Library/PcdLib.h>
26 
27 #include <Guid/Performance.h>
28 
29 #include "Dp.h"
30 #include "Literals.h"
31 #include "DpInternal.h"
32 
33 /**
34   Collect verbose statistics about the logged performance measurements.
35 
36   General Summary information for all Trace measurements is gathered and
37   stored within the SummaryData structure.  This information is both
38   used internally by subsequent reporting functions, and displayed
39   at the end of verbose reports.
40 
41   @pre  The SummaryData and CumData structures must be initialized
42         prior to calling this function.
43 
44   @post The SummaryData and CumData structures contain statistics for the
45         current performance logs.
46 
47   @param[in, out] CustomCumulativeData  A pointer to the cumtom cumulative data.
48 
49 **/
50 VOID
GatherStatistics(IN OUT PERF_CUM_DATA * CustomCumulativeData OPTIONAL)51 GatherStatistics(
52   IN OUT PERF_CUM_DATA              *CustomCumulativeData OPTIONAL
53   )
54 {
55   MEASUREMENT_RECORD        Measurement;
56   UINT64                    Duration;
57   UINTN                     LogEntryKey;
58   INTN                      TIndex;
59 
60   LogEntryKey = 0;
61   while ((LogEntryKey = GetPerformanceMeasurementEx (
62                         LogEntryKey,
63                         &Measurement.Handle,
64                         &Measurement.Token,
65                         &Measurement.Module,
66                         &Measurement.StartTimeStamp,
67                         &Measurement.EndTimeStamp,
68                         &Measurement.Identifier)) != 0)
69   {
70     ++SummaryData.NumTrace;           // Count the number of TRACE Measurement records
71     if (Measurement.EndTimeStamp == 0) {
72       ++SummaryData.NumIncomplete;    // Count the incomplete records
73       continue;
74     }
75 
76     if (Measurement.Handle != NULL) {
77       ++SummaryData.NumHandles;       // Count the number of measurements with non-NULL handles
78     }
79 
80     if (IsPhase( &Measurement)) {
81       ++SummaryData.NumSummary;       // Count the number of major phases
82     }
83     else {  // !IsPhase(...
84       if(Measurement.Handle == NULL) {
85         ++SummaryData.NumGlobal;
86       }
87     }
88 
89     if (AsciiStrnCmp (Measurement.Token, ALit_PEIM, PERF_TOKEN_LENGTH) == 0) {
90       ++SummaryData.NumPEIMs;         // Count PEIM measurements
91     }
92 
93     Duration = GetDuration (&Measurement);
94     TIndex = GetCumulativeItem (&Measurement);
95     if (TIndex >= 0) {
96       CumData[TIndex].Duration += Duration;
97       CumData[TIndex].Count++;
98       if ( Duration < CumData[TIndex].MinDur ) {
99         CumData[TIndex].MinDur = Duration;
100       }
101       if ( Duration > CumData[TIndex].MaxDur ) {
102         CumData[TIndex].MaxDur = Duration;
103       }
104     }
105 
106     //
107     // Collect the data for custom cumulative data.
108     //
109     if ((CustomCumulativeData != NULL) && (AsciiStrCmp (Measurement.Token, CustomCumulativeData->Name) == 0)) {
110       CustomCumulativeData->Duration += Duration;
111       CustomCumulativeData->Count++;
112       if (Duration < CustomCumulativeData->MinDur) {
113         CustomCumulativeData->MinDur = Duration;
114       }
115       if (Duration > CustomCumulativeData->MaxDur) {
116         CustomCumulativeData->MaxDur = Duration;
117       }
118     }
119   }
120 }
121 
122 /**
123   Gather and print ALL Trace Records.
124 
125   Displays all "interesting" Trace measurements in order.<BR>
126   The number of records displayed is controlled by:
127      - records with a duration less than mInterestThreshold microseconds are not displayed.
128      - No more than Limit records are displayed.  A Limit of zero will not limit the output.
129      - If the ExcludeFlag is TRUE, records matching entries in the CumData array are not
130        displayed.
131 
132   @pre    The mInterestThreshold global variable is set to the shortest duration to be printed.
133            The mGaugeString and mUnicodeToken global arrays are used for temporary string storage.
134            They must not be in use by a calling function.
135 
136   @param[in]    Limit       The number of records to print.  Zero is ALL.
137   @param[in]    ExcludeFlag TRUE to exclude individual Cumulative items from display.
138 
139 **/
140 VOID
DumpAllTrace(IN UINTN Limit,IN BOOLEAN ExcludeFlag)141 DumpAllTrace(
142   IN UINTN             Limit,
143   IN BOOLEAN           ExcludeFlag
144   )
145 {
146   MEASUREMENT_RECORD        Measurement;
147   UINT64                    ElapsedTime;
148   UINT64                    Duration;
149   const CHAR16              *IncFlag;
150   UINTN                     LogEntryKey;
151   UINTN                     Count;
152   UINTN                     Index;
153   UINTN                     TIndex;
154 
155   EFI_HANDLE                *HandleBuffer;
156   UINTN                     Size;
157   EFI_HANDLE                TempHandle;
158   EFI_STATUS                Status;
159   EFI_STRING                StringPtrUnknown;
160 
161   StringPtrUnknown = HiiGetString (gHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL);
162   IncFlag = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_SECTION_ALL), NULL);
163   PrintToken( STRING_TOKEN (STR_DP_SECTION_HEADER),
164               (IncFlag == NULL) ? StringPtrUnknown : IncFlag);
165   FreePool (StringPtrUnknown);
166 
167   // Get Handle information
168   //
169   Size = 0;
170   HandleBuffer = &TempHandle;
171   Status  = gBS->LocateHandle (AllHandles, NULL, NULL, &Size, &TempHandle);
172   if (Status == EFI_BUFFER_TOO_SMALL) {
173     HandleBuffer = AllocatePool (Size);
174     ASSERT (HandleBuffer != NULL);
175     if (HandleBuffer == NULL) {
176       return;
177     }
178     Status  = gBS->LocateHandle (AllHandles, NULL, NULL, &Size, HandleBuffer);
179   }
180   if (EFI_ERROR (Status)) {
181     PrintToken (STRING_TOKEN (STR_DP_HANDLES_ERROR), Status);
182   }
183   else {
184     // We have successfully populated the HandleBuffer
185     // Display ALL Measurement Records
186     //    Up to Limit lines displayed
187     //    Display only records with Elapsed times >= mInterestThreshold
188     //    Display driver names in Module field for records with Handles.
189     //
190     if (mShowId) {
191       PrintToken (STRING_TOKEN (STR_DP_ALL_HEADR2) );
192       PrintToken (STRING_TOKEN (STR_DP_ALL_DASHES2) );
193     } else {
194       PrintToken (STRING_TOKEN (STR_DP_ALL_HEADR) );
195       PrintToken (STRING_TOKEN (STR_DP_DASHES) );
196     }
197 
198     LogEntryKey = 0;
199     Count = 0;
200     Index = 0;
201     while ( WITHIN_LIMIT(Count, Limit) &&
202             ((LogEntryKey = GetPerformanceMeasurementEx (
203                             LogEntryKey,
204                             &Measurement.Handle,
205                             &Measurement.Token,
206                             &Measurement.Module,
207                             &Measurement.StartTimeStamp,
208                             &Measurement.EndTimeStamp,
209                             &Measurement.Identifier)) != 0)
210           )
211     {
212       ++Index;    // Count every record.  First record is 1.
213       ElapsedTime = 0;
214       SafeFreePool ((VOID *) IncFlag);
215       if (Measurement.EndTimeStamp != 0) {
216         Duration = GetDuration (&Measurement);
217         ElapsedTime = DurationInMicroSeconds ( Duration );
218         IncFlag = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_COMPLETE), NULL);
219       }
220       else {
221         IncFlag = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_INCOMPLETE), NULL);  // Mark incomplete records
222       }
223       if (((Measurement.EndTimeStamp != 0) && (ElapsedTime < mInterestThreshold)) ||
224           ((ExcludeFlag) && (GetCumulativeItem(&Measurement) >= 0))
225          ) {      // Ignore "uninteresting" or excluded records
226         continue;
227       }
228       ++Count;    // Count the number of records printed
229 
230       // If Handle is non-zero, see if we can determine a name for the driver
231       AsciiStrToUnicodeStr (Measurement.Module, mGaugeString); // Use Module by default
232       AsciiStrToUnicodeStr (Measurement.Token, mUnicodeToken);
233       if (Measurement.Handle != NULL) {
234         // See if the Handle is in the HandleBuffer
235         for (TIndex = 0; TIndex < (Size / sizeof(HandleBuffer[0])); TIndex++) {
236           if (Measurement.Handle == HandleBuffer[TIndex]) {
237             GetNameFromHandle (HandleBuffer[TIndex]);
238             break;
239           }
240         }
241       }
242 
243       if (AsciiStrnCmp (Measurement.Token, ALit_PEIM, PERF_TOKEN_LENGTH) == 0) {
244         UnicodeSPrint (mGaugeString, sizeof (mGaugeString), L"%g", Measurement.Handle);
245       }
246 
247       // Ensure that the argument strings are not too long.
248       mGaugeString[DP_GAUGE_STRING_LENGTH] = 0;
249       mUnicodeToken[13] = 0;
250 
251       if (mShowId) {
252         PrintToken( STRING_TOKEN (STR_DP_ALL_VARS2),
253           Index,      // 1 based, Which measurement record is being printed
254           IncFlag,
255           Measurement.Handle,
256           mGaugeString,
257           mUnicodeToken,
258           ElapsedTime,
259           Measurement.Identifier
260         );
261       } else {
262         PrintToken( STRING_TOKEN (STR_DP_ALL_VARS),
263           Index,      // 1 based, Which measurement record is being printed
264           IncFlag,
265           Measurement.Handle,
266           mGaugeString,
267           mUnicodeToken,
268           ElapsedTime
269         );
270       }
271     }
272   }
273   if (HandleBuffer != &TempHandle) {
274     FreePool (HandleBuffer);
275   }
276   SafeFreePool ((VOID *) IncFlag);
277 }
278 
279 /**
280   Gather and print Raw Trace Records.
281 
282   All Trace measurements with a duration greater than or equal to
283   mInterestThreshold are printed without interpretation.
284 
285   The number of records displayed is controlled by:
286      - records with a duration less than mInterestThreshold microseconds are not displayed.
287      - No more than Limit records are displayed.  A Limit of zero will not limit the output.
288      - If the ExcludeFlag is TRUE, records matching entries in the CumData array are not
289        displayed.
290 
291   @pre    The mInterestThreshold global variable is set to the shortest duration to be printed.
292 
293   @param[in]    Limit       The number of records to print.  Zero is ALL.
294   @param[in]    ExcludeFlag TRUE to exclude individual Cumulative items from display.
295 
296 **/
297 VOID
DumpRawTrace(IN UINTN Limit,IN BOOLEAN ExcludeFlag)298 DumpRawTrace(
299   IN UINTN          Limit,
300   IN BOOLEAN        ExcludeFlag
301   )
302 {
303   MEASUREMENT_RECORD        Measurement;
304   UINT64                    ElapsedTime;
305   UINT64                    Duration;
306   UINTN                     LogEntryKey;
307   UINTN                     Count;
308   UINTN                     Index;
309 
310   EFI_STRING    StringPtr;
311   EFI_STRING    StringPtrUnknown;
312 
313   StringPtrUnknown = HiiGetString (gHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL);
314   StringPtr = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_SECTION_RAWTRACE), NULL);
315   PrintToken( STRING_TOKEN (STR_DP_SECTION_HEADER),
316               (StringPtr == NULL) ? StringPtrUnknown : StringPtr);
317   FreePool (StringPtr);
318   FreePool (StringPtrUnknown);
319 
320   if (mShowId) {
321     PrintToken (STRING_TOKEN (STR_DP_RAW_HEADR2) );
322     PrintToken (STRING_TOKEN (STR_DP_RAW_DASHES2) );
323   } else {
324     PrintToken (STRING_TOKEN (STR_DP_RAW_HEADR) );
325     PrintToken (STRING_TOKEN (STR_DP_RAW_DASHES) );
326   }
327 
328   LogEntryKey = 0;
329   Count = 0;
330   Index = 0;
331   while ( WITHIN_LIMIT(Count, Limit) &&
332           ((LogEntryKey = GetPerformanceMeasurementEx (
333                           LogEntryKey,
334                           &Measurement.Handle,
335                           &Measurement.Token,
336                           &Measurement.Module,
337                           &Measurement.StartTimeStamp,
338                           &Measurement.EndTimeStamp,
339                           &Measurement.Identifier)) != 0)
340         )
341   {
342     ++Index;    // Count every record.  First record is 1.
343     ElapsedTime = 0;
344     if (Measurement.EndTimeStamp != 0) {
345       Duration = GetDuration (&Measurement);
346       ElapsedTime = DurationInMicroSeconds ( Duration );
347     }
348     if ((ElapsedTime < mInterestThreshold)                 ||
349         ((ExcludeFlag) && (GetCumulativeItem(&Measurement) >= 0))
350         ) { // Ignore "uninteresting" or Excluded records
351       continue;
352     }
353     ++Count;    // Count the number of records printed
354 
355     if (mShowId) {
356       PrintToken (STRING_TOKEN (STR_DP_RAW_VARS2),
357         Index,      // 1 based, Which measurement record is being printed
358         Measurement.Handle,
359         Measurement.StartTimeStamp,
360         Measurement.EndTimeStamp,
361         Measurement.Token,
362         Measurement.Module,
363         Measurement.Identifier
364       );
365     } else {
366       PrintToken (STRING_TOKEN (STR_DP_RAW_VARS),
367         Index,      // 1 based, Which measurement record is being printed
368         Measurement.Handle,
369         Measurement.StartTimeStamp,
370         Measurement.EndTimeStamp,
371         Measurement.Token,
372         Measurement.Module
373       );
374     }
375   }
376 }
377 
378 /**
379   Gather and print Major Phase metrics.
380 
381   @param[in]    Ticker      The timer value for the END of Shell phase
382 
383 **/
384 VOID
ProcessPhases(IN UINT64 Ticker)385 ProcessPhases(
386   IN UINT64            Ticker
387   )
388 {
389   MEASUREMENT_RECORD        Measurement;
390   UINT64                    BdsTimeoutValue;
391   UINT64                    SecTime;
392   UINT64                    PeiTime;
393   UINT64                    DxeTime;
394   UINT64                    BdsTime;
395   UINT64                    ShellTime;
396   UINT64                    ElapsedTime;
397   UINT64                    Duration;
398   UINT64                    Total;
399   EFI_STRING                StringPtr;
400   UINTN                     LogEntryKey;
401   EFI_STRING                StringPtrUnknown;
402 
403   BdsTimeoutValue = 0;
404   SecTime         = 0;
405   PeiTime         = 0;
406   DxeTime         = 0;
407   BdsTime         = 0;
408   ShellTime       = 0;
409   //
410   // Get Execution Phase Statistics
411   //
412   StringPtrUnknown = HiiGetString (gHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL);
413   StringPtr = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_SECTION_PHASES), NULL);
414   PrintToken( STRING_TOKEN (STR_DP_SECTION_HEADER),
415               (StringPtr == NULL) ? StringPtrUnknown : StringPtr);
416   FreePool (StringPtr);
417   FreePool (StringPtrUnknown);
418 
419   LogEntryKey = 0;
420   while ((LogEntryKey = GetPerformanceMeasurementEx (
421                           LogEntryKey,
422                           &Measurement.Handle,
423                           &Measurement.Token,
424                           &Measurement.Module,
425                           &Measurement.StartTimeStamp,
426                           &Measurement.EndTimeStamp,
427                           &Measurement.Identifier)) != 0)
428   {
429     if (AsciiStrnCmp (Measurement.Token, ALit_SHELL, PERF_TOKEN_LENGTH) == 0) {
430       Measurement.EndTimeStamp = Ticker;
431     }
432     if (Measurement.EndTimeStamp == 0) { // Skip "incomplete" records
433       continue;
434     }
435     Duration = GetDuration (&Measurement);
436     if (   Measurement.Handle != NULL
437         && (AsciiStrnCmp (Measurement.Token, ALit_BdsTO, PERF_TOKEN_LENGTH) == 0)
438        )
439     {
440       BdsTimeoutValue = Duration;
441     } else if (AsciiStrnCmp (Measurement.Token, ALit_SEC, PERF_TOKEN_LENGTH) == 0) {
442       SecTime     = Duration;
443     } else if (AsciiStrnCmp (Measurement.Token, ALit_PEI, PERF_TOKEN_LENGTH) == 0) {
444       PeiTime     = Duration;
445     } else if (AsciiStrnCmp (Measurement.Token, ALit_DXE, PERF_TOKEN_LENGTH) == 0) {
446       DxeTime      = Duration;
447     } else if (AsciiStrnCmp (Measurement.Token, ALit_BDS, PERF_TOKEN_LENGTH) == 0) {
448       BdsTime      = Duration;
449     } else if (AsciiStrnCmp (Measurement.Token, ALit_SHELL, PERF_TOKEN_LENGTH) == 0) {
450       ShellTime    = Duration;
451     }
452   }
453 
454   Total = 0;
455 
456   // print SEC phase duration time
457   //
458   if (SecTime > 0) {
459     ElapsedTime = DurationInMicroSeconds ( SecTime );     // Calculate elapsed time in microseconds
460     Total += DivU64x32 (ElapsedTime, 1000);   // Accumulate time in milliseconds
461     PrintToken (STRING_TOKEN (STR_DP_SEC_PHASE), ElapsedTime);
462   }
463 
464   // print PEI phase duration time
465   //
466   if (PeiTime > 0) {
467     ElapsedTime = DivU64x32 (
468                     PeiTime,
469                     (UINT32)TimerInfo.Frequency
470                     );
471     Total += ElapsedTime;
472     PrintToken (STRING_TOKEN (STR_DP_PHASE_DURATION), ALit_PEI, ElapsedTime);
473   }
474 
475   // print DXE phase duration time
476   //
477   if (DxeTime > 0) {
478     ElapsedTime = DivU64x32 (
479                     DxeTime,
480                     (UINT32)TimerInfo.Frequency
481                     );
482     Total += ElapsedTime;
483     PrintToken (STRING_TOKEN (STR_DP_PHASE_DURATION), ALit_DXE, ElapsedTime);
484   }
485 
486   // print BDS phase duration time
487   //
488   if (BdsTime > 0) {
489     ElapsedTime = DivU64x32 (
490                     BdsTime,
491                     (UINT32)TimerInfo.Frequency
492                     );
493     Total += ElapsedTime;
494     PrintToken (STRING_TOKEN (STR_DP_PHASE_DURATION), ALit_BDS, ElapsedTime);
495   }
496 
497   if (BdsTimeoutValue > 0) {
498     ElapsedTime = DivU64x32 (
499                     BdsTimeoutValue,
500                     (UINT32)TimerInfo.Frequency
501                     );
502     PrintToken (STRING_TOKEN (STR_DP_PHASE_BDSTO), ALit_BdsTO, ElapsedTime);
503   }
504 
505   // print SHELL phase duration time
506   //
507   if (ShellTime > 0) {
508     ElapsedTime = DivU64x32 (
509                     ShellTime,
510                     (UINT32)TimerInfo.Frequency
511                     );
512     Total += ElapsedTime;
513     PrintToken (STRING_TOKEN (STR_DP_PHASE_DURATION), ALit_SHELL, ElapsedTime);
514   }
515 
516   PrintToken (STRING_TOKEN (STR_DP_TOTAL_DURATION), Total);
517 }
518 
519 /**
520   Gather and print Handle data.
521 
522   @param[in]    ExcludeFlag   TRUE to exclude individual Cumulative items from display.
523 
524   @return       Status from a call to gBS->LocateHandle().
525 **/
526 EFI_STATUS
ProcessHandles(IN BOOLEAN ExcludeFlag)527 ProcessHandles(
528   IN BOOLEAN      ExcludeFlag
529   )
530 {
531   MEASUREMENT_RECORD        Measurement;
532   UINT64                    ElapsedTime;
533   UINT64                    Duration;
534   EFI_HANDLE                *HandleBuffer;
535   EFI_STRING                StringPtr;
536   UINTN                     Index;
537   UINTN                     LogEntryKey;
538   UINTN                     Count;
539   UINTN                     Size;
540   EFI_HANDLE                TempHandle;
541   EFI_STATUS                Status;
542   EFI_STRING                StringPtrUnknown;
543 
544   StringPtrUnknown = HiiGetString (gHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL);
545   StringPtr = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_SECTION_DRIVERS), NULL);
546   PrintToken( STRING_TOKEN (STR_DP_SECTION_HEADER),
547               (StringPtr == NULL) ? StringPtrUnknown : StringPtr);
548   FreePool (StringPtr);
549   FreePool (StringPtrUnknown);
550 
551   Size = 0;
552   HandleBuffer = &TempHandle;
553   Status  = gBS->LocateHandle (AllHandles, NULL, NULL, &Size, &TempHandle);
554   if (Status == EFI_BUFFER_TOO_SMALL) {
555     HandleBuffer = AllocatePool (Size);
556     ASSERT (HandleBuffer != NULL);
557     if (HandleBuffer == NULL) {
558       return Status;
559     }
560     Status  = gBS->LocateHandle (AllHandles, NULL, NULL, &Size, HandleBuffer);
561   }
562   if (EFI_ERROR (Status)) {
563     PrintToken (STRING_TOKEN (STR_DP_HANDLES_ERROR), Status);
564   }
565   else {
566 #if DP_DEBUG == 2
567     Print (L"There are %,d Handles defined.\n", (Size / sizeof(HandleBuffer[0])));
568 #endif
569 
570     if (mShowId) {
571       PrintToken (STRING_TOKEN (STR_DP_HANDLE_SECTION2) );
572     } else {
573       PrintToken (STRING_TOKEN (STR_DP_HANDLE_SECTION) );
574     }
575     PrintToken (STRING_TOKEN (STR_DP_DASHES) );
576 
577     LogEntryKey = 0;
578     Count   = 0;
579     while ((LogEntryKey = GetPerformanceMeasurementEx (
580                             LogEntryKey,
581                             &Measurement.Handle,
582                             &Measurement.Token,
583                             &Measurement.Module,
584                             &Measurement.StartTimeStamp,
585                             &Measurement.EndTimeStamp,
586                             &Measurement.Identifier)) != 0)
587     {
588       Count++;
589       Duration = GetDuration (&Measurement);
590       ElapsedTime = DurationInMicroSeconds ( Duration );
591       if ((ElapsedTime < mInterestThreshold)                 ||
592           (Measurement.EndTimeStamp == 0)                    ||
593           (Measurement.Handle == NULL)                       ||
594           ((ExcludeFlag) && (GetCumulativeItem(&Measurement) >= 0))
595          ) { // Ignore "uninteresting" or excluded records
596         continue;
597       }
598       mGaugeString[0] = 0;    // Empty driver name by default
599       AsciiStrToUnicodeStr (Measurement.Token, mUnicodeToken);
600       // See if the Handle is in the HandleBuffer
601       for (Index = 0; Index < (Size / sizeof(HandleBuffer[0])); Index++) {
602         if (Measurement.Handle == HandleBuffer[Index]) {
603           GetNameFromHandle (HandleBuffer[Index]); // Name is put into mGaugeString
604           break;
605         }
606       }
607       // Ensure that the argument strings are not too long.
608       mGaugeString[DP_GAUGE_STRING_LENGTH] = 0;
609       mUnicodeToken[11] = 0;
610       if (mGaugeString[0] != 0) {
611         // Display the record if it has a valid handle.
612         if (mShowId) {
613           PrintToken (
614             STRING_TOKEN (STR_DP_HANDLE_VARS2),
615             Count,      // 1 based, Which measurement record is being printed
616             Index + 1,  // 1 based, Which handle is being printed
617             mGaugeString,
618             mUnicodeToken,
619             ElapsedTime,
620             Measurement.Identifier
621           );
622         } else {
623           PrintToken (
624             STRING_TOKEN (STR_DP_HANDLE_VARS),
625             Count,      // 1 based, Which measurement record is being printed
626             Index + 1,  // 1 based, Which handle is being printed
627             mGaugeString,
628             mUnicodeToken,
629             ElapsedTime
630           );
631         }
632       }
633     }
634   }
635   if (HandleBuffer != &TempHandle) {
636     FreePool (HandleBuffer);
637   }
638   return Status;
639 }
640 
641 /**
642   Gather and print PEIM data.
643 
644   Only prints complete PEIM records
645 
646 **/
647 VOID
ProcessPeims(VOID)648 ProcessPeims(
649   VOID
650 )
651 {
652   MEASUREMENT_RECORD        Measurement;
653   UINT64                    Duration;
654   UINT64                    ElapsedTime;
655   EFI_STRING                StringPtr;
656   UINTN                     LogEntryKey;
657   UINTN                     TIndex;
658   EFI_STRING                StringPtrUnknown;
659 
660   StringPtrUnknown = HiiGetString (gHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL);
661   StringPtr = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_SECTION_PEIMS), NULL);
662   PrintToken( STRING_TOKEN (STR_DP_SECTION_HEADER),
663               (StringPtr == NULL) ? StringPtrUnknown : StringPtr);
664   FreePool (StringPtr);
665   FreePool (StringPtrUnknown);
666 
667   if (mShowId) {
668     PrintToken (STRING_TOKEN (STR_DP_PEIM_SECTION2));
669   } else {
670     PrintToken (STRING_TOKEN (STR_DP_PEIM_SECTION));
671   }
672   PrintToken (STRING_TOKEN (STR_DP_DASHES));
673   TIndex  = 0;
674   LogEntryKey = 0;
675   while ((LogEntryKey = GetPerformanceMeasurementEx (
676                           LogEntryKey,
677                           &Measurement.Handle,
678                           &Measurement.Token,
679                           &Measurement.Module,
680                           &Measurement.StartTimeStamp,
681                           &Measurement.EndTimeStamp,
682                           &Measurement.Identifier)) != 0)
683   {
684     TIndex++;
685     if ((Measurement.EndTimeStamp == 0) ||
686         (AsciiStrnCmp (Measurement.Token, ALit_PEIM, PERF_TOKEN_LENGTH) != 0)
687        ) {
688       continue;
689     }
690 
691     Duration = GetDuration (&Measurement);
692     ElapsedTime = DurationInMicroSeconds ( Duration );  // Calculate elapsed time in microseconds
693     if (ElapsedTime >= mInterestThreshold) {
694       // PEIM FILE Handle is the start address of its FFS file that contains its file guid.
695       if (mShowId) {
696         PrintToken (STRING_TOKEN (STR_DP_PEIM_VARS2),
697               TIndex,   // 1 based, Which measurement record is being printed
698               Measurement.Handle,  // base address
699               Measurement.Handle,  // file guid
700               ElapsedTime,
701               Measurement.Identifier
702         );
703       } else {
704         PrintToken (STRING_TOKEN (STR_DP_PEIM_VARS),
705               TIndex,   // 1 based, Which measurement record is being printed
706               Measurement.Handle,  // base address
707               Measurement.Handle,  // file guid
708               ElapsedTime
709         );
710       }
711     }
712   }
713 }
714 
715 /**
716   Gather and print global data.
717 
718   Strips out incomplete or "Execution Phase" records
719   Only prints records where Handle is NULL
720   Increment TIndex for every record, even skipped ones, so that we have an
721   indication of every measurement record taken.
722 
723 **/
724 VOID
ProcessGlobal(VOID)725 ProcessGlobal(
726   VOID
727 )
728 {
729   MEASUREMENT_RECORD        Measurement;
730   UINT64                    Duration;
731   UINT64                    ElapsedTime;
732   EFI_STRING                StringPtr;
733   UINTN                     LogEntryKey;
734   UINTN                     Index;        // Index, or number, of the measurement record being processed
735   EFI_STRING                StringPtrUnknown;
736 
737   StringPtrUnknown = HiiGetString (gHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL);
738   StringPtr = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_SECTION_GENERAL), NULL);
739   PrintToken( STRING_TOKEN (STR_DP_SECTION_HEADER),
740               (StringPtr == NULL) ? StringPtrUnknown: StringPtr);
741   FreePool (StringPtr);
742   FreePool (StringPtrUnknown);
743 
744   if (mShowId) {
745     PrintToken (STRING_TOKEN (STR_DP_GLOBAL_SECTION2));
746   } else {
747     PrintToken (STRING_TOKEN (STR_DP_GLOBAL_SECTION));
748   }
749   PrintToken (STRING_TOKEN (STR_DP_DASHES));
750 
751   Index = 1;
752   LogEntryKey = 0;
753 
754   while ((LogEntryKey = GetPerformanceMeasurementEx (
755                           LogEntryKey,
756                           &Measurement.Handle,
757                           &Measurement.Token,
758                           &Measurement.Module,
759                           &Measurement.StartTimeStamp,
760                           &Measurement.EndTimeStamp,
761                           &Measurement.Identifier)) != 0)
762   {
763     AsciiStrToUnicodeStr (Measurement.Module, mGaugeString);
764     AsciiStrToUnicodeStr (Measurement.Token, mUnicodeToken);
765     mGaugeString[25] = 0;
766     mUnicodeToken[31] = 0;
767     if ( ! ( IsPhase( &Measurement)  ||
768         (Measurement.Handle != NULL)      ||
769         (Measurement.EndTimeStamp == 0)
770         ))
771     {
772       Duration = GetDuration (&Measurement);
773       ElapsedTime = DurationInMicroSeconds ( Duration );
774       if (ElapsedTime >= mInterestThreshold) {
775         if (mShowId) {
776           PrintToken (
777             STRING_TOKEN (STR_DP_GLOBAL_VARS2),
778             Index,
779             mGaugeString,
780             mUnicodeToken,
781             ElapsedTime,
782             Measurement.Identifier
783             );
784         } else {
785            PrintToken (
786             STRING_TOKEN (STR_DP_GLOBAL_VARS),
787             Index,
788             mGaugeString,
789             mUnicodeToken,
790             ElapsedTime
791             );
792         }
793       }
794     }
795     Index++;
796   }
797 }
798 
799 /**
800   Gather and print cumulative data.
801 
802   Traverse the measurement records and:<BR>
803   For each record with a Token listed in the CumData array:<BR>
804      - Update the instance count and the total, minimum, and maximum durations.
805   Finally, print the gathered cumulative statistics.
806 
807   @param[in]    CustomCumulativeData  A pointer to the cumtom cumulative data.
808 
809 **/
810 VOID
ProcessCumulative(IN PERF_CUM_DATA * CustomCumulativeData OPTIONAL)811 ProcessCumulative(
812   IN PERF_CUM_DATA                  *CustomCumulativeData OPTIONAL
813   )
814 {
815   UINT64                    AvgDur;         // the computed average duration
816   UINT64                    Dur;
817   UINT64                    MinDur;
818   UINT64                    MaxDur;
819   EFI_STRING                StringPtr;
820   UINTN                     TIndex;
821   EFI_STRING                StringPtrUnknown;
822 
823   StringPtrUnknown = HiiGetString (gHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL);
824   StringPtr = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_SECTION_CUMULATIVE), NULL);
825   PrintToken( STRING_TOKEN (STR_DP_SECTION_HEADER),
826               (StringPtr == NULL) ? StringPtrUnknown: StringPtr);
827   FreePool (StringPtr);
828   FreePool (StringPtrUnknown);
829 
830   PrintToken (STRING_TOKEN (STR_DP_CUMULATIVE_SECT_1));
831   PrintToken (STRING_TOKEN (STR_DP_CUMULATIVE_SECT_2));
832   PrintToken (STRING_TOKEN (STR_DP_DASHES));
833 
834   for ( TIndex = 0; TIndex < NumCum; ++TIndex) {
835     if (CumData[TIndex].Count != 0) {
836       AvgDur = DivU64x32 (CumData[TIndex].Duration, CumData[TIndex].Count);
837       AvgDur = DurationInMicroSeconds(AvgDur);
838       Dur    = DurationInMicroSeconds(CumData[TIndex].Duration);
839       MaxDur = DurationInMicroSeconds(CumData[TIndex].MaxDur);
840       MinDur = DurationInMicroSeconds(CumData[TIndex].MinDur);
841 
842       PrintToken (STRING_TOKEN (STR_DP_CUMULATIVE_STATS),
843                   CumData[TIndex].Name,
844                   CumData[TIndex].Count,
845                   Dur,
846                   AvgDur,
847                   MinDur,
848                   MaxDur
849                  );
850     }
851   }
852 
853   //
854   // Print the custom cumulative data.
855   //
856   if (CustomCumulativeData != NULL) {
857     if (CustomCumulativeData->Count != 0) {
858       AvgDur = DivU64x32 (CustomCumulativeData->Duration, CustomCumulativeData->Count);
859       AvgDur = DurationInMicroSeconds (AvgDur);
860       Dur    = DurationInMicroSeconds (CustomCumulativeData->Duration);
861       MaxDur = DurationInMicroSeconds (CustomCumulativeData->MaxDur);
862       MinDur = DurationInMicroSeconds (CustomCumulativeData->MinDur);
863     } else {
864       AvgDur = 0;
865       Dur    = 0;
866       MaxDur = 0;
867       MinDur = 0;
868     }
869     PrintToken (STRING_TOKEN (STR_DP_CUMULATIVE_STATS),
870                 CustomCumulativeData->Name,
871                 CustomCumulativeData->Count,
872                 Dur,
873                 AvgDur,
874                 MinDur,
875                 MaxDur
876                 );
877   }
878 }
879