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 Processor’s 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