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