]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - ShellPkg/DynamicCommand/DpDynamicCommand/DpTrace.c
ShellPkg/dp: Update dp tool to parse new Perf record
[mirror_edk2.git] / ShellPkg / DynamicCommand / DpDynamicCommand / DpTrace.c
... / ...
CommitLineData
1/** @file\r
2 Trace reporting for the Dp utility.\r
3\r
4 Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.\r
5 (C) Copyright 2015-2016 Hewlett Packard Enterprise Development LP<BR>\r
6 This program and the accompanying materials\r
7 are licensed and made available under the terms and conditions of the BSD License\r
8 which accompanies this distribution. The full text of the license may be found at\r
9 http://opensource.org/licenses/bsd-license.php\r
10\r
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13**/\r
14\r
15#include <Library/BaseLib.h>\r
16#include <Library/BaseMemoryLib.h>\r
17#include <Library/MemoryAllocationLib.h>\r
18#include <Library/DebugLib.h>\r
19#include <Library/UefiBootServicesTableLib.h>\r
20#include <Library/PeCoffGetEntryPointLib.h>\r
21#include <Library/PerformanceLib.h>\r
22#include <Library/PrintLib.h>\r
23#include <Library/HiiLib.h>\r
24#include <Library/PcdLib.h>\r
25\r
26#include "Dp.h"\r
27#include "Literals.h"\r
28#include "DpInternal.h"\r
29\r
30/**\r
31 Attempts to retrieve a performance measurement log entry from the performance measurement log.\r
32\r
33\r
34 @param LogEntryKey On entry, the key of the performance measurement log entry to retrieve.\r
35 0, then the first performance measurement log entry is retrieved.\r
36 On exit, the key of the next performance log entry.\r
37 @param Handle Pointer to environment specific context used to identify the component\r
38 being measured.\r
39 @param Token Pointer to a Null-terminated ASCII string that identifies the component\r
40 being measured.\r
41 @param Module Pointer to a Null-terminated ASCII string that identifies the module\r
42 being measured.\r
43 @param StartTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement\r
44 was started.\r
45 @param EndTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement\r
46 was ended.\r
47 @param Identifier Pointer to the 32-bit identifier that was recorded when the measurement\r
48 was ended.\r
49\r
50 @return The key for the next performance log entry (in general case).\r
51\r
52**/\r
53UINTN\r
54GetPerformanceMeasurementRecord (\r
55 IN UINTN LogEntryKey,\r
56 OUT CONST VOID **Handle,\r
57 OUT CONST CHAR8 **Token,\r
58 OUT CONST CHAR8 **Module,\r
59 OUT UINT64 *StartTimeStamp,\r
60 OUT UINT64 *EndTimeStamp,\r
61 OUT UINT32 *Identifier\r
62 )\r
63{\r
64 if (LogEntryKey == mMeasurementNum) {\r
65 return 0;\r
66 }\r
67\r
68 *Handle = (VOID *) (UINTN) mMeasurementList[LogEntryKey].Handle;\r
69 *Token = mMeasurementList[LogEntryKey].Token;\r
70 *Module = mMeasurementList[LogEntryKey].Module;\r
71 *StartTimeStamp = mMeasurementList[LogEntryKey].StartTimeStamp;\r
72 *EndTimeStamp = mMeasurementList[LogEntryKey].EndTimeStamp;\r
73 *Identifier = mMeasurementList[LogEntryKey].Identifier;\r
74\r
75 LogEntryKey ++;\r
76\r
77 return LogEntryKey;\r
78}\r
79\r
80/**\r
81 Collect verbose statistics about the logged performance measurements.\r
82\r
83 General Summary information for all Trace measurements is gathered and\r
84 stored within the SummaryData structure. This information is both\r
85 used internally by subsequent reporting functions, and displayed\r
86 at the end of verbose reports.\r
87\r
88 @pre The SummaryData and CumData structures must be initialized\r
89 prior to calling this function.\r
90\r
91 @post The SummaryData and CumData structures contain statistics for the\r
92 current performance logs.\r
93\r
94 @param[in, out] CustomCumulativeData A pointer to the cumtom cumulative data.\r
95\r
96**/\r
97VOID\r
98GatherStatistics(\r
99 IN OUT PERF_CUM_DATA *CustomCumulativeData OPTIONAL\r
100 )\r
101{\r
102 MEASUREMENT_RECORD Measurement;\r
103 UINT64 Duration;\r
104 UINTN LogEntryKey;\r
105 INTN TIndex;\r
106\r
107 LogEntryKey = 0;\r
108 while ((LogEntryKey = GetPerformanceMeasurementRecord (\r
109 LogEntryKey,\r
110 &Measurement.Handle,\r
111 &Measurement.Token,\r
112 &Measurement.Module,\r
113 &Measurement.StartTimeStamp,\r
114 &Measurement.EndTimeStamp,\r
115 &Measurement.Identifier)) != 0)\r
116 {\r
117 ++SummaryData.NumTrace; // Count the number of TRACE Measurement records\r
118 if (Measurement.EndTimeStamp == 0) {\r
119 ++SummaryData.NumIncomplete; // Count the incomplete records\r
120 continue;\r
121 }\r
122\r
123 if (Measurement.Handle != NULL) {\r
124 ++SummaryData.NumHandles; // Count the number of measurements with non-NULL handles\r
125 }\r
126\r
127 if (IsPhase( &Measurement)) {\r
128 ++SummaryData.NumSummary; // Count the number of major phases\r
129 }\r
130 else { // !IsPhase\r
131 if(Measurement.Handle == NULL) {\r
132 ++SummaryData.NumGlobal;\r
133 }\r
134 }\r
135\r
136 if (AsciiStrCmp (Measurement.Token, ALit_PEIM) == 0) {\r
137 ++SummaryData.NumPEIMs; // Count PEIM measurements\r
138 }\r
139\r
140 Duration = GetDuration (&Measurement);\r
141 TIndex = GetCumulativeItem (&Measurement);\r
142 if (TIndex >= 0) {\r
143 CumData[TIndex].Duration += Duration;\r
144 CumData[TIndex].Count++;\r
145 if ( Duration < CumData[TIndex].MinDur ) {\r
146 CumData[TIndex].MinDur = Duration;\r
147 }\r
148 if ( Duration > CumData[TIndex].MaxDur ) {\r
149 CumData[TIndex].MaxDur = Duration;\r
150 }\r
151 }\r
152\r
153 //\r
154 // Collect the data for custom cumulative data.\r
155 //\r
156 if ((CustomCumulativeData != NULL) && (AsciiStrCmp (Measurement.Token, CustomCumulativeData->Name) == 0)) {\r
157 CustomCumulativeData->Duration += Duration;\r
158 CustomCumulativeData->Count++;\r
159 if (Duration < CustomCumulativeData->MinDur) {\r
160 CustomCumulativeData->MinDur = Duration;\r
161 }\r
162 if (Duration > CustomCumulativeData->MaxDur) {\r
163 CustomCumulativeData->MaxDur = Duration;\r
164 }\r
165 }\r
166 }\r
167}\r
168\r
169/**\r
170 Gather and print ALL Trace Records.\r
171\r
172 Displays all "interesting" Trace measurements in order.<BR>\r
173 The number of records displayed is controlled by:\r
174 - records with a duration less than mInterestThreshold microseconds are not displayed.\r
175 - No more than Limit records are displayed. A Limit of zero will not limit the output.\r
176 - If the ExcludeFlag is TRUE, records matching entries in the CumData array are not\r
177 displayed.\r
178\r
179 @pre The mInterestThreshold global variable is set to the shortest duration to be printed.\r
180 The mGaugeString and mUnicodeToken global arrays are used for temporary string storage.\r
181 They must not be in use by a calling function.\r
182\r
183 @param[in] Limit The number of records to print. Zero is ALL.\r
184 @param[in] ExcludeFlag TRUE to exclude individual Cumulative items from display.\r
185\r
186 @retval EFI_SUCCESS The operation was successful.\r
187 @retval EFI_ABORTED The user aborts the operation.\r
188 @return Others from a call to gBS->LocateHandleBuffer().\r
189**/\r
190EFI_STATUS\r
191DumpAllTrace(\r
192 IN UINTN Limit,\r
193 IN BOOLEAN ExcludeFlag\r
194 )\r
195{\r
196 MEASUREMENT_RECORD Measurement;\r
197 UINT64 ElapsedTime;\r
198 UINT64 Duration;\r
199 CHAR16 *IncFlag;\r
200 UINTN LogEntryKey;\r
201 UINTN Count;\r
202 UINTN Index;\r
203 UINTN TIndex;\r
204\r
205 EFI_HANDLE *HandleBuffer;\r
206 UINTN HandleCount;\r
207 EFI_STATUS Status;\r
208 EFI_STRING StringPtrUnknown;\r
209\r
210 StringPtrUnknown = HiiGetString (mDpHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL);\r
211 IncFlag = HiiGetString (mDpHiiHandle, STRING_TOKEN (STR_DP_SECTION_ALL), NULL);\r
212 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_SECTION_HEADER), mDpHiiHandle,\r
213 (IncFlag == NULL) ? StringPtrUnknown : IncFlag);\r
214 FreePool (StringPtrUnknown);\r
215\r
216 // Get Handle information\r
217 //\r
218 Status = gBS->LocateHandleBuffer (AllHandles, NULL, NULL, &HandleCount, &HandleBuffer);\r
219 if (EFI_ERROR (Status)) {\r
220 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_HANDLES_ERROR), mDpHiiHandle, Status);\r
221 }\r
222 else {\r
223 // We have successfully populated the HandleBuffer\r
224 // Display ALL Measurement Records\r
225 // Up to Limit lines displayed\r
226 // Display only records with Elapsed times >= mInterestThreshold\r
227 // Display driver names in Module field for records with Handles.\r
228 //\r
229 if (mShowId) {\r
230 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_ALL_HEADR2), mDpHiiHandle);\r
231 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_ALL_DASHES2), mDpHiiHandle);\r
232 } else {\r
233 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_ALL_HEADR), mDpHiiHandle);\r
234 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_DASHES), mDpHiiHandle);\r
235 }\r
236\r
237 LogEntryKey = 0;\r
238 Count = 0;\r
239 Index = 0;\r
240 while ( WITHIN_LIMIT(Count, Limit) &&\r
241 ((LogEntryKey = GetPerformanceMeasurementRecord (\r
242 LogEntryKey,\r
243 &Measurement.Handle,\r
244 &Measurement.Token,\r
245 &Measurement.Module,\r
246 &Measurement.StartTimeStamp,\r
247 &Measurement.EndTimeStamp,\r
248 &Measurement.Identifier)) != 0)\r
249 )\r
250 {\r
251 ++Index; // Count every record. First record is 1.\r
252 ElapsedTime = 0;\r
253 SHELL_FREE_NON_NULL (IncFlag);\r
254 if (Measurement.EndTimeStamp != 0) {\r
255 Duration = GetDuration (&Measurement);\r
256 ElapsedTime = DurationInMicroSeconds ( Duration );\r
257 IncFlag = HiiGetString (mDpHiiHandle, STRING_TOKEN (STR_DP_COMPLETE), NULL);\r
258 }\r
259 else {\r
260 IncFlag = HiiGetString (mDpHiiHandle, STRING_TOKEN (STR_DP_INCOMPLETE), NULL); // Mark incomplete records\r
261 }\r
262 if (((Measurement.EndTimeStamp != 0) && (ElapsedTime < mInterestThreshold)) ||\r
263 ((ExcludeFlag) && (GetCumulativeItem(&Measurement) >= 0))\r
264 ) { // Ignore "uninteresting" or excluded records\r
265 continue;\r
266 }\r
267 ++Count; // Count the number of records printed\r
268\r
269 // If Handle is non-zero, see if we can determine a name for the driver\r
270 AsciiStrToUnicodeStrS (Measurement.Module, mGaugeString, ARRAY_SIZE (mGaugeString)); // Use Module by default\r
271 AsciiStrToUnicodeStrS (Measurement.Token, mUnicodeToken, ARRAY_SIZE (mUnicodeToken));\r
272 if (Measurement.Handle != NULL) {\r
273 // See if the Handle is in the HandleBuffer\r
274 for (TIndex = 0; TIndex < HandleCount; TIndex++) {\r
275 if (Measurement.Handle == HandleBuffer[TIndex]) {\r
276 DpGetNameFromHandle (HandleBuffer[TIndex]);\r
277 break;\r
278 }\r
279 }\r
280 }\r
281\r
282 if (AsciiStrCmp (Measurement.Token, ALit_PEIM) == 0) {\r
283 UnicodeSPrint (mGaugeString, sizeof (mGaugeString), L"%g", Measurement.Handle);\r
284 }\r
285\r
286 // Ensure that the argument strings are not too long.\r
287 mGaugeString[DP_GAUGE_STRING_LENGTH] = 0;\r
288 mUnicodeToken[13] = 0;\r
289\r
290 if (mShowId) {\r
291 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_ALL_VARS2), mDpHiiHandle,\r
292 Index, // 1 based, Which measurement record is being printed\r
293 IncFlag,\r
294 Measurement.Handle,\r
295 mGaugeString,\r
296 mUnicodeToken,\r
297 ElapsedTime,\r
298 Measurement.Identifier\r
299 );\r
300 } else {\r
301 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_ALL_VARS), mDpHiiHandle,\r
302 Index, // 1 based, Which measurement record is being printed\r
303 IncFlag,\r
304 Measurement.Handle,\r
305 mGaugeString,\r
306 mUnicodeToken,\r
307 ElapsedTime\r
308 );\r
309 }\r
310 if (ShellGetExecutionBreakFlag ()) {\r
311 Status = EFI_ABORTED;\r
312 break;\r
313 }\r
314 }\r
315 }\r
316 if (HandleBuffer != NULL) {\r
317 FreePool (HandleBuffer);\r
318 }\r
319 SHELL_FREE_NON_NULL (IncFlag);\r
320\r
321 return Status;\r
322}\r
323\r
324/**\r
325 Gather and print Raw Trace Records.\r
326\r
327 All Trace measurements with a duration greater than or equal to\r
328 mInterestThreshold are printed without interpretation.\r
329\r
330 The number of records displayed is controlled by:\r
331 - records with a duration less than mInterestThreshold microseconds are not displayed.\r
332 - No more than Limit records are displayed. A Limit of zero will not limit the output.\r
333 - If the ExcludeFlag is TRUE, records matching entries in the CumData array are not\r
334 displayed.\r
335\r
336 @pre The mInterestThreshold global variable is set to the shortest duration to be printed.\r
337\r
338 @param[in] Limit The number of records to print. Zero is ALL.\r
339 @param[in] ExcludeFlag TRUE to exclude individual Cumulative items from display.\r
340\r
341 @retval EFI_SUCCESS The operation was successful.\r
342 @retval EFI_ABORTED The user aborts the operation.\r
343**/\r
344EFI_STATUS\r
345DumpRawTrace(\r
346 IN UINTN Limit,\r
347 IN BOOLEAN ExcludeFlag\r
348 )\r
349{\r
350 MEASUREMENT_RECORD Measurement;\r
351 UINT64 ElapsedTime;\r
352 UINT64 Duration;\r
353 UINTN LogEntryKey;\r
354 UINTN Count;\r
355 UINTN Index;\r
356\r
357 EFI_STRING StringPtr;\r
358 EFI_STRING StringPtrUnknown;\r
359 EFI_STATUS Status;\r
360\r
361 Status = EFI_SUCCESS;\r
362\r
363 StringPtrUnknown = HiiGetString (mDpHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL);\r
364 StringPtr = HiiGetString (mDpHiiHandle, STRING_TOKEN (STR_DP_SECTION_RAWTRACE), NULL);\r
365 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_SECTION_HEADER), mDpHiiHandle,\r
366 (StringPtr == NULL) ? StringPtrUnknown : StringPtr);\r
367 FreePool (StringPtr);\r
368 FreePool (StringPtrUnknown);\r
369\r
370 if (mShowId) {\r
371 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_RAW_HEADR2), mDpHiiHandle);\r
372 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_RAW_DASHES2), mDpHiiHandle);\r
373 } else {\r
374 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_RAW_HEADR), mDpHiiHandle);\r
375 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_RAW_DASHES), mDpHiiHandle);\r
376 }\r
377\r
378 LogEntryKey = 0;\r
379 Count = 0;\r
380 Index = 0;\r
381 while ( WITHIN_LIMIT(Count, Limit) &&\r
382 ((LogEntryKey = GetPerformanceMeasurementRecord (\r
383 LogEntryKey,\r
384 &Measurement.Handle,\r
385 &Measurement.Token,\r
386 &Measurement.Module,\r
387 &Measurement.StartTimeStamp,\r
388 &Measurement.EndTimeStamp,\r
389 &Measurement.Identifier)) != 0)\r
390 )\r
391 {\r
392 ++Index; // Count every record. First record is 1.\r
393 ElapsedTime = 0;\r
394 if (Measurement.EndTimeStamp != 0) {\r
395 Duration = GetDuration (&Measurement);\r
396 ElapsedTime = DurationInMicroSeconds ( Duration );\r
397 }\r
398 if ((ElapsedTime < mInterestThreshold) ||\r
399 ((ExcludeFlag) && (GetCumulativeItem(&Measurement) >= 0))\r
400 ) { // Ignore "uninteresting" or Excluded records\r
401 continue;\r
402 }\r
403 ++Count; // Count the number of records printed\r
404\r
405 if (mShowId) {\r
406 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_RAW_VARS2), mDpHiiHandle,\r
407 Index, // 1 based, Which measurement record is being printed\r
408 Measurement.Handle,\r
409 Measurement.StartTimeStamp,\r
410 Measurement.EndTimeStamp,\r
411 Measurement.Token,\r
412 Measurement.Module,\r
413 Measurement.Identifier\r
414 );\r
415 } else {\r
416 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_RAW_VARS), mDpHiiHandle,\r
417 Index, // 1 based, Which measurement record is being printed\r
418 Measurement.Handle,\r
419 Measurement.StartTimeStamp,\r
420 Measurement.EndTimeStamp,\r
421 Measurement.Token,\r
422 Measurement.Module\r
423 );\r
424 }\r
425 if (ShellGetExecutionBreakFlag ()) {\r
426 Status = EFI_ABORTED;\r
427 break;\r
428 }\r
429 }\r
430 return Status;\r
431}\r
432\r
433/**\r
434 Gather and print Major Phase metrics.\r
435\r
436**/\r
437VOID\r
438ProcessPhases(\r
439 VOID\r
440 )\r
441{\r
442 MEASUREMENT_RECORD Measurement;\r
443 UINT64 BdsTimeoutValue;\r
444 UINT64 SecTime;\r
445 UINT64 PeiTime;\r
446 UINT64 DxeTime;\r
447 UINT64 BdsTime;\r
448 UINT64 ElapsedTime;\r
449 UINT64 Duration;\r
450 UINT64 Total;\r
451 EFI_STRING StringPtr;\r
452 UINTN LogEntryKey;\r
453 EFI_STRING StringPtrUnknown;\r
454\r
455 BdsTimeoutValue = 0;\r
456 SecTime = 0;\r
457 PeiTime = 0;\r
458 DxeTime = 0;\r
459 BdsTime = 0;\r
460 //\r
461 // Get Execution Phase Statistics\r
462 //\r
463 StringPtrUnknown = HiiGetString (mDpHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL);\r
464 StringPtr = HiiGetString (mDpHiiHandle, STRING_TOKEN (STR_DP_SECTION_PHASES), NULL);\r
465 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_SECTION_HEADER), mDpHiiHandle,\r
466 (StringPtr == NULL) ? StringPtrUnknown : StringPtr);\r
467 FreePool (StringPtr);\r
468 FreePool (StringPtrUnknown);\r
469\r
470 LogEntryKey = 0;\r
471 while ((LogEntryKey = GetPerformanceMeasurementRecord (\r
472 LogEntryKey,\r
473 &Measurement.Handle,\r
474 &Measurement.Token,\r
475 &Measurement.Module,\r
476 &Measurement.StartTimeStamp,\r
477 &Measurement.EndTimeStamp,\r
478 &Measurement.Identifier)) != 0)\r
479 {\r
480 if (Measurement.EndTimeStamp == 0) { // Skip "incomplete" records\r
481 continue;\r
482 }\r
483 Duration = GetDuration (&Measurement);\r
484 if ( Measurement.Handle != NULL\r
485 && (AsciiStrCmp (Measurement.Token, ALit_BdsTO) == 0)\r
486 )\r
487 {\r
488 BdsTimeoutValue = Duration;\r
489 } else if (AsciiStrCmp (Measurement.Token, ALit_SEC) == 0) {\r
490 SecTime = Duration;\r
491 } else if (AsciiStrCmp (Measurement.Token, ALit_PEI) == 0) {\r
492 PeiTime = Duration;\r
493 } else if (AsciiStrCmp (Measurement.Token, ALit_DXE) == 0) {\r
494 DxeTime = Duration;\r
495 } else if (AsciiStrCmp (Measurement.Token, ALit_BDS) == 0) {\r
496 BdsTime = Duration;\r
497 }\r
498 }\r
499\r
500 Total = 0;\r
501\r
502 // print SEC phase duration time\r
503 //\r
504 if (SecTime > 0) {\r
505 ElapsedTime = DurationInMicroSeconds ( SecTime ); // Calculate elapsed time in microseconds\r
506 Total += DivU64x32 (ElapsedTime, 1000); // Accumulate time in milliseconds\r
507 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_SEC_PHASE), mDpHiiHandle, ElapsedTime);\r
508 }\r
509\r
510 // print PEI phase duration time\r
511 //\r
512 if (PeiTime > 0) {\r
513 ElapsedTime = DivU64x32 (PeiTime, 1000000);\r
514 Total += ElapsedTime;\r
515 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_PHASE_DURATION), mDpHiiHandle, ALit_PEI, ElapsedTime);\r
516 }\r
517\r
518 // print DXE phase duration time\r
519 //\r
520 if (DxeTime > 0) {\r
521 ElapsedTime = DivU64x32 (DxeTime, 1000000);\r
522 Total += ElapsedTime;\r
523 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_PHASE_DURATION), mDpHiiHandle, ALit_DXE, ElapsedTime);\r
524 }\r
525\r
526 // print BDS phase duration time\r
527 //\r
528 if (BdsTime > 0) {\r
529 ElapsedTime = DivU64x32 (BdsTime, 1000000);\r
530 Total += ElapsedTime;\r
531 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_PHASE_DURATION), mDpHiiHandle, ALit_BDS, ElapsedTime);\r
532 }\r
533\r
534 if (BdsTimeoutValue > 0) {\r
535 ElapsedTime = DivU64x32 (BdsTimeoutValue, 1000000);\r
536 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_PHASE_BDSTO), mDpHiiHandle, ALit_BdsTO, ElapsedTime);\r
537 }\r
538\r
539 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_TOTAL_DURATION), mDpHiiHandle, Total);\r
540}\r
541\r
542/**\r
543 Gather and print Handle data.\r
544\r
545 @param[in] ExcludeFlag TRUE to exclude individual Cumulative items from display.\r
546\r
547 @retval EFI_SUCCESS The operation was successful.\r
548 @retval EFI_ABORTED The user aborts the operation.\r
549 @return Others from a call to gBS->LocateHandleBuffer().\r
550**/\r
551EFI_STATUS\r
552ProcessHandles(\r
553 IN BOOLEAN ExcludeFlag\r
554 )\r
555{\r
556 MEASUREMENT_RECORD Measurement;\r
557 UINT64 ElapsedTime;\r
558 UINT64 Duration;\r
559 EFI_HANDLE *HandleBuffer;\r
560 EFI_STRING StringPtr;\r
561 UINTN Index;\r
562 UINTN LogEntryKey;\r
563 UINTN Count;\r
564 UINTN HandleCount;\r
565 EFI_STATUS Status;\r
566 EFI_STRING StringPtrUnknown;\r
567\r
568 StringPtrUnknown = HiiGetString (mDpHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL);\r
569 StringPtr = HiiGetString (mDpHiiHandle, STRING_TOKEN (STR_DP_SECTION_DRIVERS), NULL);\r
570 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_SECTION_HEADER), mDpHiiHandle,\r
571 (StringPtr == NULL) ? StringPtrUnknown : StringPtr);\r
572 FreePool (StringPtr);\r
573 FreePool (StringPtrUnknown);\r
574\r
575 Status = gBS->LocateHandleBuffer (AllHandles, NULL, NULL, &HandleCount, &HandleBuffer);\r
576 if (EFI_ERROR (Status)) {\r
577 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_HANDLES_ERROR), mDpHiiHandle, Status);\r
578 }\r
579 else {\r
580#if DP_DEBUG == 2\r
581 Print (L"There are %,d Handles defined.\n", (Size / sizeof(HandleBuffer[0])));\r
582#endif\r
583\r
584 if (mShowId) {\r
585 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_HANDLE_SECTION2), mDpHiiHandle);\r
586 } else {\r
587 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_HANDLE_SECTION), mDpHiiHandle);\r
588 }\r
589 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_DASHES), mDpHiiHandle);\r
590\r
591 LogEntryKey = 0;\r
592 Count = 0;\r
593 while ((LogEntryKey = GetPerformanceMeasurementRecord (\r
594 LogEntryKey,\r
595 &Measurement.Handle,\r
596 &Measurement.Token,\r
597 &Measurement.Module,\r
598 &Measurement.StartTimeStamp,\r
599 &Measurement.EndTimeStamp,\r
600 &Measurement.Identifier)) != 0)\r
601 {\r
602 Count++;\r
603 Duration = GetDuration (&Measurement);\r
604 ElapsedTime = DurationInMicroSeconds ( Duration );\r
605 if ((ElapsedTime < mInterestThreshold) ||\r
606 (Measurement.EndTimeStamp == 0) ||\r
607 (!IsCorePerf (&Measurement)) ||\r
608 ((ExcludeFlag) && (GetCumulativeItem(&Measurement) >= 0))\r
609 ) { // Ignore "uninteresting" or excluded records\r
610 continue;\r
611 }\r
612 mGaugeString[0] = 0; // Empty driver name by default\r
613 AsciiStrToUnicodeStrS (Measurement.Token, mUnicodeToken, ARRAY_SIZE (mUnicodeToken));\r
614 // See if the Handle is in the HandleBuffer\r
615 for (Index = 0; Index < HandleCount; Index++) {\r
616 if (Measurement.Handle == HandleBuffer[Index]) {\r
617 DpGetNameFromHandle (HandleBuffer[Index]); // Name is put into mGaugeString\r
618 break;\r
619 }\r
620 }\r
621 // Ensure that the argument strings are not too long.\r
622 mGaugeString[DP_GAUGE_STRING_LENGTH] = 0;\r
623 mUnicodeToken[11] = 0;\r
624 if (mGaugeString[0] != 0) {\r
625 // Display the record if it has a valid handle.\r
626 if (mShowId) {\r
627 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_HANDLE_VARS2), mDpHiiHandle,\r
628 Count, // 1 based, Which measurement record is being printed\r
629 Index + 1, // 1 based, Which handle is being printed\r
630 mGaugeString,\r
631 mUnicodeToken,\r
632 ElapsedTime,\r
633 Measurement.Identifier\r
634 );\r
635 } else {\r
636 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_HANDLE_VARS), mDpHiiHandle,\r
637 Count, // 1 based, Which measurement record is being printed\r
638 Index + 1, // 1 based, Which handle is being printed\r
639 mGaugeString,\r
640 mUnicodeToken,\r
641 ElapsedTime\r
642 );\r
643 }\r
644 }\r
645 if (ShellGetExecutionBreakFlag ()) {\r
646 Status = EFI_ABORTED;\r
647 break;\r
648 }\r
649 }\r
650 }\r
651 if (HandleBuffer != NULL) {\r
652 FreePool (HandleBuffer);\r
653 }\r
654 return Status;\r
655}\r
656\r
657/**\r
658 Gather and print PEIM data.\r
659\r
660 Only prints complete PEIM records\r
661\r
662 @retval EFI_SUCCESS The operation was successful.\r
663 @retval EFI_ABORTED The user aborts the operation.\r
664**/\r
665EFI_STATUS\r
666ProcessPeims(\r
667 VOID\r
668)\r
669{\r
670 MEASUREMENT_RECORD Measurement;\r
671 UINT64 Duration;\r
672 UINT64 ElapsedTime;\r
673 EFI_STRING StringPtr;\r
674 UINTN LogEntryKey;\r
675 UINTN TIndex;\r
676 EFI_STRING StringPtrUnknown;\r
677 EFI_STATUS Status;\r
678\r
679 Status = EFI_SUCCESS;\r
680\r
681 StringPtrUnknown = HiiGetString (mDpHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL);\r
682 StringPtr = HiiGetString (mDpHiiHandle, STRING_TOKEN (STR_DP_SECTION_PEIMS), NULL);\r
683 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_SECTION_HEADER), mDpHiiHandle,\r
684 (StringPtr == NULL) ? StringPtrUnknown : StringPtr);\r
685 FreePool (StringPtr);\r
686 FreePool (StringPtrUnknown);\r
687\r
688 if (mShowId) {\r
689 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_PEIM_SECTION2), mDpHiiHandle);\r
690 } else {\r
691 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_PEIM_SECTION), mDpHiiHandle);\r
692 }\r
693 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_DASHES), mDpHiiHandle);\r
694 TIndex = 0;\r
695 LogEntryKey = 0;\r
696 while ((LogEntryKey = GetPerformanceMeasurementRecord (\r
697 LogEntryKey,\r
698 &Measurement.Handle,\r
699 &Measurement.Token,\r
700 &Measurement.Module,\r
701 &Measurement.StartTimeStamp,\r
702 &Measurement.EndTimeStamp,\r
703 &Measurement.Identifier)) != 0)\r
704 {\r
705 TIndex++;\r
706 if ((Measurement.EndTimeStamp == 0) ||\r
707 (AsciiStrCmp (Measurement.Token, ALit_PEIM) != 0)\r
708 ) {\r
709 continue;\r
710 }\r
711\r
712 Duration = GetDuration (&Measurement);\r
713 ElapsedTime = DurationInMicroSeconds ( Duration ); // Calculate elapsed time in microseconds\r
714 if (ElapsedTime >= mInterestThreshold) {\r
715 // PEIM FILE Handle is the start address of its FFS file that contains its file guid.\r
716 if (mShowId) {\r
717 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_PEIM_VARS2), mDpHiiHandle,\r
718 TIndex, // 1 based, Which measurement record is being printed\r
719 Measurement.Handle, // file guid\r
720 ElapsedTime,\r
721 Measurement.Identifier\r
722 );\r
723 } else {\r
724 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_PEIM_VARS), mDpHiiHandle,\r
725 TIndex, // 1 based, Which measurement record is being printed\r
726 Measurement.Handle, // file guid\r
727 ElapsedTime\r
728 );\r
729 }\r
730 }\r
731 if (ShellGetExecutionBreakFlag ()) {\r
732 Status = EFI_ABORTED;\r
733 break;\r
734 }\r
735 }\r
736 return Status;\r
737}\r
738\r
739/**\r
740 Gather and print global data.\r
741\r
742 Strips out incomplete or "Execution Phase" records\r
743 Only prints records where Handle is NULL\r
744 Increment TIndex for every record, even skipped ones, so that we have an\r
745 indication of every measurement record taken.\r
746\r
747 @retval EFI_SUCCESS The operation was successful.\r
748 @retval EFI_ABORTED The user aborts the operation.\r
749**/\r
750EFI_STATUS\r
751ProcessGlobal(\r
752 VOID\r
753)\r
754{\r
755 MEASUREMENT_RECORD Measurement;\r
756 UINT64 Duration;\r
757 UINT64 ElapsedTime;\r
758 EFI_STRING StringPtr;\r
759 UINTN LogEntryKey;\r
760 UINTN Index; // Index, or number, of the measurement record being processed\r
761 EFI_STRING StringPtrUnknown;\r
762 EFI_STATUS Status;\r
763\r
764 Status = EFI_SUCCESS;\r
765\r
766 StringPtrUnknown = HiiGetString (mDpHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL);\r
767 StringPtr = HiiGetString (mDpHiiHandle, STRING_TOKEN (STR_DP_SECTION_GENERAL), NULL);\r
768 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_SECTION_HEADER), mDpHiiHandle,\r
769 (StringPtr == NULL) ? StringPtrUnknown: StringPtr);\r
770 FreePool (StringPtr);\r
771 FreePool (StringPtrUnknown);\r
772\r
773 if (mShowId) {\r
774 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_GLOBAL_SECTION2), mDpHiiHandle);\r
775 } else {\r
776 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_GLOBAL_SECTION), mDpHiiHandle);\r
777 }\r
778 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_DASHES), mDpHiiHandle);\r
779\r
780 Index = 1;\r
781 LogEntryKey = 0;\r
782\r
783 while ((LogEntryKey = GetPerformanceMeasurementRecord (\r
784 LogEntryKey,\r
785 &Measurement.Handle,\r
786 &Measurement.Token,\r
787 &Measurement.Module,\r
788 &Measurement.StartTimeStamp,\r
789 &Measurement.EndTimeStamp,\r
790 &Measurement.Identifier)) != 0)\r
791 {\r
792 AsciiStrToUnicodeStrS (Measurement.Module, mGaugeString, ARRAY_SIZE (mGaugeString));\r
793 AsciiStrToUnicodeStrS (Measurement.Token, mUnicodeToken, ARRAY_SIZE (mUnicodeToken));\r
794 mGaugeString[25] = 0;\r
795 mUnicodeToken[31] = 0;\r
796 if ( ! ( IsPhase( &Measurement) ||\r
797 IsCorePerf (&Measurement) ||\r
798 (Measurement.EndTimeStamp == 0)\r
799 ))\r
800 {\r
801 Duration = GetDuration (&Measurement);\r
802 ElapsedTime = DurationInMicroSeconds ( Duration );\r
803 if (ElapsedTime >= mInterestThreshold) {\r
804 if (mShowId) {\r
805 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_GLOBAL_VARS2), mDpHiiHandle,\r
806 Index,\r
807 mGaugeString,\r
808 mUnicodeToken,\r
809 ElapsedTime,\r
810 Measurement.Identifier\r
811 );\r
812 } else {\r
813 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_GLOBAL_VARS), mDpHiiHandle,\r
814 Index,\r
815 mGaugeString,\r
816 mUnicodeToken,\r
817 ElapsedTime\r
818 );\r
819 }\r
820 }\r
821 }\r
822 if (ShellGetExecutionBreakFlag ()) {\r
823 Status = EFI_ABORTED;\r
824 break;\r
825 }\r
826 Index++;\r
827 }\r
828 return Status;\r
829}\r
830\r
831/**\r
832 Gather and print cumulative data.\r
833\r
834 Traverse the measurement records and:<BR>\r
835 For each record with a Token listed in the CumData array:<BR>\r
836 - Update the instance count and the total, minimum, and maximum durations.\r
837 Finally, print the gathered cumulative statistics.\r
838\r
839 @param[in] CustomCumulativeData A pointer to the cumtom cumulative data.\r
840\r
841**/\r
842VOID\r
843ProcessCumulative(\r
844 IN PERF_CUM_DATA *CustomCumulativeData OPTIONAL\r
845 )\r
846{\r
847 UINT64 AvgDur; // the computed average duration\r
848 UINT64 Dur;\r
849 UINT64 MinDur;\r
850 UINT64 MaxDur;\r
851 EFI_STRING StringPtr;\r
852 UINTN TIndex;\r
853 EFI_STRING StringPtrUnknown;\r
854\r
855 StringPtrUnknown = HiiGetString (mDpHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL);\r
856 StringPtr = HiiGetString (mDpHiiHandle, STRING_TOKEN (STR_DP_SECTION_CUMULATIVE), NULL);\r
857 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_SECTION_HEADER), mDpHiiHandle,\r
858 (StringPtr == NULL) ? StringPtrUnknown: StringPtr);\r
859 FreePool (StringPtr);\r
860 FreePool (StringPtrUnknown);\r
861\r
862 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_CUMULATIVE_SECT_1), mDpHiiHandle);\r
863 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_CUMULATIVE_SECT_2), mDpHiiHandle);\r
864 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_DASHES), mDpHiiHandle);\r
865\r
866 for ( TIndex = 0; TIndex < NumCum; ++TIndex) {\r
867 if (CumData[TIndex].Count != 0) {\r
868 AvgDur = DivU64x32 (CumData[TIndex].Duration, CumData[TIndex].Count);\r
869 AvgDur = DurationInMicroSeconds(AvgDur);\r
870 Dur = DurationInMicroSeconds(CumData[TIndex].Duration);\r
871 MaxDur = DurationInMicroSeconds(CumData[TIndex].MaxDur);\r
872 MinDur = DurationInMicroSeconds(CumData[TIndex].MinDur);\r
873\r
874 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_CUMULATIVE_STATS), mDpHiiHandle,\r
875 CumData[TIndex].Name,\r
876 CumData[TIndex].Count,\r
877 Dur,\r
878 AvgDur,\r
879 MinDur,\r
880 MaxDur\r
881 );\r
882 }\r
883 }\r
884\r
885 //\r
886 // Print the custom cumulative data.\r
887 //\r
888 if (CustomCumulativeData != NULL) {\r
889 if (CustomCumulativeData->Count != 0) {\r
890 AvgDur = DivU64x32 (CustomCumulativeData->Duration, CustomCumulativeData->Count);\r
891 AvgDur = DurationInMicroSeconds (AvgDur);\r
892 Dur = DurationInMicroSeconds (CustomCumulativeData->Duration);\r
893 MaxDur = DurationInMicroSeconds (CustomCumulativeData->MaxDur);\r
894 MinDur = DurationInMicroSeconds (CustomCumulativeData->MinDur);\r
895 } else {\r
896 AvgDur = 0;\r
897 Dur = 0;\r
898 MaxDur = 0;\r
899 MinDur = 0;\r
900 }\r
901 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_CUMULATIVE_STATS), mDpHiiHandle,\r
902 CustomCumulativeData->Name,\r
903 CustomCumulativeData->Count,\r
904 Dur,\r
905 AvgDur,\r
906 MinDur,\r
907 MaxDur\r
908 );\r
909 }\r
910}\r