Home | History | Annotate | Download | only in Dp_App
      1 /** @file
      2   Trace reporting for the Dp utility.
      3 
      4   Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.<BR>
      5   (C) Copyright 2015-2016 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
     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   @retval EFI_SUCCESS           The operation was successful.
    140   @retval EFI_ABORTED           The user aborts the operation.
    141   @return Others                from a call to gBS->LocateHandleBuffer().
    142 **/
    143 EFI_STATUS
    144 DumpAllTrace(
    145   IN UINTN             Limit,
    146   IN BOOLEAN           ExcludeFlag
    147   )
    148 {
    149   MEASUREMENT_RECORD        Measurement;
    150   UINT64                    ElapsedTime;
    151   UINT64                    Duration;
    152   const CHAR16              *IncFlag;
    153   UINTN                     LogEntryKey;
    154   UINTN                     Count;
    155   UINTN                     Index;
    156   UINTN                     TIndex;
    157 
    158   EFI_HANDLE                *HandleBuffer;
    159   UINTN                     HandleCount;
    160   EFI_STATUS                Status;
    161   EFI_STRING                StringPtrUnknown;
    162 
    163   StringPtrUnknown = HiiGetString (gHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL);
    164   IncFlag = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_SECTION_ALL), NULL);
    165   PrintToken( STRING_TOKEN (STR_DP_SECTION_HEADER),
    166               (IncFlag == NULL) ? StringPtrUnknown : IncFlag);
    167   FreePool (StringPtrUnknown);
    168 
    169   // Get Handle information
    170   //
    171   Status  = gBS->LocateHandleBuffer (AllHandles, NULL, NULL, &HandleCount, &HandleBuffer);
    172   if (EFI_ERROR (Status)) {
    173     PrintToken (STRING_TOKEN (STR_DP_HANDLES_ERROR), Status);
    174   }
    175   else {
    176     // We have successfully populated the HandleBuffer
    177     // Display ALL Measurement Records
    178     //    Up to Limit lines displayed
    179     //    Display only records with Elapsed times >= mInterestThreshold
    180     //    Display driver names in Module field for records with Handles.
    181     //
    182     if (mShowId) {
    183       PrintToken (STRING_TOKEN (STR_DP_ALL_HEADR2) );
    184       PrintToken (STRING_TOKEN (STR_DP_ALL_DASHES2) );
    185     } else {
    186       PrintToken (STRING_TOKEN (STR_DP_ALL_HEADR) );
    187       PrintToken (STRING_TOKEN (STR_DP_DASHES) );
    188     }
    189 
    190     LogEntryKey = 0;
    191     Count = 0;
    192     Index = 0;
    193     while ( WITHIN_LIMIT(Count, Limit) &&
    194             ((LogEntryKey = GetPerformanceMeasurementEx (
    195                             LogEntryKey,
    196                             &Measurement.Handle,
    197                             &Measurement.Token,
    198                             &Measurement.Module,
    199                             &Measurement.StartTimeStamp,
    200                             &Measurement.EndTimeStamp,
    201                             &Measurement.Identifier)) != 0)
    202           )
    203     {
    204       ++Index;    // Count every record.  First record is 1.
    205       ElapsedTime = 0;
    206       SafeFreePool ((VOID *) IncFlag);
    207       if (Measurement.EndTimeStamp != 0) {
    208         Duration = GetDuration (&Measurement);
    209         ElapsedTime = DurationInMicroSeconds ( Duration );
    210         IncFlag = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_COMPLETE), NULL);
    211       }
    212       else {
    213         IncFlag = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_INCOMPLETE), NULL);  // Mark incomplete records
    214       }
    215       if (((Measurement.EndTimeStamp != 0) && (ElapsedTime < mInterestThreshold)) ||
    216           ((ExcludeFlag) && (GetCumulativeItem(&Measurement) >= 0))
    217          ) {      // Ignore "uninteresting" or excluded records
    218         continue;
    219       }
    220       ++Count;    // Count the number of records printed
    221 
    222       // If Handle is non-zero, see if we can determine a name for the driver
    223       AsciiStrToUnicodeStrS (Measurement.Module, mGaugeString, ARRAY_SIZE (mGaugeString)); // Use Module by default
    224       AsciiStrToUnicodeStrS (Measurement.Token, mUnicodeToken, ARRAY_SIZE (mUnicodeToken));
    225       if (Measurement.Handle != NULL) {
    226         // See if the Handle is in the HandleBuffer
    227         for (TIndex = 0; TIndex < HandleCount; TIndex++) {
    228           if (Measurement.Handle == HandleBuffer[TIndex]) {
    229             GetNameFromHandle (HandleBuffer[TIndex]);
    230             break;
    231           }
    232         }
    233       }
    234 
    235       if (AsciiStrnCmp (Measurement.Token, ALit_PEIM, PERF_TOKEN_LENGTH) == 0) {
    236         UnicodeSPrint (mGaugeString, sizeof (mGaugeString), L"%g", Measurement.Handle);
    237       }
    238 
    239       // Ensure that the argument strings are not too long.
    240       mGaugeString[DP_GAUGE_STRING_LENGTH] = 0;
    241       mUnicodeToken[13] = 0;
    242 
    243       if (mShowId) {
    244         PrintToken( STRING_TOKEN (STR_DP_ALL_VARS2),
    245           Index,      // 1 based, Which measurement record is being printed
    246           IncFlag,
    247           Measurement.Handle,
    248           mGaugeString,
    249           mUnicodeToken,
    250           ElapsedTime,
    251           Measurement.Identifier
    252         );
    253       } else {
    254         PrintToken( STRING_TOKEN (STR_DP_ALL_VARS),
    255           Index,      // 1 based, Which measurement record is being printed
    256           IncFlag,
    257           Measurement.Handle,
    258           mGaugeString,
    259           mUnicodeToken,
    260           ElapsedTime
    261         );
    262       }
    263       if (ShellGetExecutionBreakFlag ()) {
    264         Status = EFI_ABORTED;
    265         break;
    266       }
    267     }
    268   }
    269   if (HandleBuffer != NULL) {
    270     FreePool (HandleBuffer);
    271   }
    272   SafeFreePool ((VOID *) IncFlag);
    273   return Status;
    274 }
    275 
    276 /**
    277   Gather and print Raw Trace Records.
    278 
    279   All Trace measurements with a duration greater than or equal to
    280   mInterestThreshold are printed without interpretation.
    281 
    282   The number of records displayed is controlled by:
    283      - records with a duration less than mInterestThreshold microseconds are not displayed.
    284      - No more than Limit records are displayed.  A Limit of zero will not limit the output.
    285      - If the ExcludeFlag is TRUE, records matching entries in the CumData array are not
    286        displayed.
    287 
    288   @pre    The mInterestThreshold global variable is set to the shortest duration to be printed.
    289 
    290   @param[in]    Limit       The number of records to print.  Zero is ALL.
    291   @param[in]    ExcludeFlag TRUE to exclude individual Cumulative items from display.
    292 
    293   @retval EFI_SUCCESS           The operation was successful.
    294   @retval EFI_ABORTED           The user aborts the operation.
    295 **/
    296 EFI_STATUS
    297 DumpRawTrace(
    298   IN UINTN          Limit,
    299   IN BOOLEAN        ExcludeFlag
    300   )
    301 {
    302   MEASUREMENT_RECORD        Measurement;
    303   UINT64                    ElapsedTime;
    304   UINT64                    Duration;
    305   UINTN                     LogEntryKey;
    306   UINTN                     Count;
    307   UINTN                     Index;
    308 
    309   EFI_STRING    StringPtr;
    310   EFI_STRING    StringPtrUnknown;
    311   EFI_STATUS    Status;
    312 
    313   Status = EFI_SUCCESS;
    314 
    315   StringPtrUnknown = HiiGetString (gHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL);
    316   StringPtr = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_SECTION_RAWTRACE), NULL);
    317   PrintToken( STRING_TOKEN (STR_DP_SECTION_HEADER),
    318               (StringPtr == NULL) ? StringPtrUnknown : StringPtr);
    319   FreePool (StringPtr);
    320   FreePool (StringPtrUnknown);
    321 
    322   if (mShowId) {
    323     PrintToken (STRING_TOKEN (STR_DP_RAW_HEADR2) );
    324     PrintToken (STRING_TOKEN (STR_DP_RAW_DASHES2) );
    325   } else {
    326     PrintToken (STRING_TOKEN (STR_DP_RAW_HEADR) );
    327     PrintToken (STRING_TOKEN (STR_DP_RAW_DASHES) );
    328   }
    329 
    330   LogEntryKey = 0;
    331   Count = 0;
    332   Index = 0;
    333   while ( WITHIN_LIMIT(Count, Limit) &&
    334           ((LogEntryKey = GetPerformanceMeasurementEx (
    335                           LogEntryKey,
    336                           &Measurement.Handle,
    337                           &Measurement.Token,
    338                           &Measurement.Module,
    339                           &Measurement.StartTimeStamp,
    340                           &Measurement.EndTimeStamp,
    341                           &Measurement.Identifier)) != 0)
    342         )
    343   {
    344     ++Index;    // Count every record.  First record is 1.
    345     ElapsedTime = 0;
    346     if (Measurement.EndTimeStamp != 0) {
    347       Duration = GetDuration (&Measurement);
    348       ElapsedTime = DurationInMicroSeconds ( Duration );
    349     }
    350     if ((ElapsedTime < mInterestThreshold)                 ||
    351         ((ExcludeFlag) && (GetCumulativeItem(&Measurement) >= 0))
    352         ) { // Ignore "uninteresting" or Excluded records
    353       continue;
    354     }
    355     ++Count;    // Count the number of records printed
    356 
    357     if (mShowId) {
    358       PrintToken (STRING_TOKEN (STR_DP_RAW_VARS2),
    359         Index,      // 1 based, Which measurement record is being printed
    360         Measurement.Handle,
    361         Measurement.StartTimeStamp,
    362         Measurement.EndTimeStamp,
    363         Measurement.Token,
    364         Measurement.Module,
    365         Measurement.Identifier
    366       );
    367     } else {
    368       PrintToken (STRING_TOKEN (STR_DP_RAW_VARS),
    369         Index,      // 1 based, Which measurement record is being printed
    370         Measurement.Handle,
    371         Measurement.StartTimeStamp,
    372         Measurement.EndTimeStamp,
    373         Measurement.Token,
    374         Measurement.Module
    375       );
    376     }
    377     if (ShellGetExecutionBreakFlag ()) {
    378       Status = EFI_ABORTED;
    379       break;
    380     }
    381   }
    382   return Status;
    383 }
    384 
    385 /**
    386   Gather and print Major Phase metrics.
    387 
    388   @param[in]    Ticker      The timer value for the END of Shell phase
    389 
    390 **/
    391 VOID
    392 ProcessPhases(
    393   IN UINT64            Ticker
    394   )
    395 {
    396   MEASUREMENT_RECORD        Measurement;
    397   UINT64                    BdsTimeoutValue;
    398   UINT64                    SecTime;
    399   UINT64                    PeiTime;
    400   UINT64                    DxeTime;
    401   UINT64                    BdsTime;
    402   UINT64                    ShellTime;
    403   UINT64                    ElapsedTime;
    404   UINT64                    Duration;
    405   UINT64                    Total;
    406   EFI_STRING                StringPtr;
    407   UINTN                     LogEntryKey;
    408   EFI_STRING                StringPtrUnknown;
    409 
    410   BdsTimeoutValue = 0;
    411   SecTime         = 0;
    412   PeiTime         = 0;
    413   DxeTime         = 0;
    414   BdsTime         = 0;
    415   ShellTime       = 0;
    416   //
    417   // Get Execution Phase Statistics
    418   //
    419   StringPtrUnknown = HiiGetString (gHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL);
    420   StringPtr = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_SECTION_PHASES), NULL);
    421   PrintToken( STRING_TOKEN (STR_DP_SECTION_HEADER),
    422               (StringPtr == NULL) ? StringPtrUnknown : StringPtr);
    423   FreePool (StringPtr);
    424   FreePool (StringPtrUnknown);
    425 
    426   LogEntryKey = 0;
    427   while ((LogEntryKey = GetPerformanceMeasurementEx (
    428                           LogEntryKey,
    429                           &Measurement.Handle,
    430                           &Measurement.Token,
    431                           &Measurement.Module,
    432                           &Measurement.StartTimeStamp,
    433                           &Measurement.EndTimeStamp,
    434                           &Measurement.Identifier)) != 0)
    435   {
    436     if (AsciiStrnCmp (Measurement.Token, ALit_SHELL, PERF_TOKEN_LENGTH) == 0) {
    437       Measurement.EndTimeStamp = Ticker;
    438     }
    439     if (Measurement.EndTimeStamp == 0) { // Skip "incomplete" records
    440       continue;
    441     }
    442     Duration = GetDuration (&Measurement);
    443     if (   Measurement.Handle != NULL
    444         && (AsciiStrnCmp (Measurement.Token, ALit_BdsTO, PERF_TOKEN_LENGTH) == 0)
    445        )
    446     {
    447       BdsTimeoutValue = Duration;
    448     } else if (AsciiStrnCmp (Measurement.Token, ALit_SEC, PERF_TOKEN_LENGTH) == 0) {
    449       SecTime     = Duration;
    450     } else if (AsciiStrnCmp (Measurement.Token, ALit_PEI, PERF_TOKEN_LENGTH) == 0) {
    451       PeiTime     = Duration;
    452     } else if (AsciiStrnCmp (Measurement.Token, ALit_DXE, PERF_TOKEN_LENGTH) == 0) {
    453       DxeTime      = Duration;
    454     } else if (AsciiStrnCmp (Measurement.Token, ALit_BDS, PERF_TOKEN_LENGTH) == 0) {
    455       BdsTime      = Duration;
    456     } else if (AsciiStrnCmp (Measurement.Token, ALit_SHELL, PERF_TOKEN_LENGTH) == 0) {
    457       ShellTime    = Duration;
    458     }
    459   }
    460 
    461   Total = 0;
    462 
    463   // print SEC phase duration time
    464   //
    465   if (SecTime > 0) {
    466     ElapsedTime = DurationInMicroSeconds ( SecTime );     // Calculate elapsed time in microseconds
    467     Total += DivU64x32 (ElapsedTime, 1000);   // Accumulate time in milliseconds
    468     PrintToken (STRING_TOKEN (STR_DP_SEC_PHASE), ElapsedTime);
    469   }
    470 
    471   // print PEI phase duration time
    472   //
    473   if (PeiTime > 0) {
    474     ElapsedTime = DivU64x32 (
    475                     PeiTime,
    476                     (UINT32)TimerInfo.Frequency
    477                     );
    478     Total += ElapsedTime;
    479     PrintToken (STRING_TOKEN (STR_DP_PHASE_DURATION), ALit_PEI, ElapsedTime);
    480   }
    481 
    482   // print DXE phase duration time
    483   //
    484   if (DxeTime > 0) {
    485     ElapsedTime = DivU64x32 (
    486                     DxeTime,
    487                     (UINT32)TimerInfo.Frequency
    488                     );
    489     Total += ElapsedTime;
    490     PrintToken (STRING_TOKEN (STR_DP_PHASE_DURATION), ALit_DXE, ElapsedTime);
    491   }
    492 
    493   // print BDS phase duration time
    494   //
    495   if (BdsTime > 0) {
    496     ElapsedTime = DivU64x32 (
    497                     BdsTime,
    498                     (UINT32)TimerInfo.Frequency
    499                     );
    500     Total += ElapsedTime;
    501     PrintToken (STRING_TOKEN (STR_DP_PHASE_DURATION), ALit_BDS, ElapsedTime);
    502   }
    503 
    504   if (BdsTimeoutValue > 0) {
    505     ElapsedTime = DivU64x32 (
    506                     BdsTimeoutValue,
    507                     (UINT32)TimerInfo.Frequency
    508                     );
    509     PrintToken (STRING_TOKEN (STR_DP_PHASE_BDSTO), ALit_BdsTO, ElapsedTime);
    510   }
    511 
    512   // print SHELL phase duration time
    513   //
    514   if (ShellTime > 0) {
    515     ElapsedTime = DivU64x32 (
    516                     ShellTime,
    517                     (UINT32)TimerInfo.Frequency
    518                     );
    519     Total += ElapsedTime;
    520     PrintToken (STRING_TOKEN (STR_DP_PHASE_DURATION), ALit_SHELL, ElapsedTime);
    521   }
    522 
    523   PrintToken (STRING_TOKEN (STR_DP_TOTAL_DURATION), Total);
    524 }
    525 
    526 /**
    527   Gather and print Handle data.
    528 
    529   @param[in]    ExcludeFlag   TRUE to exclude individual Cumulative items from display.
    530 
    531   @retval EFI_SUCCESS             The operation was successful.
    532   @retval EFI_ABORTED             The user aborts the operation.
    533   @return Others                  from a call to gBS->LocateHandleBuffer().
    534 **/
    535 EFI_STATUS
    536 ProcessHandles(
    537   IN BOOLEAN      ExcludeFlag
    538   )
    539 {
    540   MEASUREMENT_RECORD        Measurement;
    541   UINT64                    ElapsedTime;
    542   UINT64                    Duration;
    543   EFI_HANDLE                *HandleBuffer;
    544   EFI_STRING                StringPtr;
    545   UINTN                     Index;
    546   UINTN                     LogEntryKey;
    547   UINTN                     Count;
    548   UINTN                     HandleCount;
    549   EFI_STATUS                Status;
    550   EFI_STRING                StringPtrUnknown;
    551 
    552   StringPtrUnknown = HiiGetString (gHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL);
    553   StringPtr = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_SECTION_DRIVERS), NULL);
    554   PrintToken( STRING_TOKEN (STR_DP_SECTION_HEADER),
    555               (StringPtr == NULL) ? StringPtrUnknown : StringPtr);
    556   FreePool (StringPtr);
    557   FreePool (StringPtrUnknown);
    558 
    559   Status = gBS->LocateHandleBuffer (AllHandles, NULL, NULL, &HandleCount, &HandleBuffer);
    560   if (EFI_ERROR (Status)) {
    561     PrintToken (STRING_TOKEN (STR_DP_HANDLES_ERROR), Status);
    562   }
    563   else {
    564 #if DP_DEBUG == 2
    565     Print (L"There are %,d Handles defined.\n", (Size / sizeof(HandleBuffer[0])));
    566 #endif
    567 
    568     if (mShowId) {
    569       PrintToken (STRING_TOKEN (STR_DP_HANDLE_SECTION2) );
    570     } else {
    571       PrintToken (STRING_TOKEN (STR_DP_HANDLE_SECTION) );
    572     }
    573     PrintToken (STRING_TOKEN (STR_DP_DASHES) );
    574 
    575     LogEntryKey = 0;
    576     Count   = 0;
    577     while ((LogEntryKey = GetPerformanceMeasurementEx (
    578                             LogEntryKey,
    579                             &Measurement.Handle,
    580                             &Measurement.Token,
    581                             &Measurement.Module,
    582                             &Measurement.StartTimeStamp,
    583                             &Measurement.EndTimeStamp,
    584                             &Measurement.Identifier)) != 0)
    585     {
    586       Count++;
    587       Duration = GetDuration (&Measurement);
    588       ElapsedTime = DurationInMicroSeconds ( Duration );
    589       if ((ElapsedTime < mInterestThreshold)                 ||
    590           (Measurement.EndTimeStamp == 0)                    ||
    591           (Measurement.Handle == NULL)                       ||
    592           ((ExcludeFlag) && (GetCumulativeItem(&Measurement) >= 0))
    593          ) { // Ignore "uninteresting" or excluded records
    594         continue;
    595       }
    596       mGaugeString[0] = 0;    // Empty driver name by default
    597       AsciiStrToUnicodeStrS (Measurement.Token, mUnicodeToken, ARRAY_SIZE (mUnicodeToken));
    598       // See if the Handle is in the HandleBuffer
    599       for (Index = 0; Index < HandleCount; Index++) {
    600         if (Measurement.Handle == HandleBuffer[Index]) {
    601           GetNameFromHandle (HandleBuffer[Index]); // Name is put into mGaugeString
    602           break;
    603         }
    604       }
    605       // Ensure that the argument strings are not too long.
    606       mGaugeString[DP_GAUGE_STRING_LENGTH] = 0;
    607       mUnicodeToken[11] = 0;
    608       if (mGaugeString[0] != 0) {
    609         // Display the record if it has a valid handle.
    610         if (mShowId) {
    611           PrintToken (
    612             STRING_TOKEN (STR_DP_HANDLE_VARS2),
    613             Count,      // 1 based, Which measurement record is being printed
    614             Index + 1,  // 1 based, Which handle is being printed
    615             mGaugeString,
    616             mUnicodeToken,
    617             ElapsedTime,
    618             Measurement.Identifier
    619           );
    620         } else {
    621           PrintToken (
    622             STRING_TOKEN (STR_DP_HANDLE_VARS),
    623             Count,      // 1 based, Which measurement record is being printed
    624             Index + 1,  // 1 based, Which handle is being printed
    625             mGaugeString,
    626             mUnicodeToken,
    627             ElapsedTime
    628           );
    629         }
    630       }
    631       if (ShellGetExecutionBreakFlag ()) {
    632         Status = EFI_ABORTED;
    633         break;
    634       }
    635     }
    636   }
    637   if (HandleBuffer != NULL) {
    638     FreePool (HandleBuffer);
    639   }
    640   return Status;
    641 }
    642 
    643 /**
    644   Gather and print PEIM data.
    645 
    646   Only prints complete PEIM records
    647 
    648   @retval EFI_SUCCESS           The operation was successful.
    649   @retval EFI_ABORTED           The user aborts the operation.
    650 **/
    651 EFI_STATUS
    652 ProcessPeims(
    653   VOID
    654 )
    655 {
    656   MEASUREMENT_RECORD        Measurement;
    657   UINT64                    Duration;
    658   UINT64                    ElapsedTime;
    659   EFI_STRING                StringPtr;
    660   UINTN                     LogEntryKey;
    661   UINTN                     TIndex;
    662   EFI_STRING                StringPtrUnknown;
    663   EFI_STATUS                Status;
    664 
    665   Status = EFI_SUCCESS;
    666 
    667   StringPtrUnknown = HiiGetString (gHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL);
    668   StringPtr = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_SECTION_PEIMS), NULL);
    669   PrintToken( STRING_TOKEN (STR_DP_SECTION_HEADER),
    670               (StringPtr == NULL) ? StringPtrUnknown : StringPtr);
    671   FreePool (StringPtr);
    672   FreePool (StringPtrUnknown);
    673 
    674   if (mShowId) {
    675     PrintToken (STRING_TOKEN (STR_DP_PEIM_SECTION2));
    676   } else {
    677     PrintToken (STRING_TOKEN (STR_DP_PEIM_SECTION));
    678   }
    679   PrintToken (STRING_TOKEN (STR_DP_DASHES));
    680   TIndex  = 0;
    681   LogEntryKey = 0;
    682   while ((LogEntryKey = GetPerformanceMeasurementEx (
    683                           LogEntryKey,
    684                           &Measurement.Handle,
    685                           &Measurement.Token,
    686                           &Measurement.Module,
    687                           &Measurement.StartTimeStamp,
    688                           &Measurement.EndTimeStamp,
    689                           &Measurement.Identifier)) != 0)
    690   {
    691     TIndex++;
    692     if ((Measurement.EndTimeStamp == 0) ||
    693         (AsciiStrnCmp (Measurement.Token, ALit_PEIM, PERF_TOKEN_LENGTH) != 0)
    694        ) {
    695       continue;
    696     }
    697 
    698     Duration = GetDuration (&Measurement);
    699     ElapsedTime = DurationInMicroSeconds ( Duration );  // Calculate elapsed time in microseconds
    700     if (ElapsedTime >= mInterestThreshold) {
    701       // PEIM FILE Handle is the start address of its FFS file that contains its file guid.
    702       if (mShowId) {
    703         PrintToken (STRING_TOKEN (STR_DP_PEIM_VARS2),
    704               TIndex,   // 1 based, Which measurement record is being printed
    705               Measurement.Handle,  // base address
    706               Measurement.Handle,  // file guid
    707               ElapsedTime,
    708               Measurement.Identifier
    709         );
    710       } else {
    711         PrintToken (STRING_TOKEN (STR_DP_PEIM_VARS),
    712               TIndex,   // 1 based, Which measurement record is being printed
    713               Measurement.Handle,  // base address
    714               Measurement.Handle,  // file guid
    715               ElapsedTime
    716         );
    717       }
    718     }
    719     if (ShellGetExecutionBreakFlag ()) {
    720       Status = EFI_ABORTED;
    721       break;
    722     }
    723   }
    724   return Status;
    725 }
    726 
    727 /**
    728   Gather and print global data.
    729 
    730   Strips out incomplete or "Execution Phase" records
    731   Only prints records where Handle is NULL
    732   Increment TIndex for every record, even skipped ones, so that we have an
    733   indication of every measurement record taken.
    734 
    735   @retval EFI_SUCCESS           The operation was successful.
    736   @retval EFI_ABORTED           The user aborts the operation.
    737 **/
    738 EFI_STATUS
    739 ProcessGlobal(
    740   VOID
    741 )
    742 {
    743   MEASUREMENT_RECORD        Measurement;
    744   UINT64                    Duration;
    745   UINT64                    ElapsedTime;
    746   EFI_STRING                StringPtr;
    747   UINTN                     LogEntryKey;
    748   UINTN                     Index;        // Index, or number, of the measurement record being processed
    749   EFI_STRING                StringPtrUnknown;
    750   EFI_STATUS                Status;
    751 
    752   Status = EFI_SUCCESS;
    753 
    754   StringPtrUnknown = HiiGetString (gHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL);
    755   StringPtr = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_SECTION_GENERAL), NULL);
    756   PrintToken( STRING_TOKEN (STR_DP_SECTION_HEADER),
    757               (StringPtr == NULL) ? StringPtrUnknown: StringPtr);
    758   FreePool (StringPtr);
    759   FreePool (StringPtrUnknown);
    760 
    761   if (mShowId) {
    762     PrintToken (STRING_TOKEN (STR_DP_GLOBAL_SECTION2));
    763   } else {
    764     PrintToken (STRING_TOKEN (STR_DP_GLOBAL_SECTION));
    765   }
    766   PrintToken (STRING_TOKEN (STR_DP_DASHES));
    767 
    768   Index = 1;
    769   LogEntryKey = 0;
    770 
    771   while ((LogEntryKey = GetPerformanceMeasurementEx (
    772                           LogEntryKey,
    773                           &Measurement.Handle,
    774                           &Measurement.Token,
    775                           &Measurement.Module,
    776                           &Measurement.StartTimeStamp,
    777                           &Measurement.EndTimeStamp,
    778                           &Measurement.Identifier)) != 0)
    779   {
    780     AsciiStrToUnicodeStrS (Measurement.Module, mGaugeString, ARRAY_SIZE (mGaugeString));
    781     AsciiStrToUnicodeStrS (Measurement.Token, mUnicodeToken, ARRAY_SIZE (mUnicodeToken));
    782     mGaugeString[25] = 0;
    783     mUnicodeToken[31] = 0;
    784     if ( ! ( IsPhase( &Measurement)  ||
    785         (Measurement.Handle != NULL)      ||
    786         (Measurement.EndTimeStamp == 0)
    787         ))
    788     {
    789       Duration = GetDuration (&Measurement);
    790       ElapsedTime = DurationInMicroSeconds ( Duration );
    791       if (ElapsedTime >= mInterestThreshold) {
    792         if (mShowId) {
    793           PrintToken (
    794             STRING_TOKEN (STR_DP_GLOBAL_VARS2),
    795             Index,
    796             mGaugeString,
    797             mUnicodeToken,
    798             ElapsedTime,
    799             Measurement.Identifier
    800             );
    801         } else {
    802            PrintToken (
    803             STRING_TOKEN (STR_DP_GLOBAL_VARS),
    804             Index,
    805             mGaugeString,
    806             mUnicodeToken,
    807             ElapsedTime
    808             );
    809         }
    810       }
    811     }
    812     if (ShellGetExecutionBreakFlag ()) {
    813       Status = EFI_ABORTED;
    814       break;
    815     }
    816     Index++;
    817   }
    818   return Status;
    819 }
    820 
    821 /**
    822   Gather and print cumulative data.
    823 
    824   Traverse the measurement records and:<BR>
    825   For each record with a Token listed in the CumData array:<BR>
    826      - Update the instance count and the total, minimum, and maximum durations.
    827   Finally, print the gathered cumulative statistics.
    828 
    829   @param[in]    CustomCumulativeData  A pointer to the cumtom cumulative data.
    830 
    831 **/
    832 VOID
    833 ProcessCumulative(
    834   IN PERF_CUM_DATA                  *CustomCumulativeData OPTIONAL
    835   )
    836 {
    837   UINT64                    AvgDur;         // the computed average duration
    838   UINT64                    Dur;
    839   UINT64                    MinDur;
    840   UINT64                    MaxDur;
    841   EFI_STRING                StringPtr;
    842   UINTN                     TIndex;
    843   EFI_STRING                StringPtrUnknown;
    844 
    845   StringPtrUnknown = HiiGetString (gHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL);
    846   StringPtr = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_SECTION_CUMULATIVE), NULL);
    847   PrintToken( STRING_TOKEN (STR_DP_SECTION_HEADER),
    848               (StringPtr == NULL) ? StringPtrUnknown: StringPtr);
    849   FreePool (StringPtr);
    850   FreePool (StringPtrUnknown);
    851 
    852   PrintToken (STRING_TOKEN (STR_DP_CUMULATIVE_SECT_1));
    853   PrintToken (STRING_TOKEN (STR_DP_CUMULATIVE_SECT_2));
    854   PrintToken (STRING_TOKEN (STR_DP_DASHES));
    855 
    856   for ( TIndex = 0; TIndex < NumCum; ++TIndex) {
    857     if (CumData[TIndex].Count != 0) {
    858       AvgDur = DivU64x32 (CumData[TIndex].Duration, CumData[TIndex].Count);
    859       AvgDur = DurationInMicroSeconds(AvgDur);
    860       Dur    = DurationInMicroSeconds(CumData[TIndex].Duration);
    861       MaxDur = DurationInMicroSeconds(CumData[TIndex].MaxDur);
    862       MinDur = DurationInMicroSeconds(CumData[TIndex].MinDur);
    863 
    864       PrintToken (STRING_TOKEN (STR_DP_CUMULATIVE_STATS),
    865                   CumData[TIndex].Name,
    866                   CumData[TIndex].Count,
    867                   Dur,
    868                   AvgDur,
    869                   MinDur,
    870                   MaxDur
    871                  );
    872     }
    873   }
    874 
    875   //
    876   // Print the custom cumulative data.
    877   //
    878   if (CustomCumulativeData != NULL) {
    879     if (CustomCumulativeData->Count != 0) {
    880       AvgDur = DivU64x32 (CustomCumulativeData->Duration, CustomCumulativeData->Count);
    881       AvgDur = DurationInMicroSeconds (AvgDur);
    882       Dur    = DurationInMicroSeconds (CustomCumulativeData->Duration);
    883       MaxDur = DurationInMicroSeconds (CustomCumulativeData->MaxDur);
    884       MinDur = DurationInMicroSeconds (CustomCumulativeData->MinDur);
    885     } else {
    886       AvgDur = 0;
    887       Dur    = 0;
    888       MaxDur = 0;
    889       MinDur = 0;
    890     }
    891     PrintToken (STRING_TOKEN (STR_DP_CUMULATIVE_STATS),
    892                 CustomCumulativeData->Name,
    893                 CustomCumulativeData->Count,
    894                 Dur,
    895                 AvgDur,
    896                 MinDur,
    897                 MaxDur
    898                 );
    899   }
    900 }
    901