Home | History | Annotate | Download | only in UefiShellLevel2CommandsLib
      1 /** @file
      2   Main file for attrib shell level 2 function.
      3 
      4   (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
      5   (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
      6   Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.<BR>
      7   This program and the accompanying materials
      8   are licensed and made available under the terms and conditions of the BSD License
      9   which accompanies this distribution.  The full text of the license may be found at
     10   http://opensource.org/licenses/bsd-license.php
     11 
     12   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     13   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     14 
     15 **/
     16 
     17 #include "UefiShellLevel2CommandsLib.h"
     18 
     19 /**
     20   Function will replace drive identifier with CWD.
     21 
     22   If FullPath begining with ':' is invalid path, then ASSERT.
     23   If FullPath not include dirve identifier , then do nothing.
     24   If FullPath likes "fs0:\xx" or "fs0:/xx" , then do nothing.
     25   If FullPath likes "fs0:xxx" or "fs0:", the drive replaced by CWD.
     26 
     27   @param[in, out]   FullPath    The pointer to the string containing the path.
     28   @param[in]        Cwd         Current directory.
     29 
     30   @retval   EFI_SUCCESS         Success.
     31   @retval   EFI_OUT_OF_SOURCES  A memory allocation failed.
     32 **/
     33 EFI_STATUS
     34 ReplaceDriveWithCwd (
     35   IN OUT    CHAR16  **FullPath,
     36   IN CONST  CHAR16  *Cwd
     37   )
     38 {
     39   CHAR16        *Splitter;
     40   CHAR16        *TempBuffer;
     41   UINTN         TotalSize;
     42 
     43   Splitter   = NULL;
     44   TempBuffer = NULL;
     45   TotalSize  = 0;
     46 
     47   if (FullPath == NULL || *FullPath == NULL) {
     48     return EFI_SUCCESS;
     49   }
     50 
     51   Splitter = StrStr (*FullPath, L":");
     52   ASSERT(Splitter != *FullPath);
     53 
     54   if (Splitter != NULL && *(Splitter + 1) != L'\\' && *(Splitter + 1) != L'/') {
     55     TotalSize = StrSize (Cwd) + StrSize (Splitter + 1);
     56     TempBuffer = AllocateZeroPool (TotalSize);
     57     if (TempBuffer == NULL) {
     58       return EFI_OUT_OF_RESOURCES;
     59     }
     60 
     61     StrCpyS (TempBuffer, TotalSize / sizeof(CHAR16), Cwd);
     62     StrCatS (TempBuffer, TotalSize / sizeof(CHAR16), L"\\");
     63     StrCatS (TempBuffer, TotalSize / sizeof(CHAR16), Splitter + 1);
     64 
     65     FreePool(*FullPath);
     66     *FullPath = TempBuffer;
     67   }
     68 
     69   return EFI_SUCCESS;
     70 }
     71 
     72 /**
     73   function to determine if FullPath is under current filesystem.
     74 
     75   @param[in]    FullPath    The target location to determine.
     76   @param[in]    Cwd         Current directory.
     77 
     78   @retval       TRUE        The FullPath is in the current filesystem.
     79   @retval       FALSE       The FullPaht isn't in the current filesystem.
     80 **/
     81 BOOLEAN
     82 IsCurrentFileSystem (
     83   IN CONST CHAR16   *FullPath,
     84   IN CONST CHAR16   *Cwd
     85   )
     86 {
     87   CHAR16 *Splitter1;
     88   CHAR16 *Splitter2;
     89 
     90   Splitter1 = NULL;
     91   Splitter2 = NULL;
     92 
     93   ASSERT(FullPath != NULL);
     94 
     95   Splitter1 = StrStr (FullPath, L":");
     96   if (Splitter1 == NULL) {
     97     return TRUE;
     98   }
     99 
    100   Splitter2 = StrStr (Cwd, L":");
    101 
    102   if ((UINTN) (Splitter1 - FullPath) != (UINTN) (Splitter2 - Cwd)) {
    103     return FALSE;
    104   } else {
    105     if (StrniCmp (FullPath, Cwd, (UINTN) (Splitter1 - FullPath)) == NULL) {
    106       return TRUE;
    107     } else {
    108       return FALSE;
    109     }
    110   }
    111 }
    112 
    113 /**
    114   Extract drive string and path string from FullPath.
    115 
    116   The caller must be free Drive and Path.
    117 
    118   @param[in]    FullPath    A path to be extracted.
    119   @param[out]   Drive       Buffer to save drive identifier.
    120   @param[out]   Path        Buffer to save path.
    121 
    122   @retval       EFI_SUCCESS           Success.
    123   @retval       EFI_OUT_OF_RESOUCES   A memory allocation failed.
    124 **/
    125 EFI_STATUS
    126 ExtractDriveAndPath (
    127   IN CONST CHAR16   *FullPath,
    128   OUT CHAR16        **Drive,
    129   OUT CHAR16        **Path
    130   )
    131 {
    132   CHAR16 *Splitter;
    133 
    134   ASSERT (FullPath != NULL);
    135 
    136   Splitter = StrStr (FullPath, L":");
    137 
    138   if (Splitter == NULL) {
    139     *Drive = NULL;
    140     *Path = AllocateCopyPool (StrSize (FullPath), FullPath);
    141     if (*Path == NULL) {
    142       return EFI_OUT_OF_RESOURCES;
    143     }
    144   } else {
    145     if (*(Splitter + 1) == CHAR_NULL) {
    146       *Drive = AllocateCopyPool (StrSize (FullPath), FullPath);
    147       *Path = NULL;
    148       if (*Drive == NULL) {
    149         return EFI_OUT_OF_RESOURCES;
    150       }
    151     } else {
    152       *Drive = AllocateCopyPool ((Splitter - FullPath + 2) * sizeof(CHAR16), FullPath);
    153       if (*Drive == NULL) {
    154         return EFI_OUT_OF_RESOURCES;
    155       }
    156       (*Drive)[Splitter - FullPath + 1] = CHAR_NULL;
    157 
    158       *Path = AllocateCopyPool (StrSize (Splitter + 1), Splitter + 1);
    159       if (*Path == NULL) {
    160         FreePool (*Drive);
    161         return EFI_OUT_OF_RESOURCES;
    162       }
    163     }
    164   }
    165 
    166   return EFI_SUCCESS;
    167 }
    168 
    169 /**
    170   Function for 'cd' command.
    171 
    172   @param[in] ImageHandle  Handle to the Image (NULL if Internal).
    173   @param[in] SystemTable  Pointer to the System Table (NULL if Internal).
    174 **/
    175 SHELL_STATUS
    176 EFIAPI
    177 ShellCommandRunCd (
    178   IN EFI_HANDLE        ImageHandle,
    179   IN EFI_SYSTEM_TABLE  *SystemTable
    180   )
    181 {
    182   EFI_STATUS        Status;
    183   LIST_ENTRY        *Package;
    184   CONST CHAR16      *Cwd;
    185   CHAR16            *Path;
    186   CHAR16            *Drive;
    187   CHAR16            *ProblemParam;
    188   SHELL_STATUS      ShellStatus;
    189   CONST CHAR16      *Param1;
    190   CHAR16            *Param1Copy;
    191   CHAR16            *Walker;
    192   CHAR16            *Splitter;
    193   CHAR16            *TempBuffer;
    194   UINTN             TotalSize;
    195 
    196   ProblemParam  = NULL;
    197   ShellStatus   = SHELL_SUCCESS;
    198   Cwd           = NULL;
    199   Path          = NULL;
    200   Drive         = NULL;
    201   Splitter      = NULL;
    202   TempBuffer    = NULL;
    203   TotalSize     = 0;
    204 
    205   Status = CommandInit();
    206   ASSERT_EFI_ERROR(Status);
    207 
    208   //
    209   // initialize the shell lib (we must be in non-auto-init...)
    210   //
    211   Status = ShellInitialize();
    212   ASSERT_EFI_ERROR(Status);
    213 
    214   //
    215   // parse the command line
    216   //
    217   Status = ShellCommandLineParse (EmptyParamList, &Package, &ProblemParam, TRUE);
    218   if (EFI_ERROR(Status)) {
    219     if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
    220       ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, L"cd", ProblemParam);
    221       FreePool(ProblemParam);
    222       ShellStatus = SHELL_INVALID_PARAMETER;
    223     } else {
    224       ASSERT(FALSE);
    225     }
    226   }
    227 
    228   //
    229   // check for "-?"
    230   //
    231   if (ShellCommandLineGetFlag(Package, L"-?")) {
    232     ASSERT(FALSE);
    233   } else if (ShellCommandLineGetRawValue(Package, 2) != NULL) {
    234     ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel2HiiHandle, L"cd");
    235     ShellStatus = SHELL_INVALID_PARAMETER;
    236   } else {
    237     //
    238     // remember that param 0 is the command name
    239     // If there are 0 value parameters, then print the current directory
    240     // else If there are 2 value parameters, then print the error message
    241     // else If there is  1 value paramerer , then change the directory
    242     //
    243     Cwd = ShellGetCurrentDir (NULL);
    244     if (Cwd == NULL) {
    245       ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN(STR_GEN_NO_CWD), gShellLevel2HiiHandle, L"cd");
    246       ShellStatus = SHELL_NOT_FOUND;
    247     } else {
    248       Param1 = ShellCommandLineGetRawValue (Package, 1);
    249       if (Param1 == NULL) {
    250         //
    251         // display the current directory
    252         //
    253         ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN(STR_CD_PRINT), gShellLevel2HiiHandle, Cwd);
    254       } else {
    255         Param1Copy = CatSPrint (NULL, L"%s", Param1, NULL);
    256         for (Walker = Param1Copy; Walker != NULL && *Walker != CHAR_NULL; Walker++) {
    257           if (*Walker == L'\"') {
    258             CopyMem (Walker, Walker + 1, StrSize(Walker) - sizeof(Walker[0]));
    259           }
    260         }
    261 
    262         if (Param1Copy != NULL && IsCurrentFileSystem (Param1Copy, Cwd)) {
    263           Status = ReplaceDriveWithCwd (&Param1Copy,Cwd);
    264           if (!EFI_ERROR (Status)) {
    265             Param1Copy = PathCleanUpDirectories (Param1Copy);
    266           }
    267         } else {
    268           //
    269           // Can't use cd command to change filesystem.
    270           //
    271           ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_CD_NF), gShellLevel2HiiHandle, L"cd");
    272           Status = EFI_NOT_FOUND;
    273         }
    274 
    275         if (!EFI_ERROR(Status) && Param1Copy != NULL) {
    276           Splitter = StrStr (Cwd, L":");
    277           if (Param1Copy[0] == L'\\') {
    278             //
    279             // Absolute Path on current drive letter.
    280             //
    281             TotalSize = ((Splitter - Cwd + 1) * sizeof(CHAR16)) + StrSize(Param1Copy);
    282             TempBuffer = AllocateZeroPool (TotalSize);
    283             if (TempBuffer == NULL) {
    284               Status = EFI_OUT_OF_RESOURCES;
    285             } else {
    286               StrnCpyS (TempBuffer, TotalSize / sizeof(CHAR16), Cwd, (Splitter - Cwd + 1));
    287               StrCatS (TempBuffer, TotalSize / sizeof(CHAR16), Param1Copy);
    288 
    289               FreePool (Param1Copy);
    290               Param1Copy = TempBuffer;
    291               TempBuffer = NULL;
    292             }
    293           } else {
    294             if (StrStr (Param1Copy,L":") == NULL) {
    295               TotalSize = StrSize (Cwd) + StrSize (Param1Copy);
    296               TempBuffer = AllocateZeroPool (TotalSize);
    297               if (TempBuffer == NULL) {
    298                 Status = EFI_OUT_OF_RESOURCES;
    299               } else {
    300                 StrCpyS (TempBuffer, TotalSize / sizeof (CHAR16), Cwd);
    301                 StrCatS (TempBuffer, TotalSize / sizeof (CHAR16), L"\\");
    302                 StrCatS (TempBuffer, TotalSize / sizeof (CHAR16), Param1Copy);
    303 
    304                 FreePool (Param1Copy);
    305                 Param1Copy = PathCleanUpDirectories (TempBuffer);
    306               }
    307             }
    308           }
    309         }
    310 
    311         if (!EFI_ERROR(Status)) {
    312           Status = ExtractDriveAndPath (Param1Copy, &Drive, &Path);
    313         }
    314 
    315         if (!EFI_ERROR (Status) && Drive != NULL && Path != NULL) {
    316           if (EFI_ERROR(ShellIsDirectory (Param1Copy))) {
    317             ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN(STR_GEN_NOT_DIR), gShellLevel2HiiHandle, L"cd", Param1Copy);
    318             ShellStatus = SHELL_NOT_FOUND;
    319           } else {
    320             Status = gEfiShellProtocol->SetCurDir (Drive, Path + 1);
    321             if (EFI_ERROR (Status)) {
    322               ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN(STR_GEN_DIR_NF), gShellLevel2HiiHandle, L"cd", Param1Copy);
    323               ShellStatus = SHELL_NOT_FOUND;
    324             } else {
    325               ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN(STR_CD_PRINT), gShellLevel2HiiHandle, ShellGetCurrentDir(Drive));
    326             }
    327           }
    328         }
    329 
    330         if (Drive != NULL) {
    331           FreePool (Drive);
    332         }
    333 
    334         if (Path != NULL) {
    335           FreePool (Path);
    336         }
    337 
    338         FreePool (Param1Copy);
    339       }
    340     }
    341   }
    342 
    343   //
    344   // free the command line package
    345   //
    346   ShellCommandLineFreeVarList (Package);
    347 
    348   //
    349   // return the status
    350   //
    351   return (ShellStatus);
    352 }
    353 
    354