ShellPkg/Dp: Make the help info align with code
[mirror_edk2.git] / ShellPkg / DynamicCommand / DpDynamicCommand / Dp.c
CommitLineData
d41bc92c 1/** @file\r
2 Shell command for Displaying Performance Metrics.\r
3\r
4 The Dp command reads performance data and presents it in several\r
5 different formats depending upon the needs of the user. Both\r
6 Trace and Measured Profiling information is processed and presented.\r
7\r
8 Dp uses the "PerformanceLib" to read the measurement records.\r
9 The "TimerLib" provides information about the timer, such as frequency,\r
10 beginning, and ending counter values.\r
11 Measurement records contain identifying information (Handle, Token, Module)\r
12 and start and end time values.\r
13 Dp uses this information to group records in different ways. It also uses\r
14 timer information to calculate elapsed time for each measurement.\r
15 \r
115eae65 16 Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.\r
196ccda0 17 (C) Copyright 2015-2016 Hewlett Packard Enterprise Development LP<BR>\r
d41bc92c 18 This program and the accompanying materials\r
19 are licensed and made available under the terms and conditions of the BSD License\r
20 which accompanies this distribution. The full text of the license may be found at\r
21 http://opensource.org/licenses/bsd-license.php\r
22 \r
23 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
24 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
25**/\r
26\r
d41bc92c 27#include "Dp.h"\r
28#include "Literals.h"\r
29#include "DpInternal.h"\r
30\r
115eae65
DB
31#pragma pack(1)\r
32\r
33typedef struct {\r
34 EFI_ACPI_DESCRIPTION_HEADER Header;\r
35 UINT32 Entry;\r
36} RSDT_TABLE;\r
37\r
38typedef struct {\r
39 EFI_ACPI_DESCRIPTION_HEADER Header;\r
40 UINT64 Entry;\r
41} XSDT_TABLE;\r
42\r
43#pragma pack()\r
44\r
92034c4c
RN
45EFI_HANDLE mDpHiiHandle;\r
46\r
115eae65
DB
47typedef struct {\r
48 EFI_HANDLE Handle;\r
49 EFI_GUID ModuleGuid;\r
50} HANDLE_GUID_MAP;\r
51\r
52HANDLE_GUID_MAP *mCacheHandleGuidTable;\r
53UINTN mCachePairCount = 0;\r
54\r
d41bc92c 55//\r
56/// Module-Global Variables\r
57///@{\r
58CHAR16 mGaugeString[DP_GAUGE_STRING_LENGTH + 1];\r
59CHAR16 mUnicodeToken[DXE_PERFORMANCE_STRING_SIZE];\r
60UINT64 mInterestThreshold;\r
61BOOLEAN mShowId = FALSE;\r
115eae65
DB
62UINT8 *mBootPerformanceTable;\r
63UINTN mBootPerformanceTableSize;\r
64BOOLEAN mPeiPhase = FALSE;\r
65BOOLEAN mDxePhase = FALSE;\r
d41bc92c 66\r
67PERF_SUMMARY_DATA SummaryData = { 0 }; ///< Create the SummaryData structure and init. to ZERO.\r
115eae65
DB
68MEASUREMENT_RECORD *mMeasurementList = NULL;\r
69UINTN mMeasurementNum = 0;\r
d41bc92c 70\r
71/// Items for which to gather cumulative statistics.\r
72PERF_CUM_DATA CumData[] = {\r
73 PERF_INIT_CUM_DATA (LOAD_IMAGE_TOK),\r
74 PERF_INIT_CUM_DATA (START_IMAGE_TOK),\r
75 PERF_INIT_CUM_DATA (DRIVERBINDING_START_TOK),\r
76 PERF_INIT_CUM_DATA (DRIVERBINDING_SUPPORT_TOK)\r
77};\r
78\r
79/// Number of items for which we are gathering cumulative statistics.\r
80UINT32 const NumCum = sizeof(CumData) / sizeof(PERF_CUM_DATA);\r
81\r
82STATIC CONST SHELL_PARAM_ITEM ParamList[] = {\r
83 {L"-v", TypeFlag}, // -v Verbose Mode\r
84 {L"-A", TypeFlag}, // -A All, Cooked\r
85 {L"-R", TypeFlag}, // -R RAW All\r
86 {L"-s", TypeFlag}, // -s Summary\r
d41bc92c 87 {L"-x", TypeFlag}, // -x eXclude Cumulative Items\r
88 {L"-i", TypeFlag}, // -i Display Identifier\r
a06795c6 89 {L"-c", TypeValue}, // -c Display cumulative data.\r
d41bc92c 90 {L"-n", TypeValue}, // -n # Number of records to display for A and R\r
91 {L"-t", TypeValue}, // -t # Threshold of interest\r
92 {NULL, TypeMax}\r
93 };\r
94\r
95///@}\r
96\r
97/**\r
98 Display the trailing Verbose information.\r
99**/\r
100VOID\r
101DumpStatistics( void )\r
102{\r
103 EFI_STRING StringPtr;\r
104 EFI_STRING StringPtrUnknown;\r
92034c4c
RN
105 StringPtr = HiiGetString (mDpHiiHandle, STRING_TOKEN (STR_DP_SECTION_STATISTICS), NULL);\r
106 StringPtrUnknown = HiiGetString (mDpHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL);\r
107 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_SECTION_HEADER), mDpHiiHandle,\r
d41bc92c 108 (StringPtr == NULL) ? StringPtrUnknown : StringPtr);\r
92034c4c
RN
109 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_STATS_NUMTRACE), mDpHiiHandle, SummaryData.NumTrace);\r
110 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_STATS_NUMINCOMPLETE), mDpHiiHandle, SummaryData.NumIncomplete);\r
111 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_STATS_NUMPHASES), mDpHiiHandle, SummaryData.NumSummary);\r
112 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_STATS_NUMHANDLES), mDpHiiHandle, SummaryData.NumHandles, SummaryData.NumTrace - SummaryData.NumHandles);\r
113 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_STATS_NUMPEIMS), mDpHiiHandle, SummaryData.NumPEIMs);\r
114 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_STATS_NUMGLOBALS), mDpHiiHandle, SummaryData.NumGlobal);\r
d41bc92c 115 SHELL_FREE_NON_NULL (StringPtr);\r
116 SHELL_FREE_NON_NULL (StringPtrUnknown);\r
117}\r
118\r
115eae65
DB
119/**\r
120 This function scan ACPI table in RSDT.\r
121\r
122 @param Rsdt ACPI RSDT\r
123 @param Signature ACPI table signature\r
124\r
125 @return ACPI table\r
126**/\r
127VOID *\r
128ScanTableInRSDT (\r
129 IN RSDT_TABLE *Rsdt,\r
130 IN UINT32 Signature\r
131 )\r
132{\r
133 UINTN Index;\r
134 UINT32 EntryCount;\r
135 UINT32 *EntryPtr;\r
136 EFI_ACPI_DESCRIPTION_HEADER *Table;\r
137\r
138 EntryCount = (Rsdt->Header.Length - sizeof (EFI_ACPI_DESCRIPTION_HEADER)) / sizeof(UINT32);\r
139\r
140 EntryPtr = &Rsdt->Entry;\r
141 for (Index = 0; Index < EntryCount; Index ++, EntryPtr ++) {\r
142 Table = (EFI_ACPI_DESCRIPTION_HEADER*)((UINTN)(*EntryPtr));\r
143 if (Table->Signature == Signature) {\r
144 return Table;\r
145 }\r
146 }\r
147\r
148 return NULL;\r
149}\r
150\r
151/**\r
152 This function scan ACPI table in XSDT.\r
153\r
154 @param Xsdt ACPI XSDT\r
155 @param Signature ACPI table signature\r
156\r
157 @return ACPI table\r
158**/\r
159VOID *\r
160ScanTableInXSDT (\r
161 IN XSDT_TABLE *Xsdt,\r
162 IN UINT32 Signature\r
163 )\r
164{\r
165 UINTN Index;\r
166 UINT32 EntryCount;\r
167 UINT64 EntryPtr;\r
168 UINTN BasePtr;\r
169 EFI_ACPI_DESCRIPTION_HEADER *Table;\r
170\r
171 EntryCount = (Xsdt->Header.Length - sizeof (EFI_ACPI_DESCRIPTION_HEADER)) / sizeof(UINT64);\r
172\r
173 BasePtr = (UINTN)(&(Xsdt->Entry));\r
174 for (Index = 0; Index < EntryCount; Index ++) {\r
175 CopyMem (&EntryPtr, (VOID *)(BasePtr + Index * sizeof(UINT64)), sizeof(UINT64));\r
176 Table = (EFI_ACPI_DESCRIPTION_HEADER*)((UINTN)(EntryPtr));\r
177 if (Table->Signature == Signature) {\r
178 return Table;\r
179 }\r
180 }\r
181\r
182 return NULL;\r
183}\r
184\r
185/**\r
186 This function scan ACPI table in RSDP.\r
187\r
188 @param Rsdp ACPI RSDP\r
189 @param Signature ACPI table signature\r
190\r
191 @return ACPI table\r
192**/\r
193VOID *\r
194FindAcpiPtr (\r
195 IN EFI_ACPI_5_0_ROOT_SYSTEM_DESCRIPTION_POINTER *Rsdp,\r
196 IN UINT32 Signature\r
197 )\r
198{\r
199 EFI_ACPI_DESCRIPTION_HEADER *AcpiTable;\r
200 RSDT_TABLE *Rsdt;\r
201 XSDT_TABLE *Xsdt;\r
202\r
203 AcpiTable = NULL;\r
204\r
205 //\r
206 // Check ACPI2.0 table\r
207 //\r
208 Rsdt = (RSDT_TABLE *)(UINTN)Rsdp->RsdtAddress;\r
209 Xsdt = NULL;\r
210 if ((Rsdp->Revision >= 2) && (Rsdp->XsdtAddress < (UINT64)(UINTN)-1)) {\r
211 Xsdt = (XSDT_TABLE *)(UINTN)Rsdp->XsdtAddress;\r
212 }\r
213 //\r
214 // Check Xsdt\r
215 //\r
216 if (Xsdt != NULL) {\r
217 AcpiTable = ScanTableInXSDT (Xsdt, Signature);\r
218 }\r
219 //\r
220 // Check Rsdt\r
221 //\r
222 if ((AcpiTable == NULL) && (Rsdt != NULL)) {\r
223 AcpiTable = ScanTableInRSDT (Rsdt, Signature);\r
224 }\r
225\r
226 return AcpiTable;\r
227}\r
228\r
229/**\r
230 Get Boot performance table form Acpi table.\r
231\r
232**/\r
233EFI_STATUS\r
234GetBootPerformanceTable (\r
235 )\r
236{\r
237 EFI_STATUS Status;\r
238 VOID *AcpiTable;\r
239 FIRMWARE_PERFORMANCE_TABLE *FirmwarePerformanceTable;\r
240\r
241 AcpiTable = NULL;\r
242\r
243 Status = EfiGetSystemConfigurationTable (\r
244 &gEfiAcpi20TableGuid,\r
245 &AcpiTable\r
246 );\r
247 if (EFI_ERROR (Status)) {\r
248 Status = EfiGetSystemConfigurationTable (\r
249 &gEfiAcpi10TableGuid,\r
250 &AcpiTable\r
251 );\r
252 }\r
2d70c90d 253 if (EFI_ERROR(Status) || AcpiTable == NULL) {\r
4109d0d7 254 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_GET_ACPI_TABLE_FAIL), mDpHiiHandle);\r
115eae65
DB
255 return Status;\r
256 }\r
257\r
258 FirmwarePerformanceTable = FindAcpiPtr (\r
259 (EFI_ACPI_5_0_ROOT_SYSTEM_DESCRIPTION_POINTER *)AcpiTable,\r
260 EFI_ACPI_5_0_FIRMWARE_PERFORMANCE_DATA_TABLE_SIGNATURE\r
261 );\r
262 if (FirmwarePerformanceTable == NULL) {\r
4109d0d7 263 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_GET_ACPI_FPDT_FAIL), mDpHiiHandle);\r
115eae65
DB
264 return EFI_NOT_FOUND;\r
265 }\r
266\r
267 mBootPerformanceTable = (UINT8*) (UINTN)FirmwarePerformanceTable->BootPointerRecord.BootPerformanceTablePointer;\r
268 mBootPerformanceTableSize = ((BOOT_PERFORMANCE_TABLE *) mBootPerformanceTable)->Header.Length;\r
269\r
270 return EFI_SUCCESS;\r
271}\r
272\r
273/**\r
274 Get Handle form Module Guid.\r
275\r
276 @param ModuleGuid Module Guid.\r
277 @param Handle The handle to be returned.\r
278\r
279**/\r
280VOID\r
281GetHandleFormModuleGuid (\r
282 IN EFI_GUID *ModuleGuid,\r
283 IN OUT EFI_HANDLE *Handle\r
284 )\r
285{\r
286 UINTN Index;\r
287\r
288 if (IsZeroGuid (ModuleGuid)) {\r
289 *Handle = NULL;\r
290 }\r
291 //\r
292 // Try to get the Handle form the caached array.\r
293 //\r
294 for (Index = 0; Index < mCachePairCount; Index++) {\r
295 if (CompareGuid (ModuleGuid, &mCacheHandleGuidTable[Index].ModuleGuid)) {\r
296 *Handle = mCacheHandleGuidTable[Index].Handle;\r
297 break;\r
298 }\r
299 }\r
300 if (Index >= mCachePairCount) {\r
301 *Handle = NULL;\r
302 }\r
303}\r
304\r
305/**\r
306Cache the GUID and handle mapping pairs. In order to save time for searching.\r
307\r
308**/\r
309EFI_STATUS\r
310BuildCachedGuidHandleTable (\r
311 VOID\r
312 )\r
313{\r
314 EFI_STATUS Status;\r
315 EFI_HANDLE *HandleBuffer;\r
316 UINTN HandleCount;\r
317 UINTN Index;\r
318 EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;\r
319 EFI_DRIVER_BINDING_PROTOCOL *DriverBinding;\r
320 EFI_GUID *TempGuid;\r
321 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FvFilePath;\r
322\r
323 Status = gBS->LocateHandleBuffer (AllHandles, NULL, NULL, &HandleCount, &HandleBuffer);\r
324 if (EFI_ERROR (Status)) {\r
325 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_HANDLES_ERROR), mDpHiiHandle, Status);\r
326 return Status;\r
327 }\r
328\r
329 mCacheHandleGuidTable = AllocateZeroPool (HandleCount * sizeof (HANDLE_GUID_MAP));\r
330 if (mCacheHandleGuidTable == NULL) {\r
331 return EFI_OUT_OF_RESOURCES;\r
332 }\r
333\r
334 for (Index = 0; Index < HandleCount; Index++) {\r
335 //\r
336 // Try Handle as ImageHandle.\r
337 //\r
338 Status = gBS->HandleProtocol (\r
339 HandleBuffer[Index],\r
340 &gEfiLoadedImageProtocolGuid,\r
341 (VOID**) &LoadedImage\r
342 );\r
343 if (EFI_ERROR (Status)) {\r
344 //\r
345 // Try Handle as Controller Handle\r
346 //\r
347 Status = gBS->OpenProtocol (\r
348 HandleBuffer[Index],\r
349 &gEfiDriverBindingProtocolGuid,\r
350 (VOID **) &DriverBinding,\r
351 NULL,\r
352 NULL,\r
353 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
354 );\r
355 if (!EFI_ERROR (Status)) {\r
356 //\r
357 // Get Image protocol from ImageHandle\r
358 //\r
359 Status = gBS->HandleProtocol (\r
360 DriverBinding->ImageHandle,\r
361 &gEfiLoadedImageProtocolGuid,\r
362 (VOID**) &LoadedImage\r
363 );\r
364 }\r
365 }\r
366\r
367 if (!EFI_ERROR (Status) && LoadedImage != NULL) {\r
368 //\r
369 // Get Module Guid from DevicePath.\r
370 //\r
371 if (LoadedImage->FilePath != NULL &&\r
372 LoadedImage->FilePath->Type == MEDIA_DEVICE_PATH &&\r
373 LoadedImage->FilePath->SubType == MEDIA_PIWG_FW_FILE_DP\r
374 ) {\r
375 FvFilePath = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) LoadedImage->FilePath;\r
376 TempGuid = &FvFilePath->FvFileName;\r
377\r
378 mCacheHandleGuidTable[mCachePairCount].Handle = HandleBuffer[Index];\r
379 CopyGuid (&mCacheHandleGuidTable[mCachePairCount].ModuleGuid, TempGuid);\r
380 mCachePairCount ++;\r
381 }\r
382 }\r
383 }\r
384 if (HandleBuffer != NULL) {\r
385 FreePool (HandleBuffer);\r
386 HandleBuffer = NULL;\r
387 }\r
37d533da 388 return EFI_SUCCESS;\r
115eae65
DB
389}\r
390\r
391/**\r
392 Get Measurement form Fpdt records.\r
393\r
394 @param RecordHeader Pointer to the start record.\r
395 @param IsStart Is start record or End record.\r
396 @param Measurement Pointer to the measurement which need to be filled.\r
397\r
398**/\r
399VOID\r
400GetMeasurementInfo (\r
401 IN EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER *RecordHeader,\r
402 IN BOOLEAN IsStart,\r
403 IN OUT MEASUREMENT_RECORD *Measurement\r
404 )\r
405{\r
406 VOID *ModuleGuid;\r
407 EFI_HANDLE StartHandle;\r
408\r
409 switch (RecordHeader->Type) {\r
410 case FPDT_GUID_EVENT_TYPE:\r
411 ModuleGuid = &(((FPDT_GUID_EVENT_RECORD *)RecordHeader)->Guid);\r
412 Measurement->Identifier = ((UINT32)((FPDT_GUID_EVENT_RECORD *)RecordHeader)->ProgressID);\r
413 if (IsStart) {\r
414 Measurement->StartTimeStamp = ((FPDT_GUID_EVENT_RECORD *)RecordHeader)->Timestamp;\r
415 } else {\r
416 Measurement->EndTimeStamp = ((FPDT_GUID_EVENT_RECORD *)RecordHeader)->Timestamp;\r
417 }\r
418 switch (Measurement->Identifier) {\r
419 case MODULE_START_ID:\r
420 case MODULE_END_ID:\r
421 if (mPeiPhase) {\r
422 Measurement->Token = ALit_PEIM;\r
423 Measurement->Module = ALit_PEIM;\r
424 } else if (mDxePhase) {\r
425 Measurement->Token = ALit_START_IMAGE;\r
426 Measurement->Module = ALit_START_IMAGE;\r
427 }\r
428 break;\r
429 default:\r
430 ASSERT(FALSE);\r
431 }\r
432\r
433 if (AsciiStrCmp (Measurement->Token, ALit_PEIM) == 0) {\r
434 Measurement->Handle = &(((FPDT_GUID_EVENT_RECORD *)RecordHeader)->Guid);\r
435 } else {\r
436 GetHandleFormModuleGuid(ModuleGuid, &StartHandle);\r
437 Measurement->Handle = StartHandle;\r
438 }\r
439 break;\r
440\r
441 case FPDT_DYNAMIC_STRING_EVENT_TYPE:\r
442 ModuleGuid = &(((FPDT_DYNAMIC_STRING_EVENT_RECORD *)RecordHeader)->Guid);\r
443 Measurement->Identifier = ((UINT32)((FPDT_DYNAMIC_STRING_EVENT_RECORD *)RecordHeader)->ProgressID);\r
444 if (IsStart) {\r
445 Measurement->StartTimeStamp = ((FPDT_DYNAMIC_STRING_EVENT_RECORD *)RecordHeader)->Timestamp;\r
446 } else {\r
447 Measurement->EndTimeStamp = ((FPDT_DYNAMIC_STRING_EVENT_RECORD *)RecordHeader)->Timestamp;\r
448 }\r
449 switch (Measurement->Identifier) {\r
450 case MODULE_START_ID:\r
451 case MODULE_END_ID:\r
452 if (mPeiPhase) {\r
453 Measurement->Token = ALit_PEIM;\r
454 } else if (mDxePhase) {\r
455 Measurement->Token = ALit_START_IMAGE;\r
456 }\r
457 break;\r
458\r
459 case MODULE_LOADIMAGE_START_ID:\r
460 case MODULE_LOADIMAGE_END_ID:\r
461 Measurement->Token = ALit_LOAD_IMAGE;\r
462 break;\r
463\r
464 case MODULE_DB_START_ID:\r
465 case MODULE_DB_END_ID:\r
466 Measurement->Token = ALit_DB_START;\r
467 break;\r
468\r
469 case MODULE_DB_SUPPORT_START_ID:\r
470 case MODULE_DB_SUPPORT_END_ID:\r
471 Measurement->Token = ALit_DB_SUPPORT;\r
472 break;\r
473\r
474 case MODULE_DB_STOP_START_ID:\r
475 case MODULE_DB_STOP_END_ID:\r
476 Measurement->Token = ALit_DB_STOP;\r
477 break;\r
478\r
479 default:\r
480 Measurement->Token = ((FPDT_DYNAMIC_STRING_EVENT_RECORD *)RecordHeader)->String;\r
481 break;\r
482 }\r
483\r
484 Measurement->Module = ((FPDT_DYNAMIC_STRING_EVENT_RECORD *)RecordHeader)->String;\r
485\r
486 if (AsciiStrCmp (Measurement->Token, ALit_PEIM) == 0) {\r
487 Measurement->Handle = &(((FPDT_DYNAMIC_STRING_EVENT_RECORD *)RecordHeader)->Guid);\r
488 } else {\r
489 GetHandleFormModuleGuid(ModuleGuid, &StartHandle);\r
490 Measurement->Handle = StartHandle;\r
491 }\r
492 break;\r
493\r
494 case FPDT_GUID_QWORD_EVENT_TYPE:\r
495 ModuleGuid = &(((FPDT_GUID_QWORD_EVENT_RECORD *)RecordHeader)->Guid);\r
496 Measurement->Identifier = ((UINT32)((FPDT_GUID_QWORD_EVENT_RECORD *)RecordHeader)->ProgressID);\r
497 if (IsStart) {\r
498 Measurement->StartTimeStamp = ((FPDT_GUID_QWORD_EVENT_RECORD *)RecordHeader)->Timestamp;\r
499 } else {\r
500 Measurement->EndTimeStamp = ((FPDT_GUID_QWORD_EVENT_RECORD *)RecordHeader)->Timestamp;\r
501 }\r
502 switch (Measurement->Identifier) {\r
503 case MODULE_DB_START_ID:\r
504 Measurement->Token = ALit_DB_START;\r
505 Measurement->Module = ALit_DB_START;\r
506 break;\r
507\r
508 case MODULE_DB_SUPPORT_START_ID:\r
509 case MODULE_DB_SUPPORT_END_ID:\r
510 Measurement->Token = ALit_DB_SUPPORT;\r
511 Measurement->Module = ALit_DB_SUPPORT;\r
512 break;\r
513\r
514 case MODULE_DB_STOP_START_ID:\r
515 case MODULE_DB_STOP_END_ID:\r
516 Measurement->Token = ALit_DB_STOP;\r
517 Measurement->Module = ALit_DB_STOP;\r
518 break;\r
519\r
520 case MODULE_LOADIMAGE_START_ID:\r
521 case MODULE_LOADIMAGE_END_ID:\r
522 Measurement->Token = ALit_LOAD_IMAGE;\r
523 Measurement->Module = ALit_LOAD_IMAGE;\r
524 break;\r
525\r
526 default:\r
527 ASSERT(FALSE);\r
528 }\r
529 GetHandleFormModuleGuid(ModuleGuid, &StartHandle);\r
530 Measurement->Handle = StartHandle;\r
531 break;\r
532\r
533 case FPDT_GUID_QWORD_STRING_EVENT_TYPE:\r
534 ModuleGuid = &(((FPDT_GUID_QWORD_STRING_EVENT_RECORD *)RecordHeader)->Guid);\r
535 Measurement->Identifier = ((UINT32)((FPDT_GUID_QWORD_STRING_EVENT_RECORD *)RecordHeader)->ProgressID);\r
536 if (IsStart) {\r
537 Measurement->StartTimeStamp = ((FPDT_GUID_QWORD_STRING_EVENT_RECORD*)RecordHeader)->Timestamp;\r
538 } else {\r
539 Measurement->EndTimeStamp = ((FPDT_GUID_QWORD_STRING_EVENT_RECORD *)RecordHeader)->Timestamp;\r
540 }\r
541 //\r
542 // Currently only "DB:Start:" end record with FPDT_GUID_QWORD_STRING_EVENT_TYPE.\r
543 //\r
544 switch (Measurement->Identifier) {\r
545 case MODULE_DB_END_ID:\r
546 Measurement->Token = ALit_DB_START;\r
547 Measurement->Module = ALit_DB_START;\r
548 break;\r
549 default:\r
550 ASSERT(FALSE);\r
551 }\r
552 GetHandleFormModuleGuid(ModuleGuid, &StartHandle);\r
553 Measurement->Handle = StartHandle;\r
554 break;\r
555\r
556 default:\r
557 break;\r
558 }\r
559}\r
560\r
561/**\r
562 Search the start measurement in the mMeasurementList for the end measurement.\r
563\r
564 @param EndMeasureMent Measurement for end record.\r
565\r
566**/\r
567VOID\r
568SearchMeasurement (\r
569 IN MEASUREMENT_RECORD *EndMeasureMent\r
570 )\r
571{\r
572 INTN Index;\r
573\r
574 for (Index = mMeasurementNum - 1; Index >= 0; Index--) {\r
575 if (AsciiStrCmp (EndMeasureMent->Token, ALit_PEIM) == 0) {\r
576 if (mMeasurementList[Index].EndTimeStamp == 0 && EndMeasureMent->Handle!= NULL && mMeasurementList[Index].Handle != NULL&&\r
577 CompareGuid(mMeasurementList[Index].Handle, EndMeasureMent->Handle) &&\r
578 (AsciiStrCmp (mMeasurementList[Index].Token, EndMeasureMent->Token) == 0) &&\r
579 (AsciiStrCmp (mMeasurementList[Index].Module, EndMeasureMent->Module) == 0)) {\r
580 mMeasurementList[Index].EndTimeStamp = EndMeasureMent->EndTimeStamp;\r
581 break;\r
582 }\r
583 } else {\r
584 if (mMeasurementList[Index].EndTimeStamp == 0 && mMeasurementList[Index].Handle == EndMeasureMent->Handle &&\r
585 (AsciiStrCmp (mMeasurementList[Index].Token, EndMeasureMent->Token) == 0) &&\r
586 (AsciiStrCmp (mMeasurementList[Index].Module, EndMeasureMent->Module) == 0)) {\r
587 mMeasurementList[Index].EndTimeStamp = EndMeasureMent->EndTimeStamp;\r
588 break;\r
589 }\r
590 }\r
591 }\r
592}\r
593\r
594/**\r
595 Generate the measure record array.\r
596\r
597**/\r
598EFI_STATUS\r
599BuildMeasurementList (\r
600 )\r
601{\r
602 EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER *RecordHeader;\r
603 UINT8 *PerformanceTablePtr;\r
604 UINT16 StartProgressId;\r
605 UINTN TableLength;\r
606 UINT8 *StartRecordEvent;\r
607 MEASUREMENT_RECORD MeasureMent;\r
608\r
609 mMeasurementList = AllocateZeroPool (mBootPerformanceTableSize);\r
610 if (mMeasurementList == NULL) {\r
611 return EFI_OUT_OF_RESOURCES;\r
612 }\r
613\r
614 TableLength = sizeof (BOOT_PERFORMANCE_TABLE);\r
615 PerformanceTablePtr = (mBootPerformanceTable + TableLength);\r
616\r
617 while (TableLength < mBootPerformanceTableSize) {\r
618 RecordHeader = (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER*) PerformanceTablePtr;\r
619 StartRecordEvent = (UINT8 *)RecordHeader;\r
620 StartProgressId = ((FPDT_GUID_EVENT_RECORD *)StartRecordEvent)->ProgressID;\r
621\r
622 //\r
623 // If the record is the start record, fill the info to the measurement in the mMeasurementList.\r
624 // If the record is the end record, find the related start measurement in the mMeasurementList and fill the EndTimeStamp.\r
625 //\r
626 if (((StartProgressId >= PERF_EVENTSIGNAL_START_ID && ((StartProgressId & 0x000F) == 0)) ||\r
627 (StartProgressId < PERF_EVENTSIGNAL_START_ID && ((StartProgressId & 0x0001) != 0)))) {\r
628 //\r
629 // Since PEIM and StartImage has same Type and ID when PCD PcdEdkiiFpdtStringRecordEnableOnly = FALSE\r
630 // So we need to identify these two kinds of record through different phase.\r
631 //\r
632 if (AsciiStrCmp (((FPDT_DYNAMIC_STRING_EVENT_RECORD *)StartRecordEvent)->String, ALit_PEI) == 0) {\r
633 mPeiPhase = TRUE;\r
634 } else if (AsciiStrCmp (((FPDT_DYNAMIC_STRING_EVENT_RECORD *)StartRecordEvent)->String, ALit_DXE) == 0) {\r
635 mDxePhase = TRUE;\r
636 mPeiPhase = FALSE;\r
637 }\r
638 // Get measurement info form the start record to the mMeasurementList.\r
639 GetMeasurementInfo (RecordHeader, TRUE, &(mMeasurementList[mMeasurementNum]));\r
640 mMeasurementNum ++;\r
641 } else {\r
642 GetMeasurementInfo (RecordHeader, FALSE, &MeasureMent);\r
643 SearchMeasurement (&MeasureMent);\r
644 }\r
645 TableLength += RecordHeader->Length;\r
646 PerformanceTablePtr += RecordHeader->Length;\r
647 }\r
648 return EFI_SUCCESS;\r
649}\r
650\r
303ec9bc
CS
651/**\r
652 Initialize the cumulative data.\r
653\r
654**/\r
655VOID\r
656InitCumulativeData (\r
657 VOID\r
658 )\r
659{\r
660 UINTN Index;\r
661\r
662 for (Index = 0; Index < NumCum; ++Index) {\r
663 CumData[Index].Count = 0;\r
664 CumData[Index].MinDur = PERF_MAXDUR;\r
665 CumData[Index].MaxDur = 0;\r
666 CumData[Index].Duration = 0;\r
667 }\r
668}\r
669\r
d25cf17c
DB
670/**\r
671 Initialize the Summary data.\r
672\r
673**/\r
674VOID\r
675InitSummaryData (\r
676 VOID\r
677 )\r
678{\r
679 SummaryData.NumTrace = 0;\r
d25cf17c
DB
680 SummaryData.NumIncomplete = 0;\r
681 SummaryData.NumSummary = 0;\r
682 SummaryData.NumHandles = 0;\r
683 SummaryData.NumPEIMs = 0;\r
684 SummaryData.NumGlobal = 0;\r
685}\r
686\r
303ec9bc 687/**\r
d41bc92c 688 Dump performance data.\r
689 \r
690 @param[in] ImageHandle The image handle.\r
691 @param[in] SystemTable The system table.\r
692 \r
196ccda0
CS
693 @retval SHELL_SUCCESS Command completed successfully.\r
694 @retval SHELL_INVALID_PARAMETER Command usage error.\r
695 @retval SHELL_ABORTED The user aborts the operation.\r
696 @retval value Unknown error.\r
d41bc92c 697**/\r
698SHELL_STATUS\r
92034c4c 699RunDp (\r
d41bc92c 700 IN EFI_HANDLE ImageHandle,\r
701 IN EFI_SYSTEM_TABLE *SystemTable\r
702 )\r
703{\r
704 LIST_ENTRY *ParamPackage;\r
705 CONST CHAR16 *CmdLineArg;\r
706 EFI_STATUS Status;\r
707\r
ef224032 708 PERFORMANCE_PROPERTY *PerformanceProperty;\r
d41bc92c 709 UINTN Number2Display;\r
710\r
a9b4ff8d
ED
711 EFI_STRING StringPtr;\r
712 BOOLEAN SummaryMode;\r
713 BOOLEAN VerboseMode;\r
714 BOOLEAN AllMode;\r
715 BOOLEAN RawMode;\r
a9b4ff8d 716 BOOLEAN ExcludeMode;\r
a06795c6
CS
717 BOOLEAN CumulativeMode;\r
718 CONST CHAR16 *CustomCumulativeToken;\r
719 PERF_CUM_DATA *CustomCumulativeData;\r
46213c8e 720 UINTN NameSize;\r
196ccda0 721 SHELL_STATUS ShellStatus;\r
115eae65 722 TIMER_INFO TimerInfo;\r
a9b4ff8d
ED
723\r
724 StringPtr = NULL;\r
725 SummaryMode = FALSE;\r
726 VerboseMode = FALSE;\r
727 AllMode = FALSE;\r
728 RawMode = FALSE;\r
a9b4ff8d 729 ExcludeMode = FALSE;\r
a06795c6
CS
730 CumulativeMode = FALSE;\r
731 CustomCumulativeData = NULL;\r
196ccda0 732 ShellStatus = SHELL_SUCCESS;\r
d41bc92c 733\r
d41bc92c 734 //\r
735 // initialize the shell lib (we must be in non-auto-init...)\r
736 //\r
737 Status = ShellInitialize();\r
738 ASSERT_EFI_ERROR(Status);\r
739\r
d41bc92c 740 //\r
741 // Process Command Line arguments\r
742 //\r
743 Status = ShellCommandLineParse (ParamList, &ParamPackage, NULL, TRUE);\r
744 if (EFI_ERROR(Status)) {\r
92034c4c 745 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_INVALID_ARG), mDpHiiHandle);\r
d41bc92c 746 return SHELL_INVALID_PARAMETER;\r
747 }\r
748\r
749 //\r
750 // Boolean options\r
751 //\r
752 VerboseMode = ShellCommandLineGetFlag (ParamPackage, L"-v");\r
753 SummaryMode = (BOOLEAN) (ShellCommandLineGetFlag (ParamPackage, L"-S") || ShellCommandLineGetFlag (ParamPackage, L"-s"));\r
754 AllMode = ShellCommandLineGetFlag (ParamPackage, L"-A");\r
755 RawMode = ShellCommandLineGetFlag (ParamPackage, L"-R");\r
d41bc92c 756 ExcludeMode = ShellCommandLineGetFlag (ParamPackage, L"-x");\r
757 mShowId = ShellCommandLineGetFlag (ParamPackage, L"-i");\r
a06795c6 758 CumulativeMode = ShellCommandLineGetFlag (ParamPackage, L"-c");\r
d41bc92c 759\r
760 // Options with Values\r
761 CmdLineArg = ShellCommandLineGetValue (ParamPackage, L"-n");\r
762 if (CmdLineArg == NULL) {\r
763 Number2Display = DEFAULT_DISPLAYCOUNT;\r
764 } else {\r
765 Number2Display = StrDecimalToUintn(CmdLineArg);\r
766 if (Number2Display == 0) {\r
767 Number2Display = MAXIMUM_DISPLAYCOUNT;\r
768 }\r
769 }\r
770\r
771 CmdLineArg = ShellCommandLineGetValue (ParamPackage, L"-t");\r
772 if (CmdLineArg == NULL) {\r
773 mInterestThreshold = DEFAULT_THRESHOLD; // 1ms := 1,000 us\r
774 } else {\r
775 mInterestThreshold = StrDecimalToUint64(CmdLineArg);\r
776 }\r
777\r
d41bc92c 778\r
37d533da
DB
779 //\r
780 // DP dump performance data by parsing FPDT table in ACPI table.\r
781 // Folloing 3 steps are to get the measurement form the FPDT table.\r
782 //\r
783\r
784 //\r
785 //1. Get FPDT from ACPI table.\r
786 //\r
787 Status = GetBootPerformanceTable ();\r
788 if (EFI_ERROR (Status)) {\r
789 ShellStatus = Status;\r
790 goto Done;\r
791 }\r
792\r
793 //\r
794 //2. Cache the ModuleGuid and hanlde mapping table.\r
795 //\r
796 Status = BuildCachedGuidHandleTable();\r
797 if (EFI_ERROR (Status)) {\r
798 ShellStatus = Status;\r
799 goto Done;\r
800 }\r
801\r
802 //\r
803 //3. Build the measurement array form the FPDT records.\r
804 //\r
805 Status = BuildMeasurementList ();\r
806 if (EFI_ERROR (Status)) {\r
807 ShellStatus = SHELL_OUT_OF_RESOURCES;\r
808 goto Done;\r
809 }\r
810\r
303ec9bc
CS
811 //\r
812 // Initialize the pre-defined cumulative data.\r
813 //\r
814 InitCumulativeData ();\r
815\r
d25cf17c
DB
816 //\r
817 // Initialize the Summary data.\r
818 //\r
819 InitSummaryData ();\r
820\r
a06795c6
CS
821 //\r
822 // Init the custom cumulative data.\r
823 //\r
824 CustomCumulativeToken = ShellCommandLineGetValue (ParamPackage, L"-c");\r
825 if (CustomCumulativeToken != NULL) {\r
826 CustomCumulativeData = AllocateZeroPool (sizeof (PERF_CUM_DATA));\r
d758f809 827 if (CustomCumulativeData == NULL) {\r
37d533da
DB
828 ShellStatus = SHELL_OUT_OF_RESOURCES;\r
829 goto Done;\r
d758f809 830 }\r
3cf737c7 831 CustomCumulativeData->MinDur = PERF_MAXDUR;\r
a06795c6
CS
832 CustomCumulativeData->MaxDur = 0;\r
833 CustomCumulativeData->Count = 0;\r
834 CustomCumulativeData->Duration = 0;\r
46213c8e
SZ
835 NameSize = StrLen (CustomCumulativeToken) + 1;\r
836 CustomCumulativeData->Name = AllocateZeroPool (NameSize);\r
d758f809 837 if (CustomCumulativeData->Name == NULL) {\r
37d533da
DB
838 ShellStatus = SHELL_OUT_OF_RESOURCES;\r
839 goto Done;\r
d758f809 840 }\r
46213c8e 841 UnicodeStrToAsciiStrS (CustomCumulativeToken, CustomCumulativeData->Name, NameSize);\r
a06795c6
CS
842 }\r
843\r
d41bc92c 844 //\r
845 // Timer specific processing\r
846 //\r
847 // Get the Performance counter characteristics:\r
848 // Freq = Frequency in Hz\r
849 // StartCount = Value loaded into the counter when it starts counting\r
850 // EndCount = Value counter counts to before it needs to be reset\r
851 //\r
37322be5 852 Status = EfiGetSystemConfigurationTable (&gPerformanceProtocolGuid, (VOID **) &PerformanceProperty);\r
24c6962d 853 if (EFI_ERROR (Status) || (PerformanceProperty == NULL)) {\r
92034c4c 854 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PERF_PROPERTY_NOT_FOUND), mDpHiiHandle);\r
ef224032
SZ
855 goto Done;\r
856 }\r
d41bc92c 857\r
ef224032 858 TimerInfo.Frequency = (UINT32)DivU64x32 (PerformanceProperty->Frequency, 1000);\r
115eae65
DB
859 TimerInfo.StartCount = 0;\r
860 TimerInfo.EndCount = 0xFFFF;\r
861 TimerInfo.CountUp = TRUE;\r
d41bc92c 862\r
863 //\r
864 // Print header\r
865 //\r
866 // print DP's build version\r
92034c4c 867 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_BUILD_REVISION), mDpHiiHandle, DP_MAJOR_VERSION, DP_MINOR_VERSION);\r
d41bc92c 868\r
869 // print performance timer characteristics\r
92034c4c 870 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_KHZ), mDpHiiHandle, TimerInfo.Frequency);\r
d41bc92c 871\r
872 if (VerboseMode && !RawMode) {\r
92034c4c 873 StringPtr = HiiGetString (mDpHiiHandle,\r
d41bc92c 874 (EFI_STRING_ID) (TimerInfo.CountUp ? STRING_TOKEN (STR_DP_UP) : STRING_TOKEN (STR_DP_DOWN)), NULL);\r
875 ASSERT (StringPtr != NULL);\r
876 // Print Timer count range and direction\r
92034c4c 877 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_TIMER_PROPERTIES), mDpHiiHandle,\r
d41bc92c 878 StringPtr,\r
879 TimerInfo.StartCount,\r
880 TimerInfo.EndCount\r
881 );\r
92034c4c 882 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_VERBOSE_THRESHOLD), mDpHiiHandle, mInterestThreshold);\r
d41bc92c 883 }\r
884\r
885/****************************************************************************\r
886**** Print Sections based on command line options\r
887****\r
888**** Option modes have the following priority:\r
889**** v Verbose -- Valid in combination with any other options\r
890**** t Threshold -- Modifies All, Raw, and Cooked output\r
891**** Default is 0 for All and Raw mode\r
892**** Default is DEFAULT_THRESHOLD for "Cooked" mode\r
893**** n Number2Display Used by All and Raw mode. Otherwise ignored.\r
894**** A All -- R and S options are ignored\r
895**** R Raw -- S option is ignored\r
896**** s Summary -- Modifies "Cooked" output only\r
897**** Cooked (Default)\r
d41bc92c 898****************************************************************************/\r
a06795c6
CS
899 GatherStatistics (CustomCumulativeData);\r
900 if (CumulativeMode) { \r
901 ProcessCumulative (CustomCumulativeData);\r
902 } else if (AllMode) {\r
5a56c049
DB
903 Status = DumpAllTrace( Number2Display, ExcludeMode);\r
904 if (Status == EFI_ABORTED) {\r
905 ShellStatus = SHELL_ABORTED;\r
906 goto Done;\r
907 }\r
908 } else if (RawMode) {\r
909 Status = DumpRawTrace( Number2Display, ExcludeMode);\r
910 if (Status == EFI_ABORTED) {\r
911 ShellStatus = SHELL_ABORTED;\r
912 goto Done;\r
913 }\r
914 } else {\r
915 //------------- Begin Cooked Mode Processing\r
916 ProcessPhases ();\r
917 if ( ! SummaryMode) {\r
918 Status = ProcessHandles ( ExcludeMode);\r
196ccda0
CS
919 if (Status == EFI_ABORTED) {\r
920 ShellStatus = SHELL_ABORTED;\r
921 goto Done;\r
922 }\r
5a56c049
DB
923\r
924 Status = ProcessPeims ();\r
196ccda0
CS
925 if (Status == EFI_ABORTED) {\r
926 ShellStatus = SHELL_ABORTED;\r
927 goto Done;\r
928 }\r
5a56c049
DB
929\r
930 Status = ProcessGlobal ();\r
931 if (Status == EFI_ABORTED) {\r
932 ShellStatus = SHELL_ABORTED;\r
933 goto Done;\r
d41bc92c 934 }\r
5a56c049
DB
935\r
936 ProcessCumulative (NULL);\r
d41bc92c 937 }\r
938 } //------------- End of Cooked Mode Processing\r
939 if ( VerboseMode || SummaryMode) {\r
940 DumpStatistics();\r
941 }\r
942\r
196ccda0 943Done:\r
3751a092
CS
944 if (ParamPackage != NULL) {\r
945 ShellCommandLineFreeVarList (ParamPackage);\r
946 }\r
d41bc92c 947 SHELL_FREE_NON_NULL (StringPtr);\r
a06795c6
CS
948 if (CustomCumulativeData != NULL) {\r
949 SHELL_FREE_NON_NULL (CustomCumulativeData->Name);\r
950 }\r
951 SHELL_FREE_NON_NULL (CustomCumulativeData);\r
d41bc92c 952\r
115eae65
DB
953 SHELL_FREE_NON_NULL (mMeasurementList);\r
954\r
955 SHELL_FREE_NON_NULL (mCacheHandleGuidTable);\r
956\r
957 mMeasurementNum = 0;\r
958 mCachePairCount = 0;\r
196ccda0 959 return ShellStatus;\r
d41bc92c 960}\r
92034c4c
RN
961\r
962\r
963/**\r
964 Retrive HII package list from ImageHandle and publish to HII database.\r
965\r
966 @param ImageHandle The image handle of the process.\r
967\r
968 @return HII handle.\r
969**/\r
970EFI_HANDLE\r
971InitializeHiiPackage (\r
972 EFI_HANDLE ImageHandle\r
973 )\r
974{\r
975 EFI_STATUS Status;\r
976 EFI_HII_PACKAGE_LIST_HEADER *PackageList;\r
977 EFI_HANDLE HiiHandle;\r
978\r
979 //\r
980 // Retrieve HII package list from ImageHandle\r
981 //\r
982 Status = gBS->OpenProtocol (\r
983 ImageHandle,\r
984 &gEfiHiiPackageListProtocolGuid,\r
985 (VOID **)&PackageList,\r
986 ImageHandle,\r
987 NULL,\r
988 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
989 );\r
990 ASSERT_EFI_ERROR (Status);\r
991 if (EFI_ERROR (Status)) {\r
992 return NULL;\r
993 }\r
994\r
995 //\r
996 // Publish HII package list to HII Database.\r
997 //\r
998 Status = gHiiDatabase->NewPackageList (\r
999 gHiiDatabase,\r
1000 PackageList,\r
1001 NULL,\r
1002 &HiiHandle\r
1003 );\r
1004 ASSERT_EFI_ERROR (Status);\r
1005 if (EFI_ERROR (Status)) {\r
1006 return NULL;\r
1007 }\r
1008 return HiiHandle;\r
1009}\r