summaryrefslogtreecommitdiff
path: root/ShellPkg/Library
diff options
context:
space:
mode:
authorjcarsey <jcarsey@6f19259b-4bc3-4df7-8a09-765794883524>2013-03-04 22:02:59 +0000
committerjcarsey <jcarsey@6f19259b-4bc3-4df7-8a09-765794883524>2013-03-04 22:02:59 +0000
commitd41bc92c99edd0e22dd60b5a415539987a631234 (patch)
tree3e4923543bfba445ae6d390582b2402f0a319ad6 /ShellPkg/Library
parent365aa98a5dfba45b7ecfe04495cb28e9e05d2a45 (diff)
downloadedk2-platforms-d41bc92c99edd0e22dd60b5a415539987a631234.tar.xz
ShellPkg: Add "dp" command library to ShellPkg.
This command is only included in the build with command line option "-D INCLUDE_DP". The user must also update the DSC with appropriate library instances that match the platform for the build to succeed. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Jaben Carsey <jaben.carsey@intel.com> Reviewed-by: Erik Bjorge <erik.c.bjorge@intel.com> git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@14160 6f19259b-4bc3-4df7-8a09-765794883524
Diffstat (limited to 'ShellPkg/Library')
-rw-r--r--ShellPkg/Library/UefiDpLib/Dp.c310
-rw-r--r--ShellPkg/Library/UefiDpLib/Dp.h98
-rw-r--r--ShellPkg/Library/UefiDpLib/DpInternal.h340
-rw-r--r--ShellPkg/Library/UefiDpLib/DpProfile.c101
-rw-r--r--ShellPkg/Library/UefiDpLib/DpTrace.c828
-rw-r--r--ShellPkg/Library/UefiDpLib/DpUtilities.c400
-rw-r--r--ShellPkg/Library/UefiDpLib/Literals.c23
-rw-r--r--ShellPkg/Library/UefiDpLib/Literals.h26
-rw-r--r--ShellPkg/Library/UefiDpLib/UefiDpLib.c101
-rw-r--r--ShellPkg/Library/UefiDpLib/UefiDpLib.h60
-rw-r--r--ShellPkg/Library/UefiDpLib/UefiDpLib.inf75
-rw-r--r--ShellPkg/Library/UefiDpLib/UefiDpLib.unibin0 -> 17140 bytes
-rw-r--r--ShellPkg/Library/UefiDpLib/readme.txt2
13 files changed, 2364 insertions, 0 deletions
diff --git a/ShellPkg/Library/UefiDpLib/Dp.c b/ShellPkg/Library/UefiDpLib/Dp.c
new file mode 100644
index 0000000000..b5a6e7a713
--- /dev/null
+++ b/ShellPkg/Library/UefiDpLib/Dp.c
@@ -0,0 +1,310 @@
+/** @file
+ Shell command for Displaying Performance Metrics.
+
+ The Dp command 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 - 2013, 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.
+**/
+
+#include "UefiDpLib.h"
+#include <Guid/GlobalVariable.h>
+#include <Library/PrintLib.h>
+#include <Library/HandleParsingLib.h>
+#include <Library/DevicePathLib.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 <Guid/Performance.h>
+
+#include <PerformanceTokens.h>
+#include "Dp.h"
+#include "Literals.h"
+#include "DpInternal.h"
+
+//
+/// Module-Global Variables
+///@{
+CHAR16 mGaugeString[DP_GAUGE_STRING_LENGTH + 1];
+CHAR16 mUnicodeToken[DXE_PERFORMANCE_STRING_SIZE];
+UINT64 mInterestThreshold;
+BOOLEAN mShowId = FALSE;
+
+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);
+
+STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
+ {L"-v", TypeFlag}, // -v Verbose Mode
+ {L"-A", TypeFlag}, // -A All, Cooked
+ {L"-R", TypeFlag}, // -R RAW All
+ {L"-s", TypeFlag}, // -s Summary
+#if PROFILING_IMPLEMENTED
+ {L"-P", TypeFlag}, // -P Dump Profile Data
+ {L"-T", TypeFlag}, // -T Dump Trace Data
+#endif // PROFILING_IMPLEMENTED
+ {L"-x", TypeFlag}, // -x eXclude Cumulative Items
+ {L"-i", TypeFlag}, // -i Display Identifier
+ {L"-n", TypeValue}, // -n # Number of records to display for A and R
+ {L"-t", TypeValue}, // -t # Threshold of interest
+ {NULL, TypeMax}
+ };
+
+///@}
+
+/**
+ Display the trailing Verbose information.
+**/
+VOID
+DumpStatistics( void )
+{
+ EFI_STRING StringPtr;
+ EFI_STRING StringPtrUnknown;
+ StringPtr = HiiGetString (gDpHiiHandle, STRING_TOKEN (STR_DP_SECTION_STATISTICS), NULL);
+ StringPtrUnknown = HiiGetString (gDpHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL);
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_SECTION_HEADER), gDpHiiHandle,
+ (StringPtr == NULL) ? StringPtrUnknown : StringPtr);
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_STATS_NUMTRACE), gDpHiiHandle, SummaryData.NumTrace);
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_STATS_NUMINCOMPLETE), gDpHiiHandle, SummaryData.NumIncomplete);
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_STATS_NUMPHASES), gDpHiiHandle, SummaryData.NumSummary);
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_STATS_NUMHANDLES), gDpHiiHandle, SummaryData.NumHandles, SummaryData.NumTrace - SummaryData.NumHandles);
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_STATS_NUMPEIMS), gDpHiiHandle, SummaryData.NumPEIMs);
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_STATS_NUMGLOBALS), gDpHiiHandle, SummaryData.NumGlobal);
+#if PROFILING_IMPLEMENTED
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_STATS_NUMPROFILE), gDpHiiHandle, SummaryData.NumProfile);
+#endif // PROFILING_IMPLEMENTED
+ SHELL_FREE_NON_NULL (StringPtr);
+ SHELL_FREE_NON_NULL (StringPtrUnknown);
+}
+
+/**
+ 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.
+
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunDp (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ LIST_ENTRY *ParamPackage;
+ CONST CHAR16 *CmdLineArg;
+ EFI_STATUS Status;
+
+ UINT64 Freq;
+ UINT64 Ticker;
+ UINTN Number2Display;
+
+ EFI_STRING StringPtr = NULL;
+ 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 ();
+
+ //
+ // initialize the shell lib (we must be in non-auto-init...)
+ //
+ Status = ShellInitialize();
+ ASSERT_EFI_ERROR(Status);
+
+ Status = CommandInit();
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // Process Command Line arguments
+ //
+ Status = ShellCommandLineParse (ParamList, &ParamPackage, NULL, TRUE);
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_INVALID_ARG), gDpHiiHandle);
+ return SHELL_INVALID_PARAMETER;
+ }
+
+ //
+ // Boolean options
+ //
+ VerboseMode = ShellCommandLineGetFlag (ParamPackage, L"-v");
+ SummaryMode = (BOOLEAN) (ShellCommandLineGetFlag (ParamPackage, L"-S") || ShellCommandLineGetFlag (ParamPackage, L"-s"));
+ AllMode = ShellCommandLineGetFlag (ParamPackage, L"-A");
+ RawMode = ShellCommandLineGetFlag (ParamPackage, L"-R");
+#if PROFILING_IMPLEMENTED
+ TraceMode = ShellCommandLineGetFlag (ParamPackage, L"-T");
+ ProfileMode = ShellCommandLineGetFlag (ParamPackage, L"-P");
+#endif // PROFILING_IMPLEMENTED
+ ExcludeMode = ShellCommandLineGetFlag (ParamPackage, L"-x");
+ mShowId = ShellCommandLineGetFlag (ParamPackage, L"-i");
+
+ // Options with Values
+ CmdLineArg = ShellCommandLineGetValue (ParamPackage, L"-n");
+ if (CmdLineArg == NULL) {
+ Number2Display = DEFAULT_DISPLAYCOUNT;
+ } else {
+ Number2Display = StrDecimalToUintn(CmdLineArg);
+ if (Number2Display == 0) {
+ Number2Display = MAXIMUM_DISPLAYCOUNT;
+ }
+ }
+
+ CmdLineArg = ShellCommandLineGetValue (ParamPackage, L"-t");
+ 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 header
+ //
+ // print DP's build version
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_BUILD_REVISION), gDpHiiHandle, DP_MAJOR_VERSION, DP_MINOR_VERSION);
+
+ // print performance timer characteristics
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_KHZ), gDpHiiHandle, TimerInfo.Frequency);
+
+ if (VerboseMode && !RawMode) {
+ StringPtr = HiiGetString (gDpHiiHandle,
+ (EFI_STRING_ID) (TimerInfo.CountUp ? STRING_TOKEN (STR_DP_UP) : STRING_TOKEN (STR_DP_DOWN)), NULL);
+ ASSERT (StringPtr != NULL);
+ // Print Timer count range and direction
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_TIMER_PROPERTIES), gDpHiiHandle,
+ StringPtr,
+ TimerInfo.StartCount,
+ TimerInfo.EndCount
+ );
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_VERBOSE_THRESHOLD), gDpHiiHandle, 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();
+ }
+
+ SHELL_FREE_NON_NULL (StringPtr);
+
+ return SHELL_SUCCESS;
+}
diff --git a/ShellPkg/Library/UefiDpLib/Dp.h b/ShellPkg/Library/UefiDpLib/Dp.h
new file mode 100644
index 0000000000..72e2c3ba18
--- /dev/null
+++ b/ShellPkg/Library/UefiDpLib/Dp.h
@@ -0,0 +1,98 @@
+/** @file
+ Common declarations for the Dp Performance Reporting Utility.
+
+ Copyright (c) 2009 - 2013, 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.
+**/
+
+#ifndef _EFI_APP_DP_H_
+#define _EFI_APP_DP_H_
+
+#include <Library/ShellLib.h>
+#include <ShellBase.h>
+
+#define DP_MAJOR_VERSION 2
+#define DP_MINOR_VERSION 4
+
+/**
+ * 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 {
+ CONST VOID *Handle;
+ CONST CHAR8 *Token; ///< Measured token string name.
+ CONST CHAR8 *Module; ///< Module string name.
+ UINT64 StartTimeStamp; ///< Start time point.
+ UINT64 EndTimeStamp; ///< End time point.
+ UINT32 Identifier; ///< Identifier.
+} 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/ShellPkg/Library/UefiDpLib/DpInternal.h b/ShellPkg/Library/UefiDpLib/DpInternal.h
new file mode 100644
index 0000000000..c7d9a592fe
--- /dev/null
+++ b/ShellPkg/Library/UefiDpLib/DpInternal.h
@@ -0,0 +1,340 @@
+/** @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 - 2013, 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.
+**/
+#ifndef _DP_INTELNAL_H_
+#define _DP_INTELNAL_H_
+
+#define DP_GAUGE_STRING_LENGTH 36
+
+//
+/// Module-Global Variables
+///@{
+extern EFI_HII_HANDLE gDpHiiHandle;
+extern CHAR16 mGaugeString[DP_GAUGE_STRING_LENGTH + 1];
+extern CHAR16 mUnicodeToken[DXE_PERFORMANCE_STRING_SIZE];
+extern UINT64 mInterestThreshold;
+extern BOOLEAN mShowId;
+
+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. 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.
+
+ @param 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
+ );
+
+/**
+ 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
+ );
+
+/**
+ 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.
+ The following methods will be tried orderly:
+ 1. Image PDB
+ 2. ComponentName2 protocol
+ 3. FFS UI section
+ 4. Image GUID
+ 5. Image DevicePath
+ 6. Unknown Driver Name
+
+ @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 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
+ );
+
+/**
+ 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
+ );
+
+/**
+ 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.<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
+ );
+
+/**
+ 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 to exclude individual Cumulative items from display.
+
+ @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:<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
+ );
+
+/**
+ 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
+ );
+
+/**
+ 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
+ );
+
+#endif
diff --git a/ShellPkg/Library/UefiDpLib/DpProfile.c b/ShellPkg/Library/UefiDpLib/DpProfile.c
new file mode 100644
index 0000000000..64583988c1
--- /dev/null
+++ b/ShellPkg/Library/UefiDpLib/DpProfile.c
@@ -0,0 +1,101 @@
+/** @file
+ Measured Profiling reporting for the Dp utility.
+
+ Copyright (c) 2009 - 2013, 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.
+**/
+
+#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;
+ EFI_STRING StringPtrUnknown;
+
+ StringPtrUnknown = HiiGetString (gDpHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL);
+ StringPtr = HiiGetString (gDpHiiHandle, STRING_TOKEN (STR_DP_SECTION_PROFILE), NULL);
+
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_SECTION_HEADER), gDpHiiHandle,
+ (StringPtr == NULL) ? StringPtrUnknown: StringPtr);
+ FreePool (StringPtr);
+ FreePool (StringPtrUnknown);
+}
+
+/**
+ 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;
+ EFI_STRING StringPtrUnknown;
+
+ StringPtrUnknown = HiiGetString (gDpHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL);
+ StringPtr = HiiGetString (gDpHiiHandle, STRING_TOKEN (STR_DP_SECTION_RAWPROFILE), NULL);
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_SECTION_HEADER), gDpHiiHandle,
+ (StringPtr == NULL) ? StringPtrUnknown: StringPtr);
+ FreePool (StringPtr);
+ FreePool (StringPtrUnknown);
+}
diff --git a/ShellPkg/Library/UefiDpLib/DpTrace.c b/ShellPkg/Library/UefiDpLib/DpTrace.c
new file mode 100644
index 0000000000..de1d45aa8b
--- /dev/null
+++ b/ShellPkg/Library/UefiDpLib/DpTrace.c
@@ -0,0 +1,828 @@
+/** @file
+ Trace reporting for the Dp utility.
+
+ Copyright (c) 2009 - 2013, 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.
+**/
+
+#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;
+ INTN TIndex;
+
+ LogEntryKey = 0;
+ while ((LogEntryKey = GetPerformanceMeasurementEx (
+ LogEntryKey,
+ &Measurement.Handle,
+ &Measurement.Token,
+ &Measurement.Module,
+ &Measurement.StartTimeStamp,
+ &Measurement.EndTimeStamp,
+ &Measurement.Identifier)) != 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;
+ CHAR16 *IncFlag;
+ UINTN LogEntryKey;
+ UINTN Count;
+ UINTN Index;
+ UINTN TIndex;
+
+ EFI_HANDLE *HandleBuffer;
+ UINTN Size;
+ EFI_HANDLE TempHandle;
+ EFI_STATUS Status;
+ EFI_STRING StringPtrUnknown;
+
+ StringPtrUnknown = HiiGetString (gDpHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL);
+ IncFlag = HiiGetString (gDpHiiHandle, STRING_TOKEN (STR_DP_SECTION_ALL), NULL);
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_SECTION_HEADER), gDpHiiHandle,
+ (IncFlag == NULL) ? StringPtrUnknown : IncFlag);
+ FreePool (StringPtrUnknown);
+
+ // Get Handle information
+ //
+ Size = 0;
+ HandleBuffer = &TempHandle;
+ Status = gBS->LocateHandle (AllHandles, NULL, NULL, &Size, &TempHandle);
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ HandleBuffer = AllocatePool (Size);
+ ASSERT (HandleBuffer != NULL);
+ if (HandleBuffer == NULL) {
+ return;
+ }
+ Status = gBS->LocateHandle (AllHandles, NULL, NULL, &Size, HandleBuffer);
+ }
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_HANDLES_ERROR), gDpHiiHandle, 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.
+ //
+ if (mShowId) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_ALL_HEADR2), gDpHiiHandle);
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_ALL_DASHES2), gDpHiiHandle);
+ } else {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_ALL_HEADR), gDpHiiHandle);
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_DASHES), gDpHiiHandle);
+ }
+
+ LogEntryKey = 0;
+ Count = 0;
+ Index = 0;
+ while ( WITHIN_LIMIT(Count, Limit) &&
+ ((LogEntryKey = GetPerformanceMeasurementEx (
+ LogEntryKey,
+ &Measurement.Handle,
+ &Measurement.Token,
+ &Measurement.Module,
+ &Measurement.StartTimeStamp,
+ &Measurement.EndTimeStamp,
+ &Measurement.Identifier)) != 0)
+ )
+ {
+ ++Index; // Count every record. First record is 1.
+ ElapsedTime = 0;
+ SHELL_FREE_NON_NULL (IncFlag);
+ if (Measurement.EndTimeStamp != 0) {
+ Duration = GetDuration (&Measurement);
+ ElapsedTime = DurationInMicroSeconds ( Duration );
+ IncFlag = HiiGetString (gDpHiiHandle, STRING_TOKEN (STR_DP_COMPLETE), NULL);
+ }
+ else {
+ IncFlag = HiiGetString (gDpHiiHandle, STRING_TOKEN (STR_DP_INCOMPLETE), NULL); // Mark incomplete records
+ }
+ if (((Measurement.EndTimeStamp != 0) && (ElapsedTime < mInterestThreshold)) ||
+ ((ExcludeFlag) && (GetCumulativeItem(&Measurement) >= 0))
+ ) { // Ignore "uninteresting" or excluded records
+ continue;
+ }
+ ++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;
+ }
+ }
+ }
+
+ if (AsciiStrnCmp (Measurement.Token, ALit_PEIM, PERF_TOKEN_LENGTH) == 0) {
+ UnicodeSPrint (mGaugeString, sizeof (mGaugeString), L"%g", Measurement.Handle);
+ }
+
+ // Ensure that the argument strings are not too long.
+ mGaugeString[DP_GAUGE_STRING_LENGTH] = 0;
+ mUnicodeToken[13] = 0;
+
+ if (mShowId) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_ALL_VARS2), gDpHiiHandle,
+ Index, // 1 based, Which measurement record is being printed
+ IncFlag,
+ Measurement.Handle,
+ mGaugeString,
+ mUnicodeToken,
+ ElapsedTime,
+ Measurement.Identifier
+ );
+ } else {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_ALL_VARS), gDpHiiHandle,
+ Index, // 1 based, Which measurement record is being printed
+ IncFlag,
+ Measurement.Handle,
+ mGaugeString,
+ mUnicodeToken,
+ ElapsedTime
+ );
+ }
+ }
+ }
+ if (HandleBuffer != &TempHandle) {
+ FreePool (HandleBuffer);
+ }
+ SHELL_FREE_NON_NULL (IncFlag);
+}
+
+/**
+ 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;
+ EFI_STRING StringPtrUnknown;
+
+ StringPtrUnknown = HiiGetString (gDpHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL);
+ StringPtr = HiiGetString (gDpHiiHandle, STRING_TOKEN (STR_DP_SECTION_RAWTRACE), NULL);
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_SECTION_HEADER), gDpHiiHandle,
+ (StringPtr == NULL) ? StringPtrUnknown : StringPtr);
+ FreePool (StringPtr);
+ FreePool (StringPtrUnknown);
+
+ if (mShowId) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_RAW_HEADR2), gDpHiiHandle);
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_RAW_DASHES2), gDpHiiHandle);
+ } else {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_RAW_HEADR), gDpHiiHandle);
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_RAW_DASHES), gDpHiiHandle);
+ }
+
+ LogEntryKey = 0;
+ Count = 0;
+ Index = 0;
+ while ( WITHIN_LIMIT(Count, Limit) &&
+ ((LogEntryKey = GetPerformanceMeasurementEx (
+ LogEntryKey,
+ &Measurement.Handle,
+ &Measurement.Token,
+ &Measurement.Module,
+ &Measurement.StartTimeStamp,
+ &Measurement.EndTimeStamp,
+ &Measurement.Identifier)) != 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
+
+ if (mShowId) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_RAW_VARS2), gDpHiiHandle,
+ Index, // 1 based, Which measurement record is being printed
+ Measurement.Handle,
+ Measurement.StartTimeStamp,
+ Measurement.EndTimeStamp,
+ Measurement.Token,
+ Measurement.Module,
+ Measurement.Identifier
+ );
+ } else {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_RAW_VARS), gDpHiiHandle,
+ 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(
+ IN UINT64 Ticker
+ )
+{
+ MEASUREMENT_RECORD Measurement;
+ UINT64 BdsTimeoutValue;
+ UINT64 SecTime;
+ UINT64 PeiTime;
+ UINT64 DxeTime;
+ UINT64 BdsTime;
+ UINT64 ShellTime;
+ UINT64 ElapsedTime;
+ UINT64 Duration;
+ UINT64 Total;
+ EFI_STRING StringPtr;
+ UINTN LogEntryKey;
+ EFI_STRING StringPtrUnknown;
+
+ BdsTimeoutValue = 0;
+ SecTime = 0;
+ PeiTime = 0;
+ DxeTime = 0;
+ BdsTime = 0;
+ ShellTime = 0;
+ //
+ // Get Execution Phase Statistics
+ //
+ StringPtrUnknown = HiiGetString (gDpHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL);
+ StringPtr = HiiGetString (gDpHiiHandle, STRING_TOKEN (STR_DP_SECTION_PHASES), NULL);
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_SECTION_HEADER), gDpHiiHandle,
+ (StringPtr == NULL) ? StringPtrUnknown : StringPtr);
+ FreePool (StringPtr);
+ FreePool (StringPtrUnknown);
+
+ LogEntryKey = 0;
+ while ((LogEntryKey = GetPerformanceMeasurementEx (
+ LogEntryKey,
+ &Measurement.Handle,
+ &Measurement.Token,
+ &Measurement.Module,
+ &Measurement.StartTimeStamp,
+ &Measurement.EndTimeStamp,
+ &Measurement.Identifier)) != 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
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_SEC_PHASE), gDpHiiHandle, ElapsedTime);
+ }
+
+ // print PEI phase duration time
+ //
+ if (PeiTime > 0) {
+ ElapsedTime = DivU64x32 (
+ PeiTime,
+ (UINT32)TimerInfo.Frequency
+ );
+ Total += ElapsedTime;
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_PHASE_DURATION), gDpHiiHandle, ALit_PEI, ElapsedTime);
+ }
+
+ // print DXE phase duration time
+ //
+ if (DxeTime > 0) {
+ ElapsedTime = DivU64x32 (
+ DxeTime,
+ (UINT32)TimerInfo.Frequency
+ );
+ Total += ElapsedTime;
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_PHASE_DURATION), gDpHiiHandle, ALit_DXE, ElapsedTime);
+ }
+
+ // print BDS phase duration time
+ //
+ if (BdsTime > 0) {
+ ElapsedTime = DivU64x32 (
+ BdsTime,
+ (UINT32)TimerInfo.Frequency
+ );
+ Total += ElapsedTime;
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_PHASE_DURATION), gDpHiiHandle, ALit_BDS, ElapsedTime);
+ }
+
+ if (BdsTimeoutValue > 0) {
+ ElapsedTime = DivU64x32 (
+ BdsTimeoutValue,
+ (UINT32)TimerInfo.Frequency
+ );
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_PHASE_BDSTO), gDpHiiHandle, ALit_BdsTO, ElapsedTime);
+ }
+
+ // print SHELL phase duration time
+ //
+ if (ShellTime > 0) {
+ ElapsedTime = DivU64x32 (
+ ShellTime,
+ (UINT32)TimerInfo.Frequency
+ );
+ Total += ElapsedTime;
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_PHASE_DURATION), gDpHiiHandle, ALit_SHELL, ElapsedTime);
+ }
+
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_TOTAL_DURATION), gDpHiiHandle, 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;
+ EFI_STRING StringPtrUnknown;
+
+ StringPtrUnknown = HiiGetString (gDpHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL);
+ StringPtr = HiiGetString (gDpHiiHandle, STRING_TOKEN (STR_DP_SECTION_DRIVERS), NULL);
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_SECTION_HEADER), gDpHiiHandle,
+ (StringPtr == NULL) ? StringPtrUnknown : StringPtr);
+ FreePool (StringPtr);
+ FreePool (StringPtrUnknown);
+
+ Size = 0;
+ HandleBuffer = &TempHandle;
+ Status = gBS->LocateHandle (AllHandles, NULL, NULL, &Size, &TempHandle);
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ HandleBuffer = AllocatePool (Size);
+ ASSERT (HandleBuffer != NULL);
+ if (HandleBuffer == NULL) {
+ return Status;
+ }
+ Status = gBS->LocateHandle (AllHandles, NULL, NULL, &Size, HandleBuffer);
+ }
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_HANDLES_ERROR), gDpHiiHandle, Status);
+ }
+ else {
+#if DP_DEBUG == 2
+ Print (L"There are %,d Handles defined.\n", (Size / sizeof(HandleBuffer[0])));
+#endif
+
+ if (mShowId) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_HANDLE_SECTION2), gDpHiiHandle);
+ } else {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_HANDLE_SECTION), gDpHiiHandle);
+ }
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_DASHES), gDpHiiHandle);
+
+ LogEntryKey = 0;
+ Count = 0;
+ while ((LogEntryKey = GetPerformanceMeasurementEx (
+ LogEntryKey,
+ &Measurement.Handle,
+ &Measurement.Token,
+ &Measurement.Module,
+ &Measurement.StartTimeStamp,
+ &Measurement.EndTimeStamp,
+ &Measurement.Identifier)) != 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[DP_GAUGE_STRING_LENGTH] = 0;
+ mUnicodeToken[11] = 0;
+ if (mGaugeString[0] != 0) {
+ // Display the record if it has a valid handle.
+ if (mShowId) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_HANDLE_VARS2), gDpHiiHandle,
+ Count, // 1 based, Which measurement record is being printed
+ Index + 1, // 1 based, Which handle is being printed
+ mGaugeString,
+ mUnicodeToken,
+ ElapsedTime,
+ Measurement.Identifier
+ );
+ } else {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_HANDLE_VARS), gDpHiiHandle,
+ Count, // 1 based, Which measurement record is being printed
+ Index + 1, // 1 based, Which handle is being printed
+ mGaugeString,
+ mUnicodeToken,
+ ElapsedTime
+ );
+ }
+ }
+ }
+ }
+ if (HandleBuffer != &TempHandle) {
+ 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;
+ EFI_STRING StringPtrUnknown;
+
+ StringPtrUnknown = HiiGetString (gDpHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL);
+ StringPtr = HiiGetString (gDpHiiHandle, STRING_TOKEN (STR_DP_SECTION_PEIMS), NULL);
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_SECTION_HEADER), gDpHiiHandle,
+ (StringPtr == NULL) ? StringPtrUnknown : StringPtr);
+ FreePool (StringPtr);
+ FreePool (StringPtrUnknown);
+
+ if (mShowId) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_PEIM_SECTION2), gDpHiiHandle);
+ } else {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_PEIM_SECTION), gDpHiiHandle);
+ }
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_DASHES), gDpHiiHandle);
+ TIndex = 0;
+ LogEntryKey = 0;
+ while ((LogEntryKey = GetPerformanceMeasurementEx (
+ LogEntryKey,
+ &Measurement.Handle,
+ &Measurement.Token,
+ &Measurement.Module,
+ &Measurement.StartTimeStamp,
+ &Measurement.EndTimeStamp,
+ &Measurement.Identifier)) != 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) {
+ // PEIM FILE Handle is the start address of its FFS file that contains its file guid.
+ if (mShowId) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_PEIM_VARS2), gDpHiiHandle,
+ TIndex, // 1 based, Which measurement record is being printed
+ Measurement.Handle, // base address
+ Measurement.Handle, // file guid
+ ElapsedTime,
+ Measurement.Identifier
+ );
+ } else {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_PEIM_VARS), gDpHiiHandle,
+ TIndex, // 1 based, Which measurement record is being printed
+ Measurement.Handle, // base address
+ Measurement.Handle, // file guid
+ 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
+ EFI_STRING StringPtrUnknown;
+
+ StringPtrUnknown = HiiGetString (gDpHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL);
+ StringPtr = HiiGetString (gDpHiiHandle, STRING_TOKEN (STR_DP_SECTION_GENERAL), NULL);
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_SECTION_HEADER), gDpHiiHandle,
+ (StringPtr == NULL) ? StringPtrUnknown: StringPtr);
+ FreePool (StringPtr);
+ FreePool (StringPtrUnknown);
+
+ if (mShowId) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_GLOBAL_SECTION2), gDpHiiHandle);
+ } else {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_GLOBAL_SECTION), gDpHiiHandle);
+ }
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_DASHES), gDpHiiHandle);
+
+ Index = 1;
+ LogEntryKey = 0;
+
+ while ((LogEntryKey = GetPerformanceMeasurementEx (
+ LogEntryKey,
+ &Measurement.Handle,
+ &Measurement.Token,
+ &Measurement.Module,
+ &Measurement.StartTimeStamp,
+ &Measurement.EndTimeStamp,
+ &Measurement.Identifier)) != 0)
+ {
+ AsciiStrToUnicodeStr (Measurement.Module, mGaugeString);
+ AsciiStrToUnicodeStr (Measurement.Token, mUnicodeToken);
+ mGaugeString[25] = 0;
+ mUnicodeToken[31] = 0;
+ if ( ! ( IsPhase( &Measurement) ||
+ (Measurement.Handle != NULL) ||
+ (Measurement.EndTimeStamp == 0)
+ ))
+ {
+ Duration = GetDuration (&Measurement);
+ ElapsedTime = DurationInMicroSeconds ( Duration );
+ if (ElapsedTime >= mInterestThreshold) {
+ if (mShowId) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_GLOBAL_VARS2), gDpHiiHandle,
+ Index,
+ mGaugeString,
+ mUnicodeToken,
+ ElapsedTime,
+ Measurement.Identifier
+ );
+ } else {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_GLOBAL_VARS), gDpHiiHandle,
+ 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 AvgDur; // the computed average duration
+ UINT64 Dur;
+ UINT64 MinDur;
+ UINT64 MaxDur;
+ EFI_STRING StringPtr;
+ UINTN TIndex;
+ EFI_STRING StringPtrUnknown;
+
+ StringPtrUnknown = HiiGetString (gDpHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL);
+ StringPtr = HiiGetString (gDpHiiHandle, STRING_TOKEN (STR_DP_SECTION_CUMULATIVE), NULL);
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_SECTION_HEADER), gDpHiiHandle,
+ (StringPtr == NULL) ? StringPtrUnknown: StringPtr);
+ FreePool (StringPtr);
+ FreePool (StringPtrUnknown);
+
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_CUMULATIVE_SECT_1), gDpHiiHandle);
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_CUMULATIVE_SECT_2), gDpHiiHandle);
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_DASHES), gDpHiiHandle);
+
+ for ( TIndex = 0; TIndex < NumCum; ++TIndex) {
+ if (CumData[TIndex].Count != 0) {
+ AvgDur = DivU64x32 (CumData[TIndex].Duration, CumData[TIndex].Count);
+ AvgDur = DurationInMicroSeconds(AvgDur);
+ Dur = DurationInMicroSeconds(CumData[TIndex].Duration);
+ MaxDur = DurationInMicroSeconds(CumData[TIndex].MaxDur);
+ MinDur = DurationInMicroSeconds(CumData[TIndex].MinDur);
+
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_CUMULATIVE_STATS), gDpHiiHandle,
+ CumData[TIndex].Name,
+ CumData[TIndex].Count,
+ Dur,
+ AvgDur,
+ MinDur,
+ MaxDur
+ );
+ }
+ }
+}
diff --git a/ShellPkg/Library/UefiDpLib/DpUtilities.c b/ShellPkg/Library/UefiDpLib/DpUtilities.c
new file mode 100644
index 0000000000..89c9919e03
--- /dev/null
+++ b/ShellPkg/Library/UefiDpLib/DpUtilities.c
@@ -0,0 +1,400 @@
+/** @file
+ Utility functions used by the Dp application.
+
+ Copyright (c) 2009 - 2013, 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.
+**/
+
+#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 <Library/UefiLib.h>
+#include <Library/DevicePathLib.h>
+
+#include <Pi/PiFirmwareFile.h>
+#include <Library/DxeServicesLib.h>
+
+#include <Protocol/LoadedImage.h>
+#include <Protocol/DriverBinding.h>
+#include <Protocol/ComponentName2.h>
+#include <Protocol/DevicePath.h>
+#include <Protocol/DevicePathToText.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.
+
+ @param 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.
+ The following methods will be tried orderly:
+ 1. Image PDB
+ 2. ComponentName2 protocol
+ 3. FFS UI section
+ 4. Image GUID
+ 5. Image DevicePath
+ 6. Unknown Driver Name
+
+ @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;
+ EFI_DEVICE_PATH_PROTOCOL *LoadedImageDevicePath;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ EFI_GUID *NameGuid;
+ CHAR16 *NameString;
+ UINTN StringSize;
+ CHAR8 *PlatformLanguage;
+ EFI_COMPONENT_NAME2_PROTOCOL *ComponentName2;
+ EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *DevicePathToText;
+
+ //
+ // Method 1: Get the name string from image PDB
+ //
+ Status = gBS->HandleProtocol (
+ Handle,
+ &gEfiLoadedImageProtocolGuid,
+ (VOID **) &Image
+ );
+
+ if (EFI_ERROR (Status)) {
+ Status = gBS->OpenProtocol (
+ Handle,
+ &gEfiDriverBindingProtocolGuid,
+ (VOID **) &DriverBinding,
+ NULL,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (!EFI_ERROR (Status)) {
+ Status = gBS->HandleProtocol (
+ DriverBinding->ImageHandle,
+ &gEfiLoadedImageProtocolGuid,
+ (VOID **) &Image
+ );
+ }
+ }
+
+ if (!EFI_ERROR (Status)) {
+ PdbFileName = PeCoffLoaderGetPdbPointer (Image->ImageBase);
+
+ if (PdbFileName != NULL) {
+ GetShortPdbFileName (PdbFileName, mGaugeString);
+ return;
+ }
+ }
+
+ //
+ // Method 2: Get the name string from ComponentName2 protocol
+ //
+ Status = gBS->HandleProtocol (
+ Handle,
+ &gEfiComponentName2ProtocolGuid,
+ (VOID **) &ComponentName2
+ );
+ if (!EFI_ERROR (Status)) {
+ //
+ // Get the current platform language setting
+ //
+ GetEfiGlobalVariable2 (L"PlatformLang", (VOID**)&PlatformLanguage, NULL);
+ Status = ComponentName2->GetDriverName (
+ ComponentName2,
+ PlatformLanguage != NULL ? PlatformLanguage : "en-US",
+ &StringPtr
+ );
+ if (!EFI_ERROR (Status)) {
+ SHELL_FREE_NON_NULL (PlatformLanguage);
+ StrnCpy (mGaugeString, StringPtr, DP_GAUGE_STRING_LENGTH);
+ mGaugeString[DP_GAUGE_STRING_LENGTH] = 0;
+ return;
+ }
+ }
+
+ Status = gBS->HandleProtocol (
+ Handle,
+ &gEfiLoadedImageDevicePathProtocolGuid,
+ (VOID **) &LoadedImageDevicePath
+ );
+ if (!EFI_ERROR (Status) && (LoadedImageDevicePath != NULL)) {
+ DevicePath = LoadedImageDevicePath;
+
+ //
+ // Try to get image GUID from LoadedImageDevicePath protocol
+ //
+ NameGuid = NULL;
+ while (!IsDevicePathEndType (DevicePath)) {
+ NameGuid = EfiGetNameGuidFromFwVolDevicePathNode ((MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) DevicePath);
+ if (NameGuid != NULL) {
+ break;
+ }
+ DevicePath = NextDevicePathNode (DevicePath);
+ }
+
+ if (NameGuid != NULL) {
+ //
+ // Try to get the image's FFS UI section by image GUID
+ //
+ NameString = NULL;
+ StringSize = 0;
+ Status = GetSectionFromAnyFv (
+ NameGuid,
+ EFI_SECTION_USER_INTERFACE,
+ 0,
+ (VOID **) &NameString,
+ &StringSize
+ );
+
+ if (!EFI_ERROR (Status)) {
+ //
+ // Method 3. Get the name string from FFS UI section
+ //
+ StrnCpy (mGaugeString, NameString, DP_GAUGE_STRING_LENGTH);
+ mGaugeString[DP_GAUGE_STRING_LENGTH] = 0;
+ FreePool (NameString);
+ } else {
+ //
+ // Method 4: Get the name string from image GUID
+ //
+ UnicodeSPrint (mGaugeString, sizeof (mGaugeString), L"%g", NameGuid);
+ }
+ return;
+ } else {
+ //
+ // Method 5: Get the name string from image DevicePath
+ //
+ Status = gBS->LocateProtocol (
+ &gEfiDevicePathToTextProtocolGuid,
+ NULL,
+ (VOID **) &DevicePathToText
+ );
+ if (!EFI_ERROR (Status)) {
+ NameString = DevicePathToText->ConvertDevicePathToText (LoadedImageDevicePath, TRUE, FALSE);
+ if (NameString != NULL) {
+ StrnCpy (mGaugeString, NameString, DP_GAUGE_STRING_LENGTH);
+ mGaugeString[DP_GAUGE_STRING_LENGTH] = 0;
+ FreePool (NameString);
+ return;
+ }
+ }
+ }
+ }
+
+ //
+ // Method 6: Unknown Driver Name
+ //
+ StringPtr = HiiGetString (gDpHiiHandle, STRING_TOKEN (STR_DP_ERROR_NAME), NULL);
+ ASSERT (StringPtr != NULL);
+ StrCpy (mGaugeString, StringPtr);
+ FreePool (StringPtr);
+}
+
+/**
+ 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);
+}
+
+/**
+ 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/ShellPkg/Library/UefiDpLib/Literals.c b/ShellPkg/Library/UefiDpLib/Literals.c
new file mode 100644
index 0000000000..68de0fbc9e
--- /dev/null
+++ b/ShellPkg/Library/UefiDpLib/Literals.c
@@ -0,0 +1,23 @@
+/** @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";
diff --git a/ShellPkg/Library/UefiDpLib/Literals.h b/ShellPkg/Library/UefiDpLib/Literals.h
new file mode 100644
index 0000000000..8aec09c024
--- /dev/null
+++ b/ShellPkg/Library/UefiDpLib/Literals.h
@@ -0,0 +1,26 @@
+/** @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[];
+
+#endif // _LITERALS_H_
diff --git a/ShellPkg/Library/UefiDpLib/UefiDpLib.c b/ShellPkg/Library/UefiDpLib/UefiDpLib.c
new file mode 100644
index 0000000000..f3ecfeac7f
--- /dev/null
+++ b/ShellPkg/Library/UefiDpLib/UefiDpLib.c
@@ -0,0 +1,101 @@
+/** @file
+ Main file for NULL named library for install1 shell command functions.
+
+ Copyright (c) 2010 - 2013, 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.
+
+**/
+
+#include "UefiDpLib.h"
+
+STATIC CONST CHAR16 mFileName[] = L"ShellCommands";
+EFI_HANDLE gDpHiiHandle = NULL;
+
+#define DP_HII_GUID \
+ { \
+ 0xeb832fd9, 0x9089, 0x4898, { 0x83, 0xc9, 0x41, 0x61, 0x8f, 0x5c, 0x48, 0xb9 } \
+ }
+
+EFI_GUID gDpHiiGuid = DP_HII_GUID;
+
+/**
+ Function to get the filename with help context if HII will not be used.
+
+ @return The filename with help text in it.
+**/
+CONST CHAR16*
+EFIAPI
+UefiDpLibGetManFileName (
+ VOID
+ )
+{
+ return (mFileName);
+}
+
+/**
+ Constructor for the Shell Level 1 Commands library.
+
+ Install the handlers for level 1 UEFI Shell 2.0 commands.
+
+ @param ImageHandle the image handle of the process
+ @param SystemTable the EFI System Table pointer
+
+ @retval EFI_SUCCESS the shell command handlers were installed sucessfully
+ @retval EFI_UNSUPPORTED the shell level required was not found.
+**/
+EFI_STATUS
+EFIAPI
+UefiDpLibConstructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ //
+ // check our bit of the profiles mask
+ //
+ if ((PcdGet8(PcdShellProfileMask) & BIT2) == 0) {
+ return (EFI_SUCCESS);
+ }
+
+ //
+ // 3rd parameter 'HII strings array' must be name of .uni strings file followed by 'Strings', e.g. mycommands.uni must be
+ // specified as 'mycommandsStrings' because the build Autogen process defines this as a string array for the strings in your
+ // .uni file. Examine your Build folder under your package's DEBUG folder and you will find it defined in a xxxStrDefs.h file.
+ //
+ gDpHiiHandle = HiiAddPackages (&gDpHiiGuid, gImageHandle, UefiDpLibStrings, NULL);
+ if (gDpHiiHandle == NULL) {
+ return (EFI_DEVICE_ERROR);
+ }
+
+ //
+ // install our shell command handlers that are always installed
+ //
+ ShellCommandRegisterCommandName(L"dp", ShellCommandRunDp , UefiDpLibGetManFileName, 0, L"", FALSE, gDpHiiHandle, STRING_TOKEN(STR_GET_HELP_DP));
+
+ return (EFI_SUCCESS);
+}
+
+/**
+ Destructor for the library. free any resources.
+
+ @param ImageHandle The image handle of the process.
+ @param SystemTable The EFI System Table pointer.
+**/
+EFI_STATUS
+EFIAPI
+UefiDpLibDestructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ if (gDpHiiHandle != NULL) {
+ HiiRemovePackages(gDpHiiHandle);
+ }
+ return (EFI_SUCCESS);
+}
diff --git a/ShellPkg/Library/UefiDpLib/UefiDpLib.h b/ShellPkg/Library/UefiDpLib/UefiDpLib.h
new file mode 100644
index 0000000000..2cec991483
--- /dev/null
+++ b/ShellPkg/Library/UefiDpLib/UefiDpLib.h
@@ -0,0 +1,60 @@
+/** @file
+ Main file for NULL named library for dp command functions.
+
+ Copyright (c) 2010 - 2013, 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 _UEFI_DP_LIB_H_
+#define _UEFI_DP_LIB_H_
+
+#include <Uefi.h>
+#include <ShellBase.h>
+
+extern EFI_GUID gDpHiiGuid;
+
+#include <Protocol/EfiShell.h>
+#include <Protocol/EfiShellParameters.h>
+#include <Protocol/DevicePath.h>
+#include <Protocol/LoadedImage.h>
+#include <Protocol/UnicodeCollation.h>
+#include <Protocol/DevicePathToText.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+#include <Library/ShellCommandLib.h>
+#include <Library/ShellLib.h>
+#include <Library/SortLib.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/HiiLib.h>
+#include <Library/FileHandleLib.h>
+
+extern EFI_HANDLE gDpHiiHandle;
+
+/**
+ Function for 'dp' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunDp (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+#endif
+
diff --git a/ShellPkg/Library/UefiDpLib/UefiDpLib.inf b/ShellPkg/Library/UefiDpLib/UefiDpLib.inf
new file mode 100644
index 0000000000..43de57dcfc
--- /dev/null
+++ b/ShellPkg/Library/UefiDpLib/UefiDpLib.inf
@@ -0,0 +1,75 @@
+## @file
+# Display Performance Application, Module information file.
+#
+# Copyright (c) 2009 - 2013, 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 = 0x00010006
+ BASE_NAME = UefiDpLib
+ FILE_GUID = 9DF262F7-CF81-4294-B5A5-B2E3CAFE5618
+ MODULE_TYPE = UEFI_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = NULL|UEFI_APPLICATION UEFI_DRIVER
+ CONSTRUCTOR = UefiDpLibConstructor
+ DESTRUCTOR = UefiDpLibDestructor
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources.common]
+ UefiDpLib.c
+ UefiDpLib.h
+ UefiDpLib.uni
+ Dp.c
+ Dp.h
+ Literals.h
+ Literals.c
+ DpInternal.h
+ DpUtilities.c
+ DpTrace.c
+ DpProfile.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ ShellPkg/ShellPkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ PerformancePkg/PerformancePkg.dec
+
+[LibraryClasses]
+ TimerLib
+ PerformanceLib
+ DxeServicesLib
+ MemoryAllocationLib
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ ShellCommandLib
+ ShellLib
+ UefiLib
+ UefiRuntimeServicesTableLib
+ UefiBootServicesTableLib
+ SortLib
+ PrintLib
+
+[Protocols]
+ gEfiLoadedImageProtocolGuid # ALWAYS_CONSUMED
+ gEfiDriverBindingProtocolGuid # SOMETIMES_CONSUMED
+ gEfiComponentName2ProtocolGuid # SOMETIMES_CONSUMED
+ gEfiLoadedImageDevicePathProtocolGuid # SOMETIMES_CONSUMED
+ gEfiDevicePathToTextProtocolGuid # SOMETIMES_CONSUMED
+
+[Pcd]
+ gEfiMdePkgTokenSpaceGuid.PcdUefiLibMaxPrintBufferSize
+ gEfiShellPkgTokenSpaceGuid.PcdShellProfileMask # ALWAYS_CONSUMED
diff --git a/ShellPkg/Library/UefiDpLib/UefiDpLib.uni b/ShellPkg/Library/UefiDpLib/UefiDpLib.uni
new file mode 100644
index 0000000000..fa29f9be4a
--- /dev/null
+++ b/ShellPkg/Library/UefiDpLib/UefiDpLib.uni
Binary files differ
diff --git a/ShellPkg/Library/UefiDpLib/readme.txt b/ShellPkg/Library/UefiDpLib/readme.txt
new file mode 100644
index 0000000000..849efa4360
--- /dev/null
+++ b/ShellPkg/Library/UefiDpLib/readme.txt
@@ -0,0 +1,2 @@
+from PerformancePkg\Dp_App
+SVN 13406