diff options
Diffstat (limited to 'src/VBox/Devices/EFI/Firmware/ShellPkg/DynamicCommand/DpDynamicCommand')
12 files changed, 3227 insertions, 0 deletions
diff --git a/src/VBox/Devices/EFI/Firmware/ShellPkg/DynamicCommand/DpDynamicCommand/Dp.c b/src/VBox/Devices/EFI/Firmware/ShellPkg/DynamicCommand/DpDynamicCommand/Dp.c new file mode 100644 index 00000000..8ebe5183 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/ShellPkg/DynamicCommand/DpDynamicCommand/Dp.c @@ -0,0 +1,966 @@ +/** @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; + +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 ( + ) +{ + FIRMWARE_PERFORMANCE_TABLE *FirmwarePerformanceTable; + + FirmwarePerformanceTable = (FIRMWARE_PERFORMANCE_TABLE *) EfiLocateFirstAcpiTable ( + EFI_ACPI_5_0_FIRMWARE_PERFORMANCE_DATA_TABLE_SIGNATURE + ); + if (FirmwarePerformanceTable == NULL) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_GET_ACPI_FPDT_FAIL), mDpHiiHandle); + return EFI_NOT_FOUND; + } + + 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; + UINT16 StartProgressId; + UINTN TableLength; + UINT8 *StartRecordEvent; + MEASUREMENT_RECORD MeasureMent; + + mMeasurementList = AllocateZeroPool (mBootPerformanceTableSize); + if (mMeasurementList == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + 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; +} diff --git a/src/VBox/Devices/EFI/Firmware/ShellPkg/DynamicCommand/DpDynamicCommand/Dp.h b/src/VBox/Devices/EFI/Firmware/ShellPkg/DynamicCommand/DpDynamicCommand/Dp.h new file mode 100644 index 00000000..ca6bd2f4 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/ShellPkg/DynamicCommand/DpDynamicCommand/Dp.h @@ -0,0 +1,140 @@ +/** @file + Header file for 'dp' command functions. + + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved. + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _DP_H_ +#define _DP_H_ + + +#include <Uefi.h> + +#include <Guid/Performance.h> +#include <Guid/ExtendedFirmwarePerformance.h> +#include <Guid/FirmwarePerformance.h> + +#include <Protocol/HiiPackageList.h> +#include <Protocol/DevicePath.h> +#include <Protocol/LoadedImage.h> +#include <Protocol/UnicodeCollation.h> + +#include <Library/BaseLib.h> +#include <Library/BaseMemoryLib.h> +#include <Library/DebugLib.h> +#include <Library/MemoryAllocationLib.h> +#include <Library/ShellLib.h> +#include <Library/UefiLib.h> +#include <Library/UefiRuntimeServicesTableLib.h> +#include <Library/UefiBootServicesTableLib.h> +#include <Library/PcdLib.h> +#include <Library/SortLib.h> +#include <Library/HiiLib.h> +#include <Library/FileHandleLib.h> +#include <Library/UefiHiiServicesLib.h> +#include <Library/PerformanceLib.h> + +extern EFI_HII_HANDLE mDpHiiHandle; + +#define DP_MAJOR_VERSION 2 +#define DP_MINOR_VERSION 5 + +/** + * The value assigned to DP_DEBUG controls which debug output + * is generated. Set it to ZERO to disable. +**/ +#define DP_DEBUG 0 + +#define DEFAULT_THRESHOLD 1000 ///< One millisecond. +#define DEFAULT_DISPLAYCOUNT 50 +#define MAXIMUM_DISPLAYCOUNT 999999 ///< Arbitrary maximum reasonable number. + +#define PERF_MAXDUR 0xFFFFFFFFFFFFFFFFULL + +/// Determine whether 0 <= C < L. If L == 0, return true regardless of C. +#define WITHIN_LIMIT( C, L) ( ((L) == 0) || ((C) < (L)) ) + +/// Structure for storing Timer specific information. +typedef struct { + UINT64 StartCount; ///< Value timer is initialized with. + UINT64 EndCount; ///< Value timer has just before it wraps. + UINT32 Frequency; ///< Timer count frequency in KHz. + BOOLEAN CountUp; ///< TRUE if the counter counts up. +} TIMER_INFO; + +/** Initialize one PERF_CUM_DATA structure instance for token t. + * + * This parameterized macro takes a single argument, t, which is expected + * to resolve to a pointer to an ASCII string literal. This parameter may + * take any one of the following forms: + * - PERF_INIT_CUM_DATA("Token") A string literal + * - PERF_INIT_CUM_DATA(pointer) A pointer -- CHAR8 *pointer; + * - PERF_INIT_CUM_DATA(array) Address of an array -- CHAR8 array[N]; +**/ +#define PERF_INIT_CUM_DATA(t) { 0ULL, PERF_MAXDUR, 0ULL, (t), 0U } + +typedef struct { + UINT64 Duration; ///< Cumulative duration for this item. + UINT64 MinDur; ///< Smallest duration encountered. + UINT64 MaxDur; ///< Largest duration encountered. + CHAR8 *Name; ///< ASCII name of this item. + UINT32 Count; ///< Total number of measurements accumulated. +} PERF_CUM_DATA; + +typedef struct { + UINT32 NumTrace; ///< Number of recorded TRACE performance measurements. + UINT32 NumIncomplete; ///< Number of measurements with no END value. + UINT32 NumSummary; ///< Number of summary section measurements. + UINT32 NumHandles; ///< Number of measurements with handles. + UINT32 NumPEIMs; ///< Number of measurements of PEIMs. + UINT32 NumGlobal; ///< Number of measurements with END value and NULL handle. +} PERF_SUMMARY_DATA; + +typedef struct { + CONST VOID *Handle; + CONST CHAR8 *Token; ///< Measured token string name. + CONST CHAR8 *Module; ///< Module string name. + UINT64 StartTimeStamp; ///< Start time point. + UINT64 EndTimeStamp; ///< End time point. + UINT32 Identifier; ///< Identifier. +} MEASUREMENT_RECORD; + +typedef struct { + CHAR8 *Name; ///< Measured token string name. + UINT64 CumulativeTime; ///< Accumulated Elapsed Time. + UINT64 MinTime; ///< Minimum Elapsed Time. + UINT64 MaxTime; ///< Maximum Elapsed Time. + UINT32 Count; ///< Number of measurements accumulated. +} PROFILE_RECORD; + +/** + 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 + ); + +/** + 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 + ); +#endif // _DP_H_ diff --git a/src/VBox/Devices/EFI/Firmware/ShellPkg/DynamicCommand/DpDynamicCommand/Dp.uni b/src/VBox/Devices/EFI/Firmware/ShellPkg/DynamicCommand/DpDynamicCommand/Dp.uni new file mode 100644 index 00000000..8d870057 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/ShellPkg/DynamicCommand/DpDynamicCommand/Dp.uni @@ -0,0 +1,128 @@ +// *++
+//
+// (C) Copyright 2014-2015 Hewlett-Packard Development Company, L.P.<BR>
+// Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
+// (C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+//
+// Module Name:
+//
+// DpStrings.uni
+//
+// Abstract:
+//
+// String definitions for the Shell dp command
+//
+// Revision History:
+//
+// --*/
+
+/=#
+
+#langdef en-US "English"
+
+#string STR_DP_UP #language en-US "UP"
+#string STR_DP_DOWN #language en-US "DOWN"
+#string STR_DP_DASHES #language en-US "-------------------------------------------------------------------------------\n"
+#string STR_DP_SECTION_HEADER #language en-US "\n==[ %s ]========\n"
+#string STR_DP_INVALID_ARG #language en-US "Invalid argument(s)\n"
+#string STR_DP_TOO_MANY #language en-US "Too many arguments\n"
+#string STR_DP_TOO_FEW #language en-US "Too few arguments\n"
+#string STR_DP_INVALID_NUM_ARG #language en-US "Invalid argument(s), the value of %H%s%N must be numbers\n"
+#string STR_DP_INVALID_RANGE #language en-US "Invalid argument(s), the value of %H%s%N must be between %H%d%N and %H%d%N\n"
+#string STR_DP_CONFLICT_ARG #language en-US "Invalid argument(s), %H%s%N can not be used together with %H%s%N\n"
+#string STR_DP_NO_RAW_ALL #language en-US "Invalid argument(s), -n flag must use with -A or -R\n"
+#string STR_DP_HANDLES_ERROR #language en-US "Locate all handles error - %r\n"
+#string STR_DP_ERROR_NAME #language en-US "Unknown driver name"
+#string STR_PERF_PROPERTY_NOT_FOUND #language en-US "Performance property not found\n"
+#string STR_DP_BUILD_REVISION #language en-US "\nDP Build Version: %d.%d\n"
+#string STR_DP_KHZ #language en-US "System Performance Timer Frequency: %,8d (KHz)\n"
+#string STR_DP_TIMER_PROPERTIES #language en-US "System Performance Timer counts %s from 0x%Lx to 0x%Lx\n"
+#string STR_DP_VERBOSE_THRESHOLD #language en-US "Measurements less than %,Ld microseconds are not displayed.\n"
+#string STR_DP_SECTION_PHASES #language en-US "Major Phases"
+#string STR_DP_SEC_PHASE #language en-US " SEC Phase Duration: %L8d (us)\n"
+#string STR_DP_PHASE_BDSTO #language en-US " BDS Timeout: %L8d (ms) included in BDS Duration\n"
+#string STR_DP_PHASE_DURATION #language en-US "%5a Phase Duration: %L8d (ms)\n"
+#string STR_DP_TOTAL_DURATION #language en-US "Total Duration: %L8d (ms)\n"
+#string STR_DP_SECTION_DRIVERS #language en-US "Drivers by Handle"
+#string STR_DP_HANDLE_SECTION #language en-US "Index: Handle Driver Name Description Time(us)\n"
+#string STR_DP_HANDLE_VARS #language en-US "%5d: [%3x] %36s %11s %L8d\n"
+#string STR_DP_HANDLE_SECTION2 #language en-US "Index: Handle Driver Name Description Time(us) ID\n"
+#string STR_DP_HANDLE_VARS2 #language en-US "%5d: [%3x] %36s %11s %L8d %5d\n"
+#string STR_DP_SECTION_PEIMS #language en-US "PEIMs"
+#string STR_DP_PEIM_SECTION #language en-US "Index: Instance GUID Token Time(us)\n"
+#string STR_DP_PEIM_VARS #language en-US "%5d: %g PEIM %L8d\n"
+#string STR_DP_PEIM_SECTION2 #language en-US "Index: Instance GUID Token Time(us) ID\n"
+#string STR_DP_PEIM_VARS2 #language en-US "%5d: %g PEIM %L8d %5d\n"
+#string STR_DP_SECTION_GENERAL #language en-US "General"
+#string STR_DP_GLOBAL_SECTION #language en-US "Index Name Description Time(us)\n"
+#string STR_DP_GLOBAL_VARS #language en-US "%5d:%25s %31s %L8d\n"
+#string STR_DP_GLOBAL_SECTION2 #language en-US "Index Name Description Time(us) ID\n"
+#string STR_DP_GLOBAL_VARS2 #language en-US "%5d:%25s %31s %L8d %5d\n"
+#string STR_DP_SECTION_CUMULATIVE #language en-US "Cumulative"
+#string STR_DP_CUMULATIVE_SECT_1 #language en-US "(Times in microsec.) Cumulative Average Shortest Longest\n"
+#string STR_DP_CUMULATIVE_SECT_2 #language en-US " Name Count Duration Duration Duration Duration\n"
+#string STR_DP_CUMULATIVE_STATS #language en-US "%11a %8d %L10d %L10d %L10d %L10d\n"
+#string STR_DP_SECTION_STATISTICS #language en-US "Statistics"
+#string STR_DP_STATS_NUMTRACE #language en-US "There were %d measurements taken, of which:\n"
+#string STR_DP_STATS_NUMINCOMPLETE #language en-US "%,8d are incomplete.\n"
+#string STR_DP_STATS_NUMPHASES #language en-US "%,8d are major execution phases.\n"
+#string STR_DP_STATS_NUMHANDLES #language en-US "%,8d have non-NULL handles, %d are NULL.\n"
+#string STR_DP_STATS_NUMPEIMS #language en-US "%,8d are PEIMs.\n"
+#string STR_DP_STATS_NUMGLOBALS #language en-US "%,8d are general measurements.\n"
+#string STR_DP_STATS_NUMPROFILE #language en-US "%,8d are profiling records.\n"
+#string STR_DP_SECTION_ALL #language en-US "Sequential Trace Records"
+#string STR_DP_ALL_HEADR #language en-US "\nIndex Handle Module Token Time(us)\n"
+#string STR_DP_ALL_VARS #language en-US "%5d:%3s0x%08p %36s %13s %L8d\n"
+#string STR_DP_ALL_DASHES2 #language en-US "-------------------------------------------------------------------------------------\n"
+#string STR_DP_ALL_HEADR2 #language en-US "\nIndex Handle Module Token Time(us) ID\n"
+#string STR_DP_ALL_VARS2 #language en-US "%5d:%3s0x%08p %36s %13s %L8d %5d\n"
+#string STR_DP_SECTION_RAWTRACE #language en-US "RAW Trace"
+#string STR_DP_RAW_DASHES #language en-US "---------------------------------------------------------------------------------------------------------------------------\n"
+#string STR_DP_RAW_VARS #language en-US "%5d: %16LX %16LX %16LX %31a %31a\n"
+#string STR_DP_RAW_HEADR #language en-US "\nIndex Handle Start Count End Count Token Module\n"
+#string STR_DP_RAW_DASHES2 #language en-US "---------------------------------------------------------------------------------------------------------------------------------\n"
+#string STR_DP_RAW_VARS2 #language en-US "%5d: %16LX %16LX %16LX %31a %31a %5d\n"
+#string STR_DP_RAW_HEADR2 #language en-US "\nIndex Handle Start Count End Count Token Module ID\n"
+#string STR_DP_INCOMPLETE #language en-US " I "
+#string STR_DP_COMPLETE #language en-US " "
+#string STR_ALIT_UNKNOWN #language en-US "Unknown"
+#string STR_DP_GET_ACPI_FPDT_FAIL #language en-US "Fail to get Firmware Performance Data Table (FPDT) in ACPI Table\n"
+
+#string STR_GET_HELP_DP #language en-US ""
+".TH dp 0 "Display performance metrics"\r\n"
+".SH NAME\r\n"
+"Displays performance metrics that are stored in memory.\r\n"
+".SH SYNOPSIS\r\n"
+"DP [-b] [-v] [-x] [-s | -A | -R] [-t value] [-n count] [-c [token]][-i] [-?]\r\n"
+".SH OPTIONS\r\n"
+" \r\n"
+" -b - Displays on multiple pages\r\n"
+" -v - Displays additional information\r\n"
+" -x - Prevents display of individual measurements for cumulative items\r\n"
+" -s - Displays summary information only\r\n"
+" -A - Displays all measurements in a list\r\n"
+" -R - Displays all measurements in raw format\r\n"
+" -t VALUE - Sets display threshold to VALUE microseconds\r\n"
+" -n COUNT - Limits display to COUNT lines in All and Raw modes\r\n"
+" -i - Displays identifier\r\n"
+" -c TOKEN - Display pre-defined and custom cumulative data\r\n"
+" Pre-defined cumulative token are:\r\n"
+" 1. LoadImage:\r\n"
+" 2. StartImage:\r\n"
+" 3. DB:Start:\r\n"
+" 4. DB:Support:\r\n"
+" -? - Displays DP help information\r\n"
+".SH DESCRIPTION\r\n"
+" \r\n"
+"NOTES:\r\n"
+" 1. Displays Performance metrics that are stored in memory.\r\n"
+".SH RETURNVALUES\r\n"
+" \r\n"
+"RETURN VALUES:\r\n"
+" SHELL_SUCCESS The action was completed as requested.\r\n"
+" SHELL_NOT_FOUND The requested option was not found.\r\n"
+" SHELL_INVALID_PARAMETER One of the passed in parameters was incorrectly formatted or its value was out of bounds.\r\n"
+" SHELL_UNSUPPORTED The action as requested was unsupported.\r\n"
+" SHELL_OUT_OF_RESOURCES There was insufficient free space for the request to be completed.\r\n"
diff --git a/src/VBox/Devices/EFI/Firmware/ShellPkg/DynamicCommand/DpDynamicCommand/DpApp.c b/src/VBox/Devices/EFI/Firmware/ShellPkg/DynamicCommand/DpDynamicCommand/DpApp.c new file mode 100644 index 00000000..b77d644d --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/ShellPkg/DynamicCommand/DpDynamicCommand/DpApp.c @@ -0,0 +1,47 @@ +/** @file + Entrypoint of "dp" shell standalone application. + + Copyright (c) 2017, Intel Corporation. All rights reserved. <BR> + + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ +#include "Dp.h" + +// +// String token ID of help message text. +// Shell supports to find help message in the resource section of an application image if +// .MAN file is not found. This global variable is added to make build tool recognizes +// that the help string is consumed by user and then build tool will add the string into +// the resource section. Thus the application can use '-?' option to show help message in +// Shell. +// +GLOBAL_REMOVE_IF_UNREFERENCED EFI_STRING_ID mStringHelpTokenId = STRING_TOKEN (STR_GET_HELP_DP); + +/** + Entry point of Tftp standalone application. + + @param ImageHandle The image handle of the process. + @param SystemTable The EFI System Table pointer. + + @retval EFI_SUCCESS Tftp command is executed successfully. + @retval EFI_ABORTED HII package was failed to initialize. + @retval others Other errors when executing tftp command. +**/ +EFI_STATUS +EFIAPI +DpAppInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + mDpHiiHandle = InitializeHiiPackage (ImageHandle); + if (mDpHiiHandle == NULL) { + return EFI_ABORTED; + } + + Status = (EFI_STATUS)RunDp (ImageHandle, SystemTable); + HiiRemovePackages (mDpHiiHandle); + return Status; +} diff --git a/src/VBox/Devices/EFI/Firmware/ShellPkg/DynamicCommand/DpDynamicCommand/DpApp.inf b/src/VBox/Devices/EFI/Firmware/ShellPkg/DynamicCommand/DpDynamicCommand/DpApp.inf new file mode 100644 index 00000000..25d053a3 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/ShellPkg/DynamicCommand/DpDynamicCommand/DpApp.inf @@ -0,0 +1,64 @@ +## @file +# Provides Shell 'dp' standalone application. +# +# Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved. +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010006 + BASE_NAME = dp + FILE_GUID = 1831A379-2D48-45BD-9744-D4059D93815D + MODULE_TYPE = UEFI_APPLICATION + VERSION_STRING = 1.0 + ENTRY_POINT = DpAppInitialize +# +# This flag specifies whether HII resource section is generated into PE image. +# + UEFI_HII_RESOURCE_SECTION = TRUE + +[Sources.common] + Dp.uni + Dp.c + Dp.h + Literals.h + Literals.c + DpInternal.h + DpUtilities.c + DpTrace.c + DpApp.c + +[Packages] + MdePkg/MdePkg.dec + ShellPkg/ShellPkg.dec + MdeModulePkg/MdeModulePkg.dec + +[LibraryClasses] + MemoryAllocationLib + BaseLib + BaseMemoryLib + DebugLib + ShellLib + UefiLib + UefiRuntimeServicesTableLib + UefiBootServicesTableLib + UefiApplicationEntryPoint + SortLib + PrintLib + DevicePathLib + PerformanceLib + DxeServicesLib + PeCoffGetEntryPointLib + +[Guids] + gPerformanceProtocolGuid ## CONSUMES ## SystemTable + +[Protocols] + gEfiLoadedImageProtocolGuid ## CONSUMES + gEfiDriverBindingProtocolGuid ## SOMETIMES_CONSUMES + gEfiComponentName2ProtocolGuid ## SOMETIMES_CONSUMES + gEfiLoadedImageDevicePathProtocolGuid ## SOMETIMES_CONSUMES + gEfiHiiPackageListProtocolGuid ## CONSUMES + diff --git a/src/VBox/Devices/EFI/Firmware/ShellPkg/DynamicCommand/DpDynamicCommand/DpDynamicCommand.c b/src/VBox/Devices/EFI/Firmware/ShellPkg/DynamicCommand/DpDynamicCommand/DpDynamicCommand.c new file mode 100644 index 00000000..ca8dec0a --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/ShellPkg/DynamicCommand/DpDynamicCommand/DpDynamicCommand.c @@ -0,0 +1,125 @@ +/** @file + Produce "dp" shell dynamic command. + + Copyright (c) 2017, Intel Corporation. All rights reserved. <BR> + + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ +#include "Dp.h" +#include <Protocol/ShellDynamicCommand.h> + +/** + This is the shell command handler function pointer callback type. This + function handles the command when it is invoked in the shell. + + @param[in] This The instance of the EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL. + @param[in] SystemTable The pointer to the system table. + @param[in] ShellParameters The parameters associated with the command. + @param[in] Shell The instance of the shell protocol used in the context + of processing this command. + + @return EFI_SUCCESS the operation was successful + @return other the operation failed. +**/ +SHELL_STATUS +EFIAPI +DpCommandHandler ( + IN EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL *This, + IN EFI_SYSTEM_TABLE *SystemTable, + IN EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters, + IN EFI_SHELL_PROTOCOL *Shell + ) +{ + gEfiShellParametersProtocol = ShellParameters; + gEfiShellProtocol = Shell; + return RunDp (gImageHandle, SystemTable); +} + +/** + This is the command help handler function pointer callback type. This + function is responsible for displaying help information for the associated + command. + + @param[in] This The instance of the EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL. + @param[in] Language The pointer to the language string to use. + + @return string Pool allocated help string, must be freed by caller +**/ +CHAR16 * +EFIAPI +DpCommandGetHelp ( + IN EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL *This, + IN CONST CHAR8 *Language + ) +{ + return HiiGetString (mDpHiiHandle, STRING_TOKEN (STR_GET_HELP_DP), Language); +} + +EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL mDpDynamicCommand = { + L"dp", + DpCommandHandler, + DpCommandGetHelp +}; + +/** + Entry point of Tftp Dynamic Command. + + Produce the DynamicCommand protocol to handle "tftp" command. + + @param ImageHandle The image handle of the process. + @param SystemTable The EFI System Table pointer. + + @retval EFI_SUCCESS Tftp command is executed successfully. + @retval EFI_ABORTED HII package was failed to initialize. + @retval others Other errors when executing tftp command. +**/ +EFI_STATUS +EFIAPI +DpCommandInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + mDpHiiHandle = InitializeHiiPackage (ImageHandle); + if (mDpHiiHandle == NULL) { + return EFI_ABORTED; + } + + Status = gBS->InstallProtocolInterface ( + &ImageHandle, + &gEfiShellDynamicCommandProtocolGuid, + EFI_NATIVE_INTERFACE, + &mDpDynamicCommand + ); + ASSERT_EFI_ERROR (Status); + return Status; +} + +/** + Tftp driver unload handler. + + @param ImageHandle The image handle of the process. + + @retval EFI_SUCCESS The image is unloaded. + @retval Others Failed to unload the image. +**/ +EFI_STATUS +EFIAPI +DpUnload ( + IN EFI_HANDLE ImageHandle +) +{ + EFI_STATUS Status; + Status = gBS->UninstallProtocolInterface ( + ImageHandle, + &gEfiShellDynamicCommandProtocolGuid, + &mDpDynamicCommand + ); + if (EFI_ERROR (Status)) { + return Status; + } + HiiRemovePackages (mDpHiiHandle); + return EFI_SUCCESS; +} diff --git a/src/VBox/Devices/EFI/Firmware/ShellPkg/DynamicCommand/DpDynamicCommand/DpDynamicCommand.inf b/src/VBox/Devices/EFI/Firmware/ShellPkg/DynamicCommand/DpDynamicCommand/DpDynamicCommand.inf new file mode 100644 index 00000000..159632a3 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/ShellPkg/DynamicCommand/DpDynamicCommand/DpDynamicCommand.inf @@ -0,0 +1,68 @@ +## @file +# Provides Shell 'dp' dynamic command. +# +# Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved. +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010006 + BASE_NAME = dpDynamicCommand + FILE_GUID = 0253F9FA-129A-4A8D-B12E-7DC2B6376302 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = DpCommandInitialize + UNLOAD_IMAGE = DpUnload +# +# This flag specifies whether HII resource section is generated into PE image. +# + UEFI_HII_RESOURCE_SECTION = TRUE + +[Sources.common] + Dp.uni + Dp.c + Dp.h + Literals.h + Literals.c + DpInternal.h + DpUtilities.c + DpTrace.c + DpDynamicCommand.c + +[Packages] + MdePkg/MdePkg.dec + ShellPkg/ShellPkg.dec + MdeModulePkg/MdeModulePkg.dec + +[LibraryClasses] + MemoryAllocationLib + BaseLib + BaseMemoryLib + DebugLib + ShellLib + UefiLib + UefiRuntimeServicesTableLib + UefiBootServicesTableLib + UefiDriverEntryPoint + SortLib + PrintLib + DevicePathLib + PerformanceLib + DxeServicesLib + PeCoffGetEntryPointLib + +[Guids] + gPerformanceProtocolGuid ## CONSUMES ## SystemTable + +[Protocols] + gEfiLoadedImageProtocolGuid ## CONSUMES + gEfiDriverBindingProtocolGuid ## SOMETIMES_CONSUMES + gEfiComponentName2ProtocolGuid ## SOMETIMES_CONSUMES + gEfiLoadedImageDevicePathProtocolGuid ## SOMETIMES_CONSUMES + gEfiHiiPackageListProtocolGuid ## CONSUMES + gEfiShellDynamicCommandProtocolGuid ## PRODUCES + +[DEPEX] + TRUE diff --git a/src/VBox/Devices/EFI/Firmware/ShellPkg/DynamicCommand/DpDynamicCommand/DpInternal.h b/src/VBox/Devices/EFI/Firmware/ShellPkg/DynamicCommand/DpDynamicCommand/DpInternal.h new file mode 100644 index 00000000..d6d30c54 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/ShellPkg/DynamicCommand/DpDynamicCommand/DpInternal.h @@ -0,0 +1,315 @@ +/** @file + Declarations of objects defined internally to the Dp Application. + + Declarations of data and functions which are private to the Dp application. + This file should never be referenced by anything other than components of the + Dp application. In addition to global data, function declarations for + DpUtilities.c, DpTrace.c, and DpProfile.c are included here. + + 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 +**/ +#ifndef _DP_INTELNAL_H_ +#define _DP_INTELNAL_H_ + +#define DP_GAUGE_STRING_LENGTH 36 + +// +/// Module-Global Variables +///@{ +extern EFI_HII_HANDLE mDpHiiHandle; +extern CHAR16 mGaugeString[DP_GAUGE_STRING_LENGTH + 1]; +extern CHAR16 mUnicodeToken[DXE_PERFORMANCE_STRING_SIZE]; +extern UINT64 mInterestThreshold; +extern BOOLEAN mShowId; +extern UINT8 *mBootPerformanceTable; +extern UINTN mBootPerformanceTableLength; +extern MEASUREMENT_RECORD *mMeasurementList; +extern UINTN mMeasurementNum; + +extern PERF_SUMMARY_DATA SummaryData; ///< Create the SummaryData structure and init. to ZERO. + +/// Items for which to gather cumulative statistics. +extern PERF_CUM_DATA CumData[]; + +/// Number of items for which we are gathering cumulative statistics. +extern UINT32 const NumCum; + +///@} + +/** + Calculate an event's duration in timer ticks. + + Given the count direction and the event's start and end timer values, + calculate the duration of the event in timer ticks. Information for + the current measurement is pointed to by the parameter. + + If the measurement's start time is 1, it indicates that the developer + is indicating that the measurement began at the release of reset. + The start time is adjusted to the timer's starting count before performing + the elapsed time calculation. + + The calculated duration, in ticks, is the absolute difference between + the measurement's ending and starting counts. + + @param Measurement Pointer to a MEASUREMENT_RECORD structure containing + data for the current measurement. + + @return The 64-bit duration of the event. +**/ +UINT64 +GetDuration ( + IN OUT MEASUREMENT_RECORD *Measurement + ); + +/** + Determine whether the Measurement record is for an EFI Phase. + + The Token and Module members of the measurement record are checked. + Module must be empty and Token must be one of SEC, PEI, DXE, BDS, or SHELL. + + @param[in] Measurement A pointer to the Measurement record to test. + + @retval TRUE The measurement record is for an EFI Phase. + @retval FALSE The measurement record is NOT for an EFI Phase. +**/ +BOOLEAN +IsPhase( + IN MEASUREMENT_RECORD *Measurement + ); + +/** + Determine whether the Measurement record is for core code. + + @param[in] Measurement A pointer to the Measurement record to test. + + @retval TRUE The measurement record is used for core. + @retval FALSE The measurement record is NOT used for core. + +**/ +BOOLEAN +IsCorePerf( + IN MEASUREMENT_RECORD *Measurement + ); + +/** + Get the file name portion of the Pdb File Name. + + The portion of the Pdb File Name between the last backslash and + either a following period or the end of the string is converted + to Unicode and copied into UnicodeBuffer. The name is truncated, + if necessary, to ensure that UnicodeBuffer is not overrun. + + @param[in] PdbFileName Pdb file name. + @param[out] UnicodeBuffer The resultant Unicode File Name. + +**/ +VOID +DpGetShortPdbFileName ( + IN CHAR8 *PdbFileName, + OUT CHAR16 *UnicodeBuffer + ); + +/** + Get a human readable name for an image handle. + The following methods will be tried orderly: + 1. Image PDB + 2. ComponentName2 protocol + 3. FFS UI section + 4. Image GUID + 5. Image DevicePath + 6. Unknown Driver Name + + @param[in] Handle + + @post The resulting Unicode name string is stored in the + mGaugeString global array. + +**/ +VOID +DpGetNameFromHandle ( + IN EFI_HANDLE Handle + ); + +/** + Calculate the Duration in microseconds. + + Duration is multiplied by 1000, instead of Frequency being divided by 1000 or + multiplying the result by 1000, in order to maintain precision. Since Duration is + a 64-bit value, multiplying it by 1000 is unlikely to produce an overflow. + + The time is calculated as (Duration * 1000) / Timer_Frequency. + + @param[in] Duration The event duration in timer ticks. + + @return A 64-bit value which is the Elapsed time in microseconds. +**/ +UINT64 +DurationInMicroSeconds ( + IN UINT64 Duration + ); + +/** + Get index of Measurement Record's match in the CumData array. + + If the Measurement's Token value matches a Token in one of the CumData + records, the index of the matching record is returned. The returned + index is a signed value so that negative values can indicate that + the Measurement didn't match any entry in the CumData array. + + @param[in] Measurement A pointer to a Measurement Record to match against the CumData array. + + @retval <0 Token is not in the CumData array. + @retval >=0 Return value is the index into CumData where Token is found. +**/ +INTN +GetCumulativeItem( + IN MEASUREMENT_RECORD *Measurement + ); + +/** + Collect verbose statistics about the logged performance measurements. + + General Summary information for all Trace measurements is gathered and + stored within the SummaryData structure. This information is both + used internally by subsequent reporting functions, and displayed + at the end of verbose reports. + + @pre The SummaryData and CumData structures must be initialized + prior to calling this function. + + @post The SummaryData and CumData structures contain statistics for the + current performance logs. + + @param[in, out] CustomCumulativeData The pointer to the custom cumulative data. + +**/ +VOID +GatherStatistics( + IN OUT PERF_CUM_DATA *CustomCumulativeData OPTIONAL + ); + +/** + Gather and print ALL Trace Records. + + Displays all "interesting" Trace measurements in order.<BR> + The number of records displayed is controlled by: + - records with a duration less than mInterestThreshold microseconds are not displayed. + - No more than Limit records are displayed. A Limit of zero will not limit the output. + - If the ExcludeFlag is TRUE, records matching entries in the CumData array are not + displayed. + + @pre The mInterestThreshold global variable is set to the shortest duration to be printed. + The mGaugeString and mUnicodeToken global arrays are used for temporary string storage. + They must not be in use by a calling function. + + @param[in] Limit The number of records to print. Zero is ALL. + @param[in] ExcludeFlag TRUE to exclude individual Cumulative items from display. + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_ABORTED The user aborts the operation. + @return Others from a call to gBS->LocateHandleBuffer(). +**/ +EFI_STATUS +DumpAllTrace( + IN UINTN Limit, + IN BOOLEAN ExcludeFlag + ); + +/** + Gather and print Raw Trace Records. + + All Trace measurements with a duration greater than or equal to + mInterestThreshold are printed without interpretation. + + The number of records displayed is controlled by: + - records with a duration less than mInterestThreshold microseconds are not displayed. + - No more than Limit records are displayed. A Limit of zero will not limit the output. + - If the ExcludeFlag is TRUE, records matching entries in the CumData array are not + displayed. + + @pre The mInterestThreshold global variable is set to the shortest duration to be printed. + + @param[in] Limit The number of records to print. Zero is ALL. + @param[in] ExcludeFlag TRUE to exclude individual Cumulative items from display. + @retval EFI_SUCCESS The operation was successful. + @retval EFI_ABORTED The user aborts the operation. +**/ +EFI_STATUS +DumpRawTrace( + IN UINTN Limit, + IN BOOLEAN ExcludeFlag + ); + +/** + Gather and print Major Phase metrics. + +**/ +VOID +ProcessPhases( + VOID + ); + + +/** + Gather and print Handle data. + + @param[in] ExcludeFlag TRUE to exclude individual Cumulative items from display. + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_ABORTED The user aborts the operation. + @return Others from a call to gBS->LocateHandleBuffer(). +**/ +EFI_STATUS +ProcessHandles( + IN BOOLEAN ExcludeFlag + ); + + +/** + Gather and print PEIM data. + + Only prints complete PEIM records + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_ABORTED The user aborts the operation. +**/ +EFI_STATUS +ProcessPeims( + VOID + ); + +/** + Gather and print global data. + + Strips out incomplete or "Execution Phase" records + Only prints records where Handle is NULL + Increment TIndex for every record, even skipped ones, so that we have an + indication of every measurement record taken. + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_ABORTED The user aborts the operation. +**/ +EFI_STATUS +ProcessGlobal( + VOID + ); + +/** + Gather and print cumulative data. + + Traverse the measurement records and:<BR> + For each record with a Token listed in the CumData array:<BR> + - Update the instance count and the total, minimum, and maximum durations. + Finally, print the gathered cumulative statistics. + + @param[in] CustomCumulativeData The pointer to the custom cumulative data. + +**/ +VOID +ProcessCumulative( + IN PERF_CUM_DATA *CustomCumulativeData OPTIONAL + ); + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/ShellPkg/DynamicCommand/DpDynamicCommand/DpTrace.c b/src/VBox/Devices/EFI/Firmware/ShellPkg/DynamicCommand/DpDynamicCommand/DpTrace.c new file mode 100644 index 00000000..d66f4bd6 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/ShellPkg/DynamicCommand/DpDynamicCommand/DpTrace.c @@ -0,0 +1,904 @@ +/** @file + Trace reporting for the Dp utility. + + 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 <Library/BaseLib.h> +#include <Library/BaseMemoryLib.h> +#include <Library/MemoryAllocationLib.h> +#include <Library/DebugLib.h> +#include <Library/UefiBootServicesTableLib.h> +#include <Library/PeCoffGetEntryPointLib.h> +#include <Library/PerformanceLib.h> +#include <Library/PrintLib.h> +#include <Library/HiiLib.h> +#include <Library/PcdLib.h> + +#include "Dp.h" +#include "Literals.h" +#include "DpInternal.h" + +/** + Attempts to retrieve a performance measurement log entry from the performance measurement log. + + + @param LogEntryKey On entry, the key of the performance measurement log entry to retrieve. + 0, then the first performance measurement log entry is retrieved. + On exit, the key of the next performance log entry. + @param Handle Pointer to environment specific context used to identify the component + being measured. + @param Token Pointer to a Null-terminated ASCII string that identifies the component + being measured. + @param Module Pointer to a Null-terminated ASCII string that identifies the module + being measured. + @param StartTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement + was started. + @param EndTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement + was ended. + @param Identifier Pointer to the 32-bit identifier that was recorded when the measurement + was ended. + + @return The key for the next performance log entry (in general case). + +**/ +UINTN +GetPerformanceMeasurementRecord ( + IN UINTN LogEntryKey, + OUT CONST VOID **Handle, + OUT CONST CHAR8 **Token, + OUT CONST CHAR8 **Module, + OUT UINT64 *StartTimeStamp, + OUT UINT64 *EndTimeStamp, + OUT UINT32 *Identifier + ) +{ + if (LogEntryKey == mMeasurementNum) { + return 0; + } + + *Handle = (VOID *) (UINTN) mMeasurementList[LogEntryKey].Handle; + *Token = mMeasurementList[LogEntryKey].Token; + *Module = mMeasurementList[LogEntryKey].Module; + *StartTimeStamp = mMeasurementList[LogEntryKey].StartTimeStamp; + *EndTimeStamp = mMeasurementList[LogEntryKey].EndTimeStamp; + *Identifier = mMeasurementList[LogEntryKey].Identifier; + + LogEntryKey ++; + + return LogEntryKey; +} + +/** + Collect verbose statistics about the logged performance measurements. + + General Summary information for all Trace measurements is gathered and + stored within the SummaryData structure. This information is both + used internally by subsequent reporting functions, and displayed + at the end of verbose reports. + + @pre The SummaryData and CumData structures must be initialized + prior to calling this function. + + @post The SummaryData and CumData structures contain statistics for the + current performance logs. + + @param[in, out] CustomCumulativeData A pointer to the custom cumulative data. + +**/ +VOID +GatherStatistics( + IN OUT PERF_CUM_DATA *CustomCumulativeData OPTIONAL + ) +{ + MEASUREMENT_RECORD Measurement; + UINT64 Duration; + UINTN LogEntryKey; + INTN TIndex; + + LogEntryKey = 0; + while ((LogEntryKey = GetPerformanceMeasurementRecord ( + LogEntryKey, + &Measurement.Handle, + &Measurement.Token, + &Measurement.Module, + &Measurement.StartTimeStamp, + &Measurement.EndTimeStamp, + &Measurement.Identifier)) != 0) + { + ++SummaryData.NumTrace; // Count the number of TRACE Measurement records + if (Measurement.EndTimeStamp == 0) { + ++SummaryData.NumIncomplete; // Count the incomplete records + continue; + } + + if (Measurement.Handle != NULL) { + ++SummaryData.NumHandles; // Count the number of measurements with non-NULL handles + } + + if (IsPhase( &Measurement)) { + ++SummaryData.NumSummary; // Count the number of major phases + } + else { // !IsPhase + if(Measurement.Handle == NULL) { + ++SummaryData.NumGlobal; + } + } + + if (AsciiStrCmp (Measurement.Token, ALit_PEIM) == 0) { + ++SummaryData.NumPEIMs; // Count PEIM measurements + } + + Duration = GetDuration (&Measurement); + TIndex = GetCumulativeItem (&Measurement); + if (TIndex >= 0) { + CumData[TIndex].Duration += Duration; + CumData[TIndex].Count++; + if ( Duration < CumData[TIndex].MinDur ) { + CumData[TIndex].MinDur = Duration; + } + if ( Duration > CumData[TIndex].MaxDur ) { + CumData[TIndex].MaxDur = Duration; + } + } + + // + // Collect the data for custom cumulative data. + // + if ((CustomCumulativeData != NULL) && (AsciiStrCmp (Measurement.Token, CustomCumulativeData->Name) == 0)) { + CustomCumulativeData->Duration += Duration; + CustomCumulativeData->Count++; + if (Duration < CustomCumulativeData->MinDur) { + CustomCumulativeData->MinDur = Duration; + } + if (Duration > CustomCumulativeData->MaxDur) { + CustomCumulativeData->MaxDur = Duration; + } + } + } +} + +/** + Gather and print ALL Trace Records. + + Displays all "interesting" Trace measurements in order.<BR> + The number of records displayed is controlled by: + - records with a duration less than mInterestThreshold microseconds are not displayed. + - No more than Limit records are displayed. A Limit of zero will not limit the output. + - If the ExcludeFlag is TRUE, records matching entries in the CumData array are not + displayed. + + @pre The mInterestThreshold global variable is set to the shortest duration to be printed. + The mGaugeString and mUnicodeToken global arrays are used for temporary string storage. + They must not be in use by a calling function. + + @param[in] Limit The number of records to print. Zero is ALL. + @param[in] ExcludeFlag TRUE to exclude individual Cumulative items from display. + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_ABORTED The user aborts the operation. + @return Others from a call to gBS->LocateHandleBuffer(). +**/ +EFI_STATUS +DumpAllTrace( + IN UINTN Limit, + IN BOOLEAN ExcludeFlag + ) +{ + MEASUREMENT_RECORD Measurement; + UINT64 ElapsedTime; + UINT64 Duration; + CHAR16 *IncFlag; + UINTN LogEntryKey; + UINTN Count; + UINTN Index; + UINTN TIndex; + + EFI_HANDLE *HandleBuffer; + UINTN HandleCount; + EFI_STATUS Status; + EFI_STRING StringPtrUnknown; + + StringPtrUnknown = HiiGetString (mDpHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL); + IncFlag = HiiGetString (mDpHiiHandle, STRING_TOKEN (STR_DP_SECTION_ALL), NULL); + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_SECTION_HEADER), mDpHiiHandle, + (IncFlag == NULL) ? StringPtrUnknown : IncFlag); + FreePool (StringPtrUnknown); + + // Get Handle information + // + Status = gBS->LocateHandleBuffer (AllHandles, NULL, NULL, &HandleCount, &HandleBuffer); + if (EFI_ERROR (Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_HANDLES_ERROR), mDpHiiHandle, Status); + } + else { + // We have successfully populated the HandleBuffer + // Display ALL Measurement Records + // Up to Limit lines displayed + // Display only records with Elapsed times >= mInterestThreshold + // Display driver names in Module field for records with Handles. + // + if (mShowId) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_ALL_HEADR2), mDpHiiHandle); + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_ALL_DASHES2), mDpHiiHandle); + } else { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_ALL_HEADR), mDpHiiHandle); + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_DASHES), mDpHiiHandle); + } + + LogEntryKey = 0; + Count = 0; + Index = 0; + while ( WITHIN_LIMIT(Count, Limit) && + ((LogEntryKey = GetPerformanceMeasurementRecord ( + LogEntryKey, + &Measurement.Handle, + &Measurement.Token, + &Measurement.Module, + &Measurement.StartTimeStamp, + &Measurement.EndTimeStamp, + &Measurement.Identifier)) != 0) + ) + { + ++Index; // Count every record. First record is 1. + ElapsedTime = 0; + SHELL_FREE_NON_NULL (IncFlag); + if (Measurement.EndTimeStamp != 0) { + Duration = GetDuration (&Measurement); + ElapsedTime = DurationInMicroSeconds ( Duration ); + IncFlag = HiiGetString (mDpHiiHandle, STRING_TOKEN (STR_DP_COMPLETE), NULL); + } + else { + IncFlag = HiiGetString (mDpHiiHandle, STRING_TOKEN (STR_DP_INCOMPLETE), NULL); // Mark incomplete records + } + if (((Measurement.EndTimeStamp != 0) && (ElapsedTime < mInterestThreshold)) || + ((ExcludeFlag) && (GetCumulativeItem(&Measurement) >= 0)) + ) { // Ignore "uninteresting" or excluded records + continue; + } + ++Count; // Count the number of records printed + + // If Handle is non-zero, see if we can determine a name for the driver + AsciiStrToUnicodeStrS (Measurement.Module, mGaugeString, ARRAY_SIZE (mGaugeString)); // Use Module by default + AsciiStrToUnicodeStrS (Measurement.Token, mUnicodeToken, ARRAY_SIZE (mUnicodeToken)); + if (Measurement.Handle != NULL) { + // See if the Handle is in the HandleBuffer + for (TIndex = 0; TIndex < HandleCount; TIndex++) { + if (Measurement.Handle == HandleBuffer[TIndex]) { + DpGetNameFromHandle (HandleBuffer[TIndex]); + break; + } + } + } + + if (AsciiStrCmp (Measurement.Token, ALit_PEIM) == 0) { + UnicodeSPrint (mGaugeString, sizeof (mGaugeString), L"%g", Measurement.Handle); + } + + // Ensure that the argument strings are not too long. + mGaugeString[DP_GAUGE_STRING_LENGTH] = 0; + mUnicodeToken[13] = 0; + + if (mShowId) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_ALL_VARS2), mDpHiiHandle, + Index, // 1 based, Which measurement record is being printed + IncFlag, + Measurement.Handle, + mGaugeString, + mUnicodeToken, + ElapsedTime, + Measurement.Identifier + ); + } else { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_ALL_VARS), mDpHiiHandle, + Index, // 1 based, Which measurement record is being printed + IncFlag, + Measurement.Handle, + mGaugeString, + mUnicodeToken, + ElapsedTime + ); + } + if (ShellGetExecutionBreakFlag ()) { + Status = EFI_ABORTED; + break; + } + } + } + if (HandleBuffer != NULL) { + FreePool (HandleBuffer); + } + SHELL_FREE_NON_NULL (IncFlag); + + return Status; +} + +/** + Gather and print Raw Trace Records. + + All Trace measurements with a duration greater than or equal to + mInterestThreshold are printed without interpretation. + + The number of records displayed is controlled by: + - records with a duration less than mInterestThreshold microseconds are not displayed. + - No more than Limit records are displayed. A Limit of zero will not limit the output. + - If the ExcludeFlag is TRUE, records matching entries in the CumData array are not + displayed. + + @pre The mInterestThreshold global variable is set to the shortest duration to be printed. + + @param[in] Limit The number of records to print. Zero is ALL. + @param[in] ExcludeFlag TRUE to exclude individual Cumulative items from display. + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_ABORTED The user aborts the operation. +**/ +EFI_STATUS +DumpRawTrace( + IN UINTN Limit, + IN BOOLEAN ExcludeFlag + ) +{ + MEASUREMENT_RECORD Measurement; + UINT64 ElapsedTime; + UINT64 Duration; + UINTN LogEntryKey; + UINTN Count; + UINTN Index; + + EFI_STRING StringPtr; + EFI_STRING StringPtrUnknown; + EFI_STATUS Status; + + Status = EFI_SUCCESS; + + StringPtrUnknown = HiiGetString (mDpHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL); + StringPtr = HiiGetString (mDpHiiHandle, STRING_TOKEN (STR_DP_SECTION_RAWTRACE), NULL); + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_SECTION_HEADER), mDpHiiHandle, + (StringPtr == NULL) ? StringPtrUnknown : StringPtr); + FreePool (StringPtr); + FreePool (StringPtrUnknown); + + if (mShowId) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_RAW_HEADR2), mDpHiiHandle); + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_RAW_DASHES2), mDpHiiHandle); + } else { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_RAW_HEADR), mDpHiiHandle); + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_RAW_DASHES), mDpHiiHandle); + } + + LogEntryKey = 0; + Count = 0; + Index = 0; + while ( WITHIN_LIMIT(Count, Limit) && + ((LogEntryKey = GetPerformanceMeasurementRecord ( + LogEntryKey, + &Measurement.Handle, + &Measurement.Token, + &Measurement.Module, + &Measurement.StartTimeStamp, + &Measurement.EndTimeStamp, + &Measurement.Identifier)) != 0) + ) + { + ++Index; // Count every record. First record is 1. + ElapsedTime = 0; + if (Measurement.EndTimeStamp != 0) { + Duration = GetDuration (&Measurement); + ElapsedTime = DurationInMicroSeconds ( Duration ); + } + if ((ElapsedTime < mInterestThreshold) || + ((ExcludeFlag) && (GetCumulativeItem(&Measurement) >= 0)) + ) { // Ignore "uninteresting" or Excluded records + continue; + } + ++Count; // Count the number of records printed + + if (mShowId) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_RAW_VARS2), mDpHiiHandle, + Index, // 1 based, Which measurement record is being printed + Measurement.Handle, + Measurement.StartTimeStamp, + Measurement.EndTimeStamp, + Measurement.Token, + Measurement.Module, + Measurement.Identifier + ); + } else { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_RAW_VARS), mDpHiiHandle, + Index, // 1 based, Which measurement record is being printed + Measurement.Handle, + Measurement.StartTimeStamp, + Measurement.EndTimeStamp, + Measurement.Token, + Measurement.Module + ); + } + if (ShellGetExecutionBreakFlag ()) { + Status = EFI_ABORTED; + break; + } + } + return Status; +} + +/** + Gather and print Major Phase metrics. + +**/ +VOID +ProcessPhases( + VOID + ) +{ + MEASUREMENT_RECORD Measurement; + UINT64 BdsTimeoutValue; + UINT64 SecTime; + UINT64 PeiTime; + UINT64 DxeTime; + UINT64 BdsTime; + UINT64 ElapsedTime; + UINT64 Duration; + UINT64 Total; + EFI_STRING StringPtr; + UINTN LogEntryKey; + EFI_STRING StringPtrUnknown; + + BdsTimeoutValue = 0; + SecTime = 0; + PeiTime = 0; + DxeTime = 0; + BdsTime = 0; + // + // Get Execution Phase Statistics + // + StringPtrUnknown = HiiGetString (mDpHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL); + StringPtr = HiiGetString (mDpHiiHandle, STRING_TOKEN (STR_DP_SECTION_PHASES), NULL); + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_SECTION_HEADER), mDpHiiHandle, + (StringPtr == NULL) ? StringPtrUnknown : StringPtr); + FreePool (StringPtr); + FreePool (StringPtrUnknown); + + LogEntryKey = 0; + while ((LogEntryKey = GetPerformanceMeasurementRecord ( + LogEntryKey, + &Measurement.Handle, + &Measurement.Token, + &Measurement.Module, + &Measurement.StartTimeStamp, + &Measurement.EndTimeStamp, + &Measurement.Identifier)) != 0) + { + if (Measurement.EndTimeStamp == 0) { // Skip "incomplete" records + continue; + } + Duration = GetDuration (&Measurement); + if ( Measurement.Handle != NULL + && (AsciiStrCmp (Measurement.Token, ALit_BdsTO) == 0) + ) + { + BdsTimeoutValue = Duration; + } else if (AsciiStrCmp (Measurement.Token, ALit_SEC) == 0) { + SecTime = Duration; + } else if (AsciiStrCmp (Measurement.Token, ALit_PEI) == 0) { + PeiTime = Duration; + } else if (AsciiStrCmp (Measurement.Token, ALit_DXE) == 0) { + DxeTime = Duration; + } else if (AsciiStrCmp (Measurement.Token, ALit_BDS) == 0) { + BdsTime = Duration; + } + } + + Total = 0; + + // print SEC phase duration time + // + if (SecTime > 0) { + ElapsedTime = DurationInMicroSeconds ( SecTime ); // Calculate elapsed time in microseconds + Total += DivU64x32 (ElapsedTime, 1000); // Accumulate time in milliseconds + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_SEC_PHASE), mDpHiiHandle, ElapsedTime); + } + + // print PEI phase duration time + // + if (PeiTime > 0) { + ElapsedTime = DivU64x32 (PeiTime, 1000000); + Total += ElapsedTime; + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_PHASE_DURATION), mDpHiiHandle, ALit_PEI, ElapsedTime); + } + + // print DXE phase duration time + // + if (DxeTime > 0) { + ElapsedTime = DivU64x32 (DxeTime, 1000000); + Total += ElapsedTime; + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_PHASE_DURATION), mDpHiiHandle, ALit_DXE, ElapsedTime); + } + + // print BDS phase duration time + // + if (BdsTime > 0) { + ElapsedTime = DivU64x32 (BdsTime, 1000000); + Total += ElapsedTime; + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_PHASE_DURATION), mDpHiiHandle, ALit_BDS, ElapsedTime); + } + + if (BdsTimeoutValue > 0) { + ElapsedTime = DivU64x32 (BdsTimeoutValue, 1000000); + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_PHASE_BDSTO), mDpHiiHandle, ALit_BdsTO, ElapsedTime); + } + + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_TOTAL_DURATION), mDpHiiHandle, Total); +} + +/** + Gather and print Handle data. + + @param[in] ExcludeFlag TRUE to exclude individual Cumulative items from display. + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_ABORTED The user aborts the operation. + @return Others from a call to gBS->LocateHandleBuffer(). +**/ +EFI_STATUS +ProcessHandles( + IN BOOLEAN ExcludeFlag + ) +{ + MEASUREMENT_RECORD Measurement; + UINT64 ElapsedTime; + UINT64 Duration; + EFI_HANDLE *HandleBuffer; + EFI_STRING StringPtr; + UINTN Index; + UINTN LogEntryKey; + UINTN Count; + UINTN HandleCount; + EFI_STATUS Status; + EFI_STRING StringPtrUnknown; + + StringPtrUnknown = HiiGetString (mDpHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL); + StringPtr = HiiGetString (mDpHiiHandle, STRING_TOKEN (STR_DP_SECTION_DRIVERS), NULL); + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_SECTION_HEADER), mDpHiiHandle, + (StringPtr == NULL) ? StringPtrUnknown : StringPtr); + FreePool (StringPtr); + FreePool (StringPtrUnknown); + + Status = gBS->LocateHandleBuffer (AllHandles, NULL, NULL, &HandleCount, &HandleBuffer); + if (EFI_ERROR (Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_HANDLES_ERROR), mDpHiiHandle, Status); + } + else { +#if DP_DEBUG == 2 + Print (L"There are %,d Handles defined.\n", (Size / sizeof(HandleBuffer[0]))); +#endif + + if (mShowId) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_HANDLE_SECTION2), mDpHiiHandle); + } else { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_HANDLE_SECTION), mDpHiiHandle); + } + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_DASHES), mDpHiiHandle); + + LogEntryKey = 0; + Count = 0; + while ((LogEntryKey = GetPerformanceMeasurementRecord ( + LogEntryKey, + &Measurement.Handle, + &Measurement.Token, + &Measurement.Module, + &Measurement.StartTimeStamp, + &Measurement.EndTimeStamp, + &Measurement.Identifier)) != 0) + { + Count++; + Duration = GetDuration (&Measurement); + ElapsedTime = DurationInMicroSeconds ( Duration ); + if ((ElapsedTime < mInterestThreshold) || + (Measurement.EndTimeStamp == 0) || + (!IsCorePerf (&Measurement)) || + ((ExcludeFlag) && (GetCumulativeItem(&Measurement) >= 0)) + ) { // Ignore "uninteresting" or excluded records + continue; + } + mGaugeString[0] = 0; // Empty driver name by default + AsciiStrToUnicodeStrS (Measurement.Token, mUnicodeToken, ARRAY_SIZE (mUnicodeToken)); + // See if the Handle is in the HandleBuffer + for (Index = 0; Index < HandleCount; Index++) { + if (Measurement.Handle == HandleBuffer[Index]) { + DpGetNameFromHandle (HandleBuffer[Index]); // Name is put into mGaugeString + break; + } + } + // Ensure that the argument strings are not too long. + mGaugeString[DP_GAUGE_STRING_LENGTH] = 0; + mUnicodeToken[11] = 0; + if (mGaugeString[0] != 0) { + // Display the record if it has a valid handle. + if (mShowId) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_HANDLE_VARS2), mDpHiiHandle, + Count, // 1 based, Which measurement record is being printed + Index + 1, // 1 based, Which handle is being printed + mGaugeString, + mUnicodeToken, + ElapsedTime, + Measurement.Identifier + ); + } else { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_HANDLE_VARS), mDpHiiHandle, + Count, // 1 based, Which measurement record is being printed + Index + 1, // 1 based, Which handle is being printed + mGaugeString, + mUnicodeToken, + ElapsedTime + ); + } + } + if (ShellGetExecutionBreakFlag ()) { + Status = EFI_ABORTED; + break; + } + } + } + if (HandleBuffer != NULL) { + FreePool (HandleBuffer); + } + return Status; +} + +/** + Gather and print PEIM data. + + Only prints complete PEIM records + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_ABORTED The user aborts the operation. +**/ +EFI_STATUS +ProcessPeims( + VOID +) +{ + MEASUREMENT_RECORD Measurement; + UINT64 Duration; + UINT64 ElapsedTime; + EFI_STRING StringPtr; + UINTN LogEntryKey; + UINTN TIndex; + EFI_STRING StringPtrUnknown; + EFI_STATUS Status; + + Status = EFI_SUCCESS; + + StringPtrUnknown = HiiGetString (mDpHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL); + StringPtr = HiiGetString (mDpHiiHandle, STRING_TOKEN (STR_DP_SECTION_PEIMS), NULL); + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_SECTION_HEADER), mDpHiiHandle, + (StringPtr == NULL) ? StringPtrUnknown : StringPtr); + FreePool (StringPtr); + FreePool (StringPtrUnknown); + + if (mShowId) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_PEIM_SECTION2), mDpHiiHandle); + } else { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_PEIM_SECTION), mDpHiiHandle); + } + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_DASHES), mDpHiiHandle); + TIndex = 0; + LogEntryKey = 0; + while ((LogEntryKey = GetPerformanceMeasurementRecord ( + LogEntryKey, + &Measurement.Handle, + &Measurement.Token, + &Measurement.Module, + &Measurement.StartTimeStamp, + &Measurement.EndTimeStamp, + &Measurement.Identifier)) != 0) + { + TIndex++; + if ((Measurement.EndTimeStamp == 0) || + (AsciiStrCmp (Measurement.Token, ALit_PEIM) != 0) + ) { + continue; + } + + Duration = GetDuration (&Measurement); + ElapsedTime = DurationInMicroSeconds ( Duration ); // Calculate elapsed time in microseconds + if (ElapsedTime >= mInterestThreshold) { + // PEIM FILE Handle is the start address of its FFS file that contains its file guid. + if (mShowId) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_PEIM_VARS2), mDpHiiHandle, + TIndex, // 1 based, Which measurement record is being printed + Measurement.Handle, // file guid + ElapsedTime, + Measurement.Identifier + ); + } else { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_PEIM_VARS), mDpHiiHandle, + TIndex, // 1 based, Which measurement record is being printed + Measurement.Handle, // file guid + ElapsedTime + ); + } + } + if (ShellGetExecutionBreakFlag ()) { + Status = EFI_ABORTED; + break; + } + } + return Status; +} + +/** + Gather and print global data. + + Strips out incomplete or "Execution Phase" records + Only prints records where Handle is NULL + Increment TIndex for every record, even skipped ones, so that we have an + indication of every measurement record taken. + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_ABORTED The user aborts the operation. +**/ +EFI_STATUS +ProcessGlobal( + VOID +) +{ + MEASUREMENT_RECORD Measurement; + UINT64 Duration; + UINT64 ElapsedTime; + EFI_STRING StringPtr; + UINTN LogEntryKey; + UINTN Index; // Index, or number, of the measurement record being processed + EFI_STRING StringPtrUnknown; + EFI_STATUS Status; + + Status = EFI_SUCCESS; + + StringPtrUnknown = HiiGetString (mDpHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL); + StringPtr = HiiGetString (mDpHiiHandle, STRING_TOKEN (STR_DP_SECTION_GENERAL), NULL); + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_SECTION_HEADER), mDpHiiHandle, + (StringPtr == NULL) ? StringPtrUnknown: StringPtr); + FreePool (StringPtr); + FreePool (StringPtrUnknown); + + if (mShowId) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_GLOBAL_SECTION2), mDpHiiHandle); + } else { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_GLOBAL_SECTION), mDpHiiHandle); + } + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_DASHES), mDpHiiHandle); + + Index = 1; + LogEntryKey = 0; + + while ((LogEntryKey = GetPerformanceMeasurementRecord ( + LogEntryKey, + &Measurement.Handle, + &Measurement.Token, + &Measurement.Module, + &Measurement.StartTimeStamp, + &Measurement.EndTimeStamp, + &Measurement.Identifier)) != 0) + { + AsciiStrToUnicodeStrS (Measurement.Module, mGaugeString, ARRAY_SIZE (mGaugeString)); + AsciiStrToUnicodeStrS (Measurement.Token, mUnicodeToken, ARRAY_SIZE (mUnicodeToken)); + mGaugeString[25] = 0; + mUnicodeToken[31] = 0; + if ( ! ( IsPhase( &Measurement) || + IsCorePerf (&Measurement) || + (Measurement.EndTimeStamp == 0) + )) + { + Duration = GetDuration (&Measurement); + ElapsedTime = DurationInMicroSeconds ( Duration ); + if (ElapsedTime >= mInterestThreshold) { + if (mShowId) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_GLOBAL_VARS2), mDpHiiHandle, + Index, + mGaugeString, + mUnicodeToken, + ElapsedTime, + Measurement.Identifier + ); + } else { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_GLOBAL_VARS), mDpHiiHandle, + Index, + mGaugeString, + mUnicodeToken, + ElapsedTime + ); + } + } + } + if (ShellGetExecutionBreakFlag ()) { + Status = EFI_ABORTED; + break; + } + Index++; + } + return Status; +} + +/** + Gather and print cumulative data. + + Traverse the measurement records and:<BR> + For each record with a Token listed in the CumData array:<BR> + - Update the instance count and the total, minimum, and maximum durations. + Finally, print the gathered cumulative statistics. + + @param[in] CustomCumulativeData A pointer to the custom cumulative data. + +**/ +VOID +ProcessCumulative( + IN PERF_CUM_DATA *CustomCumulativeData OPTIONAL + ) +{ + UINT64 AvgDur; // the computed average duration + UINT64 Dur; + UINT64 MinDur; + UINT64 MaxDur; + EFI_STRING StringPtr; + UINTN TIndex; + EFI_STRING StringPtrUnknown; + + StringPtrUnknown = HiiGetString (mDpHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL); + StringPtr = HiiGetString (mDpHiiHandle, STRING_TOKEN (STR_DP_SECTION_CUMULATIVE), NULL); + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_SECTION_HEADER), mDpHiiHandle, + (StringPtr == NULL) ? StringPtrUnknown: StringPtr); + FreePool (StringPtr); + FreePool (StringPtrUnknown); + + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_CUMULATIVE_SECT_1), mDpHiiHandle); + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_CUMULATIVE_SECT_2), mDpHiiHandle); + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_DASHES), mDpHiiHandle); + + for ( TIndex = 0; TIndex < NumCum; ++TIndex) { + if (CumData[TIndex].Count != 0) { + AvgDur = DivU64x32 (CumData[TIndex].Duration, CumData[TIndex].Count); + AvgDur = DurationInMicroSeconds(AvgDur); + Dur = DurationInMicroSeconds(CumData[TIndex].Duration); + MaxDur = DurationInMicroSeconds(CumData[TIndex].MaxDur); + MinDur = DurationInMicroSeconds(CumData[TIndex].MinDur); + + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_CUMULATIVE_STATS), mDpHiiHandle, + CumData[TIndex].Name, + CumData[TIndex].Count, + Dur, + AvgDur, + MinDur, + MaxDur + ); + } + } + + // + // Print the custom cumulative data. + // + if (CustomCumulativeData != NULL) { + if (CustomCumulativeData->Count != 0) { + AvgDur = DivU64x32 (CustomCumulativeData->Duration, CustomCumulativeData->Count); + AvgDur = DurationInMicroSeconds (AvgDur); + Dur = DurationInMicroSeconds (CustomCumulativeData->Duration); + MaxDur = DurationInMicroSeconds (CustomCumulativeData->MaxDur); + MinDur = DurationInMicroSeconds (CustomCumulativeData->MinDur); + } else { + AvgDur = 0; + Dur = 0; + MaxDur = 0; + MinDur = 0; + } + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_CUMULATIVE_STATS), mDpHiiHandle, + CustomCumulativeData->Name, + CustomCumulativeData->Count, + Dur, + AvgDur, + MinDur, + MaxDur + ); + } +} diff --git a/src/VBox/Devices/EFI/Firmware/ShellPkg/DynamicCommand/DpDynamicCommand/DpUtilities.c b/src/VBox/Devices/EFI/Firmware/ShellPkg/DynamicCommand/DpDynamicCommand/DpUtilities.c new file mode 100644 index 00000000..8d84e69b --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/ShellPkg/DynamicCommand/DpDynamicCommand/DpUtilities.c @@ -0,0 +1,422 @@ +/** @file + Utility functions used by the Dp application. + + 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 <Library/BaseLib.h> +#include <Library/BaseMemoryLib.h> +#include <Library/MemoryAllocationLib.h> +#include <Library/DebugLib.h> +#include <Library/UefiBootServicesTableLib.h> +#include <Library/PeCoffGetEntryPointLib.h> +#include <Library/PrintLib.h> +#include <Library/HiiLib.h> +#include <Library/PcdLib.h> +#include <Library/UefiLib.h> +#include <Library/DevicePathLib.h> +#include <Library/HandleParsingLib.h> + +#include <Pi/PiFirmwareFile.h> +#include <Library/DxeServicesLib.h> + +#include <Protocol/LoadedImage.h> +#include <Protocol/DriverBinding.h> +#include <Protocol/ComponentName2.h> +#include <Protocol/DevicePath.h> + +#include <Guid/Performance.h> + +#include "Dp.h" +#include "Literals.h" +#include "DpInternal.h" + +/** + Calculate an event's duration in timer ticks. + + Given the count direction and the event's start and end timer values, + calculate the duration of the event in timer ticks. Information for + the current measurement is pointed to by the parameter. + + If the measurement's start time is 1, it indicates that the developer + is indicating that the measurement began at the release of reset. + The start time is adjusted to the timer's starting count before performing + the elapsed time calculation. + + The calculated duration, in ticks, is the absolute difference between + the measurement's ending and starting counts. + + @param Measurement Pointer to a MEASUREMENT_RECORD structure containing + data for the current measurement. + + @return The 64-bit duration of the event. +**/ +UINT64 +GetDuration ( + IN OUT MEASUREMENT_RECORD *Measurement + ) +{ + UINT64 Duration; + BOOLEAN Error; + + if (Measurement->EndTimeStamp == 0) { + return 0; + } + + Duration = Measurement->EndTimeStamp - Measurement->StartTimeStamp; + Error = (BOOLEAN)(Duration > Measurement->EndTimeStamp); + + if (Error) { + DEBUG ((EFI_D_ERROR, ALit_TimerLibError)); + Duration = 0; + } + return Duration; +} + +/** + Determine whether the Measurement record is for an EFI Phase. + + The Token and Module members of the measurement record are checked. + Module must be empty and Token must be one of SEC, PEI, DXE, BDS, or SHELL. + + @param[in] Measurement A pointer to the Measurement record to test. + + @retval TRUE The measurement record is for an EFI Phase. + @retval FALSE The measurement record is NOT for an EFI Phase. +**/ +BOOLEAN +IsPhase( + IN MEASUREMENT_RECORD *Measurement + ) +{ + BOOLEAN RetVal; + + RetVal = (BOOLEAN)( + ((AsciiStrCmp (Measurement->Token, ALit_SEC) == 0) || + (AsciiStrCmp (Measurement->Token, ALit_PEI) == 0) || + (AsciiStrCmp (Measurement->Token, ALit_DXE) == 0) || + (AsciiStrCmp (Measurement->Token, ALit_BDS) == 0)) + ); + return RetVal; +} + +/** + Determine whether the Measurement record is for core code. + + @param[in] Measurement A pointer to the Measurement record to test. + + @retval TRUE The measurement record is used for core. + @retval FALSE The measurement record is NOT used for core. + +**/ +BOOLEAN +IsCorePerf( + IN MEASUREMENT_RECORD *Measurement + ) +{ + BOOLEAN RetVal; + + RetVal = (BOOLEAN)( + ((Measurement->Identifier == MODULE_START_ID) || + (Measurement->Identifier == MODULE_END_ID) || + (Measurement->Identifier == MODULE_LOADIMAGE_START_ID) || + (Measurement->Identifier == MODULE_LOADIMAGE_END_ID) || + (Measurement->Identifier == MODULE_DB_START_ID) || + (Measurement->Identifier == MODULE_DB_END_ID) || + (Measurement->Identifier == MODULE_DB_SUPPORT_START_ID) || + (Measurement->Identifier == MODULE_DB_SUPPORT_END_ID) || + (Measurement->Identifier == MODULE_DB_STOP_START_ID) || + (Measurement->Identifier == MODULE_DB_STOP_START_ID)) + ); + return RetVal; +} + +/** + Get the file name portion of the Pdb File Name. + + The portion of the Pdb File Name between the last backslash and + either a following period or the end of the string is converted + to Unicode and copied into UnicodeBuffer. The name is truncated, + if necessary, to ensure that UnicodeBuffer is not overrun. + + @param[in] PdbFileName Pdb file name. + @param[out] UnicodeBuffer The resultant Unicode File Name. + +**/ +VOID +DpGetShortPdbFileName ( + IN CHAR8 *PdbFileName, + OUT CHAR16 *UnicodeBuffer + ) +{ + UINTN IndexA; // Current work location within an ASCII string. + UINTN IndexU; // Current work location within a Unicode string. + UINTN StartIndex; + UINTN EndIndex; + + ZeroMem (UnicodeBuffer, (DP_GAUGE_STRING_LENGTH + 1) * sizeof (CHAR16)); + + if (PdbFileName == NULL) { + StrnCpyS (UnicodeBuffer, DP_GAUGE_STRING_LENGTH + 1, L" ", 1); + } else { + StartIndex = 0; + for (EndIndex = 0; PdbFileName[EndIndex] != 0; EndIndex++) + ; + for (IndexA = 0; PdbFileName[IndexA] != 0; IndexA++) { + if ((PdbFileName[IndexA] == '\\') || (PdbFileName[IndexA] == '/')) { + StartIndex = IndexA + 1; + } + + if (PdbFileName[IndexA] == '.') { + EndIndex = IndexA; + } + } + + IndexU = 0; + for (IndexA = StartIndex; IndexA < EndIndex; IndexA++) { + UnicodeBuffer[IndexU] = (CHAR16) PdbFileName[IndexA]; + IndexU++; + if (IndexU >= DP_GAUGE_STRING_LENGTH) { + UnicodeBuffer[DP_GAUGE_STRING_LENGTH] = 0; + break; + } + } + } +} + +/** + Get a human readable name for an image handle. + The following methods will be tried orderly: + 1. Image PDB + 2. ComponentName2 protocol + 3. FFS UI section + 4. Image GUID + 5. Image DevicePath + 6. Unknown Driver Name + + @param[in] Handle + + @post The resulting Unicode name string is stored in the + mGaugeString global array. + +**/ +VOID +DpGetNameFromHandle ( + IN EFI_HANDLE Handle + ) +{ + EFI_STATUS Status; + EFI_LOADED_IMAGE_PROTOCOL *Image; + CHAR8 *PdbFileName; + EFI_DRIVER_BINDING_PROTOCOL *DriverBinding; + EFI_STRING StringPtr; + EFI_DEVICE_PATH_PROTOCOL *LoadedImageDevicePath; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_GUID *NameGuid; + CHAR16 *NameString; + UINTN StringSize; + CHAR8 *PlatformLanguage; + CHAR8 *BestLanguage; + EFI_COMPONENT_NAME2_PROTOCOL *ComponentName2; + + Image = NULL; + LoadedImageDevicePath = NULL; + DevicePath = NULL; + + // + // Method 1: Get the name string from image PDB + // + Status = gBS->HandleProtocol ( + Handle, + &gEfiLoadedImageProtocolGuid, + (VOID **) &Image + ); + + if (EFI_ERROR (Status)) { + Status = gBS->OpenProtocol ( + Handle, + &gEfiDriverBindingProtocolGuid, + (VOID **) &DriverBinding, + NULL, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (!EFI_ERROR (Status)) { + Status = gBS->HandleProtocol ( + DriverBinding->ImageHandle, + &gEfiLoadedImageProtocolGuid, + (VOID **) &Image + ); + } + } + + if (!EFI_ERROR (Status)) { + PdbFileName = PeCoffLoaderGetPdbPointer (Image->ImageBase); + + if (PdbFileName != NULL) { + DpGetShortPdbFileName (PdbFileName, mGaugeString); + return; + } + } + + // + // Method 2: Get the name string from ComponentName2 protocol + // + Status = gBS->HandleProtocol ( + Handle, + &gEfiComponentName2ProtocolGuid, + (VOID **) &ComponentName2 + ); + if (!EFI_ERROR (Status)) { + // + // Firstly use platform language setting, secondly use driver's first supported language. + // + GetVariable2 (L"PlatformLang", &gEfiGlobalVariableGuid, (VOID**)&PlatformLanguage, NULL); + BestLanguage = GetBestLanguage( + ComponentName2->SupportedLanguages, + FALSE, + (PlatformLanguage != NULL) ? PlatformLanguage : "", + ComponentName2->SupportedLanguages, + NULL + ); + SHELL_FREE_NON_NULL (PlatformLanguage); + + Status = ComponentName2->GetDriverName ( + ComponentName2, + BestLanguage != NULL ? BestLanguage : "en-US", + &StringPtr + ); + if (!EFI_ERROR (Status)) { + SHELL_FREE_NON_NULL (BestLanguage); + StrnCpyS (mGaugeString, DP_GAUGE_STRING_LENGTH + 1, StringPtr, DP_GAUGE_STRING_LENGTH); + mGaugeString[DP_GAUGE_STRING_LENGTH] = 0; + return; + } + } + + Status = gBS->HandleProtocol ( + Handle, + &gEfiLoadedImageDevicePathProtocolGuid, + (VOID **) &LoadedImageDevicePath + ); + if (!EFI_ERROR (Status) && (LoadedImageDevicePath != NULL)) { + DevicePath = LoadedImageDevicePath; + } else if (Image != NULL) { + DevicePath = Image->FilePath; + } + + if (DevicePath != NULL) { + // + // Try to get image GUID from image DevicePath + // + NameGuid = NULL; + while (!IsDevicePathEndType (DevicePath)) { + NameGuid = EfiGetNameGuidFromFwVolDevicePathNode ((MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) DevicePath); + if (NameGuid != NULL) { + break; + } + DevicePath = NextDevicePathNode (DevicePath); + } + + if (NameGuid != NULL) { + // + // Try to get the image's FFS UI section by image GUID + // + NameString = NULL; + StringSize = 0; + Status = GetSectionFromAnyFv ( + NameGuid, + EFI_SECTION_USER_INTERFACE, + 0, + (VOID **) &NameString, + &StringSize + ); + + if (!EFI_ERROR (Status)) { + // + // Method 3. Get the name string from FFS UI section + // + StrnCpyS (mGaugeString, DP_GAUGE_STRING_LENGTH + 1, NameString, DP_GAUGE_STRING_LENGTH); + mGaugeString[DP_GAUGE_STRING_LENGTH] = 0; + FreePool (NameString); + } else { + // + // Method 4: Get the name string from image GUID + // + UnicodeSPrint (mGaugeString, sizeof (mGaugeString), L"%g", NameGuid); + } + return; + } else { + // + // Method 5: Get the name string from image DevicePath + // + NameString = ConvertDevicePathToText (DevicePath, TRUE, FALSE); + if (NameString != NULL) { + StrnCpyS (mGaugeString, DP_GAUGE_STRING_LENGTH + 1, NameString, DP_GAUGE_STRING_LENGTH); + mGaugeString[DP_GAUGE_STRING_LENGTH] = 0; + FreePool (NameString); + return; + } + } + } + + // + // Method 6: Unknown Driver Name + // + StringPtr = HiiGetString (mDpHiiHandle, STRING_TOKEN (STR_DP_ERROR_NAME), NULL); + ASSERT (StringPtr != NULL); + StrnCpyS (mGaugeString, DP_GAUGE_STRING_LENGTH + 1, StringPtr, DP_GAUGE_STRING_LENGTH); + FreePool (StringPtr); +} + +/** + Calculate the Duration in microseconds. + + Duration is multiplied by 1000, instead of Frequency being divided by 1000 or + multiplying the result by 1000, in order to maintain precision. Since Duration is + a 64-bit value, multiplying it by 1000 is unlikely to produce an overflow. + + The time is calculated as (Duration * 1000) / Timer_Frequency. + + @param[in] Duration The event duration in timer ticks. + + @return A 64-bit value which is the Elapsed time in microseconds. +**/ +UINT64 +DurationInMicroSeconds ( + IN UINT64 Duration + ) +{ + return DivU64x32 (Duration, 1000); +} + +/** + Get index of Measurement Record's match in the CumData array. + + If the Measurement's Token value matches a Token in one of the CumData + records, the index of the matching record is returned. The returned + index is a signed value so that negative values can indicate that + the Measurement didn't match any entry in the CumData array. + + @param[in] Measurement A pointer to a Measurement Record to match against the CumData array. + + @retval <0 Token is not in the CumData array. + @retval >=0 Return value is the index into CumData where Token is found. +**/ +INTN +GetCumulativeItem( + IN MEASUREMENT_RECORD *Measurement + ) +{ + INTN Index; + + for( Index = 0; Index < (INTN)NumCum; ++Index) { + if (AsciiStrCmp (Measurement->Token, CumData[Index].Name) == 0) { + return Index; // Exit, we found a match + } + } + // If the for loop exits, Token was not found. + return -1; // Indicate failure +} diff --git a/src/VBox/Devices/EFI/Firmware/ShellPkg/DynamicCommand/DpDynamicCommand/Literals.c b/src/VBox/Devices/EFI/Firmware/ShellPkg/DynamicCommand/DpDynamicCommand/Literals.c new file mode 100644 index 00000000..ec99fe4b --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/ShellPkg/DynamicCommand/DpDynamicCommand/Literals.c @@ -0,0 +1,22 @@ +/** @file + Definitions of ASCII string literals used by DP. + + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR> + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ +#include <Guid/ExtendedFirmwarePerformance.h> + +// ASCII String literals which probably don't need translation +CHAR8 const ALit_TimerLibError[] = "Timer library instance error!\n"; +CHAR8 const ALit_SEC[] = SEC_TOK; +CHAR8 const ALit_DXE[] = DXE_TOK; +CHAR8 const ALit_PEI[] = PEI_TOK; +CHAR8 const ALit_BDS[] = BDS_TOK; +CHAR8 const ALit_START_IMAGE[] = START_IMAGE_TOK; +CHAR8 const ALit_LOAD_IMAGE[] = LOAD_IMAGE_TOK; +CHAR8 const ALit_DB_START[] = DRIVERBINDING_START_TOK; +CHAR8 const ALit_DB_SUPPORT[] = DRIVERBINDING_SUPPORT_TOK; +CHAR8 const ALit_DB_STOP[] = DRIVERBINDING_STOP_TOK; + +CHAR8 const ALit_BdsTO[] = "BdsTimeOut"; +CHAR8 const ALit_PEIM[] = "PEIM"; diff --git a/src/VBox/Devices/EFI/Firmware/ShellPkg/DynamicCommand/DpDynamicCommand/Literals.h b/src/VBox/Devices/EFI/Firmware/ShellPkg/DynamicCommand/DpDynamicCommand/Literals.h new file mode 100644 index 00000000..c0ef8791 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/ShellPkg/DynamicCommand/DpDynamicCommand/Literals.h @@ -0,0 +1,26 @@ +/** @file + Declarations of ASCII string literals used by DP. + + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR> + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ +#ifndef _LITERALS_H_ +#define _LITERALS_H_ + +// ASCII String literals which probably don't need translation +extern CHAR8 const ALit_TimerLibError[]; +extern CHAR8 const ALit_SEC[]; +extern CHAR8 const ALit_DXE[]; +extern CHAR8 const ALit_SHELL[]; +extern CHAR8 const ALit_PEI[]; +extern CHAR8 const ALit_BDS[]; +extern CHAR8 const ALit_PEIM[]; +extern CHAR8 const ALit_START_IMAGE[]; +extern CHAR8 const ALit_LOAD_IMAGE[]; +extern CHAR8 const ALit_DB_START[]; +extern CHAR8 const ALit_DB_SUPPORT[]; +extern CHAR8 const ALit_DB_STOP[]; +extern CHAR8 const ALit_BdsTO[]; +extern CHAR8 const ALit_PEIM[]; + +#endif // _LITERALS_H_ |