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