diff options
Diffstat (limited to 'ShellPkg/DynamicCommand/DpDynamicCommand/Dp.c')
| -rw-r--r-- | ShellPkg/DynamicCommand/DpDynamicCommand/Dp.c | 2062 |
1 files changed, 1031 insertions, 1031 deletions
diff --git a/ShellPkg/DynamicCommand/DpDynamicCommand/Dp.c b/ShellPkg/DynamicCommand/DpDynamicCommand/Dp.c index 98c84d2ef9..c1d194ab03 100644 --- a/ShellPkg/DynamicCommand/DpDynamicCommand/Dp.c +++ b/ShellPkg/DynamicCommand/DpDynamicCommand/Dp.c @@ -1,1031 +1,1031 @@ -/** @file
- Shell command for Displaying Performance Metrics.
-
- The Dp command reads performance data and presents it in several
- different formats depending upon the needs of the user. Both
- Trace and Measured Profiling information is processed and presented.
-
- Dp uses the "PerformanceLib" to read the measurement records.
- The "TimerLib" provides information about the timer, such as frequency,
- beginning, and ending counter values.
- Measurement records contain identifying information (Handle, Token, Module)
- and start and end time values.
- Dp uses this information to group records in different ways. It also uses
- timer information to calculate elapsed time for each measurement.
-
- Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
- (C) Copyright 2015-2016 Hewlett Packard Enterprise Development LP<BR>
- SPDX-License-Identifier: BSD-2-Clause-Patent
-**/
-
-#include "Dp.h"
-#include "Literals.h"
-#include "DpInternal.h"
-
-#pragma pack(1)
-
-typedef struct {
- EFI_ACPI_DESCRIPTION_HEADER Header;
- UINT32 Entry;
-} RSDT_TABLE;
-
-typedef struct {
- EFI_ACPI_DESCRIPTION_HEADER Header;
- UINT64 Entry;
-} XSDT_TABLE;
-
-#pragma pack()
-
-EFI_HII_HANDLE mDpHiiHandle;
-
-typedef struct {
- EFI_HANDLE Handle;
- EFI_GUID ModuleGuid;
-} HANDLE_GUID_MAP;
-
-HANDLE_GUID_MAP *mCacheHandleGuidTable;
-UINTN mCachePairCount = 0;
-
-//
-/// Module-Global Variables
-///@{
-CHAR16 mGaugeString[DP_GAUGE_STRING_LENGTH + 1];
-CHAR16 mUnicodeToken[DXE_PERFORMANCE_STRING_SIZE];
-UINT64 mInterestThreshold;
-BOOLEAN mShowId = FALSE;
-UINT8 *mBootPerformanceTable;
-UINTN mBootPerformanceTableSize;
-BOOLEAN mPeiPhase = FALSE;
-BOOLEAN mDxePhase = FALSE;
-UINT64 mResetEnd = 0;
-
-PERF_SUMMARY_DATA SummaryData = { 0 }; ///< Create the SummaryData structure and init. to ZERO.
-MEASUREMENT_RECORD *mMeasurementList = NULL;
-UINTN mMeasurementNum = 0;
-
-/// Items for which to gather cumulative statistics.
-PERF_CUM_DATA CumData[] = {
- PERF_INIT_CUM_DATA (LOAD_IMAGE_TOK),
- PERF_INIT_CUM_DATA (START_IMAGE_TOK),
- PERF_INIT_CUM_DATA (DRIVERBINDING_START_TOK),
- PERF_INIT_CUM_DATA (DRIVERBINDING_SUPPORT_TOK),
- PERF_INIT_CUM_DATA (DRIVERBINDING_STOP_TOK)
-};
-
-/// Number of items for which we are gathering cumulative statistics.
-UINT32 const NumCum = sizeof (CumData) / sizeof (PERF_CUM_DATA);
-
-STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
- { L"-v", TypeFlag }, // -v Verbose Mode
- { L"-A", TypeFlag }, // -A All, Cooked
- { L"-R", TypeFlag }, // -R RAW All
- { L"-s", TypeFlag }, // -s Summary
- { L"-x", TypeFlag }, // -x eXclude Cumulative Items
- { L"-i", TypeFlag }, // -i Display Identifier
- { L"-c", TypeValue }, // -c Display cumulative data.
- { L"-n", TypeValue }, // -n # Number of records to display for A and R
- { L"-t", TypeValue }, // -t # Threshold of interest
- { NULL, TypeMax }
-};
-
-///@}
-
-/**
- Display the trailing Verbose information.
-**/
-VOID
-DumpStatistics (
- void
- )
-{
- EFI_STRING StringPtr;
- EFI_STRING StringPtrUnknown;
-
- StringPtr = HiiGetString (mDpHiiHandle, STRING_TOKEN (STR_DP_SECTION_STATISTICS), NULL);
- StringPtrUnknown = HiiGetString (mDpHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL);
- ShellPrintHiiEx (
- -1,
- -1,
- NULL,
- STRING_TOKEN (STR_DP_SECTION_HEADER),
- mDpHiiHandle,
- (StringPtr == NULL) ? StringPtrUnknown : StringPtr
- );
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_STATS_NUMTRACE), mDpHiiHandle, SummaryData.NumTrace);
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_STATS_NUMINCOMPLETE), mDpHiiHandle, SummaryData.NumIncomplete);
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_STATS_NUMPHASES), mDpHiiHandle, SummaryData.NumSummary);
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_STATS_NUMHANDLES), mDpHiiHandle, SummaryData.NumHandles, SummaryData.NumTrace - SummaryData.NumHandles);
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_STATS_NUMPEIMS), mDpHiiHandle, SummaryData.NumPEIMs);
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_STATS_NUMGLOBALS), mDpHiiHandle, SummaryData.NumGlobal);
- SHELL_FREE_NON_NULL (StringPtr);
- SHELL_FREE_NON_NULL (StringPtrUnknown);
-}
-
-/**
- Get Boot performance table form Acpi table.
-
-**/
-EFI_STATUS
-GetBootPerformanceTable (
- )
-{
- EFI_STATUS Status;
- FIRMWARE_PERFORMANCE_TABLE *FirmwarePerformanceTable;
-
- FirmwarePerformanceTable = (FIRMWARE_PERFORMANCE_TABLE *)EfiLocateFirstAcpiTable (
- EFI_ACPI_5_0_FIRMWARE_PERFORMANCE_DATA_TABLE_SIGNATURE
- );
- if (FirmwarePerformanceTable == NULL) {
- Status = EfiGetSystemConfigurationTable (&gEdkiiFpdtExtendedFirmwarePerformanceGuid, (VOID **)&mBootPerformanceTable);
- if (EFI_ERROR (Status)) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_GET_ACPI_FPDT_FAIL), mDpHiiHandle);
- return EFI_NOT_FOUND;
- }
- } else {
- mBootPerformanceTable = (UINT8 *)(UINTN)FirmwarePerformanceTable->BootPointerRecord.BootPerformanceTablePointer;
- }
-
- mBootPerformanceTableSize = ((BOOT_PERFORMANCE_TABLE *)mBootPerformanceTable)->Header.Length;
-
- return EFI_SUCCESS;
-}
-
-/**
- Get Handle form Module Guid.
-
- @param ModuleGuid Module Guid.
- @param Handle The handle to be returned.
-
-**/
-VOID
-GetHandleFormModuleGuid (
- IN EFI_GUID *ModuleGuid,
- IN OUT EFI_HANDLE *Handle
- )
-{
- UINTN Index;
-
- if (IsZeroGuid (ModuleGuid)) {
- *Handle = NULL;
- }
-
- //
- // Try to get the Handle from the cached array.
- //
- for (Index = 0; Index < mCachePairCount; Index++) {
- if (CompareGuid (ModuleGuid, &mCacheHandleGuidTable[Index].ModuleGuid)) {
- *Handle = mCacheHandleGuidTable[Index].Handle;
- break;
- }
- }
-
- if (Index >= mCachePairCount) {
- *Handle = NULL;
- }
-}
-
-/**
-Cache the GUID and handle mapping pairs. In order to save time for searching.
-
-**/
-EFI_STATUS
-BuildCachedGuidHandleTable (
- VOID
- )
-{
- EFI_STATUS Status;
- EFI_HANDLE *HandleBuffer;
- UINTN HandleCount;
- UINTN Index;
- EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
- EFI_DRIVER_BINDING_PROTOCOL *DriverBinding;
- EFI_GUID *TempGuid;
- MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FvFilePath;
-
- Status = gBS->LocateHandleBuffer (AllHandles, NULL, NULL, &HandleCount, &HandleBuffer);
- if (EFI_ERROR (Status)) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_HANDLES_ERROR), mDpHiiHandle, Status);
- return Status;
- }
-
- mCacheHandleGuidTable = AllocateZeroPool (HandleCount * sizeof (HANDLE_GUID_MAP));
- if (mCacheHandleGuidTable == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- for (Index = 0; Index < HandleCount; Index++) {
- //
- // Try Handle as ImageHandle.
- //
- Status = gBS->HandleProtocol (
- HandleBuffer[Index],
- &gEfiLoadedImageProtocolGuid,
- (VOID **)&LoadedImage
- );
- if (EFI_ERROR (Status)) {
- //
- // Try Handle as Controller Handle
- //
- Status = gBS->OpenProtocol (
- HandleBuffer[Index],
- &gEfiDriverBindingProtocolGuid,
- (VOID **)&DriverBinding,
- NULL,
- NULL,
- EFI_OPEN_PROTOCOL_GET_PROTOCOL
- );
- if (!EFI_ERROR (Status)) {
- //
- // Get Image protocol from ImageHandle
- //
- Status = gBS->HandleProtocol (
- DriverBinding->ImageHandle,
- &gEfiLoadedImageProtocolGuid,
- (VOID **)&LoadedImage
- );
- }
- }
-
- if (!EFI_ERROR (Status) && (LoadedImage != NULL)) {
- //
- // Get Module Guid from DevicePath.
- //
- if ((LoadedImage->FilePath != NULL) &&
- (LoadedImage->FilePath->Type == MEDIA_DEVICE_PATH) &&
- (LoadedImage->FilePath->SubType == MEDIA_PIWG_FW_FILE_DP)
- )
- {
- FvFilePath = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *)LoadedImage->FilePath;
- TempGuid = &FvFilePath->FvFileName;
-
- mCacheHandleGuidTable[mCachePairCount].Handle = HandleBuffer[Index];
- CopyGuid (&mCacheHandleGuidTable[mCachePairCount].ModuleGuid, TempGuid);
- mCachePairCount++;
- }
- }
- }
-
- if (HandleBuffer != NULL) {
- FreePool (HandleBuffer);
- HandleBuffer = NULL;
- }
-
- return EFI_SUCCESS;
-}
-
-/**
- Get Measurement form Fpdt records.
-
- @param RecordHeader Pointer to the start record.
- @param IsStart Is start record or End record.
- @param Measurement Pointer to the measurement which need to be filled.
-
-**/
-VOID
-GetMeasurementInfo (
- IN EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER *RecordHeader,
- IN BOOLEAN IsStart,
- IN OUT MEASUREMENT_RECORD *Measurement
- )
-{
- VOID *ModuleGuid;
- EFI_HANDLE StartHandle;
-
- switch (RecordHeader->Type) {
- case FPDT_GUID_EVENT_TYPE:
- ModuleGuid = &(((FPDT_GUID_EVENT_RECORD *)RecordHeader)->Guid);
- Measurement->Identifier = ((UINT32)((FPDT_GUID_EVENT_RECORD *)RecordHeader)->ProgressID);
- if (IsStart) {
- Measurement->StartTimeStamp = ((FPDT_GUID_EVENT_RECORD *)RecordHeader)->Timestamp;
- } else {
- Measurement->EndTimeStamp = ((FPDT_GUID_EVENT_RECORD *)RecordHeader)->Timestamp;
- }
-
- switch (Measurement->Identifier) {
- case MODULE_START_ID:
- case MODULE_END_ID:
- if (mPeiPhase) {
- Measurement->Token = ALit_PEIM;
- Measurement->Module = ALit_PEIM;
- } else if (mDxePhase) {
- Measurement->Token = ALit_START_IMAGE;
- Measurement->Module = ALit_START_IMAGE;
- }
-
- break;
- default:
- ASSERT (FALSE);
- }
-
- if ((Measurement->Token != NULL) && (AsciiStrCmp (Measurement->Token, ALit_PEIM) == 0)) {
- Measurement->Handle = &(((FPDT_DYNAMIC_STRING_EVENT_RECORD *)RecordHeader)->Guid);
- } else {
- GetHandleFormModuleGuid (ModuleGuid, &StartHandle);
- Measurement->Handle = StartHandle;
- //
- // When no perf entry to record the PEI and DXE phase,
- // For start image, we need detect the PEIM and non PEIM here.
- //
- if (Measurement->Token == NULL) {
- if ((StartHandle == NULL) && !IsZeroGuid (ModuleGuid)) {
- Measurement->Token = ALit_PEIM;
- Measurement->Module = ALit_PEIM;
- Measurement->Handle = ModuleGuid;
- } else {
- Measurement->Token = ALit_START_IMAGE;
- Measurement->Module = ALit_START_IMAGE;
- }
- }
- }
-
- break;
-
- case FPDT_DYNAMIC_STRING_EVENT_TYPE:
- ModuleGuid = &(((FPDT_DYNAMIC_STRING_EVENT_RECORD *)RecordHeader)->Guid);
- Measurement->Identifier = ((UINT32)((FPDT_DYNAMIC_STRING_EVENT_RECORD *)RecordHeader)->ProgressID);
- if (IsStart) {
- Measurement->StartTimeStamp = ((FPDT_DYNAMIC_STRING_EVENT_RECORD *)RecordHeader)->Timestamp;
- } else {
- Measurement->EndTimeStamp = ((FPDT_DYNAMIC_STRING_EVENT_RECORD *)RecordHeader)->Timestamp;
- }
-
- switch (Measurement->Identifier) {
- case MODULE_START_ID:
- case MODULE_END_ID:
- if (mPeiPhase) {
- Measurement->Token = ALit_PEIM;
- } else if (mDxePhase) {
- Measurement->Token = ALit_START_IMAGE;
- }
-
- break;
-
- case MODULE_LOADIMAGE_START_ID:
- case MODULE_LOADIMAGE_END_ID:
- Measurement->Token = ALit_LOAD_IMAGE;
- break;
-
- case MODULE_DB_START_ID:
- case MODULE_DB_END_ID:
- Measurement->Token = ALit_DB_START;
- break;
-
- case MODULE_DB_SUPPORT_START_ID:
- case MODULE_DB_SUPPORT_END_ID:
- Measurement->Token = ALit_DB_SUPPORT;
- break;
-
- case MODULE_DB_STOP_START_ID:
- case MODULE_DB_STOP_END_ID:
- Measurement->Token = ALit_DB_STOP;
- break;
-
- default:
- Measurement->Token = ((FPDT_DYNAMIC_STRING_EVENT_RECORD *)RecordHeader)->String;
- break;
- }
-
- Measurement->Module = ((FPDT_DYNAMIC_STRING_EVENT_RECORD *)RecordHeader)->String;
-
- if ((Measurement->Token != NULL) && (AsciiStrCmp (Measurement->Token, ALit_PEIM) == 0)) {
- Measurement->Handle = &(((FPDT_DYNAMIC_STRING_EVENT_RECORD *)RecordHeader)->Guid);
- } else {
- GetHandleFormModuleGuid (ModuleGuid, &StartHandle);
- Measurement->Handle = StartHandle;
- //
- // When no perf entry to record the PEI and DXE phase,
- // For start image, we need detect the PEIM and non PEIM here.
- //
- if ((Measurement->Token == NULL) && ((Measurement->Identifier == MODULE_START_ID) || (Measurement->Identifier == MODULE_END_ID))) {
- if ((StartHandle == NULL) && !IsZeroGuid (ModuleGuid)) {
- Measurement->Token = ALit_PEIM;
- Measurement->Handle = ModuleGuid;
- } else {
- Measurement->Token = ALit_START_IMAGE;
- }
- }
- }
-
- break;
-
- case FPDT_GUID_QWORD_EVENT_TYPE:
- ModuleGuid = &(((FPDT_GUID_QWORD_EVENT_RECORD *)RecordHeader)->Guid);
- Measurement->Identifier = ((UINT32)((FPDT_GUID_QWORD_EVENT_RECORD *)RecordHeader)->ProgressID);
- if (IsStart) {
- Measurement->StartTimeStamp = ((FPDT_GUID_QWORD_EVENT_RECORD *)RecordHeader)->Timestamp;
- } else {
- Measurement->EndTimeStamp = ((FPDT_GUID_QWORD_EVENT_RECORD *)RecordHeader)->Timestamp;
- }
-
- switch (Measurement->Identifier) {
- case MODULE_DB_START_ID:
- Measurement->Token = ALit_DB_START;
- Measurement->Module = ALit_DB_START;
- break;
-
- case MODULE_DB_SUPPORT_START_ID:
- case MODULE_DB_SUPPORT_END_ID:
- Measurement->Token = ALit_DB_SUPPORT;
- Measurement->Module = ALit_DB_SUPPORT;
- break;
-
- case MODULE_DB_STOP_START_ID:
- case MODULE_DB_STOP_END_ID:
- Measurement->Token = ALit_DB_STOP;
- Measurement->Module = ALit_DB_STOP;
- break;
-
- case MODULE_LOADIMAGE_START_ID:
- case MODULE_LOADIMAGE_END_ID:
- Measurement->Token = ALit_LOAD_IMAGE;
- Measurement->Module = ALit_LOAD_IMAGE;
- break;
-
- default:
- ASSERT (FALSE);
- }
-
- GetHandleFormModuleGuid (ModuleGuid, &StartHandle);
- Measurement->Handle = StartHandle;
- break;
-
- case FPDT_GUID_QWORD_STRING_EVENT_TYPE:
- ModuleGuid = &(((FPDT_GUID_QWORD_STRING_EVENT_RECORD *)RecordHeader)->Guid);
- Measurement->Identifier = ((UINT32)((FPDT_GUID_QWORD_STRING_EVENT_RECORD *)RecordHeader)->ProgressID);
- if (IsStart) {
- Measurement->StartTimeStamp = ((FPDT_GUID_QWORD_STRING_EVENT_RECORD *)RecordHeader)->Timestamp;
- } else {
- Measurement->EndTimeStamp = ((FPDT_GUID_QWORD_STRING_EVENT_RECORD *)RecordHeader)->Timestamp;
- }
-
- //
- // Currently only "DB:Start:" end record with FPDT_GUID_QWORD_STRING_EVENT_TYPE.
- //
- switch (Measurement->Identifier) {
- case MODULE_DB_END_ID:
- Measurement->Token = ALit_DB_START;
- Measurement->Module = ALit_DB_START;
- break;
- default:
- ASSERT (FALSE);
- }
-
- GetHandleFormModuleGuid (ModuleGuid, &StartHandle);
- Measurement->Handle = StartHandle;
- break;
-
- case FPDT_DUAL_GUID_STRING_EVENT_TYPE:
- ModuleGuid = &(((FPDT_DUAL_GUID_STRING_EVENT_RECORD *)RecordHeader)->Guid1);
- Measurement->Identifier = ((UINT32)((FPDT_DUAL_GUID_STRING_EVENT_RECORD *)RecordHeader)->ProgressID);
- if (IsStart) {
- Measurement->StartTimeStamp = ((FPDT_DUAL_GUID_STRING_EVENT_RECORD *)RecordHeader)->Timestamp;
- } else {
- Measurement->EndTimeStamp = ((FPDT_DUAL_GUID_STRING_EVENT_RECORD *)RecordHeader)->Timestamp;
- }
-
- Measurement->Token = ((FPDT_DUAL_GUID_STRING_EVENT_RECORD *)RecordHeader)->String;
- Measurement->Module = ((FPDT_DUAL_GUID_STRING_EVENT_RECORD *)RecordHeader)->String;
- GetHandleFormModuleGuid (ModuleGuid, &StartHandle);
- Measurement->Handle = StartHandle;
- break;
-
- default:
- break;
- }
-}
-
-/**
- Search the start measurement in the mMeasurementList for the end measurement.
-
- @param EndMeasureMent Measurement for end record.
-
-**/
-VOID
-SearchMeasurement (
- IN MEASUREMENT_RECORD *EndMeasureMent
- )
-{
- INTN Index;
-
- for (Index = mMeasurementNum - 1; Index >= 0; Index--) {
- if (AsciiStrCmp (EndMeasureMent->Token, ALit_PEIM) == 0) {
- if ((mMeasurementList[Index].EndTimeStamp == 0) && (EndMeasureMent->Handle != NULL) && (mMeasurementList[Index].Handle != NULL) &&
- CompareGuid (mMeasurementList[Index].Handle, EndMeasureMent->Handle) &&
- (AsciiStrCmp (mMeasurementList[Index].Token, EndMeasureMent->Token) == 0) &&
- (AsciiStrCmp (mMeasurementList[Index].Module, EndMeasureMent->Module) == 0))
- {
- mMeasurementList[Index].EndTimeStamp = EndMeasureMent->EndTimeStamp;
- break;
- }
- } else if (EndMeasureMent->Identifier == PERF_CROSSMODULE_END_ID) {
- if ((mMeasurementList[Index].EndTimeStamp == 0) &&
- (AsciiStrCmp (mMeasurementList[Index].Token, EndMeasureMent->Token) == 0) &&
- (AsciiStrCmp (mMeasurementList[Index].Module, EndMeasureMent->Module) == 0) &&
- (mMeasurementList[Index].Identifier == PERF_CROSSMODULE_START_ID))
- {
- mMeasurementList[Index].EndTimeStamp = EndMeasureMent->EndTimeStamp;
- break;
- }
- } else {
- if ((mMeasurementList[Index].EndTimeStamp == 0) && (mMeasurementList[Index].Handle == EndMeasureMent->Handle) &&
- (AsciiStrCmp (mMeasurementList[Index].Token, EndMeasureMent->Token) == 0) &&
- (AsciiStrCmp (mMeasurementList[Index].Module, EndMeasureMent->Module) == 0))
- {
- mMeasurementList[Index].EndTimeStamp = EndMeasureMent->EndTimeStamp;
- break;
- }
- }
- }
-}
-
-/**
- Generate the measure record array.
-
-**/
-EFI_STATUS
-BuildMeasurementList (
- )
-{
- EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER *RecordHeader;
- UINT8 *PerformanceTablePtr;
- UINT8 *BasicBootTablePtr;
- UINT64 ResetEnd;
- UINT16 StartProgressId;
- UINTN TableLength;
- UINT8 *StartRecordEvent;
- MEASUREMENT_RECORD MeasureMent;
-
- mMeasurementList = AllocateZeroPool (mBootPerformanceTableSize);
- if (mMeasurementList == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- //
- // Update the ResetEnd which was logged at the beginning of firmware image execution
- //
- TableLength = sizeof (EFI_ACPI_5_0_FPDT_PERFORMANCE_TABLE_HEADER);
- BasicBootTablePtr = (mBootPerformanceTable + TableLength);
- ResetEnd = ((EFI_ACPI_5_0_FPDT_FIRMWARE_BASIC_BOOT_RECORD *)BasicBootTablePtr)->ResetEnd;
-
- if (ResetEnd > 0) {
- mResetEnd = ResetEnd;
- }
-
- TableLength = sizeof (BOOT_PERFORMANCE_TABLE);
- PerformanceTablePtr = (mBootPerformanceTable + TableLength);
-
- while (TableLength < mBootPerformanceTableSize) {
- RecordHeader = (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER *)PerformanceTablePtr;
- StartRecordEvent = (UINT8 *)RecordHeader;
- StartProgressId = ((FPDT_GUID_EVENT_RECORD *)StartRecordEvent)->ProgressID;
-
- //
- // 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.
- // If the record is the start record, fill the info to the measurement in the mMeasurementList.
- // If the record is the end record, find the related start measurement in the mMeasurementList and fill the EndTimeStamp.
- //
- if (StartProgressId == 0) {
- GetMeasurementInfo (RecordHeader, FALSE, &(mMeasurementList[mMeasurementNum]));
- mMeasurementNum++;
- } else if ((((StartProgressId >= PERF_EVENTSIGNAL_START_ID) && ((StartProgressId & 0x000F) == 0)) ||
- ((StartProgressId < PERF_EVENTSIGNAL_START_ID) && ((StartProgressId & 0x0001) != 0))))
- {
- //
- // Since PEIM and StartImage has same Type and ID when PCD PcdEdkiiFpdtStringRecordEnableOnly = FALSE
- // So we need to identify these two kinds of record through different phase.
- //
- if (StartProgressId == PERF_CROSSMODULE_START_ID ) {
- if (AsciiStrCmp (((FPDT_DYNAMIC_STRING_EVENT_RECORD *)StartRecordEvent)->String, ALit_PEI) == 0) {
- mPeiPhase = TRUE;
- } else if (AsciiStrCmp (((FPDT_DYNAMIC_STRING_EVENT_RECORD *)StartRecordEvent)->String, ALit_DXE) == 0) {
- mDxePhase = TRUE;
- mPeiPhase = FALSE;
- }
- }
-
- // Get measurement info form the start record to the mMeasurementList.
- GetMeasurementInfo (RecordHeader, TRUE, &(mMeasurementList[mMeasurementNum]));
- mMeasurementNum++;
- } else {
- ZeroMem (&MeasureMent, sizeof (MEASUREMENT_RECORD));
- GetMeasurementInfo (RecordHeader, FALSE, &MeasureMent);
- SearchMeasurement (&MeasureMent);
- }
-
- TableLength += RecordHeader->Length;
- PerformanceTablePtr += RecordHeader->Length;
- }
-
- return EFI_SUCCESS;
-}
-
-/**
- Initialize the cumulative data.
-
-**/
-VOID
-InitCumulativeData (
- VOID
- )
-{
- UINTN Index;
-
- for (Index = 0; Index < NumCum; ++Index) {
- CumData[Index].Count = 0;
- CumData[Index].MinDur = PERF_MAXDUR;
- CumData[Index].MaxDur = 0;
- CumData[Index].Duration = 0;
- }
-}
-
-/**
- Initialize the Summary data.
-
-**/
-VOID
-InitSummaryData (
- VOID
- )
-{
- SummaryData.NumTrace = 0;
- SummaryData.NumIncomplete = 0;
- SummaryData.NumSummary = 0;
- SummaryData.NumHandles = 0;
- SummaryData.NumPEIMs = 0;
- SummaryData.NumGlobal = 0;
-}
-
-/**
- Dump performance data.
-
- @param[in] ImageHandle The image handle.
- @param[in] SystemTable The system table.
-
- @retval SHELL_SUCCESS Command completed successfully.
- @retval SHELL_INVALID_PARAMETER Command usage error.
- @retval SHELL_ABORTED The user aborts the operation.
- @retval value Unknown error.
-**/
-SHELL_STATUS
-RunDp (
- IN EFI_HANDLE ImageHandle,
- IN EFI_SYSTEM_TABLE *SystemTable
- )
-{
- LIST_ENTRY *ParamPackage;
- CONST CHAR16 *CmdLineArg;
- EFI_STATUS Status;
-
- PERFORMANCE_PROPERTY *PerformanceProperty;
- UINTN Number2Display;
-
- EFI_STRING StringPtr;
- BOOLEAN SummaryMode;
- BOOLEAN VerboseMode;
- BOOLEAN AllMode;
- BOOLEAN RawMode;
- BOOLEAN ExcludeMode;
- BOOLEAN CumulativeMode;
- CONST CHAR16 *CustomCumulativeToken;
- PERF_CUM_DATA *CustomCumulativeData;
- UINTN NameSize;
- SHELL_STATUS ShellStatus;
- TIMER_INFO TimerInfo;
- UINT64 Intermediate;
-
- StringPtr = NULL;
- SummaryMode = FALSE;
- VerboseMode = FALSE;
- AllMode = FALSE;
- RawMode = FALSE;
- ExcludeMode = FALSE;
- CumulativeMode = FALSE;
- CustomCumulativeData = NULL;
- ShellStatus = SHELL_SUCCESS;
-
- //
- // initialize the shell lib (we must be in non-auto-init...)
- //
- Status = ShellInitialize ();
- ASSERT_EFI_ERROR (Status);
-
- //
- // Process Command Line arguments
- //
- Status = ShellCommandLineParse (ParamList, &ParamPackage, NULL, TRUE);
- if (EFI_ERROR (Status)) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_INVALID_ARG), mDpHiiHandle);
- return SHELL_INVALID_PARAMETER;
- } else if (ShellCommandLineGetCount (ParamPackage) > 1) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_TOO_MANY), mDpHiiHandle);
- return SHELL_INVALID_PARAMETER;
- }
-
- //
- // Boolean options
- //
- VerboseMode = ShellCommandLineGetFlag (ParamPackage, L"-v");
- SummaryMode = (BOOLEAN)(ShellCommandLineGetFlag (ParamPackage, L"-S") || ShellCommandLineGetFlag (ParamPackage, L"-s"));
- AllMode = ShellCommandLineGetFlag (ParamPackage, L"-A");
- RawMode = ShellCommandLineGetFlag (ParamPackage, L"-R");
- ExcludeMode = ShellCommandLineGetFlag (ParamPackage, L"-x");
- mShowId = ShellCommandLineGetFlag (ParamPackage, L"-i");
- CumulativeMode = ShellCommandLineGetFlag (ParamPackage, L"-c");
-
- if (AllMode && RawMode) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_CONFLICT_ARG), mDpHiiHandle, L"-A", L"-R");
- return SHELL_INVALID_PARAMETER;
- }
-
- // Options with Values
- if (ShellCommandLineGetFlag (ParamPackage, L"-n")) {
- CmdLineArg = ShellCommandLineGetValue (ParamPackage, L"-n");
- if (CmdLineArg == NULL) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_TOO_FEW), mDpHiiHandle);
- return SHELL_INVALID_PARAMETER;
- } else {
- if (!(RawMode || AllMode)) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_NO_RAW_ALL), mDpHiiHandle);
- return SHELL_INVALID_PARAMETER;
- }
-
- Status = ShellConvertStringToUint64 (CmdLineArg, &Intermediate, FALSE, TRUE);
- if (EFI_ERROR (Status)) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_INVALID_NUM_ARG), mDpHiiHandle, L"-n");
- return SHELL_INVALID_PARAMETER;
- } else {
- Number2Display = (UINTN)Intermediate;
- if ((Number2Display == 0) || (Number2Display > MAXIMUM_DISPLAYCOUNT)) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_INVALID_RANGE), mDpHiiHandle, L"-n", 0, MAXIMUM_DISPLAYCOUNT);
- return SHELL_INVALID_PARAMETER;
- }
- }
- }
- } else {
- Number2Display = DEFAULT_DISPLAYCOUNT;
- }
-
- if (ShellCommandLineGetFlag (ParamPackage, L"-t")) {
- CmdLineArg = ShellCommandLineGetValue (ParamPackage, L"-t");
- if (CmdLineArg == NULL) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_TOO_FEW), mDpHiiHandle);
- return SHELL_INVALID_PARAMETER;
- } else {
- Status = ShellConvertStringToUint64 (CmdLineArg, &Intermediate, FALSE, TRUE);
- if (EFI_ERROR (Status)) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_INVALID_NUM_ARG), mDpHiiHandle, L"-t");
- return SHELL_INVALID_PARAMETER;
- } else {
- mInterestThreshold = Intermediate;
- }
- }
- } else {
- mInterestThreshold = DEFAULT_THRESHOLD; // 1ms := 1,000 us
- }
-
- if (ShellCommandLineGetFlag (ParamPackage, L"-c")) {
- CustomCumulativeToken = ShellCommandLineGetValue (ParamPackage, L"-c");
- if (CustomCumulativeToken == NULL) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_TOO_FEW), mDpHiiHandle);
- return SHELL_INVALID_PARAMETER;
- } else {
- CustomCumulativeData = AllocateZeroPool (sizeof (PERF_CUM_DATA));
- if (CustomCumulativeData == NULL) {
- ShellStatus = SHELL_OUT_OF_RESOURCES;
- goto Done;
- }
-
- CustomCumulativeData->MinDur = PERF_MAXDUR;
- CustomCumulativeData->MaxDur = 0;
- CustomCumulativeData->Count = 0;
- CustomCumulativeData->Duration = 0;
- NameSize = StrLen (CustomCumulativeToken) + 1;
- CustomCumulativeData->Name = AllocateZeroPool (NameSize);
- if (CustomCumulativeData->Name == NULL) {
- ShellStatus = SHELL_OUT_OF_RESOURCES;
- goto Done;
- }
-
- UnicodeStrToAsciiStrS (CustomCumulativeToken, CustomCumulativeData->Name, NameSize);
- }
- }
-
- //
- // DP dump performance data by parsing FPDT table in ACPI table.
- // Folloing 3 steps are to get the measurement form the FPDT table.
- //
-
- //
- // 1. Get FPDT from ACPI table.
- //
- Status = GetBootPerformanceTable ();
- if (EFI_ERROR (Status)) {
- ShellStatus = Status;
- goto Done;
- }
-
- //
- // 2. Cache the ModuleGuid and hanlde mapping table.
- //
- Status = BuildCachedGuidHandleTable ();
- if (EFI_ERROR (Status)) {
- ShellStatus = Status;
- goto Done;
- }
-
- //
- // 3. Build the measurement array form the FPDT records.
- //
- Status = BuildMeasurementList ();
- if (EFI_ERROR (Status)) {
- ShellStatus = SHELL_OUT_OF_RESOURCES;
- goto Done;
- }
-
- //
- // Initialize the pre-defined cumulative data.
- //
- InitCumulativeData ();
-
- //
- // Initialize the Summary data.
- //
- InitSummaryData ();
-
- //
- // Timer specific processing
- //
- // Get the Performance counter characteristics:
- // Freq = Frequency in Hz
- // StartCount = Value loaded into the counter when it starts counting
- // EndCount = Value counter counts to before it needs to be reset
- //
- Status = EfiGetSystemConfigurationTable (&gPerformanceProtocolGuid, (VOID **)&PerformanceProperty);
- if (EFI_ERROR (Status) || (PerformanceProperty == NULL)) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PERF_PROPERTY_NOT_FOUND), mDpHiiHandle);
- goto Done;
- }
-
- TimerInfo.Frequency = (UINT32)DivU64x32 (PerformanceProperty->Frequency, 1000);
- TimerInfo.StartCount = 0;
- TimerInfo.EndCount = 0xFFFF;
- TimerInfo.CountUp = TRUE;
-
- //
- // Print header
- //
- // print DP's build version
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_BUILD_REVISION), mDpHiiHandle, DP_MAJOR_VERSION, DP_MINOR_VERSION);
-
- // print performance timer characteristics
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_KHZ), mDpHiiHandle, TimerInfo.Frequency);
-
- if (VerboseMode && !RawMode) {
- StringPtr = HiiGetString (
- mDpHiiHandle,
- (EFI_STRING_ID)(TimerInfo.CountUp ? STRING_TOKEN (STR_DP_UP) : STRING_TOKEN (STR_DP_DOWN)),
- NULL
- );
- ASSERT (StringPtr != NULL);
- // Print Timer count range and direction
- ShellPrintHiiEx (
- -1,
- -1,
- NULL,
- STRING_TOKEN (STR_DP_TIMER_PROPERTIES),
- mDpHiiHandle,
- StringPtr,
- TimerInfo.StartCount,
- TimerInfo.EndCount
- );
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_VERBOSE_THRESHOLD), mDpHiiHandle, mInterestThreshold);
- }
-
- /****************************************************************************
- **** Print Sections based on command line options
- ****
- **** Option modes have the following priority:
- **** v Verbose -- Valid in combination with any other options
- **** t Threshold -- Modifies All, Raw, and Cooked output
- **** Default is 0 for All and Raw mode
- **** Default is DEFAULT_THRESHOLD for "Cooked" mode
- **** n Number2Display Used by All and Raw mode. Otherwise ignored.
- **** A All -- R and S options are ignored
- **** R Raw -- S option is ignored
- **** s Summary -- Modifies "Cooked" output only
- **** Cooked (Default)
- ****************************************************************************/
- GatherStatistics (CustomCumulativeData);
- if (CumulativeMode) {
- ProcessCumulative (CustomCumulativeData);
- } else if (AllMode) {
- Status = DumpAllTrace (Number2Display, ExcludeMode);
- if (Status == EFI_ABORTED) {
- ShellStatus = SHELL_ABORTED;
- goto Done;
- }
- } else if (RawMode) {
- Status = DumpRawTrace (Number2Display, ExcludeMode);
- if (Status == EFI_ABORTED) {
- ShellStatus = SHELL_ABORTED;
- goto Done;
- }
- } else {
- // ------------- Begin Cooked Mode Processing
- ProcessPhases ();
- if ( !SummaryMode) {
- Status = ProcessHandles (ExcludeMode);
- if (Status == EFI_ABORTED) {
- ShellStatus = SHELL_ABORTED;
- goto Done;
- }
-
- Status = ProcessPeims ();
- if (Status == EFI_ABORTED) {
- ShellStatus = SHELL_ABORTED;
- goto Done;
- }
-
- Status = ProcessGlobal ();
- if (Status == EFI_ABORTED) {
- ShellStatus = SHELL_ABORTED;
- goto Done;
- }
-
- ProcessCumulative (NULL);
- }
- } // ------------- End of Cooked Mode Processing
-
- if ( VerboseMode || SummaryMode) {
- DumpStatistics ();
- }
-
-Done:
- if (ParamPackage != NULL) {
- ShellCommandLineFreeVarList (ParamPackage);
- }
-
- SHELL_FREE_NON_NULL (StringPtr);
- if (CustomCumulativeData != NULL) {
- SHELL_FREE_NON_NULL (CustomCumulativeData->Name);
- }
-
- SHELL_FREE_NON_NULL (CustomCumulativeData);
-
- SHELL_FREE_NON_NULL (mMeasurementList);
-
- SHELL_FREE_NON_NULL (mCacheHandleGuidTable);
-
- mMeasurementNum = 0;
- mCachePairCount = 0;
- return ShellStatus;
-}
-
-/**
- Retrieve HII package list from ImageHandle and publish to HII database.
-
- @param ImageHandle The image handle of the process.
-
- @return HII handle.
-**/
-EFI_HII_HANDLE
-InitializeHiiPackage (
- EFI_HANDLE ImageHandle
- )
-{
- EFI_STATUS Status;
- EFI_HII_PACKAGE_LIST_HEADER *PackageList;
- EFI_HII_HANDLE HiiHandle;
-
- //
- // Retrieve HII package list from ImageHandle
- //
- Status = gBS->OpenProtocol (
- ImageHandle,
- &gEfiHiiPackageListProtocolGuid,
- (VOID **)&PackageList,
- ImageHandle,
- NULL,
- EFI_OPEN_PROTOCOL_GET_PROTOCOL
- );
- ASSERT_EFI_ERROR (Status);
- if (EFI_ERROR (Status)) {
- return NULL;
- }
-
- //
- // Publish HII package list to HII Database.
- //
- Status = gHiiDatabase->NewPackageList (
- gHiiDatabase,
- PackageList,
- NULL,
- &HiiHandle
- );
- ASSERT_EFI_ERROR (Status);
- if (EFI_ERROR (Status)) {
- return NULL;
- }
-
- return HiiHandle;
-}
+/** @file + Shell command for Displaying Performance Metrics. + + The Dp command reads performance data and presents it in several + different formats depending upon the needs of the user. Both + Trace and Measured Profiling information is processed and presented. + + Dp uses the "PerformanceLib" to read the measurement records. + The "TimerLib" provides information about the timer, such as frequency, + beginning, and ending counter values. + Measurement records contain identifying information (Handle, Token, Module) + and start and end time values. + Dp uses this information to group records in different ways. It also uses + timer information to calculate elapsed time for each measurement. + + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved. + (C) Copyright 2015-2016 Hewlett Packard Enterprise Development LP<BR> + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include "Dp.h" +#include "Literals.h" +#include "DpInternal.h" + +#pragma pack(1) + +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 Entry; +} RSDT_TABLE; + +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT64 Entry; +} XSDT_TABLE; + +#pragma pack() + +EFI_HII_HANDLE mDpHiiHandle; + +typedef struct { + EFI_HANDLE Handle; + EFI_GUID ModuleGuid; +} HANDLE_GUID_MAP; + +HANDLE_GUID_MAP *mCacheHandleGuidTable; +UINTN mCachePairCount = 0; + +// +/// Module-Global Variables +///@{ +CHAR16 mGaugeString[DP_GAUGE_STRING_LENGTH + 1]; +CHAR16 mUnicodeToken[DXE_PERFORMANCE_STRING_SIZE]; +UINT64 mInterestThreshold; +BOOLEAN mShowId = FALSE; +UINT8 *mBootPerformanceTable; +UINTN mBootPerformanceTableSize; +BOOLEAN mPeiPhase = FALSE; +BOOLEAN mDxePhase = FALSE; +UINT64 mResetEnd = 0; + +PERF_SUMMARY_DATA SummaryData = { 0 }; ///< Create the SummaryData structure and init. to ZERO. +MEASUREMENT_RECORD *mMeasurementList = NULL; +UINTN mMeasurementNum = 0; + +/// Items for which to gather cumulative statistics. +PERF_CUM_DATA CumData[] = { + PERF_INIT_CUM_DATA (LOAD_IMAGE_TOK), + PERF_INIT_CUM_DATA (START_IMAGE_TOK), + PERF_INIT_CUM_DATA (DRIVERBINDING_START_TOK), + PERF_INIT_CUM_DATA (DRIVERBINDING_SUPPORT_TOK), + PERF_INIT_CUM_DATA (DRIVERBINDING_STOP_TOK) +}; + +/// Number of items for which we are gathering cumulative statistics. +UINT32 const NumCum = sizeof (CumData) / sizeof (PERF_CUM_DATA); + +STATIC CONST SHELL_PARAM_ITEM ParamList[] = { + { L"-v", TypeFlag }, // -v Verbose Mode + { L"-A", TypeFlag }, // -A All, Cooked + { L"-R", TypeFlag }, // -R RAW All + { L"-s", TypeFlag }, // -s Summary + { L"-x", TypeFlag }, // -x eXclude Cumulative Items + { L"-i", TypeFlag }, // -i Display Identifier + { L"-c", TypeValue }, // -c Display cumulative data. + { L"-n", TypeValue }, // -n # Number of records to display for A and R + { L"-t", TypeValue }, // -t # Threshold of interest + { NULL, TypeMax } +}; + +///@} + +/** + Display the trailing Verbose information. +**/ +VOID +DumpStatistics ( + void + ) +{ + EFI_STRING StringPtr; + EFI_STRING StringPtrUnknown; + + StringPtr = HiiGetString (mDpHiiHandle, STRING_TOKEN (STR_DP_SECTION_STATISTICS), NULL); + StringPtrUnknown = HiiGetString (mDpHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL); + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_DP_SECTION_HEADER), + mDpHiiHandle, + (StringPtr == NULL) ? StringPtrUnknown : StringPtr + ); + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_STATS_NUMTRACE), mDpHiiHandle, SummaryData.NumTrace); + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_STATS_NUMINCOMPLETE), mDpHiiHandle, SummaryData.NumIncomplete); + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_STATS_NUMPHASES), mDpHiiHandle, SummaryData.NumSummary); + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_STATS_NUMHANDLES), mDpHiiHandle, SummaryData.NumHandles, SummaryData.NumTrace - SummaryData.NumHandles); + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_STATS_NUMPEIMS), mDpHiiHandle, SummaryData.NumPEIMs); + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_STATS_NUMGLOBALS), mDpHiiHandle, SummaryData.NumGlobal); + SHELL_FREE_NON_NULL (StringPtr); + SHELL_FREE_NON_NULL (StringPtrUnknown); +} + +/** + Get Boot performance table form Acpi table. + +**/ +EFI_STATUS +GetBootPerformanceTable ( + ) +{ + EFI_STATUS Status; + FIRMWARE_PERFORMANCE_TABLE *FirmwarePerformanceTable; + + FirmwarePerformanceTable = (FIRMWARE_PERFORMANCE_TABLE *)EfiLocateFirstAcpiTable ( + EFI_ACPI_5_0_FIRMWARE_PERFORMANCE_DATA_TABLE_SIGNATURE + ); + if (FirmwarePerformanceTable == NULL) { + Status = EfiGetSystemConfigurationTable (&gEdkiiFpdtExtendedFirmwarePerformanceGuid, (VOID **)&mBootPerformanceTable); + if (EFI_ERROR (Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_GET_ACPI_FPDT_FAIL), mDpHiiHandle); + return EFI_NOT_FOUND; + } + } else { + mBootPerformanceTable = (UINT8 *)(UINTN)FirmwarePerformanceTable->BootPointerRecord.BootPerformanceTablePointer; + } + + mBootPerformanceTableSize = ((BOOT_PERFORMANCE_TABLE *)mBootPerformanceTable)->Header.Length; + + return EFI_SUCCESS; +} + +/** + Get Handle form Module Guid. + + @param ModuleGuid Module Guid. + @param Handle The handle to be returned. + +**/ +VOID +GetHandleFormModuleGuid ( + IN EFI_GUID *ModuleGuid, + IN OUT EFI_HANDLE *Handle + ) +{ + UINTN Index; + + if (IsZeroGuid (ModuleGuid)) { + *Handle = NULL; + } + + // + // Try to get the Handle from the cached array. + // + for (Index = 0; Index < mCachePairCount; Index++) { + if (CompareGuid (ModuleGuid, &mCacheHandleGuidTable[Index].ModuleGuid)) { + *Handle = mCacheHandleGuidTable[Index].Handle; + break; + } + } + + if (Index >= mCachePairCount) { + *Handle = NULL; + } +} + +/** +Cache the GUID and handle mapping pairs. In order to save time for searching. + +**/ +EFI_STATUS +BuildCachedGuidHandleTable ( + VOID + ) +{ + EFI_STATUS Status; + EFI_HANDLE *HandleBuffer; + UINTN HandleCount; + UINTN Index; + EFI_LOADED_IMAGE_PROTOCOL *LoadedImage; + EFI_DRIVER_BINDING_PROTOCOL *DriverBinding; + EFI_GUID *TempGuid; + MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FvFilePath; + + Status = gBS->LocateHandleBuffer (AllHandles, NULL, NULL, &HandleCount, &HandleBuffer); + if (EFI_ERROR (Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_HANDLES_ERROR), mDpHiiHandle, Status); + return Status; + } + + mCacheHandleGuidTable = AllocateZeroPool (HandleCount * sizeof (HANDLE_GUID_MAP)); + if (mCacheHandleGuidTable == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + for (Index = 0; Index < HandleCount; Index++) { + // + // Try Handle as ImageHandle. + // + Status = gBS->HandleProtocol ( + HandleBuffer[Index], + &gEfiLoadedImageProtocolGuid, + (VOID **)&LoadedImage + ); + if (EFI_ERROR (Status)) { + // + // Try Handle as Controller Handle + // + Status = gBS->OpenProtocol ( + HandleBuffer[Index], + &gEfiDriverBindingProtocolGuid, + (VOID **)&DriverBinding, + NULL, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (!EFI_ERROR (Status)) { + // + // Get Image protocol from ImageHandle + // + Status = gBS->HandleProtocol ( + DriverBinding->ImageHandle, + &gEfiLoadedImageProtocolGuid, + (VOID **)&LoadedImage + ); + } + } + + if (!EFI_ERROR (Status) && (LoadedImage != NULL)) { + // + // Get Module Guid from DevicePath. + // + if ((LoadedImage->FilePath != NULL) && + (LoadedImage->FilePath->Type == MEDIA_DEVICE_PATH) && + (LoadedImage->FilePath->SubType == MEDIA_PIWG_FW_FILE_DP) + ) + { + FvFilePath = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *)LoadedImage->FilePath; + TempGuid = &FvFilePath->FvFileName; + + mCacheHandleGuidTable[mCachePairCount].Handle = HandleBuffer[Index]; + CopyGuid (&mCacheHandleGuidTable[mCachePairCount].ModuleGuid, TempGuid); + mCachePairCount++; + } + } + } + + if (HandleBuffer != NULL) { + FreePool (HandleBuffer); + HandleBuffer = NULL; + } + + return EFI_SUCCESS; +} + +/** + Get Measurement form Fpdt records. + + @param RecordHeader Pointer to the start record. + @param IsStart Is start record or End record. + @param Measurement Pointer to the measurement which need to be filled. + +**/ +VOID +GetMeasurementInfo ( + IN EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER *RecordHeader, + IN BOOLEAN IsStart, + IN OUT MEASUREMENT_RECORD *Measurement + ) +{ + VOID *ModuleGuid; + EFI_HANDLE StartHandle; + + switch (RecordHeader->Type) { + case FPDT_GUID_EVENT_TYPE: + ModuleGuid = &(((FPDT_GUID_EVENT_RECORD *)RecordHeader)->Guid); + Measurement->Identifier = ((UINT32)((FPDT_GUID_EVENT_RECORD *)RecordHeader)->ProgressID); + if (IsStart) { + Measurement->StartTimeStamp = ((FPDT_GUID_EVENT_RECORD *)RecordHeader)->Timestamp; + } else { + Measurement->EndTimeStamp = ((FPDT_GUID_EVENT_RECORD *)RecordHeader)->Timestamp; + } + + switch (Measurement->Identifier) { + case MODULE_START_ID: + case MODULE_END_ID: + if (mPeiPhase) { + Measurement->Token = ALit_PEIM; + Measurement->Module = ALit_PEIM; + } else if (mDxePhase) { + Measurement->Token = ALit_START_IMAGE; + Measurement->Module = ALit_START_IMAGE; + } + + break; + default: + ASSERT (FALSE); + } + + if ((Measurement->Token != NULL) && (AsciiStrCmp (Measurement->Token, ALit_PEIM) == 0)) { + Measurement->Handle = &(((FPDT_DYNAMIC_STRING_EVENT_RECORD *)RecordHeader)->Guid); + } else { + GetHandleFormModuleGuid (ModuleGuid, &StartHandle); + Measurement->Handle = StartHandle; + // + // When no perf entry to record the PEI and DXE phase, + // For start image, we need detect the PEIM and non PEIM here. + // + if (Measurement->Token == NULL) { + if ((StartHandle == NULL) && !IsZeroGuid (ModuleGuid)) { + Measurement->Token = ALit_PEIM; + Measurement->Module = ALit_PEIM; + Measurement->Handle = ModuleGuid; + } else { + Measurement->Token = ALit_START_IMAGE; + Measurement->Module = ALit_START_IMAGE; + } + } + } + + break; + + case FPDT_DYNAMIC_STRING_EVENT_TYPE: + ModuleGuid = &(((FPDT_DYNAMIC_STRING_EVENT_RECORD *)RecordHeader)->Guid); + Measurement->Identifier = ((UINT32)((FPDT_DYNAMIC_STRING_EVENT_RECORD *)RecordHeader)->ProgressID); + if (IsStart) { + Measurement->StartTimeStamp = ((FPDT_DYNAMIC_STRING_EVENT_RECORD *)RecordHeader)->Timestamp; + } else { + Measurement->EndTimeStamp = ((FPDT_DYNAMIC_STRING_EVENT_RECORD *)RecordHeader)->Timestamp; + } + + switch (Measurement->Identifier) { + case MODULE_START_ID: + case MODULE_END_ID: + if (mPeiPhase) { + Measurement->Token = ALit_PEIM; + } else if (mDxePhase) { + Measurement->Token = ALit_START_IMAGE; + } + + break; + + case MODULE_LOADIMAGE_START_ID: + case MODULE_LOADIMAGE_END_ID: + Measurement->Token = ALit_LOAD_IMAGE; + break; + + case MODULE_DB_START_ID: + case MODULE_DB_END_ID: + Measurement->Token = ALit_DB_START; + break; + + case MODULE_DB_SUPPORT_START_ID: + case MODULE_DB_SUPPORT_END_ID: + Measurement->Token = ALit_DB_SUPPORT; + break; + + case MODULE_DB_STOP_START_ID: + case MODULE_DB_STOP_END_ID: + Measurement->Token = ALit_DB_STOP; + break; + + default: + Measurement->Token = ((FPDT_DYNAMIC_STRING_EVENT_RECORD *)RecordHeader)->String; + break; + } + + Measurement->Module = ((FPDT_DYNAMIC_STRING_EVENT_RECORD *)RecordHeader)->String; + + if ((Measurement->Token != NULL) && (AsciiStrCmp (Measurement->Token, ALit_PEIM) == 0)) { + Measurement->Handle = &(((FPDT_DYNAMIC_STRING_EVENT_RECORD *)RecordHeader)->Guid); + } else { + GetHandleFormModuleGuid (ModuleGuid, &StartHandle); + Measurement->Handle = StartHandle; + // + // When no perf entry to record the PEI and DXE phase, + // For start image, we need detect the PEIM and non PEIM here. + // + if ((Measurement->Token == NULL) && ((Measurement->Identifier == MODULE_START_ID) || (Measurement->Identifier == MODULE_END_ID))) { + if ((StartHandle == NULL) && !IsZeroGuid (ModuleGuid)) { + Measurement->Token = ALit_PEIM; + Measurement->Handle = ModuleGuid; + } else { + Measurement->Token = ALit_START_IMAGE; + } + } + } + + break; + + case FPDT_GUID_QWORD_EVENT_TYPE: + ModuleGuid = &(((FPDT_GUID_QWORD_EVENT_RECORD *)RecordHeader)->Guid); + Measurement->Identifier = ((UINT32)((FPDT_GUID_QWORD_EVENT_RECORD *)RecordHeader)->ProgressID); + if (IsStart) { + Measurement->StartTimeStamp = ((FPDT_GUID_QWORD_EVENT_RECORD *)RecordHeader)->Timestamp; + } else { + Measurement->EndTimeStamp = ((FPDT_GUID_QWORD_EVENT_RECORD *)RecordHeader)->Timestamp; + } + + switch (Measurement->Identifier) { + case MODULE_DB_START_ID: + Measurement->Token = ALit_DB_START; + Measurement->Module = ALit_DB_START; + break; + + case MODULE_DB_SUPPORT_START_ID: + case MODULE_DB_SUPPORT_END_ID: + Measurement->Token = ALit_DB_SUPPORT; + Measurement->Module = ALit_DB_SUPPORT; + break; + + case MODULE_DB_STOP_START_ID: + case MODULE_DB_STOP_END_ID: + Measurement->Token = ALit_DB_STOP; + Measurement->Module = ALit_DB_STOP; + break; + + case MODULE_LOADIMAGE_START_ID: + case MODULE_LOADIMAGE_END_ID: + Measurement->Token = ALit_LOAD_IMAGE; + Measurement->Module = ALit_LOAD_IMAGE; + break; + + default: + ASSERT (FALSE); + } + + GetHandleFormModuleGuid (ModuleGuid, &StartHandle); + Measurement->Handle = StartHandle; + break; + + case FPDT_GUID_QWORD_STRING_EVENT_TYPE: + ModuleGuid = &(((FPDT_GUID_QWORD_STRING_EVENT_RECORD *)RecordHeader)->Guid); + Measurement->Identifier = ((UINT32)((FPDT_GUID_QWORD_STRING_EVENT_RECORD *)RecordHeader)->ProgressID); + if (IsStart) { + Measurement->StartTimeStamp = ((FPDT_GUID_QWORD_STRING_EVENT_RECORD *)RecordHeader)->Timestamp; + } else { + Measurement->EndTimeStamp = ((FPDT_GUID_QWORD_STRING_EVENT_RECORD *)RecordHeader)->Timestamp; + } + + // + // Currently only "DB:Start:" end record with FPDT_GUID_QWORD_STRING_EVENT_TYPE. + // + switch (Measurement->Identifier) { + case MODULE_DB_END_ID: + Measurement->Token = ALit_DB_START; + Measurement->Module = ALit_DB_START; + break; + default: + ASSERT (FALSE); + } + + GetHandleFormModuleGuid (ModuleGuid, &StartHandle); + Measurement->Handle = StartHandle; + break; + + case FPDT_DUAL_GUID_STRING_EVENT_TYPE: + ModuleGuid = &(((FPDT_DUAL_GUID_STRING_EVENT_RECORD *)RecordHeader)->Guid1); + Measurement->Identifier = ((UINT32)((FPDT_DUAL_GUID_STRING_EVENT_RECORD *)RecordHeader)->ProgressID); + if (IsStart) { + Measurement->StartTimeStamp = ((FPDT_DUAL_GUID_STRING_EVENT_RECORD *)RecordHeader)->Timestamp; + } else { + Measurement->EndTimeStamp = ((FPDT_DUAL_GUID_STRING_EVENT_RECORD *)RecordHeader)->Timestamp; + } + + Measurement->Token = ((FPDT_DUAL_GUID_STRING_EVENT_RECORD *)RecordHeader)->String; + Measurement->Module = ((FPDT_DUAL_GUID_STRING_EVENT_RECORD *)RecordHeader)->String; + GetHandleFormModuleGuid (ModuleGuid, &StartHandle); + Measurement->Handle = StartHandle; + break; + + default: + break; + } +} + +/** + Search the start measurement in the mMeasurementList for the end measurement. + + @param EndMeasureMent Measurement for end record. + +**/ +VOID +SearchMeasurement ( + IN MEASUREMENT_RECORD *EndMeasureMent + ) +{ + INTN Index; + + for (Index = mMeasurementNum - 1; Index >= 0; Index--) { + if (AsciiStrCmp (EndMeasureMent->Token, ALit_PEIM) == 0) { + if ((mMeasurementList[Index].EndTimeStamp == 0) && (EndMeasureMent->Handle != NULL) && (mMeasurementList[Index].Handle != NULL) && + CompareGuid (mMeasurementList[Index].Handle, EndMeasureMent->Handle) && + (AsciiStrCmp (mMeasurementList[Index].Token, EndMeasureMent->Token) == 0) && + (AsciiStrCmp (mMeasurementList[Index].Module, EndMeasureMent->Module) == 0)) + { + mMeasurementList[Index].EndTimeStamp = EndMeasureMent->EndTimeStamp; + break; + } + } else if (EndMeasureMent->Identifier == PERF_CROSSMODULE_END_ID) { + if ((mMeasurementList[Index].EndTimeStamp == 0) && + (AsciiStrCmp (mMeasurementList[Index].Token, EndMeasureMent->Token) == 0) && + (AsciiStrCmp (mMeasurementList[Index].Module, EndMeasureMent->Module) == 0) && + (mMeasurementList[Index].Identifier == PERF_CROSSMODULE_START_ID)) + { + mMeasurementList[Index].EndTimeStamp = EndMeasureMent->EndTimeStamp; + break; + } + } else { + if ((mMeasurementList[Index].EndTimeStamp == 0) && (mMeasurementList[Index].Handle == EndMeasureMent->Handle) && + (AsciiStrCmp (mMeasurementList[Index].Token, EndMeasureMent->Token) == 0) && + (AsciiStrCmp (mMeasurementList[Index].Module, EndMeasureMent->Module) == 0)) + { + mMeasurementList[Index].EndTimeStamp = EndMeasureMent->EndTimeStamp; + break; + } + } + } +} + +/** + Generate the measure record array. + +**/ +EFI_STATUS +BuildMeasurementList ( + ) +{ + EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER *RecordHeader; + UINT8 *PerformanceTablePtr; + UINT8 *BasicBootTablePtr; + UINT64 ResetEnd; + UINT16 StartProgressId; + UINTN TableLength; + UINT8 *StartRecordEvent; + MEASUREMENT_RECORD MeasureMent; + + mMeasurementList = AllocateZeroPool (mBootPerformanceTableSize); + if (mMeasurementList == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Update the ResetEnd which was logged at the beginning of firmware image execution + // + TableLength = sizeof (EFI_ACPI_5_0_FPDT_PERFORMANCE_TABLE_HEADER); + BasicBootTablePtr = (mBootPerformanceTable + TableLength); + ResetEnd = ((EFI_ACPI_5_0_FPDT_FIRMWARE_BASIC_BOOT_RECORD *)BasicBootTablePtr)->ResetEnd; + + if (ResetEnd > 0) { + mResetEnd = ResetEnd; + } + + TableLength = sizeof (BOOT_PERFORMANCE_TABLE); + PerformanceTablePtr = (mBootPerformanceTable + TableLength); + + while (TableLength < mBootPerformanceTableSize) { + RecordHeader = (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER *)PerformanceTablePtr; + StartRecordEvent = (UINT8 *)RecordHeader; + StartProgressId = ((FPDT_GUID_EVENT_RECORD *)StartRecordEvent)->ProgressID; + + // + // 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. + // If the record is the start record, fill the info to the measurement in the mMeasurementList. + // If the record is the end record, find the related start measurement in the mMeasurementList and fill the EndTimeStamp. + // + if (StartProgressId == 0) { + GetMeasurementInfo (RecordHeader, FALSE, &(mMeasurementList[mMeasurementNum])); + mMeasurementNum++; + } else if ((((StartProgressId >= PERF_EVENTSIGNAL_START_ID) && ((StartProgressId & 0x000F) == 0)) || + ((StartProgressId < PERF_EVENTSIGNAL_START_ID) && ((StartProgressId & 0x0001) != 0)))) + { + // + // Since PEIM and StartImage has same Type and ID when PCD PcdEdkiiFpdtStringRecordEnableOnly = FALSE + // So we need to identify these two kinds of record through different phase. + // + if (StartProgressId == PERF_CROSSMODULE_START_ID ) { + if (AsciiStrCmp (((FPDT_DYNAMIC_STRING_EVENT_RECORD *)StartRecordEvent)->String, ALit_PEI) == 0) { + mPeiPhase = TRUE; + } else if (AsciiStrCmp (((FPDT_DYNAMIC_STRING_EVENT_RECORD *)StartRecordEvent)->String, ALit_DXE) == 0) { + mDxePhase = TRUE; + mPeiPhase = FALSE; + } + } + + // Get measurement info form the start record to the mMeasurementList. + GetMeasurementInfo (RecordHeader, TRUE, &(mMeasurementList[mMeasurementNum])); + mMeasurementNum++; + } else { + ZeroMem (&MeasureMent, sizeof (MEASUREMENT_RECORD)); + GetMeasurementInfo (RecordHeader, FALSE, &MeasureMent); + SearchMeasurement (&MeasureMent); + } + + TableLength += RecordHeader->Length; + PerformanceTablePtr += RecordHeader->Length; + } + + return EFI_SUCCESS; +} + +/** + Initialize the cumulative data. + +**/ +VOID +InitCumulativeData ( + VOID + ) +{ + UINTN Index; + + for (Index = 0; Index < NumCum; ++Index) { + CumData[Index].Count = 0; + CumData[Index].MinDur = PERF_MAXDUR; + CumData[Index].MaxDur = 0; + CumData[Index].Duration = 0; + } +} + +/** + Initialize the Summary data. + +**/ +VOID +InitSummaryData ( + VOID + ) +{ + SummaryData.NumTrace = 0; + SummaryData.NumIncomplete = 0; + SummaryData.NumSummary = 0; + SummaryData.NumHandles = 0; + SummaryData.NumPEIMs = 0; + SummaryData.NumGlobal = 0; +} + +/** + Dump performance data. + + @param[in] ImageHandle The image handle. + @param[in] SystemTable The system table. + + @retval SHELL_SUCCESS Command completed successfully. + @retval SHELL_INVALID_PARAMETER Command usage error. + @retval SHELL_ABORTED The user aborts the operation. + @retval value Unknown error. +**/ +SHELL_STATUS +RunDp ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + LIST_ENTRY *ParamPackage; + CONST CHAR16 *CmdLineArg; + EFI_STATUS Status; + + PERFORMANCE_PROPERTY *PerformanceProperty; + UINTN Number2Display; + + EFI_STRING StringPtr; + BOOLEAN SummaryMode; + BOOLEAN VerboseMode; + BOOLEAN AllMode; + BOOLEAN RawMode; + BOOLEAN ExcludeMode; + BOOLEAN CumulativeMode; + CONST CHAR16 *CustomCumulativeToken; + PERF_CUM_DATA *CustomCumulativeData; + UINTN NameSize; + SHELL_STATUS ShellStatus; + TIMER_INFO TimerInfo; + UINT64 Intermediate; + + StringPtr = NULL; + SummaryMode = FALSE; + VerboseMode = FALSE; + AllMode = FALSE; + RawMode = FALSE; + ExcludeMode = FALSE; + CumulativeMode = FALSE; + CustomCumulativeData = NULL; + ShellStatus = SHELL_SUCCESS; + + // + // initialize the shell lib (we must be in non-auto-init...) + // + Status = ShellInitialize (); + ASSERT_EFI_ERROR (Status); + + // + // Process Command Line arguments + // + Status = ShellCommandLineParse (ParamList, &ParamPackage, NULL, TRUE); + if (EFI_ERROR (Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_INVALID_ARG), mDpHiiHandle); + return SHELL_INVALID_PARAMETER; + } else if (ShellCommandLineGetCount (ParamPackage) > 1) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_TOO_MANY), mDpHiiHandle); + return SHELL_INVALID_PARAMETER; + } + + // + // Boolean options + // + VerboseMode = ShellCommandLineGetFlag (ParamPackage, L"-v"); + SummaryMode = (BOOLEAN)(ShellCommandLineGetFlag (ParamPackage, L"-S") || ShellCommandLineGetFlag (ParamPackage, L"-s")); + AllMode = ShellCommandLineGetFlag (ParamPackage, L"-A"); + RawMode = ShellCommandLineGetFlag (ParamPackage, L"-R"); + ExcludeMode = ShellCommandLineGetFlag (ParamPackage, L"-x"); + mShowId = ShellCommandLineGetFlag (ParamPackage, L"-i"); + CumulativeMode = ShellCommandLineGetFlag (ParamPackage, L"-c"); + + if (AllMode && RawMode) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_CONFLICT_ARG), mDpHiiHandle, L"-A", L"-R"); + return SHELL_INVALID_PARAMETER; + } + + // Options with Values + if (ShellCommandLineGetFlag (ParamPackage, L"-n")) { + CmdLineArg = ShellCommandLineGetValue (ParamPackage, L"-n"); + if (CmdLineArg == NULL) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_TOO_FEW), mDpHiiHandle); + return SHELL_INVALID_PARAMETER; + } else { + if (!(RawMode || AllMode)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_NO_RAW_ALL), mDpHiiHandle); + return SHELL_INVALID_PARAMETER; + } + + Status = ShellConvertStringToUint64 (CmdLineArg, &Intermediate, FALSE, TRUE); + if (EFI_ERROR (Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_INVALID_NUM_ARG), mDpHiiHandle, L"-n"); + return SHELL_INVALID_PARAMETER; + } else { + Number2Display = (UINTN)Intermediate; + if ((Number2Display == 0) || (Number2Display > MAXIMUM_DISPLAYCOUNT)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_INVALID_RANGE), mDpHiiHandle, L"-n", 0, MAXIMUM_DISPLAYCOUNT); + return SHELL_INVALID_PARAMETER; + } + } + } + } else { + Number2Display = DEFAULT_DISPLAYCOUNT; + } + + if (ShellCommandLineGetFlag (ParamPackage, L"-t")) { + CmdLineArg = ShellCommandLineGetValue (ParamPackage, L"-t"); + if (CmdLineArg == NULL) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_TOO_FEW), mDpHiiHandle); + return SHELL_INVALID_PARAMETER; + } else { + Status = ShellConvertStringToUint64 (CmdLineArg, &Intermediate, FALSE, TRUE); + if (EFI_ERROR (Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_INVALID_NUM_ARG), mDpHiiHandle, L"-t"); + return SHELL_INVALID_PARAMETER; + } else { + mInterestThreshold = Intermediate; + } + } + } else { + mInterestThreshold = DEFAULT_THRESHOLD; // 1ms := 1,000 us + } + + if (ShellCommandLineGetFlag (ParamPackage, L"-c")) { + CustomCumulativeToken = ShellCommandLineGetValue (ParamPackage, L"-c"); + if (CustomCumulativeToken == NULL) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_TOO_FEW), mDpHiiHandle); + return SHELL_INVALID_PARAMETER; + } else { + CustomCumulativeData = AllocateZeroPool (sizeof (PERF_CUM_DATA)); + if (CustomCumulativeData == NULL) { + ShellStatus = SHELL_OUT_OF_RESOURCES; + goto Done; + } + + CustomCumulativeData->MinDur = PERF_MAXDUR; + CustomCumulativeData->MaxDur = 0; + CustomCumulativeData->Count = 0; + CustomCumulativeData->Duration = 0; + NameSize = StrLen (CustomCumulativeToken) + 1; + CustomCumulativeData->Name = AllocateZeroPool (NameSize); + if (CustomCumulativeData->Name == NULL) { + ShellStatus = SHELL_OUT_OF_RESOURCES; + goto Done; + } + + UnicodeStrToAsciiStrS (CustomCumulativeToken, CustomCumulativeData->Name, NameSize); + } + } + + // + // DP dump performance data by parsing FPDT table in ACPI table. + // Folloing 3 steps are to get the measurement form the FPDT table. + // + + // + // 1. Get FPDT from ACPI table. + // + Status = GetBootPerformanceTable (); + if (EFI_ERROR (Status)) { + ShellStatus = Status; + goto Done; + } + + // + // 2. Cache the ModuleGuid and hanlde mapping table. + // + Status = BuildCachedGuidHandleTable (); + if (EFI_ERROR (Status)) { + ShellStatus = Status; + goto Done; + } + + // + // 3. Build the measurement array form the FPDT records. + // + Status = BuildMeasurementList (); + if (EFI_ERROR (Status)) { + ShellStatus = SHELL_OUT_OF_RESOURCES; + goto Done; + } + + // + // Initialize the pre-defined cumulative data. + // + InitCumulativeData (); + + // + // Initialize the Summary data. + // + InitSummaryData (); + + // + // Timer specific processing + // + // Get the Performance counter characteristics: + // Freq = Frequency in Hz + // StartCount = Value loaded into the counter when it starts counting + // EndCount = Value counter counts to before it needs to be reset + // + Status = EfiGetSystemConfigurationTable (&gPerformanceProtocolGuid, (VOID **)&PerformanceProperty); + if (EFI_ERROR (Status) || (PerformanceProperty == NULL)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PERF_PROPERTY_NOT_FOUND), mDpHiiHandle); + goto Done; + } + + TimerInfo.Frequency = (UINT32)DivU64x32 (PerformanceProperty->Frequency, 1000); + TimerInfo.StartCount = 0; + TimerInfo.EndCount = 0xFFFF; + TimerInfo.CountUp = TRUE; + + // + // Print header + // + // print DP's build version + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_BUILD_REVISION), mDpHiiHandle, DP_MAJOR_VERSION, DP_MINOR_VERSION); + + // print performance timer characteristics + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_KHZ), mDpHiiHandle, TimerInfo.Frequency); + + if (VerboseMode && !RawMode) { + StringPtr = HiiGetString ( + mDpHiiHandle, + (EFI_STRING_ID)(TimerInfo.CountUp ? STRING_TOKEN (STR_DP_UP) : STRING_TOKEN (STR_DP_DOWN)), + NULL + ); + ASSERT (StringPtr != NULL); + // Print Timer count range and direction + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_DP_TIMER_PROPERTIES), + mDpHiiHandle, + StringPtr, + TimerInfo.StartCount, + TimerInfo.EndCount + ); + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_VERBOSE_THRESHOLD), mDpHiiHandle, mInterestThreshold); + } + + /**************************************************************************** + **** Print Sections based on command line options + **** + **** Option modes have the following priority: + **** v Verbose -- Valid in combination with any other options + **** t Threshold -- Modifies All, Raw, and Cooked output + **** Default is 0 for All and Raw mode + **** Default is DEFAULT_THRESHOLD for "Cooked" mode + **** n Number2Display Used by All and Raw mode. Otherwise ignored. + **** A All -- R and S options are ignored + **** R Raw -- S option is ignored + **** s Summary -- Modifies "Cooked" output only + **** Cooked (Default) + ****************************************************************************/ + GatherStatistics (CustomCumulativeData); + if (CumulativeMode) { + ProcessCumulative (CustomCumulativeData); + } else if (AllMode) { + Status = DumpAllTrace (Number2Display, ExcludeMode); + if (Status == EFI_ABORTED) { + ShellStatus = SHELL_ABORTED; + goto Done; + } + } else if (RawMode) { + Status = DumpRawTrace (Number2Display, ExcludeMode); + if (Status == EFI_ABORTED) { + ShellStatus = SHELL_ABORTED; + goto Done; + } + } else { + // ------------- Begin Cooked Mode Processing + ProcessPhases (); + if ( !SummaryMode) { + Status = ProcessHandles (ExcludeMode); + if (Status == EFI_ABORTED) { + ShellStatus = SHELL_ABORTED; + goto Done; + } + + Status = ProcessPeims (); + if (Status == EFI_ABORTED) { + ShellStatus = SHELL_ABORTED; + goto Done; + } + + Status = ProcessGlobal (); + if (Status == EFI_ABORTED) { + ShellStatus = SHELL_ABORTED; + goto Done; + } + + ProcessCumulative (NULL); + } + } // ------------- End of Cooked Mode Processing + + if ( VerboseMode || SummaryMode) { + DumpStatistics (); + } + +Done: + if (ParamPackage != NULL) { + ShellCommandLineFreeVarList (ParamPackage); + } + + SHELL_FREE_NON_NULL (StringPtr); + if (CustomCumulativeData != NULL) { + SHELL_FREE_NON_NULL (CustomCumulativeData->Name); + } + + SHELL_FREE_NON_NULL (CustomCumulativeData); + + SHELL_FREE_NON_NULL (mMeasurementList); + + SHELL_FREE_NON_NULL (mCacheHandleGuidTable); + + mMeasurementNum = 0; + mCachePairCount = 0; + return ShellStatus; +} + +/** + Retrieve HII package list from ImageHandle and publish to HII database. + + @param ImageHandle The image handle of the process. + + @return HII handle. +**/ +EFI_HII_HANDLE +InitializeHiiPackage ( + EFI_HANDLE ImageHandle + ) +{ + EFI_STATUS Status; + EFI_HII_PACKAGE_LIST_HEADER *PackageList; + EFI_HII_HANDLE HiiHandle; + + // + // Retrieve HII package list from ImageHandle + // + Status = gBS->OpenProtocol ( + ImageHandle, + &gEfiHiiPackageListProtocolGuid, + (VOID **)&PackageList, + ImageHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + ASSERT_EFI_ERROR (Status); + if (EFI_ERROR (Status)) { + return NULL; + } + + // + // Publish HII package list to HII Database. + // + Status = gHiiDatabase->NewPackageList ( + gHiiDatabase, + PackageList, + NULL, + &HiiHandle + ); + ASSERT_EFI_ERROR (Status); + if (EFI_ERROR (Status)) { + return NULL; + } + + return HiiHandle; +} |
