]> git.proxmox.com Git - mirror_edk2.git/blobdiff - ShellPkg/Library/UefiShellDebug1CommandsLib/DmpStore.c
ShellPkg: fix DmpStore for deleting
[mirror_edk2.git] / ShellPkg / Library / UefiShellDebug1CommandsLib / DmpStore.c
index 3445b7f7e25096e928c558b562fb2cb15b8508c2..fd109679645d13015443b6f090ffe77682fe4db6 100644 (file)
 \r
 #include "UefiShellDebug1CommandsLib.h"\r
 \r
-\r
-#define INIT_NAME_BUFFER_SIZE  128\r
-#define INIT_DATA_BUFFER_SIZE  1024\r
-\r
 /**\r
   Base on the input attribute value to return the attribute string.\r
 \r
@@ -67,11 +63,20 @@ GetAttrType (
 }\r
 \r
 /**\r
-  Function to display or delete variables.\r
+  Recursive function to display or delete variables.\r
+\r
+  This function will call itself to create a stack-based list of allt he variables to process, \r
+  then fromt he last to the first, they will do either printing or deleting.\r
+\r
+  This is necessary since once a delete happens GetNextVariableName() will work.\r
 \r
   @param[in] VariableName   The variable name of the EFI variable (or NULL).\r
   @param[in] Guid           The GUID of the variable set (or NULL).\r
   @param[in] Delete         TRUE to delete, FALSE otherwise.\r
+  @param[in] PrevName       The previous variable name from GetNextVariableName. L"" to start.\r
+  @param[in] FoundVarGuid   The previous GUID from GetNextVariableName. ignored at start.\r
+  @param[in] FoundOne       If a VariableName or Guid was specified and one was printed or\r
+                            deleted, then set this to TRUE, otherwise ignored.\r
 \r
   @retval SHELL_SUCCESS           The operation was successful.\r
   @retval SHELL_OUT_OF_RESOURCES  A memorty allocation failed.\r
@@ -81,127 +86,112 @@ GetAttrType (
 **/\r
 SHELL_STATUS\r
 EFIAPI\r
-ProcessVariables (\r
+CascadeProcessVariables (\r
   IN CONST CHAR16   *VariableName OPTIONAL,\r
   IN CONST EFI_GUID *Guid OPTIONAL,\r
-  IN BOOLEAN        Delete\r
+  IN BOOLEAN        Delete,\r
+  IN CONST CHAR16   * CONST PrevName,\r
+  IN EFI_GUID       FoundVarGuid,\r
+  IN BOOLEAN        *FoundOne\r
   )\r
 {\r
   EFI_STATUS                Status;\r
   CHAR16                    *FoundVarName;\r
-  EFI_GUID                  FoundVarGuid;\r
   UINT8                     *DataBuffer;\r
   UINTN                     DataSize;\r
   UINT32                    Atts;\r
   SHELL_STATUS              ShellStatus;\r
-  BOOLEAN                   Found;\r
-  UINTN                     NameBufferSize; // Allocated Name buffer size\r
   UINTN                     NameSize;\r
-  CHAR16                    *OldName;\r
-  UINTN                     OldNameBufferSize;\r
-  UINTN                     DataBufferSize; // Allocated data buffer size\r
   CHAR16                    *RetString;\r
 \r
-  Found         = FALSE;\r
-  ShellStatus   = SHELL_SUCCESS;\r
-  Status        = EFI_SUCCESS;\r
-\r
-  NameBufferSize = INIT_NAME_BUFFER_SIZE;\r
-  DataBufferSize = INIT_DATA_BUFFER_SIZE;\r
-  FoundVarName   = AllocateZeroPool (NameBufferSize);\r
-  if (FoundVarName == NULL) {\r
-    return (SHELL_OUT_OF_RESOURCES);\r
-  }  \r
-  DataBuffer     = AllocatePool (DataBufferSize);\r
-  if (DataBuffer == NULL) {\r
-    FreePool (FoundVarName);\r
-    return (SHELL_OUT_OF_RESOURCES);\r
+  if (ShellGetExecutionBreakFlag()) {\r
+    return (SHELL_ABORTED);\r
   }\r
 \r
-  for (;;){\r
-    if (ShellGetExecutionBreakFlag()) {\r
-      ShellStatus = SHELL_ABORTED;\r
-      break;\r
-    }\r
+  NameSize      = 0;\r
+  FoundVarName  = NULL;\r
 \r
-    NameSize  = NameBufferSize;\r
-    Status    = gRT->GetNextVariableName (&NameSize, FoundVarName, &FoundVarGuid);\r
-    if (Status == EFI_BUFFER_TOO_SMALL) {\r
-      OldName           = FoundVarName;\r
-      OldNameBufferSize = NameBufferSize;\r
-      //\r
-      // Expand at least twice to avoid reallocate many times\r
-      //\r
-      NameBufferSize = NameSize > NameBufferSize * 2 ? NameSize : NameBufferSize * 2;\r
-      FoundVarName           = AllocateZeroPool (NameBufferSize);\r
-      if (FoundVarName == NULL) {\r
-        Status = EFI_OUT_OF_RESOURCES;\r
-        FreePool (OldName);\r
-        break;\r
-      }\r
-      //\r
-      // Preserve the original content to get correct iteration for GetNextVariableName() call\r
-      //\r
-      CopyMem (FoundVarName, OldName, OldNameBufferSize);\r
-      FreePool (OldName);\r
-      NameSize = NameBufferSize;\r
-      Status = gRT->GetNextVariableName (&NameSize, FoundVarName, &FoundVarGuid);\r
-    }\r
-    if (Status == EFI_NOT_FOUND) {\r
-      break;\r
+  if (PrevName!=NULL) {\r
+    StrnCatGrow(&FoundVarName, &NameSize, PrevName, 0);\r
+  } else {\r
+    FoundVarName = AllocateZeroPool(sizeof(CHAR16));\r
+  }\r
+\r
+  Status = gRT->GetNextVariableName (&NameSize, FoundVarName, &FoundVarGuid);\r
+  if (Status == EFI_BUFFER_TOO_SMALL) {\r
+    SHELL_FREE_NON_NULL(FoundVarName);\r
+    FoundVarName = AllocateZeroPool (NameSize);\r
+    if (PrevName != NULL) {\r
+      StrCpy(FoundVarName, PrevName);\r
     }\r
-    ASSERT_EFI_ERROR(Status);\r
 \r
+    Status = gRT->GetNextVariableName (&NameSize, FoundVarName, &FoundVarGuid);\r
+  }\r
+\r
+  //\r
+  // No more is fine.\r
+  //\r
+  if (Status == EFI_NOT_FOUND) {\r
+    SHELL_FREE_NON_NULL(FoundVarName);\r
+    return (SHELL_SUCCESS);\r
+  } else if (EFI_ERROR(Status)) {\r
+    SHELL_FREE_NON_NULL(FoundVarName);\r
+    return (SHELL_DEVICE_ERROR);\r
+  }\r
+\r
+  //\r
+  // Recurse to the next iteration.  We know "our" variable's name.\r
+  //\r
+  ShellStatus = CascadeProcessVariables(VariableName, Guid, Delete, FoundVarName, FoundVarGuid, FoundOne);\r
+\r
+  //\r
+  // No matter what happened we process our own variable\r
+  // Only continue if Guid and VariableName are each either NULL or a match\r
+  //\r
+  if ( ( VariableName == NULL \r
+      || gUnicodeCollation->MetaiMatch(gUnicodeCollation, FoundVarName, (CHAR16*)VariableName) )\r
+     && ( Guid == NULL \r
+      || CompareGuid(&FoundVarGuid, Guid) )\r
+      ) {\r
+    DataSize      = 0;\r
+    DataBuffer    = NULL;\r
     //\r
-    // Check if it matches\r
+    // do the print or delete\r
     //\r
-    if (VariableName != NULL) {\r
-      if (!gUnicodeCollation->MetaiMatch(gUnicodeCollation, FoundVarName, (CHAR16*)VariableName)) {\r
-        continue;\r
-      }\r
-    }\r
-    if (Guid != NULL) {\r
-      if (!CompareGuid(&FoundVarGuid, Guid)) {\r
-        continue;\r
-      }\r
-    }\r
-\r
-    DataSize  = DataBufferSize;\r
-    Status    = gRT->GetVariable (FoundVarName, &FoundVarGuid, &Atts, &DataSize, DataBuffer);\r
+    *FoundOne = TRUE;\r
+    Status = gRT->GetVariable (FoundVarName, &FoundVarGuid, &Atts, &DataSize, DataBuffer);\r
     if (Status == EFI_BUFFER_TOO_SMALL) {\r
-      //\r
-      // Expand at least twice to avoid reallocate many times\r
-      //\r
-      FreePool (DataBuffer);\r
-      DataBufferSize = DataSize > DataBufferSize * 2 ? DataSize : DataBufferSize * 2;\r
-      DataBuffer           = AllocatePool (DataBufferSize);\r
+      SHELL_FREE_NON_NULL (DataBuffer);\r
+      DataBuffer = AllocatePool (DataSize);\r
       if (DataBuffer == NULL) {\r
         Status = EFI_OUT_OF_RESOURCES;\r
-        break;\r
+      } else {\r
+        Status = gRT->GetVariable (FoundVarName, &FoundVarGuid, &Atts, &DataSize, DataBuffer);\r
       }\r
-      DataSize = DataBufferSize;\r
-      Status   = gRT->GetVariable (FoundVarName, &FoundVarGuid, &Atts, &DataSize, DataBuffer);\r
-    }    \r
-    ASSERT_EFI_ERROR(Status);\r
-\r
-    //\r
-    // do the print or delete\r
-    //\r
-    Found = TRUE;\r
-    RetString = GetAttrType(Atts);\r
+    }\r
     if (!Delete) {\r
-      ShellPrintHiiEx(\r
-        -1,\r
-        -1,\r
-        NULL,\r
-        STRING_TOKEN(STR_DMPSTORE_HEADER_LINE),\r
-        gShellDebug1HiiHandle,\r
-        RetString,\r
-        &FoundVarGuid,\r
-        FoundVarName,\r
-        DataSize);\r
-      DumpHex(2, 0, DataSize, DataBuffer);\r
+      //\r
+      // Last error check then print this variable out.\r
+      //\r
+      if (!EFI_ERROR(Status)) {\r
+        RetString = GetAttrType(Atts);\r
+        ShellPrintHiiEx(\r
+          -1,\r
+          -1,\r
+          NULL,\r
+          STRING_TOKEN(STR_DMPSTORE_HEADER_LINE),\r
+          gShellDebug1HiiHandle,\r
+          RetString,\r
+          &FoundVarGuid,\r
+          FoundVarName,\r
+          DataSize);\r
+        DumpHex(2, 0, DataSize, DataBuffer);\r
+        SHELL_FREE_NON_NULL(RetString);\r
+      }\r
     } else {\r
+      //\r
+      // We only need name to delete it...\r
+      //\r
       ShellPrintHiiEx(\r
         -1,\r
         -1,\r
@@ -217,27 +207,59 @@ ProcessVariables (
         STRING_TOKEN(STR_DMPSTORE_DELETE_DONE),\r
         gShellDebug1HiiHandle,\r
         gRT->SetVariable(FoundVarName, &FoundVarGuid, Atts, 0, NULL));\r
-        FoundVarName[0] = CHAR_NULL;\r
-    }\r
-\r
-    if (RetString != NULL) {\r
-      FreePool (RetString);\r
     }\r
+    SHELL_FREE_NON_NULL(DataBuffer);\r
   }\r
 \r
-  if (FoundVarName != NULL) {\r
-    FreePool(FoundVarName);\r
-  }\r
-  if (DataBuffer != NULL) {\r
-    FreePool(DataBuffer);\r
+  SHELL_FREE_NON_NULL(FoundVarName);\r
+\r
+  if (Status == EFI_DEVICE_ERROR) {\r
+    ShellStatus = SHELL_DEVICE_ERROR;\r
+  } else if (Status == EFI_SECURITY_VIOLATION) {\r
+    ShellStatus = SHELL_SECURITY_VIOLATION;\r
+  } else if (EFI_ERROR(Status)) {\r
+    ShellStatus = SHELL_NOT_READY;\r
   }\r
+\r
+  return (ShellStatus);\r
+}\r
+\r
+/**\r
+  Function to display or delete variables.  This will set up and call into the recursive function.\r
+\r
+  @param[in] VariableName   The variable name of the EFI variable (or NULL).\r
+  @param[in] Guid           The GUID of the variable set (or NULL).\r
+  @param[in] Delete         TRUE to delete, FALSE otherwise.\r
+\r
+  @retval SHELL_SUCCESS           The operation was successful.\r
+  @retval SHELL_OUT_OF_RESOURCES  A memorty allocation failed.\r
+  @retval SHELL_ABORTED           The abort message was received.\r
+  @retval SHELL_DEVICE_ERROR      UEFI Variable Services returned an error.\r
+  @retval SHELL_NOT_FOUND         the Name/Guid pair could not be found.\r
+**/\r
+SHELL_STATUS\r
+EFIAPI\r
+ProcessVariables (\r
+  IN CONST CHAR16   *VariableName OPTIONAL,\r
+  IN CONST EFI_GUID *Guid OPTIONAL,\r
+  IN BOOLEAN        Delete\r
+  )\r
+{\r
+  SHELL_STATUS              ShellStatus;\r
+  BOOLEAN                   Found;\r
+  EFI_GUID                  FoundVarGuid;\r
+\r
+  Found         = FALSE;\r
+  ShellStatus   = SHELL_SUCCESS;\r
+  ZeroMem (&FoundVarGuid, sizeof(EFI_GUID));\r
+\r
+  ShellStatus = CascadeProcessVariables(VariableName, Guid, Delete, NULL, FoundVarGuid, &Found);\r
+\r
   if (!Found) {\r
-    if (Status == EFI_OUT_OF_RESOURCES) {\r
+    if (ShellStatus == SHELL_OUT_OF_RESOURCES) {\r
       ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_OUT_MEM), gShellDebug1HiiHandle);\r
-      return SHELL_OUT_OF_RESOURCES;\r
-    }\r
-\r
-    if (VariableName != NULL && Guid == NULL) {\r
+      return (ShellStatus);\r
+    } else if (VariableName != NULL && Guid == NULL) {\r
       ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_DMPSTORE_NO_VAR_FOUND_N), gShellDebug1HiiHandle, VariableName);\r
     } else if (VariableName != NULL && Guid != NULL) {\r
       ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_DMPSTORE_NO_VAR_FOUND_GN), gShellDebug1HiiHandle, Guid, VariableName);\r