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