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