1 /** @file
2 Main file for DmpStore shell Debug1 function.
3
4 (C) Copyright 2013-2015 Hewlett-Packard Development Company, L.P.<BR>
5 Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7
8 **/
9
10 #include "UefiShellDebug1CommandsLib.h"
11
12 typedef enum {
13 DmpStoreDisplay,
14 DmpStoreDelete,
15 DmpStoreSave,
16 DmpStoreLoad
17 } DMP_STORE_TYPE;
18
19 typedef struct {
20 UINT32 Signature;
21 CHAR16 *Name;
22 EFI_GUID Guid;
23 UINT32 Attributes;
24 UINT32 DataSize;
25 UINT8 *Data;
26 LIST_ENTRY Link;
27 } DMP_STORE_VARIABLE;
28
29 #define DMP_STORE_VARIABLE_SIGNATURE SIGNATURE_32 ('_', 'd', 's', 's')
30
31 /**
32 Base on the input attribute value to return the attribute string.
33
34 @param[in] Atts The input attribute value
35
36 @retval The attribute string info.
37 **/
38 CHAR16 *
GetAttrType(IN CONST UINT32 Atts)39 GetAttrType (
40 IN CONST UINT32 Atts
41 )
42 {
43 UINTN BufLen;
44 CHAR16 *RetString;
45
46 BufLen = 0;
47 RetString = NULL;
48
49 if ((Atts & EFI_VARIABLE_NON_VOLATILE) != 0) {
50 StrnCatGrow (&RetString, &BufLen, L"+NV", 0);
51 }
52 if ((Atts & EFI_VARIABLE_RUNTIME_ACCESS) != 0) {
53 StrnCatGrow (&RetString, &BufLen, L"+RT+BS", 0);
54 } else if ((Atts & EFI_VARIABLE_BOOTSERVICE_ACCESS) != 0) {
55 StrnCatGrow (&RetString, &BufLen, L"+BS", 0);
56 }
57 if ((Atts & EFI_VARIABLE_HARDWARE_ERROR_RECORD) != 0) {
58 StrnCatGrow (&RetString, &BufLen, L"+HR", 0);
59 }
60 if ((Atts & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) != 0) {
61 StrnCatGrow (&RetString, &BufLen, L"+AW", 0);
62 }
63 if ((Atts & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) != 0) {
64 StrnCatGrow (&RetString, &BufLen, L"+AT", 0);
65 }
66
67 if (RetString == NULL) {
68 RetString = StrnCatGrow(&RetString, &BufLen, L"Invalid", 0);
69 }
70
71 if ((RetString != NULL) && (RetString[0] == L'+')) {
72 CopyMem(RetString, RetString + 1, StrSize(RetString + 1));
73 }
74
75 return RetString;
76 }
77
78 /**
79 Convert binary to hex format string.
80
81 @param[in] Buffer The binary data.
82 @param[in] BufferSize The size in bytes of the binary data.
83 @param[in, out] HexString Hex format string.
84 @param[in] HexStringSize The size in bytes of the string.
85
86 @return The hex format string.
87 **/
88 CHAR16*
BinaryToHexString(IN VOID * Buffer,IN UINTN BufferSize,IN OUT CHAR16 * HexString,IN UINTN HexStringSize)89 BinaryToHexString (
90 IN VOID *Buffer,
91 IN UINTN BufferSize,
92 IN OUT CHAR16 *HexString,
93 IN UINTN HexStringSize
94 )
95 {
96 UINTN Index;
97 UINTN StringIndex;
98
99 ASSERT (Buffer != NULL);
100 ASSERT ((BufferSize * 2 + 1) * sizeof (CHAR16) <= HexStringSize);
101
102 for (Index = 0, StringIndex = 0; Index < BufferSize; Index += 1) {
103 StringIndex +=
104 UnicodeSPrint (
105 &HexString[StringIndex],
106 HexStringSize - StringIndex * sizeof (CHAR16),
107 L"%02x",
108 ((UINT8 *) Buffer)[Index]
109 );
110 }
111 return HexString;
112 }
113
114 /**
115 Load the variable data from file and set to variable data base.
116
117 @param[in] FileHandle The file to be read.
118 @param[in] Name The name of the variables to be loaded.
119 @param[in] Guid The guid of the variables to be loaded.
120 @param[out] Found TRUE when at least one variable was loaded and set.
121
122 @retval SHELL_DEVICE_ERROR Cannot access the file.
123 @retval SHELL_VOLUME_CORRUPTED The file is in bad format.
124 @retval SHELL_OUT_OF_RESOURCES There is not enough memory to perform the operation.
125 @retval SHELL_SUCCESS Successfully load and set the variables.
126 **/
127 SHELL_STATUS
LoadVariablesFromFile(IN SHELL_FILE_HANDLE FileHandle,IN CONST CHAR16 * Name,IN CONST EFI_GUID * Guid,OUT BOOLEAN * Found)128 LoadVariablesFromFile (
129 IN SHELL_FILE_HANDLE FileHandle,
130 IN CONST CHAR16 *Name,
131 IN CONST EFI_GUID *Guid,
132 OUT BOOLEAN *Found
133 )
134 {
135 EFI_STATUS Status;
136 SHELL_STATUS ShellStatus;
137 UINT32 NameSize;
138 UINT32 DataSize;
139 UINTN BufferSize;
140 UINTN RemainingSize;
141 UINT64 Position;
142 UINT64 FileSize;
143 LIST_ENTRY List;
144 DMP_STORE_VARIABLE *Variable;
145 LIST_ENTRY *Link;
146 CHAR16 *Attributes;
147 UINT8 *Buffer;
148 UINT32 Crc32;
149
150 Status = ShellGetFileSize (FileHandle, &FileSize);
151 if (EFI_ERROR (Status)) {
152 return SHELL_DEVICE_ERROR;
153 }
154
155 ShellStatus = SHELL_SUCCESS;
156
157 InitializeListHead (&List);
158
159 Position = 0;
160 while (Position < FileSize) {
161 //
162 // NameSize
163 //
164 BufferSize = sizeof (NameSize);
165 Status = ShellReadFile (FileHandle, &BufferSize, &NameSize);
166 if (EFI_ERROR (Status) || (BufferSize != sizeof (NameSize))) {
167 ShellStatus = SHELL_VOLUME_CORRUPTED;
168 break;
169 }
170
171 //
172 // DataSize
173 //
174 BufferSize = sizeof (DataSize);
175 Status = ShellReadFile (FileHandle, &BufferSize, &DataSize);
176 if (EFI_ERROR (Status) || (BufferSize != sizeof (DataSize))) {
177 ShellStatus = SHELL_VOLUME_CORRUPTED;
178 break;
179 }
180
181 //
182 // Name, Guid, Attributes, Data, Crc32
183 //
184 RemainingSize = NameSize + sizeof (EFI_GUID) + sizeof (UINT32) + DataSize + sizeof (Crc32);
185 BufferSize = sizeof (NameSize) + sizeof (DataSize) + RemainingSize;
186 Buffer = AllocatePool (BufferSize);
187 if (Buffer == NULL) {
188 ShellStatus = SHELL_OUT_OF_RESOURCES;
189 break;
190 }
191 BufferSize = RemainingSize;
192 Status = ShellReadFile (FileHandle, &BufferSize, (UINT32 *) Buffer + 2);
193 if (EFI_ERROR (Status) || (BufferSize != RemainingSize)) {
194 ShellStatus = SHELL_VOLUME_CORRUPTED;
195 FreePool (Buffer);
196 break;
197 }
198
199 //
200 // Check Crc32
201 //
202 * (UINT32 *) Buffer = NameSize;
203 * ((UINT32 *) Buffer + 1) = DataSize;
204 BufferSize = RemainingSize + sizeof (NameSize) + sizeof (DataSize) - sizeof (Crc32);
205 gBS->CalculateCrc32 (
206 Buffer,
207 BufferSize,
208 &Crc32
209 );
210 if (Crc32 != * (UINT32 *) (Buffer + BufferSize)) {
211 FreePool (Buffer);
212 ShellStatus = SHELL_VOLUME_CORRUPTED;
213 break;
214 }
215
216 Position += BufferSize + sizeof (Crc32);
217
218 Variable = AllocateZeroPool (sizeof (*Variable) + NameSize + DataSize);
219 if (Variable == NULL) {
220 FreePool (Buffer);
221 ShellStatus = SHELL_OUT_OF_RESOURCES;
222 break;
223 }
224 Variable->Signature = DMP_STORE_VARIABLE_SIGNATURE;
225 Variable->Name = (CHAR16 *) (Variable + 1);
226 Variable->DataSize = DataSize;
227 Variable->Data = (UINT8 *) Variable->Name + NameSize;
228 CopyMem (Variable->Name, Buffer + sizeof (NameSize) + sizeof (DataSize), NameSize);
229 CopyMem (&Variable->Guid, Buffer + sizeof (NameSize) + sizeof (DataSize) + NameSize, sizeof (EFI_GUID));
230 CopyMem (&Variable->Attributes, Buffer + sizeof (NameSize) + sizeof (DataSize) + NameSize + sizeof (EFI_GUID), sizeof (UINT32));
231 CopyMem (Variable->Data, Buffer + sizeof (NameSize) + sizeof (DataSize) + NameSize + sizeof (EFI_GUID) + sizeof (UINT32), DataSize);
232
233 InsertTailList (&List, &Variable->Link);
234 FreePool (Buffer);
235 }
236
237 if ((Position != FileSize) || (ShellStatus != SHELL_SUCCESS)) {
238 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_DMPSTORE_LOAD_BAD_FILE), gShellDebug1HiiHandle, L"dmpstore");
239 if (Position != FileSize) {
240 ShellStatus = SHELL_VOLUME_CORRUPTED;
241 }
242 }
243
244 for ( Link = GetFirstNode (&List)
245 ; !IsNull (&List, Link) && (ShellStatus == SHELL_SUCCESS)
246 ; Link = GetNextNode (&List, Link)
247 ) {
248 Variable = CR (Link, DMP_STORE_VARIABLE, Link, DMP_STORE_VARIABLE_SIGNATURE);
249
250 if (((Name == NULL) || gUnicodeCollation->MetaiMatch (gUnicodeCollation, Variable->Name, (CHAR16 *) Name)) &&
251 ((Guid == NULL) || CompareGuid (&Variable->Guid, Guid))
252 ) {
253 Attributes = GetAttrType (Variable->Attributes);
254 ShellPrintHiiEx (
255 -1, -1, NULL, STRING_TOKEN(STR_DMPSTORE_HEADER_LINE), gShellDebug1HiiHandle,
256 Attributes, &Variable->Guid, Variable->Name, Variable->DataSize
257 );
258 SHELL_FREE_NON_NULL(Attributes);
259
260 *Found = TRUE;
261 Status = gRT->SetVariable (
262 Variable->Name,
263 &Variable->Guid,
264 Variable->Attributes,
265 Variable->DataSize,
266 Variable->Data
267 );
268 if (EFI_ERROR (Status)) {
269 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_DMPSTORE_LOAD_GEN_FAIL), gShellDebug1HiiHandle, L"dmpstore", Variable->Name, Status);
270 }
271 }
272 }
273
274 for (Link = GetFirstNode (&List); !IsNull (&List, Link); ) {
275 Variable = CR (Link, DMP_STORE_VARIABLE, Link, DMP_STORE_VARIABLE_SIGNATURE);
276 Link = RemoveEntryList (&Variable->Link);
277 FreePool (Variable);
278 }
279
280 return ShellStatus;
281 }
282
283 /**
284 Append one variable to file.
285
286 @param[in] FileHandle The file to be appended.
287 @param[in] Name The variable name.
288 @param[in] Guid The variable GUID.
289 @param[in] Attributes The variable attributes.
290 @param[in] DataSize The variable data size.
291 @param[in] Data The variable data.
292
293 @retval EFI_OUT_OF_RESOURCES There is not enough memory to perform the operation.
294 @retval EFI_SUCCESS The variable is appended to file successfully.
295 @retval others Failed to append the variable to file.
296 **/
297 EFI_STATUS
AppendSingleVariableToFile(IN SHELL_FILE_HANDLE FileHandle,IN CONST CHAR16 * Name,IN CONST EFI_GUID * Guid,IN UINT32 Attributes,IN UINT32 DataSize,IN CONST UINT8 * Data)298 AppendSingleVariableToFile (
299 IN SHELL_FILE_HANDLE FileHandle,
300 IN CONST CHAR16 *Name,
301 IN CONST EFI_GUID *Guid,
302 IN UINT32 Attributes,
303 IN UINT32 DataSize,
304 IN CONST UINT8 *Data
305 )
306 {
307 UINT32 NameSize;
308 UINT8 *Buffer;
309 UINT8 *Ptr;
310 UINTN BufferSize;
311 EFI_STATUS Status;
312
313 NameSize = (UINT32) StrSize (Name);
314 BufferSize = sizeof (NameSize) + sizeof (DataSize)
315 + sizeof (*Guid)
316 + sizeof (Attributes)
317 + NameSize + DataSize
318 + sizeof (UINT32);
319
320 Buffer = AllocatePool (BufferSize);
321 if (Buffer == NULL) {
322 return EFI_OUT_OF_RESOURCES;
323 }
324
325 Ptr = Buffer;
326 //
327 // NameSize and DataSize
328 //
329 * (UINT32 *) Ptr = NameSize;
330 Ptr += sizeof (NameSize);
331 *(UINT32 *) Ptr = DataSize;
332 Ptr += sizeof (DataSize);
333
334 //
335 // Name
336 //
337 CopyMem (Ptr, Name, NameSize);
338 Ptr += NameSize;
339
340 //
341 // Guid
342 //
343 CopyMem (Ptr, Guid, sizeof (*Guid));
344 Ptr += sizeof (*Guid);
345
346 //
347 // Attributes
348 //
349 * (UINT32 *) Ptr = Attributes;
350 Ptr += sizeof (Attributes);
351
352 //
353 // Data
354 //
355 CopyMem (Ptr, Data, DataSize);
356 Ptr += DataSize;
357
358 //
359 // Crc32
360 //
361 gBS->CalculateCrc32 (Buffer, (UINTN) Ptr - (UINTN) Buffer, (UINT32 *) Ptr);
362
363 Status = ShellWriteFile (FileHandle, &BufferSize, Buffer);
364 FreePool (Buffer);
365
366 if (!EFI_ERROR (Status) &&
367 (BufferSize != sizeof (NameSize) + sizeof (DataSize) + sizeof (*Guid) + sizeof (Attributes) + NameSize + DataSize + sizeof (UINT32))
368 ) {
369 Status = EFI_DEVICE_ERROR;
370 }
371
372 return Status;
373 }
374
375 /**
376 Recursive function to display or delete variables.
377
378 This function will call itself to create a stack-based list of allt he variables to process,
379 then fromt he last to the first, they will do either printing or deleting.
380
381 This is necessary since once a delete happens GetNextVariableName() will work.
382
383 @param[in] Name The variable name of the EFI variable (or NULL).
384 @param[in] Guid The GUID of the variable set (or NULL).
385 @param[in] Type The operation type.
386 @param[in] FileHandle The file to operate on (or NULL).
387 @param[in] PrevName The previous variable name from GetNextVariableName. L"" to start.
388 @param[in] FoundVarGuid The previous GUID from GetNextVariableName. ignored at start.
389 @param[in] FoundOne If a VariableName or Guid was specified and one was printed or
390 deleted, then set this to TRUE, otherwise ignored.
391 @param[in] StandardFormatOutput TRUE indicates Standard-Format Output.
392
393 @retval SHELL_SUCCESS The operation was successful.
394 @retval SHELL_OUT_OF_RESOURCES A memorty allocation failed.
395 @retval SHELL_ABORTED The abort message was received.
396 @retval SHELL_DEVICE_ERROR UEFI Variable Services returned an error.
397 @retval SHELL_NOT_FOUND the Name/Guid pair could not be found.
398 **/
399 SHELL_STATUS
CascadeProcessVariables(IN CONST CHAR16 * Name OPTIONAL,IN CONST EFI_GUID * Guid OPTIONAL,IN DMP_STORE_TYPE Type,IN EFI_FILE_PROTOCOL * FileHandle OPTIONAL,IN CONST CHAR16 * CONST PrevName,IN EFI_GUID FoundVarGuid,IN BOOLEAN * FoundOne,IN BOOLEAN StandardFormatOutput)400 CascadeProcessVariables (
401 IN CONST CHAR16 *Name OPTIONAL,
402 IN CONST EFI_GUID *Guid OPTIONAL,
403 IN DMP_STORE_TYPE Type,
404 IN EFI_FILE_PROTOCOL *FileHandle OPTIONAL,
405 IN CONST CHAR16 * CONST PrevName,
406 IN EFI_GUID FoundVarGuid,
407 IN BOOLEAN *FoundOne,
408 IN BOOLEAN StandardFormatOutput
409 )
410 {
411 EFI_STATUS Status;
412 CHAR16 *FoundVarName;
413 UINT8 *DataBuffer;
414 UINTN DataSize;
415 UINT32 Atts;
416 SHELL_STATUS ShellStatus;
417 UINTN NameSize;
418 CHAR16 *AttrString;
419 CHAR16 *HexString;
420 EFI_STATUS SetStatus;
421 CONST CHAR16 *GuidName;
422
423 if (ShellGetExecutionBreakFlag()) {
424 return (SHELL_ABORTED);
425 }
426
427 NameSize = 0;
428 FoundVarName = NULL;
429
430 if (PrevName!=NULL) {
431 StrnCatGrow(&FoundVarName, &NameSize, PrevName, 0);
432 } else {
433 FoundVarName = AllocateZeroPool(sizeof(CHAR16));
434 NameSize = sizeof(CHAR16);
435 }
436
437 Status = gRT->GetNextVariableName (&NameSize, FoundVarName, &FoundVarGuid);
438 if (Status == EFI_BUFFER_TOO_SMALL) {
439 SHELL_FREE_NON_NULL(FoundVarName);
440 FoundVarName = AllocateZeroPool (NameSize);
441 if (FoundVarName != NULL) {
442 if (PrevName != NULL) {
443 StrnCpyS(FoundVarName, NameSize/sizeof(CHAR16), PrevName, NameSize/sizeof(CHAR16) - 1);
444 }
445
446 Status = gRT->GetNextVariableName (&NameSize, FoundVarName, &FoundVarGuid);
447 } else {
448 Status = EFI_OUT_OF_RESOURCES;
449 }
450 }
451
452 //
453 // No more is fine.
454 //
455 if (Status == EFI_NOT_FOUND) {
456 SHELL_FREE_NON_NULL(FoundVarName);
457 return (SHELL_SUCCESS);
458 } else if (EFI_ERROR(Status)) {
459 SHELL_FREE_NON_NULL(FoundVarName);
460 return (SHELL_DEVICE_ERROR);
461 }
462
463 //
464 // Recurse to the next iteration. We know "our" variable's name.
465 //
466 ShellStatus = CascadeProcessVariables (Name, Guid, Type, FileHandle, FoundVarName, FoundVarGuid, FoundOne, StandardFormatOutput);
467
468 if (ShellGetExecutionBreakFlag() || (ShellStatus == SHELL_ABORTED)) {
469 SHELL_FREE_NON_NULL(FoundVarName);
470 return (SHELL_ABORTED);
471 }
472
473 //
474 // No matter what happened we process our own variable
475 // Only continue if Guid and VariableName are each either NULL or a match
476 //
477 if ( ( Name == NULL
478 || gUnicodeCollation->MetaiMatch(gUnicodeCollation, FoundVarName, (CHAR16*) Name) )
479 && ( Guid == NULL
480 || CompareGuid(&FoundVarGuid, Guid) )
481 ) {
482 DataSize = 0;
483 DataBuffer = NULL;
484 //
485 // do the print or delete
486 //
487 *FoundOne = TRUE;
488 Status = gRT->GetVariable (FoundVarName, &FoundVarGuid, &Atts, &DataSize, DataBuffer);
489 if (Status == EFI_BUFFER_TOO_SMALL) {
490 SHELL_FREE_NON_NULL (DataBuffer);
491 DataBuffer = AllocatePool (DataSize);
492 if (DataBuffer == NULL) {
493 Status = EFI_OUT_OF_RESOURCES;
494 } else {
495 Status = gRT->GetVariable (FoundVarName, &FoundVarGuid, &Atts, &DataSize, DataBuffer);
496 }
497 }
498 //
499 // Last error check then print this variable out.
500 //
501 if (Type == DmpStoreDisplay) {
502 if (!EFI_ERROR(Status) && (DataBuffer != NULL) && (FoundVarName != NULL)) {
503 AttrString = GetAttrType(Atts);
504 if (StandardFormatOutput) {
505 HexString = AllocatePool ((DataSize * 2 + 1) * sizeof (CHAR16));
506 if (HexString != NULL) {
507 ShellPrintHiiEx (
508 -1, -1, NULL, STRING_TOKEN (STR_DMPSTORE_VAR_SFO), gShellDebug1HiiHandle,
509 FoundVarName, &FoundVarGuid, Atts, DataSize,
510 BinaryToHexString (
511 DataBuffer, DataSize, HexString, (DataSize * 2 + 1) * sizeof (CHAR16)
512 )
513 );
514 FreePool (HexString);
515 } else {
516 Status = EFI_OUT_OF_RESOURCES;
517 }
518 } else {
519 Status = gEfiShellProtocol->GetGuidName(&FoundVarGuid, &GuidName);
520 if (EFI_ERROR (Status)) {
521 ShellPrintHiiEx (
522 -1, -1, NULL, STRING_TOKEN (STR_DMPSTORE_HEADER_LINE), gShellDebug1HiiHandle,
523 AttrString, &FoundVarGuid, FoundVarName, DataSize
524 );
525 } else {
526 ShellPrintHiiEx (
527 -1, -1, NULL, STRING_TOKEN (STR_DMPSTORE_HEADER_LINE2), gShellDebug1HiiHandle,
528 AttrString, GuidName, FoundVarName, DataSize
529 );
530 }
531 DumpHex (2, 0, DataSize, DataBuffer);
532 }
533 SHELL_FREE_NON_NULL (AttrString);
534 }
535 } else if (Type == DmpStoreSave) {
536 if (!EFI_ERROR(Status) && (DataBuffer != NULL) && (FoundVarName != NULL)) {
537 AttrString = GetAttrType (Atts);
538 ShellPrintHiiEx (
539 -1, -1, NULL, STRING_TOKEN (STR_DMPSTORE_HEADER_LINE), gShellDebug1HiiHandle,
540 AttrString, &FoundVarGuid, FoundVarName, DataSize
541 );
542 Status = AppendSingleVariableToFile (
543 FileHandle,
544 FoundVarName,
545 &FoundVarGuid,
546 Atts,
547 (UINT32) DataSize,
548 DataBuffer
549 );
550 SHELL_FREE_NON_NULL (AttrString);
551 }
552 } else if (Type == DmpStoreDelete) {
553 //
554 // We only need name to delete it...
555 //
556 SetStatus = gRT->SetVariable (FoundVarName, &FoundVarGuid, Atts, 0, NULL);
557 if (StandardFormatOutput) {
558 if (SetStatus == EFI_SUCCESS) {
559 ShellPrintHiiEx (
560 -1, -1, NULL, STRING_TOKEN (STR_DMPSTORE_NO_VAR_FOUND_NG_SFO), gShellDebug1HiiHandle,
561 FoundVarName, &FoundVarGuid
562 );
563 }
564 } else {
565 ShellPrintHiiEx (
566 -1, -1, NULL, STRING_TOKEN (STR_DMPSTORE_DELETE_LINE), gShellDebug1HiiHandle,
567 &FoundVarGuid, FoundVarName, SetStatus
568 );
569 }
570 }
571 SHELL_FREE_NON_NULL(DataBuffer);
572 }
573
574 SHELL_FREE_NON_NULL(FoundVarName);
575
576 if (Status == EFI_DEVICE_ERROR) {
577 ShellStatus = SHELL_DEVICE_ERROR;
578 } else if (Status == EFI_SECURITY_VIOLATION) {
579 ShellStatus = SHELL_SECURITY_VIOLATION;
580 } else if (EFI_ERROR(Status)) {
581 ShellStatus = SHELL_NOT_READY;
582 }
583
584 return (ShellStatus);
585 }
586
587 /**
588 Function to display or delete variables. This will set up and call into the recursive function.
589
590 @param[in] Name The variable name of the EFI variable (or NULL).
591 @param[in] Guid The GUID of the variable set (or NULL).
592 @param[in] Type The operation type.
593 @param[in] FileHandle The file to save or load variables.
594 @param[in] StandardFormatOutput TRUE indicates Standard-Format Output.
595
596 @retval SHELL_SUCCESS The operation was successful.
597 @retval SHELL_OUT_OF_RESOURCES A memorty allocation failed.
598 @retval SHELL_ABORTED The abort message was received.
599 @retval SHELL_DEVICE_ERROR UEFI Variable Services returned an error.
600 @retval SHELL_NOT_FOUND the Name/Guid pair could not be found.
601 **/
602 SHELL_STATUS
ProcessVariables(IN CONST CHAR16 * Name OPTIONAL,IN CONST EFI_GUID * Guid OPTIONAL,IN DMP_STORE_TYPE Type,IN SHELL_FILE_HANDLE FileHandle OPTIONAL,IN BOOLEAN StandardFormatOutput)603 ProcessVariables (
604 IN CONST CHAR16 *Name OPTIONAL,
605 IN CONST EFI_GUID *Guid OPTIONAL,
606 IN DMP_STORE_TYPE Type,
607 IN SHELL_FILE_HANDLE FileHandle OPTIONAL,
608 IN BOOLEAN StandardFormatOutput
609 )
610 {
611 SHELL_STATUS ShellStatus;
612 BOOLEAN Found;
613 EFI_GUID FoundVarGuid;
614
615 Found = FALSE;
616 ShellStatus = SHELL_SUCCESS;
617 ZeroMem (&FoundVarGuid, sizeof(EFI_GUID));
618
619 if (StandardFormatOutput) {
620 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN(STR_GEN_SFO_HEADER), gShellDebug1HiiHandle, L"dmpstore");
621 }
622
623 if (Type == DmpStoreLoad) {
624 ShellStatus = LoadVariablesFromFile (FileHandle, Name, Guid, &Found);
625 } else {
626 ShellStatus = CascadeProcessVariables (Name, Guid, Type, FileHandle, NULL, FoundVarGuid, &Found, StandardFormatOutput);
627 }
628
629 if (!Found) {
630 if (ShellStatus == SHELL_OUT_OF_RESOURCES) {
631 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_OUT_MEM), gShellDebug1HiiHandle, L"dmpstore");
632 return (ShellStatus);
633 } else if (Name != NULL && Guid == NULL) {
634 if (StandardFormatOutput) {
635 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DMPSTORE_NO_VAR_FOUND_N_SFO), gShellDebug1HiiHandle, Name);
636 } else {
637 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DMPSTORE_NO_VAR_FOUND_N), gShellDebug1HiiHandle, L"dmpstore", Name);
638 }
639 } else if (Name != NULL && Guid != NULL) {
640 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_DMPSTORE_NO_VAR_FOUND_GN), gShellDebug1HiiHandle, L"dmpstore", Guid, Name);
641 } else if (Name == NULL && Guid == NULL) {
642 if (StandardFormatOutput) {
643 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DMPSTORE_NO_VAR_FOUND_SFO), gShellDebug1HiiHandle);
644 } else {
645 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DMPSTORE_NO_VAR_FOUND), gShellDebug1HiiHandle, L"dmpstore");
646 }
647 } else if (Name == NULL && Guid != NULL) {
648 if (StandardFormatOutput) {
649 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DMPSTORE_NO_VAR_FOUND_G_SFO), gShellDebug1HiiHandle, Guid);
650 } else {
651 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DMPSTORE_NO_VAR_FOUND_G), gShellDebug1HiiHandle, L"dmpstore", Guid);
652 }
653 }
654 return (SHELL_NOT_FOUND);
655 }
656 return (ShellStatus);
657 }
658
659 STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
660 {L"-d", TypeFlag},
661 {L"-l", TypeValue},
662 {L"-s", TypeValue},
663 {L"-all", TypeFlag},
664 {L"-guid", TypeValue},
665 {L"-sfo", TypeFlag},
666 {NULL, TypeMax}
667 };
668
669 /**
670 Function for 'dmpstore' command.
671
672 @param[in] ImageHandle Handle to the Image (NULL if Internal).
673 @param[in] SystemTable Pointer to the System Table (NULL if Internal).
674 **/
675 SHELL_STATUS
676 EFIAPI
ShellCommandRunDmpStore(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)677 ShellCommandRunDmpStore (
678 IN EFI_HANDLE ImageHandle,
679 IN EFI_SYSTEM_TABLE *SystemTable
680 )
681 {
682 EFI_STATUS Status;
683 RETURN_STATUS RStatus;
684 LIST_ENTRY *Package;
685 CHAR16 *ProblemParam;
686 SHELL_STATUS ShellStatus;
687 CONST CHAR16 *GuidStr;
688 CONST CHAR16 *File;
689 EFI_GUID *Guid;
690 EFI_GUID GuidData;
691 CONST CHAR16 *Name;
692 DMP_STORE_TYPE Type;
693 SHELL_FILE_HANDLE FileHandle;
694 EFI_FILE_INFO *FileInfo;
695 BOOLEAN StandardFormatOutput;
696
697 ShellStatus = SHELL_SUCCESS;
698 Package = NULL;
699 FileHandle = NULL;
700 File = NULL;
701 Type = DmpStoreDisplay;
702 StandardFormatOutput = FALSE;
703
704 Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);
705 if (EFI_ERROR(Status)) {
706 if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
707 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, L"dmpstore", ProblemParam);
708 FreePool(ProblemParam);
709 ShellStatus = SHELL_INVALID_PARAMETER;
710 } else {
711 ASSERT(FALSE);
712 }
713 } else {
714 if (ShellCommandLineGetCount(Package) > 2) {
715 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle, L"dmpstore");
716 ShellStatus = SHELL_INVALID_PARAMETER;
717 } else if (ShellCommandLineGetFlag(Package, L"-all") && ShellCommandLineGetFlag(Package, L"-guid")) {
718 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_CONFLICT), gShellDebug1HiiHandle, L"dmpstore", L"-all", L"-guid");
719 ShellStatus = SHELL_INVALID_PARAMETER;
720 } else if (ShellCommandLineGetFlag(Package, L"-s") && ShellCommandLineGetFlag(Package, L"-l")) {
721 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_CONFLICT), gShellDebug1HiiHandle, L"dmpstore", L"-l", L"-s");
722 ShellStatus = SHELL_INVALID_PARAMETER;
723 } else if ((ShellCommandLineGetFlag(Package, L"-s") || ShellCommandLineGetFlag(Package, L"-l")) && ShellCommandLineGetFlag(Package, L"-d")) {
724 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_CONFLICT), gShellDebug1HiiHandle, L"dmpstore", L"-l or -s", L"-d");
725 ShellStatus = SHELL_INVALID_PARAMETER;
726 } else if ((ShellCommandLineGetFlag(Package, L"-s") || ShellCommandLineGetFlag(Package, L"-l")) && ShellCommandLineGetFlag(Package, L"-sfo")) {
727 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_CONFLICT), gShellDebug1HiiHandle, L"dmpstore", L"-l or -s", L"-sfo");
728 ShellStatus = SHELL_INVALID_PARAMETER;
729 } else {
730 //
731 // Determine the GUID to search for based on -all and -guid parameters
732 //
733 if (!ShellCommandLineGetFlag(Package, L"-all")) {
734 GuidStr = ShellCommandLineGetValue(Package, L"-guid");
735 if (GuidStr != NULL) {
736 RStatus = StrToGuid (GuidStr, &GuidData);
737 if (RETURN_ERROR (RStatus) || (GuidStr[GUID_STRING_LENGTH] != L'\0')) {
738 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellDebug1HiiHandle, L"dmpstore", GuidStr);
739 ShellStatus = SHELL_INVALID_PARAMETER;
740 }
741 Guid = &GuidData;
742 } else {
743 Guid = &gEfiGlobalVariableGuid;
744 }
745 } else {
746 Guid = NULL;
747 }
748
749 //
750 // Get the Name of the variable to find
751 //
752 Name = ShellCommandLineGetRawValue(Package, 1);
753
754 if (ShellStatus == SHELL_SUCCESS) {
755 if (ShellCommandLineGetFlag(Package, L"-s")) {
756 Type = DmpStoreSave;
757 File = ShellCommandLineGetValue(Package, L"-s");
758 if (File == NULL) {
759 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_VALUE), gShellDebug1HiiHandle, L"dmpstore", L"-s");
760 ShellStatus = SHELL_INVALID_PARAMETER;
761 } else {
762 Status = ShellOpenFileByName (File, &FileHandle, EFI_FILE_MODE_WRITE | EFI_FILE_MODE_READ, 0);
763 if (!EFI_ERROR (Status)) {
764 //
765 // Delete existing file, but do not delete existing directory
766 //
767 FileInfo = ShellGetFileInfo (FileHandle);
768 if (FileInfo == NULL) {
769 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellDebug1HiiHandle, L"dmpstore", File);
770 Status = EFI_DEVICE_ERROR;
771 } else {
772 if ((FileInfo->Attribute & EFI_FILE_DIRECTORY) == EFI_FILE_DIRECTORY) {
773 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_IS_DIRECTORY), gShellDebug1HiiHandle, L"dmpstore", File);
774 Status = EFI_INVALID_PARAMETER;
775 } else {
776 Status = ShellDeleteFile (&FileHandle);
777 if (EFI_ERROR (Status)) {
778 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_DELETE_FAIL), gShellDebug1HiiHandle, L"dmpstore", File);
779 }
780 }
781 FreePool (FileInfo);
782 }
783 } else if (Status == EFI_NOT_FOUND) {
784 //
785 // Good when file doesn't exist
786 //
787 Status = EFI_SUCCESS;
788 } else {
789 //
790 // Otherwise it's bad.
791 //
792 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellDebug1HiiHandle, L"dmpstore", File);
793 }
794
795 if (!EFI_ERROR (Status)) {
796 Status = ShellOpenFileByName (File, &FileHandle, EFI_FILE_MODE_CREATE | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_READ, 0);
797 if (EFI_ERROR (Status)) {
798 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellDebug1HiiHandle, L"dmpstore", File);
799 }
800 }
801
802 if (EFI_ERROR (Status)) {
803 ShellStatus = SHELL_INVALID_PARAMETER;
804 }
805 }
806 } else if (ShellCommandLineGetFlag(Package, L"-l")) {
807 Type = DmpStoreLoad;
808 File = ShellCommandLineGetValue(Package, L"-l");
809 if (File == NULL) {
810 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_VALUE), gShellDebug1HiiHandle, L"dmpstore", L"-l");
811 ShellStatus = SHELL_INVALID_PARAMETER;
812 } else {
813 Status = ShellOpenFileByName (File, &FileHandle, EFI_FILE_MODE_READ, 0);
814 if (EFI_ERROR (Status)) {
815 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellDebug1HiiHandle, L"dmpstore", File);
816 ShellStatus = SHELL_INVALID_PARAMETER;
817 } else {
818 FileInfo = ShellGetFileInfo (FileHandle);
819 if (FileInfo == NULL) {
820 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellDebug1HiiHandle, L"dmpstore", File);
821 ShellStatus = SHELL_DEVICE_ERROR;
822 } else {
823 if ((FileInfo->Attribute & EFI_FILE_DIRECTORY) == EFI_FILE_DIRECTORY) {
824 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_IS_DIRECTORY), gShellDebug1HiiHandle, L"dmpstore", File);
825 ShellStatus = SHELL_INVALID_PARAMETER;
826 }
827 FreePool (FileInfo);
828 }
829 }
830 }
831 } else if (ShellCommandLineGetFlag(Package, L"-d")) {
832 Type = DmpStoreDelete;
833 }
834
835 if (ShellCommandLineGetFlag (Package,L"-sfo")) {
836 StandardFormatOutput = TRUE;
837 }
838 }
839
840 if (ShellStatus == SHELL_SUCCESS) {
841 if (Type == DmpStoreSave) {
842 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DMPSTORE_SAVE), gShellDebug1HiiHandle, File);
843 } else if (Type == DmpStoreLoad) {
844 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DMPSTORE_LOAD), gShellDebug1HiiHandle, File);
845 }
846 ShellStatus = ProcessVariables (Name, Guid, Type, FileHandle, StandardFormatOutput);
847 if ((Type == DmpStoreLoad) || (Type == DmpStoreSave)) {
848 ShellCloseFile (&FileHandle);
849 }
850 }
851 }
852 }
853
854 if (Package != NULL) {
855 ShellCommandLineFreeVarList (Package);
856 }
857 return ShellStatus;
858 }
859
860