Home | History | Annotate | Download | only in UefiShellDebug1CommandsLib
      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