]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Library/UefiHiiLib/HiiLib.c
1. Update the implementation of HII ConfigRouting Protocol in HiiDataBase module...
[mirror_edk2.git] / MdeModulePkg / Library / UefiHiiLib / HiiLib.c
index d36828a1158ebd90fd0ca4081df211fd7e4d7ffc..de7cb3f46e0b6b2e7c076480b20c454a93cd1061 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
@@ -305,62 +378,6 @@ HiiGetHiiHandles (
   }\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
   Converts all hex dtring characters in range ['A'..'F'] to ['a'..'f'] for \r
   hex digits that appear between a '=' and a '&' in a config string.\r
@@ -446,63 +463,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 +524,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,104 +697,1433 @@ 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
+  This is a internal function.\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
+  @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 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
+  @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
-\r
-  ASSERT (Guid != NULL);\r
-  ASSERT (Name != NULL);\r
-  ASSERT (BlockNameArray != NULL);\r
-\r
-  //\r
-  // Initialize local variables\r
-  //\r
-  ConfigHdr     = NULL;\r
-  ConfigRequest = NULL; \r
-  ConfigResp    = NULL;\r
-\r
-  //\r
-  // Construct <ConfigHdr> : "GUID=...&NAME=...&PATH=..."\r
-  //\r
-  ConfigHdr = HiiConstructConfigHdr (Guid, Name, DriverHandle);\r
-  if (ConfigHdr == NULL) {\r
-    goto Exit;\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
+  \r
+  DataBuffer = NULL;\r
+  StringPtr  = NULL;\r
+  ConfigHdr  = String;\r
   //\r
-  // Compute the length of the entire request starting with <ConfigHdr> and a \r
-  // Null-terminator\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
-  Length = StrLen (ConfigHdr) + 1;\r
+  for (Length = 0; *String != 0 && *String != L'&'; String++, Length++);\r
 \r
-  //\r
-  // Determine the size <BlockName> Offset/Width pairs\r
-  //\r
-  Buffer = (UINT8 *)BlockNameArray;\r
-  BufferEnd = Buffer + ReadUnaligned32 ((UINT32 *)Buffer);\r
-  Buffer += sizeof (UINT32);\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
-  //\r
-  // Add <BlockName> length that is composed of one or more Offset/Width pairs\r
-  //\r
-  // <BlockName> ::= &OFFSET=1234&WIDTH=1234\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
+  // No Request Block array, all vars are got.\r
+  //\r
+  if (BlockArray == NULL) {\r
+    return TRUE;\r
+  }\r
+  \r
+  //\r
+  // Check the input var is in the request block range.\r
+  //\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
+  // Get the length of value string\r
+  //\r
+  StringPtr = ValueString;\r
+  while (*StringPtr != L'\0' && *StringPtr != L'&') {\r
+    StringPtr++;\r
+  }\r
+  Length = StringPtr - ValueString;\r
+  \r
+  //\r
+  // Allocate buffer to store the value\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
+  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
+  // Set the converted value and string length.\r
+  //\r
+  *ValueData    = Buf;\r
+  *ValueLength  = Length;\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  This function shares the same logic to parse ConfigAltResp string \r
+  for setting default value and validating current setting.\r
+\r
+  @param ConfigResp         \r
+  @param HiiPackageList     \r
+  @param PackageListLength  \r
+  @param VarGuid\r
+  @param VarName\r
+  \r
+  @retval EFI_SUCCESS\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
+  // 1. Get the current setting to current block data array and Convert them into VarBuffer\r
+  //\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 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
+  //\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_NOT_FOUND;\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
+          // 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
+          // 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
+          // 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
+          // 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.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 shares the same logic to parse ConfigAltResp string \r
+  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
+  if ((ActionType != ACTION_SET_DEFAUTL_VALUE) && (ActionType != ACTION_VALIDATE_SETTING)) {\r
+    return FALSE;\r
+  }\r
+\r
+  //\r
+  // Get the full requested value and deault value string.\r
+  //\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
+    // 1. Find <ConfigHdr> GUID=...&NAME=...&PATH=...\r
+    //\r
+    StringHdr = StringPtr;\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 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
+    // 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
+    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
+      goto NextConfigAltResp;\r
+    }\r
+    \r
+    //\r
+    // 2. Get DefaultName string ID by parsing the PacakgeList \r
+    //\r
+\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
+      // Not found the matched default string ID\r
+      //\r
+      if (EFI_ERROR (Status)) {\r
+        goto Done;\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
+    if (EFI_ERROR (Status)) {\r
+      goto Done;\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
+      // Set the default configuration information.\r
+      //\r
+      Status = gHiiConfigRouting->RouteConfig (gHiiConfigRouting, ConfigResp, &Progress);\r
+    } else {\r
+      //\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
+    }\r
+\r
+    if (EFI_ERROR (Status)) {\r
+      goto Done;\r
+    }\r
+\r
+    //\r
+    // Free the allocated pacakge buffer and the got ConfigResp string.\r
+    //\r
+    if (HiiPackageList != NULL) {\r
+      FreePool (HiiPackageList);\r
+      HiiPackageList = NULL;\r
+    }\r
+\r
+    FreePool (ConfigResp);\r
+    ConfigResp = NULL;\r
+\r
+NextConfigAltResp:\r
+    //\r
+    // Free the allocated buffer.\r
+    //\r
+    FreePool (VarGuid);\r
+    VarGuid = NULL;\r
+  \r
+    FreePool (VarName);\r
+    VarName = NULL;\r
+  \r
+    FreePool (DevicePath);\r
+    DevicePath = NULL;\r
+\r
+    //\r
+    // 5. Jump to next ConfigAltResp for another Guid, Name, Path.\r
+    //\r
+\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
+    \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
+    // Skip char '&'\r
+    //\r
+    StringPtr ++;\r
+  }\r
+  \r
+Done:\r
+  if (VarGuid != NULL) {\r
+    FreePool (VarGuid);\r
+  }\r
+\r
+  if (VarName != NULL) {\r
+    FreePool (VarName);\r
+  }\r
+\r
+  if (DevicePath != NULL) {\r
+    FreePool (DevicePath);\r
+  }\r
+\r
+  if (ConfigResp != NULL) {\r
+    FreePool (ConfigResp);\r
+  }\r
+\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 ExtractConfig 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
+  Allocates and returns a Null-terminated Unicode <ConfigAltResp> string.\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
+\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
+  )\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
+\r
+  ASSERT (Guid != NULL);\r
+  ASSERT (Name != NULL);\r
+  ASSERT (BlockNameArray != NULL);\r
+\r
+  //\r
+  // Initialize local variables\r
+  //\r
+  ConfigHdr     = NULL;\r
+  ConfigRequest = NULL; \r
+  ConfigResp    = NULL;\r
+\r
+  //\r
+  // Construct <ConfigHdr> : "GUID=...&NAME=...&PATH=..."\r
+  //\r
+  ConfigHdr = HiiConstructConfigHdr (Guid, Name, DriverHandle);\r
+  if (ConfigHdr == NULL) {\r
+    goto Exit;\r
+  }\r
+\r
+  //\r
+  // Compute the length of the entire request starting with <ConfigHdr> and a \r
+  // Null-terminator\r
+  //\r
+  Length = StrLen (ConfigHdr) + 1;\r
+\r
+  //\r
+  // Determine the size <BlockName> Offset/Width pairs\r
+  //\r
+  Buffer = (UINT8 *)BlockNameArray;\r
+  BufferEnd = Buffer + ReadUnaligned32 ((UINT32 *)Buffer);\r
+  Buffer += sizeof (UINT32);\r
+\r
+  //\r
+  // Add <BlockName> length that is composed of one or more Offset/Width pairs\r
+  //\r
+  // <BlockName> ::= &OFFSET=1234&WIDTH=1234\r
   //                 |  8   | 4 |   7  | 4 |\r
   //\r
   Length += (((BufferEnd - Buffer) / (sizeof (UINT16) + sizeof (UINT16))) * (8 + 4 + 7 + 4));\r
@@ -885,7 +2183,7 @@ HiiConstructConfigAltResp (
   //\r
   VA_START (Args, BlockNameArray);\r
   while (TRUE) {\r
-    AltCfgId = VA_ARG (Args, UINT16);\r
+    AltCfgId = VA_ARG (Args, UINTN);\r
     Buffer   = VA_ARG (Args, UINT8 *);\r
     if (Buffer == NULL) {\r
       break;\r
@@ -939,7 +2237,7 @@ HiiConstructConfigAltResp (
   //\r
   VA_START (Args, BlockNameArray);\r
   while (TRUE) {\r
-    AltCfgId = VA_ARG (Args, UINT16);\r
+    AltCfgId = VA_ARG (Args, UINTN);\r
     Buffer   = VA_ARG (Args, UINT8 *);\r
     if (Buffer == NULL) {\r
       break;\r
@@ -1155,38 +2453,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 +2502,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 +2792,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 +2831,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