Update HiiConfigAccess.ExtractConfig interface to support NULL request string and...
[efi/edk2/.git] / edk2 / EdkCompatibilityPkg / Compatibility / FrameworkHiiOnUefiHiiThunk / ConfigAccess.c
index c49ffe6..cdf4b09 100644 (file)
@@ -147,6 +147,10 @@ GetStorageFromConfigString (
   FORMSET_STORAGE        *Storage;\r
   CHAR16                 *Name;\r
 \r
+  if (ConfigString == NULL) {\r
+    return NULL;\r
+  }\r
+\r
   StorageList = GetFirstNode (&FormSet->StorageListHead);\r
 \r
   while (!IsNull (&FormSet->StorageListHead, StorageList)) {\r
@@ -165,7 +169,7 @@ GetStorageFromConfigString (
     StorageList = GetNextNode (&FormSet->StorageListHead, StorageList);\r
   }\r
 \r
-   return NULL;\r
+  return NULL;\r
 }\r
 \r
 /**\r
@@ -419,73 +423,194 @@ ThunkExtractConfig (
   OUT EFI_STRING                             *Results\r
   )\r
 {\r
-  EFI_STATUS                                  Status;\r
-  CONFIG_ACCESS_PRIVATE                       *ConfigAccess;\r
-  FORMSET_STORAGE                             *BufferStorage;\r
-  VOID                                        *Data;\r
-  UINTN                                       DataSize;\r
-\r
-  if (Request == NULL) {\r
+  EFI_STATUS                       Status;\r
+  CONFIG_ACCESS_PRIVATE            *ConfigAccess;\r
+  FORMSET_STORAGE                  *BufferStorage;\r
+  VOID                             *Data;\r
+  UINTN                            DataSize;\r
+  FORM_BROWSER_FORMSET             *FormSetContext;\r
+  CHAR16                           *VarStoreName;\r
+  EFI_STRING                       ConfigRequestHdr;\r
+  EFI_STRING                       ConfigRequest;\r
+  UINTN                            Size;\r
+  BOOLEAN                          AllocatedRequest;\r
+  LIST_ENTRY                       *StorageList;\r
+  EFI_STRING                       SingleResult;\r
+  EFI_STRING                       FinalResults;\r
+  EFI_STRING                       StrPointer;\r
+\r
+  if (Progress == NULL || Results == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  *Progress = Request;\r
+\r
+  Status         = EFI_SUCCESS;\r
+  Data           = NULL;\r
+  StrPointer     = NULL;\r
+  SingleResult   = NULL;\r
+  FinalResults   = NULL;\r
+  ConfigAccess   = CONFIG_ACCESS_PRIVATE_FROM_PROTOCOL (This);\r
+  FormSetContext = ConfigAccess->ThunkContext->FormSet;\r
+  if (IsListEmpty (&FormSetContext->StorageListHead)) {\r
+    //\r
+    // No VarStorage does exist in this form.\r
+    //\r
     return EFI_NOT_FOUND;\r
   }\r
+  StorageList    = GetFirstNode (&FormSetContext->StorageListHead);\r
 \r
-  Data = NULL;\r
-  ConfigAccess = CONFIG_ACCESS_PRIVATE_FROM_PROTOCOL (This);\r
+  do {\r
+    if (Request != NULL) {\r
+      BufferStorage = GetStorageFromConfigString (ConfigAccess->ThunkContext->FormSet, Request);\r
+      if (BufferStorage == NULL) {\r
+        return EFI_NOT_FOUND;\r
+      }\r
+    } else {\r
+      if (IsNull (&FormSetContext->StorageListHead, StorageList)) {\r
+        //\r
+        // No Storage to be extracted into the results.\r
+        //\r
+        break;\r
+      }\r
+      BufferStorage = FORMSET_STORAGE_FROM_LINK (StorageList);\r
+      StorageList = GetNextNode (&FormSetContext->StorageListHead, StorageList);\r
+    }\r
+  \r
+    VarStoreName     = NULL;\r
+    ConfigRequestHdr = NULL;\r
+    ConfigRequest    = NULL;\r
+    Size             = 0;\r
+    AllocatedRequest = FALSE;\r
 \r
-  BufferStorage = GetStorageFromConfigString (ConfigAccess->ThunkContext->FormSet, Request);\r
+    if (ConfigAccess->ThunkContext->NvMapOverride == NULL) {\r
+      //\r
+      // NvMapOverride is not used. Get the Storage data from EFI Variable or Framework Form Callback.\r
+      //\r
+      if (ConfigAccess->FormCallbackProtocol == NULL ||\r
+          ConfigAccess->FormCallbackProtocol->NvRead == NULL) {\r
+        Status = GetUefiVariable (\r
+                   BufferStorage,\r
+                   &Data,\r
+                   &DataSize\r
+                   );\r
+      } else {\r
+        Status = CallFormCallBack (\r
+                   BufferStorage,\r
+                   ConfigAccess->FormCallbackProtocol,\r
+                    &Data,\r
+                    &DataSize\r
+                   );\r
+      }\r
+    } else {\r
+      //\r
+      // Use the NvMapOverride.\r
+      //\r
+      DataSize = BufferStorage->Size;\r
+      Data = AllocateCopyPool (DataSize, ConfigAccess->ThunkContext->NvMapOverride);\r
+      \r
+      if (Data != NULL) {\r
+        Status = EFI_SUCCESS;\r
+      } else {\r
+        Status = EFI_OUT_OF_RESOURCES;\r
+      }\r
+    }\r
+    \r
+    if (!EFI_ERROR (Status)) {\r
+      ConfigRequest = Request;\r
+      if (Request == NULL || (StrStr (Request, L"OFFSET") == NULL)) {\r
+        //\r
+        // Request is without any request element, construct full request string.\r
+        //\r
 \r
-  if (BufferStorage == NULL) {\r
-    *Progress = (EFI_STRING) Request;\r
-    return EFI_NOT_FOUND;\r
-  }\r
+        if ((BufferStorage->VarStoreId == FormSetContext->DefaultVarStoreId) && (FormSetContext->OriginalDefaultVarStoreName != NULL)) {\r
+          VarStoreName = FormSetContext->OriginalDefaultVarStoreName;\r
+        } else {\r
+          VarStoreName = BufferStorage->Name;\r
+        }\r
 \r
-  if (ConfigAccess->ThunkContext->NvMapOverride == NULL) {\r
+        //\r
+        // First Set ConfigRequestHdr string.\r
+        //\r
+        ConfigRequestHdr = HiiConstructConfigHdr (&BufferStorage->Guid, VarStoreName, ConfigAccess->ThunkContext->UefiHiiDriverHandle);\r
+        ASSERT (ConfigRequestHdr != NULL);\r
+\r
+        //\r
+        // Allocate and fill a buffer large enough to hold the <ConfigHdr> template \r
+        // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator\r
+        //\r
+        Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16);\r
+        ConfigRequest = AllocateZeroPool (Size);\r
+        ASSERT (ConfigRequest != NULL);\r
+        AllocatedRequest = TRUE;\r
+        UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr, (UINT64)DataSize);\r
+        FreePool (ConfigRequestHdr);\r
+      }\r
+      Status = mHiiConfigRoutingProtocol->BlockToConfig (\r
+                                              mHiiConfigRoutingProtocol,\r
+                                              ConfigRequest,\r
+                                              Data,\r
+                                              DataSize,\r
+                                              &SingleResult,\r
+                                              Progress\r
+                                              );\r
+      //\r
+      // Free the allocated config request string.\r
+      //\r
+      if (AllocatedRequest) {\r
+        FreePool (ConfigRequest);\r
+        ConfigRequest = NULL;\r
+      }\r
+    }\r
     //\r
-    // NvMapOverride is not used. Get the Storage data from EFI Variable or Framework Form Callback.\r
+    // Free the allocated Data\r
     //\r
-    if (ConfigAccess->FormCallbackProtocol == NULL ||\r
-        ConfigAccess->FormCallbackProtocol->NvRead == NULL) {\r
-      Status = GetUefiVariable (\r
-                 BufferStorage,\r
-                 &Data,\r
-                 &DataSize\r
-                 );\r
-    } else {\r
-      Status = CallFormCallBack (\r
-                 BufferStorage,\r
-                 ConfigAccess->FormCallbackProtocol,\r
-                  &Data,\r
-                  &DataSize\r
-                 );\r
+    if (Data != NULL) {\r
+      FreePool (Data);\r
     }\r
-  } else {\r
     //\r
-    // Use the NvMapOverride.\r
+    // Directly return when meet with error\r
     //\r
-    DataSize = BufferStorage->Size;\r
-    Data = AllocateCopyPool (DataSize, ConfigAccess->ThunkContext->NvMapOverride);\r
-    \r
-    if (Data != NULL) {\r
-      Status = EFI_SUCCESS;\r
+    if (EFI_ERROR (Status)) {\r
+      break;\r
+    }\r
+    //\r
+    // Merge result into the final results.\r
+    //\r
+    if (FinalResults == NULL) {\r
+      FinalResults = SingleResult;\r
+      SingleResult = NULL;\r
     } else {\r
-      Status = EFI_OUT_OF_RESOURCES;\r
+      Size = StrLen (FinalResults);\r
+      Size = Size + 1;\r
+      Size = Size + StrLen (SingleResult) + 1;\r
+      StrPointer = AllocateZeroPool (Size * sizeof (CHAR16));\r
+      ASSERT (StrPointer != NULL);\r
+      StrCpy (StrPointer, FinalResults);\r
+      FreePool (FinalResults);\r
+      FinalResults = StrPointer;\r
+      StrPointer  = StrPointer + StrLen (StrPointer);\r
+      *StrPointer = L'&';\r
+      StrCpy (StrPointer + 1, SingleResult);\r
+      FreePool (SingleResult);\r
     }\r
-  }\r
-  \r
+  } while (Request == NULL);\r
+\r
   if (!EFI_ERROR (Status)) {\r
-    Status = mHiiConfigRoutingProtocol->BlockToConfig (\r
-                                            mHiiConfigRoutingProtocol,\r
-                                            Request,\r
-                                            Data,\r
-                                            DataSize,\r
-                                            Results,\r
-                                            Progress\r
-                                            );\r
+    *Results = FinalResults;\r
+  } else {\r
+    if (FinalResults != NULL) {\r
+      FreePool (FinalResults);\r
+    }\r
   }\r
-\r
-  if (Data != NULL) {\r
-    FreePool (Data);\r
+  //\r
+  // Set Progress string to the original request string.\r
+  //\r
+  if (Request == NULL) {\r
+    *Progress = NULL;\r
+  } else if (StrStr (Request, L"OFFSET") == NULL) {\r
+    *Progress = Request + StrLen (Request);\r
   }\r
+\r
   return Status;\r
 }\r
 \r