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