]> git.proxmox.com Git - mirror_edk2.git/blob - ShellPkg/Library/UefiShellDebug1CommandsLib/DmpStore.c
ShellPkg/UefiShellDebug1CommandsLib: Remove unnecessary EFIAPI
[mirror_edk2.git] / ShellPkg / Library / UefiShellDebug1CommandsLib / DmpStore.c
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 - 2015, 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 *
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 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, L"dmpstore");
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, L"dmpstore", 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 + sizeof (UINT32))
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 CascadeProcessVariables (
370 IN CONST CHAR16 *Name OPTIONAL,
371 IN CONST EFI_GUID *Guid OPTIONAL,
372 IN DMP_STORE_TYPE Type,
373 IN EFI_FILE_PROTOCOL *FileHandle OPTIONAL,
374 IN CONST CHAR16 * CONST PrevName,
375 IN EFI_GUID FoundVarGuid,
376 IN BOOLEAN *FoundOne
377 )
378 {
379 EFI_STATUS Status;
380 CHAR16 *FoundVarName;
381 UINT8 *DataBuffer;
382 UINTN DataSize;
383 UINT32 Atts;
384 SHELL_STATUS ShellStatus;
385 UINTN NameSize;
386 CHAR16 *RetString;
387
388 if (ShellGetExecutionBreakFlag()) {
389 return (SHELL_ABORTED);
390 }
391
392 NameSize = 0;
393 FoundVarName = NULL;
394
395 if (PrevName!=NULL) {
396 StrnCatGrow(&FoundVarName, &NameSize, PrevName, 0);
397 } else {
398 FoundVarName = AllocateZeroPool(sizeof(CHAR16));
399 }
400
401 Status = gRT->GetNextVariableName (&NameSize, FoundVarName, &FoundVarGuid);
402 if (Status == EFI_BUFFER_TOO_SMALL) {
403 SHELL_FREE_NON_NULL(FoundVarName);
404 FoundVarName = AllocateZeroPool (NameSize);
405 if (FoundVarName != NULL) {
406 if (PrevName != NULL) {
407 StrnCpyS(FoundVarName, NameSize/sizeof(CHAR16), PrevName, NameSize/sizeof(CHAR16) - 1);
408 }
409
410 Status = gRT->GetNextVariableName (&NameSize, FoundVarName, &FoundVarGuid);
411 } else {
412 Status = EFI_OUT_OF_RESOURCES;
413 }
414 }
415
416 //
417 // No more is fine.
418 //
419 if (Status == EFI_NOT_FOUND) {
420 SHELL_FREE_NON_NULL(FoundVarName);
421 return (SHELL_SUCCESS);
422 } else if (EFI_ERROR(Status)) {
423 SHELL_FREE_NON_NULL(FoundVarName);
424 return (SHELL_DEVICE_ERROR);
425 }
426
427 //
428 // Recurse to the next iteration. We know "our" variable's name.
429 //
430 ShellStatus = CascadeProcessVariables(Name, Guid, Type, FileHandle, FoundVarName, FoundVarGuid, FoundOne);
431
432 if (ShellGetExecutionBreakFlag() || (ShellStatus == SHELL_ABORTED)) {
433 SHELL_FREE_NON_NULL(FoundVarName);
434 return (SHELL_ABORTED);
435 }
436
437 //
438 // No matter what happened we process our own variable
439 // Only continue if Guid and VariableName are each either NULL or a match
440 //
441 if ( ( Name == NULL
442 || gUnicodeCollation->MetaiMatch(gUnicodeCollation, FoundVarName, (CHAR16*) Name) )
443 && ( Guid == NULL
444 || CompareGuid(&FoundVarGuid, Guid) )
445 ) {
446 DataSize = 0;
447 DataBuffer = NULL;
448 //
449 // do the print or delete
450 //
451 *FoundOne = TRUE;
452 Status = gRT->GetVariable (FoundVarName, &FoundVarGuid, &Atts, &DataSize, DataBuffer);
453 if (Status == EFI_BUFFER_TOO_SMALL) {
454 SHELL_FREE_NON_NULL (DataBuffer);
455 DataBuffer = AllocatePool (DataSize);
456 if (DataBuffer == NULL) {
457 Status = EFI_OUT_OF_RESOURCES;
458 } else {
459 Status = gRT->GetVariable (FoundVarName, &FoundVarGuid, &Atts, &DataSize, DataBuffer);
460 }
461 }
462 if ((Type == DmpStoreDisplay) || (Type == DmpStoreSave)) {
463 //
464 // Last error check then print this variable out.
465 //
466 if (!EFI_ERROR(Status) && (DataBuffer != NULL) && (FoundVarName != NULL)) {
467 RetString = GetAttrType(Atts);
468 ShellPrintHiiEx(
469 -1,
470 -1,
471 NULL,
472 STRING_TOKEN(STR_DMPSTORE_HEADER_LINE),
473 gShellDebug1HiiHandle,
474 RetString,
475 &FoundVarGuid,
476 FoundVarName,
477 DataSize);
478 if (Type == DmpStoreDisplay) {
479 DumpHex(2, 0, DataSize, DataBuffer);
480 } else {
481 Status = AppendSingleVariableToFile (
482 FileHandle,
483 FoundVarName,
484 &FoundVarGuid,
485 Atts,
486 (UINT32) DataSize,
487 DataBuffer
488 );
489 }
490 SHELL_FREE_NON_NULL(RetString);
491 }
492 } else if (Type == DmpStoreDelete) {
493 //
494 // We only need name to delete it...
495 //
496 ShellPrintHiiEx (
497 -1,
498 -1,
499 NULL,
500 STRING_TOKEN(STR_DMPSTORE_DELETE_LINE),
501 gShellDebug1HiiHandle,
502 &FoundVarGuid,
503 FoundVarName,
504 gRT->SetVariable (FoundVarName, &FoundVarGuid, Atts, 0, NULL)
505 );
506 }
507 SHELL_FREE_NON_NULL(DataBuffer);
508 }
509
510 SHELL_FREE_NON_NULL(FoundVarName);
511
512 if (Status == EFI_DEVICE_ERROR) {
513 ShellStatus = SHELL_DEVICE_ERROR;
514 } else if (Status == EFI_SECURITY_VIOLATION) {
515 ShellStatus = SHELL_SECURITY_VIOLATION;
516 } else if (EFI_ERROR(Status)) {
517 ShellStatus = SHELL_NOT_READY;
518 }
519
520 return (ShellStatus);
521 }
522
523 /**
524 Function to display or delete variables. This will set up and call into the recursive function.
525
526 @param[in] Name The variable name of the EFI variable (or NULL).
527 @param[in] Guid The GUID of the variable set (or NULL).
528 @param[in] Type The operation type.
529 @param[in] FileHandle The file to save or load variables.
530
531 @retval SHELL_SUCCESS The operation was successful.
532 @retval SHELL_OUT_OF_RESOURCES A memorty allocation failed.
533 @retval SHELL_ABORTED The abort message was received.
534 @retval SHELL_DEVICE_ERROR UEFI Variable Services returned an error.
535 @retval SHELL_NOT_FOUND the Name/Guid pair could not be found.
536 **/
537 SHELL_STATUS
538 ProcessVariables (
539 IN CONST CHAR16 *Name OPTIONAL,
540 IN CONST EFI_GUID *Guid OPTIONAL,
541 IN DMP_STORE_TYPE Type,
542 IN SHELL_FILE_HANDLE FileHandle OPTIONAL
543 )
544 {
545 SHELL_STATUS ShellStatus;
546 BOOLEAN Found;
547 EFI_GUID FoundVarGuid;
548
549 Found = FALSE;
550 ShellStatus = SHELL_SUCCESS;
551 ZeroMem (&FoundVarGuid, sizeof(EFI_GUID));
552
553 if (Type == DmpStoreLoad) {
554 ShellStatus = LoadVariablesFromFile (FileHandle, Name, Guid, &Found);
555 } else {
556 ShellStatus = CascadeProcessVariables(Name, Guid, Type, FileHandle, NULL, FoundVarGuid, &Found);
557 }
558
559 if (!Found) {
560 if (ShellStatus == SHELL_OUT_OF_RESOURCES) {
561 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_OUT_MEM), gShellDebug1HiiHandle, L"dmpstore");
562 return (ShellStatus);
563 } else if (Name != NULL && Guid == NULL) {
564 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_DMPSTORE_NO_VAR_FOUND_N), gShellDebug1HiiHandle, L"dmpstore", Name);
565 } else if (Name != NULL && Guid != NULL) {
566 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_DMPSTORE_NO_VAR_FOUND_GN), gShellDebug1HiiHandle, L"dmpstore", Guid, Name);
567 } else if (Name == NULL && Guid == NULL) {
568 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_DMPSTORE_NO_VAR_FOUND), gShellDebug1HiiHandle, L"dmpstore");
569 } else if (Name == NULL && Guid != NULL) {
570 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_DMPSTORE_NO_VAR_FOUND_G), gShellDebug1HiiHandle, L"dmpstore", Guid);
571 }
572 return (SHELL_NOT_FOUND);
573 }
574 return (ShellStatus);
575 }
576
577 STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
578 {L"-d", TypeFlag},
579 {L"-l", TypeValue},
580 {L"-s", TypeValue},
581 {L"-all", TypeFlag},
582 {L"-guid", TypeValue},
583 {NULL, TypeMax}
584 };
585
586 /**
587 Function for 'dmpstore' command.
588
589 @param[in] ImageHandle Handle to the Image (NULL if Internal).
590 @param[in] SystemTable Pointer to the System Table (NULL if Internal).
591 **/
592 SHELL_STATUS
593 EFIAPI
594 ShellCommandRunDmpStore (
595 IN EFI_HANDLE ImageHandle,
596 IN EFI_SYSTEM_TABLE *SystemTable
597 )
598 {
599 EFI_STATUS Status;
600 LIST_ENTRY *Package;
601 CHAR16 *ProblemParam;
602 SHELL_STATUS ShellStatus;
603 CONST CHAR16 *GuidStr;
604 CONST CHAR16 *File;
605 EFI_GUID *Guid;
606 EFI_GUID GuidData;
607 CONST CHAR16 *Name;
608 DMP_STORE_TYPE Type;
609 SHELL_FILE_HANDLE FileHandle;
610 EFI_FILE_INFO *FileInfo;
611
612 ShellStatus = SHELL_SUCCESS;
613 Package = NULL;
614 FileHandle = NULL;
615 File = NULL;
616 Type = DmpStoreDisplay;
617
618 Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);
619 if (EFI_ERROR(Status)) {
620 if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
621 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, L"dmpstore", ProblemParam);
622 FreePool(ProblemParam);
623 ShellStatus = SHELL_INVALID_PARAMETER;
624 } else {
625 ASSERT(FALSE);
626 }
627 } else {
628 if (ShellCommandLineGetCount(Package) > 2) {
629 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle, L"dmpstore");
630 ShellStatus = SHELL_INVALID_PARAMETER;
631 } else if (ShellCommandLineGetFlag(Package, L"-all") && ShellCommandLineGetFlag(Package, L"-guid")) {
632 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_CONFLICT), gShellDebug1HiiHandle, L"dmpstore", L"-all", L"-guid");
633 ShellStatus = SHELL_INVALID_PARAMETER;
634 } else if (ShellCommandLineGetFlag(Package, L"-s") && ShellCommandLineGetFlag(Package, L"-l")) {
635 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_CONFLICT), gShellDebug1HiiHandle, L"dmpstore", L"-l", L"-s");
636 ShellStatus = SHELL_INVALID_PARAMETER;
637 } else if ((ShellCommandLineGetFlag(Package, L"-s") || ShellCommandLineGetFlag(Package, L"-l")) && ShellCommandLineGetFlag(Package, L"-d")) {
638 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_CONFLICT), gShellDebug1HiiHandle, L"dmpstore", L"-l or -s", L"-d");
639 ShellStatus = SHELL_INVALID_PARAMETER;
640 } else {
641 //
642 // Determine the GUID to search for based on -all and -guid parameters
643 //
644 if (!ShellCommandLineGetFlag(Package, L"-all")) {
645 GuidStr = ShellCommandLineGetValue(Package, L"-guid");
646 if (GuidStr != NULL) {
647 Status = ConvertStringToGuid(GuidStr, &GuidData);
648 if (EFI_ERROR(Status)) {
649 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellDebug1HiiHandle, L"dmpstore", GuidStr);
650 ShellStatus = SHELL_INVALID_PARAMETER;
651 }
652 Guid = &GuidData;
653 } else {
654 Guid = &gEfiGlobalVariableGuid;
655 }
656 } else {
657 Guid = NULL;
658 }
659
660 //
661 // Get the Name of the variable to find
662 //
663 Name = ShellCommandLineGetRawValue(Package, 1);
664
665 if (ShellStatus == SHELL_SUCCESS) {
666 if (ShellCommandLineGetFlag(Package, L"-s")) {
667 Type = DmpStoreSave;
668 File = ShellCommandLineGetValue(Package, L"-s");
669 if (File == NULL) {
670 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_VALUE), gShellDebug1HiiHandle, L"dmpstore", L"-s");
671 ShellStatus = SHELL_INVALID_PARAMETER;
672 } else {
673 Status = ShellOpenFileByName (File, &FileHandle, EFI_FILE_MODE_WRITE | EFI_FILE_MODE_READ, 0);
674 if (!EFI_ERROR (Status)) {
675 //
676 // Delete existing file, but do not delete existing directory
677 //
678 FileInfo = ShellGetFileInfo (FileHandle);
679 if (FileInfo == NULL) {
680 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellDebug1HiiHandle, L"dmpstore", File);
681 Status = EFI_DEVICE_ERROR;
682 } else {
683 if ((FileInfo->Attribute & EFI_FILE_DIRECTORY) == EFI_FILE_DIRECTORY) {
684 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_IS_DIRECTORY), gShellDebug1HiiHandle, L"dmpstore", File);
685 Status = EFI_INVALID_PARAMETER;
686 } else {
687 Status = ShellDeleteFile (&FileHandle);
688 if (EFI_ERROR (Status)) {
689 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_DELETE_FAIL), gShellDebug1HiiHandle, L"dmpstore", File);
690 }
691 }
692 FreePool (FileInfo);
693 }
694 } else if (Status == EFI_NOT_FOUND) {
695 //
696 // Good when file doesn't exist
697 //
698 Status = EFI_SUCCESS;
699 } else {
700 //
701 // Otherwise it's bad.
702 //
703 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellDebug1HiiHandle, L"dmpstore", File);
704 }
705
706 if (!EFI_ERROR (Status)) {
707 Status = ShellOpenFileByName (File, &FileHandle, EFI_FILE_MODE_CREATE | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_READ, 0);
708 if (EFI_ERROR (Status)) {
709 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellDebug1HiiHandle, L"dmpstore", File);
710 }
711 }
712
713 if (EFI_ERROR (Status)) {
714 ShellStatus = SHELL_INVALID_PARAMETER;
715 }
716 }
717 } else if (ShellCommandLineGetFlag(Package, L"-l")) {
718 Type = DmpStoreLoad;
719 File = ShellCommandLineGetValue(Package, L"-l");
720 if (File == NULL) {
721 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_VALUE), gShellDebug1HiiHandle, L"dmpstore", L"-l");
722 ShellStatus = SHELL_INVALID_PARAMETER;
723 } else {
724 Status = ShellOpenFileByName (File, &FileHandle, EFI_FILE_MODE_READ, 0);
725 if (EFI_ERROR (Status)) {
726 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellDebug1HiiHandle, L"dmpstore", File);
727 ShellStatus = SHELL_INVALID_PARAMETER;
728 } else {
729 FileInfo = ShellGetFileInfo (FileHandle);
730 if (FileInfo == NULL) {
731 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellDebug1HiiHandle, L"dmpstore", File);
732 ShellStatus = SHELL_DEVICE_ERROR;
733 } else {
734 if ((FileInfo->Attribute & EFI_FILE_DIRECTORY) == EFI_FILE_DIRECTORY) {
735 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_IS_DIRECTORY), gShellDebug1HiiHandle, L"dmpstore", File);
736 ShellStatus = SHELL_INVALID_PARAMETER;
737 }
738 FreePool (FileInfo);
739 }
740 }
741 }
742 } else if (ShellCommandLineGetFlag(Package, L"-d")) {
743 Type = DmpStoreDelete;
744 }
745 }
746
747 if (ShellStatus == SHELL_SUCCESS) {
748 if (Type == DmpStoreSave) {
749 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DMPSTORE_SAVE), gShellDebug1HiiHandle, File);
750 } else if (Type == DmpStoreLoad) {
751 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DMPSTORE_LOAD), gShellDebug1HiiHandle, File);
752 }
753 ShellStatus = ProcessVariables (Name, Guid, Type, FileHandle);
754 if ((Type == DmpStoreLoad) || (Type == DmpStoreSave)) {
755 ShellCloseFile (&FileHandle);
756 }
757 }
758 }
759 }
760
761 if (Package != NULL) {
762 ShellCommandLineFreeVarList (Package);
763 }
764 return ShellStatus;
765 }
766