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