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