X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=PerformancePkg%2FDp_App%2FDp.c;h=e2cb862364abd1a738f933c675d24a921918d6e1;hp=3237138b22f6e0d6373b5bfc2116bad12d925ae1;hb=e0850230500ea2a3d74ac0ab743d144f8969e801;hpb=9dd7461870e0239ce5b1d6573a3ca0bcd86b7a03 diff --git a/PerformancePkg/Dp_App/Dp.c b/PerformancePkg/Dp_App/Dp.c index 3237138b22..e2cb862364 100644 --- a/PerformancePkg/Dp_App/Dp.c +++ b/PerformancePkg/Dp_App/Dp.c @@ -1,35 +1,37 @@ /** @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.
- * 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. + 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 - 2017, Intel Corporation. All rights reserved.
+ (C) Copyright 2015-2016 Hewlett Packard Enterprise Development LP
+ 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 +#include #include #include #include #include -#include #include +#include #include #include @@ -40,14 +42,26 @@ #include "Literals.h" #include "DpInternal.h" +// +// String token ID of help message text. +// Shell supports to find help message in the resource section of an application image if +// .MAN file is not found. This global variable is added to make build tool recognizes +// that the help string is consumed by user and then build tool will add the string into +// the resource section. Thus the application can use '-?' option to show help message in +// Shell. +// +GLOBAL_REMOVE_IF_UNREFERENCED EFI_STRING_ID mDpStrEngHelpTokenId = STRING_TOKEN (STR_DP_HELP_INFORMATION); + // /// Module-Global Variables ///@{ EFI_HII_HANDLE gHiiHandle; +SHELL_PARAM_ITEM *DpParamList = NULL; CHAR16 *mPrintTokenBuffer = NULL; -CHAR16 mGaugeString[DXE_PERFORMANCE_STRING_SIZE]; -CHAR16 mUnicodeToken[PERF_TOKEN_LENGTH + 1]; +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. @@ -65,26 +79,53 @@ PERF_CUM_DATA CumData[] = { /// 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 +PARAM_ITEM_LIST ParamList[] = { + {STRING_TOKEN (STR_DP_OPTION_QH), TypeFlag}, // -? Help + {STRING_TOKEN (STR_DP_OPTION_LH), TypeFlag}, // -h Help + {STRING_TOKEN (STR_DP_OPTION_UH), TypeFlag}, // -H Help + {STRING_TOKEN (STR_DP_OPTION_LV), TypeFlag}, // -v Verbose Mode + {STRING_TOKEN (STR_DP_OPTION_UA), TypeFlag}, // -A All, Cooked + {STRING_TOKEN (STR_DP_OPTION_UR), TypeFlag}, // -R RAW All + {STRING_TOKEN (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 + {STRING_TOKEN (STR_DP_OPTION_UP), TypeFlag}, // -P Dump Profile Data + {STRING_TOKEN (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} + {STRING_TOKEN (STR_DP_OPTION_LX), TypeFlag}, // -x eXclude Cumulative Items + {STRING_TOKEN (STR_DP_OPTION_LI), TypeFlag}, // -i Display Identifier + {STRING_TOKEN (STR_DP_OPTION_LC), TypeValue}, // -c Display cumulative data. + {STRING_TOKEN (STR_DP_OPTION_LN), TypeValue}, // -n # Number of records to display for A and R + {STRING_TOKEN (STR_DP_OPTION_LT), TypeValue} // -t # Threshold of interest }; ///@} +/** + Transfer the param list value and get the command line parse. + +**/ +VOID +InitialShellParamList( void ) +{ + UINT32 ListIndex; + UINT32 ListLength; + + // + // Allocate one more for the end tag. + // + ListLength = ARRAY_SIZE (ParamList) + 1; + DpParamList = AllocatePool (sizeof (SHELL_PARAM_ITEM) * ListLength); + ASSERT (DpParamList != NULL); + + for (ListIndex = 0; ListIndex < ListLength - 1; ListIndex ++) + { + DpParamList[ListIndex].Name = HiiGetString (gHiiHandle, ParamList[ListIndex].Token, NULL); + DpParamList[ListIndex].Type = ParamList[ListIndex].Type; + } + DpParamList[ListIndex].Name = NULL; + DpParamList[ListIndex].Type = TypeMax; +} + /** Display Usage and Help information. **/ @@ -109,6 +150,8 @@ ShowHelp( void ) #endif // PROFILING_IMPLEMENTED PrintToken (STRING_TOKEN (STR_DP_HELP_THRESHOLD)); PrintToken (STRING_TOKEN (STR_DP_HELP_COUNT)); + PrintToken (STRING_TOKEN (STR_DP_HELP_ID)); + PrintToken (STRING_TOKEN (STR_DP_HELP_CUM_DATA)); PrintToken (STRING_TOKEN (STR_DP_HELP_HELP)); Print(L"\n"); } @@ -120,10 +163,11 @@ VOID DumpStatistics( void ) { EFI_STRING StringPtr; - - StringPtr = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_SECTION_STATISTICS), NULL); + EFI_STRING StringPtrUnknown; + StringPtr = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_SECTION_STATISTICS), NULL); + StringPtrUnknown = HiiGetString (gHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL); PrintToken( STRING_TOKEN (STR_DP_SECTION_HEADER), - (StringPtr == NULL) ? ALit_UNKNOWN: StringPtr); + (StringPtr == NULL) ? StringPtrUnknown : StringPtr); PrintToken( STRING_TOKEN (STR_DP_STATS_NUMTRACE), SummaryData.NumTrace); PrintToken( STRING_TOKEN (STR_DP_STATS_NUMINCOMPLETE), SummaryData.NumIncomplete); @@ -134,18 +178,20 @@ DumpStatistics( void ) #if PROFILING_IMPLEMENTED PrintToken( STRING_TOKEN (STR_DP_STATS_NUMPROFILE), SummaryData.NumProfile); #endif // PROFILING_IMPLEMENTED + FreePool (StringPtr); + FreePool (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 EFI_ABORTED The user aborts the operation. @retval value Unknown error. - **/ EFI_STATUS EFIAPI @@ -154,23 +200,44 @@ InitializeDp ( IN EFI_SYSTEM_TABLE *SystemTable ) { - UINT64 Freq; - UINT64 Ticker; + PERFORMANCE_PROPERTY *PerformanceProperty; + UINT32 ListIndex; - LIST_ENTRY *ParamPackage; - CONST CHAR16 *CmdLineArg; - EFI_STRING StringPtr; - UINTN Number2Display; + LIST_ENTRY *ParamPackage; + CONST CHAR16 *CmdLineArg; + EFI_STRING StringPtr; + UINTN Number2Display; - EFI_STATUS Status; - BOOLEAN SummaryMode; - BOOLEAN VerboseMode; - BOOLEAN AllMode; - BOOLEAN RawMode; - BOOLEAN TraceMode; - BOOLEAN ProfileMode; - BOOLEAN ExcludeMode; + EFI_STATUS Status; + BOOLEAN SummaryMode; + BOOLEAN VerboseMode; + BOOLEAN AllMode; + BOOLEAN RawMode; + BOOLEAN TraceMode; + BOOLEAN ProfileMode; + BOOLEAN ExcludeMode; + BOOLEAN CumulativeMode; + CONST CHAR16 *CustomCumulativeToken; + PERF_CUM_DATA *CustomCumulativeData; + UINTN NameSize; + EFI_HII_PACKAGE_LIST_HEADER *PackageList; + EFI_STRING StringDpOptionQh; + EFI_STRING StringDpOptionLh; + EFI_STRING StringDpOptionUh; + EFI_STRING StringDpOptionLv; + EFI_STRING StringDpOptionUs; + EFI_STRING StringDpOptionLs; + EFI_STRING StringDpOptionUa; + EFI_STRING StringDpOptionUr; + EFI_STRING StringDpOptionUt; + EFI_STRING StringDpOptionUp; + EFI_STRING StringDpOptionLx; + EFI_STRING StringDpOptionLn; + EFI_STRING StringDpOptionLt; + EFI_STRING StringDpOptionLi; + EFI_STRING StringDpOptionLc; + SummaryMode = FALSE; VerboseMode = FALSE; AllMode = FALSE; @@ -178,16 +245,60 @@ InitializeDp ( TraceMode = FALSE; ProfileMode = FALSE; ExcludeMode = FALSE; - // Get DP's entry time as soon as possible. - // This is used as the Shell-Phase end time. + CumulativeMode = FALSE; + CustomCumulativeData = NULL; + + StringDpOptionQh = NULL; + StringDpOptionLh = NULL; + StringDpOptionUh = NULL; + StringDpOptionLv = NULL; + StringDpOptionUs = NULL; + StringDpOptionLs = NULL; + StringDpOptionUa = NULL; + StringDpOptionUr = NULL; + StringDpOptionUt = NULL; + StringDpOptionUp = NULL; + StringDpOptionLx = NULL; + StringDpOptionLn = NULL; + StringDpOptionLt = NULL; + StringDpOptionLi = NULL; + StringDpOptionLc = NULL; + StringPtr = NULL; + + // + // Retrieve HII package list from ImageHandle // - Ticker = GetPerformanceCounter (); + Status = gBS->OpenProtocol ( + ImageHandle, + &gEfiHiiPackageListProtocolGuid, + (VOID **) &PackageList, + ImageHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return Status; + } - // Register our string package with HII and return the handle to it. // - gHiiHandle = HiiAddPackages (&gEfiCallerIdGuid, ImageHandle, DPStrings, NULL); + // Publish HII package list to HII Database. + // + Status = gHiiDatabase->NewPackageList ( + gHiiDatabase, + PackageList, + NULL, + &gHiiHandle + ); + if (EFI_ERROR (Status)) { + return Status; + } ASSERT (gHiiHandle != NULL); + + // Initial the command list + // + InitialShellParamList (); + /**************************************************************************** **** Process Command Line arguments **** ****************************************************************************/ @@ -198,27 +309,47 @@ InitializeDp ( ShowHelp(); } else { - if (ShellCommandLineGetFlag (ParamPackage, STR_DP_OPTION_QH) || - ShellCommandLineGetFlag (ParamPackage, STR_DP_OPTION_LH) || - ShellCommandLineGetFlag (ParamPackage, STR_DP_OPTION_UH)) + StringDpOptionQh = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_OPTION_QH), NULL); + StringDpOptionLh = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_OPTION_LH), NULL); + StringDpOptionUh = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_OPTION_UH), NULL); + + if (ShellCommandLineGetFlag (ParamPackage, StringDpOptionQh) || + ShellCommandLineGetFlag (ParamPackage, StringDpOptionLh) || + ShellCommandLineGetFlag (ParamPackage, StringDpOptionUh)) { ShowHelp(); } else { + StringDpOptionLv = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_OPTION_LV), NULL); + StringDpOptionUs = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_OPTION_US), NULL); + StringDpOptionLs = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_OPTION_LS), NULL); + StringDpOptionUa = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_OPTION_UA), NULL); + StringDpOptionUr = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_OPTION_UR), NULL); + StringDpOptionUt = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_OPTION_UT), NULL); + StringDpOptionUp = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_OPTION_UP), NULL); + StringDpOptionLx = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_OPTION_LX), NULL); + StringDpOptionLn = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_OPTION_LN), NULL); + StringDpOptionLt = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_OPTION_LT), NULL); + StringDpOptionLi = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_OPTION_LI), NULL); + StringDpOptionLc = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_OPTION_LC), NULL); + // 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)); + // + VerboseMode = ShellCommandLineGetFlag (ParamPackage, StringDpOptionLv); + SummaryMode = (BOOLEAN) (ShellCommandLineGetFlag (ParamPackage, StringDpOptionUs) || + ShellCommandLineGetFlag (ParamPackage, StringDpOptionLs)); + AllMode = ShellCommandLineGetFlag (ParamPackage, StringDpOptionUa); + RawMode = ShellCommandLineGetFlag (ParamPackage, StringDpOptionUr); #if PROFILING_IMPLEMENTED - TraceMode = (ShellCommandLineGetFlag (ParamPackage, STR_DP_OPTION_UT)); - ProfileMode = (ShellCommandLineGetFlag (ParamPackage, STR_DP_OPTION_UP)); + TraceMode = ShellCommandLineGetFlag (ParamPackage, StringDpOptionUt); + ProfileMode = ShellCommandLineGetFlag (ParamPackage, StringDpOptionUp); #endif // PROFILING_IMPLEMENTED - ExcludeMode = (ShellCommandLineGetFlag (ParamPackage, STR_DP_OPTION_LX)); + ExcludeMode = ShellCommandLineGetFlag (ParamPackage, StringDpOptionLx); + mShowId = ShellCommandLineGetFlag (ParamPackage, StringDpOptionLi); + CumulativeMode = ShellCommandLineGetFlag (ParamPackage, StringDpOptionLc); // Options with Values - CmdLineArg = ( ShellCommandLineGetValue (ParamPackage, STR_DP_OPTION_LN)); + CmdLineArg = ShellCommandLineGetValue (ParamPackage, StringDpOptionLn); if (CmdLineArg == NULL) { Number2Display = DEFAULT_DISPLAYCOUNT; } @@ -228,7 +359,7 @@ InitializeDp ( Number2Display = MAXIMUM_DISPLAYCOUNT; } } - CmdLineArg = (ShellCommandLineGetValue (ParamPackage, STR_DP_OPTION_LT)); + CmdLineArg = ShellCommandLineGetValue (ParamPackage, StringDpOptionLt); if (CmdLineArg == NULL) { mInterestThreshold = DEFAULT_THRESHOLD; // 1ms := 1,000 us } @@ -244,6 +375,22 @@ InitializeDp ( #endif // PROFILING_IMPLEMENTED } + // + // Init the custom cumulative data. + // + CustomCumulativeToken = ShellCommandLineGetValue (ParamPackage, StringDpOptionLc); + if (CustomCumulativeToken != NULL) { + CustomCumulativeData = AllocateZeroPool (sizeof (PERF_CUM_DATA)); + ASSERT (CustomCumulativeData != NULL); + CustomCumulativeData->MinDur = 0; + CustomCumulativeData->MaxDur = 0; + CustomCumulativeData->Count = 0; + CustomCumulativeData->Duration = 0; + NameSize = StrLen (CustomCumulativeToken) + 1; + CustomCumulativeData->Name = AllocateZeroPool (NameSize); + UnicodeStrToAsciiStrS (CustomCumulativeToken, CustomCumulativeData->Name, NameSize); + } + /**************************************************************************** **** Timer specific processing **** ****************************************************************************/ @@ -252,10 +399,16 @@ InitializeDp ( // 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); + Status = EfiGetSystemConfigurationTable (&gPerformanceProtocolGuid, (VOID **) &PerformanceProperty); + if (EFI_ERROR (Status)) { + PrintToken (STRING_TOKEN (STR_PERF_PROPERTY_NOT_FOUND)); + goto Done; + } // Convert the Frequency from Hz to KHz - TimerInfo.Frequency = (UINT32)DivU64x32 (Freq, 1000); + TimerInfo.Frequency = (UINT32)DivU64x32 (PerformanceProperty->Frequency, 1000); + TimerInfo.StartCount = PerformanceProperty->TimerStartValue; + TimerInfo.EndCount = PerformanceProperty->TimerEndValue; // Determine in which direction the performance counter counts. TimerInfo.CountUp = (BOOLEAN) (TimerInfo.EndCount >= TimerInfo.StartCount); @@ -273,7 +426,7 @@ InitializeDp ( (! RawMode) ) { StringPtr = HiiGetString (gHiiHandle, - TimerInfo.CountUp ? STRING_TOKEN (STR_DP_UP) : STRING_TOKEN (STR_DP_DOWN), + (EFI_STRING_ID) (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 @@ -305,10 +458,15 @@ InitializeDp ( **** !T && P := (2) Only Profile records are displayed **** T && P := (3) Same as Default, both are displayed ****************************************************************************/ - GatherStatistics(); - if (AllMode) { + GatherStatistics (CustomCumulativeData); + if (CumulativeMode) { + ProcessCumulative (CustomCumulativeData); + } else if (AllMode) { if (TraceMode) { - DumpAllTrace( Number2Display, ExcludeMode); + Status = DumpAllTrace( Number2Display, ExcludeMode); + if (Status == EFI_ABORTED) { + goto Done; + } } if (ProfileMode) { DumpAllProfile( Number2Display, ExcludeMode); @@ -316,7 +474,10 @@ InitializeDp ( } else if (RawMode) { if (TraceMode) { - DumpRawTrace( Number2Display, ExcludeMode); + Status = DumpRawTrace( Number2Display, ExcludeMode); + if (Status == EFI_ABORTED) { + goto Done; + } } if (ProfileMode) { DumpRawProfile( Number2Display, ExcludeMode); @@ -325,14 +486,24 @@ InitializeDp ( else { //------------- Begin Cooked Mode Processing if (TraceMode) { - ProcessPhases ( Ticker ); + ProcessPhases (); if ( ! SummaryMode) { Status = ProcessHandles ( ExcludeMode); - if ( ! EFI_ERROR( Status)) { - ProcessPeims ( ); - ProcessGlobal ( ); - ProcessCumulative (); + if (Status == EFI_ABORTED) { + goto Done; } + + Status = ProcessPeims (); + if (Status == EFI_ABORTED) { + goto Done; + } + + Status = ProcessGlobal (); + if (Status == EFI_ABORTED) { + goto Done; + } + + ProcessCumulative (NULL); } } if (ProfileMode) { @@ -344,7 +515,45 @@ InitializeDp ( } } } - (void) FreePool (mPrintTokenBuffer); + +Done: + + // + // Free the memory allocate from HiiGetString + // + ListIndex = 0; + while (DpParamList[ListIndex].Name != NULL) { + FreePool (DpParamList[ListIndex].Name); + ListIndex ++; + } + FreePool (DpParamList); + + SafeFreePool (StringDpOptionQh); + SafeFreePool (StringDpOptionLh); + SafeFreePool (StringDpOptionUh); + SafeFreePool (StringDpOptionLv); + SafeFreePool (StringDpOptionUs); + SafeFreePool (StringDpOptionLs); + SafeFreePool (StringDpOptionUa); + SafeFreePool (StringDpOptionUr); + SafeFreePool (StringDpOptionUt); + SafeFreePool (StringDpOptionUp); + SafeFreePool (StringDpOptionLx); + SafeFreePool (StringDpOptionLn); + SafeFreePool (StringDpOptionLt); + SafeFreePool (StringDpOptionLi); + SafeFreePool (StringDpOptionLc); + SafeFreePool (StringPtr); + SafeFreePool (mPrintTokenBuffer); + + if (ParamPackage != NULL) { + ShellCommandLineFreeVarList (ParamPackage); + } + if (CustomCumulativeData != NULL) { + SafeFreePool (CustomCumulativeData->Name); + } + SafeFreePool (CustomCumulativeData); + HiiRemovePackages (gHiiHandle); return Status; }