--- /dev/null
+/** @file\r
+ * Shell application for Displaying Performance Metrics.\r
+ *\r
+ * The Dp application 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-2010, Intel Corporation. All rights reserved.<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 <Library/UefiApplicationEntryPoint.h>\r
+#include <Library/ShellLib.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/TimerLib.h>\r
+#include <Library/UefiLib.h>\r
+#include <Library/HiiLib.h>\r
+#include <Library/PcdLib.h>\r
+\r
+#include <Guid/Performance.h>\r
+\r
+#include <PerformanceTokens.h>\r
+#include "Dp.h"\r
+#include "Literals.h"\r
+#include "DpInternal.h"\r
+\r
+//\r
+/// Module-Global Variables\r
+/// @{\r
+EFI_HII_HANDLE gHiiHandle;\r
+CHAR16 *mPrintTokenBuffer = NULL;\r
+CHAR16 mGaugeString[DXE_PERFORMANCE_STRING_SIZE];\r
+CHAR16 mUnicodeToken[PERF_TOKEN_LENGTH + 1];\r
+UINT64 mInterestThreshold;\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
+SHELL_PARAM_ITEM DpParamList[] = {\r
+ {STR_DP_OPTION_QH, TypeFlag}, // -? Help\r
+ {STR_DP_OPTION_LH, TypeFlag}, // -h Help\r
+ {STR_DP_OPTION_UH, TypeFlag}, // -H Help\r
+ {STR_DP_OPTION_LV, TypeFlag}, // -v Verbose Mode\r
+ {STR_DP_OPTION_UA, TypeFlag}, // -A All, Cooked\r
+ {STR_DP_OPTION_UR, TypeFlag}, // -R RAW All\r
+ {STR_DP_OPTION_LS, TypeFlag}, // -s Summary\r
+#if PROFILING_IMPLEMENTED\r
+ {STR_DP_OPTION_UP, TypeFlag}, // -P Dump Profile Data\r
+ {STR_DP_OPTION_UT, TypeFlag}, // -T Dump Trace Data\r
+#endif\r
+ {STR_DP_OPTION_LX, TypeFlag}, // -x eXclude Cumulative Items\r
+ {STR_DP_OPTION_LN, TypeValue}, // -n # Number of records to display for A and R\r
+ {STR_DP_OPTION_LT, TypeValue}, // -t # Threshold of interest\r
+ {NULL, TypeMax}\r
+ };\r
+\r
+/// @}\r
+\r
+/// Display Usage and Help information.\r
+VOID\r
+ShowHelp( void )\r
+{\r
+ PrintToken (STRING_TOKEN (STR_DP_HELP_HEAD));\r
+#if PROFILING_IMPLEMENTED\r
+ PrintToken (STRING_TOKEN (STR_DP_HELP_FLAGS));\r
+#else\r
+ PrintToken (STRING_TOKEN (STR_DP_HELP_FLAGS_2));\r
+#endif // PROFILING_IMPLEMENTED\r
+ PrintToken (STRING_TOKEN (STR_DP_HELP_PAGINATE));\r
+ PrintToken (STRING_TOKEN (STR_DP_HELP_VERBOSE));\r
+ PrintToken (STRING_TOKEN (STR_DP_HELP_EXCLUDE));\r
+ PrintToken (STRING_TOKEN (STR_DP_HELP_STAT));\r
+ PrintToken (STRING_TOKEN (STR_DP_HELP_ALL));\r
+ PrintToken (STRING_TOKEN (STR_DP_HELP_RAW));\r
+#if PROFILING_IMPLEMENTED\r
+ PrintToken (STRING_TOKEN (STR_DP_HELP_TRACE));\r
+ PrintToken (STRING_TOKEN (STR_DP_HELP_PROFILE));\r
+#endif // PROFILING_IMPLEMENTED\r
+ PrintToken (STRING_TOKEN (STR_DP_HELP_THRESHOLD));\r
+ PrintToken (STRING_TOKEN (STR_DP_HELP_COUNT));\r
+ PrintToken (STRING_TOKEN (STR_DP_HELP_HELP));\r
+ Print(L"\n");\r
+}\r
+\r
+/// Display the trailing Verbose information.\r
+VOID\r
+DumpStatistics( void )\r
+{\r
+ EFI_STRING StringPtr;\r
+\r
+ StringPtr = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_SECTION_STATISTICS), NULL);\r
+ PrintToken( STRING_TOKEN (STR_DP_SECTION_HEADER),\r
+ (StringPtr == NULL) ? ALit_UNKNOWN: StringPtr);\r
+\r
+ PrintToken( STRING_TOKEN (STR_DP_STATS_NUMTRACE), SummaryData.NumTrace);\r
+ PrintToken( STRING_TOKEN (STR_DP_STATS_NUMINCOMPLETE), SummaryData.NumIncomplete);\r
+ PrintToken( STRING_TOKEN (STR_DP_STATS_NUMPHASES), SummaryData.NumSummary);\r
+ PrintToken( STRING_TOKEN (STR_DP_STATS_NUMHANDLES), SummaryData.NumHandles, SummaryData.NumTrace - SummaryData.NumHandles);\r
+ PrintToken( STRING_TOKEN (STR_DP_STATS_NUMPEIMS), SummaryData.NumPEIMs);\r
+ PrintToken( STRING_TOKEN (STR_DP_STATS_NUMGLOBALS), SummaryData.NumGlobal);\r
+#if PROFILING_IMPLEMENTED\r
+ PrintToken( STRING_TOKEN (STR_DP_STATS_NUMPROFILE), SummaryData.NumProfile);\r
+#endif // PROFILING_IMPLEMENTED\r
+}\r
+\r
+/** Dump performance data.\r
+ *\r
+ * @param[in] ImageHandle The image handle.\r
+ * @param[in] SystemTable The system table.\r
+ *\r
+ * @retval EFI_SUCCESS Command completed successfully.\r
+ * @retval EFI_INVALID_PARAMETER Command usage error.\r
+ * @retval value Unknown error.\r
+ *\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+InitializeDp (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+ )\r
+{\r
+ UINT64 Freq;\r
+ UINT64 Ticker;\r
+\r
+ LIST_ENTRY *ParamPackage;\r
+ CONST CHAR16 *CmdLineArg;\r
+ EFI_STRING StringPtr;\r
+ UINTN Number2Display;\r
+\r
+ EFI_STATUS Status;\r
+ BOOLEAN SummaryMode = FALSE;\r
+ BOOLEAN VerboseMode = FALSE;\r
+ BOOLEAN AllMode = FALSE;\r
+ BOOLEAN RawMode = FALSE;\r
+ BOOLEAN TraceMode = FALSE;\r
+ BOOLEAN ProfileMode = FALSE;\r
+ BOOLEAN ExcludeMode = FALSE;\r
+\r
+\r
+ // Get DP's entry time as soon as possible.\r
+ // This is used as the Shell-Phase end time.\r
+ //\r
+ Ticker = GetPerformanceCounter ();\r
+\r
+ // Register our string package with HII and return the handle to it.\r
+ //\r
+ gHiiHandle = HiiAddPackages (&gEfiCallerIdGuid, ImageHandle, DPStrings, NULL);\r
+ ASSERT (gHiiHandle != NULL);\r
+\r
+/****************************************************************************\r
+**** Process Command Line arguments ****\r
+****************************************************************************/\r
+ Status = ShellCommandLineParse (DpParamList, &ParamPackage, NULL, TRUE);\r
+\r
+ if (EFI_ERROR(Status)) {\r
+ PrintToken (STRING_TOKEN (STR_DP_INVALID_ARG));\r
+ ShowHelp();\r
+ }\r
+ else {\r
+ if (ShellCommandLineGetFlag (ParamPackage, STR_DP_OPTION_QH) ||\r
+ ShellCommandLineGetFlag (ParamPackage, STR_DP_OPTION_LH) ||\r
+ ShellCommandLineGetFlag (ParamPackage, STR_DP_OPTION_UH))\r
+ {\r
+ ShowHelp();\r
+ }\r
+ else {\r
+ // Boolean Options\r
+ VerboseMode = (ShellCommandLineGetFlag (ParamPackage, STR_DP_OPTION_LV));\r
+ SummaryMode = (ShellCommandLineGetFlag (ParamPackage, STR_DP_OPTION_US) ||\r
+ ShellCommandLineGetFlag (ParamPackage, STR_DP_OPTION_LS));\r
+ AllMode = (ShellCommandLineGetFlag (ParamPackage, STR_DP_OPTION_UA));\r
+ RawMode = (ShellCommandLineGetFlag (ParamPackage, STR_DP_OPTION_UR));\r
+#if PROFILING_IMPLEMENTED\r
+ TraceMode = (ShellCommandLineGetFlag (ParamPackage, STR_DP_OPTION_UT));\r
+ ProfileMode = (ShellCommandLineGetFlag (ParamPackage, STR_DP_OPTION_UP));\r
+#endif // PROFILING_IMPLEMENTED\r
+ ExcludeMode = (ShellCommandLineGetFlag (ParamPackage, STR_DP_OPTION_LX));\r
+\r
+ // Options with Values\r
+ CmdLineArg = ( ShellCommandLineGetValue (ParamPackage, STR_DP_OPTION_LN));\r
+ if (CmdLineArg == NULL) {\r
+ Number2Display = DEFAULT_DISPLAYCOUNT;\r
+ }\r
+ else {\r
+ Number2Display = StrDecimalToUintn(CmdLineArg);\r
+ if (Number2Display == 0) {\r
+ Number2Display = MAXIMUM_DISPLAYCOUNT;\r
+ }\r
+ }\r
+ CmdLineArg = (ShellCommandLineGetValue (ParamPackage, STR_DP_OPTION_LT));\r
+ if (CmdLineArg == NULL) {\r
+ mInterestThreshold = DEFAULT_THRESHOLD; // 1ms := 1,000 us\r
+ }\r
+ else {\r
+ mInterestThreshold = StrDecimalToUint64(CmdLineArg);\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
+**** 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
+ Freq = GetPerformanceCounterProperties (&TimerInfo.StartCount, &TimerInfo.EndCount);\r
+\r
+ // Convert the Frequency from Hz to KHz\r
+ TimerInfo.Frequency = (UINT32)DivU64x32 (Freq, 1000);\r
+\r
+ // Determine in which direction the performance counter counts.\r
+ TimerInfo.CountUp = (BOOLEAN) (TimerInfo.EndCount >= TimerInfo.StartCount);\r
+\r
+/****************************************************************************\r
+**** Print heading ****\r
+****************************************************************************/\r
+ // print DP's build version\r
+ PrintToken (STRING_TOKEN (STR_DP_BUILD_REVISION), DP_MAJOR_VERSION, DP_MINOR_VERSION);\r
+\r
+ // print performance timer characteristics\r
+ PrintToken (STRING_TOKEN (STR_DP_KHZ), TimerInfo.Frequency); // Print Timer frequency in KHz\r
+\r
+ if ((VerboseMode) &&\r
+ (! RawMode)\r
+ ) {\r
+ StringPtr = HiiGetString (gHiiHandle,\r
+ TimerInfo.CountUp ? STRING_TOKEN (STR_DP_UP) : STRING_TOKEN (STR_DP_DOWN),\r
+ NULL);\r
+ ASSERT (StringPtr != NULL);\r
+ PrintToken (STRING_TOKEN (STR_DP_TIMER_PROPERTIES), // Print Timer count range and direction\r
+ StringPtr,\r
+ TimerInfo.StartCount,\r
+ TimerInfo.EndCount\r
+ );\r
+ PrintToken (STRING_TOKEN (STR_DP_VERBOSE_THRESHOLD), 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();\r
+ if (AllMode) {\r
+ if (TraceMode) {\r
+ DumpAllTrace( Number2Display, ExcludeMode);\r
+ }\r
+ if (ProfileMode) {\r
+ DumpAllProfile( Number2Display, ExcludeMode);\r
+ }\r
+ }\r
+ else if (RawMode) {\r
+ if (TraceMode) {\r
+ DumpRawTrace( Number2Display, ExcludeMode);\r
+ }\r
+ if (ProfileMode) {\r
+ DumpRawProfile( Number2Display, ExcludeMode);\r
+ }\r
+ }\r
+ else {\r
+ //------------- Begin Cooked Mode Processing\r
+ if (TraceMode) {\r
+ ProcessPhases ( Ticker );\r
+ if ( ! SummaryMode) {\r
+ Status = ProcessHandles ( ExcludeMode);\r
+ if ( ! EFI_ERROR( Status)) {\r
+ ProcessPeims ( );\r
+ ProcessGlobal ( );\r
+ ProcessCumulative ();\r
+ }\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
+ }\r
+ (void) FreePool (mPrintTokenBuffer);\r
+ HiiRemovePackages (gHiiHandle);\r
+ return Status;\r
+}\r
--- /dev/null
+/** @file\r
+ * Common declarations for the Dp Performance Reporting Utility.\r
+ *\r
+ * Copyright (c) 2009-2010, Intel Corporation. All rights reserved.<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
+#ifndef _EFI_APP_DP_H_\r
+#define _EFI_APP_DP_H_\r
+\r
+#define DP_MAJOR_VERSION 2\r
+#define DP_MINOR_VERSION 3\r
+\r
+/**\r
+ * The value assigned to DP_DEBUG controls which debug output\r
+ * is generated. Set it to ZERO to disable.\r
+**/\r
+#define DP_DEBUG 0\r
+\r
+/**\r
+ * Set to 1 once Profiling has been implemented in order to enable\r
+ * profiling related options and report output.\r
+**/\r
+#define PROFILING_IMPLEMENTED 0\r
+\r
+#define DEFAULT_THRESHOLD 1000 ///< One millisecond.\r
+#define DEFAULT_DISPLAYCOUNT 50\r
+#define MAXIMUM_DISPLAYCOUNT 999999 ///< Arbitrary maximum reasonable number.\r
+\r
+#define PERF_MAXDUR 0xFFFFFFFFFFFFFFFFULL\r
+\r
+/// Determine whether 0 <= C < L. If L == 0, return true regardless of C.\r
+#define WITHIN_LIMIT( C, L) ( ((L) == 0) || ((C) < (L)) )\r
+\r
+/// Structure for storing Timer specific information.\r
+typedef struct {\r
+ UINT64 StartCount; ///< Value timer is initialized with.\r
+ UINT64 EndCount; ///< Value timer has just before it wraps.\r
+ UINT32 Frequency; ///< Timer count frequency in KHz.\r
+ BOOLEAN CountUp; ///< TRUE if the counter counts up.\r
+} TIMER_INFO;\r
+\r
+/** Initialize one PERF_CUM_DATA structure instance for token t.\r
+ *\r
+ * This parameterized macro takes a single argument, t, which is expected\r
+ * to resolve to a pointer to an ASCII string literal. This parameter may\r
+ * take any one of the following forms:\r
+ * - PERF_INIT_CUM_DATA("Token") A string literal\r
+ * - PERF_INIT_CUM_DATA(pointer) A pointer -- CHAR8 *pointer;\r
+ * - PERF_INIT_CUM_DATA(array) Address of an array -- CHAR8 array[N];\r
+**/\r
+#define PERF_INIT_CUM_DATA(t) { 0ULL, PERF_MAXDUR, 0ULL, (t), 0U }\r
+\r
+typedef struct {\r
+ UINT64 Duration; ///< Cumulative duration for this item.\r
+ UINT64 MinDur; ///< Smallest duration encountered.\r
+ UINT64 MaxDur; ///< Largest duration encountered.\r
+ CHAR8 *Name; ///< ASCII name of this item.\r
+ UINT32 Count; ///< Total number of measurements accumulated.\r
+} PERF_CUM_DATA;\r
+\r
+typedef struct {\r
+ UINT32 NumTrace; ///< Number of recorded TRACE performance measurements.\r
+ UINT32 NumProfile; ///< Number of recorded PROFILE performance measurements.\r
+ UINT32 NumIncomplete; ///< Number of measurements with no END value.\r
+ UINT32 NumSummary; ///< Number of summary section measurements.\r
+ UINT32 NumHandles; ///< Number of measurements with handles.\r
+ UINT32 NumPEIMs; ///< Number of measurements of PEIMs.\r
+ UINT32 NumGlobal; ///< Number of measurements with END value and NULL handle.\r
+} PERF_SUMMARY_DATA;\r
+\r
+typedef struct {\r
+ VOID *Handle;\r
+ CHAR8 *Token; ///< Measured token string name.\r
+ CHAR8 *Module; ///< Module string name.\r
+ UINT64 StartTimeStamp; ///< Start time point.\r
+ UINT64 EndTimeStamp; ///< End time point.\r
+} MEASUREMENT_RECORD;\r
+\r
+typedef struct {\r
+ CHAR8 *Name; ///< Measured token string name.\r
+ UINT64 CumulativeTime; ///< Accumulated Elapsed Time.\r
+ UINT64 MinTime; ///< Minimum Elapsed Time.\r
+ UINT64 MaxTime; ///< Maximum Elapsed Time.\r
+ UINT32 Count; ///< Number of measurements accumulated.\r
+} PROFILE_RECORD;\r
+\r
+#endif // _EFI_APP_DP_H_\r
--- /dev/null
+#/** @file\r
+# Display Performance Application, Module information file.\r
+#\r
+# Copyright (c) 2009-2010, Intel Corporation. All rights reserved.<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
+\r
+[Defines]\r
+ INF_VERSION = 0x00010006\r
+ BASE_NAME = DP\r
+ FILE_GUID = 7d5ff0e3-2fb7-4e19-8419-44266cb60000\r
+ MODULE_TYPE = UEFI_APPLICATION\r
+ VERSION_STRING = 1.0\r
+ ENTRY_POINT = InitializeDp\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC\r
+#\r
+\r
+[Sources]\r
+ DpStrings.uni\r
+ Dp.c\r
+ Literals.c\r
+ DpUtilities.c\r
+ DpTrace.c\r
+ DpProfile.c\r
+\r
+[Packages]\r
+ MdePkg/MdePkg.dec\r
+ MdeModulePkg/MdeModulePkg.dec\r
+ ShellPkg/ShellPkg.dec\r
+ PerformancePkg/PerformancePkg.dec\r
+\r
+[LibraryClasses]\r
+ UefiApplicationEntryPoint\r
+ ShellLib\r
+ BaseMemoryLib\r
+ BaseLib\r
+ MemoryAllocationLib\r
+ DebugLib\r
+ UefiBootServicesTableLib\r
+ TimerLib\r
+ PeCoffGetEntryPointLib\r
+ PerformanceLib\r
+ PrintLib\r
+ UefiLib\r
+ HiiLib\r
+ PcdLib\r
+\r
+[Guids]\r
+\r
+[Protocols]\r
+ gEfiLoadedImageProtocolGuid # ALWAYS_CONSUMED\r
+ gEfiDriverBindingProtocolGuid # ALWAYS_CONSUMED\r
+\r
+[Pcd]\r
+ gEfiMdePkgTokenSpaceGuid.PcdUefiLibMaxPrintBufferSize\r
--- /dev/null
+/** @file\r
+ * Declarations of objects defined internally to the Dp Application.\r
+ *\r
+ * Declarations of data and functions which are private to the Dp application.\r
+ * This file should never be referenced by anything other than components of the\r
+ * Dp application. In addition to global data, function declarations for\r
+ * DpUtilities.c, DpTrace.c, and DpProfile.c are included here.\r
+ *\r
+ * Copyright (c) 2009-2010, Intel Corporation. All rights reserved.<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
+//\r
+/// Module-Global Variables\r
+/// @{\r
+extern EFI_HII_HANDLE gHiiHandle;\r
+extern CHAR16 *mPrintTokenBuffer;\r
+extern CHAR16 mGaugeString[DXE_PERFORMANCE_STRING_SIZE];\r
+extern CHAR16 mUnicodeToken[PERF_TOKEN_LENGTH + 1];\r
+extern UINT64 mInterestThreshold;\r
+\r
+extern PERF_SUMMARY_DATA SummaryData;; ///< Create the SummaryData structure and init. to ZERO.\r
+\r
+/// Timer Specific Information.\r
+extern TIMER_INFO TimerInfo;\r
+\r
+/// Items for which to gather cumulative statistics.\r
+extern PERF_CUM_DATA CumData[];\r
+\r
+/// Number of items for which we are gathering cumulative statistics.\r
+extern UINT32 const NumCum;\r
+\r
+/// @}\r
+\r
+/** Calculate an event's duration in timer ticks.\r
+ *\r
+ * Given the count direction and the event's start and end timer values,\r
+ * calculate the duration of the event in timer ticks.\r
+ *\r
+ * @pre The global TimerInfo structure must have already been initialized\r
+ * before this function is called.\r
+ *\r
+ * @param[in,out] Measurement Pointer to a structure containing data for the current measurement.\r
+ *\r
+ * @return The 64-bit duration of the event.\r
+**/\r
+UINT64\r
+GetDuration (\r
+ IN OUT MEASUREMENT_RECORD *Measurement\r
+);\r
+\r
+/** Determine whether the Measurement record is for an EFI Phase.\r
+ *\r
+ * The Token and Module members of the measurement record are checked.\r
+ * Module must be empty and Token must be one of SEC, PEI, DXE, or BDS.\r
+ *\r
+ * @param[in] Measurement A pointer to the Measurement record to test.\r
+ *\r
+ * @retval TRUE The measurement record is for an EFI Phase.\r
+ * @retval FALSE The measurement record is NOT for an EFI Phase.\r
+**/\r
+BOOLEAN\r
+IsPhase(\r
+ IN MEASUREMENT_RECORD *Measurement\r
+);\r
+\r
+/** Get the file name portion of the Pdb File Name.\r
+ *\r
+ * The portion of the Pdb File Name between the last backslash and\r
+ * either a following period or the end of the string is converted\r
+ * to Unicode and copied into UnicodeBuffer. The name is truncated,\r
+ * if necessary, to ensure that UnicodeBuffer is not overrun.\r
+ *\r
+ * @param[in] PdbFileName Pdb file name.\r
+ * @param[out] UnicodeBuffer The resultant Unicode File Name.\r
+ *\r
+**/\r
+VOID\r
+GetShortPdbFileName (\r
+ IN CHAR8 *PdbFileName,\r
+ OUT CHAR16 *UnicodeBuffer\r
+);\r
+\r
+/** Get a human readable name for an image handle.\r
+ *\r
+ * @param[in] Handle\r
+ *\r
+ * @post The resulting Unicode name string is stored in the\r
+ * mGaugeString global array.\r
+ *\r
+**/\r
+VOID\r
+GetNameFromHandle (\r
+ IN EFI_HANDLE Handle\r
+);\r
+\r
+/** Calculate the Duration in microseconds.\r
+ *\r
+ * Duration is multiplied by 1000, instead of Frequency being divided by 1000\r
+ * in order to maintain precision. Since Duration is\r
+ * a 64-bit value, multiplying it by 1000 is unlikely to produce an overflow.\r
+ *\r
+ * @param[in] Duration The event duration in timer ticks.\r
+ *\r
+ * @return A 64-bit value which is the Elapsed time in microseconds.\r
+**/\r
+UINT64\r
+DurationInMicroSeconds (\r
+ IN UINT64 Duration\r
+);\r
+\r
+/** Formatted Print using a Hii Token to reference the localized format string.\r
+ *\r
+ * @param[in] Token A HII token associated with a localized Unicode string.\r
+ *\r
+ * @return The number of characters converted by UnicodeVSPrint().\r
+ *\r
+**/\r
+UINTN\r
+PrintToken (\r
+ IN UINT16 Token,\r
+ ...\r
+);\r
+\r
+/** Get index of Measurement Record's match in the CumData array.\r
+ *\r
+ * @param[in] Measurement A pointer to a Measurement Record to match against the CumData array.\r
+ *\r
+ * @retval <0 Token is not in the CumData array.\r
+ * @retval >=0 Return value is the index into CumData where Token is found.\r
+**/\r
+INTN\r
+GetCumulativeItem(\r
+ IN MEASUREMENT_RECORD *Measurement\r
+);\r
+\r
+/** Collect verbose statistics about the logged performance measurements.\r
+ *\r
+ * General Summary information for all Trace measurements is gathered and\r
+ * stored within the SummaryData structure. This information is both\r
+ * used internally by subsequent reporting functions, and displayed\r
+ * at the end of verbose reports.\r
+ *\r
+ * @pre The SummaryData and CumData structures must be initialized\r
+ * prior to calling this function.\r
+ *\r
+ * @post The SummaryData and CumData structures contain statistics for the\r
+ * current performance logs.\r
+**/\r
+VOID\r
+GatherStatistics(\r
+ VOID\r
+);\r
+\r
+/** Gather and print ALL Trace Records.\r
+ *\r
+ * Displays all "interesting" Trace measurements in order.\r
+ * The number of records displayed is controlled by:\r
+ * - records with a duration less than mInterestThreshold microseconds are not displayed.\r
+ * - No more than Limit records are displayed. A Limit of zero will not limit the output.\r
+ * - If the ExcludeFlag is TRUE, records matching entries in the CumData array are not\r
+ * displayed.\r
+ *\r
+ * @pre The mInterestThreshold global variable is set to the shortest duration to be printed.\r
+ * The mGaugeString and mUnicodeToken global arrays are used for temporary string storage.\r
+ * They must not be in use by a calling function.\r
+ *\r
+ * @param[in] Limit The number of records to print. Zero is ALL.\r
+ * @param[in] ExcludeFlag TRUE to exclude individual Cumulative items from display.\r
+ *\r
+**/\r
+VOID\r
+DumpAllTrace(\r
+ IN UINTN Limit,\r
+ IN BOOLEAN ExcludeFlag\r
+);\r
+\r
+/** Gather and print Raw Trace Records.\r
+ *\r
+ * All Trace measurements with a duration greater than or equal to\r
+ * mInterestThreshold are printed without interpretation.\r
+ *\r
+ * The number of records displayed is controlled by:\r
+ * - records with a duration less than mInterestThreshold microseconds are not displayed.\r
+ * - No more than Limit records are displayed. A Limit of zero will not limit the output.\r
+ * - If the ExcludeFlag is TRUE, records matching entries in the CumData array are not\r
+ * displayed.\r
+ *\r
+ * @pre The mInterestThreshold global variable is set to the shortest duration to be printed.\r
+ *\r
+ * @param[in] Limit The number of records to print. Zero is ALL.\r
+ * @param[in] ExcludeFlag TRUE to exclude individual Cumulative items from display.\r
+ *\r
+**/\r
+VOID\r
+DumpRawTrace(\r
+ IN UINTN Limit,\r
+ IN BOOLEAN ExcludeFlag\r
+);\r
+\r
+/** Gather and print Major Phase metrics.\r
+ *\r
+ * @param[in] Ticker The timer value for the END of Shell phase\r
+ *\r
+**/\r
+VOID\r
+ProcessPhases(\r
+ IN UINT64 Ticker\r
+);\r
+\r
+\r
+/** Gather and print Handle data.\r
+ *\r
+ * @param[in] ExcludeFlag TRUE if the -x command line flag given. Elides accumulated trace records.\r
+ *\r
+ * @return Status from a call to gBS->LocateHandle().\r
+**/\r
+EFI_STATUS\r
+ProcessHandles(\r
+ IN BOOLEAN ExcludeFlag\r
+);\r
+\r
+\r
+/** Gather and print PEIM data.\r
+ *\r
+ * Only prints complete PEIM records\r
+ *\r
+**/\r
+VOID\r
+ProcessPeims(\r
+ VOID\r
+);\r
+\r
+/** Gather and print global data.\r
+ *\r
+ * Strips out incomplete or "Execution Phase" records\r
+ * Only prints records where Handle is NULL\r
+ * Increment TIndex for every record, even skipped ones, so that we have an\r
+ * indication of every measurement record taken.\r
+ *\r
+ *\r
+**/\r
+VOID\r
+ProcessGlobal(\r
+ VOID\r
+);\r
+\r
+/** Gather and print cumulative data.\r
+ *\r
+ * Traverse the measurement records and:\r
+ * for each record with a Token listed in the CumData array,\r
+ * Update the instance count and the total, minimum, and maximum durations.\r
+ * Finally, print the gathered cumulative statistics.\r
+ *\r
+**/\r
+VOID\r
+ProcessCumulative(\r
+ VOID\r
+);\r
+\r
+/** Gather and print ALL Profile Records.\r
+ *\r
+ * @param[in] Limit The number of records to print. Zero is ALL.\r
+ * @param[in] ExcludeFlag TRUE to exclude individual Cumulative items from display\r
+ *\r
+**/\r
+VOID\r
+DumpAllProfile(\r
+ IN UINTN Limit,\r
+ IN BOOLEAN ExcludeFlag\r
+);\r
+\r
+/** Gather and print Raw Profile Records.\r
+ *\r
+ * @param[in] Limit The number of records to print.\r
+ * @param[in] ExcludeFlag TRUE to exclude individual Cumulative items from display\r
+ *\r
+**/\r
+VOID\r
+DumpRawProfile(\r
+ IN UINTN Limit,\r
+ IN BOOLEAN ExcludeFlag\r
+);\r
--- /dev/null
+/** @file\r
+ * Measured Profiling reporting for the Dp utility.\r
+ *\r
+ * Copyright (c) 2009-2010, Intel Corporation. All rights reserved.<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 <Library/BaseLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/TimerLib.h>\r
+#include <Library/PeCoffGetEntryPointLib.h>\r
+#include <Library/PerformanceLib.h>\r
+#include <Library/PrintLib.h>\r
+#include <Library/HiiLib.h>\r
+#include <Library/PcdLib.h>\r
+\r
+#include <Guid/Performance.h>\r
+\r
+#include "Dp.h"\r
+#include "Literals.h"\r
+#include "DpInternal.h"\r
+\r
+/** Gather and print ALL Profiling Records.\r
+ *\r
+ * Displays all "interesting" Profile measurements in order.\r
+ * The number of records displayed is controlled by:\r
+ * - records with a duration less than mInterestThreshold microseconds are not displayed.\r
+ * - No more than Limit records are displayed. A Limit of zero will not limit the output.\r
+ * - If the ExcludeFlag is TRUE, records matching entries in the CumData array are not\r
+ * displayed.\r
+ *\r
+ * @pre The mInterestThreshold global variable is set to the shortest duration to be printed.\r
+ * The mGaugeString and mUnicodeToken global arrays are used for temporary string storage.\r
+ * They must not be in use by a calling function.\r
+ *\r
+ * @param[in] Limit The number of records to print. Zero is ALL.\r
+ * @param[in] ExcludeFlag TRUE to exclude individual Cumulative items from display.\r
+ *\r
+**/\r
+VOID\r
+DumpAllProfile(\r
+ IN UINTN Limit,\r
+ IN BOOLEAN ExcludeFlag\r
+ )\r
+{\r
+ EFI_STRING StringPtr;\r
+\r
+ StringPtr = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_SECTION_PROFILE), NULL);\r
+ PrintToken( STRING_TOKEN (STR_DP_SECTION_HEADER),\r
+ (StringPtr == NULL) ? ALit_UNKNOWN: StringPtr);\r
+ return;\r
+}\r
+\r
+/** Gather and print Raw Profile Records.\r
+ *\r
+ * All Profile measurements with a duration greater than or equal to\r
+ * mInterestThreshold are printed without interpretation.\r
+ *\r
+ * The number of records displayed is controlled by:\r
+ * - records with a duration less than mInterestThreshold microseconds are not displayed.\r
+ * - No more than Limit records are displayed. A Limit of zero will not limit the output.\r
+ * - If the ExcludeFlag is TRUE, records matching entries in the CumData array are not\r
+ * displayed.\r
+ *\r
+ * @pre The mInterestThreshold global variable is set to the shortest duration to be printed.\r
+ *\r
+ * @param[in] Limit The number of records to print. Zero is ALL.\r
+ * @param[in] ExcludeFlag TRUE to exclude individual Cumulative items from display.\r
+ *\r
+**/\r
+VOID\r
+DumpRawProfile(\r
+ IN UINTN Limit,\r
+ IN BOOLEAN ExcludeFlag\r
+ )\r
+{\r
+ EFI_STRING StringPtr;\r
+\r
+ StringPtr = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_SECTION_RAWPROFILE), NULL);\r
+ PrintToken( STRING_TOKEN (STR_DP_SECTION_HEADER),\r
+ (StringPtr == NULL) ? ALit_UNKNOWN: StringPtr);\r
+ return;\r
+}\r
--- /dev/null
+/** @file\r
+ * Trace reporting for the Dp utility.\r
+ *\r
+ * Copyright (c) 2009-2010, Intel Corporation. All rights reserved.<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 <Library/BaseLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/TimerLib.h>\r
+#include <Library/PeCoffGetEntryPointLib.h>\r
+#include <Library/PerformanceLib.h>\r
+#include <Library/PrintLib.h>\r
+#include <Library/HiiLib.h>\r
+#include <Library/PcdLib.h>\r
+\r
+#include <Guid/Performance.h>\r
+\r
+#include "Dp.h"\r
+#include "Literals.h"\r
+#include "DpInternal.h"\r
+\r
+/** Collect verbose statistics about the logged performance measurements.\r
+ *\r
+ * General Summary information for all Trace measurements is gathered and\r
+ * stored within the SummaryData structure. This information is both\r
+ * used internally by subsequent reporting functions, and displayed\r
+ * at the end of verbose reports.\r
+ *\r
+ * @pre The SummaryData and CumData structures must be initialized\r
+ * prior to calling this function.\r
+ *\r
+ * @post The SummaryData and CumData structures contain statistics for the\r
+ * current performance logs.\r
+**/\r
+VOID\r
+GatherStatistics(\r
+ VOID\r
+)\r
+{\r
+ MEASUREMENT_RECORD Measurement;\r
+ UINT64 Duration;\r
+ UINTN LogEntryKey;\r
+ UINTN TIndex;\r
+\r
+ LogEntryKey = 0;\r
+ while ((LogEntryKey = GetPerformanceMeasurement (\r
+ LogEntryKey,\r
+ &Measurement.Handle,\r
+ &Measurement.Token,\r
+ &Measurement.Module,\r
+ &Measurement.StartTimeStamp,\r
+ &Measurement.EndTimeStamp)) != 0)\r
+ {\r
+ ++SummaryData.NumTrace; // Count the number of TRACE Measurement records\r
+ if (Measurement.EndTimeStamp == 0) {\r
+ ++SummaryData.NumIncomplete; // Count the incomplete records\r
+ continue;\r
+ }\r
+\r
+ if (Measurement.Handle != NULL) {\r
+ ++SummaryData.NumHandles; // Count the number of measurements with non-NULL handles\r
+ }\r
+\r
+ if (IsPhase( &Measurement)) {\r
+ ++SummaryData.NumSummary; // Count the number of major phases\r
+ }\r
+ else { // !IsPhase(...\r
+ if(Measurement.Handle == NULL) {\r
+ ++SummaryData.NumGlobal;\r
+ }\r
+ }\r
+\r
+ if (AsciiStrnCmp (Measurement.Token, ALit_PEIM, PERF_TOKEN_LENGTH) == 0) {\r
+ ++SummaryData.NumPEIMs; // Count PEIM measurements\r
+ }\r
+\r
+ Duration = GetDuration (&Measurement);\r
+ TIndex = GetCumulativeItem (&Measurement);\r
+ if (TIndex >= 0) {\r
+ CumData[TIndex].Duration += Duration;\r
+ CumData[TIndex].Count++;\r
+ if ( Duration < CumData[TIndex].MinDur ) {\r
+ CumData[TIndex].MinDur = Duration;\r
+ }\r
+ if ( Duration > CumData[TIndex].MaxDur ) {\r
+ CumData[TIndex].MaxDur = Duration;\r
+ }\r
+ }\r
+ }\r
+}\r
+\r
+/** Gather and print ALL Trace Records.\r
+ *\r
+ * Displays all "interesting" Trace measurements in order.<BR>\r
+ * The number of records displayed is controlled by:\r
+ * - records with a duration less than mInterestThreshold microseconds are not displayed.\r
+ * - No more than Limit records are displayed. A Limit of zero will not limit the output.\r
+ * - If the ExcludeFlag is TRUE, records matching entries in the CumData array are not\r
+ * displayed.\r
+ *\r
+ * @pre The mInterestThreshold global variable is set to the shortest duration to be printed.\r
+ * The mGaugeString and mUnicodeToken global arrays are used for temporary string storage.\r
+ * They must not be in use by a calling function.\r
+ *\r
+ * @param[in] Limit The number of records to print. Zero is ALL.\r
+ * @param[in] ExcludeFlag TRUE to exclude individual Cumulative items from display.\r
+ *\r
+**/\r
+VOID\r
+DumpAllTrace(\r
+ IN UINTN Limit,\r
+ IN BOOLEAN ExcludeFlag\r
+ )\r
+{\r
+ MEASUREMENT_RECORD Measurement;\r
+ UINT64 ElapsedTime;\r
+ UINT64 Duration;\r
+ const CHAR16 *IncFlag;\r
+ UINTN LogEntryKey;\r
+ UINTN Count;\r
+ UINTN Index;\r
+ UINTN TIndex;\r
+\r
+ EFI_HANDLE *HandleBuffer;\r
+ UINTN Size;\r
+ EFI_HANDLE TempHandle;\r
+ EFI_STATUS Status;\r
+\r
+ IncFlag = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_SECTION_ALL), NULL);\r
+ PrintToken( STRING_TOKEN (STR_DP_SECTION_HEADER),\r
+ (IncFlag == NULL) ? ALit_UNKNOWN: IncFlag);\r
+\r
+ // Get Handle information\r
+ //\r
+ Size = 0;\r
+ HandleBuffer = NULL;\r
+ Status = gBS->LocateHandle (AllHandles, NULL, NULL, &Size, &TempHandle);\r
+ if (Status == EFI_BUFFER_TOO_SMALL) {\r
+ HandleBuffer = AllocatePool (Size);\r
+ ASSERT (HandleBuffer != NULL);\r
+ Status = gBS->LocateHandle (AllHandles, NULL, NULL, &Size, HandleBuffer);\r
+ }\r
+ if (EFI_ERROR (Status)) {\r
+ PrintToken (STRING_TOKEN (STR_DP_HANDLES_ERROR), Status);\r
+ }\r
+ else {\r
+ // We have successfully populated the HandleBuffer\r
+ // Display ALL Measurement Records\r
+ // Up to Limit lines displayed\r
+ // Display only records with Elapsed times >= mInterestThreshold\r
+ // Display driver names in Module field for records with Handles.\r
+ //\r
+ PrintToken (STRING_TOKEN (STR_DP_ALL_HEADR) );\r
+ PrintToken (STRING_TOKEN (STR_DP_DASHES) );\r
+\r
+ LogEntryKey = 0;\r
+ Count = 0;\r
+ Index = 0;\r
+ while ( WITHIN_LIMIT(Count, Limit) &&\r
+ ((LogEntryKey = GetPerformanceMeasurement (\r
+ LogEntryKey,\r
+ &Measurement.Handle,\r
+ &Measurement.Token,\r
+ &Measurement.Module,\r
+ &Measurement.StartTimeStamp,\r
+ &Measurement.EndTimeStamp)) != 0)\r
+ )\r
+ {\r
+ ++Index; // Count every record. First record is 1.\r
+ ElapsedTime = 0;\r
+ if (Measurement.EndTimeStamp != 0) {\r
+ Duration = GetDuration (&Measurement);\r
+ ElapsedTime = DurationInMicroSeconds ( Duration );\r
+ IncFlag = STR_DP_COMPLETE;\r
+ }\r
+ else {\r
+ IncFlag = STR_DP_INCOMPLETE; // Mark incomplete records\r
+ }\r
+ if ((ElapsedTime < mInterestThreshold) ||\r
+ ((ExcludeFlag) && (GetCumulativeItem(&Measurement) >= 0))\r
+ ) { // Ignore "uninteresting" or excluded records\r
+ continue;\r
+ }\r
+ if (Measurement.EndTimeStamp == 0) {\r
+ ElapsedTime = Measurement.StartTimeStamp;\r
+ }\r
+ ++Count; // Count the number of records printed\r
+\r
+ // If Handle is non-zero, see if we can determine a name for the driver\r
+ AsciiStrToUnicodeStr (Measurement.Module, mGaugeString); // Use Module by default\r
+ AsciiStrToUnicodeStr (Measurement.Token, mUnicodeToken);\r
+ if (Measurement.Handle != NULL) {\r
+ // See if the Handle is in the HandleBuffer\r
+ for (TIndex = 0; TIndex < (Size / sizeof(HandleBuffer[0])); TIndex++) {\r
+ if (Measurement.Handle == HandleBuffer[TIndex]) {\r
+ GetNameFromHandle (HandleBuffer[TIndex]);\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ // Ensure that the argument strings are not too long.\r
+ mGaugeString[31] = 0;\r
+ mUnicodeToken[18] = 0;\r
+\r
+ PrintToken( STRING_TOKEN (STR_DP_ALL_STATS),\r
+ Index, // 1 based, Which measurement record is being printed\r
+ IncFlag,\r
+ Measurement.Handle,\r
+ mGaugeString,\r
+ mUnicodeToken,\r
+ ElapsedTime\r
+ );\r
+ }\r
+ }\r
+ FreePool (HandleBuffer);\r
+}\r
+\r
+/** Gather and print Raw Trace Records.\r
+ *\r
+ * All Trace measurements with a duration greater than or equal to\r
+ * mInterestThreshold are printed without interpretation.\r
+ *\r
+ * The number of records displayed is controlled by:\r
+ * - records with a duration less than mInterestThreshold microseconds are not displayed.\r
+ * - No more than Limit records are displayed. A Limit of zero will not limit the output.\r
+ * - If the ExcludeFlag is TRUE, records matching entries in the CumData array are not\r
+ * displayed.\r
+ *\r
+ * @pre The mInterestThreshold global variable is set to the shortest duration to be printed.\r
+ *\r
+ * @param[in] Limit The number of records to print. Zero is ALL.\r
+ * @param[in] ExcludeFlag TRUE to exclude individual Cumulative items from display.\r
+ *\r
+**/\r
+VOID\r
+DumpRawTrace(\r
+ IN UINTN Limit,\r
+ IN BOOLEAN ExcludeFlag\r
+ )\r
+{\r
+ MEASUREMENT_RECORD Measurement;\r
+ UINT64 ElapsedTime;\r
+ UINT64 Duration;\r
+ UINTN LogEntryKey;\r
+ UINTN Count;\r
+ UINTN Index;\r
+\r
+ EFI_STRING StringPtr;\r
+\r
+ StringPtr = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_SECTION_RAWTRACE), NULL);\r
+ PrintToken( STRING_TOKEN (STR_DP_SECTION_HEADER),\r
+ (StringPtr == NULL) ? ALit_UNKNOWN: StringPtr);\r
+\r
+ PrintToken (STRING_TOKEN (STR_DP_RAW_HEADR) );\r
+ PrintToken (STRING_TOKEN (STR_DP_RAW_DASHES) );\r
+\r
+ LogEntryKey = 0;\r
+ Count = 0;\r
+ Index = 0;\r
+ while ( WITHIN_LIMIT(Count, Limit) &&\r
+ ((LogEntryKey = GetPerformanceMeasurement (\r
+ LogEntryKey,\r
+ &Measurement.Handle,\r
+ &Measurement.Token,\r
+ &Measurement.Module,\r
+ &Measurement.StartTimeStamp,\r
+ &Measurement.EndTimeStamp)) != 0)\r
+ )\r
+ {\r
+ ++Index; // Count every record. First record is 1.\r
+ ElapsedTime = 0;\r
+ if (Measurement.EndTimeStamp != 0) {\r
+ Duration = GetDuration (&Measurement);\r
+ ElapsedTime = DurationInMicroSeconds ( Duration );\r
+ }\r
+ if ((ElapsedTime < mInterestThreshold) ||\r
+ ((ExcludeFlag) && (GetCumulativeItem(&Measurement) >= 0))\r
+ ) { // Ignore "uninteresting" or Excluded records\r
+ continue;\r
+ }\r
+ ++Count; // Count the number of records printed\r
+ PrintToken (STRING_TOKEN (STR_DP_RAW_VARS),\r
+ Index, // 1 based, Which measurement record is being printed\r
+ Measurement.Handle,\r
+ Measurement.StartTimeStamp,\r
+ Measurement.EndTimeStamp,\r
+ Measurement.Token,\r
+ Measurement.Module\r
+ );\r
+ }\r
+}\r
+\r
+/** Gather and print Major Phase metrics.\r
+ *\r
+ * @param[in] Ticker The timer value for the END of Shell phase\r
+ *\r
+**/\r
+VOID\r
+ProcessPhases(\r
+ UINT64 Ticker\r
+ )\r
+{\r
+ MEASUREMENT_RECORD Measurement;\r
+ UINT64 BdsTimeoutValue = 0;\r
+ UINT64 SecTime = 0;\r
+ UINT64 PeiTime = 0;\r
+ UINT64 DxeTime = 0;\r
+ UINT64 BdsTime = 0;\r
+ UINT64 ShellTime = 0;\r
+ UINT64 ElapsedTime;\r
+ UINT64 Duration;\r
+ UINT64 Total;\r
+ EFI_STRING StringPtr;\r
+ UINTN LogEntryKey;\r
+\r
+ //\r
+ // Get Execution Phase Statistics\r
+ //\r
+ StringPtr = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_SECTION_PHASES), NULL);\r
+ PrintToken( STRING_TOKEN (STR_DP_SECTION_HEADER),\r
+ (StringPtr == NULL) ? ALit_UNKNOWN: StringPtr);\r
+\r
+ LogEntryKey = 0;\r
+ while ((LogEntryKey = GetPerformanceMeasurement (\r
+ LogEntryKey,\r
+ &Measurement.Handle,\r
+ &Measurement.Token,\r
+ &Measurement.Module,\r
+ &Measurement.StartTimeStamp,\r
+ &Measurement.EndTimeStamp)) != 0)\r
+ {\r
+ if (AsciiStrnCmp (Measurement.Token, ALit_SHELL, PERF_TOKEN_LENGTH) == 0) {\r
+ Measurement.EndTimeStamp = Ticker;\r
+ }\r
+ if (Measurement.EndTimeStamp == 0) { // Skip "incomplete" records\r
+ continue;\r
+ }\r
+ Duration = GetDuration (&Measurement);\r
+ if ( Measurement.Handle != NULL\r
+ && (AsciiStrnCmp (Measurement.Token, ALit_BdsTO, PERF_TOKEN_LENGTH) == 0)\r
+ )\r
+ {\r
+ BdsTimeoutValue = Duration;\r
+ } else if (AsciiStrnCmp (Measurement.Token, ALit_SEC, PERF_TOKEN_LENGTH) == 0) {\r
+ SecTime = Duration;\r
+ } else if (AsciiStrnCmp (Measurement.Token, ALit_PEI, PERF_TOKEN_LENGTH) == 0) {\r
+ PeiTime = Duration;\r
+ } else if (AsciiStrnCmp (Measurement.Token, ALit_DXE, PERF_TOKEN_LENGTH) == 0) {\r
+ DxeTime = Duration;\r
+ } else if (AsciiStrnCmp (Measurement.Token, ALit_BDS, PERF_TOKEN_LENGTH) == 0) {\r
+ BdsTime = Duration;\r
+ } else if (AsciiStrnCmp (Measurement.Token, ALit_SHELL, PERF_TOKEN_LENGTH) == 0) {\r
+ ShellTime = Duration;\r
+ }\r
+ }\r
+\r
+ Total = 0;\r
+\r
+ // print SEC phase duration time\r
+ //\r
+ if (SecTime > 0) {\r
+ ElapsedTime = DurationInMicroSeconds ( SecTime ); // Calculate elapsed time in microseconds\r
+ Total += DivU64x32 (ElapsedTime, 1000); // Accumulate time in milliseconds\r
+ PrintToken (STRING_TOKEN (STR_DP_SEC_PHASE), ElapsedTime);\r
+ }\r
+\r
+ // print PEI phase duration time\r
+ //\r
+ if (PeiTime > 0) {\r
+ ElapsedTime = DivU64x32 (\r
+ PeiTime,\r
+ (UINT32)TimerInfo.Frequency\r
+ );\r
+ Total += ElapsedTime;\r
+ PrintToken (STRING_TOKEN (STR_DP_PHASE_DURATION), ALit_PEI, ElapsedTime);\r
+ }\r
+\r
+ // print DXE phase duration time\r
+ //\r
+ if (DxeTime > 0) {\r
+ ElapsedTime = DivU64x32 (\r
+ DxeTime,\r
+ (UINT32)TimerInfo.Frequency\r
+ );\r
+ Total += ElapsedTime;\r
+ PrintToken (STRING_TOKEN (STR_DP_PHASE_DURATION), ALit_DXE, ElapsedTime);\r
+ }\r
+\r
+ // print BDS phase duration time\r
+ //\r
+ if (BdsTime > 0) {\r
+ ElapsedTime = DivU64x32 (\r
+ BdsTime,\r
+ (UINT32)TimerInfo.Frequency\r
+ );\r
+ Total += ElapsedTime;\r
+ PrintToken (STRING_TOKEN (STR_DP_PHASE_DURATION), ALit_BDS, ElapsedTime);\r
+ }\r
+\r
+ if (BdsTimeoutValue > 0) {\r
+ ElapsedTime = DivU64x32 (\r
+ BdsTimeoutValue,\r
+ (UINT32)TimerInfo.Frequency\r
+ );\r
+ PrintToken (STRING_TOKEN (STR_DP_PHASE_BDSTO), ALit_BdsTO, ElapsedTime);\r
+ }\r
+\r
+ // print SHELL phase duration time\r
+ //\r
+ if (ShellTime > 0) {\r
+ ElapsedTime = DivU64x32 (\r
+ ShellTime,\r
+ (UINT32)TimerInfo.Frequency\r
+ );\r
+ Total += ElapsedTime;\r
+ PrintToken (STRING_TOKEN (STR_DP_PHASE_DURATION), ALit_SHELL, ElapsedTime);\r
+ }\r
+\r
+ PrintToken (STRING_TOKEN (STR_DP_TOTAL_DURATION), Total);\r
+}\r
+\r
+/** Gather and print Handle data.\r
+ *\r
+ * @param[in] ExcludeFlag TRUE to exclude individual Cumulative items from display.\r
+ *\r
+ * @return Status from a call to gBS->LocateHandle().\r
+**/\r
+EFI_STATUS\r
+ProcessHandles(\r
+ IN BOOLEAN ExcludeFlag\r
+ )\r
+{\r
+ MEASUREMENT_RECORD Measurement;\r
+ UINT64 ElapsedTime;\r
+ UINT64 Duration;\r
+ EFI_HANDLE *HandleBuffer;\r
+ EFI_STRING StringPtr;\r
+ UINTN Index;\r
+ UINTN LogEntryKey;\r
+ UINTN Count;\r
+ UINTN Size;\r
+ EFI_HANDLE TempHandle;\r
+ EFI_STATUS Status;\r
+\r
+ StringPtr = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_SECTION_DRIVERS), NULL);\r
+ PrintToken( STRING_TOKEN (STR_DP_SECTION_HEADER),\r
+ (StringPtr == NULL) ? ALit_UNKNOWN: StringPtr);\r
+\r
+ Size = 0;\r
+ HandleBuffer = NULL;\r
+ Status = gBS->LocateHandle (AllHandles, NULL, NULL, &Size, &TempHandle);\r
+ if (Status == EFI_BUFFER_TOO_SMALL) {\r
+ HandleBuffer = AllocatePool (Size);\r
+ ASSERT (HandleBuffer != NULL);\r
+ Status = gBS->LocateHandle (AllHandles, NULL, NULL, &Size, HandleBuffer);\r
+ }\r
+ if (EFI_ERROR (Status)) {\r
+ PrintToken (STRING_TOKEN (STR_DP_HANDLES_ERROR), Status);\r
+ }\r
+ else {\r
+#if DP_DEBUG == 2\r
+ Print (L"There are %,d Handles defined.\n", (Size / sizeof(HandleBuffer[0])));\r
+#endif\r
+\r
+ PrintToken (STRING_TOKEN (STR_DP_HANDLE_GUID) );\r
+ PrintToken (STRING_TOKEN (STR_DP_DASHES) );\r
+\r
+ LogEntryKey = 0;\r
+ Count = 0;\r
+ while ((LogEntryKey = GetPerformanceMeasurement (\r
+ LogEntryKey,\r
+ &Measurement.Handle,\r
+ &Measurement.Token,\r
+ &Measurement.Module,\r
+ &Measurement.StartTimeStamp,\r
+ &Measurement.EndTimeStamp)) != 0)\r
+ {\r
+ Count++;\r
+ Duration = GetDuration (&Measurement);\r
+ ElapsedTime = DurationInMicroSeconds ( Duration );\r
+ if ((ElapsedTime < mInterestThreshold) ||\r
+ (Measurement.EndTimeStamp == 0) ||\r
+ (Measurement.Handle == NULL) ||\r
+ ((ExcludeFlag) && (GetCumulativeItem(&Measurement) >= 0))\r
+ ) { // Ignore "uninteresting" or excluded records\r
+ continue;\r
+ }\r
+ mGaugeString[0] = 0; // Empty driver name by default\r
+ AsciiStrToUnicodeStr (Measurement.Token, mUnicodeToken);\r
+ // See if the Handle is in the HandleBuffer\r
+ for (Index = 0; Index < (Size / sizeof(HandleBuffer[0])); Index++) {\r
+ if (Measurement.Handle == HandleBuffer[Index]) {\r
+ GetNameFromHandle (HandleBuffer[Index]); // Name is put into mGaugeString\r
+ break;\r
+ }\r
+ }\r
+ // Ensure that the argument strings are not too long.\r
+ mGaugeString[31] = 0;\r
+ mUnicodeToken[18] = 0;\r
+ if (mGaugeString[0] != 0) {\r
+ // Display the record if it has a valid handle.\r
+ PrintToken (\r
+ STRING_TOKEN (STR_DP_HANDLE_VARS),\r
+ Count, // 1 based, Which measurement record is being printed\r
+ Index + 1, // 1 based, Which handle is being printed\r
+ mGaugeString,\r
+ mUnicodeToken,\r
+ ElapsedTime\r
+ );\r
+ }\r
+ }\r
+ }\r
+ FreePool (HandleBuffer);\r
+ return Status;\r
+}\r
+\r
+/** Gather and print PEIM data.\r
+ *\r
+ * Only prints complete PEIM records\r
+ *\r
+**/\r
+VOID\r
+ProcessPeims(\r
+ VOID\r
+)\r
+{\r
+ MEASUREMENT_RECORD Measurement;\r
+ UINT64 Duration;\r
+ UINT64 ElapsedTime;\r
+ EFI_STRING StringPtr;\r
+ UINTN LogEntryKey;\r
+ UINTN TIndex;\r
+\r
+\r
+ StringPtr = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_SECTION_PEIMS), NULL);\r
+ PrintToken( STRING_TOKEN (STR_DP_SECTION_HEADER),\r
+ (StringPtr == NULL) ? ALit_UNKNOWN: StringPtr);\r
+\r
+ PrintToken (STRING_TOKEN (STR_DP_PEIM_SECTION));\r
+ PrintToken (STRING_TOKEN (STR_DP_DASHES));\r
+ TIndex = 0;\r
+ LogEntryKey = 0;\r
+ while ((LogEntryKey = GetPerformanceMeasurement (\r
+ LogEntryKey,\r
+ &Measurement.Handle,\r
+ &Measurement.Token,\r
+ &Measurement.Module,\r
+ &Measurement.StartTimeStamp,\r
+ &Measurement.EndTimeStamp)) != 0)\r
+ {\r
+ TIndex++;\r
+ if ((Measurement.EndTimeStamp == 0) ||\r
+ (AsciiStrnCmp (Measurement.Token, ALit_PEIM, PERF_TOKEN_LENGTH) != 0)\r
+ ) {\r
+ continue;\r
+ }\r
+\r
+ Duration = GetDuration (&Measurement);\r
+ ElapsedTime = DurationInMicroSeconds ( Duration ); // Calculate elapsed time in microseconds\r
+ if (ElapsedTime >= mInterestThreshold) {\r
+ GetNameFromHandle (Measurement.Handle); // Name placed in mGaugeString\r
+ PrintToken (STRING_TOKEN (STR_DP_PEIM_STAT2),\r
+ TIndex, // 1 based, Which measurement record is being printed\r
+ Measurement.Handle,\r
+ mGaugeString,\r
+ ElapsedTime\r
+ );\r
+ }\r
+ }\r
+}\r
+\r
+/** Gather and print global data.\r
+ *\r
+ * Strips out incomplete or "Execution Phase" records\r
+ * Only prints records where Handle is NULL\r
+ * Increment TIndex for every record, even skipped ones, so that we have an\r
+ * indication of every measurement record taken.\r
+ *\r
+ *\r
+**/\r
+VOID\r
+ProcessGlobal(\r
+ VOID\r
+)\r
+{\r
+ MEASUREMENT_RECORD Measurement;\r
+ UINT64 Duration;\r
+ UINT64 ElapsedTime;\r
+ EFI_STRING StringPtr;\r
+ UINTN LogEntryKey;\r
+ UINTN Index; // Index, or number, of the measurement record being processed\r
+\r
+ StringPtr = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_SECTION_GENERAL), NULL);\r
+ PrintToken( STRING_TOKEN (STR_DP_SECTION_HEADER),\r
+ (StringPtr == NULL) ? ALit_UNKNOWN: StringPtr);\r
+\r
+ PrintToken (STRING_TOKEN (STR_DP_GLOBAL_SECTION));\r
+ PrintToken (STRING_TOKEN (STR_DP_DASHES));\r
+\r
+ Index = 1;\r
+ LogEntryKey = 0;\r
+\r
+ while ((LogEntryKey = GetPerformanceMeasurement (\r
+ LogEntryKey,\r
+ &Measurement.Handle,\r
+ &Measurement.Token,\r
+ &Measurement.Module,\r
+ &Measurement.StartTimeStamp,\r
+ &Measurement.EndTimeStamp)) != 0)\r
+ {\r
+ AsciiStrToUnicodeStr (Measurement.Module, mGaugeString);\r
+ AsciiStrToUnicodeStr (Measurement.Token, mUnicodeToken);\r
+ if ( ! ( IsPhase( &Measurement) ||\r
+ (Measurement.Handle != NULL) ||\r
+ (Measurement.EndTimeStamp == 0)\r
+ ))\r
+ {\r
+ Duration = GetDuration (&Measurement);\r
+ ElapsedTime = DurationInMicroSeconds ( Duration );\r
+ if (ElapsedTime >= mInterestThreshold) {\r
+ PrintToken (\r
+ STRING_TOKEN (STR_DP_FOUR_VARS_2),\r
+ Index,\r
+ mGaugeString,\r
+ mUnicodeToken,\r
+ ElapsedTime\r
+ );\r
+ }\r
+ }\r
+ Index++;\r
+ }\r
+}\r
+\r
+/** Gather and print cumulative data.\r
+ *\r
+ * Traverse the measurement records and:<BR>\r
+ * For each record with a Token listed in the CumData array:<BR>\r
+ * - Update the instance count and the total, minimum, and maximum durations.\r
+ * Finally, print the gathered cumulative statistics.\r
+ *\r
+**/\r
+VOID\r
+ProcessCumulative(\r
+ VOID\r
+)\r
+{\r
+ UINT64 avgval; // the computed average duration\r
+ EFI_STRING StringPtr;\r
+ UINTN TIndex;\r
+\r
+\r
+ StringPtr = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_SECTION_CUMULATIVE), NULL);\r
+ PrintToken( STRING_TOKEN (STR_DP_SECTION_HEADER),\r
+ (StringPtr == NULL) ? ALit_UNKNOWN: StringPtr);\r
+\r
+ PrintToken (STRING_TOKEN (STR_DP_CUMULATIVE_SECT_1));\r
+ PrintToken (STRING_TOKEN (STR_DP_CUMULATIVE_SECT_2));\r
+ PrintToken (STRING_TOKEN (STR_DP_DASHES));\r
+\r
+ for ( TIndex = 0; TIndex < NumCum; ++TIndex) {\r
+ avgval = DivU64x32 (CumData[TIndex].Duration, CumData[TIndex].Count);\r
+ PrintToken (STRING_TOKEN (STR_DP_CUMULATIVE_STATS),\r
+ CumData[TIndex].Name,\r
+ CumData[TIndex].Count,\r
+ DurationInMicroSeconds(CumData[TIndex].Duration),\r
+ DurationInMicroSeconds(avgval),\r
+ DurationInMicroSeconds(CumData[TIndex].MinDur),\r
+ DurationInMicroSeconds(CumData[TIndex].MaxDur)\r
+ );\r
+ }\r
+}\r
--- /dev/null
+/** @file\r
+ * Utility functions used by the Dp application.\r
+ *\r
+ * Copyright (c) 2009-2010, Intel Corporation. All rights reserved.<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 <Library/BaseLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/TimerLib.h>\r
+#include <Library/PeCoffGetEntryPointLib.h>\r
+#include <Library/PrintLib.h>\r
+#include <Library/HiiLib.h>\r
+#include <Library/PcdLib.h>\r
+\r
+#include <Protocol/LoadedImage.h>\r
+#include <Protocol/Driverbinding.h>\r
+\r
+#include <Guid/Performance.h>\r
+\r
+#include "Dp.h"\r
+#include "Literals.h"\r
+#include "DpInternal.h"\r
+\r
+/** Calculate an event's duration in timer ticks.\r
+ *\r
+ * Given the count direction and the event's start and end timer values,\r
+ * calculate the duration of the event in timer ticks. Information for\r
+ * the current measurement is pointed to by the parameter.\r
+ *\r
+ * If the measurement's start time is 1, it indicates that the developer\r
+ * is indicating that the measurement began at the release of reset.\r
+ * The start time is adjusted to the timer's starting count before performing\r
+ * the elapsed time calculation.\r
+ *\r
+ * The calculated duration, in ticks, is the absolute difference between\r
+ * the measurement's ending and starting counts.\r
+ *\r
+ * @pre The global TimerInfo structure must have already been initialized\r
+ * before this function is called.\r
+ *\r
+ * @param[in,out] Measurement Pointer to a MEASUREMENT_RECORD structure containing\r
+ * data for the current measurement.\r
+ *\r
+ * @return The 64-bit duration of the event.\r
+**/\r
+UINT64\r
+GetDuration (\r
+ IN OUT MEASUREMENT_RECORD *Measurement\r
+ )\r
+{\r
+ UINT64 Duration;\r
+ BOOLEAN Error;\r
+\r
+ // PERF_START macros are called with a value of 1 to indicate\r
+ // the beginning of time. So, adjust the start ticker value\r
+ // to the real beginning of time.\r
+ // Assumes no wraparound. Even then, there is a very low probability\r
+ // of having a valid StartTicker value of 1.\r
+ if (Measurement->StartTimeStamp == 1) {\r
+ Measurement->StartTimeStamp = TimerInfo.StartCount;\r
+ }\r
+ if (TimerInfo.CountUp) {\r
+ Duration = Measurement->EndTimeStamp - Measurement->StartTimeStamp;\r
+ Error = (BOOLEAN)(Duration > Measurement->EndTimeStamp);\r
+ }\r
+ else {\r
+ Duration = Measurement->StartTimeStamp - Measurement->EndTimeStamp;\r
+ Error = (BOOLEAN)(Duration > Measurement->StartTimeStamp);\r
+ }\r
+\r
+ if (Error) {\r
+ DEBUG ((EFI_D_ERROR, ALit_TimerLibError));\r
+ Duration = 0;\r
+ }\r
+ return Duration;\r
+}\r
+\r
+/** Determine whether the Measurement record is for an EFI Phase.\r
+ *\r
+ * The Token and Module members of the measurement record are checked.\r
+ * Module must be empty and Token must be one of SEC, PEI, DXE, BDS, or SHELL.\r
+ *\r
+ * @param[in] Measurement A pointer to the Measurement record to test.\r
+ *\r
+ * @retval TRUE The measurement record is for an EFI Phase.\r
+ * @retval FALSE The measurement record is NOT for an EFI Phase.\r
+**/\r
+BOOLEAN\r
+IsPhase(\r
+ IN MEASUREMENT_RECORD *Measurement\r
+ )\r
+{\r
+ BOOLEAN RetVal;\r
+\r
+ RetVal = (BOOLEAN)( ( *Measurement->Module == '\0') &&\r
+ ((AsciiStrnCmp (Measurement->Token, ALit_SEC, PERF_TOKEN_LENGTH) == 0) ||\r
+ (AsciiStrnCmp (Measurement->Token, ALit_PEI, PERF_TOKEN_LENGTH) == 0) ||\r
+ (AsciiStrnCmp (Measurement->Token, ALit_DXE, PERF_TOKEN_LENGTH) == 0) ||\r
+ (AsciiStrnCmp (Measurement->Token, ALit_BDS, PERF_TOKEN_LENGTH) == 0))\r
+ );\r
+ return RetVal;\r
+}\r
+\r
+/** Get the file name portion of the Pdb File Name.\r
+ *\r
+ * The portion of the Pdb File Name between the last backslash and\r
+ * either a following period or the end of the string is converted\r
+ * to Unicode and copied into UnicodeBuffer. The name is truncated,\r
+ * if necessary, to ensure that UnicodeBuffer is not overrun.\r
+ *\r
+ * @param[in] PdbFileName Pdb file name.\r
+ * @param[out] UnicodeBuffer The resultant Unicode File Name.\r
+ *\r
+**/\r
+VOID\r
+GetShortPdbFileName (\r
+ IN CHAR8 *PdbFileName,\r
+ OUT CHAR16 *UnicodeBuffer\r
+ )\r
+{\r
+ UINTN IndexA; // Current work location within an ASCII string.\r
+ UINTN IndexU; // Current work location within a Unicode string.\r
+ UINTN StartIndex;\r
+ UINTN EndIndex;\r
+\r
+ ZeroMem (UnicodeBuffer, DXE_PERFORMANCE_STRING_LENGTH * sizeof (CHAR16));\r
+\r
+ if (PdbFileName == NULL) {\r
+ StrCpy (UnicodeBuffer, L" ");\r
+ } else {\r
+ StartIndex = 0;\r
+ for (EndIndex = 0; PdbFileName[EndIndex] != 0; EndIndex++)\r
+ ;\r
+ for (IndexA = 0; PdbFileName[IndexA] != 0; IndexA++) {\r
+ if (PdbFileName[IndexA] == '\\') {\r
+ StartIndex = IndexA + 1;\r
+ }\r
+\r
+ if (PdbFileName[IndexA] == '.') {\r
+ EndIndex = IndexA;\r
+ }\r
+ }\r
+\r
+ IndexU = 0;\r
+ for (IndexA = StartIndex; IndexA < EndIndex; IndexA++) {\r
+ UnicodeBuffer[IndexU] = (CHAR16) PdbFileName[IndexA];\r
+ IndexU++;\r
+ if (IndexU >= DXE_PERFORMANCE_STRING_LENGTH) {\r
+ UnicodeBuffer[DXE_PERFORMANCE_STRING_LENGTH] = 0;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+}\r
+\r
+/** Get a human readable name for an image handle.\r
+ *\r
+ * @param[in] Handle\r
+ *\r
+ * @post The resulting Unicode name string is stored in the\r
+ * mGaugeString global array.\r
+ *\r
+**/\r
+VOID\r
+GetNameFromHandle (\r
+ IN EFI_HANDLE Handle\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_LOADED_IMAGE_PROTOCOL *Image;\r
+ CHAR8 *PdbFileName;\r
+ EFI_DRIVER_BINDING_PROTOCOL *DriverBinding;\r
+ EFI_STRING StringPtr;\r
+\r
+ // Proactively get the error message so it will be ready if needed\r
+ StringPtr = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_ERROR_NAME), NULL);\r
+ ASSERT (StringPtr != NULL);\r
+\r
+ // Get handle name from image protocol\r
+ //\r
+ Status = gBS->HandleProtocol (\r
+ Handle,\r
+ &gEfiLoadedImageProtocolGuid,\r
+ &Image\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ Status = gBS->OpenProtocol (\r
+ Handle,\r
+ &gEfiDriverBindingProtocolGuid,\r
+ (VOID **) &DriverBinding,\r
+ NULL,\r
+ NULL,\r
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ StrCpy (mGaugeString, StringPtr);\r
+ return ;\r
+ }\r
+\r
+ // Get handle name from image protocol\r
+ //\r
+ Status = gBS->HandleProtocol (\r
+ DriverBinding->ImageHandle,\r
+ &gEfiLoadedImageProtocolGuid,\r
+ &Image\r
+ );\r
+ }\r
+\r
+ PdbFileName = PeCoffLoaderGetPdbPointer (Image->ImageBase);\r
+\r
+ if (PdbFileName != NULL) {\r
+ GetShortPdbFileName (PdbFileName, mGaugeString);\r
+ } else {\r
+ StrCpy (mGaugeString, StringPtr);\r
+ }\r
+ return ;\r
+}\r
+\r
+/** Calculate the Duration in microseconds.\r
+ *\r
+ * Duration is multiplied by 1000, instead of Frequency being divided by 1000 or\r
+ * multiplying the result by 1000, in order to maintain precision. Since Duration is\r
+ * a 64-bit value, multiplying it by 1000 is unlikely to produce an overflow.\r
+ *\r
+ * The time is calculated as (Duration * 1000) / Timer_Frequency.\r
+ *\r
+ * @param[in] Duration The event duration in timer ticks.\r
+ *\r
+ * @return A 64-bit value which is the Elapsed time in microseconds.\r
+**/\r
+UINT64\r
+DurationInMicroSeconds (\r
+ IN UINT64 Duration\r
+ )\r
+{\r
+ UINT64 Temp;\r
+\r
+ Temp = MultU64x32 (Duration, 1000);\r
+ return DivU64x32 (Temp, TimerInfo.Frequency);\r
+}\r
+\r
+/** Formatted Print using a Hii Token to reference the localized format string.\r
+ *\r
+ * @param[in] Token A HII token associated with a localized Unicode string.\r
+ *\r
+ * @return The number of characters converted by UnicodeVSPrint().\r
+ *\r
+**/\r
+UINTN\r
+PrintToken (\r
+ IN UINT16 Token,\r
+ ...\r
+ )\r
+{\r
+ VA_LIST Marker;\r
+ EFI_STRING StringPtr;\r
+ UINTN Return;\r
+ UINTN BufferSize;\r
+\r
+ StringPtr = HiiGetString (gHiiHandle, Token, NULL);\r
+ ASSERT (StringPtr != NULL);\r
+\r
+ VA_START (Marker, Token);\r
+\r
+ BufferSize = (PcdGet32 (PcdUefiLibMaxPrintBufferSize) + 1) * sizeof (CHAR16);\r
+\r
+ if (mPrintTokenBuffer == NULL) {\r
+ mPrintTokenBuffer = AllocatePool (BufferSize);\r
+ ASSERT (mPrintTokenBuffer != NULL);\r
+ }\r
+ SetMem( mPrintTokenBuffer, BufferSize, 0);\r
+\r
+ Return = UnicodeVSPrint (mPrintTokenBuffer, BufferSize, StringPtr, Marker);\r
+ if (Return > 0 && gST->ConOut != NULL) {\r
+ gST->ConOut->OutputString (gST->ConOut, mPrintTokenBuffer);\r
+ }\r
+ return Return;\r
+}\r
+\r
+/** Get index of Measurement Record's match in the CumData array.\r
+ *\r
+ * If the Measurement's Token value matches a Token in one of the CumData\r
+ * records, the index of the matching record is returned. The returned\r
+ * index is a signed value so that negative values can indicate that\r
+ * the Measurement didn't match any entry in the CumData array.\r
+ *\r
+ * @param[in] Measurement A pointer to a Measurement Record to match against the CumData array.\r
+ *\r
+ * @retval <0 Token is not in the CumData array.\r
+ * @retval >=0 Return value is the index into CumData where Token is found.\r
+**/\r
+INTN\r
+GetCumulativeItem(\r
+ IN MEASUREMENT_RECORD *Measurement\r
+ )\r
+{\r
+ INTN Index;\r
+\r
+ for( Index = 0; Index < (INTN)NumCum; ++Index) {\r
+ if (AsciiStrnCmp (Measurement->Token, CumData[Index].Name, PERF_TOKEN_LENGTH) == 0) {\r
+ return Index; // Exit, we found a match\r
+ }\r
+ }\r
+ // If the for loop exits, Token was not found.\r
+ return -1; // Indicate failure\r
+}\r
--- /dev/null
+/** @file\r
+ * Definitions of ASCII string literals used by DP.\r
+ *\r
+ * Copyright (c) 2009-2010, Intel Corporation. All rights reserved.<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
+#include <PerformanceTokens.h>\r
+\r
+// ASCII String literals which probably don't need translation\r
+CHAR8 const ALit_TimerLibError[] = "Timer library instance error!\n";\r
+CHAR8 const ALit_SEC[] = SEC_TOK;\r
+CHAR8 const ALit_DXE[] = DXE_TOK;\r
+CHAR8 const ALit_SHELL[] = SHELL_TOK;\r
+CHAR8 const ALit_PEI[] = PEI_TOK;\r
+CHAR8 const ALit_BDS[] = BDS_TOK;\r
+CHAR8 const ALit_BdsTO[] = "BdsTimeOut";\r
+CHAR8 const ALit_PEIM[] = "PEIM";\r
+\r
+/// UNICODE String literals which should probably be translated\r
+CHAR16 STR_DP_OPTION_UA[] = L"-A";\r
+CHAR16 STR_DP_OPTION_LA[] = L"-a";\r
+CHAR16 STR_DP_OPTION_LN[] = L"-n";\r
+CHAR16 STR_DP_OPTION_LT[] = L"-t";\r
+CHAR16 STR_DP_OPTION_UP[] = L"-P";\r
+CHAR16 STR_DP_OPTION_UR[] = L"-R";\r
+CHAR16 STR_DP_OPTION_LS[] = L"-s";\r
+CHAR16 STR_DP_OPTION_US[] = L"-S";\r
+CHAR16 STR_DP_OPTION_UT[] = L"-T";\r
+CHAR16 STR_DP_OPTION_LV[] = L"-v";\r
+CHAR16 STR_DP_OPTION_QH[] = L"-?";\r
+CHAR16 STR_DP_OPTION_LH[] = L"-h";\r
+CHAR16 STR_DP_OPTION_UH[] = L"-H";\r
+CHAR16 STR_DP_OPTION_LX[] = L"-x";\r
+\r
+CHAR16 const ALit_UNKNOWN[] = L"Unknown";\r
+CHAR16 const STR_DP_INCOMPLETE[] = L" I ";\r
+CHAR16 const STR_DP_COMPLETE[] = L" ";\r
+\r
+CHAR8 const ALit_TRUE[] = "TRUE";\r
+CHAR8 const ALit_FALSE[] = "FALSE";\r
--- /dev/null
+/** @file\r
+ * Declarations of ASCII string literals used by DP.\r
+ *\r
+ * Copyright (c) 2009-2010, Intel Corporation. All rights reserved.<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
+#ifndef _LITERALS_H_\r
+#define _LITERALS_H_\r
+\r
+// ASCII String literals which probably don't need translation\r
+extern CHAR8 const ALit_TimerLibError[];\r
+extern CHAR8 const ALit_SEC[];\r
+extern CHAR8 const ALit_DXE[];\r
+extern CHAR8 const ALit_SHELL[];\r
+extern CHAR8 const ALit_PEI[];\r
+extern CHAR8 const ALit_BDS[];\r
+extern CHAR8 const ALit_BdsTO[];\r
+extern CHAR8 const ALit_PEIM[];\r
+\r
+/// UNICODE String literals which should probably be translated\r
+extern CHAR16 STR_DP_OPTION_UA[];\r
+extern CHAR16 STR_DP_OPTION_LA[];\r
+extern CHAR16 STR_DP_OPTION_LN[];\r
+extern CHAR16 STR_DP_OPTION_LT[];\r
+extern CHAR16 STR_DP_OPTION_UP[];\r
+extern CHAR16 STR_DP_OPTION_UR[];\r
+extern CHAR16 STR_DP_OPTION_LS[];\r
+extern CHAR16 STR_DP_OPTION_US[];\r
+extern CHAR16 STR_DP_OPTION_UT[];\r
+extern CHAR16 STR_DP_OPTION_LV[];\r
+extern CHAR16 STR_DP_OPTION_QH[];\r
+extern CHAR16 STR_DP_OPTION_LH[];\r
+extern CHAR16 STR_DP_OPTION_UH[];\r
+extern CHAR16 STR_DP_OPTION_LX[];\r
+\r
+extern CHAR16 const ALit_UNKNOWN[];\r
+extern CHAR16 const STR_DP_INCOMPLETE[];\r
+extern CHAR16 const STR_DP_COMPLETE[];\r
+\r
+extern CHAR8 const ALit_TRUE[];\r
+extern CHAR8 const ALit_FALSE[];\r
+\r
+#endif // _LITERALS_H_\r
--- /dev/null
+/** @file\r
+ Generic definitions for registers in the Intel Ich devices.\r
+\r
+ These definitions should work for any version of Ich.\r
+\r
+ Copyright (c) 2009-2010, Intel Corporation. All rights reserved.<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
+\r
+#ifndef _GENERIC_ICH_H_\r
+#define _GENERIC_ICH_H_\r
+\r
+/** @defgroup GenericIchDefs Generic ICH Definitions.\r
+\r
+Definitions beginning with "R_" are registers.\r
+Definitions beginning with "B_" are bits within registers.\r
+Definitions beginning with "V_" are meaningful values of bits within the registers.\r
+**/\r
+///@{\r
+\r
+/// @defgroup IchPciAddressing PCI Bus Address for ICH.\r
+///@{\r
+#define PCI_BUS_NUMBER_ICH 0x00 ///< ICH is on PCI Bus 0.\r
+#define PCI_DEVICE_NUMBER_ICH_LPC 31 ///< ICH is Device 31.\r
+#define PCI_FUNCTION_NUMBER_ICH_LPC 0 ///< ICH is Function 0.\r
+///@}\r
+\r
+/// @defgroup IchAcpiCntr Control for the ICH's ACPI Counter.\r
+///@{\r
+#define R_ICH_LPC_ACPI_BASE 0x40\r
+#define R_ICH_LPC_ACPI_CNT 0x44\r
+#define B_ICH_LPC_ACPI_CNT_ACPI_EN 0x80\r
+///@}\r
+\r
+/// @defgroup IchAcpiTimer The ICH's ACPI Timer.\r
+///@{\r
+#define R_ACPI_PM1_TMR 0x08\r
+#define V_ACPI_TMR_FREQUENCY 3579545\r
+#define V_ACPI_PM1_TMR_MAX_VAL 0x1000000 ///< The timer is 24 bit overflow.\r
+///@}\r
+\r
+/// Macro to generate the PCI address of any given ICH Register.\r
+#define PCI_ICH_LPC_ADDRESS(Register) \\r
+ ((UINTN)(PCI_LIB_ADDRESS (PCI_BUS_NUMBER_ICH, PCI_DEVICE_NUMBER_ICH_LPC, PCI_FUNCTION_NUMBER_ICH_LPC, Register)))\r
+\r
+///@}\r
+#endif // _GENERIC_ICH_H_\r
--- /dev/null
+/** @file\r
+ ASCII String Literals with special meaning to Performance measurement and the Dp utility.\r
+\r
+Copyright (c) 2009-2010, Intel Corporation. All rights reserved.<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
+\r
+#ifndef __PERFORMANCE_TOKENS_H__\r
+#define __PERFORMANCE_TOKENS_H__\r
+\r
+#define SEC_TOK "SEC" ///< SEC Phase\r
+#define DXE_TOK "DXE" ///< DEC Phase\r
+#define SHELL_TOK "SHELL" ///< Shell Phase\r
+#define PEI_TOK "PEI" ///< PEI Phase\r
+#define BDS_TOK "BDS" ///< BDS Phase\r
+#define DRIVERBINDING_START_TOK "DB:Start:" ///< Driver Binding Start() function call\r
+#define DRIVERBINDING_SUPPORT_TOK "DB:Support:" ///< Driver Binding Support() function call\r
+#define LOAD_IMAGE_TOK "LoadImage:" ///< Load a dispatched module\r
+#define START_IMAGE_TOK "StartImage:" ///< Dispatched Modules Entry Point execution\r
+\r
+#endif // __PERFORMANCE_TOKENS_H__\r
--- /dev/null
+/** @file\r
+ A Timer Library implementation which uses the Time Stamp Counter in the processor.\r
+\r
+ For Pentium 4 processors, Intel Xeon processors (family [0FH], models [03H and higher]);\r
+ for Intel Core Solo and Intel Core Duo processors (family [06H], model [0EH]);\r
+ for the Intel Xeon processor 5100 series and Intel Core 2 Duo processors (family [06H], model [0FH]);\r
+ for Intel Core 2 and Intel Xeon processors (family [06H], display_model [17H]);\r
+ for Intel Atom processors (family [06H], display_model [1CH]):\r
+ the time-stamp counter increments at a constant rate.\r
+ That rate may be set by the maximum core-clock to bus-clock ratio of the processor or may be set by\r
+ the maximum resolved frequency at which the processor is booted. The maximum resolved frequency may\r
+ differ from the maximum qualified frequency of the processor.\r
+\r
+ The specific processor configuration determines the behavior. Constant TSC behavior ensures that the\r
+ duration of each clock tick is uniform and supports the use of the TSC as a wall clock timer even if\r
+ the processor core changes frequency. This is the architectural behavior moving forward.\r
+\r
+ A Processor\92s support for invariant TSC is indicated by CPUID.0x80000007.EDX[8].\r
+\r
+ Copyright (c) 2009-2010, Intel Corporation. All rights reserved.<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
+\r
+#include <Base.h>\r
+#include <Ich/GenericIch.h>\r
+\r
+#include <Library/TimerLib.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/IoLib.h>\r
+#include <Library/PciLib.h>\r
+#include <Library/PcdLib.h>\r
+\r
+STATIC UINT64 mTscFrequency;\r
+\r
+#ifndef R_ICH_ACPI_PM1_TMR\r
+#define R_ICH_ACPI_PM1_TMR R_ACPI_PM1_TMR\r
+#endif\r
+\r
+/** The constructor function determines the actual TSC frequency.\r
+\r
+ The TSC counting frequency is determined by comparing how far it counts\r
+ during a 1ms period as determined by the ACPI timer. The ACPI timer is\r
+ used because it counts at a known frequency.\r
+ If ACPI I/O space not enabled, this function will enable it. Then the\r
+ TSC is sampled, followed by waiting for 3579 clocks of the ACPI timer, or 1ms.\r
+ The TSC is then sampled again. The difference multiplied by 1000 is the TSC\r
+ frequency. There will be a small error because of the overhead of reading\r
+ the ACPI timer. An attempt is made to determine and compensate for this error.\r
+ This function will always return RETURN_SUCCESS.\r
+\r
+ @retval RETURN_SUCCESS The constructor always returns RETURN_SUCCESS.\r
+\r
+**/\r
+RETURN_STATUS\r
+EFIAPI\r
+TscTimerLibConstructor (\r
+ VOID\r
+ )\r
+{\r
+ UINT64 StartTSC;\r
+ UINT64 EndTSC;\r
+ UINT32 TimerAddr;\r
+ UINT32 Ticks;\r
+\r
+ //\r
+ // If ACPI I/O space is not enabled yet, program ACPI I/O base address and enable it.\r
+ //\r
+ if ((PciRead8 (PCI_ICH_LPC_ADDRESS (R_ICH_LPC_ACPI_CNT)) & B_ICH_LPC_ACPI_CNT_ACPI_EN) == 0) {\r
+ PciWrite16 (PCI_ICH_LPC_ADDRESS (R_ICH_LPC_ACPI_BASE), PcdGet16 (PcdPerfPkgAcpiIoPortBaseAddress));\r
+ PciOr8 (PCI_ICH_LPC_ADDRESS (R_ICH_LPC_ACPI_CNT), B_ICH_LPC_ACPI_CNT_ACPI_EN);\r
+ }\r
+\r
+ TimerAddr = PcdGet16 (PcdPerfPkgAcpiIoPortBaseAddress) + R_ACPI_PM1_TMR; // Locate the ACPI Timer\r
+ Ticks = IoRead32( TimerAddr) + (3579); // Set Ticks to 1ms in the future\r
+ StartTSC = AsmReadTsc(); // Get base value for the TSC\r
+ //\r
+ // Wait until the ACPI timer has counted 1ms.\r
+ // Timer wrap-arounds are handled correctly by this function.\r
+ // When the current ACPI timer value is greater than 'Ticks', the while loop will exit.\r
+ //\r
+ while (((Ticks - IoRead32( TimerAddr)) & BIT23) == 0) {\r
+ CpuPause();\r
+ }\r
+ EndTSC = AsmReadTsc(); // TSC value 1ms later\r
+\r
+ mTscFrequency = MultU64x32 (\r
+ (EndTSC - StartTSC), // Number of TSC counts in 1ms\r
+ 1000 // Number of ms in a second\r
+ );\r
+ //\r
+ // mTscFrequency is now equal to the number of TSC counts per second\r
+ //\r
+ return RETURN_SUCCESS;\r
+}\r
+\r
+/** Stalls the CPU for at least the given number of ticks.\r
+\r
+ Stalls the CPU for at least the given number of ticks. It's invoked by\r
+ MicroSecondDelay() and NanoSecondDelay().\r
+\r
+ @param[in] Delay A period of time to delay in ticks.\r
+\r
+**/\r
+STATIC\r
+VOID\r
+InternalX86Delay (\r
+ IN UINT64 Delay\r
+ )\r
+{\r
+ UINT64 Ticks;\r
+\r
+ //\r
+ // The target timer count is calculated here\r
+ //\r
+ Ticks = AsmReadTsc() + Delay;\r
+\r
+ //\r
+ // Wait until time out\r
+ // Timer wrap-arounds are NOT handled correctly by this function.\r
+ // Thus, this function must be called within 10 years of reset since\r
+ // Intel guarantees a minimum of 10 years before the TSC wraps.\r
+ //\r
+ while (AsmReadTsc() <= Ticks) CpuPause();\r
+}\r
+\r
+/** Stalls the CPU for at least the specified number of MicroSeconds.\r
+\r
+ @param[in] MicroSeconds The minimum number of microseconds to delay.\r
+\r
+ @return The value of MicroSeconds input.\r
+\r
+**/\r
+UINTN\r
+EFIAPI\r
+MicroSecondDelay (\r
+ IN UINTN MicroSeconds\r
+ )\r
+{\r
+ InternalX86Delay (\r
+ DivU64x32 (\r
+ MultU64x64 (\r
+ mTscFrequency,\r
+ MicroSeconds\r
+ ),\r
+ 1000000u\r
+ )\r
+ );\r
+ return MicroSeconds;\r
+}\r
+\r
+/** Stalls the CPU for at least the specified number of NanoSeconds.\r
+\r
+ @param[in] NanoSeconds The minimum number of nanoseconds to delay.\r
+\r
+ @return The value of NanoSeconds input.\r
+\r
+**/\r
+UINTN\r
+EFIAPI\r
+NanoSecondDelay (\r
+ IN UINTN NanoSeconds\r
+ )\r
+{\r
+ InternalX86Delay (\r
+ DivU64x32 (\r
+ MultU64x32 (\r
+ mTscFrequency,\r
+ (UINT32)NanoSeconds\r
+ ),\r
+ 1000000000u\r
+ )\r
+ );\r
+ return NanoSeconds;\r
+}\r
+\r
+/** Retrieves the current value of the 64-bit free running Time-Stamp counter.\r
+\r
+ The time-stamp counter (as implemented in the P6 family, Pentium, Pentium M,\r
+ Pentium 4, Intel Xeon, Intel Core Solo and Intel Core Duo processors and\r
+ later processors) is a 64-bit counter that is set to 0 following a RESET of\r
+ the processor. Following a RESET, the counter increments even when the\r
+ processor is halted by the HLT instruction or the external STPCLK# pin. Note\r
+ that the assertion of the external DPSLP# pin may cause the time-stamp\r
+ counter to stop.\r
+\r
+ The properties of the counter can be retrieved by the\r
+ GetPerformanceCounterProperties() function.\r
+\r
+ @return The current value of the free running performance counter.\r
+\r
+**/\r
+UINT64\r
+EFIAPI\r
+GetPerformanceCounter (\r
+ VOID\r
+ )\r
+{\r
+ return AsmReadTsc();\r
+}\r
+\r
+/** Retrieves the 64-bit frequency in Hz and the range of performance counter\r
+ values.\r
+\r
+ If StartValue is not NULL, then the value that the performance counter starts\r
+ with, 0x0, is returned in StartValue. If EndValue is not NULL, then the value\r
+ that the performance counter end with, 0xFFFFFFFFFFFFFFFF, is returned in\r
+ EndValue.\r
+\r
+ The 64-bit frequency of the performance counter, in Hz, is always returned.\r
+ To determine average processor clock frequency, Intel recommends the use of\r
+ EMON logic to count processor core clocks over the period of time for which\r
+ the average is required.\r
+\r
+\r
+ @param[out] StartValue Pointer to where the performance counter's starting value is saved, or NULL.\r
+ @param[out] EndValue Pointer to where the performance counter's ending value is saved, or NULL.\r
+\r
+ @return The frequency in Hz.\r
+\r
+**/\r
+UINT64\r
+EFIAPI\r
+GetPerformanceCounterProperties (\r
+ OUT UINT64 *StartValue, OPTIONAL\r
+ OUT UINT64 *EndValue OPTIONAL\r
+ )\r
+{\r
+ if (StartValue != NULL) {\r
+ *StartValue = 0;\r
+ }\r
+ if (EndValue != NULL) {\r
+ *EndValue = 0xFFFFFFFFFFFFFFFFull;\r
+ }\r
+\r
+ return mTscFrequency;\r
+}\r
--- /dev/null
+#/** @file\r
+# Timer Library which uses the Time Stamp Counter in the processor.\r
+#\r
+# A version of the Timer Library using the processor's TSC.\r
+# The time stamp counter in newer processors may support an enhancement, referred to as invariant TSC.\r
+# The invariant TSC runs at a constant rate in all ACPI P-, C-. and T-states.\r
+# This is the architectural behavior moving forward.\r
+# TSC reads are much more efficient and do not incur the overhead associated with a ring transition or\r
+# access to a platform resource.\r
+#\r
+# Copyright (c) 2009-2010, Intel Corporation. All rights reserved.\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
+# 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
+\r
+[Defines]\r
+ INF_VERSION = 0x00010005\r
+ BASE_NAME = TscTimerLib\r
+ FILE_GUID = 95ab030f-b4fd-4ee4-92a5-9e04e87634d9\r
+ MODULE_TYPE = BASE\r
+ VERSION_STRING = 1.0\r
+ LIBRARY_CLASS = TimerLib\r
+\r
+ CONSTRUCTOR = TscTimerLibConstructor\r
+\r
+\r
+#\r
+# VALID_ARCHITECTURES = IA32 X64\r
+#\r
+\r
+[Sources.common]\r
+ TscTimerLib.c\r
+\r
+\r
+[Packages]\r
+ MdePkg/MdePkg.dec\r
+ PerformancePkg/PerformancePkg.dec\r
+\r
+\r
+[LibraryClasses]\r
+ PcdLib\r
+ PciLib\r
+ IoLib\r
+ BaseLib\r
+\r
+[Pcd.common]\r
+ gPerformancePkgTokenSpaceGuid.PcdPerfPkgAcpiIoPortBaseAddress\r
--- /dev/null
+#/** @file\r
+# Build description file to generate Shell DP application and\r
+# Performance Libraries.\r
+#\r
+# Copyright (c) 2009-2010, Intel Corporation. All rights reserved.<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
+\r
+[Defines]\r
+ PACKAGE_NAME = PerformancePkg\r
+ PACKAGE_GUID = ce898697-b945-46e2-a26e-5752af565185\r
+ PACKAGE_VERSION = 0.1\r
+ DEC_SPECIFICATION = 0x00010005\r
+\r
+[Includes.common]\r
+ Include\r
+\r
+[Guids.common]\r
+ ## Performance Package token space guid\r
+ # Include/Guid/PerformancePkgTokenSpace.h\r
+ # 669346ef-fdad-4aeb-a608-7def3f2d4621\r
+ gPerformancePkgTokenSpaceGuid = { 0x669346ef, 0xFDad, 0x4aeb, { 0x08, 0xa6, 0x21, 0x46, 0x2d, 0x3f, 0xef, 0x7d }}\r
+\r
+[PcdsFixedAtBuild.common]\r
+ ## The base address of the ACPI registers within the ICH PCI space.\r
+ # This space must be 128-byte aligned.\r
+ gPerformancePkgTokenSpaceGuid.PcdPerfPkgAcpiIoPortBaseAddress|0x400|UINT16|1\r
--- /dev/null
+#/** @file\r
+# Build description file to generate Shell DP application.\r
+#\r
+# Copyright (c) 2009-2010, Intel Corporation. All rights reserved.<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
+\r
+[Defines]\r
+ DSC_SPECIFICATION = 0x00010005\r
+ PLATFORM_NAME = PerformancePkg\r
+ PLATFORM_GUID = 9ffd7bf2-231e-4525-9a42-480545dafd17\r
+ PLATFORM_VERSION = 0.1\r
+ OUTPUT_DIRECTORY = Build/PerformancePkg\r
+ SUPPORTED_ARCHITECTURES = IA32|IPF|X64|EBC\r
+ BUILD_TARGETS = DEBUG|RELEASE\r
+ SKUID_IDENTIFIER = DEFAULT\r
+\r
+[LibraryClasses]\r
+ #\r
+ # Entry Point Libraries\r
+ #\r
+ UefiApplicationEntryPoint|MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf\r
+ #\r
+ # Common Libraries\r
+ #\r
+ BaseLib|MdePkg/Library/BaseLib/BaseLib.inf\r
+ BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf\r
+ UefiLib|MdePkg/Library/UefiLib/UefiLib.inf\r
+ PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf\r
+ PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf\r
+ MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf\r
+ UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf\r
+ UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf\r
+ DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf\r
+ DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf\r
+ PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf\r
+ HiiLib|MdeModulePkg/Library/UefiHiiLib/UefiHiiLib.inf\r
+ UefiHiiServicesLib|MdeModulePkg/Library/UefiHiiServicesLib/UefiHiiServicesLib.inf\r
+ PerformanceLib|MdeModulePkg/Library/DxePerformanceLib/DxePerformanceLib.inf\r
+ IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf\r
+\r
+ ShellLib|ShellPkg/Library/UefiShellLib/UefiShellLib.inf\r
+ FileHandleLib|ShellPkg/Library/BaseFileHandleLib/BaseFileHandleLib.inf\r
+\r
+ # This library instance mapping needs adjusting based on platform.\r
+ # The TimerLib instance must match the TimerLib the platform was built with.\r
+ # If the platform was built with more than one TimerLib type, then this utility\r
+ # will produce invalid results for any measurements done with a TimerLib instance\r
+ # that is different than the one below.\r
+ #\r
+ # TimerLib|MdePkg/Library/SecPeiDxeTimerLibCpu/SecPeiDxeTimerLibCpu.inf\r
+ TimerLib|PerformancePkg/Library/TscTimerLib/TscTimerLib.inf\r
+ PciLib|MdePkg/Library/BasePciLibCf8/BasePciLibCf8.inf\r
+ PciCf8Lib|MdePkg/Library/BasePciCf8Lib/BasePciCf8Lib.inf\r
+\r
+[LibraryClasses.IPF]\r
+ PalLib|MdePkg/Library/UefiPalLib/UefiPalLib.inf\r
+\r
+[Components]\r
+ PerformancePkg/Library/TscTimerLib/TscTimerLib.inf\r
+ PerformancePkg/Dp_App/Dp.inf\r