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