Ls.c revision fed3be946c8bff1372e106eec8cfd73524036ceb
1/** @file
2  Main file for ls shell level 2 function.
3
4  Copyright (c) 2013 Hewlett-Packard Development Company, L.P.
5  Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.<BR>
6  This program and the accompanying materials
7  are licensed and made available under the terms and conditions of the BSD License
8  which accompanies this distribution.  The full text of the license may be found at
9  http://opensource.org/licenses/bsd-license.php
10
11  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13
14**/
15
16#include "UefiShellLevel2CommandsLib.h"
17#include <Guid/FileSystemInfo.h>
18
19/**
20  print out the standard format output volume entry.
21
22  @param[in] TheList           a list of files from the volume.
23**/
24EFI_STATUS
25EFIAPI
26PrintSfoVolumeInfoTableEntry(
27  IN CONST EFI_SHELL_FILE_INFO *TheList
28  )
29{
30  EFI_STATUS            Status;
31  EFI_SHELL_FILE_INFO   *Node;
32  CHAR16                *DirectoryName;
33  EFI_FILE_SYSTEM_INFO  *SysInfo;
34  UINTN                 SysInfoSize;
35  SHELL_FILE_HANDLE     ShellFileHandle;
36  EFI_FILE_PROTOCOL     *EfiFpHandle;
37
38  //
39  // Get the first valid handle (directories)
40  //
41  for ( Node = (EFI_SHELL_FILE_INFO *)GetFirstNode(&TheList->Link)
42      ; !IsNull(&TheList->Link, &Node->Link) && Node->Handle == NULL
43      ; Node = (EFI_SHELL_FILE_INFO *)GetNextNode(&TheList->Link, &Node->Link)
44     );
45
46  if (Node->Handle == NULL) {
47    DirectoryName = GetFullyQualifiedPath(((EFI_SHELL_FILE_INFO *)GetFirstNode(&TheList->Link))->FullName);
48
49    //
50    // We need to open something up to get system information
51    //
52    Status = gEfiShellProtocol->OpenFileByName(
53      DirectoryName,
54      &ShellFileHandle,
55      EFI_FILE_MODE_READ
56      );
57
58    ASSERT_EFI_ERROR(Status);
59    FreePool(DirectoryName);
60
61    //
62    // Get the Volume Info from ShellFileHandle
63    //
64    SysInfo     = NULL;
65    SysInfoSize = 0;
66    EfiFpHandle = ConvertShellHandleToEfiFileProtocol(ShellFileHandle);
67    Status = EfiFpHandle->GetInfo(
68      EfiFpHandle,
69      &gEfiFileSystemInfoGuid,
70      &SysInfoSize,
71      SysInfo
72      );
73
74    if (Status == EFI_BUFFER_TOO_SMALL) {
75      SysInfo = AllocateZeroPool(SysInfoSize);
76      Status = EfiFpHandle->GetInfo(
77        EfiFpHandle,
78        &gEfiFileSystemInfoGuid,
79        &SysInfoSize,
80        SysInfo
81        );
82    }
83
84    ASSERT_EFI_ERROR(Status);
85
86    gEfiShellProtocol->CloseFile(ShellFileHandle);
87  } else {
88    //
89    // Get the Volume Info from Node->Handle
90    //
91    SysInfo = NULL;
92    SysInfoSize = 0;
93    EfiFpHandle = ConvertShellHandleToEfiFileProtocol(Node->Handle);
94    Status = EfiFpHandle->GetInfo(
95      EfiFpHandle,
96      &gEfiFileSystemInfoGuid,
97      &SysInfoSize,
98      SysInfo
99      );
100
101    if (Status == EFI_BUFFER_TOO_SMALL) {
102      SysInfo = AllocateZeroPool(SysInfoSize);
103      Status = EfiFpHandle->GetInfo(
104        EfiFpHandle,
105        &gEfiFileSystemInfoGuid,
106        &SysInfoSize,
107        SysInfo
108        );
109    }
110
111    ASSERT_EFI_ERROR(Status);
112  }
113
114  ShellPrintHiiEx (
115    -1,
116    -1,
117    NULL,
118    STRING_TOKEN (STR_GEN_SFO_HEADER),
119    gShellLevel2HiiHandle,
120    L"ls"
121    );
122  //
123  // print VolumeInfo table
124  //
125  ASSERT(SysInfo != NULL);
126  ShellPrintHiiEx (
127    0,
128    gST->ConOut->Mode->CursorRow,
129    NULL,
130    STRING_TOKEN (STR_LS_SFO_VOLINFO),
131    gShellLevel2HiiHandle,
132    SysInfo->VolumeLabel,
133    SysInfo->VolumeSize,
134    SysInfo->ReadOnly?L"TRUE":L"FALSE",
135    SysInfo->FreeSpace,
136    SysInfo->BlockSize
137    );
138
139  SHELL_FREE_NON_NULL(SysInfo);
140
141  return (Status);
142}
143
144/**
145  print out the info on a single file.
146
147  @param[in] Sfo      TRUE if in SFO, false otherwise.
148  @param[in] TheNode  the EFI_SHELL_FILE_INFO node to print out information on.
149  @param[in] Files    incremented if a file is printed.
150  @param[in] Size     incremented by file size.
151  @param[in] Dirs     incremented if a directory is printed.
152
153**/
154VOID
155EFIAPI
156PrintFileInformation(
157  IN CONST BOOLEAN              Sfo,
158  IN CONST EFI_SHELL_FILE_INFO  *TheNode,
159  IN UINT64                     *Files,
160  IN UINT64                     *Size,
161  IN UINT64                     *Dirs
162  )
163{
164  ASSERT(Files    != NULL);
165  ASSERT(Size     != NULL);
166  ASSERT(Dirs     != NULL);
167  ASSERT(TheNode  != NULL);
168
169  if (Sfo) {
170    //
171    // Print the FileInfo Table
172    //
173    ShellPrintHiiEx (
174      0,
175      gST->ConOut->Mode->CursorRow,
176      NULL,
177      STRING_TOKEN (STR_LS_SFO_FILEINFO),
178      gShellLevel2HiiHandle,
179      TheNode->FullName,
180      TheNode->Info->FileSize,
181      TheNode->Info->PhysicalSize,
182      (TheNode->Info->Attribute & EFI_FILE_ARCHIVE)   != 0?L"a":L"",
183      (TheNode->Info->Attribute & EFI_FILE_DIRECTORY) != 0?L"d":L"",
184      (TheNode->Info->Attribute & EFI_FILE_HIDDEN)    != 0?L"h":L"",
185      (TheNode->Info->Attribute & EFI_FILE_READ_ONLY) != 0?L"r":L"",
186      (TheNode->Info->Attribute & EFI_FILE_SYSTEM)    != 0?L"s":L"",
187      TheNode->Info->CreateTime.Hour,
188      TheNode->Info->CreateTime.Minute,
189      TheNode->Info->CreateTime.Second,
190      TheNode->Info->CreateTime.Day,
191      TheNode->Info->CreateTime.Month,
192      TheNode->Info->CreateTime.Year,
193      TheNode->Info->LastAccessTime.Hour,
194      TheNode->Info->LastAccessTime.Minute,
195      TheNode->Info->LastAccessTime.Second,
196      TheNode->Info->LastAccessTime.Day,
197      TheNode->Info->LastAccessTime.Month,
198      TheNode->Info->LastAccessTime.Year,
199      TheNode->Info->ModificationTime.Hour,
200      TheNode->Info->ModificationTime.Minute,
201      TheNode->Info->ModificationTime.Second,
202      TheNode->Info->ModificationTime.Day,
203      TheNode->Info->ModificationTime.Month,
204      TheNode->Info->ModificationTime.Year
205      );
206  } else {
207    //
208    // print this one out...
209    // first print the universal start, next print the type specific name format, last print the CRLF
210    //
211    ShellPrintHiiEx (
212      -1,
213      -1,
214      NULL,
215      STRING_TOKEN (STR_LS_LINE_START_ALL),
216      gShellLevel2HiiHandle,
217      &TheNode->Info->ModificationTime,
218      (TheNode->Info->Attribute & EFI_FILE_DIRECTORY) != 0?L"<DIR>":L"",
219      (TheNode->Info->Attribute & EFI_FILE_READ_ONLY) != 0?L'r':L' ',
220      TheNode->Info->FileSize
221      );
222    if (TheNode->Info->Attribute & EFI_FILE_DIRECTORY) {
223      (*Dirs)++;
224      ShellPrintHiiEx (
225        -1,
226        -1,
227        NULL,
228        STRING_TOKEN (STR_LS_LINE_END_DIR),
229        gShellLevel2HiiHandle,
230        TheNode->FileName
231        );
232    } else {
233      (*Files)++;
234      (*Size) += TheNode->Info->FileSize;
235      if ( (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)L".nsh", (CHAR16*)&(TheNode->FileName[StrLen (TheNode->FileName) - 4])) == 0)
236        || (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)L".efi", (CHAR16*)&(TheNode->FileName[StrLen (TheNode->FileName) - 4])) == 0)
237       ){
238        ShellPrintHiiEx (
239          -1,
240          -1,
241          NULL,
242          STRING_TOKEN (STR_LS_LINE_END_EXE),
243          gShellLevel2HiiHandle,
244          TheNode->FileName
245          );
246      } else {
247        ShellPrintHiiEx (
248          -1,
249          -1,
250          NULL,
251          STRING_TOKEN (STR_LS_LINE_END_FILE),
252          gShellLevel2HiiHandle,
253          TheNode->FileName
254          );
255      }
256    }
257  }
258}
259
260/**
261  print out the header when not using standard format output.
262
263  @param[in] Path           String with starting path.
264**/
265VOID
266EFIAPI
267PrintNonSfoHeader(
268  IN CONST CHAR16 *Path
269  )
270{
271  CHAR16 *DirectoryName;
272
273  //
274  // get directory name from path...
275  //
276  DirectoryName = GetFullyQualifiedPath(Path);
277
278  if (DirectoryName != NULL) {
279    //
280    // print header
281    //
282    ShellPrintHiiEx (
283      0,
284      gST->ConOut->Mode->CursorRow,
285      NULL,
286      STRING_TOKEN (STR_LS_HEADER_LINE1),
287      gShellLevel2HiiHandle,
288      DirectoryName
289      );
290
291    SHELL_FREE_NON_NULL(DirectoryName);
292  }
293}
294
295/**
296  print out the footer when not using standard format output.
297
298  @param[in] Path           String with starting path.
299**/
300VOID
301EFIAPI
302PrintNonSfoFooter(
303  IN UINT64                     Files,
304  IN UINT64                     Size,
305  IN UINT64                     Dirs
306  )
307{
308  //
309  // print footer
310  //
311  ShellPrintHiiEx (
312    -1,
313    -1,
314    NULL,
315    STRING_TOKEN (STR_LS_FOOTER_LINE),
316    gShellLevel2HiiHandle,
317    Files,
318    Size,
319    Dirs
320   );
321}
322
323/**
324  print out the list of files and directories from the LS command
325
326  @param[in] Rec            TRUE to automatically recurse into each found directory
327                            FALSE to only list the specified directory.
328  @param[in] Attribs        List of required Attribute for display.
329                            If 0 then all non-system and non-hidden files will be printed.
330  @param[in] Sfo            TRUE to use Standard Format Output, FALSE otherwise
331  @param[in] Path           String with starting path.
332  @param[in] First          TRUE for the original and FALSE for any recursion spawned instances.
333  @param[in] Count          The count of bits enabled in Attribs.
334  @param[in] TimeZone       The current time zone offset.
335
336  @retval SHELL_SUCCESS     the printing was sucessful.
337**/
338SHELL_STATUS
339EFIAPI
340PrintLsOutput(
341  IN CONST BOOLEAN Rec,
342  IN CONST UINT64  Attribs,
343  IN CONST BOOLEAN Sfo,
344  IN CONST CHAR16  *Path,
345  IN CONST BOOLEAN First,
346  IN CONST UINTN   Count,
347  IN CONST INT16   TimeZone
348  )
349{
350  EFI_STATUS            Status;
351  EFI_SHELL_FILE_INFO   *ListHead;
352  EFI_SHELL_FILE_INFO   *Node;
353  SHELL_STATUS          ShellStatus;
354  UINT64                FileCount;
355  UINT64                DirCount;
356  UINT64                FileSize;
357  CHAR16                *DirectoryName;
358  UINTN                 LongestPath;
359  CHAR16                *CorrectedPath;
360
361  FileCount     = 0;
362  DirCount      = 0;
363  FileSize      = 0;
364  ListHead      = NULL;
365  ShellStatus   = SHELL_SUCCESS;
366  LongestPath   = 0;
367  CorrectedPath = NULL;
368
369  CorrectedPath = StrnCatGrow(&CorrectedPath, NULL, Path, 0);
370  if (CorrectedPath == NULL) {
371    return (SHELL_OUT_OF_RESOURCES);
372  }
373
374  PathCleanUpDirectories(CorrectedPath);
375
376  if (!Sfo) {
377    PrintNonSfoHeader(CorrectedPath);
378  }
379
380  Status = ShellOpenFileMetaArg((CHAR16*)CorrectedPath, EFI_FILE_MODE_READ, &ListHead);
381  if (EFI_ERROR(Status)) {
382    SHELL_FREE_NON_NULL(CorrectedPath);
383    if(Status == EFI_NOT_FOUND){
384      return (SHELL_NOT_FOUND);
385    }
386    return (SHELL_DEVICE_ERROR);
387  }
388  if (ListHead == NULL || IsListEmpty(&ListHead->Link)) {
389    SHELL_FREE_NON_NULL(CorrectedPath);
390    //
391    // On the first one only we expect to find something...
392    // do we find the . and .. directories otherwise?
393    //
394    if (First) {
395      return (SHELL_NOT_FOUND);
396    }
397    return (SHELL_SUCCESS);
398  }
399
400  if (Sfo && First) {
401    PrintSfoVolumeInfoTableEntry(ListHead);
402  }
403
404  for ( Node = (EFI_SHELL_FILE_INFO *)GetFirstNode(&ListHead->Link)
405      ; !IsNull(&ListHead->Link, &Node->Link)
406      ; Node = (EFI_SHELL_FILE_INFO *)GetNextNode(&ListHead->Link, &Node->Link)
407      ){
408    ASSERT(Node != NULL);
409    if (LongestPath < StrSize(Node->FullName)) {
410      LongestPath = StrSize(Node->FullName);
411    }
412    ASSERT(Node->Info != NULL);
413    ASSERT((Node->Info->Attribute & EFI_FILE_VALID_ATTR) == Node->Info->Attribute);
414    if (Attribs == 0) {
415      //
416      // NOT system & NOT hidden
417      //
418      if ( (Node->Info->Attribute & EFI_FILE_SYSTEM)
419        || (Node->Info->Attribute & EFI_FILE_HIDDEN)
420       ){
421        continue;
422      }
423    } else if ((Attribs != EFI_FILE_VALID_ATTR) ||
424               (Count == 5)) {
425      //
426      // Only matches the bits which "Attribs" contains, not
427      // all files/directories with any of the bits.
428      // Count == 5 is used to tell the difference between a user
429      // specifying all bits (EX: -arhsda) and just specifying
430      // -a (means display all files with any attribute).
431      //
432      if ( (Node->Info->Attribute & Attribs) != Attribs) {
433        continue;
434      }
435    }
436
437    PrintFileInformation(Sfo, Node, &FileCount, &FileSize, &DirCount);
438  }
439
440  if (!Sfo) {
441    PrintNonSfoFooter(FileCount, FileSize, DirCount);
442  }
443
444  if (Rec){
445    DirectoryName = AllocateZeroPool(LongestPath + 2*sizeof(CHAR16));
446    if (DirectoryName == NULL) {
447      ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_MEM), gShellLevel2HiiHandle);
448      ShellStatus = SHELL_OUT_OF_RESOURCES;
449    } else {
450      for ( Node = (EFI_SHELL_FILE_INFO *)GetFirstNode(&ListHead->Link)
451          ; !IsNull(&ListHead->Link, &Node->Link) && ShellStatus == SHELL_SUCCESS
452          ; Node = (EFI_SHELL_FILE_INFO *)GetNextNode(&ListHead->Link, &Node->Link)
453         ){
454        if (ShellGetExecutionBreakFlag ()) {
455          ShellStatus = SHELL_ABORTED;
456          break;
457        }
458
459        //
460        // recurse on any directory except the traversing ones...
461        //
462        if (((Node->Info->Attribute & EFI_FILE_DIRECTORY) == EFI_FILE_DIRECTORY)
463          && StrCmp(Node->FileName, L".") != 0
464          && StrCmp(Node->FileName, L"..") != 0
465         ){
466          StrCpy(DirectoryName, Node->FullName);
467          StrCat(DirectoryName, L"\\*");
468          ShellStatus = PrintLsOutput(
469            Rec,
470            Attribs,
471            Sfo,
472            DirectoryName,
473            FALSE,
474            Count,
475            TimeZone);
476        }
477      }
478      FreePool(DirectoryName);
479    }
480  }
481
482  FreePool(CorrectedPath);
483  ShellCloseFileMetaArg(&ListHead);
484  return (ShellStatus);
485}
486
487STATIC CONST SHELL_PARAM_ITEM LsParamList[] = {
488  {L"-r", TypeFlag},
489  {L"-a", TypeStart},
490  {L"-sfo", TypeFlag},
491  {NULL, TypeMax}
492  };
493
494/**
495  Function for 'ls' command.
496
497  @param[in] ImageHandle  Handle to the Image (NULL if Internal).
498  @param[in] SystemTable  Pointer to the System Table (NULL if Internal).
499**/
500SHELL_STATUS
501EFIAPI
502ShellCommandRunLs (
503  IN EFI_HANDLE        ImageHandle,
504  IN EFI_SYSTEM_TABLE  *SystemTable
505  )
506{
507  EFI_STATUS    Status;
508  LIST_ENTRY    *Package;
509  CHAR16        *ProblemParam;
510  CONST CHAR16  *Attribs;
511  SHELL_STATUS  ShellStatus;
512  UINT64        RequiredAttributes;
513  CONST CHAR16  *PathName;
514  CONST CHAR16  *CurDir;
515  UINTN         Count;
516  CHAR16        *FullPath;
517  UINTN         Size;
518  EFI_TIME      TheTime;
519  BOOLEAN       SfoMode;
520
521  Size                = 0;
522  FullPath            = NULL;
523  ProblemParam        = NULL;
524  Attribs             = NULL;
525  ShellStatus         = SHELL_SUCCESS;
526  RequiredAttributes  = 0;
527  PathName            = NULL;
528  CurDir              = NULL;
529  Count               = 0;
530
531  //
532  // initialize the shell lib (we must be in non-auto-init...)
533  //
534  Status = ShellInitialize();
535  ASSERT_EFI_ERROR(Status);
536
537  //
538  // Fix local copies of the protocol pointers
539  //
540  Status = CommandInit();
541  ASSERT_EFI_ERROR(Status);
542
543  //
544  // parse the command line
545  //
546  Status = ShellCommandLineParse (LsParamList, &Package, &ProblemParam, TRUE);
547  if (EFI_ERROR(Status)) {
548    if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
549      ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, ProblemParam);
550      FreePool(ProblemParam);
551      ShellStatus = SHELL_INVALID_PARAMETER;
552    } else {
553      ASSERT(FALSE);
554    }
555  } else {
556    //
557    // check for "-?"
558    //
559    if (ShellCommandLineGetFlag(Package, L"-?")) {
560      ASSERT(FALSE);
561    }
562
563    if (ShellCommandLineGetCount(Package) > 2) {
564      ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel2HiiHandle);
565      ShellStatus = SHELL_INVALID_PARAMETER;
566    } else {
567      //
568      // check for -a
569      //
570      if (ShellCommandLineGetFlag(Package, L"-a")) {
571        for ( Attribs = ShellCommandLineGetValue(Package, L"-a")
572            ; Attribs != NULL && *Attribs != CHAR_NULL && ShellStatus == SHELL_SUCCESS
573            ; Attribs++
574           ){
575          switch (*Attribs) {
576            case L'a':
577            case L'A':
578              RequiredAttributes |= EFI_FILE_ARCHIVE;
579              Count++;
580              continue;
581            case L's':
582            case L'S':
583              RequiredAttributes |= EFI_FILE_SYSTEM;
584              Count++;
585              continue;
586            case L'h':
587            case L'H':
588              RequiredAttributes |= EFI_FILE_HIDDEN;
589              Count++;
590              continue;
591            case L'r':
592            case L'R':
593              RequiredAttributes |= EFI_FILE_READ_ONLY;
594              Count++;
595              continue;
596            case L'd':
597            case L'D':
598              RequiredAttributes |= EFI_FILE_DIRECTORY;
599              Count++;
600              continue;
601            default:
602              ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_ATTRIBUTE), gShellLevel2HiiHandle, ShellCommandLineGetValue(Package, L"-a"));
603              ShellStatus = SHELL_INVALID_PARAMETER;
604              break;
605          } // switch
606        } // for loop
607        //
608        // if nothing is specified all are specified
609        //
610        if (RequiredAttributes == 0) {
611          RequiredAttributes = EFI_FILE_VALID_ATTR;
612        }
613      } // if -a present
614      if (ShellStatus == SHELL_SUCCESS) {
615        PathName = ShellCommandLineGetRawValue(Package, 1);
616        if (PathName == NULL) {
617          CurDir = gEfiShellProtocol->GetCurDir(NULL);
618          if (CurDir == NULL) {
619            ShellStatus = SHELL_NOT_FOUND;
620            ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_CWD), gShellLevel2HiiHandle);
621          }
622        }
623        if (PathName != NULL) {
624          if (StrStr(PathName, L":") == NULL && gEfiShellProtocol->GetCurDir(NULL) == NULL) {
625            ShellStatus = SHELL_NOT_FOUND;
626            ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_CWD), gShellLevel2HiiHandle);
627          } else {
628            ASSERT((FullPath == NULL && Size == 0) || (FullPath != NULL));
629            StrnCatGrow(&FullPath, &Size, PathName, 0);
630            if  (ShellIsDirectory(PathName) == EFI_SUCCESS) {
631              if (PathName[StrLen (PathName) - 1] == '\\') {
632                //
633                // For path ending with '\', just append '*'.
634                //
635                StrnCatGrow (&FullPath, &Size, L"*", 0);
636              } else if (PathName[StrLen (PathName) - 1] == '*') {
637                //
638                // For path ending with '*', do nothing.
639                //
640              } else {
641                //
642                // Otherwise, append '\*' to directory name.
643                //
644                StrnCatGrow (&FullPath, &Size, L"\\*", 0);
645              }
646            }
647          }
648        } else {
649          ASSERT(FullPath == NULL);
650          StrnCatGrow(&FullPath, NULL, L"*", 0);
651        }
652        Status = gRT->GetTime(&TheTime, NULL);
653        if (EFI_ERROR(Status)) {
654          ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_UEFI_FUNC_WARN), gShellLevel2HiiHandle, L"gRT->GetTime", Status);
655          TheTime.TimeZone = EFI_UNSPECIFIED_TIMEZONE;
656        }
657
658        SfoMode = ShellCommandLineGetFlag(Package, L"-sfo");
659        if (ShellStatus == SHELL_SUCCESS) {
660          ShellStatus = PrintLsOutput(
661            ShellCommandLineGetFlag(Package, L"-r"),
662            RequiredAttributes,
663            SfoMode,
664            FullPath,
665            TRUE,
666            Count,
667            (INT16)(TheTime.TimeZone==EFI_UNSPECIFIED_TIMEZONE?0:TheTime.TimeZone)
668           );
669          if (ShellStatus == SHELL_NOT_FOUND) {
670            ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_LS_FILE_NOT_FOUND), gShellLevel2HiiHandle);
671          } else if (ShellStatus == SHELL_INVALID_PARAMETER) {
672            ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellLevel2HiiHandle);
673          } else if (ShellStatus == SHELL_ABORTED) {
674            //
675            // Ignore aborting.
676            //
677          } else if (ShellStatus != SHELL_SUCCESS) {
678            ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellLevel2HiiHandle);
679          }
680        }
681      }
682    }
683  }
684
685  if (FullPath != NULL) {
686    FreePool(FullPath);
687  }
688  //
689  // free the command line package
690  //
691  ShellCommandLineFreeVarList (Package);
692
693  return (ShellStatus);
694}
695