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