]> git.proxmox.com Git - mirror_edk2.git/blob - PerformancePkg/Dp_App/Dp.c
PerformancePkg\Dp_App: Add NULL check to pointer returned from 'AllocateZeroPool'.
[mirror_edk2.git] / PerformancePkg / Dp_App / Dp.c
1 /** @file
2 Shell application for Displaying Performance Metrics.
3
4 The Dp application 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.<BR>
17 (C) Copyright 2015 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 <Library/UefiApplicationEntryPoint.h>
28 #include <Library/ShellLib.h>
29 #include <Library/BaseLib.h>
30 #include <Library/MemoryAllocationLib.h>
31 #include <Library/DebugLib.h>
32 #include <Library/TimerLib.h>
33 #include <Library/UefiLib.h>
34 #include <Library/HiiLib.h>
35 #include <Library/PcdLib.h>
36
37 #include <Guid/Performance.h>
38
39 #include <PerformanceTokens.h>
40 #include "Dp.h"
41 #include "Literals.h"
42 #include "DpInternal.h"
43
44 //
45 /// Module-Global Variables
46 ///@{
47 EFI_HII_HANDLE gHiiHandle;
48 SHELL_PARAM_ITEM *DpParamList = NULL;
49 CHAR16 *mPrintTokenBuffer = NULL;
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 PARAM_ITEM_LIST ParamList[] = {
72 {STRING_TOKEN (STR_DP_OPTION_QH), TypeFlag}, // -? Help
73 {STRING_TOKEN (STR_DP_OPTION_LH), TypeFlag}, // -h Help
74 {STRING_TOKEN (STR_DP_OPTION_UH), TypeFlag}, // -H Help
75 {STRING_TOKEN (STR_DP_OPTION_LV), TypeFlag}, // -v Verbose Mode
76 {STRING_TOKEN (STR_DP_OPTION_UA), TypeFlag}, // -A All, Cooked
77 {STRING_TOKEN (STR_DP_OPTION_UR), TypeFlag}, // -R RAW All
78 {STRING_TOKEN (STR_DP_OPTION_LS), TypeFlag}, // -s Summary
79 #if PROFILING_IMPLEMENTED
80 {STRING_TOKEN (STR_DP_OPTION_UP), TypeFlag}, // -P Dump Profile Data
81 {STRING_TOKEN (STR_DP_OPTION_UT), TypeFlag}, // -T Dump Trace Data
82 #endif
83 {STRING_TOKEN (STR_DP_OPTION_LX), TypeFlag}, // -x eXclude Cumulative Items
84 {STRING_TOKEN (STR_DP_OPTION_LI), TypeFlag}, // -i Display Identifier
85 {STRING_TOKEN (STR_DP_OPTION_LC), TypeValue}, // -c Display cumulative data.
86 {STRING_TOKEN (STR_DP_OPTION_LN), TypeValue}, // -n # Number of records to display for A and R
87 {STRING_TOKEN (STR_DP_OPTION_LT), TypeValue} // -t # Threshold of interest
88 };
89
90 ///@}
91
92 /**
93 Transfer the param list value and get the command line parse.
94
95 **/
96 VOID
97 InitialShellParamList( void )
98 {
99 UINT32 ListIndex;
100 UINT32 ListLength;
101
102 //
103 // Allocate one more for the end tag.
104 //
105 ListLength = sizeof (ParamList) / sizeof (ParamList[0]) + 1;
106 DpParamList = AllocatePool (sizeof (SHELL_PARAM_ITEM) * ListLength);
107 ASSERT (DpParamList != NULL);
108
109 for (ListIndex = 0; ListIndex < ListLength - 1; ListIndex ++)
110 {
111 DpParamList[ListIndex].Name = HiiGetString (gHiiHandle, ParamList[ListIndex].Token, NULL);
112 DpParamList[ListIndex].Type = ParamList[ListIndex].Type;
113 }
114 DpParamList[ListIndex].Name = NULL;
115 DpParamList[ListIndex].Type = TypeMax;
116 }
117
118 /**
119 Display Usage and Help information.
120 **/
121 VOID
122 ShowHelp( void )
123 {
124 PrintToken (STRING_TOKEN (STR_DP_HELP_HEAD));
125 #if PROFILING_IMPLEMENTED
126 PrintToken (STRING_TOKEN (STR_DP_HELP_FLAGS));
127 #else
128 PrintToken (STRING_TOKEN (STR_DP_HELP_FLAGS_2));
129 #endif // PROFILING_IMPLEMENTED
130 PrintToken (STRING_TOKEN (STR_DP_HELP_PAGINATE));
131 PrintToken (STRING_TOKEN (STR_DP_HELP_VERBOSE));
132 PrintToken (STRING_TOKEN (STR_DP_HELP_EXCLUDE));
133 PrintToken (STRING_TOKEN (STR_DP_HELP_STAT));
134 PrintToken (STRING_TOKEN (STR_DP_HELP_ALL));
135 PrintToken (STRING_TOKEN (STR_DP_HELP_RAW));
136 #if PROFILING_IMPLEMENTED
137 PrintToken (STRING_TOKEN (STR_DP_HELP_TRACE));
138 PrintToken (STRING_TOKEN (STR_DP_HELP_PROFILE));
139 #endif // PROFILING_IMPLEMENTED
140 PrintToken (STRING_TOKEN (STR_DP_HELP_THRESHOLD));
141 PrintToken (STRING_TOKEN (STR_DP_HELP_COUNT));
142 PrintToken (STRING_TOKEN (STR_DP_HELP_ID));
143 PrintToken (STRING_TOKEN (STR_DP_HELP_CUM_DATA));
144 PrintToken (STRING_TOKEN (STR_DP_HELP_HELP));
145 Print(L"\n");
146 }
147
148 /**
149 Display the trailing Verbose information.
150 **/
151 VOID
152 DumpStatistics( void )
153 {
154 EFI_STRING StringPtr;
155 EFI_STRING StringPtrUnknown;
156 StringPtr = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_SECTION_STATISTICS), NULL);
157 StringPtrUnknown = HiiGetString (gHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL);
158 PrintToken( STRING_TOKEN (STR_DP_SECTION_HEADER),
159 (StringPtr == NULL) ? StringPtrUnknown : StringPtr);
160
161 PrintToken( STRING_TOKEN (STR_DP_STATS_NUMTRACE), SummaryData.NumTrace);
162 PrintToken( STRING_TOKEN (STR_DP_STATS_NUMINCOMPLETE), SummaryData.NumIncomplete);
163 PrintToken( STRING_TOKEN (STR_DP_STATS_NUMPHASES), SummaryData.NumSummary);
164 PrintToken( STRING_TOKEN (STR_DP_STATS_NUMHANDLES), SummaryData.NumHandles, SummaryData.NumTrace - SummaryData.NumHandles);
165 PrintToken( STRING_TOKEN (STR_DP_STATS_NUMPEIMS), SummaryData.NumPEIMs);
166 PrintToken( STRING_TOKEN (STR_DP_STATS_NUMGLOBALS), SummaryData.NumGlobal);
167 #if PROFILING_IMPLEMENTED
168 PrintToken( STRING_TOKEN (STR_DP_STATS_NUMPROFILE), SummaryData.NumProfile);
169 #endif // PROFILING_IMPLEMENTED
170 FreePool (StringPtr);
171 FreePool (StringPtrUnknown);
172 }
173
174 /**
175 Initialize the cumulative data.
176
177 **/
178 VOID
179 InitCumulativeData (
180 VOID
181 )
182 {
183 UINTN Index;
184
185 for (Index = 0; Index < NumCum; ++Index) {
186 CumData[Index].Count = 0;
187 CumData[Index].MinDur = PERF_MAXDUR;
188 CumData[Index].MaxDur = 0;
189 CumData[Index].Duration = 0;
190 }
191 }
192
193 /**
194 Dump performance data.
195
196 @param[in] ImageHandle The image handle.
197 @param[in] SystemTable The system table.
198
199 @retval EFI_SUCCESS Command completed successfully.
200 @retval EFI_INVALID_PARAMETER Command usage error.
201 @retval value Unknown error.
202
203 **/
204 EFI_STATUS
205 EFIAPI
206 InitializeDp (
207 IN EFI_HANDLE ImageHandle,
208 IN EFI_SYSTEM_TABLE *SystemTable
209 )
210 {
211 UINT64 Freq;
212 UINT64 Ticker;
213 UINT32 ListIndex;
214
215 LIST_ENTRY *ParamPackage;
216 CONST CHAR16 *CmdLineArg;
217 EFI_STRING StringPtr;
218 UINTN Number2Display;
219
220 EFI_STATUS Status;
221 BOOLEAN SummaryMode;
222 BOOLEAN VerboseMode;
223 BOOLEAN AllMode;
224 BOOLEAN RawMode;
225 BOOLEAN TraceMode;
226 BOOLEAN ProfileMode;
227 BOOLEAN ExcludeMode;
228 BOOLEAN CumulativeMode;
229 CONST CHAR16 *CustomCumulativeToken;
230 PERF_CUM_DATA *CustomCumulativeData;
231
232 EFI_STRING StringDpOptionQh;
233 EFI_STRING StringDpOptionLh;
234 EFI_STRING StringDpOptionUh;
235 EFI_STRING StringDpOptionLv;
236 EFI_STRING StringDpOptionUs;
237 EFI_STRING StringDpOptionLs;
238 EFI_STRING StringDpOptionUa;
239 EFI_STRING StringDpOptionUr;
240 EFI_STRING StringDpOptionUt;
241 EFI_STRING StringDpOptionUp;
242 EFI_STRING StringDpOptionLx;
243 EFI_STRING StringDpOptionLn;
244 EFI_STRING StringDpOptionLt;
245 EFI_STRING StringDpOptionLi;
246 EFI_STRING StringDpOptionLc;
247
248 SummaryMode = FALSE;
249 VerboseMode = FALSE;
250 AllMode = FALSE;
251 RawMode = FALSE;
252 TraceMode = FALSE;
253 ProfileMode = FALSE;
254 ExcludeMode = FALSE;
255 CumulativeMode = FALSE;
256 CustomCumulativeData = NULL;
257
258 StringDpOptionQh = NULL;
259 StringDpOptionLh = NULL;
260 StringDpOptionUh = NULL;
261 StringDpOptionLv = NULL;
262 StringDpOptionUs = NULL;
263 StringDpOptionLs = NULL;
264 StringDpOptionUa = NULL;
265 StringDpOptionUr = NULL;
266 StringDpOptionUt = NULL;
267 StringDpOptionUp = NULL;
268 StringDpOptionLx = NULL;
269 StringDpOptionLn = NULL;
270 StringDpOptionLt = NULL;
271 StringDpOptionLi = NULL;
272 StringDpOptionLc = NULL;
273 StringPtr = NULL;
274
275 // Get DP's entry time as soon as possible.
276 // This is used as the Shell-Phase end time.
277 //
278 Ticker = GetPerformanceCounter ();
279
280 // Register our string package with HII and return the handle to it.
281 //
282 gHiiHandle = HiiAddPackages (&gEfiCallerIdGuid, ImageHandle, DPStrings, NULL);
283 ASSERT (gHiiHandle != NULL);
284
285 // Initial the command list
286 //
287 InitialShellParamList ();
288
289 /****************************************************************************
290 **** Process Command Line arguments ****
291 ****************************************************************************/
292 Status = ShellCommandLineParse (DpParamList, &ParamPackage, NULL, TRUE);
293
294 if (EFI_ERROR(Status)) {
295 PrintToken (STRING_TOKEN (STR_DP_INVALID_ARG));
296 ShowHelp();
297 }
298 else {
299 StringDpOptionQh = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_OPTION_QH), NULL);
300 StringDpOptionLh = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_OPTION_LH), NULL);
301 StringDpOptionUh = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_OPTION_UH), NULL);
302
303 if (ShellCommandLineGetFlag (ParamPackage, StringDpOptionQh) ||
304 ShellCommandLineGetFlag (ParamPackage, StringDpOptionLh) ||
305 ShellCommandLineGetFlag (ParamPackage, StringDpOptionUh))
306 {
307 ShowHelp();
308 }
309 else {
310 StringDpOptionLv = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_OPTION_LV), NULL);
311 StringDpOptionUs = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_OPTION_US), NULL);
312 StringDpOptionLs = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_OPTION_LS), NULL);
313 StringDpOptionUa = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_OPTION_UA), NULL);
314 StringDpOptionUr = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_OPTION_UR), NULL);
315 StringDpOptionUt = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_OPTION_UT), NULL);
316 StringDpOptionUp = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_OPTION_UP), NULL);
317 StringDpOptionLx = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_OPTION_LX), NULL);
318 StringDpOptionLn = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_OPTION_LN), NULL);
319 StringDpOptionLt = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_OPTION_LT), NULL);
320 StringDpOptionLi = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_OPTION_LI), NULL);
321 StringDpOptionLc = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_OPTION_LC), NULL);
322
323 // Boolean Options
324 //
325 VerboseMode = ShellCommandLineGetFlag (ParamPackage, StringDpOptionLv);
326 SummaryMode = (BOOLEAN) (ShellCommandLineGetFlag (ParamPackage, StringDpOptionUs) ||
327 ShellCommandLineGetFlag (ParamPackage, StringDpOptionLs));
328 AllMode = ShellCommandLineGetFlag (ParamPackage, StringDpOptionUa);
329 RawMode = ShellCommandLineGetFlag (ParamPackage, StringDpOptionUr);
330 #if PROFILING_IMPLEMENTED
331 TraceMode = ShellCommandLineGetFlag (ParamPackage, StringDpOptionUt);
332 ProfileMode = ShellCommandLineGetFlag (ParamPackage, StringDpOptionUp);
333 #endif // PROFILING_IMPLEMENTED
334 ExcludeMode = ShellCommandLineGetFlag (ParamPackage, StringDpOptionLx);
335 mShowId = ShellCommandLineGetFlag (ParamPackage, StringDpOptionLi);
336 CumulativeMode = ShellCommandLineGetFlag (ParamPackage, StringDpOptionLc);
337
338 // Options with Values
339 CmdLineArg = ShellCommandLineGetValue (ParamPackage, StringDpOptionLn);
340 if (CmdLineArg == NULL) {
341 Number2Display = DEFAULT_DISPLAYCOUNT;
342 }
343 else {
344 Number2Display = StrDecimalToUintn(CmdLineArg);
345 if (Number2Display == 0) {
346 Number2Display = MAXIMUM_DISPLAYCOUNT;
347 }
348 }
349 CmdLineArg = ShellCommandLineGetValue (ParamPackage, StringDpOptionLt);
350 if (CmdLineArg == NULL) {
351 mInterestThreshold = DEFAULT_THRESHOLD; // 1ms := 1,000 us
352 }
353 else {
354 mInterestThreshold = StrDecimalToUint64(CmdLineArg);
355 }
356 // Handle Flag combinations and default behaviors
357 // If both TraceMode and ProfileMode are FALSE, set them both to TRUE
358 if ((! TraceMode) && (! ProfileMode)) {
359 TraceMode = TRUE;
360 #if PROFILING_IMPLEMENTED
361 ProfileMode = TRUE;
362 #endif // PROFILING_IMPLEMENTED
363 }
364
365 //
366 // Init the custom cumulative data.
367 //
368 CustomCumulativeToken = ShellCommandLineGetValue (ParamPackage, StringDpOptionLc);
369 if (CustomCumulativeToken != NULL) {
370 CustomCumulativeData = AllocateZeroPool (sizeof (PERF_CUM_DATA));
371 ASSERT (CustomCumulativeData != NULL);
372 CustomCumulativeData->MinDur = 0;
373 CustomCumulativeData->MaxDur = 0;
374 CustomCumulativeData->Count = 0;
375 CustomCumulativeData->Duration = 0;
376 CustomCumulativeData->Name = AllocateZeroPool (StrLen (CustomCumulativeToken) + 1);
377 UnicodeStrToAsciiStr (CustomCumulativeToken, CustomCumulativeData->Name);
378 }
379
380 /****************************************************************************
381 **** Timer specific processing ****
382 ****************************************************************************/
383 // Get the Performance counter characteristics:
384 // Freq = Frequency in Hz
385 // StartCount = Value loaded into the counter when it starts counting
386 // EndCount = Value counter counts to before it needs to be reset
387 //
388 Freq = GetPerformanceCounterProperties (&TimerInfo.StartCount, &TimerInfo.EndCount);
389
390 // Convert the Frequency from Hz to KHz
391 TimerInfo.Frequency = (UINT32)DivU64x32 (Freq, 1000);
392
393 // Determine in which direction the performance counter counts.
394 TimerInfo.CountUp = (BOOLEAN) (TimerInfo.EndCount >= TimerInfo.StartCount);
395
396 /****************************************************************************
397 **** Print heading ****
398 ****************************************************************************/
399 // print DP's build version
400 PrintToken (STRING_TOKEN (STR_DP_BUILD_REVISION), DP_MAJOR_VERSION, DP_MINOR_VERSION);
401
402 // print performance timer characteristics
403 PrintToken (STRING_TOKEN (STR_DP_KHZ), TimerInfo.Frequency); // Print Timer frequency in KHz
404
405 if ((VerboseMode) &&
406 (! RawMode)
407 ) {
408 StringPtr = HiiGetString (gHiiHandle,
409 (EFI_STRING_ID) (TimerInfo.CountUp ? STRING_TOKEN (STR_DP_UP) : STRING_TOKEN (STR_DP_DOWN)),
410 NULL);
411 ASSERT (StringPtr != NULL);
412 PrintToken (STRING_TOKEN (STR_DP_TIMER_PROPERTIES), // Print Timer count range and direction
413 StringPtr,
414 TimerInfo.StartCount,
415 TimerInfo.EndCount
416 );
417 PrintToken (STRING_TOKEN (STR_DP_VERBOSE_THRESHOLD), mInterestThreshold);
418 }
419
420 /* **************************************************************************
421 **** Print Sections based on command line options
422 ****
423 **** Option modes have the following priority:
424 **** v Verbose -- Valid in combination with any other options
425 **** t Threshold -- Modifies All, Raw, and Cooked output
426 **** Default is 0 for All and Raw mode
427 **** Default is DEFAULT_THRESHOLD for "Cooked" mode
428 **** n Number2Display Used by All and Raw mode. Otherwise ignored.
429 **** A All -- R and S options are ignored
430 **** R Raw -- S option is ignored
431 **** s Summary -- Modifies "Cooked" output only
432 **** Cooked (Default)
433 ****
434 **** The All, Raw, and Cooked modes are modified by the Trace and Profile
435 **** options.
436 **** !T && !P := (0) Default, Both are displayed
437 **** T && !P := (1) Only Trace records are displayed
438 **** !T && P := (2) Only Profile records are displayed
439 **** T && P := (3) Same as Default, both are displayed
440 ****************************************************************************/
441 GatherStatistics (CustomCumulativeData);
442 if (CumulativeMode) {
443 ProcessCumulative (CustomCumulativeData);
444 } else if (AllMode) {
445 if (TraceMode) {
446 DumpAllTrace( Number2Display, ExcludeMode);
447 }
448 if (ProfileMode) {
449 DumpAllProfile( Number2Display, ExcludeMode);
450 }
451 }
452 else if (RawMode) {
453 if (TraceMode) {
454 DumpRawTrace( Number2Display, ExcludeMode);
455 }
456 if (ProfileMode) {
457 DumpRawProfile( Number2Display, ExcludeMode);
458 }
459 }
460 else {
461 //------------- Begin Cooked Mode Processing
462 if (TraceMode) {
463 ProcessPhases ( Ticker );
464 if ( ! SummaryMode) {
465 Status = ProcessHandles ( ExcludeMode);
466 if ( ! EFI_ERROR( Status)) {
467 ProcessPeims ( );
468 ProcessGlobal ( );
469 ProcessCumulative (NULL);
470 }
471 }
472 }
473 if (ProfileMode) {
474 DumpAllProfile( Number2Display, ExcludeMode);
475 }
476 } //------------- End of Cooked Mode Processing
477 if ( VerboseMode || SummaryMode) {
478 DumpStatistics();
479 }
480 }
481 }
482
483 //
484 // Free the memory allocate from HiiGetString
485 //
486 ListIndex = 0;
487 while (DpParamList[ListIndex].Name != NULL) {
488 FreePool (DpParamList[ListIndex].Name);
489 ListIndex ++;
490 }
491 FreePool (DpParamList);
492
493 SafeFreePool (StringDpOptionQh);
494 SafeFreePool (StringDpOptionLh);
495 SafeFreePool (StringDpOptionUh);
496 SafeFreePool (StringDpOptionLv);
497 SafeFreePool (StringDpOptionUs);
498 SafeFreePool (StringDpOptionLs);
499 SafeFreePool (StringDpOptionUa);
500 SafeFreePool (StringDpOptionUr);
501 SafeFreePool (StringDpOptionUt);
502 SafeFreePool (StringDpOptionUp);
503 SafeFreePool (StringDpOptionLx);
504 SafeFreePool (StringDpOptionLn);
505 SafeFreePool (StringDpOptionLt);
506 SafeFreePool (StringDpOptionLi);
507 SafeFreePool (StringDpOptionLc);
508 SafeFreePool (StringPtr);
509 SafeFreePool (mPrintTokenBuffer);
510
511 if (CustomCumulativeData != NULL) {
512 SafeFreePool (CustomCumulativeData->Name);
513 }
514 SafeFreePool (CustomCumulativeData);
515
516 HiiRemovePackages (gHiiHandle);
517 return Status;
518 }