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