]> 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 384bab4ed6f3d80bb83b9e683c62c1200d008e6b..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
 GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR16 mConfigHdrTemplate[] = L"GUID=00000000000000000000000000000000&NAME=0000&PATH=00";\r
 \r
+EFI_FORM_BROWSER2_PROTOCOL  *mUefiFormBrowser2 = NULL;\r
+\r
 //\r
-// Form Browser2 Protocol\r
+// Template used to mark the end of a list of packages \r
 //\r
-EFI_FORM_BROWSER2_PROTOCOL  *mUefiFormBrowser2 = NULL;\r
+GLOBAL_REMOVE_IF_UNREFERENCED CONST EFI_HII_PACKAGE_HEADER  mEndOfPakageList = {\r
+  sizeof (EFI_HII_PACKAGE_HEADER),\r
+  EFI_HII_PACKAGE_END\r
+};\r
 \r
 /**\r
-  This funciton build the package list based on the package number,\r
-  the GUID of the package list and the list of pointer which point to\r
-  package header that defined by UEFI VFR compiler and StringGather\r
-  tool.\r
-\r
-  #pragma pack (push, 1)\r
-  typedef struct {\r
-    UINT32                  BinaryLength;\r
-    EFI_HII_PACKAGE_HEADER  PackageHeader;\r
-  } EDKII_AUTOGEN_PACKAGES_HEADER;\r
-  #pragma pack (pop)\r
+  Extract Hii package list GUID for given HII handle.\r
 \r
-  If there is not enough resource for the new package list,\r
-  the function will ASSERT.\r
+  If HiiHandle could not be found in the HII database, then ASSERT.\r
+  If Guid is NULL, then ASSERT.\r
 \r
-  @param NumberOfPackages The number of packages be \r
-  @param GuidId          The GUID for the package list to be generated.\r
-  @param Marker          The variable argument list. Each entry represent a specific package header that is\r
-                         generated by VFR compiler and StrGather tool. The first 4 bytes is a UINT32 value\r
-                         that indicate the overall length of the package.\r
+  @param  Handle              Hii handle\r
+  @param  Guid                Package list GUID\r
 \r
-  @return The pointer to the package list header.\r
+  @retval EFI_SUCCESS         Successfully extract GUID from Hii database.\r
 \r
 **/\r
-EFI_HII_PACKAGE_LIST_HEADER *\r
-InternalHiiLibPreparePackages (\r
-  IN UINTN           NumberOfPackages,\r
-  IN CONST EFI_GUID  *GuidId,\r
-  IN VA_LIST         Marker\r
+EFI_STATUS\r
+EFIAPI\r
+InternalHiiExtractGuidFromHiiHandle (\r
+  IN      EFI_HII_HANDLE      Handle,\r
+  OUT     EFI_GUID            *Guid\r
   )\r
 {\r
-  EFI_HII_PACKAGE_LIST_HEADER *PackageListHeader;\r
-  UINT8                       *PackageListData;\r
-  UINT32                      PackageListLength;\r
-  UINT32                      PackageLength;\r
-  EFI_HII_PACKAGE_HEADER      PackageHeader;\r
-  UINT8                       *PackageArray;\r
-  UINTN                       Index;\r
-  VA_LIST                     MarkerBackup;\r
-\r
-  PackageListLength = sizeof (EFI_HII_PACKAGE_LIST_HEADER);\r
+  EFI_STATUS                   Status;\r
+  UINTN                        BufferSize;\r
+  EFI_HII_PACKAGE_LIST_HEADER  *HiiPackageList;\r
 \r
-  MarkerBackup = Marker;\r
+  ASSERT (Guid != NULL);\r
+  ASSERT (Handle != NULL);\r
 \r
   //\r
-  // Count the length of the final package list.\r
+  // Get HII PackageList\r
   //\r
-  for (Index = 0; Index < NumberOfPackages; Index++) {\r
-    CopyMem (&PackageLength, VA_ARG (Marker, VOID *), sizeof (UINT32));\r
-    //\r
-    // Do not count the BinaryLength field.\r
-    //\r
-    PackageListLength += (PackageLength - sizeof (UINT32));\r
-  }\r
+  BufferSize = 0;\r
+  HiiPackageList = NULL;\r
 \r
-  //\r
-  // Include the length of EFI_HII_PACKAGE_END\r
-  //\r
-  PackageListLength += sizeof (EFI_HII_PACKAGE_HEADER);\r
-  PackageListHeader = AllocateZeroPool (PackageListLength);\r
-  ASSERT (PackageListHeader != NULL);\r
+  Status = gHiiDatabase->ExportPackageLists (gHiiDatabase, Handle, &BufferSize, HiiPackageList);\r
+  ASSERT (Status != EFI_NOT_FOUND);\r
   \r
-  CopyGuid (&PackageListHeader->PackageListGuid, GuidId);\r
-  PackageListHeader->PackageLength = PackageListLength;\r
-\r
-  PackageListData = ((UINT8 *) PackageListHeader) + sizeof (EFI_HII_PACKAGE_LIST_HEADER);\r
+  if (Status == EFI_BUFFER_TOO_SMALL) {\r
+    HiiPackageList = AllocatePool (BufferSize);\r
+    ASSERT (HiiPackageList != NULL);\r
 \r
-  Marker = MarkerBackup;\r
-  //\r
-  // Prepare the final package list.\r
-  //\r
-  for (Index = 0; Index < NumberOfPackages; Index++) {\r
-    PackageArray = (UINT8 *) VA_ARG (Marker, VOID *);\r
-    //\r
-    // CopyMem is used for UINT32 to cover the unaligned address access.\r
-    //\r
-    CopyMem (&PackageLength, PackageArray, sizeof (UINT32));\r
-    PackageLength  -= sizeof (UINT32);\r
-    PackageArray += sizeof (UINT32);\r
-    CopyMem (PackageListData, PackageArray, PackageLength);\r
-    PackageListData += PackageLength;\r
+    Status = gHiiDatabase->ExportPackageLists (gHiiDatabase, Handle, &BufferSize, HiiPackageList);\r
+  }\r
+  if (EFI_ERROR (Status)) {\r
+    FreePool (HiiPackageList);\r
+    return Status;\r
   }\r
 \r
   //\r
-  // Append EFI_HII_PACKAGE_END\r
+  // Extract GUID\r
   //\r
-  PackageHeader.Type = EFI_HII_PACKAGE_END;\r
-  PackageHeader.Length = sizeof (EFI_HII_PACKAGE_HEADER);\r
-  CopyMem (PackageListData, &PackageHeader, PackageHeader.Length);\r
+  CopyGuid (Guid, &HiiPackageList->PackageListGuid);\r
+\r
+  FreePool (HiiPackageList);\r
 \r
-  return PackageListHeader;\r
+  return EFI_SUCCESS;\r
 }\r
 \r
 /**\r
-  Assemble EFI_HII_PACKAGE_LIST according to the passed in packages.\r
-\r
-  If GuidId is NULL, then ASSERT.\r
-  If not enough resource to complete the operation, then ASSERT.\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
+  with the same PackageListGuid, then NULL is returned.  If there are not enough \r
+  resources to perform the registration, then NULL is returned.  If an empty list \r
+  of packages is passed in, then NULL is returned.  If the size of the list of \r
+  package is 0, then NULL is returned.\r
 \r
-  @param  NumberOfPackages       Number of packages.\r
-  @param  GuidId                 Package GUID.\r
-  @param  ...                    Variable argument list for packages to be assembled.\r
+  The variable arguments are pointers which point to package header that defined \r
+  by UEFI VFR compiler and StringGather tool.\r
 \r
-  @return Pointer of EFI_HII_PACKAGE_LIST_HEADER.\r
+  #pragma pack (push, 1)\r
+  typedef struct {\r
+    UINT32                  BinaryLength;\r
+    EFI_HII_PACKAGE_HEADER  PackageHeader;\r
+  } EDKII_AUTOGEN_PACKAGES_HEADER;\r
+  #pragma pack (pop)\r
+  \r
+  @param[in]  PackageListGuid  The GUID of the package list.\r
+  @param[in]  DeviceHandle     If not NULL, the Device Handle on which \r
+                               an instance of DEVICE_PATH_PROTOCOL is installed.\r
+                               This Device Handle uniquely defines the device that \r
+                               the added packages are associated with.\r
+  @param[in]  ...              The variable argument list that contains pointers \r
+                               to packages terminated by a NULL.\r
+\r
+  @retval NULL   A HII Handle has already been registered in the HII Database with\r
+                 the same PackageListGuid.\r
+  @retval NULL   The HII Handle could not be created.\r
+  @retval NULL   An empty list of packages was passed in.\r
+  @retval NULL   All packages are empty.\r
+  @retval Other  The HII Handle associated with the newly registered package list.\r
 \r
 **/\r
-EFI_HII_PACKAGE_LIST_HEADER *\r
+EFI_HII_HANDLE\r
 EFIAPI\r
-HiiLibPreparePackageList (\r
-  IN UINTN                    NumberOfPackages,\r
-  IN CONST EFI_GUID           *GuidId,\r
+HiiAddPackages (\r
+  IN CONST EFI_GUID    *PackageListGuid,\r
+  IN       EFI_HANDLE  DeviceHandle  OPTIONAL,\r
   ...\r
   )\r
 {\r
-  EFI_HII_PACKAGE_LIST_HEADER *PackageListHeader;\r
-  VA_LIST                     Marker;\r
-\r
-  ASSERT (GuidId != NULL);\r
+  EFI_STATUS                   Status;\r
+  EFI_HII_HANDLE               *HiiHandleBuffer;\r
+  VA_LIST                      Args;\r
+  UINT32                       *Package;\r
+  EFI_HII_PACKAGE_LIST_HEADER  *PackageListHeader;\r
+  EFI_HII_HANDLE               HiiHandle;\r
+  UINT32                       Length;\r
+  UINT8                        *Data;\r
 \r
-  VA_START (Marker, GuidId);\r
-  PackageListHeader = InternalHiiLibPreparePackages (NumberOfPackages, GuidId, Marker);\r
-  VA_END (Marker);\r
+  ASSERT (PackageListGuid != NULL);\r
 \r
-  return PackageListHeader;\r
-}\r
+  //\r
+  // Check to see if an HII Handle has already been registered with the same \r
+  // PackageListGuid\r
+  //\r
+  HiiHandleBuffer = HiiGetHiiHandles (PackageListGuid);\r
+  if (HiiHandleBuffer != NULL) {\r
+    FreePool (HiiHandleBuffer);\r
+    return NULL;\r
+  }\r
 \r
+  //\r
+  // Calculate the length of all the packages in the variable argument list\r
+  //\r
+  for (Length = 0, VA_START (Args, DeviceHandle); (Package = VA_ARG (Args, UINT32 *)) != NULL; ) {\r
+    Length += (ReadUnaligned32 (Package) - sizeof (UINT32));\r
+  }\r
+  VA_END (Args);\r
 \r
-/**\r
-  This function allocates pool for an EFI_HII_PACKAGE_LIST structure\r
-  with additional space that is big enough to host all packages described by the variable \r
-  argument list of package pointers.  The allocated structure is initialized using NumberOfPackages, \r
-  GuidId,  and the variable length argument list of package pointers.\r
+  //\r
+  // If there are no packages in the variable argument list or all the packages \r
+  // are empty, then return a NULL HII Handle\r
+  //\r
+  if (Length == 0) {\r
+    return NULL;\r
+  }\r
 \r
-  Then, EFI_HII_PACKAGE_LIST will be register to the default System HII Database. The\r
-  Handle to the newly registered Package List is returned through HiiHandle.\r
+  //\r
+  // Add the length of the Package List Header and the terminating Package Header \r
+  //\r
+  Length += sizeof (EFI_HII_PACKAGE_LIST_HEADER) + sizeof (EFI_HII_PACKAGE_HEADER);\r
 \r
-  If HiiHandle is NULL, then ASSERT.\r
+  //\r
+  // Allocate the storage for the entire Package List\r
+  //\r
+  PackageListHeader = AllocateZeroPool (Length);\r
 \r
-  @param  NumberOfPackages    The number of HII packages to register.\r
-  @param  GuidId              Package List GUID ID.\r
-  @param  DriverHandle        Optional. If not NULL, the DriverHandle on which an instance of DEVICE_PATH_PROTOCOL is installed.\r
-                              This DriverHandle uniquely defines the device that the added packages are associated with.\r
-  @param  HiiHandle           On output, the HiiHandle is update with the handle which can be used to retrieve the Package \r
-                              List later. If the functions failed to add the package to the default HII database, this value will\r
-                              be set to NULL.\r
-  @param  ...                 The variable argument list describing all HII Package.\r
+  //\r
+  // If the Packahge List can not be allocated, then return a NULL HII Handle\r
+  //\r
+  if (PackageListHeader == NULL) {\r
+    return NULL;\r
+  }\r
 \r
-  @return  EFI_SUCCESS         If the packages are successfully added to the default HII database.\r
-  @return  EFI_OUT_OF_RESOURCE Not enough resource to complete the operation.\r
+  //\r
+  // Fill in the GUID and Length of the Package List Header\r
+  //\r
+  CopyGuid (&PackageListHeader->PackageListGuid, PackageListGuid);\r
+  PackageListHeader->PackageLength = Length;\r
 \r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-HiiLibAddPackages (\r
-  IN       UINTN               NumberOfPackages,\r
-  IN CONST EFI_GUID            *GuidId,\r
-  IN       EFI_HANDLE          DriverHandle, OPTIONAL\r
-  OUT      EFI_HII_HANDLE      *HiiHandle,\r
-  ...\r
-  )\r
-{\r
-  VA_LIST                   Args;\r
-  EFI_HII_PACKAGE_LIST_HEADER *PackageListHeader;\r
-  EFI_STATUS                Status;\r
+  //\r
+  // Initialize a pointer to the beginning if the Package List data\r
+  //\r
+  Data = (UINT8 *)(PackageListHeader + 1);\r
 \r
-  ASSERT (HiiHandle != NULL);\r
+  //\r
+  // Copy the data from each package in the variable argument list\r
+  //\r
+  for (VA_START (Args, DeviceHandle); (Package = VA_ARG (Args, UINT32 *)) != NULL; ) {\r
+    Length = ReadUnaligned32 (Package) - sizeof (UINT32);\r
+    CopyMem (Data, Package + 1, Length);\r
+    Data += Length;\r
+  }\r
+  VA_END (Args);\r
 \r
-  VA_START (Args, HiiHandle);\r
-  PackageListHeader = InternalHiiLibPreparePackages (NumberOfPackages, GuidId, Args);\r
+  //\r
+  // Append a package of type EFI_HII_PACKAGE_END to mark the end of the package list\r
+  //\r
+  CopyMem (Data, &mEndOfPakageList, sizeof (mEndOfPakageList));\r
 \r
-  Status      = gHiiDatabase->NewPackageList (gHiiDatabase, PackageListHeader, DriverHandle, HiiHandle);\r
-  if (HiiHandle != NULL) {\r
-    if (EFI_ERROR (Status)) {\r
-      *HiiHandle = NULL;\r
-    }\r
+  //\r
+  // Register the package list with the HII Database\r
+  //\r
+  Status = gHiiDatabase->NewPackageList (\r
+                           gHiiDatabase, \r
+                           PackageListHeader, \r
+                           DeviceHandle, \r
+                           &HiiHandle\r
+                           );\r
+  if (EFI_ERROR (Status)) {\r
+    HiiHandle = NULL;\r
   }\r
 \r
+  //\r
+  // Free the allocated package list\r
+  //\r
   FreePool (PackageListHeader);\r
-  VA_END (Args);\r
-  \r
-  return Status;\r
+\r
+  //\r
+  // Return the new HII Handle\r
+  //\r
+  return HiiHandle;\r
 }\r
 \r
 /**\r
-  Removes a package list from the default HII database.\r
+  Removes a package list from the HII database.\r
 \r
   If HiiHandle is NULL, then ASSERT.\r
-  If HiiHandle is not a valid EFI_HII_HANDLE in the default HII database, then ASSERT.\r
+  If HiiHandle is not a valid EFI_HII_HANDLE in the HII database, then ASSERT.\r
 \r
-  @param  HiiHandle                The handle that was previously registered to the data base that is requested for removal.\r
-                                             List later.\r
+  @param[in]  HiiHandle   The handle that was previously registered in the HII database\r
 \r
 **/\r
 VOID\r
 EFIAPI\r
-HiiLibRemovePackages (\r
+HiiRemovePackages (\r
   IN      EFI_HII_HANDLE      HiiHandle\r
   )\r
 {\r
   EFI_STATUS Status;\r
-  ASSERT (IsHiiHandleRegistered (HiiHandle));\r
 \r
+  ASSERT (HiiHandle != NULL);\r
   Status = gHiiDatabase->RemovePackageList (gHiiDatabase, HiiHandle);\r
   ASSERT_EFI_ERROR (Status);\r
 }\r
 \r
 \r
 /**\r
-  Determines the handles that are currently active in the database.\r
-  It's the caller's responsibility to free handle buffer.\r
-\r
-  If HandleBufferLength is NULL, then ASSERT.\r
-  If HiiHandleBuffer is NULL, then ASSERT.\r
-\r
-  @param  HandleBufferLength     On input, a pointer to the length of the handle\r
-                                 buffer. On output, the length of the handle buffer\r
-                                 that is required for the handles found.\r
-  @param  HiiHandleBuffer        Pointer to an array of Hii Handles returned.\r
-\r
-  @retval EFI_SUCCESS            Get an array of Hii Handles successfully.\r
+  Retrieves the array of all the HII Handles or the HII handle of a specific\r
+  package list 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
+                               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
+\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
+  @retval Other  A pointer to the NULL terminated array of HII Handles\r
 \r
 **/\r
-EFI_STATUS\r
+EFI_HII_HANDLE *\r
 EFIAPI\r
-HiiLibGetHiiHandles (\r
-  IN OUT UINTN                     *HandleBufferLength,\r
-  OUT    EFI_HII_HANDLE            **HiiHandleBuffer\r
+HiiGetHiiHandles (\r
+  IN CONST EFI_GUID  *PackageListGuid  OPTIONAL\r
   )\r
 {\r
-  EFI_STATUS  Status;\r
+  EFI_STATUS      Status;\r
+  UINTN           HandleBufferLength;\r
+  EFI_HII_HANDLE  TempHiiHandleBuffer;\r
+  EFI_HII_HANDLE  *HiiHandleBuffer;\r
+  EFI_GUID        Guid;\r
+  UINTN           Index;\r
 \r
-  ASSERT (HandleBufferLength != NULL);\r
-  ASSERT (HiiHandleBuffer != NULL);\r
+  //\r
+  // Retrieve the size required for the buffer of all HII handles.\r
+  //\r
+  HandleBufferLength = 0;\r
+  Status = gHiiDatabase->ListPackageLists (\r
+                           gHiiDatabase,\r
+                           EFI_HII_PACKAGE_TYPE_ALL,\r
+                           NULL,\r
+                           &HandleBufferLength,\r
+                           &TempHiiHandleBuffer\r
+                           );\r
+\r
+  //\r
+  // If ListPackageLists() returns EFI_SUCCESS for a zero size, \r
+  // then there are no HII handles in the HII database.  If ListPackageLists() \r
+  // returns an error other than EFI_BUFFER_TOO_SMALL, then there are no HII \r
+  // handles in the HII database.\r
+  //\r
+  if (Status != EFI_BUFFER_TOO_SMALL) {\r
+    //\r
+    // Return NULL if the size can not be retrieved, or if there are no HII \r
+    // handles in the HII Database\r
+    //\r
+    return NULL;\r
+  }\r
 \r
-  *HandleBufferLength = 0;\r
-  *HiiHandleBuffer = NULL;\r
+  //\r
+  // Allocate the array of HII handles to hold all the HII Handles and a NULL terminator\r
+  //\r
+  HiiHandleBuffer = AllocateZeroPool (HandleBufferLength + sizeof (EFI_HII_HANDLE));\r
+  if (HiiHandleBuffer == NULL) {\r
+    //\r
+    // Return NULL if allocation fails.\r
+    //\r
+    return NULL;\r
+  }\r
 \r
   //\r
-  // Try to find the actual buffer size for HiiHandle Buffer.\r
+  // Retrieve the array of HII Handles in the HII Database\r
   //\r
   Status = gHiiDatabase->ListPackageLists (\r
-                                 gHiiDatabase,\r
-                                 EFI_HII_PACKAGE_TYPE_ALL,\r
-                                 NULL,\r
-                                 HandleBufferLength,\r
-                                 *HiiHandleBuffer\r
-                                 );\r
-  \r
-  if (Status == EFI_BUFFER_TOO_SMALL) {\r
-      *HiiHandleBuffer = AllocateZeroPool (*HandleBufferLength);\r
-      ASSERT (*HiiHandleBuffer != NULL);\r
-      Status = gHiiDatabase->ListPackageLists (\r
-                                     gHiiDatabase,\r
-                                     EFI_HII_PACKAGE_TYPE_ALL,\r
-                                     NULL,\r
-                                     HandleBufferLength,\r
-                                     *HiiHandleBuffer\r
-                                     );\r
+                           gHiiDatabase,\r
+                           EFI_HII_PACKAGE_TYPE_ALL,\r
+                           NULL,\r
+                           &HandleBufferLength,\r
+                           HiiHandleBuffer\r
+                           );\r
+  if (EFI_ERROR (Status)) {\r
+    //\r
+    // Free the buffer and return NULL if the HII handles can not be retrieved.\r
+    //\r
+    FreePool (HiiHandleBuffer);\r
+    return NULL;\r
+  }\r
 \r
-      if (EFI_ERROR (Status)) {\r
-        FreePool (*HiiHandleBuffer);\r
-        *HiiHandleBuffer = NULL;\r
+  if (PackageListGuid == NULL) {\r
+    //\r
+    // Return the NULL terminated array of HII handles in the HII Database\r
+    //\r
+    return HiiHandleBuffer;\r
+  } else {\r
+    for (Index = 0; HiiHandleBuffer[Index] != NULL; Index++) {\r
+      Status = InternalHiiExtractGuidFromHiiHandle (HiiHandleBuffer[Index], &Guid);\r
+      ASSERT_EFI_ERROR (Status);\r
+      if (CompareGuid (&Guid, PackageListGuid)) {\r
+        HiiHandleBuffer[0] = HiiHandleBuffer[Index];\r
+        HiiHandleBuffer[1] = NULL;\r
+        return HiiHandleBuffer;\r
       }\r
+    }\r
+    FreePool (HiiHandleBuffer);\r
+    return NULL;\r
   }\r
-\r
-  return Status;\r
 }\r
 \r
 /**\r
-  Extract Hii package list GUID for given HII handle.\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
 \r
-  If HiiHandle could not be found in the default HII database, then ASSERT.\r
-  If Guid is NULL, then ASSERT.\r
+  If String is NULL, then ASSERT().\r
 \r
-  @param  Handle              Hii handle\r
-  @param  Guid                Package list GUID\r
+  @param[in] String  Pointer to a Null-terminated Unicode string.\r
 \r
-  @retval EFI_SUCCESS            Successfully extract GUID from Hii database.\r
+  @return  Pointer to the Null-terminated Unicode result string.\r
 \r
 **/\r
-EFI_STATUS\r
+EFI_STRING\r
 EFIAPI\r
-HiiLibExtractGuidFromHiiHandle (\r
-  IN      EFI_HII_HANDLE      Handle,\r
-  OUT     EFI_GUID            *Guid\r
+InternalHiiLowerConfigString (\r
+  IN EFI_STRING  ConfigString\r
   )\r
 {\r
-  EFI_STATUS                   Status;\r
-  UINTN                        BufferSize;\r
-  EFI_HII_PACKAGE_LIST_HEADER  *HiiPackageList;\r
+  EFI_STRING  String;\r
+  BOOLEAN     Lower;\r
 \r
-  ASSERT (Guid != NULL);\r
-  ASSERT (IsHiiHandleRegistered (Handle));\r
+  ASSERT (ConfigString != NULL);\r
 \r
   //\r
-  // Get HII PackageList\r
+  // Convert all hex digits in range [A-F] in the configuration header to [a-f]\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
+  for (String = ConfigString, Lower = FALSE; *String != L'\0'; String++) {\r
+    if (*String == L'=') {\r
+      Lower = TRUE;\r
+    } else if (*String == L'&') {\r
+      Lower = FALSE;\r
+    } else if (Lower && *String >= L'A' && *String <= L'F') {\r
+      *String = (CHAR16) (*String - L'A' + L'a');\r
+    }\r
   }\r
 \r
-  //\r
-  // Extract GUID\r
-  //\r
-  CopyGuid (Guid, &HiiPackageList->PackageListGuid);\r
-\r
-  FreePool (HiiPackageList);\r
-\r
-  return EFI_SUCCESS;\r
+  return ConfigString;\r
 }\r
 \r
 /**\r
-  Find HII Handle in the default HII database associated with given Device Path.\r
+  Uses the BlockToConfig() service of the Config Routing Protocol to \r
+  convert <ConfigRequest> and a buffer to a <ConfigResp>\r
 \r
-  If DevicePath is NULL, then ASSERT.\r
+  If ConfigRequest is NULL, then ASSERT().\r
+  If Block is NULL, then ASSERT().\r
 \r
-  @param  DevicePath             Device Path associated with the HII package list\r
-                                 handle.\r
+  @param[in] ConfigRequest  Pointer to a Null-terminated Unicode string.\r
+  @param[in] Block          Pointer to a block of data.\r
+  @param[in] BlockSize      The zie, in bytes, of Block.\r
 \r
-  @retval Handle                 HII package list Handle associated with the Device\r
-                                        Path.\r
-  @retval NULL                   Hii Package list handle is not found.\r
+  @retval NULL   The <ConfigResp> string could not be generated.\r
+  @retval Other  Pointer to the Null-terminated Unicode <ConfigResp> string.\r
 \r
 **/\r
-EFI_HII_HANDLE\r
+EFI_STRING\r
 EFIAPI\r
-HiiLibDevicePathToHiiHandle (\r
-  IN EFI_DEVICE_PATH_PROTOCOL   *DevicePath\r
+InternalHiiBlockToConfig (\r
+  IN CONST EFI_STRING  ConfigRequest,\r
+  IN CONST UINT8       *Block,\r
+  IN UINTN             BlockSize\r
   )\r
 {\r
-  EFI_STATUS                  Status;\r
-  EFI_DEVICE_PATH_PROTOCOL    *TmpDevicePath;\r
-  UINTN                       BufferSize;\r
-  UINTN                       HandleCount;\r
-  UINTN                       Index;\r
-  EFI_HANDLE                  *Handles;\r
-  EFI_HANDLE                  Handle;\r
-  UINTN                       Size;\r
-  EFI_HANDLE                  DriverHandle;\r
-  EFI_HII_HANDLE              *HiiHandles;\r
-  EFI_HII_HANDLE              HiiHandle;\r
-\r
-  ASSERT (DevicePath != NULL);\r
-\r
-  //\r
-  // Locate Device Path Protocol handle buffer\r
-  //\r
-  Status = gBS->LocateHandleBuffer (\r
-                  ByProtocol,\r
-                  &gEfiDevicePathProtocolGuid,\r
-                  NULL,\r
-                  &HandleCount,\r
-                  &Handles\r
-                  );\r
-  if (EFI_ERROR (Status)) {\r
-    return NULL;\r
-  }\r
-\r
-  //\r
-  // Search Driver Handle by Device Path\r
-  //\r
-  DriverHandle = NULL;\r
-  BufferSize = GetDevicePathSize (DevicePath);\r
-  for(Index = 0; Index < HandleCount; Index++) {\r
-    Handle = Handles[Index];\r
-    gBS->HandleProtocol (Handle, &gEfiDevicePathProtocolGuid, (VOID **) &TmpDevicePath);\r
-\r
-    //\r
-    // Check whether DevicePath match\r
-    //\r
-    Size = GetDevicePathSize (TmpDevicePath);\r
-    if ((Size == BufferSize) && CompareMem (DevicePath, TmpDevicePath, Size) == 0) {\r
-      DriverHandle = Handle;\r
-      break;\r
-    }\r
-  }\r
-  FreePool (Handles);\r
+  EFI_STATUS  Status;\r
+  EFI_STRING  ConfigResp;\r
+  CHAR16      *Progress;\r
 \r
-  if (DriverHandle == NULL) {\r
-    return NULL;\r
-  }\r
+  ASSERT (ConfigRequest != NULL);\r
+  ASSERT (Block != NULL);\r
 \r
   //\r
-  // Retrieve all Hii Handles from HII database\r
-  //\r
-  BufferSize = 0x1000;\r
-  HiiHandles = AllocatePool (BufferSize);\r
-  ASSERT (HiiHandles != NULL);\r
-  Status = gHiiDatabase->ListPackageLists (\r
-                          gHiiDatabase,\r
-                          EFI_HII_PACKAGE_TYPE_ALL,\r
-                          NULL,\r
-                          &BufferSize,\r
-                          HiiHandles\r
-                          );\r
-  if (Status == EFI_BUFFER_TOO_SMALL) {\r
-    FreePool (HiiHandles);\r
-    HiiHandles = AllocatePool (BufferSize);\r
-    ASSERT (HiiHandles != NULL);\r
-\r
-    Status = gHiiDatabase->ListPackageLists (\r
-                            gHiiDatabase,\r
-                            EFI_HII_PACKAGE_TYPE_ALL,\r
-                            NULL,\r
-                            &BufferSize,\r
-                            HiiHandles\r
-                            );\r
-  }\r
-\r
-  if (EFI_ERROR (Status)) {\r
-    FreePool (HiiHandles);\r
-    return NULL;\r
-  }\r
-\r
-  //\r
-  // Search Hii Handle by Driver Handle\r
-  //\r
-  HiiHandle = NULL;\r
-  HandleCount = BufferSize / sizeof (EFI_HII_HANDLE);\r
-  for (Index = 0; Index < HandleCount; Index++) {\r
-    Status = gHiiDatabase->GetPackageListHandle (\r
-                            gHiiDatabase,\r
-                            HiiHandles[Index],\r
-                            &Handle\r
-                            );\r
-    if (!EFI_ERROR (Status) && (Handle == DriverHandle)) {\r
-      HiiHandle = HiiHandles[Index];\r
-      break;\r
-    }\r
-  }\r
-\r
-  FreePool (HiiHandles);\r
-  return HiiHandle;\r
-}\r
-\r
-/**\r
-  Exports the contents of one or all package lists in the HII database into a buffer.\r
-\r
-  If Handle is not NULL and not a valid EFI_HII_HANDLE registered in the database, \r
-  then ASSERT.\r
-  If PackageListHeader is NULL, then ASSERT.\r
-  If PackageListSize is NULL, then ASSERT.\r
-\r
-  @param  Handle                 The HII Handle.\r
-  @param  PackageListHeader      A pointer to a buffer that will contain the results of \r
-                                 the export function.\r
-  @param  PackageListSize        On output, the length of the buffer that is required for the exported data.\r
-\r
-  @retval EFI_SUCCESS            Package exported.\r
-\r
-  @retval EFI_OUT_OF_RESOURCES   Not enought memory to complete the operations.\r
-\r
-**/\r
-EFI_STATUS \r
-EFIAPI\r
-HiiLibExportPackageLists (\r
-  IN EFI_HII_HANDLE                    Handle,\r
-  OUT EFI_HII_PACKAGE_LIST_HEADER      **PackageListHeader,\r
-  OUT UINTN                            *PackageListSize\r
-  )\r
-{\r
-  EFI_STATUS                       Status;\r
-  UINTN                            Size;\r
-  EFI_HII_PACKAGE_LIST_HEADER      *PackageListHdr;\r
-\r
-  ASSERT (PackageListSize != NULL);\r
-  ASSERT (PackageListHeader != NULL);\r
-\r
-  if (Handle != NULL) {\r
-    ASSERT (IsHiiHandleRegistered (Handle));\r
-  }\r
-\r
-  Size = 0;\r
-  PackageListHdr = NULL;\r
-  Status = gHiiDatabase->ExportPackageLists (\r
-                                      gHiiDatabase,\r
-                                      Handle,\r
-                                      &Size,\r
-                                      PackageListHdr\r
-                                      );\r
-  ASSERT_EFI_ERROR (Status != EFI_BUFFER_TOO_SMALL);\r
-  \r
-  if (Status == EFI_BUFFER_TOO_SMALL) {\r
-    PackageListHdr = AllocateZeroPool (Size);\r
-    \r
-    if (PackageListHeader == NULL) {\r
-      return EFI_OUT_OF_RESOURCES;\r
-    } else {\r
-      Status = gHiiDatabase->ExportPackageLists (\r
-                                          gHiiDatabase,\r
-                                          Handle,\r
-                                          &Size,\r
-                                          PackageListHdr\r
-                                           );\r
-    }\r
-  }\r
-\r
-  if (!EFI_ERROR (Status)) {\r
-    *PackageListHeader = PackageListHdr;\r
-    *PackageListSize   = Size;\r
-  } else {\r
-    FreePool (PackageListHdr);\r
-  }\r
-\r
-  return Status;\r
-}\r
-\r
-/**\r
-  \r
-  This function returns a list of the package handles of the   \r
-  specified type that are currently active in the HII database. The   \r
-  pseudo-type EFI_HII_PACKAGE_TYPE_ALL will cause all package   \r
-  handles to be listed.\r
-\r
-  If HandleBufferLength is NULL, then ASSERT.\r
-  If HandleBuffer is NULL, the ASSERT.\r
-  If PackageType is EFI_HII_PACKAGE_TYPE_GUID and PackageGuid is\r
-  NULL, then ASSERT.\r
-  If PackageType is not EFI_HII_PACKAGE_TYPE_GUID and PackageGuid is not\r
-  NULL, then ASSERT.\r
-  \r
-  \r
-  @param PackageType          Specifies the package type of the packages\r
-                              to list or EFI_HII_PACKAGE_TYPE_ALL for\r
-                              all packages to be listed.\r
-  \r
-  @param PackageGuid          If PackageType is\r
-                              EFI_HII_PACKAGE_TYPE_GUID, then this is\r
-                              the pointer to the GUID which must match\r
-                              the Guid field of\r
-                              EFI_HII_PACKAGE_GUID_HEADER. Otherwise, it\r
-                              must be NULL.\r
-  \r
-  @param HandleBufferLength   On output, the length of the handle buffer\r
-                              that is required for the handles found.\r
-\r
-  @param HandleBuffer         On output, an array of EFI_HII_HANDLE  instances returned.\r
-                              The caller is responcible to free this pointer allocated.\r
-\r
-  @retval EFI_SUCCESS           The matching handles are outputed successfully.\r
-                                HandleBufferLength is updated with the actual length.\r
-  @retval EFI_OUT_OF_RESOURCES  Not enough resource to complete the operation.\r
-  @retval EFI_NOT_FOUND         No matching handle could not be found in database.\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-HiiLibListPackageLists (\r
-  IN        UINT8                     PackageType,\r
-  IN CONST  EFI_GUID                  *PackageGuid,\r
-  IN OUT    UINTN                     *HandleBufferLength,\r
-  OUT       EFI_HII_HANDLE            **HandleBuffer\r
-  )\r
-{\r
-  EFI_STATUS          Status;\r
-  \r
-  ASSERT (HandleBufferLength != NULL);\r
-  ASSERT (HandleBuffer != NULL);\r
-  \r
-  *HandleBufferLength = 0;\r
-  *HandleBuffer       = NULL;\r
-\r
-  if (PackageType == EFI_HII_PACKAGE_TYPE_GUID) {\r
-    ASSERT (PackageGuid != NULL);\r
-  } else {\r
-    ASSERT (PackageGuid == NULL);\r
-  }\r
-\r
-  Status = gHiiDatabase->ListPackageLists (\r
-                            gHiiDatabase,\r
-                            PackageType,\r
-                            PackageGuid,\r
-                            HandleBufferLength,\r
-                            *HandleBuffer\r
-                            );\r
-  if (EFI_ERROR (Status) && (Status != EFI_BUFFER_TOO_SMALL)) {\r
-    //\r
-    // No packages is registered to UEFI HII Database, just return.\r
-    // \r
-    //\r
-    return Status;\r
-  }\r
-\r
-  *HandleBuffer = AllocateZeroPool (*HandleBufferLength);\r
-  \r
-  if (*HandleBuffer == NULL) {\r
-    return EFI_OUT_OF_RESOURCES;\r
-  }\r
-  \r
-  return gHiiDatabase->ListPackageLists (\r
-                            gHiiDatabase,\r
-                            PackageType,\r
-                            PackageGuid,\r
-                            HandleBufferLength,\r
-                            *HandleBuffer\r
-                            );\r
-  \r
-}\r
-/**\r
-  This function check if the Hii Handle is a valid handle registered\r
-  in the HII database.\r
-\r
-  @param HiiHandle The HII Handle.\r
-\r
-  @retval TRUE If it is a valid HII handle.\r
-  @retval FALSE If it is a invalid HII handle.\r
-**/\r
-BOOLEAN\r
-IsHiiHandleRegistered (\r
-  EFI_HII_HANDLE    HiiHandle\r
-  )\r
-{\r
-  EFI_STATUS                   Status;\r
-  UINTN                        BufferSize;\r
-  EFI_HII_PACKAGE_LIST_HEADER  *HiiPackageList;\r
-\r
-  ASSERT (HiiHandle != NULL);\r
-\r
-  HiiPackageList = NULL;\r
-  BufferSize = 0;\r
-\r
-  Status = gHiiDatabase->ExportPackageLists (\r
-             gHiiDatabase,\r
-             HiiHandle,\r
-             &BufferSize,\r
-             HiiPackageList\r
-             );\r
-\r
-  return (BOOLEAN) (Status == EFI_BUFFER_TOO_SMALL);\r
-}\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
-\r
-  If String is NULL, then ASSERT().\r
-\r
-  @param[in] String  Pointer to a Null-terminated Unicode string.\r
-\r
-  @return  Pointer to the Null-terminated Unicode result string.\r
-\r
-**/\r
-EFI_STRING\r
-EFIAPI\r
-InternalHiiLowerConfigString (\r
-  IN EFI_STRING  ConfigString\r
-  )\r
-{\r
-  EFI_STRING  String;\r
-  BOOLEAN     Lower;\r
-\r
-  ASSERT (ConfigString != NULL);\r
-\r
-  //\r
-  // Convert all hex digits in range [A-F] in the configuration header to [a-f]\r
-  //\r
-  for (String = ConfigString, Lower = FALSE; *String != L'\0'; String++) {\r
-    if (*String == L'=') {\r
-      Lower = TRUE;\r
-    } else if (*String == L'&') {\r
-      Lower = FALSE;\r
-    } else if (Lower && *String >= L'A' && *String <= L'F') {\r
-      *String = (CHAR16) (*String - L'A' + L'a');\r
-    }\r
-  }\r
-\r
-  return ConfigString;\r
-}\r
-\r
-/**\r
-  Uses the BlockToConfig() service of the Config Routing Protocol to \r
-  convert <ConfigRequest> and a buffer to a <ConfigResp>\r
-\r
-  If ConfigRequest is NULL, then ASSERT().\r
-  If Block is NULL, then ASSERT().\r
-\r
-  @param[in] ConfigRequest  Pointer to a Null-terminated Unicode string.\r
-  @param[in] Block          Pointer to a block of data.\r
-  @param[in] BlockSize      The zie, in bytes, of Block.\r
-\r
-  @retval NULL   The <ConfigResp> string could not be generated.\r
-  @retval Other  Pointer to the Null-terminated Unicode <ConfigResp> string.\r
-\r
-**/\r
-EFI_STRING\r
-EFIAPI\r
-InternalHiiBlockToConfig (\r
-  IN CONST EFI_STRING  ConfigRequest,\r
-  IN CONST UINT8       *Block,\r
-  IN UINTN             BlockSize\r
-  )\r
-{\r
-  EFI_STATUS  Status;\r
-  EFI_STRING  ConfigResp;\r
-  CHAR16      *Progress;\r
-\r
-  ASSERT (ConfigRequest != NULL);\r
-  ASSERT (Block != NULL);\r
-\r
-  //\r
-  // Convert <ConfigRequest> to <ConfigResp>\r
+  // Convert <ConfigRequest> to <ConfigResp>\r
   //\r
   Status = gHiiConfigRouting->BlockToConfig (\r
                                 gHiiConfigRouting,\r
@@ -754,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
@@ -857,182 +509,1520 @@ InternalHiiBrowserCallback (
 \r
   if (SetResultsData != NULL) {\r
     //\r
-    // Request to to set data in the uncommitted browser state information\r
+    // Request to to set data in the uncommitted browser state information\r
+    //\r
+    ResultsData = SetResultsData;\r
+  } else {\r
+    //\r
+    // Retrieve the length of the buffer required ResultsData from the Browser Callback\r
+    //\r
+    Status = mUefiFormBrowser2->BrowserCallback (\r
+                              mUefiFormBrowser2,\r
+                              &ResultsDataSize,\r
+                              &TempResultsData,\r
+                              TRUE,\r
+                              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
+\r
+    //\r
+    // Allocate the ResultsData buffer\r
+    //\r
+    ResultsData = AllocateZeroPool (ResultsDataSize);\r
+    if (ResultsData == NULL) {\r
+      return NULL;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Retrieve or set the ResultsData from the Browser Callback\r
+  //\r
+  Status = mUefiFormBrowser2->BrowserCallback (\r
+                            mUefiFormBrowser2,\r
+                            &ResultsDataSize,\r
+                            ResultsData,\r
+                            (BOOLEAN)(SetResultsData == NULL),\r
+                            VariableGuid,\r
+                            VariableName\r
+                            );\r
+  if (EFI_ERROR (Status)) {\r
+    return NULL;\r
+  }\r
+\r
+  return ResultsData;\r
+}\r
+\r
+/**\r
+  Allocates and returns a Null-terminated Unicode <ConfigHdr> string using routing \r
+  information that includes a GUID, an optional Unicode string name, and a device\r
+  path.  The string returned is allocated with AllocatePool().  The caller is \r
+  responsible for freeing the allocated string with FreePool().\r
+  \r
+  The format of a <ConfigHdr> is as follows:\r
+\r
+    GUID=<HexCh>32&NAME=<Char>NameLength&PATH=<HexChar>DevicePathSize<Null>\r
+\r
+  @param[in]  Guid          Pointer to an EFI_GUID that is the routing information\r
+                            GUID.  Each of the 16 bytes in Guid is converted to \r
+                            a 2 Unicode character hexidecimal string.  This is \r
+                            an optional parameter that may be NULL.\r
+  @param[in]  Name          Pointer to a Null-terminated Unicode string that is \r
+                            the routing information NAME.  This is an optional \r
+                            parameter that may be NULL.  Each 16-bit Unicode \r
+                            character in Name is converted to a 4 character Unicode \r
+                            hexidecimal string.                        \r
+  @param[in]  DriverHandle  The driver handle which supports a Device Path Protocol\r
+                            that is the routing information PATH.  Each byte of\r
+                            the Device Path associated with DriverHandle is converted\r
+                            to a 2 Unicode character hexidecimal string.\r
+\r
+  @retval NULL   DriverHandle does not support the Device Path Protocol.\r
+  @retval Other  A pointer to the Null-terminate Unicode <ConfigHdr> string\r
+\r
+**/\r
+EFI_STRING\r
+EFIAPI\r
+HiiConstructConfigHdr (\r
+  IN CONST EFI_GUID  *Guid,  OPTIONAL\r
+  IN CONST CHAR16    *Name,  OPTIONAL\r
+  IN EFI_HANDLE      DriverHandle\r
+  )\r
+{\r
+  UINTN                     NameLength;\r
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;\r
+  UINTN                     DevicePathSize;\r
+  CHAR16                    *String;\r
+  CHAR16                    *ReturnString;\r
+  UINTN                     Index;\r
+  UINT8                     *Buffer;\r
+\r
+  //\r
+  // Compute the length of Name in Unicode characters.  \r
+  // If Name is NULL, then the length is 0.\r
+  //\r
+  NameLength = 0;\r
+  if (Name != NULL) {\r
+    NameLength = StrLen (Name);\r
+  }\r
+\r
+  DevicePath = NULL;\r
+  DevicePathSize = 0;\r
+  //\r
+  // Retrieve DevicePath Protocol associated with DriverHandle\r
+  //\r
+  if (DriverHandle != NULL) {\r
+    DevicePath = DevicePathFromHandle (DriverHandle);\r
+    if (DevicePath == NULL) {\r
+      return NULL;\r
+    }\r
+    //\r
+    // Compute the size of the device path in bytes\r
+    //\r
+    DevicePathSize = GetDevicePathSize (DevicePath);\r
+  }\r
+\r
+  //\r
+  // GUID=<HexCh>32&NAME=<Char>NameLength&PATH=<HexChar>DevicePathSize <Null>\r
+  // | 5 | sizeof (EFI_GUID) * 2 | 6 | NameStrLen*4 | 6 | DevicePathSize * 2 | 1 |\r
+  //\r
+  String = AllocateZeroPool ((5 + sizeof (EFI_GUID) * 2 + 6 + NameLength * 4 + 6 + DevicePathSize * 2 + 1) * sizeof (CHAR16));\r
+  if (String == NULL) {\r
+    return NULL;\r
+  }\r
+\r
+  //\r
+  // Start with L"GUID="\r
+  //\r
+  ReturnString = StrCpy (String, L"GUID=");\r
+  String += StrLen (String);\r
+\r
+  if (Guid != NULL) {\r
+    //\r
+    // Append Guid converted to <HexCh>32\r
+    //\r
+    for (Index = 0, Buffer = (UINT8 *)Guid; Index < sizeof (EFI_GUID); Index++) {\r
+      String += UnicodeValueToString (String, PREFIX_ZERO | RADIX_HEX, *(Buffer++), 2);\r
+    }\r
+  }\r
+  \r
+  //\r
+  // Append L"&NAME="\r
+  //\r
+  StrCpy (String, L"&NAME=");\r
+  String += StrLen (String);\r
+\r
+  if (Name != NULL) {\r
+    //\r
+    // Append Name converted to <Char>NameLength\r
+    //\r
+    for (; *Name != L'\0'; Name++) {\r
+      String += UnicodeValueToString (String, PREFIX_ZERO | RADIX_HEX, *Name, 4);\r
+    }\r
+  }\r
+\r
+  //\r
+  // Append L"&PATH="\r
+  //\r
+  StrCpy (String, L"&PATH=");\r
+  String += StrLen (String);\r
+\r
+  //\r
+  // Append the device path associated with DriverHandle converted to <HexChar>DevicePathSize\r
+  //\r
+  for (Index = 0, Buffer = (UINT8 *)DevicePath; Index < DevicePathSize; Index++) {\r
+    String += UnicodeValueToString (String, PREFIX_ZERO | RADIX_HEX, *(Buffer++), 2);\r
+  }\r
+\r
+  //\r
+  // Null terminate the Unicode string\r
+  //\r
+  *String = L'\0';\r
+\r
+  //\r
+  // Convert all hex digits in range [A-F] in the configuration header to [a-f]\r
+  //\r
+  return InternalHiiLowerConfigString (ReturnString);\r
+}\r
+\r
+/**\r
+  Convert the hex UNICODE encoding string of UEFI GUID, NAME or device path \r
+  to binary buffer from <ConfigHdr>.\r
+\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_STATUS\r
+InternalHiiGetBufferFromString (\r
+  IN  EFI_STRING                 String,\r
+  IN  UINT8                      Flag,\r
+  OUT UINT8                      **Buffer\r
+  )\r
+{\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
+  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
+  // 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
-    ResultsData = SetResultsData;\r
-  } else {\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
-    // Retrieve the length of the buffer required ResultsData from the Browser Callback\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
-    Status = mUefiFormBrowser2->BrowserCallback (\r
-                              mUefiFormBrowser2,\r
-                              &ResultsDataSize,\r
-                              &TempResultsData,\r
-                              TRUE,\r
-                              VariableGuid,\r
-                              VariableName\r
-                              );\r
-    if (Status != EFI_BUFFER_TOO_SMALL) {\r
-      return NULL;\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
-    // Allocate the ResultsData buffer\r
+    // Free the allocated pacakge buffer and the got ConfigResp string.\r
     //\r
-    ResultsData = AllocateZeroPool (ResultsDataSize);\r
-    if (ResultsData == NULL) {\r
-      return NULL;\r
+    if (HiiPackageList != NULL) {\r
+      FreePool (HiiPackageList);\r
+      HiiPackageList = NULL;\r
     }\r
-  }\r
-\r
-  //\r
-  // Retrieve or set the ResultsData from the Browser Callback\r
-  //\r
-  Status = mUefiFormBrowser2->BrowserCallback (\r
-                            mUefiFormBrowser2,\r
-                            &ResultsDataSize,\r
-                            ResultsData,\r
-                            (BOOLEAN)(SetResultsData == NULL),\r
-                            VariableGuid,\r
-                            VariableName\r
-                            );\r
-  if (EFI_ERROR (Status)) {\r
-    return NULL;\r
-  }\r
 \r
-  return ResultsData;\r
-}\r
+    FreePool (ConfigResp);\r
+    ConfigResp = NULL;\r
 \r
-/**\r
-  Allocates and returns a Null-terminated Unicode <ConfigHdr> string using routing \r
-  information that includes a GUID, an optional Unicode string name, and a device\r
-  path.  The string returned is allocated with AllocatePool().  The caller is \r
-  responsible for freeing the allocated string with FreePool().\r
+NextConfigAltResp:\r
+    //\r
+    // Free the allocated buffer.\r
+    //\r
+    FreePool (VarGuid);\r
+    VarGuid = NULL;\r
   \r
-  The format of a <ConfigHdr> is as follows:\r
-\r
-    GUID=<HexCh>32&NAME=<Char>NameLength&PATH=<HexChar>DevicePathSize<Null>\r
-\r
-  @param[in]  Guid          Pointer to an EFI_GUID that is the routing information\r
-                            GUID.  Each of the 16 bytes in Guid is converted to \r
-                            a 2 Unicode character hexidecimal string.  This is \r
-                            an optional parameter that may be NULL.\r
-  @param[in]  Name          Pointer to a Null-terminated Unicode string that is \r
-                            the routing information NAME.  This is an optional \r
-                            parameter that may be NULL.  Each 16-bit Unicode \r
-                            character in Name is converted to a 4 character Unicode \r
-                            hexidecimal string.                        \r
-  @param[in]  DriverHandle  The driver handle which supports a Device Path Protocol\r
-                            that is the routing information PATH.  Each byte of\r
-                            the Device Path associated with DriverHandle is converted\r
-                            to a 2 Unicode character hexidecimal string.\r
-\r
-  @retval NULL   DriverHandle does not support the Device Path Protocol.\r
-  @retval Other  A pointer to the Null-terminate Unicode <ConfigHdr> string\r
-\r
-**/\r
-EFI_STRING\r
-EFIAPI\r
-HiiConstructConfigHdr (\r
-  IN CONST EFI_GUID  *Guid,  OPTIONAL\r
-  IN CONST CHAR16    *Name,  OPTIONAL\r
-  IN EFI_HANDLE      DriverHandle\r
-  )\r
-{\r
-  UINTN                     NameLength;\r
-  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;\r
-  UINTN                     DevicePathSize;\r
-  CHAR16                    *String;\r
-  CHAR16                    *ReturnString;\r
-  UINTN                     Index;\r
-  UINT8                     *Buffer;\r
+    FreePool (VarName);\r
+    VarName = NULL;\r
+  \r
+    FreePool (DevicePath);\r
+    DevicePath = NULL;\r
 \r
-  //\r
-  // Compute the length of Name in Unicode characters.  \r
-  // If Name is NULL, then the length is 0.\r
-  //\r
-  NameLength = 0;\r
-  if (Name != NULL) {\r
-    NameLength = StrLen (Name);\r
-  }\r
+    //\r
+    // 5. Jump to next ConfigAltResp for another Guid, Name, Path.\r
+    //\r
 \r
-  DevicePath = NULL;\r
-  DevicePathSize = 0;\r
-  //\r
-  // Retrieve DevicePath Protocol associated with DriverHandle\r
-  //\r
-  if (DriverHandle != NULL) {\r
-    DevicePath = DevicePathFromHandle (DriverHandle);\r
-    if (DevicePath == NULL) {\r
-      return NULL;\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
-    // Compute the size of the device path in bytes\r
+    // Construct ConfigAltHdr string  "&<ConfigHdr>&ALTCFG=\0" \r
+    //                               | 1 | StrLen (ConfigHdr) | 8 | 1 |\r
     //\r
-    DevicePathSize = GetDevicePathSize (DevicePath);\r
-  }\r
-\r
-  //\r
-  // GUID=<HexCh>32&NAME=<Char>NameLength&PATH=<HexChar>DevicePathSize <Null>\r
-  // | 5 | sizeof (EFI_GUID) * 2 | 6 | NameStrLen*4 | 6 | DevicePathSize * 2 | 1 |\r
-  //\r
-  String = AllocateZeroPool ((5 + sizeof (EFI_GUID) * 2 + 6 + NameLength * 4 + 6 + DevicePathSize * 2 + 1) * sizeof (CHAR16));\r
-  if (String == NULL) {\r
-    return NULL;\r
-  }\r
-\r
-  //\r
-  // Start with L"GUID="\r
-  //\r
-  ReturnString = StrCpy (String, L"GUID=");\r
-  String += StrLen (String);\r
-\r
-  if (Guid != NULL) {\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
-    // Append Guid converted to <HexCh>32\r
+    // Skip all AltResp (AltConfigHdr ConfigBody) for the same ConfigHdr\r
     //\r
-    for (Index = 0, Buffer = (UINT8 *)Guid; Index < sizeof (EFI_GUID); Index++) {\r
-      String += UnicodeValueToString (String, PREFIX_ZERO | RADIX_HEX, *(Buffer++), 2);\r
+    while ((StringHdr = StrStr (StringPtr, ConfigAltHdr)) != NULL) {\r
+      StringPtr = StringHdr + StrLen (ConfigAltHdr);\r
+      if (*StringPtr == L'\0') {\r
+        break;\r
+      }\r
     }\r
-  }\r
-  \r
-  //\r
-  // Append L"&NAME="\r
-  //\r
-  StrCpy (String, L"&NAME=");\r
-  String += StrLen (String);\r
-\r
-  if (Name != NULL) {\r
+    \r
     //\r
-    // Append Name converted to <Char>NameLength\r
+    // Free the allocated ConfigAltHdr string\r
     //\r
-    for (; *Name != L'\0'; Name++) {\r
-      String += UnicodeValueToString (String, PREFIX_ZERO | RADIX_HEX, *Name, 4);\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
-  //\r
-  // Append L"&PATH="\r
-  //\r
-  StrCpy (String, L"&PATH=");\r
-  String += StrLen (String);\r
+  if (VarName != NULL) {\r
+    FreePool (VarName);\r
+  }\r
 \r
-  //\r
-  // Append the device path associated with DriverHandle converted to <HexChar>DevicePathSize\r
-  //\r
-  for (Index = 0, Buffer = (UINT8 *)DevicePath; Index < DevicePathSize; Index++) {\r
-    String += UnicodeValueToString (String, PREFIX_ZERO | RADIX_HEX, *(Buffer++), 2);\r
+  if (DevicePath != NULL) {\r
+    FreePool (DevicePath);\r
   }\r
 \r
-  //\r
-  // Null terminate the Unicode string\r
-  //\r
-  *String = L'\0';\r
+  if (ConfigResp != NULL) {\r
+    FreePool (ConfigResp);\r
+  }\r
 \r
-  //\r
-  // Convert all hex digits in range [A-F] in the configuration header to [a-f]\r
-  //\r
-  return InternalHiiLowerConfigString (ReturnString);\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
@@ -1193,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
@@ -1247,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
@@ -1463,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]  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
@@ -1510,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
@@ -1787,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
@@ -1826,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
@@ -2499,8 +3504,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
@@ -2538,7 +3542,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
@@ -2571,20 +3575,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
-        AddOpCode      = (EFI_IFR_OP_HEADER *) (OpCodeBufferStart->Buffer + UpdateIfrOpHdr->Length);\r
-        AddSize        = UpdateIfrOpHdr->Length;\r
-        while (AddSize < OpCodeBufferStart->Position) {\r
-          CopyMem (BufferPos, AddOpCode, AddOpCode->Length);\r
-          BufferPos           += AddOpCode->Length;\r
-          UpdatePackageLength += AddOpCode->Length;\r
-\r
-          AddOpCode = (EFI_IFR_OP_HEADER *) ((UINT8 *) (AddOpCode) + AddOpCode->Length);\r
-          AddSize += AddOpCode->Length;          \r
-        }\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
@@ -2594,10 +3592,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
@@ -2617,7 +3624,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
@@ -2916,3 +3923,4 @@ HiiIfrLibExtractDefault(
 \r
   return EFI_SUCCESS;\r
 }\r
+\r