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