2 Main file for SetVar shell Debug1 function.
4 (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
5 Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
10 #include "UefiShellDebug1CommandsLib.h"
12 STATIC CONST SHELL_PARAM_ITEM ParamList
[] = {
13 { L
"-guid", TypeValue
},
21 DataTypeHexNumber
= 0,
25 DataTypeDevicePath
= 4,
37 Check if the input is a (potentially empty) string of hexadecimal nibbles.
39 @param[in] String The CHAR16 string to check.
41 @retval FALSE A character has been found in String for which
42 ShellIsHexaDecimalDigitCharacter() returned FALSE.
44 @retval TRUE Otherwise. (Note that this covers the case when String is
48 IsStringOfHexNibbles (
49 IN CONST CHAR16
*String
54 for (Pos
= String
; *Pos
!= L
'\0'; ++Pos
) {
55 if (!ShellIsHexaDecimalDigitCharacter (*Pos
)) {
64 Function to check the TYPE of Data.
66 @param[in] Data The Data to be check.
68 @retval DATA_TYPE The TYPE of Data.
75 if ((Data
[0] == L
'0') && ((Data
[1] == L
'x') || (Data
[1] == L
'X'))) {
76 if (IsStringOfHexNibbles (Data
+2) && (StrLen (Data
+ 2) <= 16)) {
77 return DataTypeHexNumber
;
79 return DataTypeUnKnow
;
81 } else if (Data
[0] == L
'H') {
82 if (IsStringOfHexNibbles (Data
+ 1) && (StrLen (Data
+ 1) % 2 == 0)) {
83 return DataTypeHexArray
;
85 return DataTypeUnKnow
;
87 } else if (Data
[0] == L
'S') {
89 } else if (Data
[0] == L
'L') {
90 return DataTypeUnicode
;
91 } else if ((Data
[0] == L
'P') || (StrnCmp (Data
, L
"--", 2) == 0)) {
92 return DataTypeDevicePath
;
95 if (IsStringOfHexNibbles (Data
) && (StrLen (Data
) % 2 == 0)) {
96 return DataTypeHexArray
;
103 Function to parse the Data by the type of Data, and save in the Buffer.
105 @param[in] Data A pointer to a buffer to be parsed.
106 @param[out] Buffer A pointer to a buffer to hold the return data.
107 @param[in,out] BufferSize On input, indicates the size of Buffer in bytes.
108 On output,indicates the size of data return in Buffer.
109 Or the size in bytes of the buffer needed to obtain.
111 @retval EFI_INVALID_PARAMETER The Buffer or BufferSize is NULL.
112 @retval EFI_BUFFER_TOO_SMALL The Buffer is too small to hold the data.
113 @retval EFI_OUT_OF_RESOURCES A memory allcation failed.
114 @retval EFI_SUCCESS The Data parsed successful and save in the Buffer.
118 IN CONST CHAR16
*Data
,
120 IN OUT UINTN
*BufferSize
128 EFI_DEVICE_PATH_PROTOCOL
*DevPath
;
136 Status
= EFI_SUCCESS
;
138 if ((Data
== NULL
) || (BufferSize
== NULL
)) {
139 return EFI_INVALID_PARAMETER
;
142 DataType
= TestDataType (Data
);
143 if (DataType
== DataTypeHexNumber
) {
147 StrHexToUint64S (Data
+ 2, NULL
, &HexNumber
);
148 HexNumberLen
= StrLen (Data
+ 2);
149 if ((HexNumberLen
>= 1) && (HexNumberLen
<= 2)) {
151 } else if ((HexNumberLen
>= 3) && (HexNumberLen
<= 4)) {
153 } else if ((HexNumberLen
>= 5) && (HexNumberLen
<= 8)) {
155 } else if ((HexNumberLen
>= 9) && (HexNumberLen
<= 16)) {
159 if ((Buffer
!= NULL
) && (*BufferSize
>= Size
)) {
160 CopyMem (Buffer
, (VOID
*)&HexNumber
, Size
);
162 Status
= EFI_BUFFER_TOO_SMALL
;
166 } else if (DataType
== DataTypeHexArray
) {
174 Size
= StrLen (Data
) / 2;
175 if ((Buffer
!= NULL
) && (*BufferSize
>= Size
)) {
176 StrHexToBytes (Data
, StrLen (Data
), (UINT8
*)Buffer
, Size
);
178 Status
= EFI_BUFFER_TOO_SMALL
;
182 } else if (DataType
== DataTypeAscii
) {
190 AsciiBuffer
= AllocateZeroPool (StrSize (Data
) / 2);
191 if (AsciiBuffer
== NULL
) {
192 Status
= EFI_OUT_OF_RESOURCES
;
194 AsciiSPrint (AsciiBuffer
, StrSize (Data
) / 2, "%s", (CHAR8
*)Data
);
196 Size
= StrSize (Data
) / 2 - 1;
197 if ((Buffer
!= NULL
) && (*BufferSize
>= Size
)) {
198 CopyMem (Buffer
, AsciiBuffer
, Size
);
200 Status
= EFI_BUFFER_TOO_SMALL
;
206 SHELL_FREE_NON_NULL (AsciiBuffer
);
207 } else if (DataType
== DataTypeUnicode
) {
215 Size
= StrSize (Data
) - sizeof (CHAR16
);
216 if ((Buffer
!= NULL
) && (*BufferSize
>= Size
)) {
217 CopyMem (Buffer
, Data
, Size
);
219 Status
= EFI_BUFFER_TOO_SMALL
;
223 } else if (DataType
== DataTypeDevicePath
) {
226 } else if (StrnCmp (Data
, L
"--", 2) == 0) {
230 DevPath
= ConvertTextToDevicePath (Data
);
231 if (DevPath
== NULL
) {
232 ShellPrintHiiEx (-1, -1, NULL
, STRING_TOKEN (STR_SETVAR_ERROR_DPFT
), gShellDebug1HiiHandle
, L
"setvar");
233 Status
= EFI_INVALID_PARAMETER
;
235 Size
= GetDevicePathSize (DevPath
);
236 if ((Buffer
!= NULL
) && (*BufferSize
>= Size
)) {
237 CopyMem (Buffer
, DevPath
, Size
);
239 Status
= EFI_BUFFER_TOO_SMALL
;
245 SHELL_FREE_NON_NULL (DevPath
);
247 Status
= EFI_INVALID_PARAMETER
;
254 Function to get each data from parameters.
256 @param[in] Package The package of checked values.
257 @param[out] Buffer A pointer to a buffer to hold the return data.
258 @param[out] BufferSize Indicates the size of data in bytes return in Buffer.
260 @retval EFI_INVALID_PARAMETER Buffer or BufferSize is NULL.
261 @retval EFI_OUT_OF_RESOURCES A memory allcation failed.
262 @retval EFI_SUCCESS Get each parameter data was successful.
265 GetVariableDataFromParameter (
266 IN CONST LIST_ENTRY
*Package
,
268 OUT UINTN
*BufferSize
271 CONST CHAR16
*TempData
;
280 Status
= EFI_SUCCESS
;
282 if ((BufferSize
== NULL
) || (Buffer
== NULL
) || (ShellCommandLineGetCount (Package
) < 3)) {
283 return EFI_INVALID_PARAMETER
;
286 for (Index
= 2; Index
< ShellCommandLineGetCount (Package
); Index
++) {
287 TempData
= ShellCommandLineGetRawValue (Package
, Index
);
288 ASSERT (TempData
!= NULL
);
290 if (TempData
[0] != L
'=') {
291 ShellPrintHiiEx (-1, -1, NULL
, STRING_TOKEN (STR_GEN_PARAM_INV
), gShellDebug1HiiHandle
, L
"setvar", TempData
);
292 return EFI_INVALID_PARAMETER
;
295 TempData
= TempData
+ 1;
297 Status
= ParseParameterData (TempData
, NULL
, &Size
);
298 if (EFI_ERROR (Status
)) {
299 if (Status
== EFI_BUFFER_TOO_SMALL
) {
301 // We expect return EFI_BUFFER_TOO_SMALL when pass 'NULL' as second parameter to the function ParseParameterData.
305 if (Status
== EFI_INVALID_PARAMETER
) {
306 ShellPrintHiiEx (-1, -1, NULL
, STRING_TOKEN (STR_GEN_PARAM_INV
), gShellDebug1HiiHandle
, L
"setvar", TempData
);
307 } else if (Status
== EFI_NOT_FOUND
) {
308 ShellPrintHiiEx (-1, -1, NULL
, STRING_TOKEN (STR_SETVAR_ERROR_DPFT
), gShellDebug1HiiHandle
, L
"setvar");
316 *BufferSize
= TotalSize
;
317 *Buffer
= AllocateZeroPool (TotalSize
);
319 if (*Buffer
== NULL
) {
320 Status
= EFI_OUT_OF_RESOURCES
;
322 BufferWalker
= *Buffer
;
323 for (Index
= 2; Index
< ShellCommandLineGetCount (Package
); Index
++) {
324 TempData
= ShellCommandLineGetRawValue (Package
, Index
);
325 TempData
= TempData
+ 1;
328 Status
= ParseParameterData (TempData
, (VOID
*)BufferWalker
, &Size
);
329 if (!EFI_ERROR (Status
)) {
330 BufferWalker
= BufferWalker
+ Size
;
331 TotalSize
= TotalSize
- Size
;
342 Function for 'setvar' command.
344 @param[in] ImageHandle Handle to the Image (NULL if Internal).
345 @param[in] SystemTable Pointer to the System Table (NULL if Internal).
349 ShellCommandRunSetVar (
350 IN EFI_HANDLE ImageHandle
,
351 IN EFI_SYSTEM_TABLE
*SystemTable
355 RETURN_STATUS RStatus
;
357 CHAR16
*ProblemParam
;
358 SHELL_STATUS ShellStatus
;
359 CONST CHAR16
*VariableName
;
361 CONST CHAR16
*StringGuid
;
367 ShellStatus
= SHELL_SUCCESS
;
368 Status
= EFI_SUCCESS
;
374 // initialize the shell lib (we must be in non-auto-init...)
376 Status
= ShellInitialize ();
377 ASSERT_EFI_ERROR (Status
);
379 Status
= CommandInit ();
380 ASSERT_EFI_ERROR (Status
);
383 // parse the command line
385 Status
= ShellCommandLineParse (ParamList
, &Package
, &ProblemParam
, TRUE
);
386 if (EFI_ERROR (Status
)) {
387 if ((Status
== EFI_VOLUME_CORRUPTED
) && (ProblemParam
!= NULL
)) {
388 ShellPrintHiiEx (-1, -1, NULL
, STRING_TOKEN (STR_GEN_PROBLEM
), gShellDebug1HiiHandle
, L
"setvar", ProblemParam
);
389 FreePool (ProblemParam
);
390 ShellStatus
= SHELL_INVALID_PARAMETER
;
394 } else if (ShellCommandLineCheckDuplicate (Package
, &ProblemParam
) != EFI_SUCCESS
) {
395 ShellPrintHiiEx (-1, -1, NULL
, STRING_TOKEN (STR_GEN_DUPLICATE
), gShellDebug1HiiHandle
, L
"setvar", ProblemParam
);
396 FreePool (ProblemParam
);
397 ShellStatus
= SHELL_INVALID_PARAMETER
;
399 if (ShellCommandLineGetCount (Package
) < 2) {
400 ShellPrintHiiEx (-1, -1, NULL
, STRING_TOKEN (STR_GEN_TOO_FEW
), gShellDebug1HiiHandle
, L
"setvar");
401 ShellStatus
= SHELL_INVALID_PARAMETER
;
403 VariableName
= ShellCommandLineGetRawValue (Package
, 1);
404 if (!ShellCommandLineGetFlag (Package
, L
"-guid")) {
405 CopyGuid (&Guid
, &gEfiGlobalVariableGuid
);
407 StringGuid
= ShellCommandLineGetValue (Package
, L
"-guid");
408 RStatus
= StrToGuid (StringGuid
, &Guid
);
409 if (RETURN_ERROR (RStatus
) || (StringGuid
[GUID_STRING_LENGTH
] != L
'\0')) {
410 ShellPrintHiiEx (-1, -1, NULL
, STRING_TOKEN (STR_GEN_PARAM_INV
), gShellDebug1HiiHandle
, L
"setvar", StringGuid
);
411 ShellStatus
= SHELL_INVALID_PARAMETER
;
415 if (ShellCommandLineGetCount (Package
) == 2) {
419 Status
= gRT
->GetVariable ((CHAR16
*)VariableName
, &Guid
, &Attributes
, &Size
, Buffer
);
420 if (Status
== EFI_BUFFER_TOO_SMALL
) {
421 Buffer
= AllocateZeroPool (Size
);
422 Status
= gRT
->GetVariable ((CHAR16
*)VariableName
, &Guid
, &Attributes
, &Size
, Buffer
);
425 if (!EFI_ERROR (Status
) && (Buffer
!= NULL
)) {
426 ShellPrintHiiEx (-1, -1, NULL
, STRING_TOKEN (STR_SETVAR_PRINT
), gShellDebug1HiiHandle
, &Guid
, VariableName
, Size
);
427 for (LoopVar
= 0; LoopVar
< Size
; LoopVar
++) {
428 ShellPrintEx (-1, -1, L
"%02x ", ((UINT8
*)Buffer
)[LoopVar
]);
431 ShellPrintEx (-1, -1, L
"\r\n");
433 ShellPrintHiiEx (-1, -1, NULL
, STRING_TOKEN (STR_SETVAR_ERROR_GET
), gShellDebug1HiiHandle
, L
"setvar", &Guid
, VariableName
);
434 ShellStatus
= SHELL_ACCESS_DENIED
;
438 // Create, Delete or Modify.
440 Status
= gRT
->GetVariable ((CHAR16
*)VariableName
, &Guid
, &Attributes
, &Size
, Buffer
);
441 if (Status
== EFI_BUFFER_TOO_SMALL
) {
442 Buffer
= AllocateZeroPool (Size
);
443 Status
= gRT
->GetVariable ((CHAR16
*)VariableName
, &Guid
, &Attributes
, &Size
, Buffer
);
446 if (EFI_ERROR (Status
) || (Buffer
== NULL
)) {
448 // Creating a new variable. determine attributes from command line.
451 if (ShellCommandLineGetFlag (Package
, L
"-bs")) {
452 Attributes
|= EFI_VARIABLE_BOOTSERVICE_ACCESS
;
455 if (ShellCommandLineGetFlag (Package
, L
"-rt")) {
456 Attributes
|= EFI_VARIABLE_RUNTIME_ACCESS
|
457 EFI_VARIABLE_BOOTSERVICE_ACCESS
;
460 if (ShellCommandLineGetFlag (Package
, L
"-nv")) {
461 Attributes
|= EFI_VARIABLE_NON_VOLATILE
;
465 SHELL_FREE_NON_NULL (Buffer
);
468 Status
= GetVariableDataFromParameter (Package
, (UINT8
**)&Buffer
, &Size
);
469 if (!EFI_ERROR (Status
)) {
470 Status
= gRT
->SetVariable ((CHAR16
*)VariableName
, &Guid
, Attributes
, Size
, Buffer
);
473 if (EFI_ERROR (Status
)) {
474 ShellPrintHiiEx (-1, -1, NULL
, STRING_TOKEN (STR_SETVAR_ERROR_SET
), gShellDebug1HiiHandle
, L
"setvar", &Guid
, VariableName
);
475 ShellStatus
= SHELL_ACCESS_DENIED
;
477 ASSERT (ShellStatus
== SHELL_SUCCESS
);
482 ShellCommandLineFreeVarList (Package
);
485 if (Buffer
!= NULL
) {
489 return (ShellStatus
);