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