VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/FirmwareNew/ShellPkg/Library/UefiShellDebug1CommandsLib/SetVar.c@ 108794

Last change on this file since 108794 was 108794, checked in by vboxsync, 2 weeks ago

Devices/EFI/FirmwareNew: Merge edk2-stable202502 from the vendor branch and make it build for the important platforms, bugref:4643

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

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette