Since performance library instances have been updated to create new FPDT records for new Perf macros. So enhance dp tool to parse the new FPDT records. Enhancement mainly includes: 1. parse the single records for PERF_EVENT macro 2. Parse the new added FPDT_DUAL_GUID_STRING_EVENT_RECORD Cc: Liming Gao <liming.gao@intel.com> Cc: Ruiyu Ni <ruiyu.ni@intel.com> Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Dandan Bi <dandan.bi@intel.com> Reviewed-by: Liming Gao <liming.gao@intel.com>
		
			
				
	
	
		
			911 lines
		
	
	
		
			33 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			911 lines
		
	
	
		
			33 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @file
 | |
|   Trace reporting for the Dp utility.
 | |
| 
 | |
|   Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
 | |
|   (C) Copyright 2015-2016 Hewlett Packard Enterprise Development LP<BR>
 | |
|   This program and the accompanying materials
 | |
|   are licensed and made available under the terms and conditions of the BSD License
 | |
|   which accompanies this distribution.  The full text of the license may be found at
 | |
|   http://opensource.org/licenses/bsd-license.php
 | |
| 
 | |
|   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
 | |
|   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 | |
| **/
 | |
| 
 | |
| #include <Library/BaseLib.h>
 | |
| #include <Library/BaseMemoryLib.h>
 | |
| #include <Library/MemoryAllocationLib.h>
 | |
| #include <Library/DebugLib.h>
 | |
| #include <Library/UefiBootServicesTableLib.h>
 | |
| #include <Library/PeCoffGetEntryPointLib.h>
 | |
| #include <Library/PerformanceLib.h>
 | |
| #include <Library/PrintLib.h>
 | |
| #include <Library/HiiLib.h>
 | |
| #include <Library/PcdLib.h>
 | |
| 
 | |
| #include "Dp.h"
 | |
| #include "Literals.h"
 | |
| #include "DpInternal.h"
 | |
| 
 | |
| /**
 | |
|   Attempts to retrieve a performance measurement log entry from the performance measurement log.
 | |
| 
 | |
| 
 | |
|   @param  LogEntryKey             On entry, the key of the performance measurement log entry to retrieve.
 | |
|                                   0, then the first performance measurement log entry is retrieved.
 | |
|                                   On exit, the key of the next performance log entry.
 | |
|   @param  Handle                  Pointer to environment specific context used to identify the component
 | |
|                                   being measured.
 | |
|   @param  Token                   Pointer to a Null-terminated ASCII string that identifies the component
 | |
|                                   being measured.
 | |
|   @param  Module                  Pointer to a Null-terminated ASCII string that identifies the module
 | |
|                                   being measured.
 | |
|   @param  StartTimeStamp          Pointer to the 64-bit time stamp that was recorded when the measurement
 | |
|                                   was started.
 | |
|   @param  EndTimeStamp            Pointer to the 64-bit time stamp that was recorded when the measurement
 | |
|                                   was ended.
 | |
|   @param  Identifier              Pointer to the 32-bit identifier that was recorded when the measurement
 | |
|                                   was ended.
 | |
| 
 | |
|   @return The key for the next performance log entry (in general case).
 | |
| 
 | |
| **/
 | |
| UINTN
 | |
| GetPerformanceMeasurementRecord (
 | |
|  IN  UINTN       LogEntryKey,
 | |
|  OUT CONST VOID  **Handle,
 | |
|  OUT CONST CHAR8 **Token,
 | |
|  OUT CONST CHAR8 **Module,
 | |
|  OUT UINT64      *StartTimeStamp,
 | |
|  OUT UINT64      *EndTimeStamp,
 | |
|  OUT UINT32      *Identifier
 | |
|   )
 | |
| {
 | |
|   if (LogEntryKey == mMeasurementNum) {
 | |
|     return 0;
 | |
|   }
 | |
| 
 | |
|   *Handle         = (VOID *) (UINTN) mMeasurementList[LogEntryKey].Handle;
 | |
|   *Token          = mMeasurementList[LogEntryKey].Token;
 | |
|   *Module         = mMeasurementList[LogEntryKey].Module;
 | |
|   *StartTimeStamp = mMeasurementList[LogEntryKey].StartTimeStamp;
 | |
|   *EndTimeStamp   = mMeasurementList[LogEntryKey].EndTimeStamp;
 | |
|   *Identifier     = mMeasurementList[LogEntryKey].Identifier;
 | |
| 
 | |
|   LogEntryKey ++;
 | |
| 
 | |
|   return LogEntryKey;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Collect verbose statistics about the logged performance measurements.
 | |
| 
 | |
|   General Summary information for all Trace measurements is gathered and
 | |
|   stored within the SummaryData structure.  This information is both
 | |
|   used internally by subsequent reporting functions, and displayed
 | |
|   at the end of verbose reports.
 | |
| 
 | |
|   @pre  The SummaryData and CumData structures must be initialized
 | |
|         prior to calling this function.
 | |
| 
 | |
|   @post The SummaryData and CumData structures contain statistics for the
 | |
|         current performance logs.
 | |
| 
 | |
|   @param[in, out] CustomCumulativeData  A pointer to the cumtom cumulative data.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| GatherStatistics(
 | |
|   IN OUT PERF_CUM_DATA              *CustomCumulativeData OPTIONAL
 | |
|   )
 | |
| {
 | |
|   MEASUREMENT_RECORD        Measurement;
 | |
|   UINT64                    Duration;
 | |
|   UINTN                     LogEntryKey;
 | |
|   INTN                      TIndex;
 | |
| 
 | |
|   LogEntryKey = 0;
 | |
|   while ((LogEntryKey = GetPerformanceMeasurementRecord (
 | |
|                         LogEntryKey,
 | |
|                         &Measurement.Handle,
 | |
|                         &Measurement.Token,
 | |
|                         &Measurement.Module,
 | |
|                         &Measurement.StartTimeStamp,
 | |
|                         &Measurement.EndTimeStamp,
 | |
|                         &Measurement.Identifier)) != 0)
 | |
|   {
 | |
|     ++SummaryData.NumTrace;           // Count the number of TRACE Measurement records
 | |
|     if (Measurement.EndTimeStamp == 0) {
 | |
|       ++SummaryData.NumIncomplete;    // Count the incomplete records
 | |
|       continue;
 | |
|     }
 | |
| 
 | |
|     if (Measurement.Handle != NULL) {
 | |
|       ++SummaryData.NumHandles;       // Count the number of measurements with non-NULL handles
 | |
|     }
 | |
| 
 | |
|     if (IsPhase( &Measurement)) {
 | |
|       ++SummaryData.NumSummary;       // Count the number of major phases
 | |
|     }
 | |
|     else {  // !IsPhase
 | |
|       if(Measurement.Handle == NULL) {
 | |
|         ++SummaryData.NumGlobal;
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     if (AsciiStrCmp (Measurement.Token, ALit_PEIM) == 0) {
 | |
|       ++SummaryData.NumPEIMs;         // Count PEIM measurements
 | |
|     }
 | |
| 
 | |
|     Duration = GetDuration (&Measurement);
 | |
|     TIndex = GetCumulativeItem (&Measurement);
 | |
|     if (TIndex >= 0) {
 | |
|       CumData[TIndex].Duration += Duration;
 | |
|       CumData[TIndex].Count++;
 | |
|       if ( Duration < CumData[TIndex].MinDur ) {
 | |
|         CumData[TIndex].MinDur = Duration;
 | |
|       }
 | |
|       if ( Duration > CumData[TIndex].MaxDur ) {
 | |
|         CumData[TIndex].MaxDur = Duration;
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // Collect the data for custom cumulative data.
 | |
|     //
 | |
|     if ((CustomCumulativeData != NULL) && (AsciiStrCmp (Measurement.Token, CustomCumulativeData->Name) == 0)) {
 | |
|       CustomCumulativeData->Duration += Duration;
 | |
|       CustomCumulativeData->Count++;
 | |
|       if (Duration < CustomCumulativeData->MinDur) {
 | |
|         CustomCumulativeData->MinDur = Duration;
 | |
|       }
 | |
|       if (Duration > CustomCumulativeData->MaxDur) {
 | |
|         CustomCumulativeData->MaxDur = Duration;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Gather and print ALL Trace Records.
 | |
| 
 | |
|   Displays all "interesting" Trace measurements in order.<BR>
 | |
|   The number of records displayed is controlled by:
 | |
|      - records with a duration less than mInterestThreshold microseconds are not displayed.
 | |
|      - No more than Limit records are displayed.  A Limit of zero will not limit the output.
 | |
|      - If the ExcludeFlag is TRUE, records matching entries in the CumData array are not
 | |
|        displayed.
 | |
| 
 | |
|   @pre    The mInterestThreshold global variable is set to the shortest duration to be printed.
 | |
|            The mGaugeString and mUnicodeToken global arrays are used for temporary string storage.
 | |
|            They must not be in use by a calling function.
 | |
| 
 | |
|   @param[in]    Limit       The number of records to print.  Zero is ALL.
 | |
|   @param[in]    ExcludeFlag TRUE to exclude individual Cumulative items from display.
 | |
| 
 | |
|   @retval EFI_SUCCESS           The operation was successful.
 | |
|   @retval EFI_ABORTED           The user aborts the operation.
 | |
|   @return Others                from a call to gBS->LocateHandleBuffer().
 | |
| **/
 | |
| EFI_STATUS
 | |
| DumpAllTrace(
 | |
|   IN UINTN             Limit,
 | |
|   IN BOOLEAN           ExcludeFlag
 | |
|   )
 | |
| {
 | |
|   MEASUREMENT_RECORD        Measurement;
 | |
|   UINT64                    ElapsedTime;
 | |
|   UINT64                    Duration;
 | |
|   CHAR16                    *IncFlag;
 | |
|   UINTN                     LogEntryKey;
 | |
|   UINTN                     Count;
 | |
|   UINTN                     Index;
 | |
|   UINTN                     TIndex;
 | |
| 
 | |
|   EFI_HANDLE                *HandleBuffer;
 | |
|   UINTN                     HandleCount;
 | |
|   EFI_STATUS                Status;
 | |
|   EFI_STRING                StringPtrUnknown;
 | |
| 
 | |
|   StringPtrUnknown = HiiGetString (mDpHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL);
 | |
|   IncFlag = HiiGetString (mDpHiiHandle, STRING_TOKEN (STR_DP_SECTION_ALL), NULL);
 | |
|   ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_SECTION_HEADER), mDpHiiHandle,
 | |
|               (IncFlag == NULL) ? StringPtrUnknown : IncFlag);
 | |
|   FreePool (StringPtrUnknown);
 | |
| 
 | |
|   // Get Handle information
 | |
|   //
 | |
|   Status  = gBS->LocateHandleBuffer (AllHandles, NULL, NULL, &HandleCount, &HandleBuffer);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_HANDLES_ERROR), mDpHiiHandle, Status);
 | |
|   }
 | |
|   else {
 | |
|     // We have successfully populated the HandleBuffer
 | |
|     // Display ALL Measurement Records
 | |
|     //    Up to Limit lines displayed
 | |
|     //    Display only records with Elapsed times >= mInterestThreshold
 | |
|     //    Display driver names in Module field for records with Handles.
 | |
|     //
 | |
|     if (mShowId) {
 | |
|       ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_ALL_HEADR2), mDpHiiHandle);
 | |
|       ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_ALL_DASHES2), mDpHiiHandle);
 | |
|     } else {
 | |
|       ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_ALL_HEADR), mDpHiiHandle);
 | |
|       ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_DASHES), mDpHiiHandle);
 | |
|     }
 | |
| 
 | |
|     LogEntryKey = 0;
 | |
|     Count = 0;
 | |
|     Index = 0;
 | |
|     while ( WITHIN_LIMIT(Count, Limit) &&
 | |
|             ((LogEntryKey = GetPerformanceMeasurementRecord (
 | |
|                             LogEntryKey,
 | |
|                             &Measurement.Handle,
 | |
|                             &Measurement.Token,
 | |
|                             &Measurement.Module,
 | |
|                             &Measurement.StartTimeStamp,
 | |
|                             &Measurement.EndTimeStamp,
 | |
|                             &Measurement.Identifier)) != 0)
 | |
|           )
 | |
|     {
 | |
|       ++Index;    // Count every record.  First record is 1.
 | |
|       ElapsedTime = 0;
 | |
|       SHELL_FREE_NON_NULL (IncFlag);
 | |
|       if (Measurement.EndTimeStamp != 0) {
 | |
|         Duration = GetDuration (&Measurement);
 | |
|         ElapsedTime = DurationInMicroSeconds ( Duration );
 | |
|         IncFlag = HiiGetString (mDpHiiHandle, STRING_TOKEN (STR_DP_COMPLETE), NULL);
 | |
|       }
 | |
|       else {
 | |
|         IncFlag = HiiGetString (mDpHiiHandle, STRING_TOKEN (STR_DP_INCOMPLETE), NULL);  // Mark incomplete records
 | |
|       }
 | |
|       if (((Measurement.EndTimeStamp != 0) && (ElapsedTime < mInterestThreshold)) ||
 | |
|           ((ExcludeFlag) && (GetCumulativeItem(&Measurement) >= 0))
 | |
|          ) {      // Ignore "uninteresting" or excluded records
 | |
|         continue;
 | |
|       }
 | |
|       ++Count;    // Count the number of records printed
 | |
| 
 | |
|       // If Handle is non-zero, see if we can determine a name for the driver
 | |
|       AsciiStrToUnicodeStrS (Measurement.Module, mGaugeString, ARRAY_SIZE (mGaugeString)); // Use Module by default
 | |
|       AsciiStrToUnicodeStrS (Measurement.Token, mUnicodeToken, ARRAY_SIZE (mUnicodeToken));
 | |
|       if (Measurement.Handle != NULL) {
 | |
|         // See if the Handle is in the HandleBuffer
 | |
|         for (TIndex = 0; TIndex < HandleCount; TIndex++) {
 | |
|           if (Measurement.Handle == HandleBuffer[TIndex]) {
 | |
|             DpGetNameFromHandle (HandleBuffer[TIndex]);
 | |
|             break;
 | |
|           }
 | |
|         }
 | |
|       }
 | |
| 
 | |
|       if (AsciiStrCmp (Measurement.Token, ALit_PEIM) == 0) {
 | |
|         UnicodeSPrint (mGaugeString, sizeof (mGaugeString), L"%g", Measurement.Handle);
 | |
|       }
 | |
| 
 | |
|       // Ensure that the argument strings are not too long.
 | |
|       mGaugeString[DP_GAUGE_STRING_LENGTH] = 0;
 | |
|       mUnicodeToken[13] = 0;
 | |
| 
 | |
|       if (mShowId) {
 | |
|         ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_ALL_VARS2), mDpHiiHandle,
 | |
|           Index,      // 1 based, Which measurement record is being printed
 | |
|           IncFlag,
 | |
|           Measurement.Handle,
 | |
|           mGaugeString,
 | |
|           mUnicodeToken,
 | |
|           ElapsedTime,
 | |
|           Measurement.Identifier
 | |
|         );
 | |
|       } else {
 | |
|         ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_ALL_VARS), mDpHiiHandle,
 | |
|           Index,      // 1 based, Which measurement record is being printed
 | |
|           IncFlag,
 | |
|           Measurement.Handle,
 | |
|           mGaugeString,
 | |
|           mUnicodeToken,
 | |
|           ElapsedTime
 | |
|         );
 | |
|       }
 | |
|       if (ShellGetExecutionBreakFlag ()) {
 | |
|         Status = EFI_ABORTED;
 | |
|         break;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
|   if (HandleBuffer != NULL) {
 | |
|     FreePool (HandleBuffer);
 | |
|   }
 | |
|   SHELL_FREE_NON_NULL (IncFlag);
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Gather and print Raw Trace Records.
 | |
| 
 | |
|   All Trace measurements with a duration greater than or equal to
 | |
|   mInterestThreshold are printed without interpretation.
 | |
| 
 | |
|   The number of records displayed is controlled by:
 | |
|      - records with a duration less than mInterestThreshold microseconds are not displayed.
 | |
|      - No more than Limit records are displayed.  A Limit of zero will not limit the output.
 | |
|      - If the ExcludeFlag is TRUE, records matching entries in the CumData array are not
 | |
|        displayed.
 | |
| 
 | |
|   @pre    The mInterestThreshold global variable is set to the shortest duration to be printed.
 | |
| 
 | |
|   @param[in]    Limit       The number of records to print.  Zero is ALL.
 | |
|   @param[in]    ExcludeFlag TRUE to exclude individual Cumulative items from display.
 | |
| 
 | |
|   @retval EFI_SUCCESS           The operation was successful.
 | |
|   @retval EFI_ABORTED           The user aborts the operation.
 | |
| **/
 | |
| EFI_STATUS
 | |
| DumpRawTrace(
 | |
|   IN UINTN          Limit,
 | |
|   IN BOOLEAN        ExcludeFlag
 | |
|   )
 | |
| {
 | |
|   MEASUREMENT_RECORD        Measurement;
 | |
|   UINT64                    ElapsedTime;
 | |
|   UINT64                    Duration;
 | |
|   UINTN                     LogEntryKey;
 | |
|   UINTN                     Count;
 | |
|   UINTN                     Index;
 | |
| 
 | |
|   EFI_STRING    StringPtr;
 | |
|   EFI_STRING    StringPtrUnknown;
 | |
|   EFI_STATUS    Status;
 | |
| 
 | |
|   Status = EFI_SUCCESS;
 | |
| 
 | |
|   StringPtrUnknown = HiiGetString (mDpHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL);
 | |
|   StringPtr = HiiGetString (mDpHiiHandle, STRING_TOKEN (STR_DP_SECTION_RAWTRACE), NULL);
 | |
|   ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_SECTION_HEADER), mDpHiiHandle,
 | |
|               (StringPtr == NULL) ? StringPtrUnknown : StringPtr);
 | |
|   FreePool (StringPtr);
 | |
|   FreePool (StringPtrUnknown);
 | |
| 
 | |
|   if (mShowId) {
 | |
|     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_RAW_HEADR2), mDpHiiHandle);
 | |
|     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_RAW_DASHES2), mDpHiiHandle);
 | |
|   } else {
 | |
|     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_RAW_HEADR), mDpHiiHandle);
 | |
|     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_RAW_DASHES), mDpHiiHandle);
 | |
|   }
 | |
| 
 | |
|   LogEntryKey = 0;
 | |
|   Count = 0;
 | |
|   Index = 0;
 | |
|   while ( WITHIN_LIMIT(Count, Limit) &&
 | |
|           ((LogEntryKey = GetPerformanceMeasurementRecord (
 | |
|                           LogEntryKey,
 | |
|                           &Measurement.Handle,
 | |
|                           &Measurement.Token,
 | |
|                           &Measurement.Module,
 | |
|                           &Measurement.StartTimeStamp,
 | |
|                           &Measurement.EndTimeStamp,
 | |
|                           &Measurement.Identifier)) != 0)
 | |
|         )
 | |
|   {
 | |
|     ++Index;    // Count every record.  First record is 1.
 | |
|     ElapsedTime = 0;
 | |
|     if (Measurement.EndTimeStamp != 0) {
 | |
|       Duration = GetDuration (&Measurement);
 | |
|       ElapsedTime = DurationInMicroSeconds ( Duration );
 | |
|     }
 | |
|     if ((ElapsedTime < mInterestThreshold)                 ||
 | |
|         ((ExcludeFlag) && (GetCumulativeItem(&Measurement) >= 0))
 | |
|         ) { // Ignore "uninteresting" or Excluded records
 | |
|       continue;
 | |
|     }
 | |
|     ++Count;    // Count the number of records printed
 | |
| 
 | |
|     if (mShowId) {
 | |
|       ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_RAW_VARS2), mDpHiiHandle,
 | |
|         Index,      // 1 based, Which measurement record is being printed
 | |
|         Measurement.Handle,
 | |
|         Measurement.StartTimeStamp,
 | |
|         Measurement.EndTimeStamp,
 | |
|         Measurement.Token,
 | |
|         Measurement.Module,
 | |
|         Measurement.Identifier
 | |
|       );
 | |
|     } else {
 | |
|       ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_RAW_VARS), mDpHiiHandle,
 | |
|         Index,      // 1 based, Which measurement record is being printed
 | |
|         Measurement.Handle,
 | |
|         Measurement.StartTimeStamp,
 | |
|         Measurement.EndTimeStamp,
 | |
|         Measurement.Token,
 | |
|         Measurement.Module
 | |
|       );
 | |
|     }
 | |
|     if (ShellGetExecutionBreakFlag ()) {
 | |
|       Status = EFI_ABORTED;
 | |
|       break;
 | |
|     }
 | |
|   }
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Gather and print Major Phase metrics.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| ProcessPhases(
 | |
|   VOID
 | |
|   )
 | |
| {
 | |
|   MEASUREMENT_RECORD        Measurement;
 | |
|   UINT64                    BdsTimeoutValue;
 | |
|   UINT64                    SecTime;
 | |
|   UINT64                    PeiTime;
 | |
|   UINT64                    DxeTime;
 | |
|   UINT64                    BdsTime;
 | |
|   UINT64                    ElapsedTime;
 | |
|   UINT64                    Duration;
 | |
|   UINT64                    Total;
 | |
|   EFI_STRING                StringPtr;
 | |
|   UINTN                     LogEntryKey;
 | |
|   EFI_STRING                StringPtrUnknown;
 | |
| 
 | |
|   BdsTimeoutValue = 0;
 | |
|   SecTime         = 0;
 | |
|   PeiTime         = 0;
 | |
|   DxeTime         = 0;
 | |
|   BdsTime         = 0;
 | |
|   //
 | |
|   // Get Execution Phase Statistics
 | |
|   //
 | |
|   StringPtrUnknown = HiiGetString (mDpHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL);
 | |
|   StringPtr = HiiGetString (mDpHiiHandle, STRING_TOKEN (STR_DP_SECTION_PHASES), NULL);
 | |
|   ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_SECTION_HEADER), mDpHiiHandle,
 | |
|               (StringPtr == NULL) ? StringPtrUnknown : StringPtr);
 | |
|   FreePool (StringPtr);
 | |
|   FreePool (StringPtrUnknown);
 | |
| 
 | |
|   LogEntryKey = 0;
 | |
|   while ((LogEntryKey = GetPerformanceMeasurementRecord (
 | |
|                           LogEntryKey,
 | |
|                           &Measurement.Handle,
 | |
|                           &Measurement.Token,
 | |
|                           &Measurement.Module,
 | |
|                           &Measurement.StartTimeStamp,
 | |
|                           &Measurement.EndTimeStamp,
 | |
|                           &Measurement.Identifier)) != 0)
 | |
|   {
 | |
|     if (Measurement.EndTimeStamp == 0) { // Skip "incomplete" records
 | |
|       continue;
 | |
|     }
 | |
|     Duration = GetDuration (&Measurement);
 | |
|     if (   Measurement.Handle != NULL
 | |
|         && (AsciiStrCmp (Measurement.Token, ALit_BdsTO) == 0)
 | |
|        )
 | |
|     {
 | |
|       BdsTimeoutValue = Duration;
 | |
|     } else if (AsciiStrCmp (Measurement.Token, ALit_SEC) == 0) {
 | |
|       SecTime     = Duration;
 | |
|     } else if (AsciiStrCmp (Measurement.Token, ALit_PEI) == 0) {
 | |
|       PeiTime     = Duration;
 | |
|     } else if (AsciiStrCmp (Measurement.Token, ALit_DXE) == 0) {
 | |
|       DxeTime      = Duration;
 | |
|     } else if (AsciiStrCmp (Measurement.Token, ALit_BDS) == 0) {
 | |
|       BdsTime      = Duration;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   Total = 0;
 | |
| 
 | |
|   // print SEC phase duration time
 | |
|   //
 | |
|   if (SecTime > 0) {
 | |
|     ElapsedTime = DurationInMicroSeconds ( SecTime );     // Calculate elapsed time in microseconds
 | |
|     Total += DivU64x32 (ElapsedTime, 1000);   // Accumulate time in milliseconds
 | |
|     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_SEC_PHASE), mDpHiiHandle, ElapsedTime);
 | |
|   }
 | |
| 
 | |
|   // print PEI phase duration time
 | |
|   //
 | |
|   if (PeiTime > 0) {
 | |
|     ElapsedTime = DivU64x32 (PeiTime, 1000000);
 | |
|     Total += ElapsedTime;
 | |
|     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_PHASE_DURATION), mDpHiiHandle, ALit_PEI, ElapsedTime);
 | |
|   }
 | |
| 
 | |
|   // print DXE phase duration time
 | |
|   //
 | |
|   if (DxeTime > 0) {
 | |
|     ElapsedTime = DivU64x32 (DxeTime, 1000000);
 | |
|     Total += ElapsedTime;
 | |
|     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_PHASE_DURATION), mDpHiiHandle, ALit_DXE, ElapsedTime);
 | |
|   }
 | |
| 
 | |
|   // print BDS phase duration time
 | |
|   //
 | |
|   if (BdsTime > 0) {
 | |
|     ElapsedTime = DivU64x32 (BdsTime, 1000000);
 | |
|     Total += ElapsedTime;
 | |
|     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_PHASE_DURATION), mDpHiiHandle, ALit_BDS, ElapsedTime);
 | |
|   }
 | |
| 
 | |
|   if (BdsTimeoutValue > 0) {
 | |
|     ElapsedTime = DivU64x32 (BdsTimeoutValue, 1000000);
 | |
|     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_PHASE_BDSTO), mDpHiiHandle, ALit_BdsTO, ElapsedTime);
 | |
|   }
 | |
| 
 | |
|   ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_TOTAL_DURATION), mDpHiiHandle, Total);
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Gather and print Handle data.
 | |
| 
 | |
|   @param[in]    ExcludeFlag   TRUE to exclude individual Cumulative items from display.
 | |
| 
 | |
|   @retval EFI_SUCCESS             The operation was successful.
 | |
|   @retval EFI_ABORTED             The user aborts the operation.
 | |
|   @return Others                  from a call to gBS->LocateHandleBuffer().
 | |
| **/
 | |
| EFI_STATUS
 | |
| ProcessHandles(
 | |
|   IN BOOLEAN      ExcludeFlag
 | |
|   )
 | |
| {
 | |
|   MEASUREMENT_RECORD        Measurement;
 | |
|   UINT64                    ElapsedTime;
 | |
|   UINT64                    Duration;
 | |
|   EFI_HANDLE                *HandleBuffer;
 | |
|   EFI_STRING                StringPtr;
 | |
|   UINTN                     Index;
 | |
|   UINTN                     LogEntryKey;
 | |
|   UINTN                     Count;
 | |
|   UINTN                     HandleCount;
 | |
|   EFI_STATUS                Status;
 | |
|   EFI_STRING                StringPtrUnknown;
 | |
| 
 | |
|   StringPtrUnknown = HiiGetString (mDpHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL);
 | |
|   StringPtr = HiiGetString (mDpHiiHandle, STRING_TOKEN (STR_DP_SECTION_DRIVERS), NULL);
 | |
|   ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_SECTION_HEADER), mDpHiiHandle,
 | |
|               (StringPtr == NULL) ? StringPtrUnknown : StringPtr);
 | |
|   FreePool (StringPtr);
 | |
|   FreePool (StringPtrUnknown);
 | |
| 
 | |
|   Status = gBS->LocateHandleBuffer (AllHandles, NULL, NULL, &HandleCount, &HandleBuffer);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_HANDLES_ERROR), mDpHiiHandle, Status);
 | |
|   }
 | |
|   else {
 | |
| #if DP_DEBUG == 2
 | |
|     Print (L"There are %,d Handles defined.\n", (Size / sizeof(HandleBuffer[0])));
 | |
| #endif
 | |
| 
 | |
|     if (mShowId) {
 | |
|       ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_HANDLE_SECTION2), mDpHiiHandle);
 | |
|     } else {
 | |
|       ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_HANDLE_SECTION), mDpHiiHandle);
 | |
|     }
 | |
|     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_DASHES), mDpHiiHandle);
 | |
| 
 | |
|     LogEntryKey = 0;
 | |
|     Count   = 0;
 | |
|     while ((LogEntryKey = GetPerformanceMeasurementRecord (
 | |
|                             LogEntryKey,
 | |
|                             &Measurement.Handle,
 | |
|                             &Measurement.Token,
 | |
|                             &Measurement.Module,
 | |
|                             &Measurement.StartTimeStamp,
 | |
|                             &Measurement.EndTimeStamp,
 | |
|                             &Measurement.Identifier)) != 0)
 | |
|     {
 | |
|       Count++;
 | |
|       Duration = GetDuration (&Measurement);
 | |
|       ElapsedTime = DurationInMicroSeconds ( Duration );
 | |
|       if ((ElapsedTime < mInterestThreshold)                 ||
 | |
|           (Measurement.EndTimeStamp == 0)                    ||
 | |
|           (!IsCorePerf (&Measurement))                       ||
 | |
|           ((ExcludeFlag) && (GetCumulativeItem(&Measurement) >= 0))
 | |
|          ) { // Ignore "uninteresting" or excluded records
 | |
|         continue;
 | |
|       }
 | |
|       mGaugeString[0] = 0;    // Empty driver name by default
 | |
|       AsciiStrToUnicodeStrS (Measurement.Token, mUnicodeToken, ARRAY_SIZE (mUnicodeToken));
 | |
|       // See if the Handle is in the HandleBuffer
 | |
|       for (Index = 0; Index < HandleCount; Index++) {
 | |
|         if (Measurement.Handle == HandleBuffer[Index]) {
 | |
|           DpGetNameFromHandle (HandleBuffer[Index]); // Name is put into mGaugeString
 | |
|           break;
 | |
|         }
 | |
|       }
 | |
|       // Ensure that the argument strings are not too long.
 | |
|       mGaugeString[DP_GAUGE_STRING_LENGTH] = 0;
 | |
|       mUnicodeToken[11] = 0;
 | |
|       if (mGaugeString[0] != 0) {
 | |
|         // Display the record if it has a valid handle.
 | |
|         if (mShowId) {
 | |
|           ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_HANDLE_VARS2), mDpHiiHandle,
 | |
|             Count,      // 1 based, Which measurement record is being printed
 | |
|             Index + 1,  // 1 based, Which handle is being printed
 | |
|             mGaugeString,
 | |
|             mUnicodeToken,
 | |
|             ElapsedTime,
 | |
|             Measurement.Identifier
 | |
|           );
 | |
|         } else {
 | |
|           ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_HANDLE_VARS), mDpHiiHandle,
 | |
|             Count,      // 1 based, Which measurement record is being printed
 | |
|             Index + 1,  // 1 based, Which handle is being printed
 | |
|             mGaugeString,
 | |
|             mUnicodeToken,
 | |
|             ElapsedTime
 | |
|           );
 | |
|         }
 | |
|       }
 | |
|       if (ShellGetExecutionBreakFlag ()) {
 | |
|         Status = EFI_ABORTED;
 | |
|         break;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
|   if (HandleBuffer != NULL) {
 | |
|     FreePool (HandleBuffer);
 | |
|   }
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Gather and print PEIM data.
 | |
| 
 | |
|   Only prints complete PEIM records
 | |
| 
 | |
|   @retval EFI_SUCCESS           The operation was successful.
 | |
|   @retval EFI_ABORTED           The user aborts the operation.
 | |
| **/
 | |
| EFI_STATUS
 | |
| ProcessPeims(
 | |
|   VOID
 | |
| )
 | |
| {
 | |
|   MEASUREMENT_RECORD        Measurement;
 | |
|   UINT64                    Duration;
 | |
|   UINT64                    ElapsedTime;
 | |
|   EFI_STRING                StringPtr;
 | |
|   UINTN                     LogEntryKey;
 | |
|   UINTN                     TIndex;
 | |
|   EFI_STRING                StringPtrUnknown;
 | |
|   EFI_STATUS                Status;
 | |
| 
 | |
|   Status = EFI_SUCCESS;
 | |
| 
 | |
|   StringPtrUnknown = HiiGetString (mDpHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL);
 | |
|   StringPtr = HiiGetString (mDpHiiHandle, STRING_TOKEN (STR_DP_SECTION_PEIMS), NULL);
 | |
|   ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_SECTION_HEADER), mDpHiiHandle,
 | |
|               (StringPtr == NULL) ? StringPtrUnknown : StringPtr);
 | |
|   FreePool (StringPtr);
 | |
|   FreePool (StringPtrUnknown);
 | |
| 
 | |
|   if (mShowId) {
 | |
|     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_PEIM_SECTION2), mDpHiiHandle);
 | |
|   } else {
 | |
|     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_PEIM_SECTION), mDpHiiHandle);
 | |
|   }
 | |
|   ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_DASHES), mDpHiiHandle);
 | |
|   TIndex  = 0;
 | |
|   LogEntryKey = 0;
 | |
|   while ((LogEntryKey = GetPerformanceMeasurementRecord (
 | |
|                           LogEntryKey,
 | |
|                           &Measurement.Handle,
 | |
|                           &Measurement.Token,
 | |
|                           &Measurement.Module,
 | |
|                           &Measurement.StartTimeStamp,
 | |
|                           &Measurement.EndTimeStamp,
 | |
|                           &Measurement.Identifier)) != 0)
 | |
|   {
 | |
|     TIndex++;
 | |
|     if ((Measurement.EndTimeStamp == 0) ||
 | |
|         (AsciiStrCmp (Measurement.Token, ALit_PEIM) != 0)
 | |
|        ) {
 | |
|       continue;
 | |
|     }
 | |
| 
 | |
|     Duration = GetDuration (&Measurement);
 | |
|     ElapsedTime = DurationInMicroSeconds ( Duration );  // Calculate elapsed time in microseconds
 | |
|     if (ElapsedTime >= mInterestThreshold) {
 | |
|       // PEIM FILE Handle is the start address of its FFS file that contains its file guid.
 | |
|       if (mShowId) {
 | |
|         ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_PEIM_VARS2), mDpHiiHandle,
 | |
|               TIndex,   // 1 based, Which measurement record is being printed
 | |
|               Measurement.Handle,  // file guid
 | |
|               ElapsedTime,
 | |
|               Measurement.Identifier
 | |
|         );
 | |
|       } else {
 | |
|         ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_PEIM_VARS), mDpHiiHandle,
 | |
|               TIndex,   // 1 based, Which measurement record is being printed
 | |
|               Measurement.Handle,  // file guid
 | |
|               ElapsedTime
 | |
|         );
 | |
|       }
 | |
|     }
 | |
|     if (ShellGetExecutionBreakFlag ()) {
 | |
|       Status = EFI_ABORTED;
 | |
|       break;
 | |
|     }
 | |
|   }
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Gather and print global data.
 | |
| 
 | |
|   Strips out incomplete or "Execution Phase" records
 | |
|   Only prints records where Handle is NULL
 | |
|   Increment TIndex for every record, even skipped ones, so that we have an
 | |
|   indication of every measurement record taken.
 | |
| 
 | |
|   @retval EFI_SUCCESS           The operation was successful.
 | |
|   @retval EFI_ABORTED           The user aborts the operation.
 | |
| **/
 | |
| EFI_STATUS
 | |
| ProcessGlobal(
 | |
|   VOID
 | |
| )
 | |
| {
 | |
|   MEASUREMENT_RECORD        Measurement;
 | |
|   UINT64                    Duration;
 | |
|   UINT64                    ElapsedTime;
 | |
|   EFI_STRING                StringPtr;
 | |
|   UINTN                     LogEntryKey;
 | |
|   UINTN                     Index;        // Index, or number, of the measurement record being processed
 | |
|   EFI_STRING                StringPtrUnknown;
 | |
|   EFI_STATUS                Status;
 | |
| 
 | |
|   Status = EFI_SUCCESS;
 | |
| 
 | |
|   StringPtrUnknown = HiiGetString (mDpHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL);
 | |
|   StringPtr = HiiGetString (mDpHiiHandle, STRING_TOKEN (STR_DP_SECTION_GENERAL), NULL);
 | |
|   ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_SECTION_HEADER), mDpHiiHandle,
 | |
|               (StringPtr == NULL) ? StringPtrUnknown: StringPtr);
 | |
|   FreePool (StringPtr);
 | |
|   FreePool (StringPtrUnknown);
 | |
| 
 | |
|   if (mShowId) {
 | |
|     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_GLOBAL_SECTION2), mDpHiiHandle);
 | |
|   } else {
 | |
|     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_GLOBAL_SECTION), mDpHiiHandle);
 | |
|   }
 | |
|   ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_DASHES), mDpHiiHandle);
 | |
| 
 | |
|   Index = 1;
 | |
|   LogEntryKey = 0;
 | |
| 
 | |
|   while ((LogEntryKey = GetPerformanceMeasurementRecord (
 | |
|                           LogEntryKey,
 | |
|                           &Measurement.Handle,
 | |
|                           &Measurement.Token,
 | |
|                           &Measurement.Module,
 | |
|                           &Measurement.StartTimeStamp,
 | |
|                           &Measurement.EndTimeStamp,
 | |
|                           &Measurement.Identifier)) != 0)
 | |
|   {
 | |
|     AsciiStrToUnicodeStrS (Measurement.Module, mGaugeString, ARRAY_SIZE (mGaugeString));
 | |
|     AsciiStrToUnicodeStrS (Measurement.Token, mUnicodeToken, ARRAY_SIZE (mUnicodeToken));
 | |
|     mGaugeString[25] = 0;
 | |
|     mUnicodeToken[31] = 0;
 | |
|     if ( ! ( IsPhase( &Measurement)  ||
 | |
|         IsCorePerf (&Measurement)      ||
 | |
|         (Measurement.EndTimeStamp == 0)
 | |
|         ))
 | |
|     {
 | |
|       Duration = GetDuration (&Measurement);
 | |
|       ElapsedTime = DurationInMicroSeconds ( Duration );
 | |
|       if (ElapsedTime >= mInterestThreshold) {
 | |
|         if (mShowId) {
 | |
|           ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_GLOBAL_VARS2), mDpHiiHandle,
 | |
|             Index,
 | |
|             mGaugeString,
 | |
|             mUnicodeToken,
 | |
|             ElapsedTime,
 | |
|             Measurement.Identifier
 | |
|             );
 | |
|         } else {
 | |
|            ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_GLOBAL_VARS), mDpHiiHandle,
 | |
|             Index,
 | |
|             mGaugeString,
 | |
|             mUnicodeToken,
 | |
|             ElapsedTime
 | |
|             );
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|     if (ShellGetExecutionBreakFlag ()) {
 | |
|       Status = EFI_ABORTED;
 | |
|       break;
 | |
|     }
 | |
|     Index++;
 | |
|   }
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Gather and print cumulative data.
 | |
| 
 | |
|   Traverse the measurement records and:<BR>
 | |
|   For each record with a Token listed in the CumData array:<BR>
 | |
|      - Update the instance count and the total, minimum, and maximum durations.
 | |
|   Finally, print the gathered cumulative statistics.
 | |
| 
 | |
|   @param[in]    CustomCumulativeData  A pointer to the cumtom cumulative data.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| ProcessCumulative(
 | |
|   IN PERF_CUM_DATA                  *CustomCumulativeData OPTIONAL
 | |
|   )
 | |
| {
 | |
|   UINT64                    AvgDur;         // the computed average duration
 | |
|   UINT64                    Dur;
 | |
|   UINT64                    MinDur;
 | |
|   UINT64                    MaxDur;
 | |
|   EFI_STRING                StringPtr;
 | |
|   UINTN                     TIndex;
 | |
|   EFI_STRING                StringPtrUnknown;
 | |
| 
 | |
|   StringPtrUnknown = HiiGetString (mDpHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL);
 | |
|   StringPtr = HiiGetString (mDpHiiHandle, STRING_TOKEN (STR_DP_SECTION_CUMULATIVE), NULL);
 | |
|   ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_SECTION_HEADER), mDpHiiHandle,
 | |
|               (StringPtr == NULL) ? StringPtrUnknown: StringPtr);
 | |
|   FreePool (StringPtr);
 | |
|   FreePool (StringPtrUnknown);
 | |
| 
 | |
|   ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_CUMULATIVE_SECT_1), mDpHiiHandle);
 | |
|   ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_CUMULATIVE_SECT_2), mDpHiiHandle);
 | |
|   ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_DASHES), mDpHiiHandle);
 | |
| 
 | |
|   for ( TIndex = 0; TIndex < NumCum; ++TIndex) {
 | |
|     if (CumData[TIndex].Count != 0) {
 | |
|       AvgDur = DivU64x32 (CumData[TIndex].Duration, CumData[TIndex].Count);
 | |
|       AvgDur = DurationInMicroSeconds(AvgDur);
 | |
|       Dur    = DurationInMicroSeconds(CumData[TIndex].Duration);
 | |
|       MaxDur = DurationInMicroSeconds(CumData[TIndex].MaxDur);
 | |
|       MinDur = DurationInMicroSeconds(CumData[TIndex].MinDur);
 | |
| 
 | |
|       ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_CUMULATIVE_STATS), mDpHiiHandle,
 | |
|                   CumData[TIndex].Name,
 | |
|                   CumData[TIndex].Count,
 | |
|                   Dur,
 | |
|                   AvgDur,
 | |
|                   MinDur,
 | |
|                   MaxDur
 | |
|                  );
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Print the custom cumulative data.
 | |
|   //
 | |
|   if (CustomCumulativeData != NULL) {
 | |
|     if (CustomCumulativeData->Count != 0) {
 | |
|       AvgDur = DivU64x32 (CustomCumulativeData->Duration, CustomCumulativeData->Count);
 | |
|       AvgDur = DurationInMicroSeconds (AvgDur);
 | |
|       Dur    = DurationInMicroSeconds (CustomCumulativeData->Duration);
 | |
|       MaxDur = DurationInMicroSeconds (CustomCumulativeData->MaxDur);
 | |
|       MinDur = DurationInMicroSeconds (CustomCumulativeData->MinDur);
 | |
|     } else {
 | |
|       AvgDur = 0;
 | |
|       Dur    = 0;
 | |
|       MaxDur = 0;
 | |
|       MinDur = 0;
 | |
|     }
 | |
|     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_CUMULATIVE_STATS), mDpHiiHandle,
 | |
|                 CustomCumulativeData->Name,
 | |
|                 CustomCumulativeData->Count,
 | |
|                 Dur,
 | |
|                 AvgDur,
 | |
|                 MinDur,
 | |
|                 MaxDur
 | |
|                 );
 | |
|   }
 | |
| }
 |