]> git.proxmox.com Git - mirror_edk2.git/blob - ShellPkg/Library/UefiDpLib/Dp.c
0176e31bc0d6624ad0371b3ecb01b181d69c9beb
[mirror_edk2.git] / ShellPkg / Library / UefiDpLib / Dp.c
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 - 2015, 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
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
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
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 SHELL_STATUS ShellStatus;
172
173 StringPtr = NULL;
174 SummaryMode = FALSE;
175 VerboseMode = FALSE;
176 AllMode = FALSE;
177 RawMode = FALSE;
178 TraceMode = FALSE;
179 ProfileMode = FALSE;
180 ExcludeMode = FALSE;
181 CumulativeMode = FALSE;
182 CustomCumulativeData = NULL;
183 ShellStatus = SHELL_SUCCESS;
184
185 // Get DP's entry time as soon as possible.
186 // This is used as the Shell-Phase end time.
187 //
188 Ticker = GetPerformanceCounter ();
189
190 //
191 // initialize the shell lib (we must be in non-auto-init...)
192 //
193 Status = ShellInitialize();
194 ASSERT_EFI_ERROR(Status);
195
196 Status = CommandInit();
197 ASSERT_EFI_ERROR(Status);
198
199 //
200 // Process Command Line arguments
201 //
202 Status = ShellCommandLineParse (ParamList, &ParamPackage, NULL, TRUE);
203 if (EFI_ERROR(Status)) {
204 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_INVALID_ARG), gDpHiiHandle);
205 return SHELL_INVALID_PARAMETER;
206 }
207
208 //
209 // Boolean options
210 //
211 VerboseMode = ShellCommandLineGetFlag (ParamPackage, L"-v");
212 SummaryMode = (BOOLEAN) (ShellCommandLineGetFlag (ParamPackage, L"-S") || ShellCommandLineGetFlag (ParamPackage, L"-s"));
213 AllMode = ShellCommandLineGetFlag (ParamPackage, L"-A");
214 RawMode = ShellCommandLineGetFlag (ParamPackage, L"-R");
215 #if PROFILING_IMPLEMENTED
216 TraceMode = ShellCommandLineGetFlag (ParamPackage, L"-T");
217 ProfileMode = ShellCommandLineGetFlag (ParamPackage, L"-P");
218 #endif // PROFILING_IMPLEMENTED
219 ExcludeMode = ShellCommandLineGetFlag (ParamPackage, L"-x");
220 mShowId = ShellCommandLineGetFlag (ParamPackage, L"-i");
221 CumulativeMode = ShellCommandLineGetFlag (ParamPackage, L"-c");
222
223 // Options with Values
224 CmdLineArg = ShellCommandLineGetValue (ParamPackage, L"-n");
225 if (CmdLineArg == NULL) {
226 Number2Display = DEFAULT_DISPLAYCOUNT;
227 } else {
228 Number2Display = StrDecimalToUintn(CmdLineArg);
229 if (Number2Display == 0) {
230 Number2Display = MAXIMUM_DISPLAYCOUNT;
231 }
232 }
233
234 CmdLineArg = ShellCommandLineGetValue (ParamPackage, L"-t");
235 if (CmdLineArg == NULL) {
236 mInterestThreshold = DEFAULT_THRESHOLD; // 1ms := 1,000 us
237 } else {
238 mInterestThreshold = StrDecimalToUint64(CmdLineArg);
239 }
240
241 // Handle Flag combinations and default behaviors
242 // If both TraceMode and ProfileMode are FALSE, set them both to TRUE
243 if ((! TraceMode) && (! ProfileMode)) {
244 TraceMode = TRUE;
245 #if PROFILING_IMPLEMENTED
246 ProfileMode = TRUE;
247 #endif // PROFILING_IMPLEMENTED
248 }
249
250 //
251 // Initialize the pre-defined cumulative data.
252 //
253 InitCumulativeData ();
254
255 //
256 // Init the custom cumulative data.
257 //
258 CustomCumulativeToken = ShellCommandLineGetValue (ParamPackage, L"-c");
259 if (CustomCumulativeToken != NULL) {
260 CustomCumulativeData = AllocateZeroPool (sizeof (PERF_CUM_DATA));
261 ASSERT (CustomCumulativeData != NULL);
262 CustomCumulativeData->MinDur = 0;
263 CustomCumulativeData->MaxDur = 0;
264 CustomCumulativeData->Count = 0;
265 CustomCumulativeData->Duration = 0;
266 CustomCumulativeData->Name = AllocateZeroPool (StrLen (CustomCumulativeToken) + 1);
267 UnicodeStrToAsciiStr (CustomCumulativeToken, CustomCumulativeData->Name);
268 }
269
270 //
271 // Timer specific processing
272 //
273 // Get the Performance counter characteristics:
274 // Freq = Frequency in Hz
275 // StartCount = Value loaded into the counter when it starts counting
276 // EndCount = Value counter counts to before it needs to be reset
277 //
278 Freq = GetPerformanceCounterProperties (&TimerInfo.StartCount, &TimerInfo.EndCount);
279
280 // Convert the Frequency from Hz to KHz
281 TimerInfo.Frequency = (UINT32)DivU64x32 (Freq, 1000);
282
283 // Determine in which direction the performance counter counts.
284 TimerInfo.CountUp = (BOOLEAN) (TimerInfo.EndCount >= TimerInfo.StartCount);
285
286 //
287 // Print header
288 //
289 // print DP's build version
290 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_BUILD_REVISION), gDpHiiHandle, DP_MAJOR_VERSION, DP_MINOR_VERSION);
291
292 // print performance timer characteristics
293 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_KHZ), gDpHiiHandle, TimerInfo.Frequency);
294
295 if (VerboseMode && !RawMode) {
296 StringPtr = HiiGetString (gDpHiiHandle,
297 (EFI_STRING_ID) (TimerInfo.CountUp ? STRING_TOKEN (STR_DP_UP) : STRING_TOKEN (STR_DP_DOWN)), NULL);
298 ASSERT (StringPtr != NULL);
299 // Print Timer count range and direction
300 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_TIMER_PROPERTIES), gDpHiiHandle,
301 StringPtr,
302 TimerInfo.StartCount,
303 TimerInfo.EndCount
304 );
305 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_VERBOSE_THRESHOLD), gDpHiiHandle, mInterestThreshold);
306 }
307
308 /****************************************************************************
309 **** Print Sections based on command line options
310 ****
311 **** Option modes have the following priority:
312 **** v Verbose -- Valid in combination with any other options
313 **** t Threshold -- Modifies All, Raw, and Cooked output
314 **** Default is 0 for All and Raw mode
315 **** Default is DEFAULT_THRESHOLD for "Cooked" mode
316 **** n Number2Display Used by All and Raw mode. Otherwise ignored.
317 **** A All -- R and S options are ignored
318 **** R Raw -- S option is ignored
319 **** s Summary -- Modifies "Cooked" output only
320 **** Cooked (Default)
321 ****
322 **** The All, Raw, and Cooked modes are modified by the Trace and Profile
323 **** options.
324 **** !T && !P := (0) Default, Both are displayed
325 **** T && !P := (1) Only Trace records are displayed
326 **** !T && P := (2) Only Profile records are displayed
327 **** T && P := (3) Same as Default, both are displayed
328 ****************************************************************************/
329 GatherStatistics (CustomCumulativeData);
330 if (CumulativeMode) {
331 ProcessCumulative (CustomCumulativeData);
332 } else if (AllMode) {
333 if (TraceMode) {
334 Status = DumpAllTrace( Number2Display, ExcludeMode);
335 if (Status == EFI_ABORTED) {
336 ShellStatus = SHELL_ABORTED;
337 goto Done;
338 }
339 }
340 if (ProfileMode) {
341 DumpAllProfile( Number2Display, ExcludeMode);
342 }
343 } else if (RawMode) {
344 if (TraceMode) {
345 Status = DumpRawTrace( Number2Display, ExcludeMode);
346 if (Status == EFI_ABORTED) {
347 ShellStatus = SHELL_ABORTED;
348 goto Done;
349 }
350 }
351 if (ProfileMode) {
352 DumpRawProfile( Number2Display, ExcludeMode);
353 }
354 } else {
355 //------------- Begin Cooked Mode Processing
356 if (TraceMode) {
357 ProcessPhases ( Ticker );
358 if ( ! SummaryMode) {
359 Status = ProcessHandles ( ExcludeMode);
360 if (Status == EFI_ABORTED) {
361 ShellStatus = SHELL_ABORTED;
362 goto Done;
363 }
364
365 Status = ProcessPeims ();
366 if (Status == EFI_ABORTED) {
367 ShellStatus = SHELL_ABORTED;
368 goto Done;
369 }
370
371 Status = ProcessGlobal ();
372 if (Status == EFI_ABORTED) {
373 ShellStatus = SHELL_ABORTED;
374 goto Done;
375 }
376
377 ProcessCumulative (NULL);
378 }
379 }
380 if (ProfileMode) {
381 DumpAllProfile( Number2Display, ExcludeMode);
382 }
383 } //------------- End of Cooked Mode Processing
384 if ( VerboseMode || SummaryMode) {
385 DumpStatistics();
386 }
387
388 Done:
389 SHELL_FREE_NON_NULL (StringPtr);
390 if (CustomCumulativeData != NULL) {
391 SHELL_FREE_NON_NULL (CustomCumulativeData->Name);
392 }
393 SHELL_FREE_NON_NULL (CustomCumulativeData);
394
395 return ShellStatus;
396 }