]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Library/UefiHiiLib/HiiLib.c
Fixes the GCC build 'Unused variable' warning (raised an error when warnings are...
[mirror_edk2.git] / MdeModulePkg / Library / UefiHiiLib / HiiLib.c
index 0e7ddee35a92d3e475f566b5da9ede98217d06af..4ef64428bb37eb1d0ee895f607a1a05899674597 100644 (file)
@@ -31,6 +31,11 @@ typedef struct {
   UINT8               Scope;\r
 } IFR_BLOCK_DATA;\r
 \r
+typedef struct {\r
+  EFI_VARSTORE_ID     VarStoreId;\r
+  UINT16              Size;\r
+} IFR_VARSTORAGE_DATA;\r
+\r
 //\r
 // <ConfigHdr> Template\r
 //\r
@@ -913,43 +918,93 @@ InternalHiiGetValueOfNumber (
   return EFI_SUCCESS;\r
 }\r
 \r
+/**\r
+  Get value from config request resp string.\r
+\r
+  @param ConfigElement           ConfigResp string contains the current setting.\r
+  @param VarName                 The variable name which need to get value.\r
+  @param VarValue                The return value.\r
+  \r
+  @retval EFI_SUCCESS            Get the value for the VarName\r
+  @retval EFI_OUT_OF_RESOURCES   The memory is not enough.\r
+**/\r
+EFI_STATUS\r
+GetValueFromRequest (\r
+  IN CHAR16                       *ConfigElement,\r
+  IN CHAR16                       *VarName,\r
+  OUT UINT64                      *VarValue\r
+  )\r
+{\r
+  UINT8                        *TmpBuffer;\r
+  CHAR16                       *StringPtr;\r
+  UINTN                        Length;\r
+  EFI_STATUS                   Status;\r
+\r
+  //\r
+  // Find VarName related string.\r
+  //\r
+  StringPtr = StrStr (ConfigElement, VarName);\r
+  ASSERT (StringPtr != NULL);\r
+\r
+  //\r
+  // Skip the "VarName=" string\r
+  //\r
+  StringPtr += StrLen (VarName) + 1;\r
+\r
+  //\r
+  // Get Offset\r
+  //\r
+  Status = InternalHiiGetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  *VarValue = 0;\r
+  CopyMem (VarValue, TmpBuffer, (((Length + 1) / 2) < sizeof (UINT64)) ? ((Length + 1) / 2) : sizeof (UINT64));\r
+\r
+  FreePool (TmpBuffer);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
 /**\r
   This internal function parses IFR data to validate current setting.\r
 \r
-  @param ConfigResp         ConfigResp string contains the current setting.\r
+  Base on the NameValueType, if it is TRUE, RequestElement and HiiHandle is valid;\r
+  else the VarBuffer and CurrentBlockArray is valid.\r
+\r
   @param HiiPackageList     Point to Hii package list.\r
   @param PackageListLength  The length of the pacakge.\r
   @param VarGuid            Guid of the buffer storage.\r
   @param VarName            Name of the buffer storage.\r
+  @param VarBuffer          The data buffer for the storage.\r
+  @param CurrentBlockArray  The block array from the config Requst string.\r
+  @param RequestElement     The config string for this storage.\r
+  @param HiiHandle          The HiiHandle for this formset.\r
+  @param NameValueType      Whether current storage is name/value varstore or not.\r
   \r
   @retval EFI_SUCCESS            The current setting is valid.\r
   @retval EFI_OUT_OF_RESOURCES   The memory is not enough.\r
   @retval EFI_INVALID_PARAMETER  The config string or the Hii package is invalid.\r
 **/\r
 EFI_STATUS\r
-EFIAPI\r
-InternalHiiValidateCurrentSetting (\r
-  IN EFI_STRING                    ConfigResp,\r
+ValidateQuestionFromVfr (\r
   IN EFI_HII_PACKAGE_LIST_HEADER   *HiiPackageList,\r
   IN UINTN                         PackageListLength,\r
   IN EFI_GUID                      *VarGuid,\r
-  IN CHAR16                        *VarName\r
-  )\r
-{ \r
-  IFR_BLOCK_DATA               *CurrentBlockArray;\r
-  IFR_BLOCK_DATA               *BlockData;\r
-  IFR_BLOCK_DATA               *NewBlockData;\r
-  IFR_BLOCK_DATA               VarBlockData;\r
-  EFI_STRING                   StringPtr;\r
-  UINTN                        Length;\r
-  UINT8                        *TmpBuffer;\r
-  UINT16                       Offset;\r
-  UINT16                       Width;\r
-  UINT64                       VarValue;\r
+  IN CHAR16                        *VarName,\r
+  IN UINT8                         *VarBuffer,\r
+  IN IFR_BLOCK_DATA                *CurrentBlockArray,\r
+  IN CHAR16                        *RequestElement,\r
+  IN EFI_HII_HANDLE                HiiHandle,\r
+  IN BOOLEAN                       NameValueType\r
+  )
+{
+  IFR_BLOCK_DATA               VarBlockData;
+  UINT16                       Offset;
+  UINT16                       Width;
+  UINT64                       VarValue;
   EFI_IFR_TYPE_VALUE           TmpValue;\r
-  LIST_ENTRY                   *Link;\r
-  UINT8                        *VarBuffer;\r
-  UINTN                        MaxBufferSize;\r
   EFI_STATUS                   Status;\r
   EFI_HII_PACKAGE_HEADER       PacakgeHeader;\r
   UINT32                       PackageOffset;\r
@@ -957,6 +1012,9 @@ InternalHiiValidateCurrentSetting (
   UINTN                        IfrOffset;\r
   EFI_IFR_OP_HEADER            *IfrOpHdr;\r
   EFI_IFR_VARSTORE             *IfrVarStore;\r
+  EFI_IFR_VARSTORE_NAME_VALUE  *IfrNameValueStore;\r
+  EFI_IFR_VARSTORE_EFI         *IfrEfiVarStore;\r
+  IFR_VARSTORAGE_DATA          VarStoreData;\r
   EFI_IFR_ONE_OF               *IfrOneOf;\r
   EFI_IFR_NUMERIC              *IfrNumeric;\r
   EFI_IFR_ONE_OF_OPTION        *IfrOneOfOption;\r
@@ -964,230 +1022,29 @@ InternalHiiValidateCurrentSetting (
   EFI_IFR_STRING               *IfrString;\r
   CHAR8                        *VarStoreName;\r
   UINTN                        Index;\r
-  \r
-  //\r
-  // 1. Get the current setting to current block data array and Convert them into VarBuffer\r
-  //\r
+  CHAR16                       *QuestionName;\r
+  CHAR16                       *StringPtr;\r
 \r
-  //\r
-  // Skip ConfigHdr string\r
-  //\r
-  StringPtr = ConfigResp;\r
-  StringPtr = StrStr (ConfigResp, L"&OFFSET");\r
-  if (StringPtr == NULL) {\r
-    //\r
-    // No ConfigBlock value is required to be validated.\r
-    // EFI_SUCCESS directly return.\r
-    //\r
-    return EFI_SUCCESS;\r
-  }\r
-   \r
   //\r
   // Initialize the local variables.\r
   //\r
-  Index         = 0;\r
-  VarStoreName  = NULL;\r
-  Status        = EFI_SUCCESS;\r
-  BlockData     = NULL;\r
-  NewBlockData  = NULL;\r
-  TmpBuffer     = NULL;\r
-  MaxBufferSize = HII_LIB_DEFAULT_VARSTORE_SIZE;\r
-  VarBuffer     = AllocateZeroPool (MaxBufferSize);\r
-  if (VarBuffer == NULL) {\r
-    return EFI_OUT_OF_RESOURCES;\r
-  }\r
-\r
-  //\r
-  // Init CurrentBlockArray\r
-  //\r
-  CurrentBlockArray = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));\r
-  if (CurrentBlockArray == NULL) {\r
-    Status = EFI_OUT_OF_RESOURCES;\r
-    goto Done;\r
-  }\r
-  InitializeListHead (&CurrentBlockArray->Entry);\r
-  \r
-  //\r
-  // Parse each <RequestElement> if exists\r
-  // Only <BlockName> format is supported by this help function.\r
-  // <BlockName> ::= &'OFFSET='<Number>&'WIDTH='<Number>\r
-  //\r
-  while (*StringPtr != 0 && StrnCmp (StringPtr, L"&OFFSET=", StrLen (L"&OFFSET=")) == 0) {\r
-    //\r
-    // Skip the &OFFSET= string\r
-    // \r
-    StringPtr += StrLen (L"&OFFSET=");\r
-\r
-    //\r
-    // Get Offset\r
-    //\r
-    Status = InternalHiiGetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
-    if (EFI_ERROR (Status)) {\r
-      goto Done;\r
-    }\r
-    Offset = 0;\r
-    CopyMem (\r
-      &Offset,\r
-      TmpBuffer,\r
-      (((Length + 1) / 2) < sizeof (UINT16)) ? ((Length + 1) / 2) : sizeof (UINT16)\r
-      );\r
-    FreePool (TmpBuffer);\r
-    TmpBuffer = NULL;\r
-\r
-    StringPtr += Length;\r
-    if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {\r
-      Status = EFI_INVALID_PARAMETER;\r
-      goto Done;\r
-    }\r
-    StringPtr += StrLen (L"&WIDTH=");\r
-\r
-    //\r
-    // Get Width\r
-    //\r
-    Status = InternalHiiGetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
-    if (EFI_ERROR (Status)) {\r
-      goto Done;\r
-    }\r
-    Width = 0;\r
-    CopyMem (\r
-      &Width,\r
-      TmpBuffer,\r
-      (((Length + 1) / 2) < sizeof (UINT16)) ? ((Length + 1) / 2) : sizeof (UINT16)\r
-      );\r
-    FreePool (TmpBuffer);\r
-    TmpBuffer = NULL;\r
-\r
-    StringPtr += Length;\r
-    if (*StringPtr != 0 && *StringPtr != L'&') {\r
-      Status = EFI_INVALID_PARAMETER;\r
-      goto Done;\r
-    }\r
-\r
-    if (StrnCmp (StringPtr, L"&VALUE=", StrLen (L"&VALUE=")) != 0) {\r
-      Status = EFI_INVALID_PARAMETER;\r
-      goto Done;\r
-    }\r
-    StringPtr += StrLen (L"&VALUE=");\r
-\r
-    //\r
-    // Get Value\r
-    //\r
-    Status = InternalHiiGetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
-    if (EFI_ERROR (Status)) {\r
-      goto Done;\r
-    }\r
-\r
-    StringPtr += Length;\r
-    if (*StringPtr != 0 && *StringPtr != L'&') {\r
-      Status = EFI_INVALID_PARAMETER;\r
-      goto Done;\r
-    }\r
-\r
-    //\r
-    // Check whether VarBuffer is enough\r
-    //\r
-    if ((UINTN) (Offset + Width) > MaxBufferSize) {\r
-      VarBuffer = ReallocatePool (\r
-                    MaxBufferSize,\r
-                    Offset + Width + HII_LIB_DEFAULT_VARSTORE_SIZE,\r
-                    VarBuffer\r
-                    );\r
-      if (VarBuffer == NULL) {\r
-        Status = EFI_OUT_OF_RESOURCES;\r
-        goto Done;\r
-      }\r
-      MaxBufferSize = Offset + Width + HII_LIB_DEFAULT_VARSTORE_SIZE;\r
-    }\r
-\r
-    //\r
-    // Update the Block with configuration info\r
-    //\r
-    CopyMem (VarBuffer + Offset, TmpBuffer, Width);\r
-    FreePool (TmpBuffer);\r
-    TmpBuffer = NULL;\r
-\r
-    //\r
-    // Set new Block Data\r
-    //\r
-    NewBlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));\r
-    if (NewBlockData == NULL) {\r
-      Status = EFI_OUT_OF_RESOURCES;\r
-      goto Done;\r
-    }\r
-    NewBlockData->Offset = Offset;\r
-    NewBlockData->Width  = Width;\r
-\r
-    //\r
-    // Insert the new block data into the block data array.\r
-    //\r
-    for (Link = CurrentBlockArray->Entry.ForwardLink; Link != &CurrentBlockArray->Entry; Link = Link->ForwardLink) {\r
-      BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);\r
-      if (NewBlockData->Offset == BlockData->Offset) {\r
-        if (NewBlockData->Width > BlockData->Width) {\r
-          BlockData->Width = NewBlockData->Width;\r
-        }\r
-        FreePool (NewBlockData);\r
-        break;\r
-      } else if (NewBlockData->Offset < BlockData->Offset) {\r
-        //\r
-        // Insert new block data as the previous one of this link.\r
-        //\r
-        InsertTailList (Link, &NewBlockData->Entry);\r
-        break;\r
-      }\r
-    }\r
-\r
-    //\r
-    // Insert new block data into the array tail.\r
-    //\r
-    if (Link == &CurrentBlockArray->Entry) {\r
-      InsertTailList (Link, &NewBlockData->Entry);\r
-    }\r
-\r
-    //\r
-    // If '\0', parsing is finished. \r
-    //\r
-    if (*StringPtr == 0) {\r
-      break;\r
-    }\r
-    //\r
-    // Go to next ConfigBlock \r
-    //\r
-  }\r
-\r
-  //\r
-  // Merge the aligned block data into the single block data.\r
-  //\r
-  Link = CurrentBlockArray->Entry.ForwardLink;\r
-  while ((Link != &CurrentBlockArray->Entry) && (Link->ForwardLink != &CurrentBlockArray->Entry)) {\r
-    BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);\r
-    NewBlockData = BASE_CR (Link->ForwardLink, IFR_BLOCK_DATA, Entry);\r
-    if ((NewBlockData->Offset >= BlockData->Offset) && (NewBlockData->Offset <= (BlockData->Offset + BlockData->Width))) {\r
-      if ((NewBlockData->Offset + NewBlockData->Width) > (BlockData->Offset + BlockData->Width)) {\r
-        BlockData->Width = (UINT16) (NewBlockData->Offset + NewBlockData->Width - BlockData->Offset);\r
-      }\r
-      RemoveEntryList (Link->ForwardLink);\r
-      FreePool (NewBlockData);\r
-      continue;\r
-    }\r
-    Link = Link->ForwardLink;      \r
-  }\r
-  \r
-  if (IsListEmpty (&CurrentBlockArray->Entry)) {\r
-    Status = EFI_SUCCESS;\r
-    goto Done;\r
-  }\r
+  Index             = 0;
+  VarStoreName      = NULL;
+  Status            = EFI_SUCCESS;
+  VarValue          = 0;
+  IfrVarStore       = NULL;
+  IfrNameValueStore = NULL;
+  IfrEfiVarStore    = NULL;\r
+  ZeroMem (&VarStoreData, sizeof (IFR_VARSTORAGE_DATA));\r
+  ZeroMem (&VarBlockData, sizeof (VarBlockData));\r
 \r
   //\r
-  // 2. Check IFR value is in block data, then Validate Value\r
+  // Check IFR value is in block data, then Validate Value\r
   //\r
-  ZeroMem (&VarBlockData, sizeof (VarBlockData));\r
-  VarValue      = 0;\r
-  IfrVarStore   = NULL;\r
   PackageOffset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);\r
   while (PackageOffset < PackageListLength) {\r
     CopyMem (&PacakgeHeader, (UINT8 *) HiiPackageList + PackageOffset, sizeof (PacakgeHeader));\r
-    \r
+\r
     //\r
     // Parse IFR opcode from the form package.\r
     //\r
@@ -1200,11 +1057,11 @@ InternalHiiValidateCurrentSetting (
         // Validate current setting to the value built in IFR opcode\r
         //\r
         switch (IfrOpHdr->OpCode) {\r
-        case EFI_IFR_VARSTORE_OP:          \r
+        case EFI_IFR_VARSTORE_OP:\r
           //\r
           // VarStoreId has been found. No further found.\r
           //\r
-          if (IfrVarStore != NULL) {\r
+          if (VarStoreData.VarStoreId != 0) {\r
             break;\r
           }\r
           //\r
@@ -1227,72 +1084,152 @@ InternalHiiValidateCurrentSetting (
           } else {\r
             IfrVarStore = NULL;\r
           }\r
+\r
+          if (IfrVarStore != NULL) {\r
+            VarStoreData.VarStoreId = IfrVarStore->VarStoreId;\r
+            VarStoreData.Size       = IfrVarStore->Size;\r
+          }\r
           break;\r
-        case EFI_IFR_FORM_OP:\r
-        case EFI_IFR_FORM_MAP_OP:\r
+        case EFI_IFR_VARSTORE_NAME_VALUE_OP:\r
           //\r
-          // Check the matched VarStoreId is found.\r
+          // VarStoreId has been found. No further found.\r
           //\r
-          if (IfrVarStore == NULL) {\r
-            Status = EFI_SUCCESS;\r
-            goto Done;\r
+          if (VarStoreData.VarStoreId != 0) {\r
+            break;\r
           }\r
-          break;\r
-        case EFI_IFR_ONE_OF_OP:\r
           //\r
-          // Check whether current value is the one of option.\r
+          // Find the matched VarStoreId to the input VarGuid\r
           //\r
+          IfrNameValueStore = (EFI_IFR_VARSTORE_NAME_VALUE *) IfrOpHdr;\r
+          if (!CompareGuid ((EFI_GUID *) (VOID *) &IfrNameValueStore->Guid, VarGuid)) {\r
+            IfrNameValueStore = NULL;\r
+          }\r
 \r
-          //\r
-          // OneOf question is not in IFR Form. This IFR form is not valid. \r
-          //\r
-          if (IfrVarStore == NULL) {\r
-            Status = EFI_INVALID_PARAMETER;\r
-            goto Done;\r
+          if (IfrNameValueStore != NULL) {\r
+            VarStoreData.VarStoreId = IfrNameValueStore->VarStoreId;\r
           }\r
-          // \r
-          // Check whether this question is for the requested varstore.\r
+          break;\r
+        case EFI_IFR_VARSTORE_EFI_OP:\r
           //\r
-          IfrOneOf = (EFI_IFR_ONE_OF *) IfrOpHdr;\r
-          if (IfrOneOf->Question.VarStoreId != IfrVarStore->VarStoreId) {\r
+          // VarStore is found. Don't need to search any more.\r
+          //\r
+          if (VarStoreData.VarStoreId != 0) {\r
             break;\r
           }\r
-          \r
-          //\r
-          // Get Offset by Question header and Width by DataType Flags\r
-          //\r
-          Offset = IfrOneOf->Question.VarStoreInfo.VarOffset;\r
-          Width  = (UINT16) (1 << (IfrOneOf->Flags & EFI_IFR_NUMERIC_SIZE));\r
+\r
+          IfrEfiVarStore = (EFI_IFR_VARSTORE_EFI *) IfrOpHdr;\r
+\r
           //\r
-          // Check whether this question is in current block array.\r
+          // If the length is small than the structure, this is from old efi \r
+          // varstore definition. Old efi varstore get config directly from \r
+          // GetVariable function.\r
           //\r
-          if (!BlockArrayCheck (CurrentBlockArray, Offset, Width)) {\r
-            //\r
-            // This question is not in the current configuration string. Skip it.\r
-            //\r
+          if (IfrOpHdr->Length < sizeof (EFI_IFR_VARSTORE_EFI)) {\r
             break;\r
           }\r
-          //\r
-          // Check this var question is in the var storage \r
-          //\r
-          if ((Offset + Width) > IfrVarStore->Size) {\r
+\r
+          if (CompareGuid ((EFI_GUID *) (VOID *) &IfrEfiVarStore->Guid, VarGuid)) {\r
+            VarStoreName = (CHAR8 *) IfrEfiVarStore->Name;\r
+            for (Index = 0; VarStoreName[Index] != 0; Index ++) {\r
+              if ((CHAR16) VarStoreName[Index] != VarName[Index]) {\r
+                break;\r
+              }\r
+            }\r
             //\r
-            // This question exceeds the var store size. \r
+            // The matched VarStore is found.\r
             //\r
-            Status = EFI_INVALID_PARAMETER;\r
-            goto Done;\r
+            if ((VarStoreName[Index] != 0) || (VarName[Index] != 0)) {\r
+              IfrEfiVarStore = NULL;\r
+            }\r
+          } else {\r
+            IfrEfiVarStore = NULL;\r
           }\r
 \r
+          if (IfrEfiVarStore != NULL) {\r
+            //\r
+            // Find the matched VarStore\r
+            //\r
+            VarStoreData.VarStoreId = IfrEfiVarStore->VarStoreId;\r
+            VarStoreData.Size       = IfrEfiVarStore->Size;\r
+          }\r
+          break;\r
+        case EFI_IFR_FORM_OP:\r
+        case EFI_IFR_FORM_MAP_OP:\r
           //\r
-          // Get the current value for oneof opcode\r
+          // Check the matched VarStoreId is found.\r
           //\r
-          VarValue = 0;\r
-          CopyMem (&VarValue, VarBuffer +  Offset, Width);\r
+          if (VarStoreData.VarStoreId == 0) {\r
+            return EFI_SUCCESS;\r
+          }\r
+          break;\r
+        case EFI_IFR_ONE_OF_OP:\r
+          //\r
+          // Check whether current value is the one of option.\r
+          //\r
+\r
+          //\r
+          // OneOf question is not in IFR Form. This IFR form is not valid. \r
+          //\r
+          if (VarStoreData.VarStoreId == 0) {\r
+            return EFI_INVALID_PARAMETER;\r
+          }\r
+          // \r
+          // Check whether this question is for the requested varstore.\r
+          //\r
+          IfrOneOf = (EFI_IFR_ONE_OF *) IfrOpHdr;\r
+          if (IfrOneOf->Question.VarStoreId != VarStoreData.VarStoreId) {\r
+            break;\r
+          }\r
+\r
+          if (NameValueType) {\r
+            QuestionName = HiiGetString (HiiHandle, IfrOneOf->Question.VarStoreInfo.VarName, NULL);\r
+            ASSERT (QuestionName != NULL);\r
+\r
+            if (StrStr (RequestElement, QuestionName) == NULL) {\r
+              //\r
+              // This question is not in the current configuration string. Skip it.\r
+              //\r
+              break;\r
+            }\r
+\r
+            Status = GetValueFromRequest (RequestElement, QuestionName, &VarValue);\r
+            if (EFI_ERROR (Status)) {\r
+              return Status;\r
+            }\r
+          } else {\r
+            //\r
+            // Get Offset by Question header and Width by DataType Flags\r
+            //\r
+            Offset = IfrOneOf->Question.VarStoreInfo.VarOffset;\r
+            Width  = (UINT16) (1 << (IfrOneOf->Flags & EFI_IFR_NUMERIC_SIZE));\r
+            //\r
+            // Check whether this question is in current block array.\r
+            //\r
+            if (!BlockArrayCheck (CurrentBlockArray, Offset, Width)) {\r
+              //\r
+              // This question is not in the current configuration string. Skip it.\r
+              //\r
+              break;\r
+            }\r
+            //\r
+            // Check this var question is in the var storage \r
+            //\r
+            if ((Offset + Width) > VarStoreData.Size) {\r
+              //\r
+              // This question exceeds the var store size. \r
+              //\r
+              return EFI_INVALID_PARAMETER;\r
+            }\r
+\r
+            //\r
+            // Get the current value for oneof opcode\r
+            //\r
+            VarValue = 0;\r
+            CopyMem (&VarValue, VarBuffer +  Offset, Width);\r
+          }\r
           //\r
           // Set Block Data, to be checked in the following Oneof option opcode.\r
           //\r
-          VarBlockData.Offset     = Offset;\r
-          VarBlockData.Width      = Width;\r
           VarBlockData.OpCode     = IfrOpHdr->OpCode;\r
           VarBlockData.Scope      = IfrOpHdr->Scope;\r
           break;\r
@@ -1304,56 +1241,70 @@ InternalHiiValidateCurrentSetting (
           //\r
           // Numeric question is not in IFR Form. This IFR form is not valid. \r
           //\r
-          if (IfrVarStore == NULL) {\r
-            Status = EFI_INVALID_PARAMETER;\r
-            goto Done;\r
+          if (VarStoreData.VarStoreId == 0) {\r
+            return EFI_INVALID_PARAMETER;\r
           }\r
           //\r
           // Check whether this question is for the requested varstore.\r
           //\r
           IfrNumeric = (EFI_IFR_NUMERIC *) IfrOpHdr;\r
-          if (IfrNumeric->Question.VarStoreId != IfrVarStore->VarStoreId) {\r
+          if (IfrNumeric->Question.VarStoreId != VarStoreData.VarStoreId) {\r
             break;\r
           }\r
-          \r
-          //\r
-          // Get Offset by Question header and Width by DataType Flags\r
-          //\r
-          Offset = IfrNumeric->Question.VarStoreInfo.VarOffset;\r
-          Width  = (UINT16) (1 << (IfrNumeric->Flags & EFI_IFR_NUMERIC_SIZE));\r
-          //\r
-          // Check whether this question is in current block array.\r
-          //\r
-          if (!BlockArrayCheck (CurrentBlockArray, Offset, Width)) {\r
+\r
+          if (NameValueType) {\r
+            QuestionName = HiiGetString (HiiHandle, IfrNumeric->Question.VarStoreInfo.VarName, NULL);\r
+            ASSERT (QuestionName != NULL);\r
+\r
+            if (StrStr (RequestElement, QuestionName) == NULL) {\r
+              //\r
+              // This question is not in the current configuration string. Skip it.\r
+              //\r
+              break;\r
+            }\r
+            \r
+            Status = GetValueFromRequest (RequestElement, QuestionName, &VarValue);\r
+            if (EFI_ERROR (Status)) {\r
+              return Status;\r
+            }\r
+          } else {\r
             //\r
-            // This question is not in the current configuration string. Skip it.\r
+            // Get Offset by Question header and Width by DataType Flags\r
             //\r
-            break;\r
-          }\r
-          //\r
-          // Check this var question is in the var storage \r
-          //\r
-          if ((Offset + Width) > IfrVarStore->Size) {\r
+            Offset = IfrNumeric->Question.VarStoreInfo.VarOffset;\r
+            Width  = (UINT16) (1 << (IfrNumeric->Flags & EFI_IFR_NUMERIC_SIZE));\r
             //\r
-            // This question exceeds the var store size. \r
+            // Check whether this question is in current block array.\r
             //\r
-            Status = EFI_INVALID_PARAMETER;\r
-            goto Done;\r
-          }\r
+            if (!BlockArrayCheck (CurrentBlockArray, Offset, Width)) {\r
+              //\r
+              // This question is not in the current configuration string. Skip it.\r
+              //\r
+              break;\r
+            }\r
+            //\r
+            // Check this var question is in the var storage \r
+            //\r
+            if ((Offset + Width) > VarStoreData.Size) {\r
+              //\r
+              // This question exceeds the var store size. \r
+              //\r
+              return EFI_INVALID_PARAMETER;\r
+            }\r
 \r
-          //\r
-          // Check the current value is in the numeric range.\r
-          //\r
-          VarValue = 0;\r
-          CopyMem (&VarValue, VarBuffer +  Offset, Width);\r
+            //\r
+            // Check the current value is in the numeric range.\r
+            //\r
+            VarValue = 0;\r
+            CopyMem (&VarValue, VarBuffer +  Offset, Width);\r
+          }\r
           switch (IfrNumeric->Flags & EFI_IFR_NUMERIC_SIZE) {\r
           case EFI_IFR_NUMERIC_SIZE_1:\r
             if ((UINT8) VarValue < IfrNumeric->data.u8.MinValue || (UINT8) VarValue > IfrNumeric->data.u8.MaxValue) {\r
               //\r
               // Not in the valid range.\r
               //\r
-              Status = EFI_INVALID_PARAMETER;\r
-              goto Done;\r
+              return EFI_INVALID_PARAMETER;\r
             }\r
             break;\r
           case EFI_IFR_NUMERIC_SIZE_2:\r
@@ -1361,8 +1312,7 @@ InternalHiiValidateCurrentSetting (
               //\r
               // Not in the valid range.\r
               //\r
-              Status = EFI_INVALID_PARAMETER;\r
-              goto Done;\r
+              return EFI_INVALID_PARAMETER;\r
             }\r
             break;\r
           case EFI_IFR_NUMERIC_SIZE_4:\r
@@ -1370,8 +1320,7 @@ InternalHiiValidateCurrentSetting (
               //\r
               // Not in the valid range.\r
               //\r
-              Status = EFI_INVALID_PARAMETER;\r
-              goto Done;\r
+              return EFI_INVALID_PARAMETER;\r
             }\r
             break;\r
           case EFI_IFR_NUMERIC_SIZE_8:\r
@@ -1379,8 +1328,7 @@ InternalHiiValidateCurrentSetting (
               //\r
               // Not in the valid range.\r
               //\r
-              Status = EFI_INVALID_PARAMETER;\r
-              goto Done;\r
+              return EFI_INVALID_PARAMETER;\r
             }\r
             break;\r
           }\r
@@ -1394,52 +1342,69 @@ InternalHiiValidateCurrentSetting (
           //\r
           // CheckBox question is not in IFR Form. This IFR form is not valid. \r
           //\r
-          if (IfrVarStore == NULL) {\r
-            Status = EFI_INVALID_PARAMETER;\r
-            goto Done;\r
+          if (VarStoreData.VarStoreId == 0) {\r
+            return EFI_INVALID_PARAMETER;\r
           }\r
 \r
           //\r
           // Check whether this question is for the requested varstore.\r
           //\r
           IfrCheckBox = (EFI_IFR_CHECKBOX *) IfrOpHdr;\r
-          if (IfrCheckBox->Question.VarStoreId != IfrVarStore->VarStoreId) {\r
+          if (IfrCheckBox->Question.VarStoreId != VarStoreData.VarStoreId) {\r
             break;\r
           }\r
-          \r
-          //\r
-          // Get Offset by Question header\r
-          //\r
-          Offset = IfrCheckBox->Question.VarStoreInfo.VarOffset;\r
-          Width  = (UINT16) sizeof (BOOLEAN);\r
-          //\r
-          // Check whether this question is in current block array.\r
-          //\r
-          if (!BlockArrayCheck (CurrentBlockArray, Offset, Width)) {\r
+\r
+          if (NameValueType) {\r
+            QuestionName = HiiGetString (HiiHandle, IfrCheckBox->Question.VarStoreInfo.VarName, NULL);\r
+            ASSERT (QuestionName != NULL);\r
+\r
+            if (StrStr (RequestElement, QuestionName) == NULL) {\r
+              //\r
+              // This question is not in the current configuration string. Skip it.\r
+              //\r
+              break;\r
+            }\r
+            \r
+            Status = GetValueFromRequest (RequestElement, QuestionName, &VarValue);\r
+            if (EFI_ERROR (Status)) {\r
+              return Status;\r
+            }\r
+          } else {\r
             //\r
-            // This question is not in the current configuration string. Skip it.\r
+            // Get Offset by Question header\r
             //\r
-            break;\r
-          }\r
-          //\r
-          // Check this var question is in the var storage \r
-          //\r
-          if ((Offset + Width) > IfrVarStore->Size) {\r
+            Offset = IfrCheckBox->Question.VarStoreInfo.VarOffset;\r
+            Width  = (UINT16) sizeof (BOOLEAN);\r
             //\r
-            // This question exceeds the var store size. \r
+            // Check whether this question is in current block array.\r
             //\r
-            Status = EFI_INVALID_PARAMETER;\r
-            goto Done;\r
+            if (!BlockArrayCheck (CurrentBlockArray, Offset, Width)) {\r
+              //\r
+              // This question is not in the current configuration string. Skip it.\r
+              //\r
+              break;\r
+            }\r
+            //\r
+            // Check this var question is in the var storage \r
+            //\r
+            if ((Offset + Width) > VarStoreData.Size) {\r
+              //\r
+              // This question exceeds the var store size. \r
+              //\r
+              return EFI_INVALID_PARAMETER;\r
+            }\r
+            //\r
+            // Check the current value is in the numeric range.\r
+            //\r
+            VarValue = 0;\r
+            CopyMem (&VarValue, VarBuffer +  Offset, Width);\r
           }\r
-\r
           //\r
           // Boolean type, only 1 and 0 is valid.\r
           //\r
-          if (*(VarBuffer + Offset) > 1) {\r
-            Status = EFI_INVALID_PARAMETER;\r
-            goto Done;            \r
+          if (VarValue > 1) {\r
+            return EFI_INVALID_PARAMETER;\r
           }\r
-          \r
           break;\r
         case EFI_IFR_STRING_OP:\r
           //\r
@@ -1449,124 +1414,471 @@ InternalHiiValidateCurrentSetting (
           //\r
           // CheckBox question is not in IFR Form. This IFR form is not valid. \r
           //\r
-          if (IfrVarStore == NULL) {\r
-            Status = EFI_INVALID_PARAMETER;\r
-            goto Done;\r
+          if (VarStoreData.VarStoreId == 0) {\r
+            return EFI_INVALID_PARAMETER;\r
           }\r
 \r
           //\r
           // Check whether this question is for the requested varstore.\r
           //\r
           IfrString = (EFI_IFR_STRING *) IfrOpHdr;\r
-          if (IfrString->Question.VarStoreId != IfrVarStore->VarStoreId) {\r
+          if (IfrString->Question.VarStoreId != VarStoreData.VarStoreId) {\r
             break;\r
           }\r
-          \r
           //\r
-          // Get Offset/Width by Question header and OneOf Flags\r
+          // Get Width by OneOf Flags\r
           //\r
-          Offset = IfrString->Question.VarStoreInfo.VarOffset;\r
           Width  = (UINT16) (IfrString->MaxSize * sizeof (UINT16));\r
-          //\r
-          // Check whether this question is in current block array.\r
-          //\r
-          if (!BlockArrayCheck (CurrentBlockArray, Offset, Width)) {\r
+          if (NameValueType) {\r
+            QuestionName = HiiGetString (HiiHandle, IfrString->Question.VarStoreInfo.VarName, NULL);\r
+            ASSERT (QuestionName != NULL);\r
+\r
+            StringPtr = StrStr (RequestElement, QuestionName);\r
+            if (StringPtr == NULL) {\r
+              //\r
+              // This question is not in the current configuration string. Skip it.\r
+              //\r
+              break;\r
+            }\r
+\r
+            //\r
+            // Skip the "=".\r
+            // \r
+            StringPtr += 1;\r
+            \r
+            //\r
+            // Check current string length is less than maxsize\r
+            //\r
+            if (StrSize (StringPtr) > Width) {\r
+              return EFI_INVALID_PARAMETER;\r
+            }\r
+          } else {\r
             //\r
-            // This question is not in the current configuration string. Skip it.\r
+            // Get Offset/Width by Question header and OneOf Flags\r
             //\r
+            Offset = IfrString->Question.VarStoreInfo.VarOffset;\r
+            //\r
+            // Check whether this question is in current block array.\r
+            //\r
+            if (!BlockArrayCheck (CurrentBlockArray, Offset, Width)) {\r
+              //\r
+              // This question is not in the current configuration string. Skip it.\r
+              //\r
+              break;\r
+            }\r
+            //\r
+            // Check this var question is in the var storage \r
+            //\r
+            if ((Offset + Width) > VarStoreData.Size) {\r
+              //\r
+              // This question exceeds the var store size. \r
+              //\r
+              return EFI_INVALID_PARAMETER;\r
+            }\r
+\r
+            //\r
+            // Check current string length is less than maxsize\r
+            //\r
+            if (StrSize ((CHAR16 *) (VarBuffer + Offset)) > Width) {\r
+              return EFI_INVALID_PARAMETER;\r
+            }\r
+          }\r
+          break;\r
+        case EFI_IFR_ONE_OF_OPTION_OP:\r
+          //\r
+          // Opcode Scope is zero. This one of option is not to be checked. \r
+          //\r
+          if (VarBlockData.Scope == 0) {\r
             break;\r
           }\r
+\r
           //\r
-          // Check this var question is in the var storage \r
+          // Only check for OneOf and OrderList opcode\r
           //\r
-          if ((Offset + Width) > IfrVarStore->Size) {\r
+          IfrOneOfOption = (EFI_IFR_ONE_OF_OPTION *) IfrOpHdr;\r
+          if (VarBlockData.OpCode == EFI_IFR_ONE_OF_OP) {\r
             //\r
-            // This question exceeds the var store size. \r
+            // Check current value is the value of one of option.\r
             //\r
-            Status = EFI_INVALID_PARAMETER;\r
-            goto Done;\r
+            ASSERT (IfrOneOfOption->Type <= EFI_IFR_TYPE_NUM_SIZE_64);\r
+            ZeroMem (&TmpValue, sizeof (EFI_IFR_TYPE_VALUE));\r
+            CopyMem (&TmpValue, &IfrOneOfOption->Value, IfrOneOfOption->Header.Length - OFFSET_OF (EFI_IFR_ONE_OF_OPTION, Value));\r
+            if (VarValue == TmpValue.u64) {\r
+              //\r
+              // The value is one of option value.\r
+              // Set OpCode to Zero, don't need check again.\r
+              //\r
+              VarBlockData.OpCode = 0;\r
+            }\r
           }\r
-          \r
+          break;\r
+        case EFI_IFR_END_OP:\r
           //\r
-          // Check current string length is less than maxsize\r
+          // Decrease opcode scope for the validated opcode\r
           //\r
-          if (StrSize ((CHAR16 *) (VarBuffer + Offset)) > Width) {\r
-            Status = EFI_INVALID_PARAMETER;\r
-            goto Done;            \r
+          if (VarBlockData.Scope > 0) {\r
+            VarBlockData.Scope --;\r
+          }\r
+\r
+          //\r
+          // OneOf value doesn't belong to one of option value. \r
+          //\r
+          if ((VarBlockData.Scope == 0) && (VarBlockData.OpCode == EFI_IFR_ONE_OF_OP)) {\r
+            return EFI_INVALID_PARAMETER;\r
           }\r
           break;\r
-        case EFI_IFR_ONE_OF_OPTION_OP:\r
+        default:\r
           //\r
-          // Opcode Scope is zero. This one of option is not to be checked. \r
+          // Increase Scope for the validated opcode\r
           //\r
-          if (VarBlockData.Scope == 0) {\r
-            break;\r
+          if (VarBlockData.Scope > 0) {\r
+            VarBlockData.Scope = (UINT8) (VarBlockData.Scope + IfrOpHdr->Scope);\r
           }\r
+          break;\r
+        }\r
+        //\r
+        // Go to the next opcode\r
+        //\r
+        IfrOffset += IfrOpHdr->Length;\r
+      }\r
+      //\r
+      // Only one form is in a package list.\r
+      //\r
+      break;\r
+    }\r
+\r
+    //\r
+    // Go to next package.\r
+    //\r
+    PackageOffset += PacakgeHeader.Length;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  This internal function parses IFR data to validate current setting.\r
+\r
+  @param ConfigElement         ConfigResp element string contains the current setting.\r
+  @param CurrentBlockArray     Current block array.\r
+  @param VarBuffer             Data buffer for this varstore.\r
+  \r
+  @retval EFI_SUCCESS            The current setting is valid.\r
+  @retval EFI_OUT_OF_RESOURCES   The memory is not enough.\r
+  @retval EFI_INVALID_PARAMETER  The config string or the Hii package is invalid.\r
+**/\r
+EFI_STATUS\r
+GetBlockDataInfo (\r
+  IN  CHAR16                        *ConfigElement,\r
+  OUT IFR_BLOCK_DATA                **CurrentBlockArray,\r
+  OUT UINT8                         **VarBuffer\r
+  )\r
+{\r
+  IFR_BLOCK_DATA               *BlockData;\r
+  IFR_BLOCK_DATA               *NewBlockData;\r
+  EFI_STRING                   StringPtr;\r
+  UINTN                        Length;\r
+  UINT8                        *TmpBuffer;\r
+  UINT16                       Offset;\r
+  UINT16                       Width;\r
+  LIST_ENTRY                   *Link;
+  UINTN                        MaxBufferSize;
+  EFI_STATUS                   Status;
+  IFR_BLOCK_DATA               *BlockArray;
+  UINT8                        *DataBuffer;
+  
+  //
+  // Initialize the local variables.
+  //
+  Status        = EFI_SUCCESS;
+  BlockData     = NULL;
+  NewBlockData  = NULL;
+  TmpBuffer     = NULL;\r
+  BlockArray    = NULL;\r
+  MaxBufferSize = HII_LIB_DEFAULT_VARSTORE_SIZE;\r
+  DataBuffer     = AllocateZeroPool (MaxBufferSize);\r
+  if (DataBuffer == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  //\r
+  // Init BlockArray\r
+  //\r
+  BlockArray = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));\r
+  if (BlockArray == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto Done;\r
+  }\r
+  InitializeListHead (&BlockArray->Entry);\r
+\r
+  StringPtr = StrStr (ConfigElement, L"&OFFSET=");\r
+  ASSERT (StringPtr != NULL);\r
+\r
+  //\r
+  // Parse each <RequestElement> if exists\r
+  // Only <BlockName> format is supported by this help function.\r
+  // <BlockName> ::= &'OFFSET='<Number>&'WIDTH='<Number>\r
+  //\r
+  while (*StringPtr != 0 && StrnCmp (StringPtr, L"&OFFSET=", StrLen (L"&OFFSET=")) == 0) {\r
+    //\r
+    // Skip the &OFFSET= string\r
+    // \r
+    StringPtr += StrLen (L"&OFFSET=");\r
+\r
+    //\r
+    // Get Offset\r
+    //\r
+    Status = InternalHiiGetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
+    if (EFI_ERROR (Status)) {\r
+      goto Done;\r
+    }\r
+    Offset = 0;\r
+    CopyMem (\r
+      &Offset,\r
+      TmpBuffer,\r
+      (((Length + 1) / 2) < sizeof (UINT16)) ? ((Length + 1) / 2) : sizeof (UINT16)\r
+      );\r
+    FreePool (TmpBuffer);\r
+    TmpBuffer = NULL;\r
+\r
+    StringPtr += Length;\r
+    if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {\r
+      Status = EFI_INVALID_PARAMETER;\r
+      goto Done;\r
+    }\r
+    StringPtr += StrLen (L"&WIDTH=");\r
+\r
+    //\r
+    // Get Width\r
+    //\r
+    Status = InternalHiiGetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
+    if (EFI_ERROR (Status)) {\r
+      goto Done;\r
+    }\r
+    Width = 0;\r
+    CopyMem (\r
+      &Width,\r
+      TmpBuffer,\r
+      (((Length + 1) / 2) < sizeof (UINT16)) ? ((Length + 1) / 2) : sizeof (UINT16)\r
+      );\r
+    FreePool (TmpBuffer);\r
+    TmpBuffer = NULL;\r
 \r
-          //\r
-          // Only check for OneOf and OrderList opcode\r
-          //\r
-          IfrOneOfOption = (EFI_IFR_ONE_OF_OPTION *) IfrOpHdr;\r
-          if (VarBlockData.OpCode == EFI_IFR_ONE_OF_OP) {\r
-            //\r
-            // Check current value is the value of one of option.\r
-            //\r
-            ASSERT (IfrOneOfOption->Type <= EFI_IFR_TYPE_NUM_SIZE_64);\r
-            ZeroMem (&TmpValue, sizeof (EFI_IFR_TYPE_VALUE));\r
-            CopyMem (&TmpValue, &IfrOneOfOption->Value, IfrOneOfOption->Header.Length - OFFSET_OF (EFI_IFR_ONE_OF_OPTION, Value));\r
-            if (VarValue == TmpValue.u64) {\r
-              //\r
-              // The value is one of option value.\r
-              // Set OpCode to Zero, don't need check again.\r
-              //\r
-              VarBlockData.OpCode = 0;\r
-            }\r
-          }\r
+    StringPtr += Length;\r
+    if (*StringPtr != 0 && *StringPtr != L'&') {\r
+      Status = EFI_INVALID_PARAMETER;\r
+      goto Done;\r
+    }\r
 \r
-          break;\r
-        case EFI_IFR_END_OP:\r
-          //\r
-          // Decrease opcode scope for the validated opcode\r
-          //\r
-          if (VarBlockData.Scope > 0) {\r
-            VarBlockData.Scope --;\r
-          }\r
+    if (StrnCmp (StringPtr, L"&VALUE=", StrLen (L"&VALUE=")) != 0) {\r
+      Status = EFI_INVALID_PARAMETER;\r
+      goto Done;\r
+    }\r
+    StringPtr += StrLen (L"&VALUE=");\r
 \r
-          //\r
-          // OneOf value doesn't belong to one of option value. \r
-          //\r
-          if ((VarBlockData.Scope == 0) && (VarBlockData.OpCode == EFI_IFR_ONE_OF_OP)) {\r
-            Status = EFI_INVALID_PARAMETER;\r
-            goto Done;\r
-          }\r
-          break;\r
-        default:\r
-          //\r
-          // Increase Scope for the validated opcode\r
-          //\r
-          if (VarBlockData.Scope > 0) {\r
-            VarBlockData.Scope = (UINT8) (VarBlockData.Scope + IfrOpHdr->Scope);\r
-          }\r
-          break;\r
+    //\r
+    // Get Value\r
+    //\r
+    Status = InternalHiiGetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
+    if (EFI_ERROR (Status)) {\r
+      goto Done;\r
+    }\r
+\r
+    StringPtr += Length;\r
+    if (*StringPtr != 0 && *StringPtr != L'&') {\r
+      Status = EFI_INVALID_PARAMETER;\r
+      goto Done;\r
+    }\r
+\r
+    //\r
+    // Check whether VarBuffer is enough\r
+    //\r
+    if ((UINTN) (Offset + Width) > MaxBufferSize) {\r
+      DataBuffer = ReallocatePool (\r
+                    MaxBufferSize,\r
+                    Offset + Width + HII_LIB_DEFAULT_VARSTORE_SIZE,\r
+                    DataBuffer\r
+                    );\r
+      if (DataBuffer == NULL) {\r
+        Status = EFI_OUT_OF_RESOURCES;\r
+        goto Done;\r
+      }\r
+      MaxBufferSize = Offset + Width + HII_LIB_DEFAULT_VARSTORE_SIZE;\r
+    }\r
+\r
+    //\r
+    // Update the Block with configuration info\r
+    //\r
+    CopyMem (DataBuffer + Offset, TmpBuffer, Width);\r
+    FreePool (TmpBuffer);\r
+    TmpBuffer = NULL;\r
+\r
+    //\r
+    // Set new Block Data\r
+    //\r
+    NewBlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));\r
+    if (NewBlockData == NULL) {\r
+      Status = EFI_OUT_OF_RESOURCES;\r
+      goto Done;\r
+    }\r
+    NewBlockData->Offset = Offset;\r
+    NewBlockData->Width  = Width;\r
+\r
+    //\r
+    // Insert the new block data into the block data array.\r
+    //\r
+    for (Link = BlockArray->Entry.ForwardLink; Link != &BlockArray->Entry; Link = Link->ForwardLink) {\r
+      BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);\r
+      if (NewBlockData->Offset == BlockData->Offset) {\r
+        if (NewBlockData->Width > BlockData->Width) {\r
+          BlockData->Width = NewBlockData->Width;\r
         }\r
+        FreePool (NewBlockData);\r
+        break;\r
+      } else if (NewBlockData->Offset < BlockData->Offset) {\r
         //\r
-        // Go to the next opcode\r
+        // Insert new block data as the previous one of this link.\r
         //\r
-        IfrOffset += IfrOpHdr->Length;\r
+        InsertTailList (Link, &NewBlockData->Entry);\r
+        break;\r
       }\r
-      //\r
-      // Only one form is in a package list.\r
-      //\r
+    }\r
+\r
+    //\r
+    // Insert new block data into the array tail.\r
+    //\r
+    if (Link == &BlockArray->Entry) {\r
+      InsertTailList (Link, &NewBlockData->Entry);\r
+    }\r
+\r
+    //\r
+    // If '\0', parsing is finished. \r
+    //\r
+    if (*StringPtr == 0) {\r
       break;\r
     }\r
-    \r
     //\r
-    // Go to next package.\r
+    // Go to next ConfigBlock \r
     //\r
-    PackageOffset += PacakgeHeader.Length;      \r
   }\r
 \r
+  //\r
+  // Merge the aligned block data into the single block data.\r
+  //\r
+  Link = BlockArray->Entry.ForwardLink;\r
+  while ((Link != &BlockArray->Entry) && (Link->ForwardLink != &BlockArray->Entry)) {\r
+    BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);\r
+    NewBlockData = BASE_CR (Link->ForwardLink, IFR_BLOCK_DATA, Entry);\r
+    if ((NewBlockData->Offset >= BlockData->Offset) && (NewBlockData->Offset <= (BlockData->Offset + BlockData->Width))) {\r
+      if ((NewBlockData->Offset + NewBlockData->Width) > (BlockData->Offset + BlockData->Width)) {\r
+        BlockData->Width = (UINT16) (NewBlockData->Offset + NewBlockData->Width - BlockData->Offset);\r
+      }\r
+      RemoveEntryList (Link->ForwardLink);\r
+      FreePool (NewBlockData);\r
+      continue;\r
+    }\r
+    Link = Link->ForwardLink;\r
+  }\r
+\r
+  *VarBuffer         = DataBuffer;\r
+  *CurrentBlockArray = BlockArray;\r
+  return EFI_SUCCESS;\r
+\r
 Done:\r
+  if (DataBuffer != NULL) {\r
+    FreePool (DataBuffer);\r
+  }\r
+  \r
+  if (BlockArray != NULL) {\r
+    //\r
+    // Free Link Array CurrentBlockArray\r
+    //\r
+    while (!IsListEmpty (&BlockArray->Entry)) {\r
+      BlockData = BASE_CR (BlockArray->Entry.ForwardLink, IFR_BLOCK_DATA, Entry);\r
+      RemoveEntryList (&BlockData->Entry);\r
+      FreePool (BlockData);\r
+    }\r
+    FreePool (BlockArray);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  This internal function parses IFR data to validate current setting.\r
+\r
+  @param ConfigResp         ConfigResp string contains the current setting.\r
+  @param HiiPackageList     Point to Hii package list.\r
+  @param PackageListLength  The length of the pacakge.\r
+  @param VarGuid            Guid of the buffer storage.\r
+  @param VarName            Name of the buffer storage.\r
+  @param HiiHandle          The HiiHandle for this package.\r
+  \r
+  @retval EFI_SUCCESS            The current setting is valid.\r
+  @retval EFI_OUT_OF_RESOURCES   The memory is not enough.\r
+  @retval EFI_INVALID_PARAMETER  The config string or the Hii package is invalid.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+InternalHiiValidateCurrentSetting (\r
+  IN EFI_STRING                    ConfigResp,\r
+  IN EFI_HII_PACKAGE_LIST_HEADER   *HiiPackageList,\r
+  IN UINTN                         PackageListLength,\r
+  IN EFI_GUID                      *VarGuid,\r
+  IN CHAR16                        *VarName,\r
+  IN EFI_HII_HANDLE                HiiHandle\r
+  )\r
+{\r
+  CHAR16              *StringPtr;\r
+  EFI_STATUS          Status;\r
+  IFR_BLOCK_DATA      *CurrentBlockArray;\r
+  IFR_BLOCK_DATA      *BlockData;\r
+  UINT8               *VarBuffer;\r
+  BOOLEAN             NameValueType;\r
+\r
+  CurrentBlockArray = NULL;\r
+  VarBuffer         = NULL;\r
+  StringPtr         = NULL;\r
+  Status            = EFI_SUCCESS;\r
+\r
+  //\r
+  // If StringPtr != NULL, get the request elements.\r
+  //\r
+  if (StrStr (ConfigResp, L"&OFFSET=") != NULL) {\r
+    Status = GetBlockDataInfo(ConfigResp, &CurrentBlockArray, &VarBuffer);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+    NameValueType = FALSE;\r
+  } else {\r
+    //\r
+    // Skip header part.\r
+    //\r
+    StringPtr = StrStr (ConfigResp, L"PATH=");\r
+    ASSERT (StringPtr != NULL);\r
+\r
+    if (StrStr (StringPtr, L"&") != NULL) {\r
+      NameValueType = TRUE;\r
+    } else {\r
+      //\r
+      // Not found Request element, return success.\r
+      //\r
+      return EFI_SUCCESS;\r
+    }\r
+  }\r
+\r
+  Status = ValidateQuestionFromVfr(\r
+                          HiiPackageList,\r
+                          PackageListLength,\r
+                          VarGuid,\r
+                          VarName,\r
+                          VarBuffer,\r
+                          CurrentBlockArray,\r
+                          ConfigResp,\r
+                          HiiHandle,\r
+                          NameValueType\r
+                          );\r
+\r
   if (VarBuffer != NULL) {\r
     FreePool (VarBuffer);\r
   }\r
@@ -1580,12 +1892,40 @@ Done:
       RemoveEntryList (&BlockData->Entry);\r
       FreePool (BlockData);\r
     }\r
-    FreePool (CurrentBlockArray);    \r
+    FreePool (CurrentBlockArray);\r
   }\r
 \r
   return Status;\r
 }\r
 \r
+/**\r
+  Check whether the ConfigRequest string has the request elements.\r
+  For EFI_HII_VARSTORE_BUFFER type, the request has "&OFFSET=****&WIDTH=****..." format.\r
+  For EFI_HII_VARSTORE_NAME_VALUE type, the request has "&NAME1**&NAME2..." format.\r
+\r
+  @param  ConfigRequest      The input config request string.\r
+\r
+  @retval  TRUE              The input include config request elements.\r
+  @retval  FALSE             The input string not includes.\r
+                                 \r
+**/\r
+BOOLEAN\r
+GetElementsFromRequest (\r
+  IN EFI_STRING    ConfigRequest\r
+  )\r
+{\r
+  EFI_STRING   TmpRequest;\r
+\r
+  TmpRequest = StrStr (ConfigRequest, L"PATH=");\r
+  ASSERT (TmpRequest != NULL);\r
+\r
+  if ((StrStr (TmpRequest, L"&OFFSET=") != NULL) || (StrStr (TmpRequest, L"&") != NULL)) {\r
+    return TRUE;\r
+  }\r
+\r
+  return FALSE;\r
+}\r
+\r
 /**\r
   This function parses the input ConfigRequest string and its matched IFR code\r
   string for setting default value and validating current setting.\r
@@ -1765,7 +2105,7 @@ InternalHiiIfrValueAction (
       // Its default value and validating can't execute by parsing IFR data.\r
       // Directly jump into the next ConfigAltResp string for another pair Guid, Name, and Path.   \r
       //\r
-           Status = EFI_SUCCESS;\r
+      Status = EFI_SUCCESS;\r
       goto NextConfigAltResp;\r
     }\r
 \r
@@ -1822,7 +2162,7 @@ InternalHiiIfrValueAction (
     //\r
     // Only the ConfigHdr is found. Not any block data is found. No data is required to be validated and set.\r
     //\r
-    if (StrStr (ConfigResp, L"&OFFSET=") == NULL) {\r
+    if (!GetElementsFromRequest (ConfigResp)) {\r
       goto NextConfigAltResp;\r
     }\r
     \r
@@ -1839,7 +2179,7 @@ InternalHiiIfrValueAction (
       //\r
       // Current Setting is in ConfigResp, will be set into buffer, then check it again.\r
       //\r
-      Status = InternalHiiValidateCurrentSetting (ConfigResp, HiiPackageList, PackageListLength, VarGuid, VarName);\r
+      Status = InternalHiiValidateCurrentSetting (ConfigResp, HiiPackageList, PackageListLength, VarGuid, VarName, HiiHandle);\r
     }\r
 \r
     if (EFI_ERROR (Status)) {\r
@@ -1855,10 +2195,10 @@ NextConfigAltResp:
       HiiPackageList = NULL;\r
     }\r
     \r
-       if (ConfigResp != NULL) {\r
-         FreePool (ConfigResp);\r
-         ConfigResp = NULL;\r
-       }\r
+    if (ConfigResp != NULL) {\r
+      FreePool (ConfigResp);\r
+      ConfigResp = NULL;\r
+    }\r
 \r
     //\r
     // Free the allocated buffer.\r
@@ -2858,6 +3198,82 @@ HiiCreateGotoOpCode (
   return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_REF_OP, sizeof (OpCode));\r
 }\r
 \r
+/**\r
+  Create EFI_IFR_REF_OP, EFI_IFR_REF2_OP, EFI_IFR_REF3_OP and EFI_IFR_REF4_OP opcode.\r
+\r
+  When RefDevicePath is not zero, EFI_IFR_REF4 opcode will be created. \r
+  When RefDevicePath is zero and RefFormSetId is not NULL, EFI_IFR_REF3 opcode will be created.\r
+  When RefDevicePath is zero, RefFormSetId is NULL and RefQuestionId is not zero, EFI_IFR_REF2 opcode will be created.\r
+  When RefDevicePath is zero, RefFormSetId is NULL and RefQuestionId is zero, EFI_IFR_REF opcode will be created.\r
+\r
+  If OpCodeHandle is NULL, then ASSERT().\r
+  If any reserved bits are set in QuestionFlags, then ASSERT().\r
+\r
+  @param[in]  OpCodeHandle   The handle to the buffer of opcodes.\r
+  @param[in]  RefFormId      The Destination Form ID.\r
+  @param[in]  Prompt         The string ID for Prompt.\r
+  @param[in]  Help           The string ID for Help.\r
+  @param[in]  QuestionFlags  The flags in Question Header\r
+  @param[in]  QuestionId     Question ID.\r
+  @param[in]  RefQuestionId  The question on the form to which this link is referring. \r
+                             If its value is zero, then the link refers to the top of the form.\r
+  @param[in]  RefFormSetId   The form set to which this link is referring. If its value is NULL, and RefDevicePath is \r
+                             zero, then the link is to the current form set.\r
+  @param[in]  RefDevicePath  The string identifier that specifies the string containing the text representation of \r
+                             the device path to which the form set containing the form specified by FormId.\r
+                             If its value is zero, then the link refers to the current page.\r
+\r
+  @retval NULL   There is not enough space left in Buffer to add the opcode.\r
+  @retval Other  A pointer to the created opcode.\r
+\r
+**/\r
+UINT8 *\r
+EFIAPI\r
+HiiCreateGotoExOpCode (\r
+  IN VOID             *OpCodeHandle,\r
+  IN EFI_FORM_ID      RefFormId,\r
+  IN EFI_STRING_ID    Prompt,\r
+  IN EFI_STRING_ID    Help,\r
+  IN UINT8            QuestionFlags,\r
+  IN EFI_QUESTION_ID  QuestionId,\r
+  IN EFI_QUESTION_ID  RefQuestionId,\r
+  IN EFI_GUID         *RefFormSetId,    OPTIONAL\r
+  IN EFI_STRING_ID    RefDevicePath\r
+  )\r
+{\r
+  EFI_IFR_REF4  OpCode;\r
+  UINTN         OpCodeSize;\r
+\r
+  ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED))) == 0);\r
+\r
+  ZeroMem (&OpCode, sizeof (OpCode));\r
+  OpCode.Question.Header.Prompt = Prompt;\r
+  OpCode.Question.Header.Help   = Help;\r
+  OpCode.Question.QuestionId    = QuestionId;\r
+  OpCode.Question.Flags         = QuestionFlags;\r
+  OpCode.FormId                 = RefFormId;\r
+  OpCode.QuestionId             = RefQuestionId;\r
+  OpCode.DevicePath             = RefDevicePath;\r
+  if (RefFormSetId != NULL) {\r
+    CopyMem (&OpCode.FormSetId, RefFormSetId, sizeof (OpCode.FormSetId));\r
+  }\r
+\r
+  //\r
+  // Cacluate OpCodeSize based on the input Ref value.\r
+  // Try to use the small OpCode to save size.\r
+  //\r
+  OpCodeSize = sizeof (EFI_IFR_REF);\r
+  if (RefDevicePath != 0) {\r
+    OpCodeSize = sizeof (EFI_IFR_REF4);\r
+  } else if (RefFormSetId != NULL) {\r
+    OpCodeSize = sizeof (EFI_IFR_REF3);\r
+  } else if (RefQuestionId != 0) {\r
+    OpCodeSize = sizeof (EFI_IFR_REF2);\r
+  }\r
+\r
+  return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_REF_OP, OpCodeSize);\r
+}\r
+\r
 /**\r
   Create EFI_IFR_CHECKBOX_OP opcode.\r
 \r