]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Library/UefiHiiLib/HiiLib.c
specify operand order
[mirror_edk2.git] / MdeModulePkg / Library / UefiHiiLib / HiiLib.c
index e1d8a64730fc789f1241ac0cd9a7ece777ac6ab6..2a42cd799e1e8aa3e1a5e0d51bdd548077392f01 100644 (file)
 \r
 #include "InternalHiiLib.h"\r
 \r
+#define GUID_CONFIG_STRING_TYPE 0x00\r
+#define NAME_CONFIG_STRING_TYPE 0x01\r
+#define PATH_CONFIG_STRING_TYPE 0x02\r
+\r
+#define ACTION_SET_DEFAUTL_VALUE 0x01\r
+#define ACTION_VALIDATE_SETTING  0x02\r
+\r
+#define HII_LIB_DEFAULT_VARSTORE_SIZE  0x200\r
+\r
+typedef struct {\r
+  LIST_ENTRY          Entry;      // Link to Block array\r
+  UINT16              Offset;\r
+  UINT16              Width;\r
+  UINT8               OpCode;\r
+  UINT8               Scope;\r
+} IFR_BLOCK_DATA;\r
+\r
 //\r
 // <ConfigHdr> Template\r
 //\r
@@ -29,6 +46,62 @@ GLOBAL_REMOVE_IF_UNREFERENCED CONST EFI_HII_PACKAGE_HEADER  mEndOfPakageList = {
   EFI_HII_PACKAGE_END\r
 };\r
 \r
+/**\r
+  Extract Hii package list GUID for given HII handle.\r
+\r
+  If HiiHandle could not be found in the HII database, then ASSERT.\r
+  If Guid is NULL, then ASSERT.\r
+\r
+  @param  Handle              Hii handle\r
+  @param  Guid                Package list GUID\r
+\r
+  @retval EFI_SUCCESS         Successfully extract GUID from Hii database.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+InternalHiiExtractGuidFromHiiHandle (\r
+  IN      EFI_HII_HANDLE      Handle,\r
+  OUT     EFI_GUID            *Guid\r
+  )\r
+{\r
+  EFI_STATUS                   Status;\r
+  UINTN                        BufferSize;\r
+  EFI_HII_PACKAGE_LIST_HEADER  *HiiPackageList;\r
+\r
+  ASSERT (Guid != NULL);\r
+  ASSERT (Handle != NULL);\r
+\r
+  //\r
+  // Get HII PackageList\r
+  //\r
+  BufferSize = 0;\r
+  HiiPackageList = NULL;\r
+\r
+  Status = gHiiDatabase->ExportPackageLists (gHiiDatabase, Handle, &BufferSize, HiiPackageList);\r
+  ASSERT (Status != EFI_NOT_FOUND);\r
+  \r
+  if (Status == EFI_BUFFER_TOO_SMALL) {\r
+    HiiPackageList = AllocatePool (BufferSize);\r
+    ASSERT (HiiPackageList != NULL);\r
+\r
+    Status = gHiiDatabase->ExportPackageLists (gHiiDatabase, Handle, &BufferSize, HiiPackageList);\r
+  }\r
+  if (EFI_ERROR (Status)) {\r
+    FreePool (HiiPackageList);\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Extract GUID\r
+  //\r
+  CopyGuid (Guid, &HiiPackageList->PackageListGuid);\r
+\r
+  FreePool (HiiPackageList);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
 /**\r
   Registers a list of packages in the HII Database and returns the HII Handle\r
   associated with that registration.  If an HII Handle has already been registered\r
@@ -199,18 +272,19 @@ HiiRemovePackages (
 \r
 \r
 /**\r
-  Retrieves the array of all the HII Handles or the HII handle of a specific\r
-  package list in the HII Database.\r
+  Retrieves the array of all the HII Handles or the HII handles of a specific\r
+  package list GUID in the HII Database.\r
   This array is terminated with a NULL HII Handle.\r
   This function allocates the returned array using AllocatePool().\r
   The caller is responsible for freeing the array with FreePool().\r
 \r
   @param[in]  PackageListGuid  An optional parameter that is used to request \r
-                               an HII Handle that is associatd with a specific\r
-                               Package List GUID.  If this parameter is NULL\r
+                               HII Handles associated with a specific\r
+                               Package List GUID.  If this parameter is NULL,\r
                                then all the HII Handles in the HII Database\r
-                               are returned.  If this parameter is not NULL\r
-                               then at most 1 HII Handle is returned.\r
+                               are returned.  If this parameter is not NULL,\r
+                               then zero or more HII Handles associated with \r
+                               PackageListGuid are returned.\r
 \r
   @retval NULL   No HII handles were found in the HII database\r
   @retval NULL   The array of HII Handles could not be retrieved\r
@@ -228,7 +302,8 @@ HiiGetHiiHandles (
   EFI_HII_HANDLE  TempHiiHandleBuffer;\r
   EFI_HII_HANDLE  *HiiHandleBuffer;\r
   EFI_GUID        Guid;\r
-  UINTN           Index;\r
+  UINTN           Index1;\r
+  UINTN           Index2;\r
 \r
   //\r
   // Retrieve the size required for the buffer of all HII handles.\r
@@ -291,74 +366,21 @@ HiiGetHiiHandles (
     //\r
     return HiiHandleBuffer;\r
   } else {\r
-    for (Index = 0; HiiHandleBuffer[Index] != NULL; Index++) {\r
-      Status = InternalHiiExtractGuidFromHiiHandle (HiiHandleBuffer[Index], &Guid);\r
+    for (Index1 = 0, Index2 = 0; HiiHandleBuffer[Index1] != NULL; Index1++) {\r
+      Status = InternalHiiExtractGuidFromHiiHandle (HiiHandleBuffer[Index1], &Guid);\r
       ASSERT_EFI_ERROR (Status);\r
       if (CompareGuid (&Guid, PackageListGuid)) {\r
-        HiiHandleBuffer[0] = HiiHandleBuffer[Index];\r
-        HiiHandleBuffer[1] = NULL;\r
-        return HiiHandleBuffer;\r
+        HiiHandleBuffer[Index2++] = HiiHandleBuffer[Index1];       \r
       }\r
     }\r
-    FreePool (HiiHandleBuffer);\r
-    return NULL;\r
-  }\r
-}\r
-\r
-/**\r
-  Extract Hii package list GUID for given HII handle.\r
-\r
-  If HiiHandle could not be found in the HII database, then ASSERT.\r
-  If Guid is NULL, then ASSERT.\r
-\r
-  @param  Handle              Hii handle\r
-  @param  Guid                Package list GUID\r
-\r
-  @retval EFI_SUCCESS            Successfully extract GUID from Hii database.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-InternalHiiExtractGuidFromHiiHandle (\r
-  IN      EFI_HII_HANDLE      Handle,\r
-  OUT     EFI_GUID            *Guid\r
-  )\r
-{\r
-  EFI_STATUS                   Status;\r
-  UINTN                        BufferSize;\r
-  EFI_HII_PACKAGE_LIST_HEADER  *HiiPackageList;\r
-\r
-  ASSERT (Guid != NULL);\r
-  ASSERT (Handle != NULL);\r
-\r
-  //\r
-  // Get HII PackageList\r
-  //\r
-  BufferSize = 0;\r
-  HiiPackageList = NULL;\r
-\r
-  Status = gHiiDatabase->ExportPackageLists (gHiiDatabase, Handle, &BufferSize, HiiPackageList);\r
-  ASSERT (Status != EFI_NOT_FOUND);\r
-  \r
-  if (Status == EFI_BUFFER_TOO_SMALL) {\r
-    HiiPackageList = AllocatePool (BufferSize);\r
-    ASSERT (HiiPackageList != NULL);\r
-\r
-    Status = gHiiDatabase->ExportPackageLists (gHiiDatabase, Handle, &BufferSize, HiiPackageList);\r
-  }\r
-  if (EFI_ERROR (Status)) {\r
-    FreePool (HiiPackageList);\r
-    return Status;\r
+    if (Index2 > 0) {\r
+      HiiHandleBuffer[Index2] = NULL;\r
+      return HiiHandleBuffer;\r
+    } else {\r
+      FreePool (HiiHandleBuffer);\r
+      return NULL;\r
+    }\r
   }\r
-\r
-  //\r
-  // Extract GUID\r
-  //\r
-  CopyGuid (Guid, &HiiPackageList->PackageListGuid);\r
-\r
-  FreePool (HiiPackageList);\r
-\r
-  return EFI_SUCCESS;\r
 }\r
 \r
 /**\r
@@ -446,63 +468,6 @@ InternalHiiBlockToConfig (
   return ConfigResp;\r
 }\r
 \r
-/**\r
-  Uses the ConfigToBlock() service of the Config Routing Protocol to \r
-  convert <ConfigResp> to a block.  The block is allocated using\r
-  AllocatePool().  The caller is responsible for freeing the block\r
-  using FreePool().\r
-\r
-  If ConfigResp is NULL, then ASSERT().\r
-\r
-  @param[in] ConfigResp  Pointer to a Null-terminated Unicode string.\r
-  @param[in] BufferSize  Length in bytes of buffer to hold retrived data. \r
-\r
-  @retval NULL   The block could not be generated..\r
-  @retval Other  Pointer to the allocated block.\r
-\r
-**/\r
-UINT8 *\r
-EFIAPI\r
-InternalHiiConfigToBlock (\r
-  IN  EFI_STRING  ConfigResp,\r
-  IN  UINTN       BlockSize\r
-  )\r
-{\r
-  EFI_STATUS  Status;\r
-  CHAR16      *Progress;\r
-  UINT8       *Block;\r
-\r
-  ASSERT (ConfigResp != NULL);\r
-\r
-  //\r
-  // Allocate a buffer to hold the <ConfigResp> conversion\r
-  //\r
-  Block = AllocateZeroPool (BlockSize);\r
-  if (Block == NULL) {\r
-    return NULL;\r
-  }\r
-\r
-  //\r
-  // Convert <ConfigResp> to a buffer\r
-  //\r
-  Status = gHiiConfigRouting->ConfigToBlock (\r
-                                gHiiConfigRouting,\r
-                                ConfigResp,\r
-                                Block,\r
-                                &BlockSize,\r
-                                &Progress\r
-                                );\r
-  if (EFI_ERROR (Status)) {\r
-    FreePool (Block);\r
-    return NULL;\r
-  }\r
-\r
-  //\r
-  // Return converted buffer\r
-  //\r
-  return Block;\r
-}\r
-\r
 /**\r
   Uses the BrowserCallback() service of the Form Browser Protocol to retrieve \r
   or set uncommitted data.  If sata i being retrieved, then the buffer is \r
@@ -564,6 +529,15 @@ InternalHiiBrowserCallback (
                               VariableGuid,\r
                               VariableName\r
                               );\r
+    \r
+    if (!EFI_ERROR (Status)) {\r
+      //\r
+      // No Resluts Data, only allocate one char for '\0'\r
+      //\r
+      ResultsData = AllocateZeroPool (sizeof (CHAR16));\r
+      return ResultsData;\r
+    }\r
+\r
     if (Status != EFI_BUFFER_TOO_SMALL) {\r
       return NULL;\r
     }\r
@@ -728,296 +702,1382 @@ HiiConstructConfigHdr (
 }\r
 \r
 /**\r
-  Allocates and returns a Null-terminated Unicode <ConfigAltResp> string.\r
+  Convert the hex UNICODE encoding string of UEFI GUID, NAME or device path \r
+  to binary buffer from <ConfigHdr>.\r
 \r
-  If Guid is NULL, then ASSERT().\r
-  If Name is NULL, then ASSERT().\r
-  If BlockNameArray is NULL, then ASSERT().\r
-\r
-  @param[in] Guid               GUID of the buffer storage.\r
-  @param[in] Name               Name of the buffer storage.\r
-  @param[in] DriverHandle       The DriverHandle that support a Device Path\r
-                                Protocol.    \r
-  @param[in] BufferStorage      Content of the buffer storage.\r
-  @param[in] BufferStorageSize  Length in bytes of the buffer storage.\r
-  @param[in] BlockNameArray     Array generated by VFR compiler.  This array\r
-                                contains a UINT32 value that is the length\r
-                                of BlockNameArray in bytes, followed by pairs\r
-                                of 16-bit values that are the offset and length\r
-                                values used to contruct a <ConfigRequest> string.\r
-  @param[in]  ...               A variable argument list that contains pairs of 16-bit\r
-                                ALTCFG identifiers and pointers to DefaultValueArrays.\r
-                                The variable argument list is terminated by a NULL \r
-                                DefaultValueArray pointer.  A DefaultValueArray \r
-                                contains a UINT32 value that is the length, in bytes,\r
-                                of the DefaultValueArray.  The UINT32 length value \r
-                                is followed by a series of records that contain\r
-                                a 16-bit WIDTH value followed by a byte array with \r
-                                WIDTH entries.  The records must be parsed from\r
-                                beginning to end until the UINT32 length limit\r
-                                is reached.  \r
-\r
-  @retval NULL          There are not enough resources to process the request.\r
-  @retval NULL          A <ConfigResp> could not be retrieved from the Config \r
-                        Routing Protocol.\r
-  @retval Other         A pointer to the Null-terminate Unicode <ConfigAltResp>\r
-                        string.\r
+  This is a internal function.\r
+\r
+  @param  String                 UEFI configuration string.\r
+  @param  Flag                   Flag specifies what type buffer will be retrieved.\r
+  @param  Buffer                 Binary of Guid, Name or Device path.\r
+\r
+  @retval EFI_INVALID_PARAMETER  Any incoming parameter is invalid.\r
+  @retval EFI_OUT_OF_RESOURCES   Lake of resources to store neccesary structures.\r
+  @retval EFI_SUCCESS            The buffer data is retrieved and translated to\r
+                                 binary format.\r
 \r
 **/\r
-EFI_STRING\r
-EFIAPI\r
-HiiConstructConfigAltResp (\r
-  IN CONST EFI_GUID  *Guid,\r
-  IN CONST CHAR16    *Name,\r
-  IN EFI_HANDLE      DriverHandle,\r
-  IN CONST VOID      *BufferStorage,\r
-  IN UINTN           BufferStorageSize,\r
-  IN CONST VOID      *BlockNameArray, \r
-  ...\r
+EFI_STATUS\r
+InternalHiiGetBufferFromString (\r
+  IN  EFI_STRING                 String,\r
+  IN  UINT8                      Flag,\r
+  OUT UINT8                      **Buffer\r
   )\r
 {\r
-  UINTN         Length;\r
-  CHAR16        *String;\r
-  CHAR16        *ConfigHdr;\r
-  UINT8         *Buffer;\r
-  UINT8         *BufferEnd;\r
-  CHAR16        *ConfigRequest;\r
-  EFI_STRING    ConfigResp;\r
-  EFI_STRING    ConfigAltResp;\r
-  VA_LIST       Args;\r
-  UINTN         AltCfgId;\r
-  UINT16        Width;\r
-  UINT16        OffsetValue;\r
-  UINT16        WidthValue;\r
+  UINTN      Length;\r
+  EFI_STRING ConfigHdr;\r
+  CHAR16     *StringPtr;\r
+  UINT8      *DataBuffer;\r
+  CHAR16     TemStr[5];\r
+  UINTN      Index;\r
+  UINT8      DigitUint8;\r
+\r
+  if (String == NULL || Buffer == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  \r
+  DataBuffer = NULL;\r
+  StringPtr  = NULL;\r
+  ConfigHdr  = String;\r
+  //\r
+  // The content between 'GUID', 'NAME', 'PATH' of <ConfigHdr> and '&' of next element\r
+  // or '\0' (end of configuration string) is the UNICODE %02x bytes encoding string.\r
+  //\r
+  for (Length = 0; *String != 0 && *String != L'&'; String++, Length++);\r
 \r
-  ASSERT (Guid != NULL);\r
-  ASSERT (Name != NULL);\r
-  ASSERT (BlockNameArray != NULL);\r
+  switch (Flag) {\r
+  case GUID_CONFIG_STRING_TYPE:\r
+  case PATH_CONFIG_STRING_TYPE:\r
+    //\r
+    // The data in <ConfigHdr> is encoded as hex UNICODE %02x bytes in the same order\r
+    // as the device path and Guid resides in RAM memory.\r
+    // Translate the data into binary.\r
+    //\r
+    DataBuffer = (UINT8 *) AllocateZeroPool ((Length + 1) / 2);\r
+    if (DataBuffer == NULL) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+    //\r
+    // Convert binary byte one by one\r
+    //\r
+    ZeroMem (TemStr, sizeof (TemStr));\r
+    for (Index = 0; Index < Length; Index ++) {\r
+      TemStr[0] = ConfigHdr[Index];\r
+      DigitUint8 = (UINT8) StrHexToUint64 (TemStr);\r
+      if ((Index & 1) == 0) {\r
+        DataBuffer [Index/2] = DigitUint8;\r
+      } else {\r
+        DataBuffer [Index/2] = (UINT8) ((DataBuffer [Index/2] << 4) + DigitUint8);\r
+      }\r
+    }\r
+    \r
+    *Buffer = DataBuffer;\r
+    break;\r
+\r
+  case NAME_CONFIG_STRING_TYPE:\r
+    //\r
+    // Convert Config String to Unicode String, e.g. "0041004200430044" => "ABCD"\r
+    // \r
+\r
+    //\r
+    // Add the tailling char L'\0'\r
+    //\r
+    DataBuffer = (UINT8 *) AllocateZeroPool ((Length/4 + 1) * sizeof (CHAR16));\r
+    if (DataBuffer == NULL) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+    //\r
+    // Convert character one by one\r
+    //\r
+    StringPtr = (CHAR16 *) DataBuffer;\r
+    ZeroMem (TemStr, sizeof (TemStr));\r
+    for (Index = 0; Index < Length; Index += 4) {\r
+      StrnCpy (TemStr, ConfigHdr + Index, 4);\r
+      StringPtr[Index/4] = (CHAR16) StrHexToUint64 (TemStr);\r
+    }\r
+    //\r
+    // Add tailing L'\0' character\r
+    //\r
+    StringPtr[Index/4] = L'\0';\r
+\r
+    *Buffer = DataBuffer;\r
+    break;\r
+\r
+  default:\r
+    return EFI_INVALID_PARAMETER;\r
+    break;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  This function checks VarOffset and VarWidth is in the block range.\r
 \r
+  @param  BlockArray         The block array is to be checked. \r
+  @param  VarOffset          Offset of var to the structure\r
+  @param  VarWidth           Width of var.\r
+  \r
+  @retval TRUE   This Var is in the block range.\r
+  @retval FALSE  This Var is not in the block range.\r
+**/\r
+BOOLEAN\r
+BlockArrayCheck (\r
+  IN IFR_BLOCK_DATA  *BlockArray,\r
+  IN UINT16          VarOffset,\r
+  IN UINT16          VarWidth\r
+  )\r
+{\r
+  LIST_ENTRY          *Link;\r
+  IFR_BLOCK_DATA      *BlockData;\r
+  \r
   //\r
-  // Initialize local variables\r
+  // No Request Block array, all vars are got.\r
   //\r
-  ConfigHdr     = NULL;\r
-  ConfigRequest = NULL; \r
-  ConfigResp    = NULL;\r
-\r
+  if (BlockArray == NULL) {\r
+    return TRUE;\r
+  }\r
+  \r
   //\r
-  // Construct <ConfigHdr> : "GUID=...&NAME=...&PATH=..."\r
+  // Check the input var is in the request block range.\r
   //\r
-  ConfigHdr = HiiConstructConfigHdr (Guid, Name, DriverHandle);\r
-  if (ConfigHdr == NULL) {\r
-    goto Exit;\r
+  for (Link = BlockArray->Entry.ForwardLink; Link != &BlockArray->Entry; Link = Link->ForwardLink) {\r
+    BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);\r
+    if ((VarOffset >= BlockData->Offset) && ((VarOffset + VarWidth) <= (BlockData->Offset + BlockData->Width))) {\r
+      return TRUE;\r
+    }\r
   }\r
 \r
+  return FALSE;\r
+}\r
+\r
+/**\r
+  Get the value of <Number> in <BlockConfig> format, i.e. the value of OFFSET\r
+  or WIDTH or VALUE.\r
+  <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>\r
+\r
+  @param  ValueString            String in <BlockConfig> format and points to the\r
+                                 first character of <Number>.\r
+  @param  ValueData              The output value. Caller takes the responsibility\r
+                                 to free memory.\r
+  @param  ValueLength            Length of the <Number>, in characters.\r
+\r
+  @retval EFI_OUT_OF_RESOURCES   Insufficient resources to store neccessary\r
+                                 structures.\r
+  @retval EFI_SUCCESS            Value of <Number> is outputted in Number\r
+                                 successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+InternalHiiGetValueOfNumber (\r
+  IN  EFI_STRING           ValueString,\r
+  OUT UINT8                **ValueData,\r
+  OUT UINTN                *ValueLength\r
+  )\r
+{\r
+  EFI_STRING               StringPtr;\r
+  UINTN                    Length;\r
+  UINT8                    *Buf;\r
+  UINT8                    DigitUint8;\r
+  UINTN                    Index;\r
+  CHAR16                   TemStr[2];\r
+\r
+  ASSERT (ValueString != NULL && ValueData != NULL && ValueLength != NULL);\r
+  ASSERT (*ValueString != L'\0');\r
+\r
   //\r
-  // Compute the length of the entire request starting with <ConfigHdr> and a \r
-  // Null-terminator\r
+  // Get the length of value string\r
   //\r
-  Length = StrLen (ConfigHdr) + 1;\r
-\r
+  StringPtr = ValueString;\r
+  while (*StringPtr != L'\0' && *StringPtr != L'&') {\r
+    StringPtr++;\r
+  }\r
+  Length = StringPtr - ValueString;\r
+  \r
   //\r
-  // Determine the size <BlockName> Offset/Width pairs\r
+  // Allocate buffer to store the value\r
   //\r
-  Buffer = (UINT8 *)BlockNameArray;\r
-  BufferEnd = Buffer + ReadUnaligned32 ((UINT32 *)Buffer);\r
-  Buffer += sizeof (UINT32);\r
-\r
+  Buf = (UINT8 *) AllocateZeroPool ((Length + 1) / 2);\r
+  if (Buf == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+  \r
+  //\r
+  // Convert character one by one to the value buffer\r
   //\r
-  // Add <BlockName> length that is composed of one or more Offset/Width pairs\r
+  ZeroMem (TemStr, sizeof (TemStr));\r
+  for (Index = 0; Index < Length; Index ++) {\r
+    TemStr[0] = ValueString[Length - Index - 1];\r
+    DigitUint8 = (UINT8) StrHexToUint64 (TemStr);\r
+    if ((Index & 1) == 0) {\r
+      Buf [Index/2] = DigitUint8;\r
+    } else {\r
+      Buf [Index/2] = (UINT8) ((DigitUint8 << 4) + Buf [Index/2]);\r
+    }\r
+  }\r
+  \r
   //\r
-  // <BlockName> ::= &OFFSET=1234&WIDTH=1234\r
-  //                 |  8   | 4 |   7  | 4 |\r
+  // Set the converted value and string length.\r
   //\r
-  Length += (((BufferEnd - Buffer) / (sizeof (UINT16) + sizeof (UINT16))) * (8 + 4 + 7 + 4));\r
+  *ValueData    = Buf;\r
+  *ValueLength  = Length;\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
+  @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
+  \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
+  )\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
+  LIST_ENTRY                   *Link;\r
+  UINT8                        *VarBuffer;\r
+  UINTN                        MaxBufferSize;\r
+  EFI_STATUS                   Status;\r
+  EFI_HII_PACKAGE_HEADER       PacakgeHeader;\r
+  UINT32                       PackageOffset;\r
+  UINT8                        *PackageData;\r
+  UINTN                        IfrOffset;\r
+  EFI_IFR_OP_HEADER            *IfrOpHdr;\r
+  EFI_IFR_VARSTORE             *IfrVarStore;\r
+  EFI_IFR_ONE_OF               *IfrOneOf;\r
+  EFI_IFR_NUMERIC              *IfrNumeric;\r
+  EFI_IFR_ONE_OF_OPTION        *IfrOneOfOption;\r
+  EFI_IFR_CHECKBOX             *IfrCheckBox;\r
+  EFI_IFR_STRING               *IfrString;\r
+  CHAR8                        *VarStoreName;\r
+  UINTN                        Index;\r
+  \r
   //\r
-  // Allocate buffer for the entire <ConfigRequest>\r
+  // 1. Get the current setting to current block data array and Convert them into VarBuffer\r
   //\r
-  ConfigRequest = AllocateZeroPool (Length * sizeof (CHAR16));\r
-  if (ConfigRequest == NULL) {\r
-    goto Exit;\r
-  }\r
-  String = ConfigRequest;\r
 \r
   //\r
-  // Start with <ConfigHdr>\r
+  // Skip ConfigHdr string\r
+  //\r
+  StringPtr = ConfigResp;\r
+  StringPtr = StrStr (ConfigResp, L"&OFFSET");\r
+  if (StringPtr == NULL) {\r
+    //\r
+    // No ConfigBlock value is requied 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
+\r
+  //\r
+  // 2. Check IFR value is in block data, then Validate Vaule\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
+    // Parse IFR opcode from the form package.\r
+    //\r
+    if (PacakgeHeader.Type == EFI_HII_PACKAGE_FORMS) {\r
+      IfrOffset   = sizeof (PacakgeHeader);\r
+      PackageData = (UINT8 *) HiiPackageList + PackageOffset;\r
+      while (IfrOffset < PacakgeHeader.Length) {\r
+        IfrOpHdr = (EFI_IFR_OP_HEADER *) (PackageData + IfrOffset);\r
+        //\r
+        // Validate current setting to the value built in IFR opcode\r
+        //\r
+        switch (IfrOpHdr->OpCode) {\r
+        case EFI_IFR_VARSTORE_OP:          \r
+          //\r
+          // VarStoreId has been found. No further found.\r
+          //\r
+          if (IfrVarStore != NULL) {\r
+            break;\r
+          }\r
+          //\r
+          // Find the matched VarStoreId to the input VarGuid and VarName\r
+          //\r
+          IfrVarStore = (EFI_IFR_VARSTORE *) IfrOpHdr;\r
+          if (CompareGuid ((EFI_GUID *) (VOID *) &IfrVarStore->Guid, VarGuid)) {\r
+            VarStoreName = (CHAR8 *) IfrVarStore->Name;\r
+            for (Index = 0; VarStoreName[Index] != 0; Index ++) {\r
+              if ((CHAR16) VarStoreName[Index] != VarName[Index]) {\r
+                break;\r
+              }\r
+            }\r
+            //\r
+            // The matched VarStore is found.\r
+            //\r
+            if ((VarStoreName[Index] != 0) || (VarName[Index] != 0)) {\r
+              IfrVarStore = NULL;\r
+            }\r
+          } else {\r
+            IfrVarStore = NULL;\r
+          }\r
+          break;\r
+        case EFI_IFR_FORM_OP:\r
+          //\r
+          // Check the matched VarStoreId is found.\r
+          //\r
+          if (IfrVarStore == NULL) {\r
+            Status = EFI_SUCCESS;\r
+            goto Done;\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 (IfrVarStore == NULL) {\r
+            Status = EFI_INVALID_PARAMETER;\r
+            goto Done;\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 != IfrVarStore->VarStoreId) {\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
+          // 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) > IfrVarStore->Size) {\r
+            //\r
+            // This question exceeds the var store size. \r
+            //\r
+            Status = EFI_INVALID_PARAMETER;\r
+            goto Done;\r
+          }\r
+\r
+          //\r
+          // Get the current value for oneof opcode\r
+          //\r
+          VarValue = 0;\r
+          CopyMem (&VarValue, VarBuffer +  Offset, Width);\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
+        case EFI_IFR_NUMERIC_OP:\r
+          //\r
+          // Check the current value is in the numeric range.\r
+          //\r
+\r
+          //\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
+          }\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
+            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
+            // 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) > IfrVarStore->Size) {\r
+            //\r
+            // This question exceeds the var store size. \r
+            //\r
+            Status = EFI_INVALID_PARAMETER;\r
+            goto Done;\r
+          }\r
+\r
+          //\r
+          // Check the current value is in the numeric range.\r
+          //\r
+          VarValue = 0;\r
+          CopyMem (&VarValue, VarBuffer +  Offset, Width);\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
+            }\r
+            break;\r
+          case EFI_IFR_NUMERIC_SIZE_2:\r
+            if ((UINT16) VarValue < IfrNumeric->data.u16.MinValue || (UINT16) VarValue > IfrNumeric->data.u16.MaxValue) {\r
+              //\r
+              // Not in the valid range.\r
+              //\r
+              Status = EFI_INVALID_PARAMETER;\r
+              goto Done;\r
+            }\r
+            break;\r
+          case EFI_IFR_NUMERIC_SIZE_4:\r
+            if ((UINT32) VarValue < IfrNumeric->data.u32.MinValue || (UINT32) VarValue > IfrNumeric->data.u32.MaxValue) {\r
+              //\r
+              // Not in the valid range.\r
+              //\r
+              Status = EFI_INVALID_PARAMETER;\r
+              goto Done;\r
+            }\r
+            break;\r
+          case EFI_IFR_NUMERIC_SIZE_8:\r
+            if ((UINT64) VarValue < IfrNumeric->data.u64.MinValue || (UINT64) VarValue > IfrNumeric->data.u64.MaxValue) {\r
+              //\r
+              // Not in the valid range.\r
+              //\r
+              Status = EFI_INVALID_PARAMETER;\r
+              goto Done;\r
+            }\r
+            break;\r
+          }\r
+\r
+          break;\r
+        case EFI_IFR_CHECKBOX_OP:\r
+          //\r
+          // Check value is BOOLEAN type, only 0 and 1 is valid.\r
+          //\r
+\r
+          //\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
+          }\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
+            break;\r
+          }\r
+          \r
+          //\r
+          // Get Offset by Question header\r
+          //\r
+          Offset = IfrCheckBox->Question.VarStoreInfo.VarOffset;\r
+          Width  = sizeof (BOOLEAN);\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) > IfrVarStore->Size) {\r
+            //\r
+            // This question exceeds the var store size. \r
+            //\r
+            Status = EFI_INVALID_PARAMETER;\r
+            goto Done;\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
+          }\r
+          \r
+          break;\r
+        case EFI_IFR_STRING_OP:\r
+          //\r
+          // Check current string length is less than maxsize\r
+          //\r
+\r
+          //\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
+          }\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
+            break;\r
+          }\r
+          \r
+          //\r
+          // Get Offset/Width by Question header and 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
+            //\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) > IfrVarStore->Size) {\r
+            //\r
+            // This question exceeds the var store size. \r
+            //\r
+            Status = EFI_INVALID_PARAMETER;\r
+            goto Done;\r
+          }\r
+          \r
+          //\r
+          // Check current string length is less than maxsize\r
+          //\r
+          if (StrSize ((CHAR16 *) (VarBuffer + Offset)) > Width) {\r
+            Status = EFI_INVALID_PARAMETER;\r
+            goto Done;            \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
+          // 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
+            if (VarValue == IfrOneOfOption->Value.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
+          // Decrease opcode scope for the validated opcode\r
+          //\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
+            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
+        //\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
+Done:\r
+  if (VarBuffer != NULL) {\r
+    FreePool (VarBuffer);\r
+  }\r
+  \r
+  if (CurrentBlockArray != NULL) {\r
+    //\r
+    // Free Link Array CurrentBlockArray\r
+    //\r
+    while (!IsListEmpty (&CurrentBlockArray->Entry)) {\r
+      BlockData = BASE_CR (CurrentBlockArray->Entry.ForwardLink, IFR_BLOCK_DATA, Entry);\r
+      RemoveEntryList (&BlockData->Entry);\r
+      FreePool (BlockData);\r
+    }\r
+    FreePool (CurrentBlockArray);    \r
+  }\r
+\r
+  return Status;\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
+\r
+  1. For setting default action, Reset the default value specified by DefaultId \r
+  to the driver configuration got by Request string.\r
+  2. For validating current setting, Validate the current configuration \r
+  by parsing HII form IFR opcode.\r
+\r
+  NULL request string support depends on the ExportConfig interface of\r
+  HiiConfigRouting protocol in UEFI specification.\r
+  \r
+  @param Request    A null-terminated Unicode string in \r
+                    <MultiConfigRequest> format. It can be NULL.\r
+                    If it is NULL, all current configuration for the\r
+                    entirety of the current HII database will be validated.\r
+                    If it is NULL, all configuration for the\r
+                    entirety of the current HII database will be reset.\r
+  @param DefaultId  Specifies the type of defaults to retrieve only for setting default action.\r
+  @param ActionType Action supports setting defaults and validate current setting.\r
+  \r
+  @retval TURE    Action runs successfully.\r
+  @retval FALSE   Action is not valid or Action can't be executed successfully..\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+InternalHiiIfrValueAction (\r
+  IN CONST EFI_STRING Request,  OPTIONAL\r
+  IN UINT16           DefaultId,\r
+  IN UINT8            ActionType\r
+  )\r
+{\r
+  EFI_STRING     ConfigAltResp;\r
+  EFI_STRING     ConfigAltHdr;\r
+  EFI_STRING     ConfigResp;\r
+  EFI_STRING     Progress;\r
+  EFI_STRING     StringPtr;\r
+  EFI_STRING     StringHdr;\r
+  EFI_STATUS     Status;\r
+  EFI_HANDLE     DriverHandle;\r
+  EFI_HANDLE     TempDriverHandle;\r
+  EFI_HII_HANDLE *HiiHandleBuffer;\r
+  EFI_HII_HANDLE HiiHandle;\r
+  UINT32         Index;\r
+  EFI_GUID       *VarGuid;\r
+  EFI_STRING     VarName;\r
+  EFI_STRING_ID  DefaultName;\r
+\r
+  UINT8                        *PackageData;\r
+  UINTN                        IfrOffset;\r
+  EFI_IFR_OP_HEADER            *IfrOpHdr;\r
+  EFI_HII_PACKAGE_LIST_HEADER  *HiiPackageList;\r
+  UINT32                       PackageOffset;  \r
+  UINTN                        PackageListLength;\r
+  EFI_HII_PACKAGE_HEADER       PacakgeHeader;\r
+  EFI_DEVICE_PATH_PROTOCOL     *DevicePath;\r
+  EFI_DEVICE_PATH_PROTOCOL     *TempDevicePath;\r
+  \r
+  ConfigAltResp = NULL;\r
+  ConfigResp    = NULL;\r
+  VarGuid       = NULL;\r
+  VarName       = NULL;\r
+  DevicePath    = NULL;\r
+  ConfigAltHdr  = NULL;\r
+  HiiHandleBuffer  = NULL;\r
+  Index            = 0;\r
+  TempDriverHandle = NULL;\r
+  HiiHandle        = NULL;\r
+  PackageData      = NULL;\r
+  HiiPackageList   = NULL;\r
+  \r
+  //\r
+  // Only support set default and validate setting action.\r
   //\r
-  StrCpy (String, ConfigHdr);\r
-  String += StrLen (String);\r
+  if ((ActionType != ACTION_SET_DEFAUTL_VALUE) && (ActionType != ACTION_VALIDATE_SETTING)) {\r
+    return FALSE;\r
+  }\r
 \r
   //\r
-  // Loop through all the Offset/Width pairs and append them to ConfigRequest\r
+  // Get the full requested value and deault value string.\r
   //\r
-  while (Buffer < BufferEnd) {\r
+  if (Request != NULL) {\r
+    Status = gHiiConfigRouting->ExtractConfig (\r
+                                  gHiiConfigRouting,\r
+                                  Request,\r
+                                  &Progress,\r
+                                  &ConfigAltResp\r
+                                );\r
+  } else {\r
+    Status = gHiiConfigRouting->ExportConfig (\r
+                                  gHiiConfigRouting,\r
+                                  &ConfigAltResp\r
+                                );\r
+  }\r
+  \r
+  if (EFI_ERROR (Status)) {\r
+    return FALSE;\r
+  }\r
+  \r
+  StringPtr = ConfigAltResp;\r
+  \r
+  while (StringPtr != L'\0') {\r
     //\r
-    // Append &OFFSET=XXXX&WIDTH=YYYY\r
+    // 1. Find <ConfigHdr> GUID=...&NAME=...&PATH=...\r
     //\r
-    OffsetValue = ReadUnaligned16 ((UINT16 *)Buffer);\r
-    WidthValue  = ReadUnaligned16 ((UINT16 *)(Buffer + sizeof (UINT16)));\r
-    UnicodeSPrint (\r
-      String, \r
-      (8 + 4 + 7 + 4) * sizeof (CHAR16), \r
-      L"&OFFSET=%04X&WIDTH=%04X", \r
-      OffsetValue, \r
-      WidthValue\r
-    );\r
+    StringHdr = StringPtr;\r
 \r
-    String += StrLen (String);\r
-    Buffer += (sizeof (UINT16) + sizeof (UINT16));\r
-  }\r
+    //\r
+    // Get Guid value\r
+    //\r
+    if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
+      Status = EFI_INVALID_PARAMETER;\r
+      goto Done;\r
+    }\r
+    StringPtr += StrLen (L"GUID=");\r
+    Status = InternalHiiGetBufferFromString (StringPtr, GUID_CONFIG_STRING_TYPE, (UINT8 **) &VarGuid);\r
+    if (EFI_ERROR (Status)) {\r
+      goto Done;\r
+    }\r
 \r
-  //\r
-  // Get the <ConfigResp>\r
-  //\r
-  ConfigResp = InternalHiiBlockToConfig (ConfigRequest, BufferStorage, BufferStorageSize);\r
-  if (ConfigResp == NULL) {\r
-    goto Exit;\r
-  }\r
+    //\r
+    // Get Name value VarName\r
+    //\r
+    while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&NAME=", StrLen (L"&NAME=")) != 0) {\r
+      StringPtr++;\r
+    }\r
+    if (*StringPtr == L'\0') {\r
+      Status = EFI_INVALID_PARAMETER;\r
+      goto Done;\r
+    }\r
+    StringPtr += StrLen (L"&NAME=");\r
+    Status = InternalHiiGetBufferFromString (StringPtr, NAME_CONFIG_STRING_TYPE, (UINT8 **) &VarName);\r
+    if (EFI_ERROR (Status)) {\r
+      goto Done;\r
+    }\r
+    \r
+    //\r
+    // Get Path value DevicePath\r
+    //\r
+    while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&PATH=", StrLen (L"&PATH=")) != 0) {\r
+      StringPtr++;\r
+    }\r
+    if (*StringPtr == L'\0') {\r
+      Status = EFI_INVALID_PARAMETER;\r
+      goto Done;\r
+    }\r
+    StringPtr += StrLen (L"&PATH=");\r
+    Status = InternalHiiGetBufferFromString (StringPtr, PATH_CONFIG_STRING_TYPE, (UINT8 **) &DevicePath);\r
+    if (EFI_ERROR (Status)) {\r
+      goto Done;\r
+    }\r
 \r
-  //\r
-  // Compute the length of the entire response starting with <ConfigResp> and a \r
-  // Null-terminator\r
-  //\r
-  Length = StrLen (ConfigResp) + 1;\r
+    //\r
+    // Get the Driver handle by the got device path.\r
+    //\r
+    TempDevicePath = DevicePath;\r
+    Status = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &TempDevicePath, &DriverHandle);\r
+    if (EFI_ERROR (Status)) {\r
+      goto Done;\r
+    }\r
+    \r
+    //\r
+    // Find the matched Hii Handle for the found Driver handle\r
+    //\r
+    HiiHandleBuffer = HiiGetHiiHandles (NULL);\r
+    if (HiiHandleBuffer == NULL) {\r
+      Status = EFI_NOT_FOUND;\r
+      goto Done;\r
+    }\r
 \r
-  //\r
-  // Add the length associated with each pair of variable argument parameters\r
-  //\r
-  VA_START (Args, BlockNameArray);\r
-  while (TRUE) {\r
-    AltCfgId = VA_ARG (Args, UINT16);\r
-    Buffer   = VA_ARG (Args, UINT8 *);\r
-    if (Buffer == NULL) {\r
-      break;\r
+    for (Index = 0; HiiHandleBuffer[Index] != NULL; Index ++) {\r
+      gHiiDatabase->GetPackageListHandle (gHiiDatabase, HiiHandleBuffer[Index], &TempDriverHandle);\r
+      if (TempDriverHandle == DriverHandle) {\r
+        break;\r
+      }\r
     }\r
 \r
+    HiiHandle = HiiHandleBuffer[Index];\r
+    FreePool (HiiHandleBuffer);\r
+\r
+    if (HiiHandle == NULL) {\r
+      //\r
+      // This request string has no its Hii package.\r
+      // 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
+      goto NextConfigAltResp;\r
+    }\r
+    \r
     //\r
-    // Add length for "&<ConfigHdr>&ALTCFG=XXXX"\r
-    //                |1| StrLen (ConfigHdr) | 8 | 4 |\r
+    // 2. Get DefaultName string ID by parsing the PacakgeList \r
     //\r
-    Length += (1 + StrLen (ConfigHdr) + 8 + 4);\r
 \r
-    BufferEnd = Buffer + ReadUnaligned32 ((UINT32 *)Buffer);\r
-    Buffer += sizeof (UINT32);\r
-    while (Buffer < BufferEnd) {\r
+    //\r
+    // Get HiiPackage by HiiHandle\r
+    //\r
+    PackageListLength  = 0;\r
+    HiiPackageList     = NULL;\r
+    Status = gHiiDatabase->ExportPackageLists (gHiiDatabase, HiiHandle, &PackageListLength, HiiPackageList);\r
+  \r
+    //\r
+    // The return status should always be EFI_BUFFER_TOO_SMALL as input buffer's size is 0.\r
+    //\r
+    if (Status != EFI_BUFFER_TOO_SMALL) {\r
+      Status = EFI_INVALID_PARAMETER;\r
+      goto Done;\r
+    }\r
+  \r
+    HiiPackageList = AllocatePool (PackageListLength);\r
+    if (HiiPackageList == NULL) {\r
+      Status = EFI_OUT_OF_RESOURCES;\r
+      goto Done;\r
+    }\r
+  \r
+    //\r
+    // Get PackageList on HiiHandle\r
+    //\r
+    Status = gHiiDatabase->ExportPackageLists (gHiiDatabase, HiiHandle, &PackageListLength, HiiPackageList);\r
+    if (EFI_ERROR (Status)) {\r
+      goto Done;\r
+    }\r
+    \r
+    //\r
+    // Parse the form package and get the default name string ID.\r
+    //\r
+    if (ActionType == ACTION_SET_DEFAUTL_VALUE) {\r
+      PackageOffset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);\r
+      Status = EFI_NOT_FOUND;\r
+      while (PackageOffset < PackageListLength) {\r
+        CopyMem (&PacakgeHeader, (UINT8 *) HiiPackageList + PackageOffset, sizeof (PacakgeHeader));\r
+        \r
+        //\r
+        // Parse IFR opcode to get default store opcode\r
+        //\r
+        if (PacakgeHeader.Type == EFI_HII_PACKAGE_FORMS) {\r
+          IfrOffset = sizeof (PacakgeHeader);\r
+          PackageData = (UINT8 *) HiiPackageList + PackageOffset;\r
+          while (IfrOffset < PacakgeHeader.Length) {\r
+            IfrOpHdr = (EFI_IFR_OP_HEADER *) (PackageData + IfrOffset);\r
+            //\r
+            // Match DefaultId to find its DefaultName\r
+            //\r
+            if (IfrOpHdr->OpCode == EFI_IFR_DEFAULTSTORE_OP) {\r
+              if (((EFI_IFR_DEFAULTSTORE *) IfrOpHdr)->DefaultId == DefaultId) {\r
+                DefaultName = ((EFI_IFR_DEFAULTSTORE *) IfrOpHdr)->DefaultName;\r
+                Status = EFI_SUCCESS;\r
+                break;\r
+              }\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
       //\r
-      // Extract Width field\r
+      // Not found the matched default string ID\r
       //\r
-      Width = ReadUnaligned16 ((UINT16 *)(Buffer + sizeof (UINT16)));\r
-\r
+      if (EFI_ERROR (Status)) {\r
+        Status = EFI_SUCCESS;\r
+        goto NextConfigAltResp;\r
+      }\r
+    }\r
+    \r
+    //\r
+    // 3. Call ConfigRouting GetAltCfg(ConfigRoute, <ConfigResponse>, Guid, Name, DevicePath, AltCfgId, AltCfgResp)\r
+    //    Get the default configuration string according to the found defaultname string ID.\r
+    //\r
+    Status = gHiiConfigRouting->GetAltConfig (\r
+                                  gHiiConfigRouting,\r
+                                  ConfigAltResp,\r
+                                  VarGuid,\r
+                                  VarName,\r
+                                  DevicePath,\r
+                                  (ActionType == ACTION_SET_DEFAUTL_VALUE) ? &DefaultName:NULL,  // it can be NULL to get the current setting.\r
+                                  &ConfigResp\r
+                                );\r
+    \r
+    //\r
+    // The required setting can't be found. So, it is not required to be validated and set.\r
+    //\r
+    if (EFI_ERROR (Status)) {\r
+      Status = EFI_SUCCESS;\r
+      goto NextConfigAltResp;\r
+    }\r
+    //\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
+      goto NextConfigAltResp;\r
+    }\r
+    \r
+    //\r
+    // 4. Set the default configuration information or Validate current setting by parse IFR code.\r
+    //    Current Setting is in ConfigResp, will be set into buffer, then check it again.\r
+    //\r
+    if (ActionType == ACTION_SET_DEFAUTL_VALUE) {\r
       //\r
-      // Add length for "&OFFSET=XXXX&WIDTH=YYYY&VALUE=zzzzzzzzzzzz"\r
-      //                |    8  | 4 |   7  | 4 |   7  | Width * 2 |\r
+      // Set the default configuration information.\r
       //\r
-      Length += (8 + 4 + 7 + 4 + 7 + Width * 2);\r
-\r
+      Status = gHiiConfigRouting->RouteConfig (gHiiConfigRouting, ConfigResp, &Progress);\r
+    } else {\r
       //\r
-      // Update Buffer to the next record\r
+      // Current Setting is in ConfigResp, will be set into buffer, then check it again.\r
       //\r
-      Buffer += (sizeof (UINT16) + sizeof (UINT16) + Width);\r
+      Status = InternalHiiValidateCurrentSetting (ConfigResp, HiiPackageList, PackageListLength, VarGuid, VarName);\r
     }\r
-  }\r
-  VA_END (Args);\r
-\r
-  //\r
-  // Allocate a buffer for the entire response\r
-  //\r
-  ConfigAltResp = AllocateZeroPool (Length * sizeof (CHAR16));\r
-  if (ConfigAltResp == NULL) {\r
-    goto Exit;\r
-  }\r
-  String = ConfigAltResp;\r
-\r
-  //\r
-  // Add <ConfigResp>\r
-  //\r
-  StrCpy (String, ConfigResp);\r
-  String += StrLen (String);\r
 \r
-  //\r
-  // Add <AltResp> for each pair of variable argument parameters\r
-  //\r
-  VA_START (Args, BlockNameArray);\r
-  while (TRUE) {\r
-    AltCfgId = VA_ARG (Args, UINT16);\r
-    Buffer   = VA_ARG (Args, UINT8 *);\r
-    if (Buffer == NULL) {\r
-      break;\r
+    if (EFI_ERROR (Status)) {\r
+      goto Done;\r
     }\r
 \r
+NextConfigAltResp:\r
     //\r
-    // Add <AltConfigHdr> of the form "&<ConfigHdr>&ALTCFG=XXXX"\r
-    //                                |1| StrLen (ConfigHdr) | 8 | 4 |\r
+    // Free the allocated pacakge buffer and the got ConfigResp string.\r
     //\r
-    UnicodeSPrint (\r
-      String, \r
-      (1 + StrLen (ConfigHdr) + 8 + 4) * sizeof (CHAR16), \r
-      L"&%s&ALTCFG=%04X", \r
-      ConfigHdr, \r
-      AltCfgId\r
-      );\r
-    String += StrLen (String);\r
+    if (HiiPackageList != NULL) {\r
+      FreePool (HiiPackageList);\r
+      HiiPackageList = NULL;\r
+    }\r
+    \r
+       if (ConfigResp != NULL) {\r
+         FreePool (ConfigResp);\r
+         ConfigResp = NULL;\r
+       }\r
 \r
     //\r
-    // Add <ConfigBody> ::= <ConfigElement>*\r
+    // Free the allocated buffer.\r
     //\r
-    BufferEnd = Buffer + ReadUnaligned32 ((UINT32 *)Buffer);\r
-    Buffer += sizeof (UINT32);\r
-    while (Buffer < BufferEnd) {\r
-      //\r
-      // Extract Width field\r
-      //\r
-      Width = ReadUnaligned16 ((UINT16 *)(Buffer + sizeof (UINT16)));\r
-\r
-      //\r
-      // Add <BlockConfig>\r
-      //\r
-      UnicodeSPrint (\r
-        String, \r
-        (8 + 4 + 7 + 4 + 7 + Width * 2) * sizeof (CHAR16),\r
-        L"&OFFSET=%04X&WIDTH=%04X&VALUE=", \r
-        ReadUnaligned16 ((UINT16 *)Buffer), \r
-        Width\r
-        );\r
-      String += StrLen (String);\r
+    FreePool (VarGuid);\r
+    VarGuid = NULL;\r
+  \r
+    FreePool (VarName);\r
+    VarName = NULL;\r
+  \r
+    FreePool (DevicePath);\r
+    DevicePath = NULL;\r
 \r
-      //\r
-      // Update Buffer to point to the value in the current record\r
-      //\r
-      Buffer += (sizeof (UINT16) + sizeof (UINT16));\r
+    //\r
+    // 5. Jump to next ConfigAltResp for another Guid, Name, Path.\r
+    //\r
 \r
-      //\r
-      // Convert Value to a hex string in "%x" format\r
-      //   NOTE: This is in the opposite byte that GUID and PATH use\r
-      //\r
-      for (; Width > 0; Width--) {\r
-        String += UnicodeValueToString (String, PREFIX_ZERO | RADIX_HEX, Buffer[Width - 1], 2);\r
+    //\r
+    // Get and Skip ConfigHdr\r
+    //\r
+    while (*StringPtr != L'\0' && *StringPtr != L'&') {\r
+      StringPtr++;\r
+    }\r
+    if (*StringPtr == L'\0') {\r
+      break;\r
+    }\r
+        \r
+    //\r
+    // Construct ConfigAltHdr string  "&<ConfigHdr>&ALTCFG=\0" \r
+    //                               | 1 | StrLen (ConfigHdr) | 8 | 1 |\r
+    //\r
+    ConfigAltHdr = AllocateZeroPool ((1 + StringPtr - StringHdr + 8 + 1) * sizeof (CHAR16));\r
+    if (ConfigAltHdr == NULL) {\r
+      Status = EFI_OUT_OF_RESOURCES;\r
+      goto Done;\r
+    }\r
+    StrCpy (ConfigAltHdr, L"&");\r
+    StrnCat (ConfigAltHdr, StringHdr, StringPtr - StringHdr);\r
+    StrCat (ConfigAltHdr, L"&ALTCFG=");\r
+    \r
+    //\r
+    // Skip all AltResp (AltConfigHdr ConfigBody) for the same ConfigHdr\r
+    //\r
+    while ((StringHdr = StrStr (StringPtr, ConfigAltHdr)) != NULL) {\r
+      StringPtr = StringHdr + StrLen (ConfigAltHdr);\r
+      if (*StringPtr == L'\0') {\r
+        break;\r
       }\r
-      //\r
-      // Update Buffer to the next record\r
-      //\r
-      Buffer += Width;\r
     }\r
-  }\r
-  VA_END (Args);\r
+    \r
+    //\r
+    // Free the allocated ConfigAltHdr string\r
+    //\r
+    FreePool (ConfigAltHdr);\r
+    if (*StringPtr == L'\0') {\r
+      break;\r
+    }\r
+    \r
+    //\r
+    // Find &GUID as the next ConfigHdr\r
+    //\r
+    StringPtr = StrStr (StringPtr, L"&GUID");\r
+    if (StringPtr == NULL) {\r
+      break;\r
+    }\r
 \r
-  //\r
-  // Convert all hex digits in range [A-F] in the configuration header to [a-f]\r
-  //\r
-  return InternalHiiLowerConfigString (ConfigAltResp);\r
+    //\r
+    // Skip char '&'\r
+    //\r
+    StringPtr ++;\r
+  }\r
+  \r
+Done:\r
+  if (VarGuid != NULL) {\r
+    FreePool (VarGuid);\r
+  }\r
 \r
-Exit:\r
-  if (ConfigHdr != NULL) {\r
-    FreePool (ConfigHdr);\r
+  if (VarName != NULL) {\r
+    FreePool (VarName);\r
   }\r
-  if (ConfigRequest != NULL) {\r
-    FreePool (ConfigRequest);\r
+\r
+  if (DevicePath != NULL) {\r
+    FreePool (DevicePath);\r
   }\r
+\r
   if (ConfigResp != NULL) {\r
     FreePool (ConfigResp);\r
   }\r
 \r
-  return NULL;\r
+  if (ConfigAltResp != NULL) {\r
+    FreePool (ConfigAltResp);\r
+  }\r
\r
+  if (HiiPackageList != NULL) {\r
+    FreePool (HiiPackageList);\r
+  }\r
+  \r
+  if (EFI_ERROR (Status)) {\r
+    return FALSE;\r
+  }\r
+\r
+  return TRUE;\r
+}\r
+\r
+/**\r
+  Validate the current configuration by parsing HII form IFR opcode.\r
+\r
+  NULL request string support depends on the ExportConfig interface of\r
+  HiiConfigRouting protocol in UEFI specification.\r
+  \r
+  @param  Request   A null-terminated Unicode string in \r
+                    <MultiConfigRequest> format. It can be NULL.\r
+                    If it is NULL, all current configuration for the\r
+                    entirety of the current HII database will be validated.\r
+  \r
+  @retval TURE    Current configuration is valid.\r
+  @retval FALSE   Current configuration is invalid.\r
+**/\r
+BOOLEAN\r
+EFIAPI                               \r
+HiiValidateSettings (\r
+  IN CONST EFI_STRING Request  OPTIONAL\r
+  )\r
+{\r
+  return InternalHiiIfrValueAction (Request, 0, ACTION_VALIDATE_SETTING);\r
+}\r
+\r
+/**\r
+  Reset the default value specified by DefaultId to the driver\r
+  configuration got by Request string. \r
+\r
+  NULL request string support depends on the ExportConfig interface of\r
+  HiiConfigRouting protocol in UEFI specification.\r
+  \r
+  @param Request    A null-terminated Unicode string in \r
+                    <MultiConfigRequest> format. It can be NULL.\r
+                    If it is NULL, all configuration for the\r
+                    entirety of the current HII database will be reset.\r
+  @param DefaultId  Specifies the type of defaults to retrieve.\r
+  \r
+  @retval TURE    The default value is set successfully.\r
+  @retval FALSE   The default value can't be found and set.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+HiiSetToDefaults (\r
+  IN CONST EFI_STRING Request,  OPTIONAL\r
+  IN UINT16        DefaultId\r
+  )\r
+{\r
+  return InternalHiiIfrValueAction (Request, DefaultId, ACTION_SET_DEFAUTL_VALUE);\r
 }\r
 \r
 /**\r
@@ -1155,38 +2215,40 @@ HiiIsConfigHdrMatch (
 \r
 /**\r
   Retrieves uncommited data from the Form Browser and converts it to a binary\r
-  buffer.  The returned buffer is allocated using AllocatePool().  The caller\r
-  is responsible for freeing the returned buffer using FreePool().\r
+  buffer.\r
 \r
-  @param[in]  VariableGuid  Pointer to an EFI_GUID structure.  This is an optional \r
-                            parameter that may be NULL.\r
   @param[in]  VariableName  Pointer to a Null-terminated Unicode string.  This \r
                             is an optional parameter that may be NULL.\r
+  @param[in]  VariableGuid  Pointer to an EFI_GUID structure.  This is an optional \r
+                            parameter that may be NULL.\r
   @param[in]  BufferSize    Length in bytes of buffer to hold retrived data. \r
+  @param[out] Block         Buffer of data to be updated.\r
 \r
-  @retval NULL   The uncommitted data could not be retrieved.\r
-  @retval Other  A pointer to a buffer containing the uncommitted data.\r
+  @retval FALSE  The uncommitted data could not be retrieved.\r
+  @retval TRUE   The uncommitted data was retrieved.\r
 \r
 **/\r
-UINT8 *\r
+BOOLEAN\r
 EFIAPI\r
 HiiGetBrowserData (\r
   IN CONST EFI_GUID  *VariableGuid,  OPTIONAL\r
   IN CONST CHAR16    *VariableName,  OPTIONAL\r
-  IN UINTN           BlockSize\r
+  IN UINTN           BlockSize,\r
+  OUT UINT8          *Block\r
   )\r
 {\r
   EFI_STRING  ResultsData;\r
   UINTN       Size;\r
   EFI_STRING  ConfigResp;\r
-  UINT8       *Block;\r
+  EFI_STATUS  Status;\r
+  CHAR16      *Progress;\r
 \r
   //\r
   // Retrieve the results data from the Browser Callback\r
   //\r
   ResultsData = InternalHiiBrowserCallback (VariableGuid, VariableName, NULL);\r
   if (ResultsData == NULL) {\r
-    return NULL;\r
+    return FALSE;\r
   }\r
 \r
   //\r
@@ -1202,16 +2264,29 @@ HiiGetBrowserData (
   //\r
   FreePool (ResultsData);\r
   if (ConfigResp == NULL) {\r
-    return NULL;\r
+    return FALSE;\r
   }\r
 \r
   //\r
   // Convert <ConfigResp> to a buffer\r
   //\r
-  Block = InternalHiiConfigToBlock (ConfigResp, BlockSize);\r
+  Status = gHiiConfigRouting->ConfigToBlock (\r
+                                gHiiConfigRouting,\r
+                                ConfigResp,\r
+                                Block,\r
+                                &BlockSize,\r
+                                &Progress\r
+                                );\r
+  //\r
+  // Free the allocated buffer\r
+  //\r
   FreePool (ConfigResp);\r
 \r
-  return Block;\r
+  if (EFI_ERROR (Status)) {\r
+    return FALSE;\r
+  }\r
+\r
+  return TRUE;\r
 }\r
 \r
 /**\r
@@ -1479,7 +2554,7 @@ InternalHiiCreateOpCode (
 **/\r
 UINT8 *\r
 EFIAPI\r
-InternalHiiCreateRawOpCodes (\r
+HiiCreateRawOpCodes (\r
   IN VOID   *OpCodeHandle,\r
   IN UINT8  *RawBuffer,\r
   IN UINTN  RawBufferSize\r
@@ -1518,7 +2593,7 @@ InternalHiiAppendOpCodes (
   ASSERT (RawOpCodeHandle != NULL);\r
 \r
   RawOpCodeBuffer = (HII_LIB_OPCODE_BUFFER *)RawOpCodeHandle;\r
-  return InternalHiiCreateRawOpCodes (OpCodeHandle, RawOpCodeBuffer->Buffer, RawOpCodeBuffer->Position);\r
+  return HiiCreateRawOpCodes (OpCodeHandle, RawOpCodeBuffer->Buffer, RawOpCodeBuffer->Position);\r
 }\r
 \r
 /**\r
@@ -2191,8 +3266,7 @@ InternalHiiUpdateFormPackageData (
   BOOLEAN                   GetFormSet;\r
   BOOLEAN                   GetForm;\r
   BOOLEAN                   Updated;\r
-  EFI_IFR_OP_HEADER         *AddOpCode;\r
-  UINT32                    UpdatePackageLength;\r
+  UINTN                     UpdatePackageLength;\r
 \r
   CopyMem (TempPackage, Package, sizeof (EFI_HII_PACKAGE_HEADER));\r
   UpdatePackageLength = sizeof (EFI_HII_PACKAGE_HEADER);\r
@@ -2230,7 +3304,7 @@ InternalHiiUpdateFormPackageData (
     //\r
     // The matched Form is found, and Update data in this form\r
     //\r
-    if (GetFormSet && GetForm && !Updated) {\r
+    if (GetFormSet && GetForm) {\r
       UpdateIfrOpHdr = (EFI_IFR_OP_HEADER *) OpCodeBufferStart->Buffer;\r
       if ((UpdateIfrOpHdr->Length == IfrOpHdr->Length) && \\r
           (CompareMem (IfrOpHdr, UpdateIfrOpHdr, UpdateIfrOpHdr->Length) == 0)) {\r
@@ -2263,22 +3337,14 @@ InternalHiiUpdateFormPackageData (
             return EFI_NOT_FOUND;\r
           }\r
         }\r
+\r
         //\r
         // Insert the updated data\r
         //\r
-        UpdateIfrOpHdr = (EFI_IFR_OP_HEADER *) OpCodeBufferStart->Buffer;\r
-        AddSize        = UpdateIfrOpHdr->Length;\r
-        AddOpCode      = (EFI_IFR_OP_HEADER *) (OpCodeBufferStart->Buffer + AddSize);\r
-        while (AddSize < OpCodeBufferStart->Position) {\r
-          CopyMem (BufferPos, AddOpCode, AddOpCode->Length);\r
-          BufferPos           += AddOpCode->Length;\r
-          UpdatePackageLength += AddOpCode->Length;\r
-          \r
-          AddSize   += AddOpCode->Length;\r
-          AddOpCode  = (EFI_IFR_OP_HEADER *) (OpCodeBufferStart->Buffer + AddSize);\r
-        }\r
-\r
-        ASSERT (AddSize == OpCodeBufferStart->Position);\r
+        AddSize = ((EFI_IFR_OP_HEADER *) OpCodeBufferStart->Buffer)->Length;\r
+        CopyMem (BufferPos, OpCodeBufferStart->Buffer + AddSize, OpCodeBufferStart->Position - AddSize);\r
+        BufferPos           += OpCodeBufferStart->Position - AddSize;\r
+        UpdatePackageLength += OpCodeBufferStart->Position - AddSize;\r
 \r
         if (OpCodeBufferEnd != NULL) {\r
           //\r
@@ -2288,10 +3354,19 @@ InternalHiiUpdateFormPackageData (
           BufferPos           += IfrOpHdr->Length;\r
           UpdatePackageLength += IfrOpHdr->Length;\r
         }\r
+\r
+        //\r
+        // Copy the left package data.\r
+        //\r
+        Offset += IfrOpHdr->Length;\r
+        CopyMem (BufferPos, (UINT8 *) Package + Offset, PackageHeader.Length - Offset);\r
+        UpdatePackageLength += PackageHeader.Length - Offset;\r
+\r
         //\r
         // Set update flag\r
         //\r
         Updated = TRUE;\r
+        break;\r
       }\r
     }\r
 \r
@@ -2311,7 +3386,7 @@ InternalHiiUpdateFormPackageData (
   //\r
   // Update the package length.\r
   //\r
-  PackageHeader.Length = UpdatePackageLength;\r
+  PackageHeader.Length = (UINT32) UpdatePackageLength;\r
   CopyMem (TempPackage, &PackageHeader, sizeof (EFI_HII_PACKAGE_HEADER));\r
 \r
   return EFI_SUCCESS;\r
@@ -2536,78 +3611,3 @@ Finish:
 \r
   return Status; \r
 }\r
-\r
-/**\r
-  Configure the buffer accrording to ConfigBody strings in the format of\r
-  <Length:4 bytes>, <Offset: 2 bytes>, <Width:2 bytes>, <Data:n bytes>.\r
-  This ConfigBody strings is generated by UEFI VfrCompiler for the default\r
-  values in a Form Set. The name of the ConfigBody strings is VfrMyIfrNVDataDefault0000\r
-  constructed following this rule: \r
-   "Vfr" + varstore.name + "Default" + defaultstore.attributes.\r
-  Check the generated C file in Output for details.\r
-\r
-  @param  Buffer                 The start address of buffer.\r
-  @param  BufferSize             The size of buffer.\r
-  @param  Number                 The number of the strings.\r
-  @param  ...                    Variable argument list for default value in <AltResp> format \r
-                                 generated by the tool.\r
-\r
-  @retval EFI_BUFFER_TOO_SMALL   the BufferSize is too small to operate.\r
-  @retval EFI_INVALID_PARAMETER  Buffer is NULL or BufferSize is 0.\r
-  @retval EFI_SUCCESS            Operation successful.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-HiiIfrLibExtractDefault(\r
-  IN VOID                         *Buffer,\r
-  IN UINTN                        *BufferSize,\r
-  UINTN                           Number,\r
-  ...\r
-  )\r
-{\r
-  VA_LIST                         Args;\r
-  UINTN                           Index;\r
-  UINT32                          TotalLen;\r
-  UINT8                           *BufCfgArray;\r
-  UINT8                           *BufferPos;\r
-  UINT16                          Offset;\r
-  UINT16                          Width;\r
-  UINT8                           *Value;\r
-\r
-  if ((Buffer == NULL) || (BufferSize == NULL)) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  Offset = 0;\r
-  Width  = 0;\r
-  Value  = NULL;\r
-\r
-  VA_START (Args, Number);\r
-  for (Index = 0; Index < Number; Index++) {\r
-    BufCfgArray = (UINT8 *) VA_ARG (Args, VOID *);\r
-    TotalLen = ReadUnaligned32 ((UINT32 *)BufCfgArray);\r
-    BufferPos = BufCfgArray + sizeof (UINT32);\r
-\r
-    while ((UINT32)(BufferPos - BufCfgArray) < TotalLen) {\r
-      Offset = ReadUnaligned16 ((UINT16 *)BufferPos);\r
-      BufferPos += sizeof (UINT16);\r
-      Width = ReadUnaligned16 ((UINT16 *)BufferPos);\r
-      BufferPos += sizeof (UINT16);\r
-      Value = BufferPos;\r
-      BufferPos += Width;\r
-\r
-      if ((UINTN)(Offset + Width) > *BufferSize) {\r
-        return EFI_BUFFER_TOO_SMALL;\r
-      }\r
-\r
-      CopyMem ((UINT8 *)Buffer + Offset, Value, Width);\r
-    }\r
-  }\r
-  VA_END (Args);\r
-\r
-  *BufferSize = (UINTN)Offset;\r
-\r
-  return EFI_SUCCESS;\r
-}\r
-\r