]> git.proxmox.com Git - mirror_edk2.git/blob - ShellPkg/Library/UefiDpLib/DpTrace.c
ShellPkg/UefiDpLib: Refine the code of locating all handles in DpTrace.c.
[mirror_edk2.git] / ShellPkg / Library / UefiDpLib / DpTrace.c
1 /** @file
2 Trace reporting for the Dp utility.
3
4 Copyright (c) 2009 - 2013, Intel Corporation. All rights reserved.
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 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 (gDpHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL);
161 IncFlag = HiiGetString (gDpHiiHandle, STRING_TOKEN (STR_DP_SECTION_ALL), NULL);
162 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_SECTION_HEADER), gDpHiiHandle,
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 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_HANDLES_ERROR), gDpHiiHandle, 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 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_ALL_HEADR2), gDpHiiHandle);
181 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_ALL_DASHES2), gDpHiiHandle);
182 } else {
183 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_ALL_HEADR), gDpHiiHandle);
184 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_DASHES), gDpHiiHandle);
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 SHELL_FREE_NON_NULL (IncFlag);
204 if (Measurement.EndTimeStamp != 0) {
205 Duration = GetDuration (&Measurement);
206 ElapsedTime = DurationInMicroSeconds ( Duration );
207 IncFlag = HiiGetString (gDpHiiHandle, STRING_TOKEN (STR_DP_COMPLETE), NULL);
208 }
209 else {
210 IncFlag = HiiGetString (gDpHiiHandle, 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 DpGetNameFromHandle (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 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_ALL_VARS2), gDpHiiHandle,
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 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_ALL_VARS), gDpHiiHandle,
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 SHELL_FREE_NON_NULL (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 (gDpHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL);
303 StringPtr = HiiGetString (gDpHiiHandle, STRING_TOKEN (STR_DP_SECTION_RAWTRACE), NULL);
304 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_SECTION_HEADER), gDpHiiHandle,
305 (StringPtr == NULL) ? StringPtrUnknown : StringPtr);
306 FreePool (StringPtr);
307 FreePool (StringPtrUnknown);
308
309 if (mShowId) {
310 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_RAW_HEADR2), gDpHiiHandle);
311 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_RAW_DASHES2), gDpHiiHandle);
312 } else {
313 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_RAW_HEADR), gDpHiiHandle);
314 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_RAW_DASHES), gDpHiiHandle);
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 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_RAW_VARS2), gDpHiiHandle,
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 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_RAW_VARS), gDpHiiHandle,
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 (gDpHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL);
402 StringPtr = HiiGetString (gDpHiiHandle, STRING_TOKEN (STR_DP_SECTION_PHASES), NULL);
403 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_SECTION_HEADER), gDpHiiHandle,
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 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_SEC_PHASE), gDpHiiHandle, 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 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_PHASE_DURATION), gDpHiiHandle, 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 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_PHASE_DURATION), gDpHiiHandle, 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 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_PHASE_DURATION), gDpHiiHandle, ALit_BDS, ElapsedTime);
484 }
485
486 if (BdsTimeoutValue > 0) {
487 ElapsedTime = DivU64x32 (
488 BdsTimeoutValue,
489 (UINT32)TimerInfo.Frequency
490 );
491 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_PHASE_BDSTO), gDpHiiHandle, 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 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_PHASE_DURATION), gDpHiiHandle, ALit_SHELL, ElapsedTime);
503 }
504
505 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_TOTAL_DURATION), gDpHiiHandle, 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 (gDpHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL);
533 StringPtr = HiiGetString (gDpHiiHandle, STRING_TOKEN (STR_DP_SECTION_DRIVERS), NULL);
534 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_SECTION_HEADER), gDpHiiHandle,
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 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_HANDLES_ERROR), gDpHiiHandle, 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 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_HANDLE_SECTION2), gDpHiiHandle);
550 } else {
551 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_HANDLE_SECTION), gDpHiiHandle);
552 }
553 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_DASHES), gDpHiiHandle);
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 DpGetNameFromHandle (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 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_HANDLE_VARS2), gDpHiiHandle,
592 Count, // 1 based, Which measurement record is being printed
593 Index + 1, // 1 based, Which handle is being printed
594 mGaugeString,
595 mUnicodeToken,
596 ElapsedTime,
597 Measurement.Identifier
598 );
599 } else {
600 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_HANDLE_VARS), gDpHiiHandle,
601 Count, // 1 based, Which measurement record is being printed
602 Index + 1, // 1 based, Which handle is being printed
603 mGaugeString,
604 mUnicodeToken,
605 ElapsedTime
606 );
607 }
608 }
609 }
610 }
611 if (HandleBuffer != NULL) {
612 FreePool (HandleBuffer);
613 }
614 return Status;
615 }
616
617 /**
618 Gather and print PEIM data.
619
620 Only prints complete PEIM records
621
622 **/
623 VOID
624 ProcessPeims(
625 VOID
626 )
627 {
628 MEASUREMENT_RECORD Measurement;
629 UINT64 Duration;
630 UINT64 ElapsedTime;
631 EFI_STRING StringPtr;
632 UINTN LogEntryKey;
633 UINTN TIndex;
634 EFI_STRING StringPtrUnknown;
635
636 StringPtrUnknown = HiiGetString (gDpHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL);
637 StringPtr = HiiGetString (gDpHiiHandle, STRING_TOKEN (STR_DP_SECTION_PEIMS), NULL);
638 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_SECTION_HEADER), gDpHiiHandle,
639 (StringPtr == NULL) ? StringPtrUnknown : StringPtr);
640 FreePool (StringPtr);
641 FreePool (StringPtrUnknown);
642
643 if (mShowId) {
644 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_PEIM_SECTION2), gDpHiiHandle);
645 } else {
646 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_PEIM_SECTION), gDpHiiHandle);
647 }
648 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_DASHES), gDpHiiHandle);
649 TIndex = 0;
650 LogEntryKey = 0;
651 while ((LogEntryKey = GetPerformanceMeasurementEx (
652 LogEntryKey,
653 &Measurement.Handle,
654 &Measurement.Token,
655 &Measurement.Module,
656 &Measurement.StartTimeStamp,
657 &Measurement.EndTimeStamp,
658 &Measurement.Identifier)) != 0)
659 {
660 TIndex++;
661 if ((Measurement.EndTimeStamp == 0) ||
662 (AsciiStrnCmp (Measurement.Token, ALit_PEIM, PERF_TOKEN_LENGTH) != 0)
663 ) {
664 continue;
665 }
666
667 Duration = GetDuration (&Measurement);
668 ElapsedTime = DurationInMicroSeconds ( Duration ); // Calculate elapsed time in microseconds
669 if (ElapsedTime >= mInterestThreshold) {
670 // PEIM FILE Handle is the start address of its FFS file that contains its file guid.
671 if (mShowId) {
672 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_PEIM_VARS2), gDpHiiHandle,
673 TIndex, // 1 based, Which measurement record is being printed
674 Measurement.Handle, // base address
675 Measurement.Handle, // file guid
676 ElapsedTime,
677 Measurement.Identifier
678 );
679 } else {
680 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_PEIM_VARS), gDpHiiHandle,
681 TIndex, // 1 based, Which measurement record is being printed
682 Measurement.Handle, // base address
683 Measurement.Handle, // file guid
684 ElapsedTime
685 );
686 }
687 }
688 }
689 }
690
691 /**
692 Gather and print global data.
693
694 Strips out incomplete or "Execution Phase" records
695 Only prints records where Handle is NULL
696 Increment TIndex for every record, even skipped ones, so that we have an
697 indication of every measurement record taken.
698
699 **/
700 VOID
701 ProcessGlobal(
702 VOID
703 )
704 {
705 MEASUREMENT_RECORD Measurement;
706 UINT64 Duration;
707 UINT64 ElapsedTime;
708 EFI_STRING StringPtr;
709 UINTN LogEntryKey;
710 UINTN Index; // Index, or number, of the measurement record being processed
711 EFI_STRING StringPtrUnknown;
712
713 StringPtrUnknown = HiiGetString (gDpHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL);
714 StringPtr = HiiGetString (gDpHiiHandle, STRING_TOKEN (STR_DP_SECTION_GENERAL), NULL);
715 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_SECTION_HEADER), gDpHiiHandle,
716 (StringPtr == NULL) ? StringPtrUnknown: StringPtr);
717 FreePool (StringPtr);
718 FreePool (StringPtrUnknown);
719
720 if (mShowId) {
721 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_GLOBAL_SECTION2), gDpHiiHandle);
722 } else {
723 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_GLOBAL_SECTION), gDpHiiHandle);
724 }
725 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_DASHES), gDpHiiHandle);
726
727 Index = 1;
728 LogEntryKey = 0;
729
730 while ((LogEntryKey = GetPerformanceMeasurementEx (
731 LogEntryKey,
732 &Measurement.Handle,
733 &Measurement.Token,
734 &Measurement.Module,
735 &Measurement.StartTimeStamp,
736 &Measurement.EndTimeStamp,
737 &Measurement.Identifier)) != 0)
738 {
739 AsciiStrToUnicodeStr (Measurement.Module, mGaugeString);
740 AsciiStrToUnicodeStr (Measurement.Token, mUnicodeToken);
741 mGaugeString[25] = 0;
742 mUnicodeToken[31] = 0;
743 if ( ! ( IsPhase( &Measurement) ||
744 (Measurement.Handle != NULL) ||
745 (Measurement.EndTimeStamp == 0)
746 ))
747 {
748 Duration = GetDuration (&Measurement);
749 ElapsedTime = DurationInMicroSeconds ( Duration );
750 if (ElapsedTime >= mInterestThreshold) {
751 if (mShowId) {
752 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_GLOBAL_VARS2), gDpHiiHandle,
753 Index,
754 mGaugeString,
755 mUnicodeToken,
756 ElapsedTime,
757 Measurement.Identifier
758 );
759 } else {
760 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_GLOBAL_VARS), gDpHiiHandle,
761 Index,
762 mGaugeString,
763 mUnicodeToken,
764 ElapsedTime
765 );
766 }
767 }
768 }
769 Index++;
770 }
771 }
772
773 /**
774 Gather and print cumulative data.
775
776 Traverse the measurement records and:<BR>
777 For each record with a Token listed in the CumData array:<BR>
778 - Update the instance count and the total, minimum, and maximum durations.
779 Finally, print the gathered cumulative statistics.
780
781 @param[in] CustomCumulativeData A pointer to the cumtom cumulative data.
782
783 **/
784 VOID
785 ProcessCumulative(
786 IN PERF_CUM_DATA *CustomCumulativeData OPTIONAL
787 )
788 {
789 UINT64 AvgDur; // the computed average duration
790 UINT64 Dur;
791 UINT64 MinDur;
792 UINT64 MaxDur;
793 EFI_STRING StringPtr;
794 UINTN TIndex;
795 EFI_STRING StringPtrUnknown;
796
797 StringPtrUnknown = HiiGetString (gDpHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL);
798 StringPtr = HiiGetString (gDpHiiHandle, STRING_TOKEN (STR_DP_SECTION_CUMULATIVE), NULL);
799 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_SECTION_HEADER), gDpHiiHandle,
800 (StringPtr == NULL) ? StringPtrUnknown: StringPtr);
801 FreePool (StringPtr);
802 FreePool (StringPtrUnknown);
803
804 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_CUMULATIVE_SECT_1), gDpHiiHandle);
805 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_CUMULATIVE_SECT_2), gDpHiiHandle);
806 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_DASHES), gDpHiiHandle);
807
808 for ( TIndex = 0; TIndex < NumCum; ++TIndex) {
809 if (CumData[TIndex].Count != 0) {
810 AvgDur = DivU64x32 (CumData[TIndex].Duration, CumData[TIndex].Count);
811 AvgDur = DurationInMicroSeconds(AvgDur);
812 Dur = DurationInMicroSeconds(CumData[TIndex].Duration);
813 MaxDur = DurationInMicroSeconds(CumData[TIndex].MaxDur);
814 MinDur = DurationInMicroSeconds(CumData[TIndex].MinDur);
815
816 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_CUMULATIVE_STATS), gDpHiiHandle,
817 CumData[TIndex].Name,
818 CumData[TIndex].Count,
819 Dur,
820 AvgDur,
821 MinDur,
822 MaxDur
823 );
824 }
825 }
826
827 //
828 // Print the custom cumulative data.
829 //
830 if (CustomCumulativeData != NULL) {
831 if (CustomCumulativeData->Count != 0) {
832 AvgDur = DivU64x32 (CustomCumulativeData->Duration, CustomCumulativeData->Count);
833 AvgDur = DurationInMicroSeconds (AvgDur);
834 Dur = DurationInMicroSeconds (CustomCumulativeData->Duration);
835 MaxDur = DurationInMicroSeconds (CustomCumulativeData->MaxDur);
836 MinDur = DurationInMicroSeconds (CustomCumulativeData->MinDur);
837 } else {
838 AvgDur = 0;
839 Dur = 0;
840 MaxDur = 0;
841 MinDur = 0;
842 }
843 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_CUMULATIVE_STATS), gDpHiiHandle,
844 CustomCumulativeData->Name,
845 CustomCumulativeData->Count,
846 Dur,
847 AvgDur,
848 MinDur,
849 MaxDur
850 );
851 }
852 }