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