]> git.proxmox.com Git - mirror_edk2.git/blob - ShellPkg/DynamicCommand/DpDynamicCommand/DpTrace.c
9c0a9a06a1c985e918c3992f7d77915f79120dea
[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 Reset End if it's valid
552 //
553 if (SecTime > mResetEnd) {
554 SecTime = SecTime - mResetEnd; // Calculate sec time duration start from the beginning of firmware image execution
555 ElapsedTime = DurationInMicroSeconds (mResetEnd); // Calculate elapsed time in microseconds
556 Total += DivU64x32 (ElapsedTime, 1000); // Accumulate time in milliseconds
557 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_RESET_END), mDpHiiHandle, ElapsedTime);
558 }
559
560 // print SEC phase duration time
561 //
562 if (SecTime > 0) {
563 ElapsedTime = DurationInMicroSeconds (SecTime); // Calculate elapsed time in microseconds
564 Total += DivU64x32 (ElapsedTime, 1000); // Accumulate time in milliseconds
565 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_SEC_PHASE), mDpHiiHandle, ElapsedTime);
566 }
567
568 // print PEI phase duration time
569 //
570 if (PeiTime > 0) {
571 ElapsedTime = DivU64x32 (PeiTime, 1000000);
572 Total += ElapsedTime;
573 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_PHASE_DURATION), mDpHiiHandle, ALit_PEI, ElapsedTime);
574 }
575
576 // print DXE phase duration time
577 //
578 if (DxeTime > 0) {
579 ElapsedTime = DivU64x32 (DxeTime, 1000000);
580 Total += ElapsedTime;
581 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_PHASE_DURATION), mDpHiiHandle, ALit_DXE, ElapsedTime);
582 }
583
584 // print BDS phase duration time
585 //
586 if (BdsTime > 0) {
587 ElapsedTime = DivU64x32 (BdsTime, 1000000);
588 Total += ElapsedTime;
589 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_PHASE_DURATION), mDpHiiHandle, ALit_BDS, ElapsedTime);
590 }
591
592 if (BdsTimeoutValue > 0) {
593 ElapsedTime = DivU64x32 (BdsTimeoutValue, 1000000);
594 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_PHASE_BDSTO), mDpHiiHandle, ALit_BdsTO, ElapsedTime);
595 }
596
597 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_TOTAL_DURATION), mDpHiiHandle, Total);
598 }
599
600 /**
601 Gather and print Handle data.
602
603 @param[in] ExcludeFlag TRUE to exclude individual Cumulative items from display.
604
605 @retval EFI_SUCCESS The operation was successful.
606 @retval EFI_ABORTED The user aborts the operation.
607 @return Others from a call to gBS->LocateHandleBuffer().
608 **/
609 EFI_STATUS
610 ProcessHandles (
611 IN BOOLEAN ExcludeFlag
612 )
613 {
614 MEASUREMENT_RECORD Measurement;
615 UINT64 ElapsedTime;
616 UINT64 Duration;
617 EFI_HANDLE *HandleBuffer;
618 EFI_STRING StringPtr;
619 UINTN Index;
620 UINTN LogEntryKey;
621 UINTN Count;
622 UINTN HandleCount;
623 EFI_STATUS Status;
624 EFI_STRING StringPtrUnknown;
625
626 StringPtrUnknown = HiiGetString (mDpHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL);
627 StringPtr = HiiGetString (mDpHiiHandle, STRING_TOKEN (STR_DP_SECTION_DRIVERS), NULL);
628 ShellPrintHiiEx (
629 -1,
630 -1,
631 NULL,
632 STRING_TOKEN (STR_DP_SECTION_HEADER),
633 mDpHiiHandle,
634 (StringPtr == NULL) ? StringPtrUnknown : StringPtr
635 );
636 FreePool (StringPtr);
637 FreePool (StringPtrUnknown);
638
639 Status = gBS->LocateHandleBuffer (AllHandles, NULL, NULL, &HandleCount, &HandleBuffer);
640 if (EFI_ERROR (Status)) {
641 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_HANDLES_ERROR), mDpHiiHandle, Status);
642 } else {
643 #if DP_DEBUG == 2
644 Print (L"There are %,d Handles defined.\n", (Size / sizeof (HandleBuffer[0])));
645 #endif
646
647 if (mShowId) {
648 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_HANDLE_SECTION2), mDpHiiHandle);
649 } else {
650 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_HANDLE_SECTION), mDpHiiHandle);
651 }
652
653 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_DASHES), mDpHiiHandle);
654
655 LogEntryKey = 0;
656 Count = 0;
657 while ((LogEntryKey = GetPerformanceMeasurementRecord (
658 LogEntryKey,
659 &Measurement.Handle,
660 &Measurement.Token,
661 &Measurement.Module,
662 &Measurement.StartTimeStamp,
663 &Measurement.EndTimeStamp,
664 &Measurement.Identifier
665 )) != 0)
666 {
667 Count++;
668 Duration = GetDuration (&Measurement);
669 ElapsedTime = DurationInMicroSeconds (Duration);
670 if ((ElapsedTime < mInterestThreshold) ||
671 (Measurement.EndTimeStamp == 0) ||
672 (!IsCorePerf (&Measurement)) ||
673 ((ExcludeFlag) && (GetCumulativeItem (&Measurement) >= 0))
674 ) // Ignore "uninteresting" or excluded records
675 {
676 continue;
677 }
678
679 mGaugeString[0] = 0; // Empty driver name by default
680 AsciiStrToUnicodeStrS (Measurement.Token, mUnicodeToken, ARRAY_SIZE (mUnicodeToken));
681 // See if the Handle is in the HandleBuffer
682 for (Index = 0; Index < HandleCount; Index++) {
683 if (Measurement.Handle == HandleBuffer[Index]) {
684 DpGetNameFromHandle (HandleBuffer[Index]); // Name is put into mGaugeString
685 break;
686 }
687 }
688
689 // Ensure that the argument strings are not too long.
690 mGaugeString[DP_GAUGE_STRING_LENGTH] = 0;
691 mUnicodeToken[11] = 0;
692 if (mGaugeString[0] != 0) {
693 // Display the record if it has a valid handle.
694 if (mShowId) {
695 ShellPrintHiiEx (
696 -1,
697 -1,
698 NULL,
699 STRING_TOKEN (STR_DP_HANDLE_VARS2),
700 mDpHiiHandle,
701 Count, // 1 based, Which measurement record is being printed
702 Index + 1, // 1 based, Which handle is being printed
703 mGaugeString,
704 mUnicodeToken,
705 ElapsedTime,
706 Measurement.Identifier
707 );
708 } else {
709 ShellPrintHiiEx (
710 -1,
711 -1,
712 NULL,
713 STRING_TOKEN (STR_DP_HANDLE_VARS),
714 mDpHiiHandle,
715 Count, // 1 based, Which measurement record is being printed
716 Index + 1, // 1 based, Which handle is being printed
717 mGaugeString,
718 mUnicodeToken,
719 ElapsedTime
720 );
721 }
722 }
723
724 if (ShellGetExecutionBreakFlag ()) {
725 Status = EFI_ABORTED;
726 break;
727 }
728 }
729 }
730
731 if (HandleBuffer != NULL) {
732 FreePool (HandleBuffer);
733 }
734
735 return Status;
736 }
737
738 /**
739 Gather and print PEIM data.
740
741 Only prints complete PEIM records
742
743 @retval EFI_SUCCESS The operation was successful.
744 @retval EFI_ABORTED The user aborts the operation.
745 **/
746 EFI_STATUS
747 ProcessPeims (
748 VOID
749 )
750 {
751 MEASUREMENT_RECORD Measurement;
752 UINT64 Duration;
753 UINT64 ElapsedTime;
754 EFI_STRING StringPtr;
755 UINTN LogEntryKey;
756 UINTN TIndex;
757 EFI_STRING StringPtrUnknown;
758 EFI_STATUS Status;
759
760 Status = EFI_SUCCESS;
761
762 StringPtrUnknown = HiiGetString (mDpHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL);
763 StringPtr = HiiGetString (mDpHiiHandle, STRING_TOKEN (STR_DP_SECTION_PEIMS), NULL);
764 ShellPrintHiiEx (
765 -1,
766 -1,
767 NULL,
768 STRING_TOKEN (STR_DP_SECTION_HEADER),
769 mDpHiiHandle,
770 (StringPtr == NULL) ? StringPtrUnknown : StringPtr
771 );
772 FreePool (StringPtr);
773 FreePool (StringPtrUnknown);
774
775 if (mShowId) {
776 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_PEIM_SECTION2), mDpHiiHandle);
777 } else {
778 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_PEIM_SECTION), mDpHiiHandle);
779 }
780
781 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_DASHES), mDpHiiHandle);
782 TIndex = 0;
783 LogEntryKey = 0;
784 while ((LogEntryKey = GetPerformanceMeasurementRecord (
785 LogEntryKey,
786 &Measurement.Handle,
787 &Measurement.Token,
788 &Measurement.Module,
789 &Measurement.StartTimeStamp,
790 &Measurement.EndTimeStamp,
791 &Measurement.Identifier
792 )) != 0)
793 {
794 TIndex++;
795 if ((Measurement.EndTimeStamp == 0) ||
796 (AsciiStrCmp (Measurement.Token, ALit_PEIM) != 0)
797 )
798 {
799 continue;
800 }
801
802 Duration = GetDuration (&Measurement);
803 ElapsedTime = DurationInMicroSeconds (Duration); // Calculate elapsed time in microseconds
804 if (ElapsedTime >= mInterestThreshold) {
805 // PEIM FILE Handle is the start address of its FFS file that contains its file guid.
806 if (mShowId) {
807 ShellPrintHiiEx (
808 -1,
809 -1,
810 NULL,
811 STRING_TOKEN (STR_DP_PEIM_VARS2),
812 mDpHiiHandle,
813 TIndex, // 1 based, Which measurement record is being printed
814 Measurement.Handle, // file guid
815 ElapsedTime,
816 Measurement.Identifier
817 );
818 } else {
819 ShellPrintHiiEx (
820 -1,
821 -1,
822 NULL,
823 STRING_TOKEN (STR_DP_PEIM_VARS),
824 mDpHiiHandle,
825 TIndex, // 1 based, Which measurement record is being printed
826 Measurement.Handle, // file guid
827 ElapsedTime
828 );
829 }
830 }
831
832 if (ShellGetExecutionBreakFlag ()) {
833 Status = EFI_ABORTED;
834 break;
835 }
836 }
837
838 return Status;
839 }
840
841 /**
842 Gather and print global data.
843
844 Strips out incomplete or "Execution Phase" records
845 Only prints records where Handle is NULL
846 Increment TIndex for every record, even skipped ones, so that we have an
847 indication of every measurement record taken.
848
849 @retval EFI_SUCCESS The operation was successful.
850 @retval EFI_ABORTED The user aborts the operation.
851 **/
852 EFI_STATUS
853 ProcessGlobal (
854 VOID
855 )
856 {
857 MEASUREMENT_RECORD Measurement;
858 UINT64 Duration;
859 UINT64 ElapsedTime;
860 EFI_STRING StringPtr;
861 UINTN LogEntryKey;
862 UINTN Index; // Index, or number, of the measurement record being processed
863 EFI_STRING StringPtrUnknown;
864 EFI_STATUS Status;
865
866 Status = EFI_SUCCESS;
867
868 StringPtrUnknown = HiiGetString (mDpHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL);
869 StringPtr = HiiGetString (mDpHiiHandle, STRING_TOKEN (STR_DP_SECTION_GENERAL), NULL);
870 ShellPrintHiiEx (
871 -1,
872 -1,
873 NULL,
874 STRING_TOKEN (STR_DP_SECTION_HEADER),
875 mDpHiiHandle,
876 (StringPtr == NULL) ? StringPtrUnknown : StringPtr
877 );
878 FreePool (StringPtr);
879 FreePool (StringPtrUnknown);
880
881 if (mShowId) {
882 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_GLOBAL_SECTION2), mDpHiiHandle);
883 } else {
884 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_GLOBAL_SECTION), mDpHiiHandle);
885 }
886
887 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_DASHES), mDpHiiHandle);
888
889 Index = 1;
890 LogEntryKey = 0;
891
892 while ((LogEntryKey = GetPerformanceMeasurementRecord (
893 LogEntryKey,
894 &Measurement.Handle,
895 &Measurement.Token,
896 &Measurement.Module,
897 &Measurement.StartTimeStamp,
898 &Measurement.EndTimeStamp,
899 &Measurement.Identifier
900 )) != 0)
901 {
902 AsciiStrToUnicodeStrS (Measurement.Module, mGaugeString, ARRAY_SIZE (mGaugeString));
903 AsciiStrToUnicodeStrS (Measurement.Token, mUnicodeToken, ARRAY_SIZE (mUnicodeToken));
904 mGaugeString[25] = 0;
905 mUnicodeToken[31] = 0;
906 if ( !(IsPhase (&Measurement) ||
907 IsCorePerf (&Measurement) ||
908 (Measurement.EndTimeStamp == 0)
909 ))
910 {
911 Duration = GetDuration (&Measurement);
912 ElapsedTime = DurationInMicroSeconds (Duration);
913 if (ElapsedTime >= mInterestThreshold) {
914 if (mShowId) {
915 ShellPrintHiiEx (
916 -1,
917 -1,
918 NULL,
919 STRING_TOKEN (STR_DP_GLOBAL_VARS2),
920 mDpHiiHandle,
921 Index,
922 mGaugeString,
923 mUnicodeToken,
924 ElapsedTime,
925 Measurement.Identifier
926 );
927 } else {
928 ShellPrintHiiEx (
929 -1,
930 -1,
931 NULL,
932 STRING_TOKEN (STR_DP_GLOBAL_VARS),
933 mDpHiiHandle,
934 Index,
935 mGaugeString,
936 mUnicodeToken,
937 ElapsedTime
938 );
939 }
940 }
941 }
942
943 if (ShellGetExecutionBreakFlag ()) {
944 Status = EFI_ABORTED;
945 break;
946 }
947
948 Index++;
949 }
950
951 return Status;
952 }
953
954 /**
955 Gather and print cumulative data.
956
957 Traverse the measurement records and:<BR>
958 For each record with a Token listed in the CumData array:<BR>
959 - Update the instance count and the total, minimum, and maximum durations.
960 Finally, print the gathered cumulative statistics.
961
962 @param[in] CustomCumulativeData A pointer to the custom cumulative data.
963
964 **/
965 VOID
966 ProcessCumulative (
967 IN PERF_CUM_DATA *CustomCumulativeData OPTIONAL
968 )
969 {
970 UINT64 AvgDur; // the computed average duration
971 UINT64 Dur;
972 UINT64 MinDur;
973 UINT64 MaxDur;
974 EFI_STRING StringPtr;
975 UINTN TIndex;
976 EFI_STRING StringPtrUnknown;
977
978 StringPtrUnknown = HiiGetString (mDpHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL);
979 StringPtr = HiiGetString (mDpHiiHandle, STRING_TOKEN (STR_DP_SECTION_CUMULATIVE), NULL);
980 ShellPrintHiiEx (
981 -1,
982 -1,
983 NULL,
984 STRING_TOKEN (STR_DP_SECTION_HEADER),
985 mDpHiiHandle,
986 (StringPtr == NULL) ? StringPtrUnknown : StringPtr
987 );
988 FreePool (StringPtr);
989 FreePool (StringPtrUnknown);
990
991 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_CUMULATIVE_SECT_1), mDpHiiHandle);
992 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_CUMULATIVE_SECT_2), mDpHiiHandle);
993 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_DASHES), mDpHiiHandle);
994
995 for ( TIndex = 0; TIndex < NumCum; ++TIndex) {
996 if (CumData[TIndex].Count != 0) {
997 AvgDur = DivU64x32 (CumData[TIndex].Duration, CumData[TIndex].Count);
998 AvgDur = DurationInMicroSeconds (AvgDur);
999 Dur = DurationInMicroSeconds (CumData[TIndex].Duration);
1000 MaxDur = DurationInMicroSeconds (CumData[TIndex].MaxDur);
1001 MinDur = DurationInMicroSeconds (CumData[TIndex].MinDur);
1002
1003 ShellPrintHiiEx (
1004 -1,
1005 -1,
1006 NULL,
1007 STRING_TOKEN (STR_DP_CUMULATIVE_STATS),
1008 mDpHiiHandle,
1009 CumData[TIndex].Name,
1010 CumData[TIndex].Count,
1011 Dur,
1012 AvgDur,
1013 MinDur,
1014 MaxDur
1015 );
1016 }
1017 }
1018
1019 //
1020 // Print the custom cumulative data.
1021 //
1022 if (CustomCumulativeData != NULL) {
1023 if (CustomCumulativeData->Count != 0) {
1024 AvgDur = DivU64x32 (CustomCumulativeData->Duration, CustomCumulativeData->Count);
1025 AvgDur = DurationInMicroSeconds (AvgDur);
1026 Dur = DurationInMicroSeconds (CustomCumulativeData->Duration);
1027 MaxDur = DurationInMicroSeconds (CustomCumulativeData->MaxDur);
1028 MinDur = DurationInMicroSeconds (CustomCumulativeData->MinDur);
1029 } else {
1030 AvgDur = 0;
1031 Dur = 0;
1032 MaxDur = 0;
1033 MinDur = 0;
1034 }
1035
1036 ShellPrintHiiEx (
1037 -1,
1038 -1,
1039 NULL,
1040 STRING_TOKEN (STR_DP_CUMULATIVE_STATS),
1041 mDpHiiHandle,
1042 CustomCumulativeData->Name,
1043 CustomCumulativeData->Count,
1044 Dur,
1045 AvgDur,
1046 MinDur,
1047 MaxDur
1048 );
1049 }
1050 }