--- /dev/null
+/** @file\r
+ Shell command for Displaying Performance Metrics.\r
+\r
+ The Dp command reads performance data and presents it in several\r
+ different formats depending upon the needs of the user. Both\r
+ Trace and Measured Profiling information is processed and presented.\r
+\r
+ Dp uses the "PerformanceLib" to read the measurement records.\r
+ The "TimerLib" provides information about the timer, such as frequency,\r
+ beginning, and ending counter values.\r
+ Measurement records contain identifying information (Handle, Token, Module)\r
+ and start and end time values.\r
+ Dp uses this information to group records in different ways. It also uses\r
+ timer information to calculate elapsed time for each measurement.\r
+ \r
+ Copyright (c) 2009 - 2017, Intel Corporation. All rights reserved.\r
+ (C) Copyright 2015-2016 Hewlett Packard Enterprise Development LP<BR>\r
+ This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php\r
+ \r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+**/\r
+\r
+#include "PerformanceTokens.h"\r
+#include "Dp.h"\r
+#include "Literals.h"\r
+#include "DpInternal.h"\r
+\r
+EFI_HANDLE mDpHiiHandle;\r
+\r
+//\r
+/// Module-Global Variables\r
+///@{\r
+CHAR16 mGaugeString[DP_GAUGE_STRING_LENGTH + 1];\r
+CHAR16 mUnicodeToken[DXE_PERFORMANCE_STRING_SIZE];\r
+UINT64 mInterestThreshold;\r
+BOOLEAN mShowId = FALSE;\r
+\r
+PERF_SUMMARY_DATA SummaryData = { 0 }; ///< Create the SummaryData structure and init. to ZERO.\r
+\r
+/// Timer Specific Information.\r
+TIMER_INFO TimerInfo;\r
+\r
+/// Items for which to gather cumulative statistics.\r
+PERF_CUM_DATA CumData[] = {\r
+ PERF_INIT_CUM_DATA (LOAD_IMAGE_TOK),\r
+ PERF_INIT_CUM_DATA (START_IMAGE_TOK),\r
+ PERF_INIT_CUM_DATA (DRIVERBINDING_START_TOK),\r
+ PERF_INIT_CUM_DATA (DRIVERBINDING_SUPPORT_TOK)\r
+};\r
+\r
+/// Number of items for which we are gathering cumulative statistics.\r
+UINT32 const NumCum = sizeof(CumData) / sizeof(PERF_CUM_DATA);\r
+\r
+STATIC CONST SHELL_PARAM_ITEM ParamList[] = {\r
+ {L"-v", TypeFlag}, // -v Verbose Mode\r
+ {L"-A", TypeFlag}, // -A All, Cooked\r
+ {L"-R", TypeFlag}, // -R RAW All\r
+ {L"-s", TypeFlag}, // -s Summary\r
+#if PROFILING_IMPLEMENTED\r
+ {L"-P", TypeFlag}, // -P Dump Profile Data\r
+ {L"-T", TypeFlag}, // -T Dump Trace Data\r
+#endif // PROFILING_IMPLEMENTED\r
+ {L"-x", TypeFlag}, // -x eXclude Cumulative Items\r
+ {L"-i", TypeFlag}, // -i Display Identifier\r
+ {L"-c", TypeValue}, // -c Display cumulative data.\r
+ {L"-n", TypeValue}, // -n # Number of records to display for A and R\r
+ {L"-t", TypeValue}, // -t # Threshold of interest\r
+ {NULL, TypeMax}\r
+ };\r
+\r
+///@}\r
+\r
+/**\r
+ Display the trailing Verbose information.\r
+**/\r
+VOID\r
+DumpStatistics( void )\r
+{\r
+ EFI_STRING StringPtr;\r
+ EFI_STRING StringPtrUnknown;\r
+ StringPtr = HiiGetString (mDpHiiHandle, STRING_TOKEN (STR_DP_SECTION_STATISTICS), NULL);\r
+ StringPtrUnknown = HiiGetString (mDpHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL);\r
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_SECTION_HEADER), mDpHiiHandle,\r
+ (StringPtr == NULL) ? StringPtrUnknown : StringPtr);\r
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_STATS_NUMTRACE), mDpHiiHandle, SummaryData.NumTrace);\r
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_STATS_NUMINCOMPLETE), mDpHiiHandle, SummaryData.NumIncomplete);\r
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_STATS_NUMPHASES), mDpHiiHandle, SummaryData.NumSummary);\r
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_STATS_NUMHANDLES), mDpHiiHandle, SummaryData.NumHandles, SummaryData.NumTrace - SummaryData.NumHandles);\r
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_STATS_NUMPEIMS), mDpHiiHandle, SummaryData.NumPEIMs);\r
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_STATS_NUMGLOBALS), mDpHiiHandle, SummaryData.NumGlobal);\r
+#if PROFILING_IMPLEMENTED\r
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_STATS_NUMPROFILE), mDpHiiHandle, SummaryData.NumProfile);\r
+#endif // PROFILING_IMPLEMENTED\r
+ SHELL_FREE_NON_NULL (StringPtr);\r
+ SHELL_FREE_NON_NULL (StringPtrUnknown);\r
+}\r
+\r
+/**\r
+ Initialize the cumulative data.\r
+\r
+**/\r
+VOID\r
+InitCumulativeData (\r
+ VOID\r
+ )\r
+{\r
+ UINTN Index;\r
+\r
+ for (Index = 0; Index < NumCum; ++Index) {\r
+ CumData[Index].Count = 0;\r
+ CumData[Index].MinDur = PERF_MAXDUR;\r
+ CumData[Index].MaxDur = 0;\r
+ CumData[Index].Duration = 0;\r
+ }\r
+}\r
+\r
+/**\r
+ Dump performance data.\r
+ \r
+ @param[in] ImageHandle The image handle.\r
+ @param[in] SystemTable The system table.\r
+ \r
+ @retval SHELL_SUCCESS Command completed successfully.\r
+ @retval SHELL_INVALID_PARAMETER Command usage error.\r
+ @retval SHELL_ABORTED The user aborts the operation.\r
+ @retval value Unknown error.\r
+**/\r
+SHELL_STATUS\r
+RunDp (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+ )\r
+{\r
+ LIST_ENTRY *ParamPackage;\r
+ CONST CHAR16 *CmdLineArg;\r
+ EFI_STATUS Status;\r
+\r
+ PERFORMANCE_PROPERTY *PerformanceProperty;\r
+ UINTN Number2Display;\r
+\r
+ EFI_STRING StringPtr;\r
+ BOOLEAN SummaryMode;\r
+ BOOLEAN VerboseMode;\r
+ BOOLEAN AllMode;\r
+ BOOLEAN RawMode;\r
+ BOOLEAN TraceMode;\r
+ BOOLEAN ProfileMode;\r
+ BOOLEAN ExcludeMode;\r
+ BOOLEAN CumulativeMode;\r
+ CONST CHAR16 *CustomCumulativeToken;\r
+ PERF_CUM_DATA *CustomCumulativeData;\r
+ UINTN NameSize;\r
+ SHELL_STATUS ShellStatus;\r
+\r
+ StringPtr = NULL;\r
+ SummaryMode = FALSE;\r
+ VerboseMode = FALSE;\r
+ AllMode = FALSE;\r
+ RawMode = FALSE;\r
+ TraceMode = FALSE;\r
+ ProfileMode = FALSE;\r
+ ExcludeMode = FALSE;\r
+ CumulativeMode = FALSE;\r
+ CustomCumulativeData = NULL;\r
+ ShellStatus = SHELL_SUCCESS;\r
+\r
+ //\r
+ // initialize the shell lib (we must be in non-auto-init...)\r
+ //\r
+ Status = ShellInitialize();\r
+ ASSERT_EFI_ERROR(Status);\r
+\r
+ //\r
+ // Process Command Line arguments\r
+ //\r
+ Status = ShellCommandLineParse (ParamList, &ParamPackage, NULL, TRUE);\r
+ if (EFI_ERROR(Status)) {\r
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_INVALID_ARG), mDpHiiHandle);\r
+ return SHELL_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Boolean options\r
+ //\r
+ VerboseMode = ShellCommandLineGetFlag (ParamPackage, L"-v");\r
+ SummaryMode = (BOOLEAN) (ShellCommandLineGetFlag (ParamPackage, L"-S") || ShellCommandLineGetFlag (ParamPackage, L"-s"));\r
+ AllMode = ShellCommandLineGetFlag (ParamPackage, L"-A");\r
+ RawMode = ShellCommandLineGetFlag (ParamPackage, L"-R");\r
+#if PROFILING_IMPLEMENTED\r
+ TraceMode = ShellCommandLineGetFlag (ParamPackage, L"-T");\r
+ ProfileMode = ShellCommandLineGetFlag (ParamPackage, L"-P");\r
+#endif // PROFILING_IMPLEMENTED\r
+ ExcludeMode = ShellCommandLineGetFlag (ParamPackage, L"-x");\r
+ mShowId = ShellCommandLineGetFlag (ParamPackage, L"-i");\r
+ CumulativeMode = ShellCommandLineGetFlag (ParamPackage, L"-c");\r
+\r
+ // Options with Values\r
+ CmdLineArg = ShellCommandLineGetValue (ParamPackage, L"-n");\r
+ if (CmdLineArg == NULL) {\r
+ Number2Display = DEFAULT_DISPLAYCOUNT;\r
+ } else {\r
+ Number2Display = StrDecimalToUintn(CmdLineArg);\r
+ if (Number2Display == 0) {\r
+ Number2Display = MAXIMUM_DISPLAYCOUNT;\r
+ }\r
+ }\r
+\r
+ CmdLineArg = ShellCommandLineGetValue (ParamPackage, L"-t");\r
+ if (CmdLineArg == NULL) {\r
+ mInterestThreshold = DEFAULT_THRESHOLD; // 1ms := 1,000 us\r
+ } else {\r
+ mInterestThreshold = StrDecimalToUint64(CmdLineArg);\r
+ }\r
+\r
+ // Handle Flag combinations and default behaviors\r
+ // If both TraceMode and ProfileMode are FALSE, set them both to TRUE\r
+ if ((! TraceMode) && (! ProfileMode)) {\r
+ TraceMode = TRUE;\r
+#if PROFILING_IMPLEMENTED\r
+ ProfileMode = TRUE;\r
+#endif // PROFILING_IMPLEMENTED\r
+ }\r
+\r
+ //\r
+ // Initialize the pre-defined cumulative data.\r
+ //\r
+ InitCumulativeData ();\r
+\r
+ //\r
+ // Init the custom cumulative data.\r
+ //\r
+ CustomCumulativeToken = ShellCommandLineGetValue (ParamPackage, L"-c");\r
+ if (CustomCumulativeToken != NULL) {\r
+ CustomCumulativeData = AllocateZeroPool (sizeof (PERF_CUM_DATA));\r
+ if (CustomCumulativeData == NULL) {\r
+ return SHELL_OUT_OF_RESOURCES;\r
+ }\r
+ CustomCumulativeData->MinDur = PERF_MAXDUR;\r
+ CustomCumulativeData->MaxDur = 0;\r
+ CustomCumulativeData->Count = 0;\r
+ CustomCumulativeData->Duration = 0;\r
+ NameSize = StrLen (CustomCumulativeToken) + 1;\r
+ CustomCumulativeData->Name = AllocateZeroPool (NameSize);\r
+ if (CustomCumulativeData->Name == NULL) {\r
+ FreePool (CustomCumulativeData);\r
+ return SHELL_OUT_OF_RESOURCES;\r
+ }\r
+ UnicodeStrToAsciiStrS (CustomCumulativeToken, CustomCumulativeData->Name, NameSize);\r
+ }\r
+\r
+ //\r
+ // Timer specific processing\r
+ //\r
+ // Get the Performance counter characteristics:\r
+ // Freq = Frequency in Hz\r
+ // StartCount = Value loaded into the counter when it starts counting\r
+ // EndCount = Value counter counts to before it needs to be reset\r
+ //\r
+ Status = EfiGetSystemConfigurationTable (&gPerformanceProtocolGuid, (VOID **) &PerformanceProperty);\r
+ if (EFI_ERROR (Status) || (PerformanceProperty == NULL)) {\r
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PERF_PROPERTY_NOT_FOUND), mDpHiiHandle);\r
+ goto Done;\r
+ }\r
+\r
+ TimerInfo.Frequency = (UINT32)DivU64x32 (PerformanceProperty->Frequency, 1000);\r
+ TimerInfo.StartCount = PerformanceProperty->TimerStartValue;\r
+ TimerInfo.EndCount = PerformanceProperty->TimerEndValue;\r
+\r
+ // Determine in which direction the performance counter counts.\r
+ TimerInfo.CountUp = (BOOLEAN) (TimerInfo.EndCount >= TimerInfo.StartCount);\r
+\r
+ //\r
+ // Print header\r
+ //\r
+ // print DP's build version\r
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_BUILD_REVISION), mDpHiiHandle, DP_MAJOR_VERSION, DP_MINOR_VERSION);\r
+\r
+ // print performance timer characteristics\r
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_KHZ), mDpHiiHandle, TimerInfo.Frequency);\r
+\r
+ if (VerboseMode && !RawMode) {\r
+ StringPtr = HiiGetString (mDpHiiHandle,\r
+ (EFI_STRING_ID) (TimerInfo.CountUp ? STRING_TOKEN (STR_DP_UP) : STRING_TOKEN (STR_DP_DOWN)), NULL);\r
+ ASSERT (StringPtr != NULL);\r
+ // Print Timer count range and direction\r
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_TIMER_PROPERTIES), mDpHiiHandle,\r
+ StringPtr,\r
+ TimerInfo.StartCount,\r
+ TimerInfo.EndCount\r
+ );\r
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_VERBOSE_THRESHOLD), mDpHiiHandle, mInterestThreshold);\r
+ }\r
+\r
+/****************************************************************************\r
+**** Print Sections based on command line options\r
+****\r
+**** Option modes have the following priority:\r
+**** v Verbose -- Valid in combination with any other options\r
+**** t Threshold -- Modifies All, Raw, and Cooked output\r
+**** Default is 0 for All and Raw mode\r
+**** Default is DEFAULT_THRESHOLD for "Cooked" mode\r
+**** n Number2Display Used by All and Raw mode. Otherwise ignored.\r
+**** A All -- R and S options are ignored\r
+**** R Raw -- S option is ignored\r
+**** s Summary -- Modifies "Cooked" output only\r
+**** Cooked (Default)\r
+****\r
+**** The All, Raw, and Cooked modes are modified by the Trace and Profile\r
+**** options.\r
+**** !T && !P := (0) Default, Both are displayed\r
+**** T && !P := (1) Only Trace records are displayed\r
+**** !T && P := (2) Only Profile records are displayed\r
+**** T && P := (3) Same as Default, both are displayed\r
+****************************************************************************/\r
+ GatherStatistics (CustomCumulativeData);\r
+ if (CumulativeMode) { \r
+ ProcessCumulative (CustomCumulativeData);\r
+ } else if (AllMode) {\r
+ if (TraceMode) {\r
+ Status = DumpAllTrace( Number2Display, ExcludeMode);\r
+ if (Status == EFI_ABORTED) {\r
+ ShellStatus = SHELL_ABORTED;\r
+ goto Done;\r
+ }\r
+ }\r
+ if (ProfileMode) {\r
+ DumpAllProfile( Number2Display, ExcludeMode);\r
+ }\r
+ } else if (RawMode) {\r
+ if (TraceMode) {\r
+ Status = DumpRawTrace( Number2Display, ExcludeMode);\r
+ if (Status == EFI_ABORTED) {\r
+ ShellStatus = SHELL_ABORTED;\r
+ goto Done;\r
+ }\r
+ }\r
+ if (ProfileMode) {\r
+ DumpRawProfile( Number2Display, ExcludeMode);\r
+ }\r
+ } else {\r
+ //------------- Begin Cooked Mode Processing\r
+ if (TraceMode) {\r
+ ProcessPhases ();\r
+ if ( ! SummaryMode) {\r
+ Status = ProcessHandles ( ExcludeMode);\r
+ if (Status == EFI_ABORTED) {\r
+ ShellStatus = SHELL_ABORTED;\r
+ goto Done;\r
+ }\r
+\r
+ Status = ProcessPeims ();\r
+ if (Status == EFI_ABORTED) {\r
+ ShellStatus = SHELL_ABORTED;\r
+ goto Done;\r
+ }\r
+\r
+ Status = ProcessGlobal ();\r
+ if (Status == EFI_ABORTED) {\r
+ ShellStatus = SHELL_ABORTED;\r
+ goto Done;\r
+ }\r
+\r
+ ProcessCumulative (NULL);\r
+ }\r
+ }\r
+ if (ProfileMode) {\r
+ DumpAllProfile( Number2Display, ExcludeMode);\r
+ }\r
+ } //------------- End of Cooked Mode Processing\r
+ if ( VerboseMode || SummaryMode) {\r
+ DumpStatistics();\r
+ }\r
+\r
+Done:\r
+ if (ParamPackage != NULL) {\r
+ ShellCommandLineFreeVarList (ParamPackage);\r
+ }\r
+ SHELL_FREE_NON_NULL (StringPtr);\r
+ if (CustomCumulativeData != NULL) {\r
+ SHELL_FREE_NON_NULL (CustomCumulativeData->Name);\r
+ }\r
+ SHELL_FREE_NON_NULL (CustomCumulativeData);\r
+\r
+ return ShellStatus;\r
+}\r
+\r
+\r
+/**\r
+ Retrive HII package list from ImageHandle and publish to HII database.\r
+\r
+ @param ImageHandle The image handle of the process.\r
+\r
+ @return HII handle.\r
+**/\r
+EFI_HANDLE\r
+InitializeHiiPackage (\r
+ EFI_HANDLE ImageHandle\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_HII_PACKAGE_LIST_HEADER *PackageList;\r
+ EFI_HANDLE HiiHandle;\r
+\r
+ //\r
+ // Retrieve HII package list from ImageHandle\r
+ //\r
+ Status = gBS->OpenProtocol (\r
+ ImageHandle,\r
+ &gEfiHiiPackageListProtocolGuid,\r
+ (VOID **)&PackageList,\r
+ ImageHandle,\r
+ NULL,\r
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+ if (EFI_ERROR (Status)) {\r
+ return NULL;\r
+ }\r
+\r
+ //\r
+ // Publish HII package list to HII Database.\r
+ //\r
+ Status = gHiiDatabase->NewPackageList (\r
+ gHiiDatabase,\r
+ PackageList,\r
+ NULL,\r
+ &HiiHandle\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+ if (EFI_ERROR (Status)) {\r
+ return NULL;\r
+ }\r
+ return HiiHandle;\r
+}\r