]> git.proxmox.com Git - mirror_edk2.git/blobdiff - ShellPkg/DynamicCommand/DpDynamicCommand/Dp.c
ShellPkg/dp: Convert from NULL class library to Dynamic Command
[mirror_edk2.git] / ShellPkg / DynamicCommand / DpDynamicCommand / Dp.c
diff --git a/ShellPkg/DynamicCommand/DpDynamicCommand/Dp.c b/ShellPkg/DynamicCommand/DpDynamicCommand/Dp.c
new file mode 100644 (file)
index 0000000..3ecc753
--- /dev/null
@@ -0,0 +1,438 @@
+/** @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