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