]> git.proxmox.com Git - mirror_edk2.git/blob - PerformancePkg/Dp_App/DpTrace.c
PerformancePkg/Dp_App: Refine the code of locating all handles in DpTrace.c.
[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-2016 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 HandleCount;
157 EFI_STATUS Status;
158 EFI_STRING StringPtrUnknown;
159
160 StringPtrUnknown = HiiGetString (gHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL);
161 IncFlag = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_SECTION_ALL), NULL);
162 PrintToken( STRING_TOKEN (STR_DP_SECTION_HEADER),
163 (IncFlag == NULL) ? StringPtrUnknown : IncFlag);
164 FreePool (StringPtrUnknown);
165
166 // Get Handle information
167 //
168 Status = gBS->LocateHandleBuffer (AllHandles, NULL, NULL, &HandleCount, &HandleBuffer);
169 if (EFI_ERROR (Status)) {
170 PrintToken (STRING_TOKEN (STR_DP_HANDLES_ERROR), Status);
171 }
172 else {
173 // We have successfully populated the HandleBuffer
174 // Display ALL Measurement Records
175 // Up to Limit lines displayed
176 // Display only records with Elapsed times >= mInterestThreshold
177 // Display driver names in Module field for records with Handles.
178 //
179 if (mShowId) {
180 PrintToken (STRING_TOKEN (STR_DP_ALL_HEADR2) );
181 PrintToken (STRING_TOKEN (STR_DP_ALL_DASHES2) );
182 } else {
183 PrintToken (STRING_TOKEN (STR_DP_ALL_HEADR) );
184 PrintToken (STRING_TOKEN (STR_DP_DASHES) );
185 }
186
187 LogEntryKey = 0;
188 Count = 0;
189 Index = 0;
190 while ( WITHIN_LIMIT(Count, Limit) &&
191 ((LogEntryKey = GetPerformanceMeasurementEx (
192 LogEntryKey,
193 &Measurement.Handle,
194 &Measurement.Token,
195 &Measurement.Module,
196 &Measurement.StartTimeStamp,
197 &Measurement.EndTimeStamp,
198 &Measurement.Identifier)) != 0)
199 )
200 {
201 ++Index; // Count every record. First record is 1.
202 ElapsedTime = 0;
203 SafeFreePool ((VOID *) IncFlag);
204 if (Measurement.EndTimeStamp != 0) {
205 Duration = GetDuration (&Measurement);
206 ElapsedTime = DurationInMicroSeconds ( Duration );
207 IncFlag = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_COMPLETE), NULL);
208 }
209 else {
210 IncFlag = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_INCOMPLETE), NULL); // Mark incomplete records
211 }
212 if (((Measurement.EndTimeStamp != 0) && (ElapsedTime < mInterestThreshold)) ||
213 ((ExcludeFlag) && (GetCumulativeItem(&Measurement) >= 0))
214 ) { // Ignore "uninteresting" or excluded records
215 continue;
216 }
217 ++Count; // Count the number of records printed
218
219 // If Handle is non-zero, see if we can determine a name for the driver
220 AsciiStrToUnicodeStr (Measurement.Module, mGaugeString); // Use Module by default
221 AsciiStrToUnicodeStr (Measurement.Token, mUnicodeToken);
222 if (Measurement.Handle != NULL) {
223 // See if the Handle is in the HandleBuffer
224 for (TIndex = 0; TIndex < HandleCount; TIndex++) {
225 if (Measurement.Handle == HandleBuffer[TIndex]) {
226 GetNameFromHandle (HandleBuffer[TIndex]);
227 break;
228 }
229 }
230 }
231
232 if (AsciiStrnCmp (Measurement.Token, ALit_PEIM, PERF_TOKEN_LENGTH) == 0) {
233 UnicodeSPrint (mGaugeString, sizeof (mGaugeString), L"%g", Measurement.Handle);
234 }
235
236 // Ensure that the argument strings are not too long.
237 mGaugeString[DP_GAUGE_STRING_LENGTH] = 0;
238 mUnicodeToken[13] = 0;
239
240 if (mShowId) {
241 PrintToken( STRING_TOKEN (STR_DP_ALL_VARS2),
242 Index, // 1 based, Which measurement record is being printed
243 IncFlag,
244 Measurement.Handle,
245 mGaugeString,
246 mUnicodeToken,
247 ElapsedTime,
248 Measurement.Identifier
249 );
250 } else {
251 PrintToken( STRING_TOKEN (STR_DP_ALL_VARS),
252 Index, // 1 based, Which measurement record is being printed
253 IncFlag,
254 Measurement.Handle,
255 mGaugeString,
256 mUnicodeToken,
257 ElapsedTime
258 );
259 }
260 }
261 }
262 if (HandleBuffer != NULL) {
263 FreePool (HandleBuffer);
264 }
265 SafeFreePool ((VOID *) IncFlag);
266 }
267
268 /**
269 Gather and print Raw Trace Records.
270
271 All Trace measurements with a duration greater than or equal to
272 mInterestThreshold are printed without interpretation.
273
274 The number of records displayed is controlled by:
275 - records with a duration less than mInterestThreshold microseconds are not displayed.
276 - No more than Limit records are displayed. A Limit of zero will not limit the output.
277 - If the ExcludeFlag is TRUE, records matching entries in the CumData array are not
278 displayed.
279
280 @pre The mInterestThreshold global variable is set to the shortest duration to be printed.
281
282 @param[in] Limit The number of records to print. Zero is ALL.
283 @param[in] ExcludeFlag TRUE to exclude individual Cumulative items from display.
284
285 **/
286 VOID
287 DumpRawTrace(
288 IN UINTN Limit,
289 IN BOOLEAN ExcludeFlag
290 )
291 {
292 MEASUREMENT_RECORD Measurement;
293 UINT64 ElapsedTime;
294 UINT64 Duration;
295 UINTN LogEntryKey;
296 UINTN Count;
297 UINTN Index;
298
299 EFI_STRING StringPtr;
300 EFI_STRING StringPtrUnknown;
301
302 StringPtrUnknown = HiiGetString (gHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL);
303 StringPtr = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_SECTION_RAWTRACE), NULL);
304 PrintToken( STRING_TOKEN (STR_DP_SECTION_HEADER),
305 (StringPtr == NULL) ? StringPtrUnknown : StringPtr);
306 FreePool (StringPtr);
307 FreePool (StringPtrUnknown);
308
309 if (mShowId) {
310 PrintToken (STRING_TOKEN (STR_DP_RAW_HEADR2) );
311 PrintToken (STRING_TOKEN (STR_DP_RAW_DASHES2) );
312 } else {
313 PrintToken (STRING_TOKEN (STR_DP_RAW_HEADR) );
314 PrintToken (STRING_TOKEN (STR_DP_RAW_DASHES) );
315 }
316
317 LogEntryKey = 0;
318 Count = 0;
319 Index = 0;
320 while ( WITHIN_LIMIT(Count, Limit) &&
321 ((LogEntryKey = GetPerformanceMeasurementEx (
322 LogEntryKey,
323 &Measurement.Handle,
324 &Measurement.Token,
325 &Measurement.Module,
326 &Measurement.StartTimeStamp,
327 &Measurement.EndTimeStamp,
328 &Measurement.Identifier)) != 0)
329 )
330 {
331 ++Index; // Count every record. First record is 1.
332 ElapsedTime = 0;
333 if (Measurement.EndTimeStamp != 0) {
334 Duration = GetDuration (&Measurement);
335 ElapsedTime = DurationInMicroSeconds ( Duration );
336 }
337 if ((ElapsedTime < mInterestThreshold) ||
338 ((ExcludeFlag) && (GetCumulativeItem(&Measurement) >= 0))
339 ) { // Ignore "uninteresting" or Excluded records
340 continue;
341 }
342 ++Count; // Count the number of records printed
343
344 if (mShowId) {
345 PrintToken (STRING_TOKEN (STR_DP_RAW_VARS2),
346 Index, // 1 based, Which measurement record is being printed
347 Measurement.Handle,
348 Measurement.StartTimeStamp,
349 Measurement.EndTimeStamp,
350 Measurement.Token,
351 Measurement.Module,
352 Measurement.Identifier
353 );
354 } else {
355 PrintToken (STRING_TOKEN (STR_DP_RAW_VARS),
356 Index, // 1 based, Which measurement record is being printed
357 Measurement.Handle,
358 Measurement.StartTimeStamp,
359 Measurement.EndTimeStamp,
360 Measurement.Token,
361 Measurement.Module
362 );
363 }
364 }
365 }
366
367 /**
368 Gather and print Major Phase metrics.
369
370 @param[in] Ticker The timer value for the END of Shell phase
371
372 **/
373 VOID
374 ProcessPhases(
375 IN UINT64 Ticker
376 )
377 {
378 MEASUREMENT_RECORD Measurement;
379 UINT64 BdsTimeoutValue;
380 UINT64 SecTime;
381 UINT64 PeiTime;
382 UINT64 DxeTime;
383 UINT64 BdsTime;
384 UINT64 ShellTime;
385 UINT64 ElapsedTime;
386 UINT64 Duration;
387 UINT64 Total;
388 EFI_STRING StringPtr;
389 UINTN LogEntryKey;
390 EFI_STRING StringPtrUnknown;
391
392 BdsTimeoutValue = 0;
393 SecTime = 0;
394 PeiTime = 0;
395 DxeTime = 0;
396 BdsTime = 0;
397 ShellTime = 0;
398 //
399 // Get Execution Phase Statistics
400 //
401 StringPtrUnknown = HiiGetString (gHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL);
402 StringPtr = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_SECTION_PHASES), NULL);
403 PrintToken( STRING_TOKEN (STR_DP_SECTION_HEADER),
404 (StringPtr == NULL) ? StringPtrUnknown : StringPtr);
405 FreePool (StringPtr);
406 FreePool (StringPtrUnknown);
407
408 LogEntryKey = 0;
409 while ((LogEntryKey = GetPerformanceMeasurementEx (
410 LogEntryKey,
411 &Measurement.Handle,
412 &Measurement.Token,
413 &Measurement.Module,
414 &Measurement.StartTimeStamp,
415 &Measurement.EndTimeStamp,
416 &Measurement.Identifier)) != 0)
417 {
418 if (AsciiStrnCmp (Measurement.Token, ALit_SHELL, PERF_TOKEN_LENGTH) == 0) {
419 Measurement.EndTimeStamp = Ticker;
420 }
421 if (Measurement.EndTimeStamp == 0) { // Skip "incomplete" records
422 continue;
423 }
424 Duration = GetDuration (&Measurement);
425 if ( Measurement.Handle != NULL
426 && (AsciiStrnCmp (Measurement.Token, ALit_BdsTO, PERF_TOKEN_LENGTH) == 0)
427 )
428 {
429 BdsTimeoutValue = Duration;
430 } else if (AsciiStrnCmp (Measurement.Token, ALit_SEC, PERF_TOKEN_LENGTH) == 0) {
431 SecTime = Duration;
432 } else if (AsciiStrnCmp (Measurement.Token, ALit_PEI, PERF_TOKEN_LENGTH) == 0) {
433 PeiTime = Duration;
434 } else if (AsciiStrnCmp (Measurement.Token, ALit_DXE, PERF_TOKEN_LENGTH) == 0) {
435 DxeTime = Duration;
436 } else if (AsciiStrnCmp (Measurement.Token, ALit_BDS, PERF_TOKEN_LENGTH) == 0) {
437 BdsTime = Duration;
438 } else if (AsciiStrnCmp (Measurement.Token, ALit_SHELL, PERF_TOKEN_LENGTH) == 0) {
439 ShellTime = Duration;
440 }
441 }
442
443 Total = 0;
444
445 // print SEC phase duration time
446 //
447 if (SecTime > 0) {
448 ElapsedTime = DurationInMicroSeconds ( SecTime ); // Calculate elapsed time in microseconds
449 Total += DivU64x32 (ElapsedTime, 1000); // Accumulate time in milliseconds
450 PrintToken (STRING_TOKEN (STR_DP_SEC_PHASE), ElapsedTime);
451 }
452
453 // print PEI phase duration time
454 //
455 if (PeiTime > 0) {
456 ElapsedTime = DivU64x32 (
457 PeiTime,
458 (UINT32)TimerInfo.Frequency
459 );
460 Total += ElapsedTime;
461 PrintToken (STRING_TOKEN (STR_DP_PHASE_DURATION), ALit_PEI, ElapsedTime);
462 }
463
464 // print DXE phase duration time
465 //
466 if (DxeTime > 0) {
467 ElapsedTime = DivU64x32 (
468 DxeTime,
469 (UINT32)TimerInfo.Frequency
470 );
471 Total += ElapsedTime;
472 PrintToken (STRING_TOKEN (STR_DP_PHASE_DURATION), ALit_DXE, ElapsedTime);
473 }
474
475 // print BDS phase duration time
476 //
477 if (BdsTime > 0) {
478 ElapsedTime = DivU64x32 (
479 BdsTime,
480 (UINT32)TimerInfo.Frequency
481 );
482 Total += ElapsedTime;
483 PrintToken (STRING_TOKEN (STR_DP_PHASE_DURATION), ALit_BDS, ElapsedTime);
484 }
485
486 if (BdsTimeoutValue > 0) {
487 ElapsedTime = DivU64x32 (
488 BdsTimeoutValue,
489 (UINT32)TimerInfo.Frequency
490 );
491 PrintToken (STRING_TOKEN (STR_DP_PHASE_BDSTO), ALit_BdsTO, ElapsedTime);
492 }
493
494 // print SHELL phase duration time
495 //
496 if (ShellTime > 0) {
497 ElapsedTime = DivU64x32 (
498 ShellTime,
499 (UINT32)TimerInfo.Frequency
500 );
501 Total += ElapsedTime;
502 PrintToken (STRING_TOKEN (STR_DP_PHASE_DURATION), ALit_SHELL, ElapsedTime);
503 }
504
505 PrintToken (STRING_TOKEN (STR_DP_TOTAL_DURATION), Total);
506 }
507
508 /**
509 Gather and print Handle data.
510
511 @param[in] ExcludeFlag TRUE to exclude individual Cumulative items from display.
512
513 @return Status from a call to gBS->LocateHandle().
514 **/
515 EFI_STATUS
516 ProcessHandles(
517 IN BOOLEAN ExcludeFlag
518 )
519 {
520 MEASUREMENT_RECORD Measurement;
521 UINT64 ElapsedTime;
522 UINT64 Duration;
523 EFI_HANDLE *HandleBuffer;
524 EFI_STRING StringPtr;
525 UINTN Index;
526 UINTN LogEntryKey;
527 UINTN Count;
528 UINTN HandleCount;
529 EFI_STATUS Status;
530 EFI_STRING StringPtrUnknown;
531
532 StringPtrUnknown = HiiGetString (gHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL);
533 StringPtr = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_SECTION_DRIVERS), NULL);
534 PrintToken( STRING_TOKEN (STR_DP_SECTION_HEADER),
535 (StringPtr == NULL) ? StringPtrUnknown : StringPtr);
536 FreePool (StringPtr);
537 FreePool (StringPtrUnknown);
538
539 Status = gBS->LocateHandleBuffer (AllHandles, NULL, NULL, &HandleCount, &HandleBuffer);
540 if (EFI_ERROR (Status)) {
541 PrintToken (STRING_TOKEN (STR_DP_HANDLES_ERROR), Status);
542 }
543 else {
544 #if DP_DEBUG == 2
545 Print (L"There are %,d Handles defined.\n", (Size / sizeof(HandleBuffer[0])));
546 #endif
547
548 if (mShowId) {
549 PrintToken (STRING_TOKEN (STR_DP_HANDLE_SECTION2) );
550 } else {
551 PrintToken (STRING_TOKEN (STR_DP_HANDLE_SECTION) );
552 }
553 PrintToken (STRING_TOKEN (STR_DP_DASHES) );
554
555 LogEntryKey = 0;
556 Count = 0;
557 while ((LogEntryKey = GetPerformanceMeasurementEx (
558 LogEntryKey,
559 &Measurement.Handle,
560 &Measurement.Token,
561 &Measurement.Module,
562 &Measurement.StartTimeStamp,
563 &Measurement.EndTimeStamp,
564 &Measurement.Identifier)) != 0)
565 {
566 Count++;
567 Duration = GetDuration (&Measurement);
568 ElapsedTime = DurationInMicroSeconds ( Duration );
569 if ((ElapsedTime < mInterestThreshold) ||
570 (Measurement.EndTimeStamp == 0) ||
571 (Measurement.Handle == NULL) ||
572 ((ExcludeFlag) && (GetCumulativeItem(&Measurement) >= 0))
573 ) { // Ignore "uninteresting" or excluded records
574 continue;
575 }
576 mGaugeString[0] = 0; // Empty driver name by default
577 AsciiStrToUnicodeStr (Measurement.Token, mUnicodeToken);
578 // See if the Handle is in the HandleBuffer
579 for (Index = 0; Index < HandleCount; Index++) {
580 if (Measurement.Handle == HandleBuffer[Index]) {
581 GetNameFromHandle (HandleBuffer[Index]); // Name is put into mGaugeString
582 break;
583 }
584 }
585 // Ensure that the argument strings are not too long.
586 mGaugeString[DP_GAUGE_STRING_LENGTH] = 0;
587 mUnicodeToken[11] = 0;
588 if (mGaugeString[0] != 0) {
589 // Display the record if it has a valid handle.
590 if (mShowId) {
591 PrintToken (
592 STRING_TOKEN (STR_DP_HANDLE_VARS2),
593 Count, // 1 based, Which measurement record is being printed
594 Index + 1, // 1 based, Which handle is being printed
595 mGaugeString,
596 mUnicodeToken,
597 ElapsedTime,
598 Measurement.Identifier
599 );
600 } else {
601 PrintToken (
602 STRING_TOKEN (STR_DP_HANDLE_VARS),
603 Count, // 1 based, Which measurement record is being printed
604 Index + 1, // 1 based, Which handle is being printed
605 mGaugeString,
606 mUnicodeToken,
607 ElapsedTime
608 );
609 }
610 }
611 }
612 }
613 if (HandleBuffer != NULL) {
614 FreePool (HandleBuffer);
615 }
616 return Status;
617 }
618
619 /**
620 Gather and print PEIM data.
621
622 Only prints complete PEIM records
623
624 **/
625 VOID
626 ProcessPeims(
627 VOID
628 )
629 {
630 MEASUREMENT_RECORD Measurement;
631 UINT64 Duration;
632 UINT64 ElapsedTime;
633 EFI_STRING StringPtr;
634 UINTN LogEntryKey;
635 UINTN TIndex;
636 EFI_STRING StringPtrUnknown;
637
638 StringPtrUnknown = HiiGetString (gHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL);
639 StringPtr = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_SECTION_PEIMS), NULL);
640 PrintToken( STRING_TOKEN (STR_DP_SECTION_HEADER),
641 (StringPtr == NULL) ? StringPtrUnknown : StringPtr);
642 FreePool (StringPtr);
643 FreePool (StringPtrUnknown);
644
645 if (mShowId) {
646 PrintToken (STRING_TOKEN (STR_DP_PEIM_SECTION2));
647 } else {
648 PrintToken (STRING_TOKEN (STR_DP_PEIM_SECTION));
649 }
650 PrintToken (STRING_TOKEN (STR_DP_DASHES));
651 TIndex = 0;
652 LogEntryKey = 0;
653 while ((LogEntryKey = GetPerformanceMeasurementEx (
654 LogEntryKey,
655 &Measurement.Handle,
656 &Measurement.Token,
657 &Measurement.Module,
658 &Measurement.StartTimeStamp,
659 &Measurement.EndTimeStamp,
660 &Measurement.Identifier)) != 0)
661 {
662 TIndex++;
663 if ((Measurement.EndTimeStamp == 0) ||
664 (AsciiStrnCmp (Measurement.Token, ALit_PEIM, PERF_TOKEN_LENGTH) != 0)
665 ) {
666 continue;
667 }
668
669 Duration = GetDuration (&Measurement);
670 ElapsedTime = DurationInMicroSeconds ( Duration ); // Calculate elapsed time in microseconds
671 if (ElapsedTime >= mInterestThreshold) {
672 // PEIM FILE Handle is the start address of its FFS file that contains its file guid.
673 if (mShowId) {
674 PrintToken (STRING_TOKEN (STR_DP_PEIM_VARS2),
675 TIndex, // 1 based, Which measurement record is being printed
676 Measurement.Handle, // base address
677 Measurement.Handle, // file guid
678 ElapsedTime,
679 Measurement.Identifier
680 );
681 } else {
682 PrintToken (STRING_TOKEN (STR_DP_PEIM_VARS),
683 TIndex, // 1 based, Which measurement record is being printed
684 Measurement.Handle, // base address
685 Measurement.Handle, // file guid
686 ElapsedTime
687 );
688 }
689 }
690 }
691 }
692
693 /**
694 Gather and print global data.
695
696 Strips out incomplete or "Execution Phase" records
697 Only prints records where Handle is NULL
698 Increment TIndex for every record, even skipped ones, so that we have an
699 indication of every measurement record taken.
700
701 **/
702 VOID
703 ProcessGlobal(
704 VOID
705 )
706 {
707 MEASUREMENT_RECORD Measurement;
708 UINT64 Duration;
709 UINT64 ElapsedTime;
710 EFI_STRING StringPtr;
711 UINTN LogEntryKey;
712 UINTN Index; // Index, or number, of the measurement record being processed
713 EFI_STRING StringPtrUnknown;
714
715 StringPtrUnknown = HiiGetString (gHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL);
716 StringPtr = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_SECTION_GENERAL), NULL);
717 PrintToken( STRING_TOKEN (STR_DP_SECTION_HEADER),
718 (StringPtr == NULL) ? StringPtrUnknown: StringPtr);
719 FreePool (StringPtr);
720 FreePool (StringPtrUnknown);
721
722 if (mShowId) {
723 PrintToken (STRING_TOKEN (STR_DP_GLOBAL_SECTION2));
724 } else {
725 PrintToken (STRING_TOKEN (STR_DP_GLOBAL_SECTION));
726 }
727 PrintToken (STRING_TOKEN (STR_DP_DASHES));
728
729 Index = 1;
730 LogEntryKey = 0;
731
732 while ((LogEntryKey = GetPerformanceMeasurementEx (
733 LogEntryKey,
734 &Measurement.Handle,
735 &Measurement.Token,
736 &Measurement.Module,
737 &Measurement.StartTimeStamp,
738 &Measurement.EndTimeStamp,
739 &Measurement.Identifier)) != 0)
740 {
741 AsciiStrToUnicodeStr (Measurement.Module, mGaugeString);
742 AsciiStrToUnicodeStr (Measurement.Token, mUnicodeToken);
743 mGaugeString[25] = 0;
744 mUnicodeToken[31] = 0;
745 if ( ! ( IsPhase( &Measurement) ||
746 (Measurement.Handle != NULL) ||
747 (Measurement.EndTimeStamp == 0)
748 ))
749 {
750 Duration = GetDuration (&Measurement);
751 ElapsedTime = DurationInMicroSeconds ( Duration );
752 if (ElapsedTime >= mInterestThreshold) {
753 if (mShowId) {
754 PrintToken (
755 STRING_TOKEN (STR_DP_GLOBAL_VARS2),
756 Index,
757 mGaugeString,
758 mUnicodeToken,
759 ElapsedTime,
760 Measurement.Identifier
761 );
762 } else {
763 PrintToken (
764 STRING_TOKEN (STR_DP_GLOBAL_VARS),
765 Index,
766 mGaugeString,
767 mUnicodeToken,
768 ElapsedTime
769 );
770 }
771 }
772 }
773 Index++;
774 }
775 }
776
777 /**
778 Gather and print cumulative data.
779
780 Traverse the measurement records and:<BR>
781 For each record with a Token listed in the CumData array:<BR>
782 - Update the instance count and the total, minimum, and maximum durations.
783 Finally, print the gathered cumulative statistics.
784
785 @param[in] CustomCumulativeData A pointer to the cumtom cumulative data.
786
787 **/
788 VOID
789 ProcessCumulative(
790 IN PERF_CUM_DATA *CustomCumulativeData OPTIONAL
791 )
792 {
793 UINT64 AvgDur; // the computed average duration
794 UINT64 Dur;
795 UINT64 MinDur;
796 UINT64 MaxDur;
797 EFI_STRING StringPtr;
798 UINTN TIndex;
799 EFI_STRING StringPtrUnknown;
800
801 StringPtrUnknown = HiiGetString (gHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL);
802 StringPtr = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_SECTION_CUMULATIVE), NULL);
803 PrintToken( STRING_TOKEN (STR_DP_SECTION_HEADER),
804 (StringPtr == NULL) ? StringPtrUnknown: StringPtr);
805 FreePool (StringPtr);
806 FreePool (StringPtrUnknown);
807
808 PrintToken (STRING_TOKEN (STR_DP_CUMULATIVE_SECT_1));
809 PrintToken (STRING_TOKEN (STR_DP_CUMULATIVE_SECT_2));
810 PrintToken (STRING_TOKEN (STR_DP_DASHES));
811
812 for ( TIndex = 0; TIndex < NumCum; ++TIndex) {
813 if (CumData[TIndex].Count != 0) {
814 AvgDur = DivU64x32 (CumData[TIndex].Duration, CumData[TIndex].Count);
815 AvgDur = DurationInMicroSeconds(AvgDur);
816 Dur = DurationInMicroSeconds(CumData[TIndex].Duration);
817 MaxDur = DurationInMicroSeconds(CumData[TIndex].MaxDur);
818 MinDur = DurationInMicroSeconds(CumData[TIndex].MinDur);
819
820 PrintToken (STRING_TOKEN (STR_DP_CUMULATIVE_STATS),
821 CumData[TIndex].Name,
822 CumData[TIndex].Count,
823 Dur,
824 AvgDur,
825 MinDur,
826 MaxDur
827 );
828 }
829 }
830
831 //
832 // Print the custom cumulative data.
833 //
834 if (CustomCumulativeData != NULL) {
835 if (CustomCumulativeData->Count != 0) {
836 AvgDur = DivU64x32 (CustomCumulativeData->Duration, CustomCumulativeData->Count);
837 AvgDur = DurationInMicroSeconds (AvgDur);
838 Dur = DurationInMicroSeconds (CustomCumulativeData->Duration);
839 MaxDur = DurationInMicroSeconds (CustomCumulativeData->MaxDur);
840 MinDur = DurationInMicroSeconds (CustomCumulativeData->MinDur);
841 } else {
842 AvgDur = 0;
843 Dur = 0;
844 MaxDur = 0;
845 MinDur = 0;
846 }
847 PrintToken (STRING_TOKEN (STR_DP_CUMULATIVE_STATS),
848 CustomCumulativeData->Name,
849 CustomCumulativeData->Count,
850 Dur,
851 AvgDur,
852 MinDur,
853 MaxDur
854 );
855 }
856 }