]> git.proxmox.com Git - mirror_edk2.git/commitdiff
MdeModulePkg/HiiDatabaseDxe: Support EfiVarStore to get AltCfg from Driver
authorDandan Bi <dandan.bi@intel.com>
Wed, 13 Apr 2016 08:47:25 +0000 (16:47 +0800)
committerStar Zeng <star.zeng@intel.com>
Tue, 19 Apr 2016 09:53:59 +0000 (17:53 +0800)
Allow EfiVarStore to get <AltResp> from Hii Driver, and enhance code logic
in MergeDefaultString function to get a full AltCfgResp.
The logic in function MergeDefaultString after enhancement:
(1) If there are no <AltResp> in AltCfgResp, merge the <AltResp> in
DefaultAltCfgResp to AltCfgResp.
(2) If there are <AltResp> in AltCfgResp, for the same <AltConfigHdr>, if
the <ConfigElement> already in AltCfgResp, don't need to merge from
DefaultAltCfgResp, else merge the <ConfigElement> in the DefaultAltCfgResp
to the related <AltResp> in AltCfgResp.
AltCfgResp: Generated by Driver.
DefaultAltCfgResp: Generated by HiiDatabase.

Cc: Liming Gao <liming.gao@intel.com>
Cc: Eric Dong <eric.dong@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Dandan Bi <dandan.bi@intel.com>
Reviewed-by: Eric Dong <eric.dong@intel.com>
Reviewed-by: Liming Gao <liming.gao@intel.com>
MdeModulePkg/Universal/HiiDatabaseDxe/ConfigRouting.c

index 4ed4eccdc2cafb848239afbc23ac574fd47e91b6..5e778fa4c2edecd181f6074c38a9e6c83ed6e5ac 100644 (file)
@@ -509,6 +509,477 @@ Exit:
   return Status;\r
 }\r
 \r
+/**\r
+ To find the BlockName in the string with same value.\r
+\r
+  @param  String                 Pointer to a Null-terminated Unicode string.\r
+  @param  BlockName              Pointer to a Null-terminated Unicode string to search for.\r
+  @param  Buffer                 Pointer to the value correspond to the BlockName.\r
+  @param  Found                  The Block whether has been found.\r
+  @param  BufferLen              The length of the buffer.\r
+\r
+  @retval EFI_OUT_OF_RESOURCES   Insufficient resources to store neccessary structures.\r
+  @retval EFI_SUCCESS            The function finishes successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+FindSameBlockElement(\r
+  IN  EFI_STRING   String,\r
+  IN  EFI_STRING   BlockName,\r
+  IN  UINT8        *Buffer,\r
+  OUT BOOLEAN      *Found,\r
+  IN  UINTN        BufferLen\r
+  )\r
+{\r
+  EFI_STRING   BlockPtr;\r
+  UINTN        Length;\r
+  UINT8        *TempBuffer;\r
+  EFI_STATUS   Status;\r
+\r
+  TempBuffer = NULL;\r
+  *Found = FALSE;\r
+  BlockPtr = StrStr (String, BlockName);\r
+\r
+  while (BlockPtr != NULL) {\r
+    BlockPtr += StrLen (BlockName);\r
+    Status = GetValueOfNumber (BlockPtr, &TempBuffer, &Length);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+    ASSERT (TempBuffer != NULL);\r
+    if ((BufferLen == Length) && (0 == CompareMem (Buffer, TempBuffer, Length))) {\r
+      *Found = TRUE;\r
+      return EFI_SUCCESS;\r
+    } else {\r
+      FreePool (TempBuffer);\r
+      TempBuffer = NULL;\r
+      BlockPtr = StrStr (BlockPtr + 1, BlockName);\r
+    }\r
+  }\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Compare the <AltResp> in ConfigAltResp and DefaultAltCfgResp, if the <AltResp>\r
+  in DefaultAltCfgResp but not in ConfigAltResp,add it to the ConfigAltResp.\r
+\r
+  @param  DefaultAltCfgResp      Pointer to a null-terminated Unicode string in\r
+                                 <MultiConfigAltResp> format. The default value\r
+                                 string may contain more than one ConfigAltResp\r
+                                 string for the different varstore buffer.\r
+  @param  ConfigAltResp          Pointer to a null-terminated Unicode string in\r
+                                 <ConfigAltResp> format.\r
+  @param  AltConfigHdr           Pointer to a Unicode string in <AltConfigHdr> format.\r
+  @param  ConfigAltRespChanged   Whether the ConfigAltResp has been changed.\r
+\r
+  @retval EFI_OUT_OF_RESOURCES   Insufficient resources to store neccessary structures.\r
+  @retval EFI_SUCCESS            The function finishes  successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+CompareBlockElementDefault (\r
+  IN      EFI_STRING  DefaultAltCfgResp,\r
+  IN OUT  EFI_STRING  *ConfigAltResp,\r
+  IN      EFI_STRING  AltConfigHdr,\r
+  IN OUT  BOOLEAN     *ConfigAltRespChanged\r
+)\r
+{\r
+  EFI_STATUS    Status;\r
+  EFI_STRING    BlockPtr;\r
+  EFI_STRING    BlockPtrStart;\r
+  EFI_STRING    StringPtr;\r
+  EFI_STRING    AppendString;\r
+  EFI_STRING    AltConfigHdrPtr;\r
+  UINT8         *TempBuffer;\r
+  UINTN         OffsetLength;\r
+  UINTN         AppendSize;\r
+  UINTN         TotalSize;\r
+  BOOLEAN       FoundOffset;\r
+\r
+  AppendString = NULL;\r
+  TempBuffer   = NULL;\r
+  //\r
+  // Make BlockPtr point to the first <BlockConfig> with AltConfigHdr in DefaultAltCfgResp.\r
+  //\r
+  AltConfigHdrPtr = StrStr (DefaultAltCfgResp, AltConfigHdr);\r
+  ASSERT (AltConfigHdrPtr != NULL);\r
+  BlockPtr = StrStr (AltConfigHdrPtr, L"&OFFSET=");\r
+  //\r
+  // Make StringPtr point to the AltConfigHdr in ConfigAltResp.\r
+  //\r
+  StringPtr = StrStr (*ConfigAltResp, AltConfigHdr);\r
+  ASSERT (StringPtr != NULL);\r
+\r
+  while (BlockPtr != NULL) {\r
+    //\r
+    // Find the "&OFFSET=<Number>" block and get the value of the Number with AltConfigHdr in DefaultAltCfgResp.\r
+    //\r
+    BlockPtrStart = BlockPtr;\r
+    BlockPtr += StrLen (L"&OFFSET=");\r
+    Status = GetValueOfNumber (BlockPtr, &TempBuffer, &OffsetLength);\r
+    if (EFI_ERROR (Status)) {\r
+      Status = EFI_OUT_OF_RESOURCES;\r
+      goto Exit;\r
+    }\r
+    //\r
+    // To find the same "&OFFSET=<Number>" block in ConfigAltResp.\r
+    //\r
+    Status = FindSameBlockElement (StringPtr, L"&OFFSET=", TempBuffer, &FoundOffset, OffsetLength);\r
+    if (TempBuffer != NULL) {\r
+      FreePool (TempBuffer);\r
+      TempBuffer = NULL;\r
+    }\r
+    if (EFI_ERROR (Status)) {\r
+      Status = EFI_OUT_OF_RESOURCES;\r
+      goto Exit;\r
+    }\r
+    if (!FoundOffset) {\r
+      //\r
+      // Don't find the same "&OFFSET=<Number>" block in ConfigAltResp.\r
+      // Calculate the size of <BlockConfig>.\r
+      // <BlockConfig>::='OFFSET='<Number>'&WIDTH='<Number>'&VALUE='<Number>.\r
+      //\r
+      BlockPtr = StrStr (BlockPtr + 1, L"&OFFSET=");\r
+      if (BlockPtr != NULL) {\r
+        AppendSize = (BlockPtr - BlockPtrStart) * sizeof (CHAR16);\r
+      } else {\r
+        AppendSize = StrSize (BlockPtrStart);\r
+      }\r
+      //\r
+      // Copy the <BlockConfig> to AppendString.\r
+      //\r
+      if (AppendString == NULL) {\r
+        AppendString = (EFI_STRING) AllocateZeroPool (AppendSize + sizeof (CHAR16));\r
+        StrnCatS (AppendString, AppendSize / sizeof (CHAR16) + 1, BlockPtrStart, AppendSize / sizeof (CHAR16));\r
+      } else {\r
+        TotalSize = StrSize (AppendString) + AppendSize + sizeof (CHAR16);\r
+        AppendString = (EFI_STRING) ReallocatePool (\r
+                                      StrSize (AppendString),\r
+                                      TotalSize,\r
+                                      AppendString\r
+                                      );\r
+        if (AppendString == NULL) {\r
+          Status = EFI_OUT_OF_RESOURCES;\r
+          goto Exit;\r
+        }\r
+        StrnCatS (AppendString, TotalSize / sizeof (CHAR16), BlockPtrStart, AppendSize / sizeof (CHAR16));\r
+      }\r
+    } else {\r
+      //\r
+      // To find next "&OFFSET=<Number>" block with AltConfigHdr in DefaultAltCfgResp.\r
+      //\r
+      BlockPtr = StrStr (BlockPtr + 1, L"&OFFSET=");\r
+    }\r
+  }\r
+\r
+  if (AppendString != NULL) {\r
+    //\r
+    // Reallocate ConfigAltResp to copy the AppendString.\r
+    //\r
+    TotalSize = StrSize (*ConfigAltResp) + StrSize (AppendString) + sizeof (CHAR16);\r
+    *ConfigAltResp = (EFI_STRING) ReallocatePool (\r
+                                    StrSize (*ConfigAltResp),\r
+                                    TotalSize,\r
+                                    *ConfigAltResp\r
+                                    );\r
+    if (*ConfigAltResp == NULL) {\r
+      Status = EFI_OUT_OF_RESOURCES;\r
+      goto Exit;\r
+    }\r
+    StrCatS (*ConfigAltResp, TotalSize / sizeof (CHAR16), AppendString);\r
+    *ConfigAltRespChanged = TRUE;\r
+  }\r
+\r
+  Status = EFI_SUCCESS;\r
+\r
+Exit:\r
+  if (AppendString != NULL) {\r
+    FreePool (AppendString);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Compare the <AltResp> in ConfigAltResp and DefaultAltCfgResp, if the <AltResp>\r
+  in DefaultAltCfgResp but not in ConfigAltResp,add it to the ConfigAltResp.\r
+\r
+  @param  DefaultAltCfgResp      Pointer to a null-terminated Unicode string in\r
+                                 <MultiConfigAltResp> format. The default value\r
+                                 string may contain more than one ConfigAltResp\r
+                                 string for the different varstore buffer.\r
+  @param  ConfigAltResp          Pointer to a null-terminated Unicode string in\r
+                                 <ConfigAltResp> format.\r
+  @param  AltConfigHdr           Pointer to a Unicode string in <AltConfigHdr> format.\r
+  @param  ConfigAltRespChanged   Whether the ConfigAltResp has been changed.\r
+\r
+  @retval EFI_OUT_OF_RESOURCES   Insufficient resources to store neccessary structures.\r
+  @retval EFI_SUCCESS            The function finishes  successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+CompareNameElementDefault (\r
+  IN     EFI_STRING  DefaultAltCfgResp,\r
+  IN OUT EFI_STRING  *ConfigAltResp,\r
+  IN     EFI_STRING  AltConfigHdr,\r
+  IN OUT BOOLEAN     *ConfigAltRespChanged\r
+)\r
+{\r
+  EFI_STATUS    Status;\r
+  EFI_STRING    NvConfigPtr;\r
+  EFI_STRING    NvConfigStart;\r
+  EFI_STRING    NvConfigValuePtr;\r
+  EFI_STRING    StringPtr;\r
+  EFI_STRING    NvConfigExist;\r
+  EFI_STRING    AppendString;\r
+  CHAR16        TempChar;\r
+  UINTN         AppendSize;\r
+  UINTN         TotalSize;\r
+\r
+  AppendString = NULL;\r
+  NvConfigExist = NULL;\r
+  //\r
+  // Make NvConfigPtr point to the first <NvConfig> with AltConfigHdr in DefaultAltCfgResp.\r
+  //\r
+  NvConfigPtr = StrStr (DefaultAltCfgResp, AltConfigHdr);\r
+  ASSERT (NvConfigPtr != NULL);\r
+  NvConfigPtr = StrStr (NvConfigPtr + StrLen(AltConfigHdr),L"&");\r
+  //\r
+  // Make StringPtr point to the first <NvConfig> with AltConfigHdr in ConfigAltResp.\r
+  //\r
+  StringPtr = StrStr (*ConfigAltResp, AltConfigHdr);\r
+  ASSERT (StringPtr != NULL);\r
+  StringPtr = StrStr (StringPtr + StrLen (AltConfigHdr), L"&");\r
+  ASSERT (StringPtr != NULL);\r
+\r
+  while (NvConfigPtr != NULL) {\r
+    //\r
+    // <NvConfig> ::= <Label>'='<String> | <Label>'='<Number>.\r
+    // Get the <Label> with AltConfigHdr in DefaultAltCfgResp.\r
+    //\r
+    NvConfigStart = NvConfigPtr;\r
+    NvConfigValuePtr = StrStr (NvConfigPtr + 1, L"=");\r
+    ASSERT (NvConfigValuePtr != NULL);\r
+    TempChar = *NvConfigValuePtr;\r
+    *NvConfigValuePtr = L'\0';\r
+    //\r
+    // Get the <Label> with AltConfigHdr in ConfigAltResp.\r
+    //\r
+    NvConfigExist = StrStr (StringPtr, NvConfigPtr);\r
+    if (NvConfigExist == NULL) {\r
+      //\r
+      // Don't find same <Label> in ConfigAltResp.\r
+      // Calculate the size of <NvConfig>.\r
+      //\r
+      *NvConfigValuePtr = TempChar;\r
+      NvConfigPtr = StrStr (NvConfigPtr + 1, L"&");\r
+      if (NvConfigPtr != NULL) {\r
+        AppendSize = (NvConfigPtr - NvConfigStart) * sizeof (CHAR16);\r
+      } else {\r
+        AppendSize = StrSize (NvConfigStart);\r
+      }\r
+      //\r
+      // Copy the <NvConfig> to AppendString.\r
+      //\r
+      if (AppendString == NULL) {\r
+        AppendString = (EFI_STRING) AllocateZeroPool (AppendSize + sizeof (CHAR16));\r
+        StrnCatS (AppendString, AppendSize / sizeof (CHAR16) + 1, NvConfigStart, AppendSize / sizeof (CHAR16));\r
+      } else {\r
+         TotalSize = StrSize (AppendString) + AppendSize + sizeof (CHAR16);\r
+         AppendString = (EFI_STRING) ReallocatePool (\r
+                                       StrSize (AppendString),\r
+                                       TotalSize,\r
+                                       AppendString\r
+                                       );\r
+        if (AppendString == NULL) {\r
+          Status = EFI_OUT_OF_RESOURCES;\r
+          goto Exit;\r
+        }\r
+        StrnCatS (AppendString, TotalSize / sizeof (CHAR16), NvConfigStart, AppendSize / sizeof (CHAR16));\r
+      }\r
+    } else {\r
+      //\r
+      // To find next <Label> in DefaultAltCfgResp.\r
+      //\r
+      *NvConfigValuePtr = TempChar;\r
+      NvConfigPtr = StrStr (NvConfigPtr + 1, L"&");\r
+    }\r
+  }\r
+  if (AppendString != NULL) {\r
+    //\r
+    // Reallocate ConfigAltResp to copy the AppendString.\r
+    //\r
+    TotalSize = StrSize (*ConfigAltResp) + StrSize (AppendString) + sizeof (CHAR16);\r
+    *ConfigAltResp = (EFI_STRING) ReallocatePool (\r
+                                    StrSize (*ConfigAltResp),\r
+                                    StrSize (*ConfigAltResp) + StrSize (AppendString) + sizeof (CHAR16),\r
+                                    *ConfigAltResp\r
+                                    );\r
+    if (*ConfigAltResp == NULL) {\r
+      Status = EFI_OUT_OF_RESOURCES;\r
+      goto Exit;\r
+    }\r
+    StrCatS (*ConfigAltResp, TotalSize / sizeof (CHAR16), AppendString);\r
+    *ConfigAltRespChanged = TRUE;\r
+  }\r
+  Status = EFI_SUCCESS;\r
+\r
+Exit:\r
+  if (AppendString != NULL) {\r
+    FreePool (AppendString);\r
+  }\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Compare the <AltResp> in AltCfgResp and DefaultAltCfgResp, if the <AltResp>\r
+  in DefaultAltCfgResp but not in AltCfgResp,add it to the AltCfgResp.\r
+\r
+  @param  AltCfgResp             Pointer to a null-terminated Unicode string in\r
+                                 <ConfigAltResp> format.\r
+  @param  DefaultAltCfgResp      Pointer to a null-terminated Unicode string in\r
+                                 <MultiConfigAltResp> format. The default value\r
+                                 string may contain more than one ConfigAltResp\r
+                                 string for the different varstore buffer.\r
+  @param  AltConfigHdr           Pointer to a Unicode string in <AltConfigHdr> format.\r
+\r
+  @retval EFI_OUT_OF_RESOURCES   Insufficient resources to store neccessary\r
+                                 structures.\r
+  @retval EFI_SUCCESS            The function finishes  successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+CompareAndMergeDefaultString (\r
+  IN OUT EFI_STRING  *AltCfgResp,\r
+  IN     EFI_STRING  DefaultAltCfgResp,\r
+  IN     EFI_STRING  AltConfigHdr\r
+  )\r
+{\r
+  EFI_STATUS     Status;\r
+  EFI_STRING     AltCfgRespBackup;\r
+  EFI_STRING     AltConfigHdrPtr;\r
+  EFI_STRING     AltConfigHdrPtrNext;\r
+  EFI_STRING     ConfigAltResp;\r
+  EFI_STRING     StringPtr;\r
+  EFI_STRING     StringPtrNext;\r
+  EFI_STRING     BlockPtr;\r
+  UINTN          ReallocateSize;\r
+  CHAR16         TempChar;\r
+  CHAR16         TempCharA;\r
+  BOOLEAN        ConfigAltRespChanged;\r
+\r
+  Status = EFI_OUT_OF_RESOURCES;\r
+  BlockPtr             = NULL;\r
+  AltConfigHdrPtrNext  = NULL;\r
+  StringPtrNext        = NULL;\r
+  ConfigAltResp        = NULL;\r
+  AltCfgRespBackup     = NULL;\r
+  ConfigAltRespChanged = FALSE;\r
+\r
+  //\r
+  //To find the <AltResp> with AltConfigHdr in DefaultAltCfgResp, ignore other <AltResp> which follow it.\r
+  //\r
+  AltConfigHdrPtr = StrStr (DefaultAltCfgResp, AltConfigHdr);\r
+  ASSERT (AltConfigHdrPtr != NULL);\r
+  AltConfigHdrPtrNext = StrStr (AltConfigHdrPtr + 1, L"&GUID");\r
+  if (AltConfigHdrPtrNext != NULL) {\r
+    TempChar = *AltConfigHdrPtrNext;\r
+    *AltConfigHdrPtrNext = L'\0';\r
+  }\r
+  //\r
+  // To find the <AltResp> with AltConfigHdr in AltCfgResp, ignore other <AltResp> which follow it.\r
+  //\r
+  StringPtr = StrStr (*AltCfgResp, AltConfigHdr);\r
+  StringPtrNext = StrStr (StringPtr + 1, L"&GUID");\r
+  if (StringPtrNext != NULL) {\r
+    TempCharA = *StringPtrNext;\r
+    *StringPtrNext = L'\0';\r
+  }\r
+  //\r
+  // Copy the content of <ConfigAltResp> which contain current AltConfigHdr in AltCfgResp.\r
+  //\r
+  ConfigAltResp = AllocateCopyPool (StrSize (*AltCfgResp), *AltCfgResp);\r
+  if (ConfigAltResp == NULL) {\r
+    goto Exit;\r
+  }\r
+  //\r
+  // To find the <ConfigBody> with AltConfigHdr in DefaultAltCfgResp.\r
+  //\r
+  BlockPtr = StrStr (AltConfigHdrPtr, L"&OFFSET=");\r
+  if (BlockPtr != NULL) {\r
+    //\r
+    // <BlockConfig>::='OFFSET='<Number>'&WIDTH='<Number>'&VALUE='<Number> style.\r
+    // Call function CompareBlockElementDefault to compare the <BlockConfig> in DefaultAltCfgResp and ConfigAltResp.\r
+    // The ConfigAltResp which may contain the new <BlockConfig> get from DefaultAltCfgResp.\r
+    //\r
+    Status = CompareBlockElementDefault (DefaultAltCfgResp, &ConfigAltResp, AltConfigHdr, &ConfigAltRespChanged);\r
+    if (EFI_ERROR(Status)) {\r
+      goto Exit;\r
+    }\r
+  } else {\r
+    //\r
+    // <NvConfig> ::= <Label>'='<String> | <Label>'='<Number> style.\r
+    // Call function CompareNameElementDefault to compare the <NvConfig> in DefaultAltCfgResp and ConfigAltResp.\r
+    // The ConfigAltResp which may contain the new <NvConfig> get from DefaultAltCfgResp.\r
+    //\r
+    Status = CompareNameElementDefault (DefaultAltCfgResp, &ConfigAltResp, AltConfigHdr, &ConfigAltRespChanged);\r
+    if (EFI_ERROR(Status)) {\r
+      goto Exit;\r
+    }\r
+  }\r
+  //\r
+  // Restore the AltCfgResp.\r
+  //\r
+  if (StringPtrNext != NULL) {\r
+    *StringPtrNext = TempCharA;\r
+  }\r
+\r
+  //\r
+  // If the ConfigAltResp has no change,no need to update the content in AltCfgResp.\r
+  //\r
+  if (ConfigAltRespChanged == FALSE) {\r
+    Status = EFI_SUCCESS;\r
+    goto Exit;\r
+  }\r
+  //\r
+  // ConfigAltResp has been changed, need to update the content in AltCfgResp.\r
+  //\r
+  if (StringPtrNext != NULL) {\r
+    ReallocateSize = StrSize (ConfigAltResp) + StrSize (StringPtrNext) + sizeof (CHAR16);\r
+  } else {\r
+    ReallocateSize = StrSize (ConfigAltResp) + sizeof (CHAR16);\r
+  }\r
+\r
+  AltCfgRespBackup = (EFI_STRING) AllocateZeroPool (ReallocateSize);\r
+  if (AltCfgRespBackup == NULL) {\r
+    goto Exit;\r
+  }\r
+\r
+  StrCatS (AltCfgRespBackup, ReallocateSize / sizeof (CHAR16), ConfigAltResp);\r
+  if (StringPtrNext != NULL) {\r
+    StrCatS (AltCfgRespBackup, ReallocateSize / sizeof (CHAR16), StringPtrNext);\r
+  }\r
+\r
+  FreePool (*AltCfgResp);\r
+  *AltCfgResp = AltCfgRespBackup;\r
+\r
+  Status = EFI_SUCCESS;\r
+\r
+Exit:\r
+  if (ConfigAltResp != NULL) {\r
+    FreePool(ConfigAltResp);\r
+  }\r
+  //\r
+  // Restore the DefaultAltCfgResp.\r
+  //\r
+  if ( AltConfigHdrPtrNext != NULL) {\r
+    *AltConfigHdrPtrNext = TempChar;\r
+    AltConfigHdrPtrNext = NULL;\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
 /**\r
   This function merges DefaultAltCfgResp string into AltCfgResp string for\r
   the missing AltCfgId in AltCfgResq.\r
@@ -632,6 +1103,13 @@ MergeDefaultString (
         StrCatS (*AltCfgResp, TotalSize / sizeof (CHAR16), StringPtrDefault);\r
         *StringPtrEnd = TempChar;\r
       }\r
+    } else {\r
+      //\r
+      // The AltCfgResp contains <AltCfgResp>.\r
+      // If the <ConfigElement> in <AltCfgResp> in the DefaultAltCfgResp but not in the\r
+      // related <AltCfgResp> in AltCfgResp, merge it to AltCfgResp. else no need to merge.\r
+      //\r
+      CompareAndMergeDefaultString (AltCfgResp, DefaultAltCfgResp, AltConfigHdr);\r
     }\r
     \r
     //\r
@@ -3802,6 +4280,8 @@ HiiConfigRoutingExtractConfig (
   EFI_HII_CONFIG_ACCESS_PROTOCOL      *ConfigAccess;\r
   EFI_STRING                          AccessProgress;\r
   EFI_STRING                          AccessResults;\r
+  EFI_STRING                          AccessProgressBackup;\r
+  EFI_STRING                          AccessResultsBackup;\r
   EFI_STRING                          DefaultResults;\r
   BOOLEAN                             FirstElement;\r
   BOOLEAN                             IfrDataParsedFlag;\r
@@ -3809,6 +4289,9 @@ HiiConfigRoutingExtractConfig (
   EFI_IFR_VARSTORE_EFI                *EfiVarStoreInfo;\r
   EFI_STRING                          ErrorPtr;\r
   UINTN                               DevicePathSize;\r
+  UINTN                               ConigStringSize;\r
+  UINTN                               ConigStringSizeNewsize;\r
+  EFI_STRING                          ConfigStringPtr;\r
 \r
   if (This == NULL || Progress == NULL || Results == NULL) {\r
     return EFI_INVALID_PARAMETER;\r
@@ -3827,6 +4310,8 @@ HiiConfigRoutingExtractConfig (
   Status         = EFI_SUCCESS;\r
   AccessResults  = NULL;\r
   AccessProgress = NULL;\r
+  AccessResultsBackup  = NULL;\r
+  AccessProgressBackup = NULL;\r
   DevicePath     = NULL;\r
   IfrDataParsedFlag = FALSE;\r
   IsEfiVarStore     = FALSE;\r
@@ -3976,6 +4461,62 @@ HiiConfigRoutingExtractConfig (
       //\r
       Status = GetConfigRespFromEfiVarStore(This, EfiVarStoreInfo, ConfigRequest, &AccessResults, &AccessProgress);\r
       FreePool (EfiVarStoreInfo);\r
+      if (EFI_ERROR (Status)) {\r
+        //\r
+        // AccessProgress indicates the parsing progress on <ConfigRequest>.\r
+        // Map it to the progress on <MultiConfigRequest> then return it.\r
+        //\r
+        *Progress = StrStr (StringPtr, AccessProgress);\r
+        goto Done;\r
+      }\r
+\r
+      //\r
+      // For EfiVarstore, call corresponding ConfigAccess protocol to get the AltCfgResp from driver.\r
+      //\r
+      Status = gBS->HandleProtocol (\r
+                      DriverHandle,\r
+                      &gEfiHiiConfigAccessProtocolGuid,\r
+                      (VOID **) &ConfigAccess\r
+                      );\r
+      if (EFI_ERROR (Status)) {\r
+        //\r
+        // The driver has EfiVarStore, may not install ConfigAccess protocol.\r
+        // So ignore the error status in this case.\r
+        //\r
+        Status = EFI_SUCCESS;\r
+      } else {\r
+        Status = ConfigAccess->ExtractConfig (\r
+                                 ConfigAccess,\r
+                                 ConfigRequest,\r
+                                 &AccessProgressBackup,\r
+                                 &AccessResultsBackup\r
+                                 );\r
+        if (!EFI_ERROR(Status)) {\r
+          //\r
+          //Merge the AltCfgResp in AccessResultsBackup to AccessResults\r
+          //\r
+          if ((AccessResultsBackup != NULL) && (StrStr (AccessResultsBackup, L"&ALTCFG=") != NULL)) {\r
+            ConigStringSize = StrSize (AccessResults);\r
+            ConfigStringPtr = StrStr (AccessResultsBackup, L"&GUID=");\r
+            ConigStringSizeNewsize = StrSize (ConfigStringPtr) + ConigStringSize + sizeof (CHAR16);\r
+            AccessResults = (EFI_STRING) ReallocatePool (\r
+                                         ConigStringSize,\r
+                                         ConigStringSizeNewsize,\r
+                                         AccessResults);\r
+            StrCatS (AccessResults, ConigStringSizeNewsize / sizeof (CHAR16), ConfigStringPtr);\r
+          }\r
+        } else {\r
+          //\r
+          // In the ExtractConfig function of some driver may not support EfiVarStore,\r
+          // may return error status, just ignore the error status in this case.\r
+          //\r
+          Status = EFI_SUCCESS;\r
+        }\r
+        if (AccessResultsBackup != NULL) {\r
+          FreePool (AccessResultsBackup);\r
+          AccessResultsBackup = NULL;\r
+        }\r
+      }\r
     } else {\r
       //\r
       // Call corresponding ConfigAccess protocol to extract settings\r