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