Home | History | Annotate | Download | only in UefiShellLevel2CommandsLib
      1 /** @file
      2   Main file for vol shell level 2 function.
      3 
      4   (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
      5   Copyright (c) 2011 - 2015, 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 #include <Guid/FileSystemVolumeLabelInfo.h>
     19 
     20 /**
     21   Print the info or change the volume info.
     22 
     23   @param[in] Path           String with starting path.
     24   @param[in] Delete         TRUE to delete the volume label. FALSE otherwise.
     25   @param[in] Name           New name to set to the volume label.
     26 
     27   @retval SHELL_SUCCESS     The operation was sucessful.
     28 **/
     29 SHELL_STATUS
     30 EFIAPI
     31 HandleVol(
     32   IN CONST CHAR16  *Path,
     33   IN CONST BOOLEAN Delete,
     34   IN CONST CHAR16  *Name OPTIONAL
     35   )
     36 {
     37   EFI_STATUS            Status;
     38   SHELL_STATUS          ShellStatus;
     39   EFI_FILE_SYSTEM_INFO  *SysInfo;
     40   UINTN                 SysInfoSize;
     41   SHELL_FILE_HANDLE     ShellFileHandle;
     42   EFI_FILE_PROTOCOL     *EfiFpHandle;
     43   UINTN                 Size1;
     44   UINTN                 Size2;
     45 
     46   ShellStatus   = SHELL_SUCCESS;
     47 
     48   if (
     49       Name != NULL && (
     50       StrStr(Name, L"%") != NULL ||
     51       StrStr(Name, L"^") != NULL ||
     52       StrStr(Name, L"*") != NULL ||
     53       StrStr(Name, L"+") != NULL ||
     54       StrStr(Name, L"=") != NULL ||
     55       StrStr(Name, L"[") != NULL ||
     56       StrStr(Name, L"]") != NULL ||
     57       StrStr(Name, L"|") != NULL ||
     58       StrStr(Name, L":") != NULL ||
     59       StrStr(Name, L";") != NULL ||
     60       StrStr(Name, L"\"") != NULL ||
     61       StrStr(Name, L"<") != NULL ||
     62       StrStr(Name, L">") != NULL ||
     63       StrStr(Name, L"?") != NULL ||
     64       StrStr(Name, L"/") != NULL ||
     65       StrStr(Name, L" ") != NULL )
     66       ){
     67     ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellLevel2HiiHandle, L"vol", Name);
     68     return (SHELL_INVALID_PARAMETER);
     69   }
     70 
     71   Status = gEfiShellProtocol->OpenFileByName(
     72     Path,
     73     &ShellFileHandle,
     74     Name != NULL?EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE:EFI_FILE_MODE_READ);
     75 
     76   if (EFI_ERROR(Status) || ShellFileHandle == NULL) {
     77     ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellLevel2HiiHandle, L"vol", Path);
     78     return (SHELL_ACCESS_DENIED);
     79   }
     80 
     81   //
     82   // Get the Volume Info from ShellFileHandle
     83   //
     84   SysInfo     = NULL;
     85   SysInfoSize = 0;
     86   EfiFpHandle = ConvertShellHandleToEfiFileProtocol(ShellFileHandle);
     87   Status = EfiFpHandle->GetInfo(
     88     EfiFpHandle,
     89     &gEfiFileSystemInfoGuid,
     90     &SysInfoSize,
     91     SysInfo);
     92 
     93   if (Status == EFI_BUFFER_TOO_SMALL) {
     94     SysInfo = AllocateZeroPool(SysInfoSize);
     95     Status = EfiFpHandle->GetInfo(
     96       EfiFpHandle,
     97       &gEfiFileSystemInfoGuid,
     98       &SysInfoSize,
     99       SysInfo);
    100   }
    101 
    102   ASSERT(SysInfo != NULL);
    103 
    104   if (Delete) {
    105     *((CHAR16 *) SysInfo->VolumeLabel) = CHAR_NULL;
    106     SysInfo->Size = SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize(SysInfo->VolumeLabel);
    107     Status = EfiFpHandle->SetInfo(
    108       EfiFpHandle,
    109       &gEfiFileSystemInfoGuid,
    110       (UINTN)SysInfo->Size,
    111       SysInfo);
    112   } else if (Name != NULL) {
    113     Size1 = StrSize(Name);
    114     Size2 = StrSize(SysInfo->VolumeLabel);
    115     if (Size1 > Size2) {
    116       SysInfo = ReallocatePool((UINTN)SysInfo->Size, (UINTN)SysInfo->Size + Size1 - Size2, SysInfo);
    117       if (SysInfo == NULL) {
    118         ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_OUT_MEM), gShellLevel2HiiHandle, L"vol");
    119         ShellStatus = SHELL_OUT_OF_RESOURCES;
    120       }
    121     }
    122     if (SysInfo != NULL) {
    123       StrCpyS ( (CHAR16 *) SysInfo->VolumeLabel,
    124                   (Size1>Size2? Size1/sizeof(CHAR16) : Size2/sizeof(CHAR16)),
    125                   Name
    126                   );
    127       SysInfo->Size = SIZE_OF_EFI_FILE_SYSTEM_INFO + Size1;
    128       Status = EfiFpHandle->SetInfo(
    129         EfiFpHandle,
    130         &gEfiFileSystemInfoGuid,
    131         (UINTN)SysInfo->Size,
    132         SysInfo);
    133     }
    134   }
    135 
    136   FreePool(SysInfo);
    137 
    138   if (Delete || Name != NULL) {
    139     if (EFI_ERROR(Status)) {
    140       ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_AD), gShellLevel2HiiHandle, L"vol", Path);
    141       ShellStatus = SHELL_ACCESS_DENIED;
    142     }
    143   }
    144 
    145   SysInfoSize = 0;
    146   SysInfo = NULL;
    147 
    148   Status = EfiFpHandle->GetInfo(
    149     EfiFpHandle,
    150     &gEfiFileSystemInfoGuid,
    151     &SysInfoSize,
    152     SysInfo);
    153 
    154   if (Status == EFI_BUFFER_TOO_SMALL) {
    155     SysInfo = AllocateZeroPool(SysInfoSize);
    156     Status = EfiFpHandle->GetInfo(
    157       EfiFpHandle,
    158       &gEfiFileSystemInfoGuid,
    159       &SysInfoSize,
    160       SysInfo);
    161   }
    162 
    163   gEfiShellProtocol->CloseFile(ShellFileHandle);
    164 
    165   ASSERT(SysInfo != NULL);
    166 
    167   if (SysInfo != NULL) {
    168     //
    169     // print VolumeInfo table
    170     //
    171     ShellPrintHiiEx (
    172       0,
    173       gST->ConOut->Mode->CursorRow,
    174       NULL,
    175       STRING_TOKEN (STR_VOL_VOLINFO),
    176       gShellLevel2HiiHandle,
    177       SysInfo->VolumeLabel,
    178       SysInfo->ReadOnly?L"r":L"rw",
    179       SysInfo->VolumeSize,
    180       SysInfo->FreeSpace,
    181       SysInfo->BlockSize
    182      );
    183     SHELL_FREE_NON_NULL(SysInfo);
    184   }
    185 
    186   return (ShellStatus);
    187 }
    188 
    189 STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
    190   {L"-d", TypeFlag},
    191   {L"-n", TypeValue},
    192   {NULL, TypeMax}
    193   };
    194 
    195 /**
    196   Function for 'Vol' command.
    197 
    198   @param[in] ImageHandle  Handle to the Image (NULL if Internal).
    199   @param[in] SystemTable  Pointer to the System Table (NULL if Internal).
    200 **/
    201 SHELL_STATUS
    202 EFIAPI
    203 ShellCommandRunVol (
    204   IN EFI_HANDLE        ImageHandle,
    205   IN EFI_SYSTEM_TABLE  *SystemTable
    206   )
    207 {
    208   EFI_STATUS    Status;
    209   LIST_ENTRY    *Package;
    210   CHAR16        *ProblemParam;
    211   SHELL_STATUS  ShellStatus;
    212   CONST CHAR16  *PathName;
    213   CONST CHAR16  *CurDir;
    214   BOOLEAN       DeleteMode;
    215   CHAR16        *FullPath;
    216   CHAR16        *TempSpot;
    217   UINTN         Length;
    218   CONST CHAR16  *NewName;
    219 
    220   Length              = 0;
    221   ProblemParam        = NULL;
    222   ShellStatus         = SHELL_SUCCESS;
    223   PathName            = NULL;
    224   CurDir              = NULL;
    225   FullPath            = NULL;
    226 
    227   //
    228   // initialize the shell lib (we must be in non-auto-init...)
    229   //
    230   Status = ShellInitialize();
    231   ASSERT_EFI_ERROR(Status);
    232 
    233   //
    234   // Fix local copies of the protocol pointers
    235   //
    236   Status = CommandInit();
    237   ASSERT_EFI_ERROR(Status);
    238 
    239   //
    240   // parse the command line
    241   //
    242   Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);
    243   if (EFI_ERROR(Status)) {
    244     if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
    245       ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, L"vol", ProblemParam);
    246       FreePool(ProblemParam);
    247       ShellStatus = SHELL_INVALID_PARAMETER;
    248     } else {
    249       ASSERT(FALSE);
    250     }
    251   } else {
    252     //
    253     // check for "-?"
    254     //
    255     if (ShellCommandLineGetFlag(Package, L"-?")) {
    256       ASSERT(FALSE);
    257     }
    258 
    259     if (ShellCommandLineGetCount(Package) > 2) {
    260       ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel2HiiHandle, L"vol");
    261       ShellStatus = SHELL_INVALID_PARAMETER;
    262     } else {
    263       PathName = ShellCommandLineGetRawValue(Package, 1);
    264       if (PathName == NULL) {
    265         CurDir = gEfiShellProtocol->GetCurDir(NULL);
    266         if (CurDir == NULL) {
    267           ShellStatus = SHELL_NOT_FOUND;
    268           ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_CWD), gShellLevel2HiiHandle, L"vol");
    269         } else {
    270           PathName = CurDir;
    271         }
    272       }
    273       if (PathName != NULL) {
    274         TempSpot = StrStr(PathName, L":");
    275         if (TempSpot != NULL) {
    276           *TempSpot = CHAR_NULL;
    277         }
    278         TempSpot = StrStr(PathName, L"\\");
    279         if (TempSpot != NULL) {
    280           *TempSpot = CHAR_NULL;
    281         }
    282         StrnCatGrow(&FullPath, &Length, PathName, 0);
    283         StrnCatGrow(&FullPath, &Length, L":\\", 0);
    284         DeleteMode = ShellCommandLineGetFlag(Package, L"-d");
    285         NewName    = ShellCommandLineGetValue(Package, L"-n");
    286         if (DeleteMode && ShellCommandLineGetFlag(Package, L"-n")) {
    287           ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_CONFLICT), gShellLevel2HiiHandle, L"vol", L"-d", L"-n");
    288           ShellStatus = SHELL_INVALID_PARAMETER;
    289         } else if (ShellCommandLineGetFlag(Package, L"-n") && NewName == NULL) {
    290           ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_VALUE), gShellLevel2HiiHandle, L"vol", L"-n");
    291           ShellStatus = SHELL_INVALID_PARAMETER;
    292         } else if (NewName != NULL && StrLen(NewName) > 11) {
    293           ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM_VAL), gShellLevel2HiiHandle, L"vol", NewName, L"-n");
    294           ShellStatus = SHELL_INVALID_PARAMETER;
    295         } else if (ShellStatus == SHELL_SUCCESS) {
    296           ShellStatus = HandleVol(
    297             FullPath,
    298             DeleteMode,
    299             NewName
    300            );
    301         }
    302       }
    303     }
    304   }
    305 
    306   SHELL_FREE_NON_NULL(FullPath);
    307 
    308   //
    309   // free the command line package
    310   //
    311   ShellCommandLineFreeVarList (Package);
    312 
    313   return (ShellStatus);
    314 }
    315