1/** @file
2  Shell application for Displaying Performance Metrics.
3
4  The Dp application reads performance data and presents it in several
5  different formats depending upon the needs of the user.  Both
6  Trace and Measured Profiling information is processed and presented.
7
8  Dp uses the "PerformanceLib" to read the measurement records.
9  The "TimerLib" provides information about the timer, such as frequency,
10  beginning, and ending counter values.
11  Measurement records contain identifying information (Handle, Token, Module)
12  and start and end time values.
13  Dp uses this information to group records in different ways.  It also uses
14  timer information to calculate elapsed time for each measurement.
15
16  Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.<BR>
17  (C) Copyright 2015-2016 Hewlett Packard Enterprise Development LP<BR>
18  This program and the accompanying materials
19  are licensed and made available under the terms and conditions of the BSD License
20  which accompanies this distribution.  The full text of the license may be found at
21  http://opensource.org/licenses/bsd-license.php
22
23  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
24  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
25**/
26
27#include <Library/UefiApplicationEntryPoint.h>
28#include <Library/UefiBootServicesTableLib.h>
29#include <Library/ShellLib.h>
30#include <Library/BaseLib.h>
31#include <Library/MemoryAllocationLib.h>
32#include <Library/DebugLib.h>
33#include <Library/TimerLib.h>
34#include <Library/UefiLib.h>
35#include <Library/UefiHiiServicesLib.h>
36#include <Library/HiiLib.h>
37#include <Library/PcdLib.h>
38
39#include <Guid/Performance.h>
40
41#include <PerformanceTokens.h>
42#include "Dp.h"
43#include "Literals.h"
44#include "DpInternal.h"
45
46//
47// String token ID of help message text.
48// Shell supports to find help message in the resource section of an application image if
49// .MAN file is not found. This global variable is added to make build tool recognizes
50// that the help string is consumed by user and then build tool will add the string into
51// the resource section. Thus the application can use '-?' option to show help message in
52// Shell.
53//
54GLOBAL_REMOVE_IF_UNREFERENCED EFI_STRING_ID mDpStrEngHelpTokenId = STRING_TOKEN (STR_DP_HELP_INFORMATION);
55
56//
57/// Module-Global Variables
58///@{
59EFI_HII_HANDLE   gHiiHandle;
60SHELL_PARAM_ITEM *DpParamList       = NULL;
61CHAR16           *mPrintTokenBuffer = NULL;
62CHAR16           mGaugeString[DP_GAUGE_STRING_LENGTH + 1];
63CHAR16           mUnicodeToken[DXE_PERFORMANCE_STRING_SIZE];
64UINT64           mInterestThreshold;
65BOOLEAN          mShowId = FALSE;
66
67PERF_SUMMARY_DATA SummaryData = { 0 };    ///< Create the SummaryData structure and init. to ZERO.
68
69/// Timer Specific Information.
70TIMER_INFO TimerInfo;
71
72/// Items for which to gather cumulative statistics.
73PERF_CUM_DATA CumData[] = {
74  PERF_INIT_CUM_DATA (LOAD_IMAGE_TOK),
75  PERF_INIT_CUM_DATA (START_IMAGE_TOK),
76  PERF_INIT_CUM_DATA (DRIVERBINDING_START_TOK),
77  PERF_INIT_CUM_DATA (DRIVERBINDING_SUPPORT_TOK)
78};
79
80/// Number of items for which we are gathering cumulative statistics.
81UINT32 const      NumCum = sizeof(CumData) / sizeof(PERF_CUM_DATA);
82
83PARAM_ITEM_LIST  ParamList[] = {
84  {STRING_TOKEN (STR_DP_OPTION_QH), TypeFlag},   // -?   Help
85  {STRING_TOKEN (STR_DP_OPTION_LH), TypeFlag},   // -h   Help
86  {STRING_TOKEN (STR_DP_OPTION_UH), TypeFlag},   // -H   Help
87  {STRING_TOKEN (STR_DP_OPTION_LV), TypeFlag},   // -v   Verbose Mode
88  {STRING_TOKEN (STR_DP_OPTION_UA), TypeFlag},   // -A   All, Cooked
89  {STRING_TOKEN (STR_DP_OPTION_UR), TypeFlag},   // -R   RAW All
90  {STRING_TOKEN (STR_DP_OPTION_LS), TypeFlag},   // -s   Summary
91#if PROFILING_IMPLEMENTED
92  {STRING_TOKEN (STR_DP_OPTION_UP), TypeFlag},   // -P   Dump Profile Data
93  {STRING_TOKEN (STR_DP_OPTION_UT), TypeFlag},   // -T   Dump Trace Data
94#endif
95  {STRING_TOKEN (STR_DP_OPTION_LX), TypeFlag},   // -x   eXclude Cumulative Items
96  {STRING_TOKEN (STR_DP_OPTION_LI), TypeFlag},   // -i   Display Identifier
97  {STRING_TOKEN (STR_DP_OPTION_LC), TypeValue},  // -c   Display cumulative data.
98  {STRING_TOKEN (STR_DP_OPTION_LN), TypeValue},  // -n # Number of records to display for A and R
99  {STRING_TOKEN (STR_DP_OPTION_LT), TypeValue}   // -t # Threshold of interest
100  };
101
102///@}
103
104/**
105  Transfer the param list value and get the command line parse.
106
107**/
108VOID
109InitialShellParamList( void )
110{
111  UINT32            ListIndex;
112  UINT32            ListLength;
113
114  //
115  // Allocate one more for the end tag.
116  //
117  ListLength = ARRAY_SIZE (ParamList) + 1;
118  DpParamList = AllocatePool (sizeof (SHELL_PARAM_ITEM) * ListLength);
119  ASSERT (DpParamList != NULL);
120
121  for (ListIndex = 0; ListIndex < ListLength - 1; ListIndex ++)
122  {
123    DpParamList[ListIndex].Name = HiiGetString (gHiiHandle, ParamList[ListIndex].Token, NULL);
124    DpParamList[ListIndex].Type = ParamList[ListIndex].Type;
125  }
126  DpParamList[ListIndex].Name = NULL;
127  DpParamList[ListIndex].Type = TypeMax;
128}
129
130/**
131   Display Usage and Help information.
132**/
133VOID
134ShowHelp( void )
135{
136  PrintToken (STRING_TOKEN (STR_DP_HELP_HEAD));
137#if PROFILING_IMPLEMENTED
138  PrintToken (STRING_TOKEN (STR_DP_HELP_FLAGS));
139#else
140  PrintToken (STRING_TOKEN (STR_DP_HELP_FLAGS_2));
141#endif // PROFILING_IMPLEMENTED
142  PrintToken (STRING_TOKEN (STR_DP_HELP_PAGINATE));
143  PrintToken (STRING_TOKEN (STR_DP_HELP_VERBOSE));
144  PrintToken (STRING_TOKEN (STR_DP_HELP_EXCLUDE));
145  PrintToken (STRING_TOKEN (STR_DP_HELP_STAT));
146  PrintToken (STRING_TOKEN (STR_DP_HELP_ALL));
147  PrintToken (STRING_TOKEN (STR_DP_HELP_RAW));
148#if PROFILING_IMPLEMENTED
149  PrintToken (STRING_TOKEN (STR_DP_HELP_TRACE));
150  PrintToken (STRING_TOKEN (STR_DP_HELP_PROFILE));
151#endif // PROFILING_IMPLEMENTED
152  PrintToken (STRING_TOKEN (STR_DP_HELP_THRESHOLD));
153  PrintToken (STRING_TOKEN (STR_DP_HELP_COUNT));
154  PrintToken (STRING_TOKEN (STR_DP_HELP_ID));
155  PrintToken (STRING_TOKEN (STR_DP_HELP_CUM_DATA));
156  PrintToken (STRING_TOKEN (STR_DP_HELP_HELP));
157  Print(L"\n");
158}
159
160/**
161   Display the trailing Verbose information.
162**/
163VOID
164DumpStatistics( void )
165{
166  EFI_STRING                StringPtr;
167  EFI_STRING                StringPtrUnknown;
168  StringPtr        = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_SECTION_STATISTICS), NULL);
169  StringPtrUnknown = HiiGetString (gHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL);
170  PrintToken( STRING_TOKEN (STR_DP_SECTION_HEADER),
171              (StringPtr == NULL) ? StringPtrUnknown : StringPtr);
172
173  PrintToken( STRING_TOKEN (STR_DP_STATS_NUMTRACE),       SummaryData.NumTrace);
174  PrintToken( STRING_TOKEN (STR_DP_STATS_NUMINCOMPLETE),  SummaryData.NumIncomplete);
175  PrintToken( STRING_TOKEN (STR_DP_STATS_NUMPHASES),      SummaryData.NumSummary);
176  PrintToken( STRING_TOKEN (STR_DP_STATS_NUMHANDLES),     SummaryData.NumHandles, SummaryData.NumTrace - SummaryData.NumHandles);
177  PrintToken( STRING_TOKEN (STR_DP_STATS_NUMPEIMS),       SummaryData.NumPEIMs);
178  PrintToken( STRING_TOKEN (STR_DP_STATS_NUMGLOBALS),     SummaryData.NumGlobal);
179#if PROFILING_IMPLEMENTED
180  PrintToken( STRING_TOKEN (STR_DP_STATS_NUMPROFILE),     SummaryData.NumProfile);
181#endif // PROFILING_IMPLEMENTED
182  FreePool (StringPtr);
183  FreePool (StringPtrUnknown);
184}
185
186/**
187  Dump performance data.
188
189  @param[in]  ImageHandle     The image handle.
190  @param[in]  SystemTable     The system table.
191
192  @retval EFI_SUCCESS            Command completed successfully.
193  @retval EFI_INVALID_PARAMETER  Command usage error.
194  @retval EFI_ABORTED            The user aborts the operation.
195  @retval value                  Unknown error.
196**/
197EFI_STATUS
198EFIAPI
199InitializeDp (
200  IN EFI_HANDLE               ImageHandle,
201  IN EFI_SYSTEM_TABLE         *SystemTable
202  )
203{
204  UINT64                    Freq;
205  UINT64                    Ticker;
206  UINT32                    ListIndex;
207
208  LIST_ENTRY                *ParamPackage;
209  CONST CHAR16              *CmdLineArg;
210  EFI_STRING                StringPtr;
211  UINTN                     Number2Display;
212
213  EFI_STATUS                    Status;
214  BOOLEAN                       SummaryMode;
215  BOOLEAN                       VerboseMode;
216  BOOLEAN                       AllMode;
217  BOOLEAN                       RawMode;
218  BOOLEAN                       TraceMode;
219  BOOLEAN                       ProfileMode;
220  BOOLEAN                       ExcludeMode;
221  BOOLEAN                       CumulativeMode;
222  CONST CHAR16                  *CustomCumulativeToken;
223  PERF_CUM_DATA                 *CustomCumulativeData;
224  UINTN                         NameSize;
225  EFI_HII_PACKAGE_LIST_HEADER   *PackageList;
226
227  EFI_STRING                StringDpOptionQh;
228  EFI_STRING                StringDpOptionLh;
229  EFI_STRING                StringDpOptionUh;
230  EFI_STRING                StringDpOptionLv;
231  EFI_STRING                StringDpOptionUs;
232  EFI_STRING                StringDpOptionLs;
233  EFI_STRING                StringDpOptionUa;
234  EFI_STRING                StringDpOptionUr;
235  EFI_STRING                StringDpOptionUt;
236  EFI_STRING                StringDpOptionUp;
237  EFI_STRING                StringDpOptionLx;
238  EFI_STRING                StringDpOptionLn;
239  EFI_STRING                StringDpOptionLt;
240  EFI_STRING                StringDpOptionLi;
241  EFI_STRING                StringDpOptionLc;
242
243  SummaryMode     = FALSE;
244  VerboseMode     = FALSE;
245  AllMode         = FALSE;
246  RawMode         = FALSE;
247  TraceMode       = FALSE;
248  ProfileMode     = FALSE;
249  ExcludeMode     = FALSE;
250  CumulativeMode = FALSE;
251  CustomCumulativeData = NULL;
252
253  StringDpOptionQh = NULL;
254  StringDpOptionLh = NULL;
255  StringDpOptionUh = NULL;
256  StringDpOptionLv = NULL;
257  StringDpOptionUs = NULL;
258  StringDpOptionLs = NULL;
259  StringDpOptionUa = NULL;
260  StringDpOptionUr = NULL;
261  StringDpOptionUt = NULL;
262  StringDpOptionUp = NULL;
263  StringDpOptionLx = NULL;
264  StringDpOptionLn = NULL;
265  StringDpOptionLt = NULL;
266  StringDpOptionLi = NULL;
267  StringDpOptionLc = NULL;
268  StringPtr        = NULL;
269
270  // Get DP's entry time as soon as possible.
271  // This is used as the Shell-Phase end time.
272  //
273  Ticker  = GetPerformanceCounter ();
274
275  //
276  // Retrieve HII package list from ImageHandle
277  //
278  Status = gBS->OpenProtocol (
279                  ImageHandle,
280                  &gEfiHiiPackageListProtocolGuid,
281                  (VOID **) &PackageList,
282                  ImageHandle,
283                  NULL,
284                  EFI_OPEN_PROTOCOL_GET_PROTOCOL
285                  );
286  if (EFI_ERROR (Status)) {
287    return Status;
288  }
289
290  //
291  // Publish HII package list to HII Database.
292  //
293  Status = gHiiDatabase->NewPackageList (
294                          gHiiDatabase,
295                          PackageList,
296                          NULL,
297                          &gHiiHandle
298                          );
299  if (EFI_ERROR (Status)) {
300    return Status;
301  }
302  ASSERT (gHiiHandle != NULL);
303
304
305  // Initial the command list
306  //
307  InitialShellParamList ();
308
309/****************************************************************************
310****            Process Command Line arguments                           ****
311****************************************************************************/
312  Status = ShellCommandLineParse (DpParamList, &ParamPackage, NULL, TRUE);
313
314  if (EFI_ERROR(Status)) {
315    PrintToken (STRING_TOKEN (STR_DP_INVALID_ARG));
316    ShowHelp();
317  }
318  else {
319    StringDpOptionQh = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_OPTION_QH), NULL);
320    StringDpOptionLh = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_OPTION_LH), NULL);
321    StringDpOptionUh = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_OPTION_UH), NULL);
322
323    if (ShellCommandLineGetFlag (ParamPackage, StringDpOptionQh)  ||
324        ShellCommandLineGetFlag (ParamPackage, StringDpOptionLh)  ||
325        ShellCommandLineGetFlag (ParamPackage, StringDpOptionUh))
326    {
327      ShowHelp();
328    }
329    else {
330      StringDpOptionLv = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_OPTION_LV), NULL);
331      StringDpOptionUs = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_OPTION_US), NULL);
332      StringDpOptionLs = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_OPTION_LS), NULL);
333      StringDpOptionUa = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_OPTION_UA), NULL);
334      StringDpOptionUr = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_OPTION_UR), NULL);
335      StringDpOptionUt = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_OPTION_UT), NULL);
336      StringDpOptionUp = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_OPTION_UP), NULL);
337      StringDpOptionLx = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_OPTION_LX), NULL);
338      StringDpOptionLn = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_OPTION_LN), NULL);
339      StringDpOptionLt = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_OPTION_LT), NULL);
340      StringDpOptionLi = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_OPTION_LI), NULL);
341      StringDpOptionLc = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_OPTION_LC), NULL);
342
343      // Boolean Options
344      //
345      VerboseMode = ShellCommandLineGetFlag (ParamPackage, StringDpOptionLv);
346      SummaryMode = (BOOLEAN) (ShellCommandLineGetFlag (ParamPackage, StringDpOptionUs) ||
347                    ShellCommandLineGetFlag (ParamPackage, StringDpOptionLs));
348      AllMode     = ShellCommandLineGetFlag (ParamPackage, StringDpOptionUa);
349      RawMode     = ShellCommandLineGetFlag (ParamPackage, StringDpOptionUr);
350#if PROFILING_IMPLEMENTED
351      TraceMode   = ShellCommandLineGetFlag (ParamPackage, StringDpOptionUt);
352      ProfileMode = ShellCommandLineGetFlag (ParamPackage, StringDpOptionUp);
353#endif  // PROFILING_IMPLEMENTED
354      ExcludeMode = ShellCommandLineGetFlag (ParamPackage, StringDpOptionLx);
355      mShowId     =  ShellCommandLineGetFlag (ParamPackage, StringDpOptionLi);
356      CumulativeMode = ShellCommandLineGetFlag (ParamPackage, StringDpOptionLc);
357
358      // Options with Values
359      CmdLineArg  = ShellCommandLineGetValue (ParamPackage, StringDpOptionLn);
360      if (CmdLineArg == NULL) {
361        Number2Display = DEFAULT_DISPLAYCOUNT;
362      }
363      else {
364        Number2Display = StrDecimalToUintn(CmdLineArg);
365        if (Number2Display == 0) {
366          Number2Display = MAXIMUM_DISPLAYCOUNT;
367        }
368      }
369      CmdLineArg  = ShellCommandLineGetValue (ParamPackage, StringDpOptionLt);
370      if (CmdLineArg == NULL) {
371        mInterestThreshold = DEFAULT_THRESHOLD;  // 1ms := 1,000 us
372      }
373      else {
374        mInterestThreshold = StrDecimalToUint64(CmdLineArg);
375      }
376      // Handle Flag combinations and default behaviors
377      // If both TraceMode and ProfileMode are FALSE, set them both to TRUE
378      if ((! TraceMode) && (! ProfileMode)) {
379        TraceMode   = TRUE;
380#if PROFILING_IMPLEMENTED
381        ProfileMode = TRUE;
382#endif  // PROFILING_IMPLEMENTED
383      }
384
385  //
386  // Init the custom cumulative data.
387  //
388  CustomCumulativeToken = ShellCommandLineGetValue (ParamPackage, StringDpOptionLc);
389  if (CustomCumulativeToken != NULL) {
390    CustomCumulativeData = AllocateZeroPool (sizeof (PERF_CUM_DATA));
391    ASSERT (CustomCumulativeData != NULL);
392    CustomCumulativeData->MinDur = 0;
393    CustomCumulativeData->MaxDur = 0;
394    CustomCumulativeData->Count  = 0;
395    CustomCumulativeData->Duration = 0;
396    NameSize = StrLen (CustomCumulativeToken) + 1;
397    CustomCumulativeData->Name   = AllocateZeroPool (NameSize);
398    UnicodeStrToAsciiStrS (CustomCumulativeToken, CustomCumulativeData->Name, NameSize);
399  }
400
401/****************************************************************************
402****            Timer specific processing                                ****
403****************************************************************************/
404      // Get the Performance counter characteristics:
405      //          Freq = Frequency in Hz
406      //    StartCount = Value loaded into the counter when it starts counting
407      //      EndCount = Value counter counts to before it needs to be reset
408      //
409      Freq = GetPerformanceCounterProperties (&TimerInfo.StartCount, &TimerInfo.EndCount);
410
411      // Convert the Frequency from Hz to KHz
412      TimerInfo.Frequency = (UINT32)DivU64x32 (Freq, 1000);
413
414      // Determine in which direction the performance counter counts.
415      TimerInfo.CountUp = (BOOLEAN) (TimerInfo.EndCount >= TimerInfo.StartCount);
416
417/****************************************************************************
418****            Print heading                                            ****
419****************************************************************************/
420      // print DP's build version
421      PrintToken (STRING_TOKEN (STR_DP_BUILD_REVISION), DP_MAJOR_VERSION, DP_MINOR_VERSION);
422
423      // print performance timer characteristics
424      PrintToken (STRING_TOKEN (STR_DP_KHZ), TimerInfo.Frequency);         // Print Timer frequency in KHz
425
426      if ((VerboseMode)   &&
427          (! RawMode)
428         ) {
429        StringPtr = HiiGetString (gHiiHandle,
430                      (EFI_STRING_ID) (TimerInfo.CountUp ? STRING_TOKEN (STR_DP_UP) : STRING_TOKEN (STR_DP_DOWN)),
431                      NULL);
432        ASSERT (StringPtr != NULL);
433        PrintToken (STRING_TOKEN (STR_DP_TIMER_PROPERTIES),   // Print Timer count range and direction
434                    StringPtr,
435                    TimerInfo.StartCount,
436                    TimerInfo.EndCount
437                    );
438        PrintToken (STRING_TOKEN (STR_DP_VERBOSE_THRESHOLD), mInterestThreshold);
439      }
440
441/* **************************************************************************
442****            Print Sections based on command line options
443****
444****  Option modes have the following priority:
445****    v Verbose     --  Valid in combination with any other options
446****    t Threshold   --  Modifies All, Raw, and Cooked output
447****                      Default is 0 for All and Raw mode
448****                      Default is DEFAULT_THRESHOLD for "Cooked" mode
449****    n Number2Display  Used by All and Raw mode.  Otherwise ignored.
450****    A All         --  R and S options are ignored
451****    R Raw         --  S option is ignored
452****    s Summary     --  Modifies "Cooked" output only
453****    Cooked (Default)
454****
455****  The All, Raw, and Cooked modes are modified by the Trace and Profile
456****  options.
457****    !T && !P  := (0) Default, Both are displayed
458****     T && !P  := (1) Only Trace records are displayed
459****    !T &&  P  := (2) Only Profile records are displayed
460****     T &&  P  := (3) Same as Default, both are displayed
461****************************************************************************/
462      GatherStatistics (CustomCumulativeData);
463      if (CumulativeMode) {
464        ProcessCumulative (CustomCumulativeData);
465      } else if (AllMode) {
466        if (TraceMode) {
467          Status = DumpAllTrace( Number2Display, ExcludeMode);
468          if (Status == EFI_ABORTED) {
469            goto Done;
470          }
471        }
472        if (ProfileMode) {
473          DumpAllProfile( Number2Display, ExcludeMode);
474        }
475      }
476      else if (RawMode) {
477        if (TraceMode) {
478          Status = DumpRawTrace( Number2Display, ExcludeMode);
479          if (Status == EFI_ABORTED) {
480            goto Done;
481          }
482        }
483        if (ProfileMode) {
484          DumpRawProfile( Number2Display, ExcludeMode);
485        }
486      }
487      else {
488        //------------- Begin Cooked Mode Processing
489        if (TraceMode) {
490          ProcessPhases ( Ticker );
491          if ( ! SummaryMode) {
492            Status = ProcessHandles ( ExcludeMode);
493            if (Status == EFI_ABORTED) {
494              goto Done;
495            }
496
497            Status = ProcessPeims ();
498            if (Status == EFI_ABORTED) {
499              goto Done;
500            }
501
502            Status = ProcessGlobal ();
503            if (Status == EFI_ABORTED) {
504              goto Done;
505            }
506
507            ProcessCumulative (NULL);
508          }
509        }
510        if (ProfileMode) {
511          DumpAllProfile( Number2Display, ExcludeMode);
512        }
513      } //------------- End of Cooked Mode Processing
514      if ( VerboseMode || SummaryMode) {
515        DumpStatistics();
516      }
517    }
518  }
519
520Done:
521
522  //
523  // Free the memory allocate from HiiGetString
524  //
525  ListIndex = 0;
526  while (DpParamList[ListIndex].Name != NULL) {
527    FreePool (DpParamList[ListIndex].Name);
528    ListIndex ++;
529  }
530  FreePool (DpParamList);
531
532  SafeFreePool (StringDpOptionQh);
533  SafeFreePool (StringDpOptionLh);
534  SafeFreePool (StringDpOptionUh);
535  SafeFreePool (StringDpOptionLv);
536  SafeFreePool (StringDpOptionUs);
537  SafeFreePool (StringDpOptionLs);
538  SafeFreePool (StringDpOptionUa);
539  SafeFreePool (StringDpOptionUr);
540  SafeFreePool (StringDpOptionUt);
541  SafeFreePool (StringDpOptionUp);
542  SafeFreePool (StringDpOptionLx);
543  SafeFreePool (StringDpOptionLn);
544  SafeFreePool (StringDpOptionLt);
545  SafeFreePool (StringDpOptionLi);
546  SafeFreePool (StringDpOptionLc);
547  SafeFreePool (StringPtr);
548  SafeFreePool (mPrintTokenBuffer);
549
550  if (ParamPackage != NULL) {
551    ShellCommandLineFreeVarList (ParamPackage);
552  }
553  if (CustomCumulativeData != NULL) {
554    SafeFreePool (CustomCumulativeData->Name);
555  }
556  SafeFreePool (CustomCumulativeData);
557
558  HiiRemovePackages (gHiiHandle);
559  return Status;
560}
561