VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/FirmwareNew/ShellPkg/DynamicCommand/DpDynamicCommand/Dp.c

Last change on this file was 105670, checked in by vboxsync, 9 months ago

Devices/EFI/FirmwareNew: Merge edk2-stable-202405 and make it build on aarch64, bugref:4643

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

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette