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