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