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