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