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