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