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