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