2 Shell application for Displaying Performance Metrics.
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.
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.
16 Copyright (c) 2009 - 2017, Intel Corporation. All rights reserved.<BR>
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
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.
27 #include <Library/UefiApplicationEntryPoint.h>
28 #include <Library/UefiBootServicesTableLib.h>
29 #include <Library/ShellLib.h>
30 #include <Library/BaseLib.h>
31 #include <Library/MemoryAllocationLib.h>
32 #include <Library/DebugLib.h>
33 #include <Library/UefiLib.h>
34 #include <Library/UefiHiiServicesLib.h>
35 #include <Library/HiiLib.h>
36 #include <Library/PcdLib.h>
38 #include <Guid/Performance.h>
40 #include <PerformanceTokens.h>
43 #include "DpInternal.h"
46 // String token ID of help message text.
47 // Shell supports to find help message in the resource section of an application image if
48 // .MAN file is not found. This global variable is added to make build tool recognizes
49 // that the help string is consumed by user and then build tool will add the string into
50 // the resource section. Thus the application can use '-?' option to show help message in
53 GLOBAL_REMOVE_IF_UNREFERENCED EFI_STRING_ID mDpStrEngHelpTokenId
= STRING_TOKEN (STR_DP_HELP_INFORMATION
);
56 /// Module-Global Variables
58 EFI_HII_HANDLE gHiiHandle
;
59 SHELL_PARAM_ITEM
*DpParamList
= NULL
;
60 CHAR16
*mPrintTokenBuffer
= NULL
;
61 CHAR16 mGaugeString
[DP_GAUGE_STRING_LENGTH
+ 1];
62 CHAR16 mUnicodeToken
[DXE_PERFORMANCE_STRING_SIZE
];
63 UINT64 mInterestThreshold
;
64 BOOLEAN mShowId
= FALSE
;
66 PERF_SUMMARY_DATA SummaryData
= { 0 }; ///< Create the SummaryData structure and init. to ZERO.
68 /// Timer Specific Information.
71 /// Items for which to gather cumulative statistics.
72 PERF_CUM_DATA CumData
[] = {
73 PERF_INIT_CUM_DATA (LOAD_IMAGE_TOK
),
74 PERF_INIT_CUM_DATA (START_IMAGE_TOK
),
75 PERF_INIT_CUM_DATA (DRIVERBINDING_START_TOK
),
76 PERF_INIT_CUM_DATA (DRIVERBINDING_SUPPORT_TOK
)
79 /// Number of items for which we are gathering cumulative statistics.
80 UINT32
const NumCum
= sizeof(CumData
) / sizeof(PERF_CUM_DATA
);
82 PARAM_ITEM_LIST ParamList
[] = {
83 {STRING_TOKEN (STR_DP_OPTION_QH
), TypeFlag
}, // -? Help
84 {STRING_TOKEN (STR_DP_OPTION_LH
), TypeFlag
}, // -h Help
85 {STRING_TOKEN (STR_DP_OPTION_UH
), TypeFlag
}, // -H Help
86 {STRING_TOKEN (STR_DP_OPTION_LV
), TypeFlag
}, // -v Verbose Mode
87 {STRING_TOKEN (STR_DP_OPTION_UA
), TypeFlag
}, // -A All, Cooked
88 {STRING_TOKEN (STR_DP_OPTION_UR
), TypeFlag
}, // -R RAW All
89 {STRING_TOKEN (STR_DP_OPTION_LS
), TypeFlag
}, // -s Summary
90 #if PROFILING_IMPLEMENTED
91 {STRING_TOKEN (STR_DP_OPTION_UP
), TypeFlag
}, // -P Dump Profile Data
92 {STRING_TOKEN (STR_DP_OPTION_UT
), TypeFlag
}, // -T Dump Trace Data
94 {STRING_TOKEN (STR_DP_OPTION_LX
), TypeFlag
}, // -x eXclude Cumulative Items
95 {STRING_TOKEN (STR_DP_OPTION_LI
), TypeFlag
}, // -i Display Identifier
96 {STRING_TOKEN (STR_DP_OPTION_LC
), TypeValue
}, // -c Display cumulative data.
97 {STRING_TOKEN (STR_DP_OPTION_LN
), TypeValue
}, // -n # Number of records to display for A and R
98 {STRING_TOKEN (STR_DP_OPTION_LT
), TypeValue
} // -t # Threshold of interest
104 Transfer the param list value and get the command line parse.
108 InitialShellParamList( void )
114 // Allocate one more for the end tag.
116 ListLength
= ARRAY_SIZE (ParamList
) + 1;
117 DpParamList
= AllocatePool (sizeof (SHELL_PARAM_ITEM
) * ListLength
);
118 ASSERT (DpParamList
!= NULL
);
120 for (ListIndex
= 0; ListIndex
< ListLength
- 1; ListIndex
++)
122 DpParamList
[ListIndex
].Name
= HiiGetString (gHiiHandle
, ParamList
[ListIndex
].Token
, NULL
);
123 DpParamList
[ListIndex
].Type
= ParamList
[ListIndex
].Type
;
125 DpParamList
[ListIndex
].Name
= NULL
;
126 DpParamList
[ListIndex
].Type
= TypeMax
;
130 Display Usage and Help information.
135 PrintToken (STRING_TOKEN (STR_DP_HELP_HEAD
));
136 #if PROFILING_IMPLEMENTED
137 PrintToken (STRING_TOKEN (STR_DP_HELP_FLAGS
));
139 PrintToken (STRING_TOKEN (STR_DP_HELP_FLAGS_2
));
140 #endif // PROFILING_IMPLEMENTED
141 PrintToken (STRING_TOKEN (STR_DP_HELP_PAGINATE
));
142 PrintToken (STRING_TOKEN (STR_DP_HELP_VERBOSE
));
143 PrintToken (STRING_TOKEN (STR_DP_HELP_EXCLUDE
));
144 PrintToken (STRING_TOKEN (STR_DP_HELP_STAT
));
145 PrintToken (STRING_TOKEN (STR_DP_HELP_ALL
));
146 PrintToken (STRING_TOKEN (STR_DP_HELP_RAW
));
147 #if PROFILING_IMPLEMENTED
148 PrintToken (STRING_TOKEN (STR_DP_HELP_TRACE
));
149 PrintToken (STRING_TOKEN (STR_DP_HELP_PROFILE
));
150 #endif // PROFILING_IMPLEMENTED
151 PrintToken (STRING_TOKEN (STR_DP_HELP_THRESHOLD
));
152 PrintToken (STRING_TOKEN (STR_DP_HELP_COUNT
));
153 PrintToken (STRING_TOKEN (STR_DP_HELP_ID
));
154 PrintToken (STRING_TOKEN (STR_DP_HELP_CUM_DATA
));
155 PrintToken (STRING_TOKEN (STR_DP_HELP_HELP
));
160 Display the trailing Verbose information.
163 DumpStatistics( void )
165 EFI_STRING StringPtr
;
166 EFI_STRING StringPtrUnknown
;
167 StringPtr
= HiiGetString (gHiiHandle
, STRING_TOKEN (STR_DP_SECTION_STATISTICS
), NULL
);
168 StringPtrUnknown
= HiiGetString (gHiiHandle
, STRING_TOKEN (STR_ALIT_UNKNOWN
), NULL
);
169 PrintToken( STRING_TOKEN (STR_DP_SECTION_HEADER
),
170 (StringPtr
== NULL
) ? StringPtrUnknown
: StringPtr
);
172 PrintToken( STRING_TOKEN (STR_DP_STATS_NUMTRACE
), SummaryData
.NumTrace
);
173 PrintToken( STRING_TOKEN (STR_DP_STATS_NUMINCOMPLETE
), SummaryData
.NumIncomplete
);
174 PrintToken( STRING_TOKEN (STR_DP_STATS_NUMPHASES
), SummaryData
.NumSummary
);
175 PrintToken( STRING_TOKEN (STR_DP_STATS_NUMHANDLES
), SummaryData
.NumHandles
, SummaryData
.NumTrace
- SummaryData
.NumHandles
);
176 PrintToken( STRING_TOKEN (STR_DP_STATS_NUMPEIMS
), SummaryData
.NumPEIMs
);
177 PrintToken( STRING_TOKEN (STR_DP_STATS_NUMGLOBALS
), SummaryData
.NumGlobal
);
178 #if PROFILING_IMPLEMENTED
179 PrintToken( STRING_TOKEN (STR_DP_STATS_NUMPROFILE
), SummaryData
.NumProfile
);
180 #endif // PROFILING_IMPLEMENTED
181 FreePool (StringPtr
);
182 FreePool (StringPtrUnknown
);
186 Dump performance data.
188 @param[in] ImageHandle The image handle.
189 @param[in] SystemTable The system table.
191 @retval EFI_SUCCESS Command completed successfully.
192 @retval EFI_INVALID_PARAMETER Command usage error.
193 @retval EFI_ABORTED The user aborts the operation.
194 @retval value Unknown error.
199 IN EFI_HANDLE ImageHandle
,
200 IN EFI_SYSTEM_TABLE
*SystemTable
203 PERFORMANCE_PROPERTY
*PerformanceProperty
;
206 LIST_ENTRY
*ParamPackage
;
207 CONST CHAR16
*CmdLineArg
;
208 EFI_STRING StringPtr
;
209 UINTN Number2Display
;
219 BOOLEAN CumulativeMode
;
220 CONST CHAR16
*CustomCumulativeToken
;
221 PERF_CUM_DATA
*CustomCumulativeData
;
223 EFI_HII_PACKAGE_LIST_HEADER
*PackageList
;
225 EFI_STRING StringDpOptionQh
;
226 EFI_STRING StringDpOptionLh
;
227 EFI_STRING StringDpOptionUh
;
228 EFI_STRING StringDpOptionLv
;
229 EFI_STRING StringDpOptionUs
;
230 EFI_STRING StringDpOptionLs
;
231 EFI_STRING StringDpOptionUa
;
232 EFI_STRING StringDpOptionUr
;
233 EFI_STRING StringDpOptionUt
;
234 EFI_STRING StringDpOptionUp
;
235 EFI_STRING StringDpOptionLx
;
236 EFI_STRING StringDpOptionLn
;
237 EFI_STRING StringDpOptionLt
;
238 EFI_STRING StringDpOptionLi
;
239 EFI_STRING StringDpOptionLc
;
248 CumulativeMode
= FALSE
;
249 CustomCumulativeData
= NULL
;
251 StringDpOptionQh
= NULL
;
252 StringDpOptionLh
= NULL
;
253 StringDpOptionUh
= NULL
;
254 StringDpOptionLv
= NULL
;
255 StringDpOptionUs
= NULL
;
256 StringDpOptionLs
= NULL
;
257 StringDpOptionUa
= NULL
;
258 StringDpOptionUr
= NULL
;
259 StringDpOptionUt
= NULL
;
260 StringDpOptionUp
= NULL
;
261 StringDpOptionLx
= NULL
;
262 StringDpOptionLn
= NULL
;
263 StringDpOptionLt
= NULL
;
264 StringDpOptionLi
= NULL
;
265 StringDpOptionLc
= NULL
;
269 // Retrieve HII package list from ImageHandle
271 Status
= gBS
->OpenProtocol (
273 &gEfiHiiPackageListProtocolGuid
,
274 (VOID
**) &PackageList
,
277 EFI_OPEN_PROTOCOL_GET_PROTOCOL
279 if (EFI_ERROR (Status
)) {
284 // Publish HII package list to HII Database.
286 Status
= gHiiDatabase
->NewPackageList (
292 if (EFI_ERROR (Status
)) {
295 ASSERT (gHiiHandle
!= NULL
);
298 // Initial the command list
300 InitialShellParamList ();
302 /****************************************************************************
303 **** Process Command Line arguments ****
304 ****************************************************************************/
305 Status
= ShellCommandLineParse (DpParamList
, &ParamPackage
, NULL
, TRUE
);
307 if (EFI_ERROR(Status
)) {
308 PrintToken (STRING_TOKEN (STR_DP_INVALID_ARG
));
312 StringDpOptionQh
= HiiGetString (gHiiHandle
, STRING_TOKEN (STR_DP_OPTION_QH
), NULL
);
313 StringDpOptionLh
= HiiGetString (gHiiHandle
, STRING_TOKEN (STR_DP_OPTION_LH
), NULL
);
314 StringDpOptionUh
= HiiGetString (gHiiHandle
, STRING_TOKEN (STR_DP_OPTION_UH
), NULL
);
316 if (ShellCommandLineGetFlag (ParamPackage
, StringDpOptionQh
) ||
317 ShellCommandLineGetFlag (ParamPackage
, StringDpOptionLh
) ||
318 ShellCommandLineGetFlag (ParamPackage
, StringDpOptionUh
))
323 StringDpOptionLv
= HiiGetString (gHiiHandle
, STRING_TOKEN (STR_DP_OPTION_LV
), NULL
);
324 StringDpOptionUs
= HiiGetString (gHiiHandle
, STRING_TOKEN (STR_DP_OPTION_US
), NULL
);
325 StringDpOptionLs
= HiiGetString (gHiiHandle
, STRING_TOKEN (STR_DP_OPTION_LS
), NULL
);
326 StringDpOptionUa
= HiiGetString (gHiiHandle
, STRING_TOKEN (STR_DP_OPTION_UA
), NULL
);
327 StringDpOptionUr
= HiiGetString (gHiiHandle
, STRING_TOKEN (STR_DP_OPTION_UR
), NULL
);
328 StringDpOptionUt
= HiiGetString (gHiiHandle
, STRING_TOKEN (STR_DP_OPTION_UT
), NULL
);
329 StringDpOptionUp
= HiiGetString (gHiiHandle
, STRING_TOKEN (STR_DP_OPTION_UP
), NULL
);
330 StringDpOptionLx
= HiiGetString (gHiiHandle
, STRING_TOKEN (STR_DP_OPTION_LX
), NULL
);
331 StringDpOptionLn
= HiiGetString (gHiiHandle
, STRING_TOKEN (STR_DP_OPTION_LN
), NULL
);
332 StringDpOptionLt
= HiiGetString (gHiiHandle
, STRING_TOKEN (STR_DP_OPTION_LT
), NULL
);
333 StringDpOptionLi
= HiiGetString (gHiiHandle
, STRING_TOKEN (STR_DP_OPTION_LI
), NULL
);
334 StringDpOptionLc
= HiiGetString (gHiiHandle
, STRING_TOKEN (STR_DP_OPTION_LC
), NULL
);
338 VerboseMode
= ShellCommandLineGetFlag (ParamPackage
, StringDpOptionLv
);
339 SummaryMode
= (BOOLEAN
) (ShellCommandLineGetFlag (ParamPackage
, StringDpOptionUs
) ||
340 ShellCommandLineGetFlag (ParamPackage
, StringDpOptionLs
));
341 AllMode
= ShellCommandLineGetFlag (ParamPackage
, StringDpOptionUa
);
342 RawMode
= ShellCommandLineGetFlag (ParamPackage
, StringDpOptionUr
);
343 #if PROFILING_IMPLEMENTED
344 TraceMode
= ShellCommandLineGetFlag (ParamPackage
, StringDpOptionUt
);
345 ProfileMode
= ShellCommandLineGetFlag (ParamPackage
, StringDpOptionUp
);
346 #endif // PROFILING_IMPLEMENTED
347 ExcludeMode
= ShellCommandLineGetFlag (ParamPackage
, StringDpOptionLx
);
348 mShowId
= ShellCommandLineGetFlag (ParamPackage
, StringDpOptionLi
);
349 CumulativeMode
= ShellCommandLineGetFlag (ParamPackage
, StringDpOptionLc
);
351 // Options with Values
352 CmdLineArg
= ShellCommandLineGetValue (ParamPackage
, StringDpOptionLn
);
353 if (CmdLineArg
== NULL
) {
354 Number2Display
= DEFAULT_DISPLAYCOUNT
;
357 Number2Display
= StrDecimalToUintn(CmdLineArg
);
358 if (Number2Display
== 0) {
359 Number2Display
= MAXIMUM_DISPLAYCOUNT
;
362 CmdLineArg
= ShellCommandLineGetValue (ParamPackage
, StringDpOptionLt
);
363 if (CmdLineArg
== NULL
) {
364 mInterestThreshold
= DEFAULT_THRESHOLD
; // 1ms := 1,000 us
367 mInterestThreshold
= StrDecimalToUint64(CmdLineArg
);
369 // Handle Flag combinations and default behaviors
370 // If both TraceMode and ProfileMode are FALSE, set them both to TRUE
371 if ((! TraceMode
) && (! ProfileMode
)) {
373 #if PROFILING_IMPLEMENTED
375 #endif // PROFILING_IMPLEMENTED
379 // Init the custom cumulative data.
381 CustomCumulativeToken
= ShellCommandLineGetValue (ParamPackage
, StringDpOptionLc
);
382 if (CustomCumulativeToken
!= NULL
) {
383 CustomCumulativeData
= AllocateZeroPool (sizeof (PERF_CUM_DATA
));
384 ASSERT (CustomCumulativeData
!= NULL
);
385 CustomCumulativeData
->MinDur
= 0;
386 CustomCumulativeData
->MaxDur
= 0;
387 CustomCumulativeData
->Count
= 0;
388 CustomCumulativeData
->Duration
= 0;
389 NameSize
= StrLen (CustomCumulativeToken
) + 1;
390 CustomCumulativeData
->Name
= AllocateZeroPool (NameSize
);
391 UnicodeStrToAsciiStrS (CustomCumulativeToken
, CustomCumulativeData
->Name
, NameSize
);
394 /****************************************************************************
395 **** Timer specific processing ****
396 ****************************************************************************/
397 // Get the Performance counter characteristics:
398 // Freq = Frequency in Hz
399 // StartCount = Value loaded into the counter when it starts counting
400 // EndCount = Value counter counts to before it needs to be reset
402 Status
= EfiGetSystemConfigurationTable (&gPerformanceProtocolGuid
, (VOID
**) &PerformanceProperty
);
403 if (EFI_ERROR (Status
) || (PerformanceProperty
== NULL
)) {
404 PrintToken (STRING_TOKEN (STR_PERF_PROPERTY_NOT_FOUND
));
408 // Convert the Frequency from Hz to KHz
409 TimerInfo
.Frequency
= (UINT32
)DivU64x32 (PerformanceProperty
->Frequency
, 1000);
410 TimerInfo
.StartCount
= PerformanceProperty
->TimerStartValue
;
411 TimerInfo
.EndCount
= PerformanceProperty
->TimerEndValue
;
413 // Determine in which direction the performance counter counts.
414 TimerInfo
.CountUp
= (BOOLEAN
) (TimerInfo
.EndCount
>= TimerInfo
.StartCount
);
416 /****************************************************************************
417 **** Print heading ****
418 ****************************************************************************/
419 // print DP's build version
420 PrintToken (STRING_TOKEN (STR_DP_BUILD_REVISION
), DP_MAJOR_VERSION
, DP_MINOR_VERSION
);
422 // print performance timer characteristics
423 PrintToken (STRING_TOKEN (STR_DP_KHZ
), TimerInfo
.Frequency
); // Print Timer frequency in KHz
428 StringPtr
= HiiGetString (gHiiHandle
,
429 (EFI_STRING_ID
) (TimerInfo
.CountUp
? STRING_TOKEN (STR_DP_UP
) : STRING_TOKEN (STR_DP_DOWN
)),
431 ASSERT (StringPtr
!= NULL
);
432 PrintToken (STRING_TOKEN (STR_DP_TIMER_PROPERTIES
), // Print Timer count range and direction
434 TimerInfo
.StartCount
,
437 PrintToken (STRING_TOKEN (STR_DP_VERBOSE_THRESHOLD
), mInterestThreshold
);
440 /* **************************************************************************
441 **** Print Sections based on command line options
443 **** Option modes have the following priority:
444 **** v Verbose -- Valid in combination with any other options
445 **** t Threshold -- Modifies All, Raw, and Cooked output
446 **** Default is 0 for All and Raw mode
447 **** Default is DEFAULT_THRESHOLD for "Cooked" mode
448 **** n Number2Display Used by All and Raw mode. Otherwise ignored.
449 **** A All -- R and S options are ignored
450 **** R Raw -- S option is ignored
451 **** s Summary -- Modifies "Cooked" output only
452 **** Cooked (Default)
454 **** The All, Raw, and Cooked modes are modified by the Trace and Profile
456 **** !T && !P := (0) Default, Both are displayed
457 **** T && !P := (1) Only Trace records are displayed
458 **** !T && P := (2) Only Profile records are displayed
459 **** T && P := (3) Same as Default, both are displayed
460 ****************************************************************************/
461 GatherStatistics (CustomCumulativeData
);
462 if (CumulativeMode
) {
463 ProcessCumulative (CustomCumulativeData
);
464 } else if (AllMode
) {
466 Status
= DumpAllTrace( Number2Display
, ExcludeMode
);
467 if (Status
== EFI_ABORTED
) {
472 DumpAllProfile( Number2Display
, ExcludeMode
);
477 Status
= DumpRawTrace( Number2Display
, ExcludeMode
);
478 if (Status
== EFI_ABORTED
) {
483 DumpRawProfile( Number2Display
, ExcludeMode
);
487 //------------- Begin Cooked Mode Processing
490 if ( ! SummaryMode
) {
491 Status
= ProcessHandles ( ExcludeMode
);
492 if (Status
== EFI_ABORTED
) {
496 Status
= ProcessPeims ();
497 if (Status
== EFI_ABORTED
) {
501 Status
= ProcessGlobal ();
502 if (Status
== EFI_ABORTED
) {
506 ProcessCumulative (NULL
);
510 DumpAllProfile( Number2Display
, ExcludeMode
);
512 } //------------- End of Cooked Mode Processing
513 if ( VerboseMode
|| SummaryMode
) {
522 // Free the memory allocate from HiiGetString
525 while (DpParamList
[ListIndex
].Name
!= NULL
) {
526 FreePool (DpParamList
[ListIndex
].Name
);
529 FreePool (DpParamList
);
531 SafeFreePool (StringDpOptionQh
);
532 SafeFreePool (StringDpOptionLh
);
533 SafeFreePool (StringDpOptionUh
);
534 SafeFreePool (StringDpOptionLv
);
535 SafeFreePool (StringDpOptionUs
);
536 SafeFreePool (StringDpOptionLs
);
537 SafeFreePool (StringDpOptionUa
);
538 SafeFreePool (StringDpOptionUr
);
539 SafeFreePool (StringDpOptionUt
);
540 SafeFreePool (StringDpOptionUp
);
541 SafeFreePool (StringDpOptionLx
);
542 SafeFreePool (StringDpOptionLn
);
543 SafeFreePool (StringDpOptionLt
);
544 SafeFreePool (StringDpOptionLi
);
545 SafeFreePool (StringDpOptionLc
);
546 SafeFreePool (StringPtr
);
547 SafeFreePool (mPrintTokenBuffer
);
549 if (ParamPackage
!= NULL
) {
550 ShellCommandLineFreeVarList (ParamPackage
);
552 if (CustomCumulativeData
!= NULL
) {
553 SafeFreePool (CustomCumulativeData
->Name
);
555 SafeFreePool (CustomCumulativeData
);
557 HiiRemovePackages (gHiiHandle
);