• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /** @file
2   Shell command for Displaying Performance Metrics.
3 
4   The Dp command reads performance data and presents it in several
5   different formats depending upon the needs of the user.  Both
6   Trace and Measured Profiling information is processed and presented.
7 
8   Dp uses the "PerformanceLib" to read the measurement records.
9   The "TimerLib" provides information about the timer, such as frequency,
10   beginning, and ending counter values.
11   Measurement records contain identifying information (Handle, Token, Module)
12   and start and end time values.
13   Dp uses this information to group records in different ways.  It also uses
14   timer information to calculate elapsed time for each measurement.
15 
16   Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.
17   (C) Copyright 2015-2016 Hewlett Packard Enterprise Development LP<BR>
18   This program and the accompanying materials
19   are licensed and made available under the terms and conditions of the BSD License
20   which accompanies this distribution.  The full text of the license may be found at
21   http://opensource.org/licenses/bsd-license.php
22 
23   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
24   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
25 **/
26 
27 #include "UefiDpLib.h"
28 #include <Guid/GlobalVariable.h>
29 #include <Library/PrintLib.h>
30 #include <Library/HandleParsingLib.h>
31 #include <Library/DevicePathLib.h>
32 
33 #include <Library/ShellLib.h>
34 #include <Library/BaseLib.h>
35 #include <Library/MemoryAllocationLib.h>
36 #include <Library/DebugLib.h>
37 #include <Library/TimerLib.h>
38 #include <Library/UefiLib.h>
39 
40 #include <Guid/Performance.h>
41 
42 #include "PerformanceTokens.h"
43 #include "Dp.h"
44 #include "Literals.h"
45 #include "DpInternal.h"
46 
47 //
48 /// Module-Global Variables
49 ///@{
50 CHAR16           mGaugeString[DP_GAUGE_STRING_LENGTH + 1];
51 CHAR16           mUnicodeToken[DXE_PERFORMANCE_STRING_SIZE];
52 UINT64           mInterestThreshold;
53 BOOLEAN          mShowId = FALSE;
54 
55 PERF_SUMMARY_DATA SummaryData = { 0 };    ///< Create the SummaryData structure and init. to ZERO.
56 
57 /// Timer Specific Information.
58 TIMER_INFO TimerInfo;
59 
60 /// Items for which to gather cumulative statistics.
61 PERF_CUM_DATA CumData[] = {
62   PERF_INIT_CUM_DATA (LOAD_IMAGE_TOK),
63   PERF_INIT_CUM_DATA (START_IMAGE_TOK),
64   PERF_INIT_CUM_DATA (DRIVERBINDING_START_TOK),
65   PERF_INIT_CUM_DATA (DRIVERBINDING_SUPPORT_TOK)
66 };
67 
68 /// Number of items for which we are gathering cumulative statistics.
69 UINT32 const      NumCum = sizeof(CumData) / sizeof(PERF_CUM_DATA);
70 
71 STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
72   {L"-v", TypeFlag},   // -v   Verbose Mode
73   {L"-A", TypeFlag},   // -A   All, Cooked
74   {L"-R", TypeFlag},   // -R   RAW All
75   {L"-s", TypeFlag},   // -s   Summary
76 #if PROFILING_IMPLEMENTED
77   {L"-P", TypeFlag},   // -P   Dump Profile Data
78   {L"-T", TypeFlag},   // -T   Dump Trace Data
79 #endif // PROFILING_IMPLEMENTED
80   {L"-x", TypeFlag},   // -x   eXclude Cumulative Items
81   {L"-i", TypeFlag},   // -i   Display Identifier
82   {L"-c", TypeValue},  // -c   Display cumulative data.
83   {L"-n", TypeValue},  // -n # Number of records to display for A and R
84   {L"-t", TypeValue},  // -t # Threshold of interest
85   {NULL, TypeMax}
86   };
87 
88 ///@}
89 
90 /**
91    Display the trailing Verbose information.
92 **/
93 VOID
DumpStatistics(void)94 DumpStatistics( void )
95 {
96   EFI_STRING                StringPtr;
97   EFI_STRING                StringPtrUnknown;
98   StringPtr        = HiiGetString (gDpHiiHandle, STRING_TOKEN (STR_DP_SECTION_STATISTICS), NULL);
99   StringPtrUnknown = HiiGetString (gDpHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL);
100   ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_SECTION_HEADER), gDpHiiHandle,
101               (StringPtr == NULL) ? StringPtrUnknown : StringPtr);
102   ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_STATS_NUMTRACE), gDpHiiHandle,      SummaryData.NumTrace);
103   ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_STATS_NUMINCOMPLETE), gDpHiiHandle, SummaryData.NumIncomplete);
104   ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_STATS_NUMPHASES), gDpHiiHandle,     SummaryData.NumSummary);
105   ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_STATS_NUMHANDLES), gDpHiiHandle,    SummaryData.NumHandles, SummaryData.NumTrace - SummaryData.NumHandles);
106   ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_STATS_NUMPEIMS), gDpHiiHandle,      SummaryData.NumPEIMs);
107   ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_STATS_NUMGLOBALS), gDpHiiHandle,    SummaryData.NumGlobal);
108 #if PROFILING_IMPLEMENTED
109   ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_STATS_NUMPROFILE), gDpHiiHandle,    SummaryData.NumProfile);
110 #endif // PROFILING_IMPLEMENTED
111   SHELL_FREE_NON_NULL (StringPtr);
112   SHELL_FREE_NON_NULL (StringPtrUnknown);
113 }
114 
115 /**
116   Initialize the cumulative data.
117 
118 **/
119 VOID
InitCumulativeData(VOID)120 InitCumulativeData (
121   VOID
122   )
123 {
124   UINTN                             Index;
125 
126   for (Index = 0; Index < NumCum; ++Index) {
127     CumData[Index].Count = 0;
128     CumData[Index].MinDur = PERF_MAXDUR;
129     CumData[Index].MaxDur = 0;
130     CumData[Index].Duration = 0;
131   }
132 }
133 
134 /**
135   Dump performance data.
136 
137   @param[in]  ImageHandle     The image handle.
138   @param[in]  SystemTable     The system table.
139 
140   @retval SHELL_SUCCESS            Command completed successfully.
141   @retval SHELL_INVALID_PARAMETER  Command usage error.
142   @retval SHELL_ABORTED            The user aborts the operation.
143   @retval value                    Unknown error.
144 **/
145 SHELL_STATUS
146 EFIAPI
ShellCommandRunDp(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)147 ShellCommandRunDp (
148   IN EFI_HANDLE               ImageHandle,
149   IN EFI_SYSTEM_TABLE         *SystemTable
150   )
151 {
152   LIST_ENTRY                *ParamPackage;
153   CONST CHAR16              *CmdLineArg;
154   EFI_STATUS                Status;
155 
156   UINT64                    Freq;
157   UINT64                    Ticker;
158   UINTN                     Number2Display;
159 
160   EFI_STRING                StringPtr;
161   BOOLEAN                   SummaryMode;
162   BOOLEAN                   VerboseMode;
163   BOOLEAN                   AllMode;
164   BOOLEAN                   RawMode;
165   BOOLEAN                   TraceMode;
166   BOOLEAN                   ProfileMode;
167   BOOLEAN                   ExcludeMode;
168   BOOLEAN                   CumulativeMode;
169   CONST CHAR16              *CustomCumulativeToken;
170   PERF_CUM_DATA             *CustomCumulativeData;
171   UINTN                     NameSize;
172   SHELL_STATUS              ShellStatus;
173 
174   StringPtr   = NULL;
175   SummaryMode = FALSE;
176   VerboseMode = FALSE;
177   AllMode     = FALSE;
178   RawMode     = FALSE;
179   TraceMode   = FALSE;
180   ProfileMode = FALSE;
181   ExcludeMode = FALSE;
182   CumulativeMode = FALSE;
183   CustomCumulativeData = NULL;
184   ShellStatus = SHELL_SUCCESS;
185 
186   // Get DP's entry time as soon as possible.
187   // This is used as the Shell-Phase end time.
188   //
189   Ticker  = GetPerformanceCounter ();
190 
191   //
192   // initialize the shell lib (we must be in non-auto-init...)
193   //
194   Status = ShellInitialize();
195   ASSERT_EFI_ERROR(Status);
196 
197   Status = CommandInit();
198   ASSERT_EFI_ERROR(Status);
199 
200   //
201   // Process Command Line arguments
202   //
203   Status = ShellCommandLineParse (ParamList, &ParamPackage, NULL, TRUE);
204   if (EFI_ERROR(Status)) {
205     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_INVALID_ARG), gDpHiiHandle);
206     return SHELL_INVALID_PARAMETER;
207   }
208 
209   //
210   // Boolean options
211   //
212   VerboseMode = ShellCommandLineGetFlag (ParamPackage, L"-v");
213   SummaryMode = (BOOLEAN) (ShellCommandLineGetFlag (ParamPackage, L"-S") || ShellCommandLineGetFlag (ParamPackage, L"-s"));
214   AllMode     = ShellCommandLineGetFlag (ParamPackage, L"-A");
215   RawMode     = ShellCommandLineGetFlag (ParamPackage, L"-R");
216 #if PROFILING_IMPLEMENTED
217   TraceMode   = ShellCommandLineGetFlag (ParamPackage, L"-T");
218   ProfileMode = ShellCommandLineGetFlag (ParamPackage, L"-P");
219 #endif  // PROFILING_IMPLEMENTED
220   ExcludeMode = ShellCommandLineGetFlag (ParamPackage, L"-x");
221   mShowId     = ShellCommandLineGetFlag (ParamPackage, L"-i");
222   CumulativeMode = ShellCommandLineGetFlag (ParamPackage, L"-c");
223 
224   // Options with Values
225   CmdLineArg  = ShellCommandLineGetValue (ParamPackage, L"-n");
226   if (CmdLineArg == NULL) {
227     Number2Display = DEFAULT_DISPLAYCOUNT;
228   } else {
229     Number2Display = StrDecimalToUintn(CmdLineArg);
230     if (Number2Display == 0) {
231       Number2Display = MAXIMUM_DISPLAYCOUNT;
232     }
233   }
234 
235   CmdLineArg  = ShellCommandLineGetValue (ParamPackage, L"-t");
236   if (CmdLineArg == NULL) {
237     mInterestThreshold = DEFAULT_THRESHOLD;  // 1ms := 1,000 us
238   } else {
239     mInterestThreshold = StrDecimalToUint64(CmdLineArg);
240   }
241 
242   // Handle Flag combinations and default behaviors
243   // If both TraceMode and ProfileMode are FALSE, set them both to TRUE
244   if ((! TraceMode) && (! ProfileMode)) {
245     TraceMode   = TRUE;
246 #if PROFILING_IMPLEMENTED
247     ProfileMode = TRUE;
248 #endif  // PROFILING_IMPLEMENTED
249   }
250 
251   //
252   // Initialize the pre-defined cumulative data.
253   //
254   InitCumulativeData ();
255 
256   //
257   // Init the custom cumulative data.
258   //
259   CustomCumulativeToken = ShellCommandLineGetValue (ParamPackage, L"-c");
260   if (CustomCumulativeToken != NULL) {
261     CustomCumulativeData = AllocateZeroPool (sizeof (PERF_CUM_DATA));
262     if (CustomCumulativeData == NULL) {
263       return SHELL_OUT_OF_RESOURCES;
264     }
265     CustomCumulativeData->MinDur = 0;
266     CustomCumulativeData->MaxDur = 0;
267     CustomCumulativeData->Count  = 0;
268     CustomCumulativeData->Duration = 0;
269     NameSize = StrLen (CustomCumulativeToken) + 1;
270     CustomCumulativeData->Name   = AllocateZeroPool (NameSize);
271     if (CustomCumulativeData->Name == NULL) {
272       FreePool (CustomCumulativeData);
273       return SHELL_OUT_OF_RESOURCES;
274     }
275     UnicodeStrToAsciiStrS (CustomCumulativeToken, CustomCumulativeData->Name, NameSize);
276   }
277 
278   //
279   // Timer specific processing
280   //
281   // Get the Performance counter characteristics:
282   //          Freq = Frequency in Hz
283   //    StartCount = Value loaded into the counter when it starts counting
284   //      EndCount = Value counter counts to before it needs to be reset
285   //
286   Freq = GetPerformanceCounterProperties (&TimerInfo.StartCount, &TimerInfo.EndCount);
287 
288   // Convert the Frequency from Hz to KHz
289   TimerInfo.Frequency = (UINT32)DivU64x32 (Freq, 1000);
290 
291   // Determine in which direction the performance counter counts.
292   TimerInfo.CountUp = (BOOLEAN) (TimerInfo.EndCount >= TimerInfo.StartCount);
293 
294   //
295   // Print header
296   //
297   // print DP's build version
298   ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_BUILD_REVISION), gDpHiiHandle, DP_MAJOR_VERSION, DP_MINOR_VERSION);
299 
300   // print performance timer characteristics
301   ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_KHZ), gDpHiiHandle, TimerInfo.Frequency);
302 
303   if (VerboseMode && !RawMode) {
304     StringPtr = HiiGetString (gDpHiiHandle,
305                   (EFI_STRING_ID) (TimerInfo.CountUp ? STRING_TOKEN (STR_DP_UP) : STRING_TOKEN (STR_DP_DOWN)), NULL);
306     ASSERT (StringPtr != NULL);
307     // Print Timer count range and direction
308     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_TIMER_PROPERTIES), gDpHiiHandle,
309                 StringPtr,
310                 TimerInfo.StartCount,
311                 TimerInfo.EndCount
312                 );
313     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_VERBOSE_THRESHOLD), gDpHiiHandle, mInterestThreshold);
314   }
315 
316 /****************************************************************************
317 ****            Print Sections based on command line options
318 ****
319 ****  Option modes have the following priority:
320 ****    v Verbose     --  Valid in combination with any other options
321 ****    t Threshold   --  Modifies All, Raw, and Cooked output
322 ****                      Default is 0 for All and Raw mode
323 ****                      Default is DEFAULT_THRESHOLD for "Cooked" mode
324 ****    n Number2Display  Used by All and Raw mode.  Otherwise ignored.
325 ****    A All         --  R and S options are ignored
326 ****    R Raw         --  S option is ignored
327 ****    s Summary     --  Modifies "Cooked" output only
328 ****    Cooked (Default)
329 ****
330 ****  The All, Raw, and Cooked modes are modified by the Trace and Profile
331 ****  options.
332 ****    !T && !P  := (0) Default, Both are displayed
333 ****     T && !P  := (1) Only Trace records are displayed
334 ****    !T &&  P  := (2) Only Profile records are displayed
335 ****     T &&  P  := (3) Same as Default, both are displayed
336 ****************************************************************************/
337   GatherStatistics (CustomCumulativeData);
338   if (CumulativeMode) {
339     ProcessCumulative (CustomCumulativeData);
340   } else if (AllMode) {
341     if (TraceMode) {
342       Status = DumpAllTrace( Number2Display, ExcludeMode);
343       if (Status == EFI_ABORTED) {
344         ShellStatus = SHELL_ABORTED;
345         goto Done;
346       }
347     }
348     if (ProfileMode) {
349       DumpAllProfile( Number2Display, ExcludeMode);
350     }
351   } else if (RawMode) {
352     if (TraceMode) {
353       Status = DumpRawTrace( Number2Display, ExcludeMode);
354       if (Status == EFI_ABORTED) {
355         ShellStatus = SHELL_ABORTED;
356         goto Done;
357       }
358     }
359     if (ProfileMode) {
360       DumpRawProfile( Number2Display, ExcludeMode);
361     }
362   } else {
363     //------------- Begin Cooked Mode Processing
364     if (TraceMode) {
365       ProcessPhases ( Ticker );
366       if ( ! SummaryMode) {
367         Status = ProcessHandles ( ExcludeMode);
368         if (Status == EFI_ABORTED) {
369           ShellStatus = SHELL_ABORTED;
370           goto Done;
371         }
372 
373         Status = ProcessPeims ();
374         if (Status == EFI_ABORTED) {
375           ShellStatus = SHELL_ABORTED;
376           goto Done;
377         }
378 
379         Status = ProcessGlobal ();
380         if (Status == EFI_ABORTED) {
381           ShellStatus = SHELL_ABORTED;
382           goto Done;
383         }
384 
385         ProcessCumulative (NULL);
386       }
387     }
388     if (ProfileMode) {
389       DumpAllProfile( Number2Display, ExcludeMode);
390     }
391   } //------------- End of Cooked Mode Processing
392   if ( VerboseMode || SummaryMode) {
393     DumpStatistics();
394   }
395 
396 Done:
397   if (ParamPackage != NULL) {
398     ShellCommandLineFreeVarList (ParamPackage);
399   }
400   SHELL_FREE_NON_NULL (StringPtr);
401   if (CustomCumulativeData != NULL) {
402     SHELL_FREE_NON_NULL (CustomCumulativeData->Name);
403   }
404   SHELL_FREE_NON_NULL (CustomCumulativeData);
405 
406   return ShellStatus;
407 }
408