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