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