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