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