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