ShellPkg/SetVar: Fix typo in comments
[mirror_edk2.git] / ShellPkg / Library / UefiShellDebug1CommandsLib / SetVar.c
CommitLineData
028db58d 1/** @file\r
5d73d92f 2 Main file for SetVar shell Debug1 function.\r
3\r
c011b6c9 4 (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>\r
7f6511ee 5 Copyright (c) 2010 - 2017, Intel Corporation. All rights reserved.<BR>\r
5d73d92f 6 This program and the accompanying materials\r
7 are licensed and made available under the terms and conditions of the BSD License\r
8 which accompanies this distribution. The full text of the license may be found at\r
9 http://opensource.org/licenses/bsd-license.php\r
10\r
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13\r
14**/\r
15\r
16#include "UefiShellDebug1CommandsLib.h"\r
17\r
18STATIC CONST SHELL_PARAM_ITEM ParamList[] = {\r
19 {L"-guid", TypeValue},\r
20 {L"-bs", TypeFlag},\r
21 {L"-rt", TypeFlag},\r
22 {L"-nv", TypeFlag},\r
23 {NULL, TypeMax}\r
24 };\r
25\r
47454e23
CC
26typedef enum {\r
27 DataTypeHexNumber = 0,\r
28 DataTypeHexArray = 1,\r
29 DataTypeAscii = 2,\r
30 DataTypeUnicode = 3,\r
31 DataTypeDevicePath = 4,\r
32 DataTypeUnKnow = 5\r
33} DATA_TYPE;\r
34\r
35typedef union {\r
36 UINT8 HexNumber8;\r
37 UINT16 HexNumber16;\r
38 UINT32 HexNumber32;\r
39 UINT64 HexNumber64;\r
40} HEX_NUMBER;\r
bbf57d4f
LE
41\r
42/**\r
43 Check if the input is a (potentially empty) string of hexadecimal nibbles.\r
44\r
45 @param[in] String The CHAR16 string to check.\r
46\r
47 @retval FALSE A character has been found in String for which\r
48 ShellIsHexaDecimalDigitCharacter() returned FALSE.\r
49\r
50 @retval TRUE Otherwise. (Note that this covers the case when String is\r
51 empty.)\r
52**/\r
53BOOLEAN\r
bbf57d4f
LE
54IsStringOfHexNibbles (\r
55 IN CONST CHAR16 *String\r
56 )\r
57{\r
58 CONST CHAR16 *Pos;\r
59\r
60 for (Pos = String; *Pos != L'\0'; ++Pos) {\r
61 if (!ShellIsHexaDecimalDigitCharacter (*Pos)) {\r
62 return FALSE;\r
63 }\r
64 }\r
65 return TRUE;\r
66}\r
67\r
47454e23
CC
68/**\r
69 Function to check the TYPE of Data.\r
70\r
71 @param[in] Data The Data to be check.\r
72\r
73 @retval DATA_TYPE The TYPE of Data.\r
74**/\r
75DATA_TYPE\r
76TestDataType (\r
77 IN CONST CHAR16 *Data\r
78 )\r
79{\r
80 if (Data[0] == L'0' && (Data[1] == L'x' || Data[1] == L'X')) {\r
81 if (IsStringOfHexNibbles (Data+2) && StrLen (Data + 2) <= 16) {\r
82 return DataTypeHexNumber;\r
83 } else {\r
84 return DataTypeUnKnow;\r
85 }\r
86 } else if (Data[0] == L'H') {\r
87 if (IsStringOfHexNibbles (Data + 1) && StrLen (Data + 1) % 2 == 0) {\r
88 return DataTypeHexArray;\r
89 } else {\r
90 return DataTypeUnKnow;\r
91 }\r
92 } else if (Data[0] == L'S') {\r
93 return DataTypeAscii;\r
94 } else if (Data[0] == L'L') {\r
95 return DataTypeUnicode;\r
96 } else if (Data[0] == L'P' || StrnCmp (Data, L"--", 2) == 0) {\r
97 return DataTypeDevicePath;\r
98 }\r
99\r
100 if (IsStringOfHexNibbles (Data) && StrLen (Data) % 2 == 0) {\r
101 return DataTypeHexArray;\r
102 }\r
103\r
104 return DataTypeAscii;\r
105}\r
106\r
107/**\r
108 Function to parse the Data by the type of Data, and save in the Buffer.\r
109\r
110 @param[in] Data A pointer to a buffer to be parsed.\r
111 @param[out] Buffer A pointer to a buffer to hold the return data.\r
112 @param[in,out] BufferSize On input, indicates the size of Buffer in bytes.\r
113 On output,indicates the size of data return in Buffer.\r
114 Or the size in bytes of the buffer needed to obtain.\r
115\r
116 @retval EFI_INVALID_PARAMETER The Buffer or BufferSize is NULL.\r
117 @retval EFI_BUFFER_TOO_SMALL The Buffer is too small to hold the data.\r
118 @retval EFI_OUT_OF_RESOURCES A memory allcation failed.\r
119 @retval EFI_SUCCESS The Data parsed successful and save in the Buffer.\r
120**/\r
121EFI_STATUS\r
122ParseParameterData (\r
123 IN CONST CHAR16 *Data,\r
124 OUT VOID *Buffer,\r
125 IN OUT UINTN *BufferSize\r
126 )\r
127{\r
128 UINT64 HexNumber;\r
129 UINTN HexNumberLen;\r
130 UINTN Size;\r
131 CHAR8 *AsciiBuffer;\r
132 DATA_TYPE DataType;\r
133 EFI_DEVICE_PATH_PROTOCOL *DevPath;\r
134 EFI_STATUS Status;\r
135\r
136 HexNumber = 0;\r
137 HexNumberLen = 0;\r
138 Size = 0;\r
139 AsciiBuffer = NULL;\r
140 DevPath = NULL;\r
141 Status = EFI_SUCCESS;\r
142\r
143 if (Data == NULL || BufferSize == NULL) {\r
144 return EFI_INVALID_PARAMETER;\r
145 }\r
146\r
147 DataType = TestDataType (Data);\r
148 if (DataType == DataTypeHexNumber) {\r
149 //\r
150 // hex number\r
151 //\r
152 StrHexToUint64S (Data + 2, NULL, &HexNumber);\r
153 HexNumberLen = StrLen (Data + 2);\r
154 if (HexNumberLen >= 1 && HexNumberLen <= 2) {\r
155 Size = 1;\r
156 } else if (HexNumberLen >= 3 && HexNumberLen <= 4) {\r
157 Size = 2;\r
158 } else if (HexNumberLen >= 5 && HexNumberLen <= 8) {\r
159 Size = 4;\r
160 } else if (HexNumberLen >= 9 && HexNumberLen <= 16) {\r
161 Size = 8;\r
162 }\r
163 if (Buffer != NULL && *BufferSize >= Size) {\r
164 CopyMem(Buffer, (VOID *)&HexNumber, Size);\r
165 } else {\r
166 Status = EFI_BUFFER_TOO_SMALL;\r
167 }\r
168 *BufferSize = Size;\r
169 } else if (DataType == DataTypeHexArray) {\r
170 //\r
171 // hex array\r
172 //\r
173 if (*Data == L'H') {\r
174 Data = Data + 1;\r
175 }\r
176\r
177 Size = StrLen (Data) / 2;\r
178 if (Buffer != NULL && *BufferSize >= Size) {\r
179 StrHexToBytes(Data, StrLen (Data), (UINT8 *)Buffer, Size);\r
180 } else {\r
181 Status = EFI_BUFFER_TOO_SMALL;\r
182 }\r
183 *BufferSize = Size;\r
184 } else if (DataType == DataTypeAscii) {\r
185 //\r
186 // ascii text\r
187 //\r
188 if (*Data == L'S') {\r
189 Data = Data + 1;\r
190 }\r
191 AsciiBuffer = AllocateZeroPool (StrSize (Data) / 2);\r
192 if (AsciiBuffer == NULL) {\r
193 Status = EFI_OUT_OF_RESOURCES;\r
194 } else {\r
195 AsciiSPrint (AsciiBuffer, StrSize (Data) / 2, "%s", (CHAR8 *)Data);\r
196\r
197 Size = StrSize (Data) / 2 - 1;\r
198 if (Buffer != NULL && *BufferSize >= Size) {\r
199 CopyMem (Buffer, AsciiBuffer, Size);\r
200 } else {\r
201 Status = EFI_BUFFER_TOO_SMALL;\r
202 }\r
203 *BufferSize = Size;\r
204 }\r
205 SHELL_FREE_NON_NULL (AsciiBuffer);\r
206 } else if (DataType == DataTypeUnicode) {\r
207 //\r
208 // unicode text\r
209 //\r
210 if (*Data == L'L') {\r
211 Data = Data + 1;\r
212 }\r
213 Size = StrSize (Data) - sizeof (CHAR16);\r
214 if (Buffer != NULL && *BufferSize >= Size) {\r
215 CopyMem (Buffer, Data, Size);\r
216 } else {\r
217 Status = EFI_BUFFER_TOO_SMALL;\r
218 }\r
219 *BufferSize = Size;\r
220 } else if (DataType == DataTypeDevicePath) {\r
221 if (*Data == L'P') {\r
222 Data = Data + 1;\r
223 } else if (StrnCmp (Data, L"--", 2) == 0) {\r
224 Data = Data + 2;\r
225 }\r
226 DevPath = ConvertTextToDevicePath (Data);\r
227 if (DevPath == NULL) {\r
228 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_SETVAR_ERROR_DPFT), gShellDebug1HiiHandle, L"setvar");\r
229 Status = EFI_INVALID_PARAMETER;\r
230 } else {\r
231 Size = GetDevicePathSize (DevPath);\r
232 if (Buffer != NULL && *BufferSize >= Size) {\r
233 CopyMem (Buffer, DevPath, Size);\r
234 } else {\r
235 Status = EFI_BUFFER_TOO_SMALL;\r
236 }\r
237 *BufferSize = Size;\r
238 }\r
239 SHELL_FREE_NON_NULL (DevPath);\r
240 } else {\r
241 Status = EFI_INVALID_PARAMETER;\r
242 }\r
243\r
244 return Status;\r
245}\r
246\r
247/**\r
248 Function to get each data from parameters.\r
249\r
6877b9bd 250 @param[in] Package The package of checked values.\r
47454e23
CC
251 @param[out] Buffer A pointer to a buffer to hold the return data.\r
252 @param[out] BufferSize Indicates the size of data in bytes return in Buffer.\r
253\r
254 @retval EFI_INVALID_PARAMETER Buffer or BufferSize is NULL.\r
255 @retval EFI_OUT_OF_RESOURCES A memory allcation failed.\r
256 @retval EFI_SUCCESS Get each parameter data was successful.\r
257**/\r
258EFI_STATUS\r
259GetVariableDataFromParameter (\r
260 IN CONST LIST_ENTRY *Package,\r
261 OUT UINT8 **Buffer,\r
262 OUT UINTN *BufferSize\r
263 )\r
264{\r
265 CONST CHAR16 *TempData;\r
266 UINTN Index;\r
267 UINTN TotalSize;\r
268 UINTN Size;\r
269 UINT8 *BufferWalker;\r
270 EFI_STATUS Status;\r
271\r
272 TotalSize = 0;\r
273 Size = 0;\r
274 Status = EFI_SUCCESS;\r
275\r
276 if (BufferSize == NULL || Buffer == NULL || ShellCommandLineGetCount (Package) < 3) {\r
277 return EFI_INVALID_PARAMETER;\r
278 }\r
279\r
280 for (Index = 2; Index < ShellCommandLineGetCount (Package); Index++) {\r
281 TempData = ShellCommandLineGetRawValue (Package, Index);\r
028db58d 282 ASSERT (TempData != NULL);\r
47454e23
CC
283\r
284 if (TempData[0] != L'=') {\r
285 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellDebug1HiiHandle, L"setvar", TempData);\r
286 return EFI_INVALID_PARAMETER;\r
287 }\r
288\r
289 TempData = TempData + 1;\r
290 Size = 0;\r
291 Status = ParseParameterData (TempData, NULL, &Size);\r
292 if (EFI_ERROR (Status)) {\r
293 if (Status == EFI_BUFFER_TOO_SMALL) {\r
294 //\r
295 // We expect return EFI_BUFFER_TOO_SMALL when pass 'NULL' as second parameter to the function ParseParameterData.\r
296 //\r
297 TotalSize += Size;\r
298 } else {\r
299 if (Status == EFI_INVALID_PARAMETER) {\r
300 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellDebug1HiiHandle, L"setvar", TempData);\r
301 } else if (Status == EFI_NOT_FOUND) {\r
302 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_SETVAR_ERROR_DPFT), gShellDebug1HiiHandle, L"setvar");\r
303 }\r
304 return Status;\r
305 }\r
306 }\r
307 }\r
308\r
309 *BufferSize = TotalSize;\r
310 *Buffer = AllocateZeroPool (TotalSize);\r
311\r
312 if (*Buffer == NULL) {\r
313 Status = EFI_OUT_OF_RESOURCES;\r
314 } else {\r
315 BufferWalker = *Buffer;\r
316 for (Index = 2; Index < ShellCommandLineGetCount (Package); Index++) {\r
317 TempData = ShellCommandLineGetRawValue (Package, Index);\r
318 TempData = TempData + 1;\r
319\r
320 Size = TotalSize;\r
321 Status = ParseParameterData (TempData, (VOID *)BufferWalker, &Size);\r
322 if (!EFI_ERROR (Status)) {\r
323 BufferWalker = BufferWalker + Size;\r
324 TotalSize = TotalSize - Size;\r
325 } else {\r
326 return Status;\r
327 }\r
328 }\r
329 }\r
330\r
331 return EFI_SUCCESS;\r
332}\r
bbf57d4f 333\r
3737ac2b 334/**\r
335 Function for 'setvar' command.\r
336\r
337 @param[in] ImageHandle Handle to the Image (NULL if Internal).\r
338 @param[in] SystemTable Pointer to the System Table (NULL if Internal).\r
339**/\r
5d73d92f 340SHELL_STATUS\r
341EFIAPI\r
342ShellCommandRunSetVar (\r
343 IN EFI_HANDLE ImageHandle,\r
344 IN EFI_SYSTEM_TABLE *SystemTable\r
345 )\r
346{\r
347 EFI_STATUS Status;\r
7f6511ee 348 RETURN_STATUS RStatus;\r
5d73d92f 349 LIST_ENTRY *Package;\r
350 CHAR16 *ProblemParam;\r
351 SHELL_STATUS ShellStatus;\r
352 CONST CHAR16 *VariableName;\r
5d73d92f 353 EFI_GUID Guid;\r
354 CONST CHAR16 *StringGuid;\r
355 UINT32 Attributes;\r
356 VOID *Buffer;\r
357 UINTN Size;\r
358 UINTN LoopVar;\r
5d73d92f 359\r
360 ShellStatus = SHELL_SUCCESS;\r
361 Status = EFI_SUCCESS;\r
362 Buffer = NULL;\r
363 Size = 0;\r
364 Attributes = 0;\r
5d73d92f 365\r
366 //\r
367 // initialize the shell lib (we must be in non-auto-init...)\r
368 //\r
369 Status = ShellInitialize();\r
370 ASSERT_EFI_ERROR(Status);\r
371\r
372 Status = CommandInit();\r
373 ASSERT_EFI_ERROR(Status);\r
374\r
375 //\r
376 // parse the command line\r
377 //\r
378 Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);\r
379 if (EFI_ERROR(Status)) {\r
380 if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {\r
4092a8f6 381 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, L"setvar", ProblemParam); \r
5d73d92f 382 FreePool(ProblemParam);\r
383 ShellStatus = SHELL_INVALID_PARAMETER;\r
384 } else {\r
385 ASSERT(FALSE);\r
386 }\r
387 } else {\r
388 if (ShellCommandLineGetCount(Package) < 2) {\r
4092a8f6 389 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellDebug1HiiHandle, L"setvar"); \r
5d73d92f 390 ShellStatus = SHELL_INVALID_PARAMETER;\r
5d73d92f 391 } else {\r
392 VariableName = ShellCommandLineGetRawValue(Package, 1);\r
5d73d92f 393 if (!ShellCommandLineGetFlag(Package, L"-guid")){\r
394 CopyGuid(&Guid, &gEfiGlobalVariableGuid);\r
395 } else {\r
396 StringGuid = ShellCommandLineGetValue(Package, L"-guid");\r
7f6511ee
RN
397 RStatus = StrToGuid (StringGuid, &Guid);\r
398 if (RETURN_ERROR (RStatus) || (StringGuid[GUID_STRING_LENGTH] != L'\0')) {\r
4092a8f6 399 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellDebug1HiiHandle, L"setvar", StringGuid); \r
3737ac2b 400 ShellStatus = SHELL_INVALID_PARAMETER;\r
5d73d92f 401 }\r
402 }\r
47454e23
CC
403\r
404 if (ShellCommandLineGetCount(Package) == 2) {\r
5d73d92f 405 //\r
47454e23 406 // Display\r
5d73d92f 407 //\r
408 Status = gRT->GetVariable((CHAR16*)VariableName, &Guid, &Attributes, &Size, Buffer);\r
409 if (Status == EFI_BUFFER_TOO_SMALL) {\r
3737ac2b 410 Buffer = AllocateZeroPool(Size);\r
5d73d92f 411 Status = gRT->GetVariable((CHAR16*)VariableName, &Guid, &Attributes, &Size, Buffer);\r
412 }\r
47454e23
CC
413 if (!EFI_ERROR(Status) && Buffer != NULL) {\r
414 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN(STR_SETVAR_PRINT), gShellDebug1HiiHandle, &Guid, VariableName, Size);\r
415 for (LoopVar = 0; LoopVar < Size; LoopVar++) {\r
5d73d92f 416 ShellPrintEx(-1, -1, L"%02x ", ((UINT8*)Buffer)[LoopVar]);\r
417 }\r
418 ShellPrintEx(-1, -1, L"\r\n");\r
419 } else {\r
47454e23 420 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SETVAR_ERROR_GET), gShellDebug1HiiHandle, L"setvar", &Guid, VariableName);\r
5d73d92f 421 ShellStatus = SHELL_ACCESS_DENIED;\r
5d73d92f 422 }\r
423 } else {\r
5d73d92f 424 //\r
47454e23 425 // Create, Delete or Modify.\r
475387e9
JC
426 //\r
427 Status = gRT->GetVariable((CHAR16*)VariableName, &Guid, &Attributes, &Size, Buffer);\r
428 if (Status == EFI_BUFFER_TOO_SMALL) {\r
429 Buffer = AllocateZeroPool(Size);\r
430 Status = gRT->GetVariable((CHAR16*)VariableName, &Guid, &Attributes, &Size, Buffer);\r
5d73d92f 431 }\r
475387e9
JC
432 if (EFI_ERROR(Status) || Buffer == NULL) {\r
433 //\r
434 // Creating a new variable. determine attributes from command line.\r
435 //\r
436 Attributes = 0;\r
437 if (ShellCommandLineGetFlag(Package, L"-bs")) {\r
438 Attributes |= EFI_VARIABLE_BOOTSERVICE_ACCESS;\r
439 }\r
440 if (ShellCommandLineGetFlag(Package, L"-rt")) {\r
441 Attributes |= EFI_VARIABLE_RUNTIME_ACCESS |\r
442 EFI_VARIABLE_BOOTSERVICE_ACCESS;\r
443 }\r
444 if (ShellCommandLineGetFlag(Package, L"-nv")) {\r
445 Attributes |= EFI_VARIABLE_NON_VOLATILE;\r
446 }\r
5d73d92f 447 }\r
475387e9
JC
448 SHELL_FREE_NON_NULL(Buffer);\r
449\r
47454e23
CC
450 Size = 0;\r
451 Status = GetVariableDataFromParameter(Package, (UINT8 **)&Buffer, &Size);\r
452 if (!EFI_ERROR(Status)) {\r
453 Status = gRT->SetVariable((CHAR16*)VariableName, &Guid, Attributes, Size, Buffer);\r
454 }\r
455 if (EFI_ERROR(Status)) {\r
456 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN(STR_SETVAR_ERROR_SET), gShellDebug1HiiHandle, L"setvar", &Guid, VariableName);\r
457 ShellStatus = SHELL_ACCESS_DENIED;\r
5d73d92f 458 } else {\r
47454e23 459 ASSERT(ShellStatus == SHELL_SUCCESS);\r
5d73d92f 460 }\r
461 }\r
462 }\r
463 ShellCommandLineFreeVarList (Package);\r
464 }\r
465\r
466 if (Buffer != NULL) {\r
467 FreePool(Buffer);\r
468 }\r
469\r
5d73d92f 470 return (ShellStatus);\r
471}\r