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