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