]> git.proxmox.com Git - mirror_edk2.git/blame - ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiView.c
ShellPkg/UefiShellAcpiViewCommandLib: Fix ECC issues
[mirror_edk2.git] / ShellPkg / Library / UefiShellAcpiViewCommandLib / AcpiView.c
CommitLineData
a6eaba4d 1/** @file\r
ee4dc24f
RN
2\r
3 Copyright (c) 2016 - 2018, ARM Limited. All rights reserved.\r
4 This program and the accompanying materials\r
5 are licensed and made available under the terms and conditions of the BSD License\r
6 which accompanies this distribution. The full text of the license may be found at\r
7 http://opensource.org/licenses/bsd-license.php\r
8\r
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
11**/\r
12\r
13#include <Library/PrintLib.h>\r
14#include <Library/UefiLib.h>\r
15#include <Library/ShellLib.h>\r
16#include <Library/UefiBootServicesTableLib.h>\r
17#include <Library/BaseMemoryLib.h>\r
18#include <Library/DebugLib.h>\r
19#include <Library/MemoryAllocationLib.h>\r
20#include "AcpiParser.h"\r
21#include "AcpiTableParser.h"\r
22#include "AcpiView.h"\r
23#include "UefiShellAcpiViewCommandLib.h"\r
24\r
25EFI_HII_HANDLE gShellAcpiViewHiiHandle = NULL;\r
26\r
27// Report variables\r
28STATIC UINT32 mSelectedAcpiTable;\r
29STATIC CONST CHAR16* mSelectedAcpiTableName;\r
30STATIC BOOLEAN mSelectedAcpiTableFound;\r
31STATIC EREPORT_OPTION mReportType;\r
32STATIC UINT32 mTableCount;\r
33STATIC UINT32 mBinTableCount;\r
34STATIC BOOLEAN mVerbose;\r
35STATIC BOOLEAN mConsistencyCheck;\r
36STATIC BOOLEAN mColourHighlighting;\r
37\r
a6eaba4d
DB
38/**\r
39 An array of acpiview command line parameters.\r
40**/\r
ee4dc24f
RN
41STATIC CONST SHELL_PARAM_ITEM ParamList[] = {\r
42 {L"/?", TypeFlag},\r
43 {L"-c", TypeFlag},\r
44 {L"-d", TypeFlag},\r
45 {L"-h", TypeValue},\r
46 {L"-l", TypeFlag},\r
47 {L"-s", TypeValue},\r
48 {L"-v", TypeFlag},\r
49 {NULL, TypeMax}\r
50};\r
51\r
a6eaba4d
DB
52/**\r
53 This function returns the colour highlighting status.\r
ee4dc24f
RN
54\r
55 @retval TRUE if colour highlighting is enabled.\r
a6eaba4d 56**/\r
ee4dc24f
RN
57BOOLEAN\r
58GetColourHighlighting (\r
59 VOID\r
60 )\r
61{\r
62 return mColourHighlighting;\r
63}\r
64\r
a6eaba4d
DB
65/**\r
66 This function sets the colour highlighting status.\r
ee4dc24f 67\r
a6eaba4d
DB
68 @param Highlight The Highlight status.\r
69\r
70**/\r
ee4dc24f
RN
71VOID\r
72SetColourHighlighting (\r
73 BOOLEAN Highlight\r
74 )\r
75{\r
76 mColourHighlighting = Highlight;\r
77}\r
78\r
a6eaba4d
DB
79/**\r
80 This function returns the report options.\r
ee4dc24f
RN
81\r
82 @retval Returns the report option.\r
a6eaba4d 83**/\r
ee4dc24f
RN
84STATIC\r
85EREPORT_OPTION\r
86GetReportOption (\r
87 VOID\r
88 )\r
89{\r
90 return mReportType;\r
91}\r
92\r
a6eaba4d
DB
93/**\r
94 This function returns the selected ACPI table.\r
ee4dc24f
RN
95\r
96 @retval Returns signature of the selected ACPI table.\r
a6eaba4d 97**/\r
ee4dc24f
RN
98STATIC\r
99UINT32\r
100GetSelectedAcpiTable (\r
101 VOID\r
102 )\r
103{\r
104 return mSelectedAcpiTable;\r
105}\r
106\r
a6eaba4d
DB
107/**\r
108 This function dumps the ACPI table to a file.\r
109\r
ee4dc24f
RN
110 @param [in] Ptr Pointer to the ACPI table data.\r
111 @param [in] Length The length of the ACPI table.\r
112\r
113 @retval TRUE Success.\r
114 @retval FALSE Failure.\r
a6eaba4d 115**/\r
ee4dc24f
RN
116STATIC\r
117BOOLEAN\r
118DumpAcpiTableToFile (\r
119 IN CONST UINT8* Ptr,\r
120 IN CONST UINTN Length\r
121 )\r
122{\r
123 EFI_STATUS Status;\r
124 CHAR16 FileNameBuffer[MAX_FILE_NAME_LEN];\r
125 SHELL_FILE_HANDLE DumpFileHandle = NULL;\r
126 UINTN TransferBytes = Length;\r
127\r
128 UnicodeSPrint (\r
129 FileNameBuffer,\r
130 sizeof (FileNameBuffer),\r
131 L".\\%s%04d.bin",\r
132 mSelectedAcpiTableName,\r
133 mBinTableCount++\r
134 );\r
135\r
136 Status = ShellOpenFileByName (\r
137 FileNameBuffer,\r
138 &DumpFileHandle,\r
139 EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE,\r
140 0\r
141 );\r
142 if (EFI_ERROR (Status)) {\r
143 ShellPrintHiiEx (\r
144 -1,\r
145 -1,\r
146 NULL,\r
147 STRING_TOKEN (STR_GEN_READONLY_MEDIA),\r
148 gShellAcpiViewHiiHandle,\r
149 L"acpiview"\r
150 );\r
151 return FALSE;\r
152 }\r
153\r
154 Print (L"Dumping ACPI table to : %s ... ", FileNameBuffer);\r
155\r
156 Status = ShellWriteFile (\r
157 DumpFileHandle,\r
158 &TransferBytes,\r
159 (VOID*)Ptr\r
160 );\r
161 if (EFI_ERROR (Status)) {\r
162 Print (L"ERROR: Failed to dump table to binary file.\n");\r
163 TransferBytes = 0;\r
164 } else {\r
165 Print (L"DONE.\n");\r
166 }\r
167\r
168 ShellCloseFile (&DumpFileHandle);\r
169 return (Length == TransferBytes);\r
170}\r
171\r
a6eaba4d
DB
172/**\r
173 This function processes the table reporting options for the ACPI table.\r
ee4dc24f
RN
174\r
175 @param [in] Signature The ACPI table Signature.\r
176 @param [in] TablePtr Pointer to the ACPI table data.\r
177 @param [in] Length The length fo the ACPI table.\r
178\r
179 @retval Returns TRUE if the ACPI table should be traced.\r
a6eaba4d 180**/\r
ee4dc24f
RN
181BOOLEAN\r
182ProcessTableReportOptions (\r
183 IN CONST UINT32 Signature,\r
184 IN CONST UINT8* TablePtr,\r
185 IN CONST UINT32 Length\r
186 )\r
187{\r
188 UINTN OriginalAttribute;\r
189 UINT8* SignaturePtr = (UINT8*)(UINTN)&Signature;\r
190 BOOLEAN Log = FALSE;\r
191 BOOLEAN HighLight = GetColourHighlighting ();\r
192 switch (GetReportOption ()) {\r
193 case EREPORT_ALL:\r
194 Log = TRUE;\r
195 break;\r
196 case EREPORT_SELECTED:\r
197 if (Signature == GetSelectedAcpiTable ()) {\r
198 Log = TRUE;\r
199 mSelectedAcpiTableFound = TRUE;\r
200 }\r
201 break;\r
202 case EREPORT_TABLE_LIST:\r
203 if (mTableCount == 0) {\r
204 if (HighLight) {\r
205 OriginalAttribute = gST->ConOut->Mode->Attribute;\r
206 gST->ConOut->SetAttribute (\r
207 gST->ConOut,\r
208 EFI_TEXT_ATTR(EFI_CYAN,\r
209 ((OriginalAttribute&(BIT4|BIT5|BIT6))>>4))\r
210 );\r
211 }\r
212 Print (L"\nInstalled Table(s):\n");\r
213 if (HighLight) {\r
214 gST->ConOut->SetAttribute (gST->ConOut, OriginalAttribute);\r
215 }\r
216 }\r
217 Print (\r
218 L"\t%4d. %c%c%c%c\n",\r
219 ++mTableCount,\r
220 SignaturePtr[0],\r
221 SignaturePtr[1],\r
222 SignaturePtr[2],\r
223 SignaturePtr[3]\r
224 );\r
225 break;\r
226 case EREPORT_DUMP_BIN_FILE:\r
227 if (Signature == GetSelectedAcpiTable ()) {\r
228 mSelectedAcpiTableFound = TRUE;\r
229 DumpAcpiTableToFile (TablePtr, Length);\r
230 }\r
231 break;\r
232 case EREPORT_MAX:\r
233 // We should never be here.\r
234 // This case is only present to prevent compiler warning.\r
235 break;\r
236 } // switch\r
237\r
238 if (Log) {\r
239 if (HighLight) {\r
240 OriginalAttribute = gST->ConOut->Mode->Attribute;\r
241 gST->ConOut->SetAttribute (\r
242 gST->ConOut,\r
243 EFI_TEXT_ATTR(EFI_LIGHTBLUE,\r
244 ((OriginalAttribute&(BIT4|BIT5|BIT6))>>4))\r
245 );\r
246 }\r
247 Print (\r
248 L"\n\n --------------- %c%c%c%c Table --------------- \n\n",\r
249 SignaturePtr[0],\r
250 SignaturePtr[1],\r
251 SignaturePtr[2],\r
252 SignaturePtr[3]\r
253 );\r
254 if (HighLight) {\r
255 gST->ConOut->SetAttribute (gST->ConOut, OriginalAttribute);\r
256 }\r
257 }\r
258\r
259 return Log;\r
260}\r
261\r
a6eaba4d
DB
262/**\r
263 This function converts a string to ACPI table signature.\r
ee4dc24f
RN
264\r
265 @param [in] Str Pointer to the string to be converted to the\r
266 ACPI table signature.\r
267\r
268 @retval The ACPI table signature.\r
a6eaba4d 269**/\r
ee4dc24f
RN
270STATIC\r
271UINT32\r
272ConvertStrToAcpiSignature (\r
273 IN CONST CHAR16* Str\r
274 )\r
275{\r
276 UINT8 Index = 0;\r
277 CHAR8 Ptr[4];\r
278\r
279 // Convert to Upper case and convert to ASCII\r
280 while ((Index < 4) && (Str[Index] != 0)) {\r
281 if (Str[Index] >= L'a' && Str[Index] <= L'z') {\r
282 Ptr[Index] = (CHAR8)(Str[Index] - (L'a' - L'A'));\r
283 } else {\r
284 Ptr[Index] = (CHAR8)Str[Index];\r
285 }\r
286 Index++;\r
287 }\r
288 return *(UINT32*)Ptr;\r
289}\r
290\r
a6eaba4d
DB
291/**\r
292 This function iterates the configuration table entries in the\r
293 system table, retrieves the RSDP pointer and starts parsing the ACPI tables.\r
ee4dc24f
RN
294\r
295 @param [in] SystemTable Pointer to the EFI system table.\r
296\r
297 @retval Returns EFI_NOT_FOUND if the RSDP pointer is not found.\r
298 Returns EFI_UNSUPPORTED if the RSDP version is less than 2.\r
299 Returns EFI_SUCCESS if successful.\r
a6eaba4d 300**/\r
ee4dc24f
RN
301STATIC\r
302EFI_STATUS\r
303EFIAPI\r
304AcpiView (\r
305 IN EFI_SYSTEM_TABLE* SystemTable\r
306 )\r
307{\r
308 EFI_STATUS Status;\r
309 UINTN Index;\r
310 EFI_CONFIGURATION_TABLE* EfiConfigurationTable;\r
311 BOOLEAN FoundAcpiTable;\r
312 UINTN OriginalAttribute;\r
313 UINTN PrintAttribute;\r
314 EREPORT_OPTION ReportOption;\r
315 UINT8* RsdpPtr;\r
316 UINT32 RsdpLength;\r
317 UINT8 RsdpRevision;\r
318 PARSE_ACPI_TABLE_PROC RsdpParserProc;\r
319 BOOLEAN Trace;\r
320\r
321 // Search the table for an entry that matches the ACPI Table Guid\r
322 FoundAcpiTable = FALSE;\r
323 for (Index = 0; Index < SystemTable->NumberOfTableEntries; Index++) {\r
324 if (CompareGuid (&gEfiAcpiTableGuid,\r
325 &(SystemTable->ConfigurationTable[Index].VendorGuid))) {\r
326 EfiConfigurationTable = &SystemTable->ConfigurationTable[Index];\r
327 FoundAcpiTable = TRUE;\r
328 break;\r
329 }\r
330 }\r
331\r
332 if (FoundAcpiTable) {\r
333 RsdpPtr = (UINT8*)EfiConfigurationTable->VendorTable;\r
334\r
335 // The RSDP revision is 1 byte starting at offset 15\r
336 RsdpRevision = *(RsdpPtr + RSDP_REVISION_OFFSET);\r
337\r
338 if (RsdpRevision < 2) {\r
339 Print (\r
340 L"ERROR: RSDP version less than 2 is not supported.\n"\r
341 );\r
342 return EFI_UNSUPPORTED;\r
343 }\r
344\r
345 // The RSDP length is 4 bytes starting at offset 20\r
346 RsdpLength = *(UINT32*)(RsdpPtr + RSDP_LENGTH_OFFSET);\r
347\r
348 Trace = ProcessTableReportOptions (RSDP_TABLE_INFO, RsdpPtr, RsdpLength);\r
349\r
350 Status = GetParser (RSDP_TABLE_INFO, &RsdpParserProc);\r
351 if (EFI_ERROR (Status)) {\r
352 Print (\r
353 L"ERROR: No registered parser found for RSDP.\n"\r
354 );\r
355 return Status;\r
356 }\r
357\r
358 RsdpParserProc (\r
359 Trace,\r
360 RsdpPtr,\r
361 RsdpLength,\r
362 RsdpRevision\r
363 );\r
364\r
365 } else {\r
366 IncrementErrorCount ();\r
367 Print (\r
368 L"ERROR: Failed to find ACPI Table Guid in System Configuration Table.\n"\r
369 );\r
370 return EFI_NOT_FOUND;\r
371 }\r
372\r
373 ReportOption = GetReportOption ();\r
374 if (EREPORT_TABLE_LIST != ReportOption) {\r
375 if (((EREPORT_SELECTED == ReportOption) ||\r
376 (EREPORT_DUMP_BIN_FILE == ReportOption)) &&\r
377 (!mSelectedAcpiTableFound)) {\r
378 Print (L"\nRequested ACPI Table not found.\n");\r
379 } else if (EREPORT_DUMP_BIN_FILE != ReportOption) {\r
380 OriginalAttribute = gST->ConOut->Mode->Attribute;\r
381\r
382 Print (L"\nTable Statistics:\n");\r
383\r
384 if (GetColourHighlighting ()) {\r
385 PrintAttribute = (GetErrorCount () > 0) ?\r
386 EFI_TEXT_ATTR (\r
387 EFI_RED,\r
388 ((OriginalAttribute&(BIT4|BIT5|BIT6))>>4)\r
389 ) :\r
390 OriginalAttribute;\r
391 gST->ConOut->SetAttribute (gST->ConOut, PrintAttribute);\r
392 }\r
393 Print (L"\t%d Error(s)\n", GetErrorCount ());\r
394\r
395 if (GetColourHighlighting ()) {\r
396 PrintAttribute = (GetWarningCount () > 0) ?\r
397 EFI_TEXT_ATTR (\r
398 EFI_RED,\r
399 ((OriginalAttribute&(BIT4|BIT5|BIT6))>>4)\r
400 ) :\r
401 OriginalAttribute;\r
402\r
403 gST->ConOut->SetAttribute (gST->ConOut, PrintAttribute);\r
404 }\r
405 Print (L"\t%d Warning(s)\n", GetWarningCount ());\r
406\r
407 if (GetColourHighlighting ()) {\r
408 gST->ConOut->SetAttribute (gST->ConOut, OriginalAttribute);\r
409 }\r
410 }\r
411 }\r
412 return EFI_SUCCESS;\r
413}\r
414\r
415/**\r
416 Function for 'acpiview' command.\r
417\r
418 @param[in] ImageHandle Handle to the Image (NULL if Internal).\r
419 @param[in] SystemTable Pointer to the System Table (NULL if Internal).\r
a6eaba4d 420**/\r
ee4dc24f
RN
421SHELL_STATUS\r
422EFIAPI\r
423ShellCommandRunAcpiView (\r
424 IN EFI_HANDLE ImageHandle,\r
425 IN EFI_SYSTEM_TABLE* SystemTable\r
426 )\r
427{\r
428 EFI_STATUS Status;\r
429 SHELL_STATUS ShellStatus = SHELL_SUCCESS;\r
430 LIST_ENTRY* Package = NULL;\r
431 CHAR16* ProblemParam;\r
432 CONST CHAR16* Temp;\r
433 CHAR8 ColourOption[8];\r
434 SHELL_FILE_HANDLE TmpDumpFileHandle = NULL;\r
435\r
436 // Set Defaults\r
437 mReportType = EREPORT_ALL;\r
438 mTableCount = 0;\r
439 mBinTableCount = 0;\r
440 mSelectedAcpiTable = 0;\r
441 mSelectedAcpiTableName = NULL;\r
442 mSelectedAcpiTableFound = FALSE;\r
443 mVerbose = TRUE;\r
444 mConsistencyCheck = TRUE;\r
445\r
446 // Reset The error/warning counters\r
447 ResetErrorCount ();\r
448 ResetWarningCount ();\r
449\r
450 Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);\r
451 if (EFI_ERROR (Status)) {\r
452 if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {\r
453 ShellPrintHiiEx (\r
454 -1,\r
455 -1,\r
456 NULL,\r
457 STRING_TOKEN (STR_GEN_PROBLEM),\r
458 gShellAcpiViewHiiHandle,\r
459 L"acpiview",\r
460 ProblemParam\r
461 );\r
462 FreePool (ProblemParam);\r
463 } else {\r
464 Print (L"acpiview: Error processing input parameter(s)\n");\r
465 }\r
466 ShellStatus = SHELL_INVALID_PARAMETER;\r
467 } else {\r
468 if (ShellCommandLineGetCount (Package) > 1) {\r
469 ShellPrintHiiEx (\r
470 -1,\r
471 -1,\r
472 NULL,\r
473 STRING_TOKEN (STR_GEN_TOO_MANY),\r
474 gShellAcpiViewHiiHandle,\r
475 L"acpiview"\r
476 );\r
477 ShellStatus = SHELL_INVALID_PARAMETER;\r
478 } else if (ShellCommandLineGetFlag (Package, L"-?")) {\r
479 ShellPrintHiiEx (\r
480 -1,\r
481 -1,\r
482 NULL,\r
483 STRING_TOKEN (STR_GET_HELP_ACPIVIEW),\r
484 gShellAcpiViewHiiHandle,\r
485 L"acpiview"\r
486 );\r
487 } else if (ShellCommandLineGetFlag (Package, L"-s") &&\r
488 ShellCommandLineGetValue (Package, L"-s") == NULL) {\r
489 ShellPrintHiiEx (\r
490 -1,\r
491 -1,\r
492 NULL,\r
493 STRING_TOKEN (STR_GEN_NO_VALUE),\r
494 gShellAcpiViewHiiHandle,\r
495 L"acpiview",\r
496 L"-s"\r
497 );\r
498 ShellStatus = SHELL_INVALID_PARAMETER;\r
499 } else if ((ShellCommandLineGetFlag (Package, L"-s") &&\r
500 ShellCommandLineGetFlag (Package, L"-l"))) {\r
501 ShellPrintHiiEx (\r
502 -1,\r
503 -1,\r
504 NULL,\r
505 STRING_TOKEN (STR_GEN_TOO_MANY),\r
506 gShellAcpiViewHiiHandle,\r
507 L"acpiview"\r
508 );\r
509 ShellStatus = SHELL_INVALID_PARAMETER;\r
510 } else if (ShellCommandLineGetFlag (Package, L"-h") &&\r
511 ShellCommandLineGetValue (Package, L"-h") == NULL) {\r
512 ShellPrintHiiEx (\r
513 -1,\r
514 -1,\r
515 NULL,\r
516 STRING_TOKEN (STR_GEN_NO_VALUE),\r
517 gShellAcpiViewHiiHandle,\r
518 L"acpiview",\r
519 L"-h"\r
520 );\r
521 ShellStatus = SHELL_INVALID_PARAMETER;\r
522 } else if (ShellCommandLineGetFlag (Package, L"-d") &&\r
523 !ShellCommandLineGetFlag (Package, L"-s")) {\r
524 ShellPrintHiiEx (\r
525 -1,\r
526 -1,\r
527 NULL,\r
528 STRING_TOKEN (STR_GEN_MISSING_OPTION),\r
529 gShellAcpiViewHiiHandle,\r
530 L"acpiview",\r
531 L"-s",\r
532 L"-d"\r
533 );\r
534 ShellStatus = SHELL_INVALID_PARAMETER;\r
535 } else {\r
536 // Check if the colour option is set\r
537 Temp = ShellCommandLineGetValue (Package, L"-h");\r
538 if (Temp != NULL) {\r
539 UnicodeStrToAsciiStrS (Temp, ColourOption, sizeof (ColourOption));\r
540 if ((AsciiStriCmp (ColourOption, "ON") == 0) ||\r
541 (AsciiStriCmp (ColourOption, "TRUE") == 0)) {\r
542 SetColourHighlighting (TRUE);\r
543 } else if ((AsciiStriCmp (ColourOption, "OFF") == 0) ||\r
544 (AsciiStriCmp (ColourOption, "FALSE") == 0)) {\r
545 SetColourHighlighting (FALSE);\r
546 }\r
547 }\r
548\r
549 if (ShellCommandLineGetFlag (Package, L"-l")) {\r
550 mReportType = EREPORT_TABLE_LIST;\r
551 } else {\r
552 mSelectedAcpiTableName = ShellCommandLineGetValue (Package, L"-s");\r
553 if (mSelectedAcpiTableName != NULL) {\r
554 mSelectedAcpiTable = (UINT32)ConvertStrToAcpiSignature (\r
555 mSelectedAcpiTableName\r
556 );\r
557 mReportType = EREPORT_SELECTED;\r
558\r
559 if (ShellCommandLineGetFlag (Package, L"-d")) {\r
560 // Create a temporary file to check if the media is writable.\r
561 CHAR16 FileNameBuffer[MAX_FILE_NAME_LEN];\r
562 mReportType = EREPORT_DUMP_BIN_FILE;\r
563\r
564 UnicodeSPrint (\r
565 FileNameBuffer,\r
566 sizeof (FileNameBuffer),\r
567 L".\\%s%04d.tmp",\r
568 mSelectedAcpiTableName,\r
569 mBinTableCount\r
570 );\r
571\r
572 Status = ShellOpenFileByName (\r
573 FileNameBuffer,\r
574 &TmpDumpFileHandle,\r
575 EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE |\r
576 EFI_FILE_MODE_CREATE,\r
577 0\r
578 );\r
579\r
580 if (EFI_ERROR (Status)) {\r
581 ShellStatus = SHELL_INVALID_PARAMETER;\r
582 TmpDumpFileHandle = NULL;\r
583 ShellPrintHiiEx (\r
584 -1,\r
585 -1,\r
586 NULL,\r
587 STRING_TOKEN (STR_GEN_READONLY_MEDIA),\r
588 gShellAcpiViewHiiHandle,\r
589 L"acpiview"\r
590 );\r
591 goto Done;\r
592 }\r
593 // Delete Temporary file.\r
594 ShellDeleteFile (&TmpDumpFileHandle);\r
595 } // -d\r
596 } // -s\r
597 }\r
598\r
599 // Parse ACPI Table information\r
600 Status = AcpiView (SystemTable);\r
601 if (EFI_ERROR (Status)) {\r
602 ShellStatus = SHELL_NOT_FOUND;\r
603 }\r
604 }\r
605 }\r
606\r
607Done:\r
608 if (Package != NULL) {\r
609 ShellCommandLineFreeVarList (Package);\r
610 }\r
611 return ShellStatus;\r
612}\r