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