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