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 //
54 GLOBAL_REMOVE_IF_UNREFERENCED EFI_STRING_ID mDpStrEngHelpTokenId = STRING_TOKEN (STR_DP_HELP_INFORMATION);
55 
56 //
57 /// Module-Global Variables
58 ///@{
59 EFI_HII_HANDLE   gHiiHandle;
60 SHELL_PARAM_ITEM *DpParamList       = NULL;
61 CHAR16           *mPrintTokenBuffer = NULL;
62 CHAR16           mGaugeString[DP_GAUGE_STRING_LENGTH + 1];
63 CHAR16           mUnicodeToken[DXE_PERFORMANCE_STRING_SIZE];
64 UINT64           mInterestThreshold;
65 BOOLEAN          mShowId = FALSE;
66 
67 PERF_SUMMARY_DATA SummaryData = { 0 };    ///< Create the SummaryData structure and init. to ZERO.
68 
69 /// Timer Specific Information.
70 TIMER_INFO TimerInfo;
71 
72 /// Items for which to gather cumulative statistics.
73 PERF_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.
81 UINT32 const      NumCum = sizeof(CumData) / sizeof(PERF_CUM_DATA);
82 
83 PARAM_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 **/
108 VOID
InitialShellParamList(void)109 InitialShellParamList( 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 **/
133 VOID
ShowHelp(void)134 ShowHelp( 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 **/
163 VOID
DumpStatistics(void)164 DumpStatistics( 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 **/
197 EFI_STATUS
198 EFIAPI
InitializeDp(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)199 InitializeDp (
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 
520 Done:
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