]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Library/UefiHiiLib/HiiLib.c
MdeModulePkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / MdeModulePkg / Library / UefiHiiLib / HiiLib.c
index 83e33d2a6ee67b7501df037fe0a83ab93dba2a27..564169bc144b71811be1feb48255ced87b59615c 100644 (file)
 /** @file\r
   HII Library implementation that uses DXE protocols and services.\r
 \r
-  Copyright (c) 2006 - 2008, Intel Corporation<BR>\r
-  All rights reserved. This program and the accompanying materials\r
-  are licensed and made available under the terms and conditions of the BSD License\r
-  which accompanies this distribution.  The full text of the license may be found at\r
-  http://opensource.org/licenses/bsd-license.php\r
+  Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
+  SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
-  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+**/\r
+\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
+typedef struct {\r
+  EFI_VARSTORE_ID     VarStoreId;\r
+  UINT16              Size;\r
+} IFR_VARSTORAGE_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
+// Template used to mark the end of a list of packages\r
+//\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
+  Extract Hii package list GUID for given HII handle.\r
+\r
+  If HiiHandle could not be found in the HII database, then ASSERT.\r
+  If Guid is NULL, then ASSERT.\r
+\r
+  @param  Handle              Hii handle\r
+  @param  Guid                Package list GUID\r
+\r
+  @retval EFI_SUCCESS         Successfully extract GUID from Hii database.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+InternalHiiExtractGuidFromHiiHandle (\r
+  IN      EFI_HII_HANDLE      Handle,\r
+  OUT     EFI_GUID            *Guid\r
+  )\r
+{\r
+  EFI_STATUS                   Status;\r
+  UINTN                        BufferSize;\r
+  EFI_HII_PACKAGE_LIST_HEADER  *HiiPackageList;\r
+\r
+  ASSERT (Guid != NULL);\r
+  ASSERT (Handle != NULL);\r
+\r
+  //\r
+  // Get HII PackageList\r
+  //\r
+  BufferSize = 0;\r
+  HiiPackageList = NULL;\r
+\r
+  Status = gHiiDatabase->ExportPackageLists (gHiiDatabase, Handle, &BufferSize, HiiPackageList);\r
+  ASSERT (Status != EFI_NOT_FOUND);\r
+\r
+  if (Status == EFI_BUFFER_TOO_SMALL) {\r
+    HiiPackageList = AllocatePool (BufferSize);\r
+    ASSERT (HiiPackageList != NULL);\r
+\r
+    Status = gHiiDatabase->ExportPackageLists (gHiiDatabase, Handle, &BufferSize, HiiPackageList);\r
+  }\r
+  if (EFI_ERROR (Status)) {\r
+    FreePool (HiiPackageList);\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Extract GUID\r
+  //\r
+  CopyGuid (Guid, &HiiPackageList->PackageListGuid);\r
+\r
+  FreePool (HiiPackageList);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Registers a list of packages in the HII Database and returns the HII Handle\r
+  associated with that registration.  If an HII Handle has already been registered\r
+  with the same PackageListGuid and DeviceHandle, then NULL is returned.  If there\r
+  are not enough resources to perform the registration, then NULL is returned.\r
+  If an empty list of packages is passed in, then NULL is returned.  If the size of\r
+  the list of package is 0, then NULL is returned.\r
+\r
+  The variable arguments are pointers which point to package header that defined\r
+  by UEFI VFR compiler and StringGather 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
+\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 and DeviceHandle.\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_HANDLE\r
+EFIAPI\r
+HiiAddPackages (\r
+  IN CONST EFI_GUID    *PackageListGuid,\r
+  IN       EFI_HANDLE  DeviceHandle  OPTIONAL,\r
+  ...\r
+  )\r
+{\r
+  EFI_STATUS                   Status;\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
+  ASSERT (PackageListGuid != NULL);\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
+  // 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
+  //\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
+  //\r
+  // Allocate the storage for the entire Package List\r
+  //\r
+  PackageListHeader = AllocateZeroPool (Length);\r
+\r
+  //\r
+  // If the Package List can not be allocated, then return a NULL HII Handle\r
+  //\r
+  if (PackageListHeader == NULL) {\r
+    return NULL;\r
+  }\r
+\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
+  // Initialize a pointer to the beginning if the Package List data\r
+  //\r
+  Data = (UINT8 *)(PackageListHeader + 1);\r
+\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
+  //\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
+  //\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
+\r
+  //\r
+  // Return the new HII Handle\r
+  //\r
+  return HiiHandle;\r
+}\r
+\r
+/**\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 HII database, then ASSERT.\r
+\r
+  @param[in]  HiiHandle   The handle that was previously registered in the HII database\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+HiiRemovePackages (\r
+  IN      EFI_HII_HANDLE      HiiHandle\r
+  )\r
+{\r
+  EFI_STATUS Status;\r
+\r
+  ASSERT (HiiHandle != NULL);\r
+  Status = gHiiDatabase->RemovePackageList (gHiiDatabase, HiiHandle);\r
+  ASSERT_EFI_ERROR (Status);\r
+}\r
+\r
+\r
+/**\r
+  Retrieves the array of all the HII Handles or the HII handles of a specific\r
+  package list GUID in the HII Database.\r
+  This array is terminated with a NULL HII Handle.\r
+  This function allocates the returned array using AllocatePool().\r
+  The caller is responsible for freeing the array with FreePool().\r
+\r
+  @param[in]  PackageListGuid  An optional parameter that is used to request\r
+                               HII Handles associated with a specific\r
+                               Package List GUID.  If this parameter is NULL,\r
+                               then all the HII Handles in the HII Database\r
+                               are returned.  If this parameter is not NULL,\r
+                               then zero or more HII Handles associated with\r
+                               PackageListGuid are returned.\r
+\r
+  @retval NULL   No HII handles were found in the HII database\r
+  @retval NULL   The array of HII Handles could not be retrieved\r
+  @retval Other  A pointer to the NULL terminated array of HII Handles\r
+\r
+**/\r
+EFI_HII_HANDLE *\r
+EFIAPI\r
+HiiGetHiiHandles (\r
+  IN CONST EFI_GUID  *PackageListGuid  OPTIONAL\r
+  )\r
+{\r
+  EFI_STATUS      Status;\r
+  UINTN           HandleBufferLength;\r
+  EFI_HII_HANDLE  TempHiiHandleBuffer;\r
+  EFI_HII_HANDLE  *HiiHandleBuffer;\r
+  EFI_GUID        Guid;\r
+  UINTN           Index1;\r
+  UINTN           Index2;\r
+\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
+  //\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
+  // 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
+  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 (PackageListGuid == NULL) {\r
+    //\r
+    // Return the NULL terminated array of HII handles in the HII Database\r
+    //\r
+    return HiiHandleBuffer;\r
+  } else {\r
+    for (Index1 = 0, Index2 = 0; HiiHandleBuffer[Index1] != NULL; Index1++) {\r
+      Status = InternalHiiExtractGuidFromHiiHandle (HiiHandleBuffer[Index1], &Guid);\r
+      ASSERT_EFI_ERROR (Status);\r
+      if (CompareGuid (&Guid, PackageListGuid)) {\r
+        HiiHandleBuffer[Index2++] = HiiHandleBuffer[Index1];\r
+      }\r
+    }\r
+    if (Index2 > 0) {\r
+      HiiHandleBuffer[Index2] = NULL;\r
+      return HiiHandleBuffer;\r
+    } else {\r
+      FreePool (HiiHandleBuffer);\r
+      return NULL;\r
+    }\r
+  }\r
+}\r
+\r
+/**\r
+  This function allows a caller to extract the form set opcode form the Hii Handle.\r
+  The returned buffer is allocated using AllocatePool().The caller is responsible\r
+  for freeing the allocated buffer using FreePool().\r
+\r
+  @param Handle            The HII handle.\r
+  @param Buffer            On return, points to a pointer which point to the buffer that contain the formset opcode.\r
+  @param BufferSize        On return, points to the length of the buffer.\r
+\r
+  @retval EFI_OUT_OF_RESOURCES   No enough memory resource is allocated.\r
+  @retval EFI_NOT_FOUND          Can't find the package data for the input Handle.\r
+  @retval EFI_INVALID_PARAMETER  The input parameters are not correct.\r
+  @retval EFI_SUCCESS            Get the formset opcode from the hii handle successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HiiGetFormSetFromHiiHandle(\r
+  IN  EFI_HII_HANDLE     Handle,\r
+  OUT EFI_IFR_FORM_SET   **Buffer,\r
+  OUT UINTN              *BufferSize\r
+  )\r
+{\r
+  EFI_STATUS                   Status;\r
+  UINTN                        PackageListSize;\r
+  UINTN                        TempSize;\r
+  EFI_HII_PACKAGE_LIST_HEADER  *HiiPackageList;\r
+  UINT8                        *Package;\r
+  UINT8                        *OpCodeData;\r
+  UINT8                        *FormSetBuffer;\r
+  UINT8                        *TempBuffer;\r
+  UINT32                       Offset;\r
+  UINT32                       Offset2;\r
+  UINT32                       PackageListLength;\r
+  EFI_HII_PACKAGE_HEADER       PackageHeader;\r
+\r
+  TempSize = 0;\r
+  FormSetBuffer = NULL;\r
+  TempBuffer    = NULL;\r
+\r
+  //\r
+  // Get HII PackageList\r
+  //\r
+  PackageListSize = 0;\r
+  HiiPackageList = NULL;\r
+  Status = gHiiDatabase->ExportPackageLists (gHiiDatabase, Handle, &PackageListSize, HiiPackageList);\r
+  if (EFI_ERROR (Status) && (Status != EFI_BUFFER_TOO_SMALL)) {\r
+    return Status;\r
+  }\r
+\r
+  HiiPackageList = AllocatePool (PackageListSize);\r
+  if (HiiPackageList == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  Status = gHiiDatabase->ExportPackageLists (gHiiDatabase, Handle, &PackageListSize, HiiPackageList);\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  //\r
+  // Get Form package from this HII package List\r
+  //\r
+  Status = EFI_NOT_FOUND;\r
+  Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);\r
+  PackageListLength = ReadUnaligned32 (&HiiPackageList->PackageLength);\r
+\r
+  while (Offset < PackageListLength) {\r
+    Package = ((UINT8 *) HiiPackageList) + Offset;\r
+    CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));\r
+    Offset += PackageHeader.Length;\r
+\r
+    if (PackageHeader.Type != EFI_HII_PACKAGE_FORMS) {\r
+      continue;\r
+    }\r
+\r
+    //\r
+    // Search FormSet Opcode in this Form Package\r
+    //\r
+    Offset2 = sizeof (EFI_HII_PACKAGE_HEADER);\r
+    while (Offset2 < PackageHeader.Length) {\r
+      OpCodeData = Package + Offset2;\r
+      Offset2 += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;\r
+\r
+      if (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode != EFI_IFR_FORM_SET_OP) {\r
+        continue;\r
+      }\r
+\r
+      if (FormSetBuffer != NULL){\r
+        TempBuffer = ReallocatePool (\r
+                       TempSize,\r
+                       TempSize + ((EFI_IFR_OP_HEADER *) OpCodeData)->Length,\r
+                       FormSetBuffer\r
+                       );\r
+        if (TempBuffer == NULL) {\r
+          Status = EFI_OUT_OF_RESOURCES;\r
+          goto Done;\r
+        }\r
+        CopyMem (TempBuffer + TempSize,  OpCodeData, ((EFI_IFR_OP_HEADER *) OpCodeData)->Length);\r
+        FormSetBuffer = NULL;\r
+      } else {\r
+        TempBuffer = AllocatePool (TempSize + ((EFI_IFR_OP_HEADER *) OpCodeData)->Length);\r
+        if (TempBuffer == NULL) {\r
+          Status = EFI_OUT_OF_RESOURCES;\r
+          goto Done;\r
+        }\r
+        CopyMem (TempBuffer, OpCodeData, ((EFI_IFR_OP_HEADER *) OpCodeData)->Length);\r
+      }\r
+      TempSize += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;\r
+      FormSetBuffer = TempBuffer;\r
+\r
+      Status = EFI_SUCCESS;\r
+      //\r
+      //One form package has one formset, exit current form package to search other form package in the packagelist.\r
+      //\r
+      break;\r
+    }\r
+  }\r
+Done:\r
+  FreePool (HiiPackageList);\r
+\r
+  *BufferSize = TempSize;\r
+  *Buffer = (EFI_IFR_FORM_SET *)FormSetBuffer;\r
+\r
+  return Status;\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 ConfigString is NULL, then ASSERT().\r
+\r
+  @param[in] ConfigString  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
+  //\r
+  Status = gHiiConfigRouting->BlockToConfig (\r
+                                gHiiConfigRouting,\r
+                                ConfigRequest,\r
+                                Block,\r
+                                BlockSize,\r
+                                &ConfigResp,\r
+                                &Progress\r
+                                );\r
+  if (EFI_ERROR (Status)) {\r
+    return NULL;\r
+  }\r
+  return ConfigResp;\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
+  allocated using AllocatePool().  The caller is then responsible for freeing\r
+  the buffer using FreePool().\r
+\r
+  @param[in]  VariableGuid    Pointer to an EFI_GUID structure.  This is an optional\r
+                              parameter that may be NULL.\r
+  @param[in]  VariableName    Pointer to a Null-terminated Unicode string.  This\r
+                              is an optional parameter that may be NULL.\r
+  @param[in]  SetResultsData  If not NULL, then this parameter specified the buffer\r
+                              of uncommited data to set.  If this parameter is NULL,\r
+                              then the caller is requesting to get the uncommited data\r
+                              from the Form Browser.\r
+\r
+  @retval NULL   The uncommitted data could not be retrieved.\r
+  @retval Other  A pointer to a buffer containing the uncommitted data.\r
+\r
+**/\r
+EFI_STRING\r
+EFIAPI\r
+InternalHiiBrowserCallback (\r
+  IN CONST EFI_GUID    *VariableGuid,  OPTIONAL\r
+  IN CONST CHAR16      *VariableName,  OPTIONAL\r
+  IN CONST EFI_STRING  SetResultsData  OPTIONAL\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+  UINTN       ResultsDataSize;\r
+  EFI_STRING  ResultsData;\r
+  CHAR16      TempResultsData;\r
+\r
+  //\r
+  // Locate protocols\r
+  //\r
+  if (mUefiFormBrowser2 == NULL) {\r
+    Status = gBS->LocateProtocol (&gEfiFormBrowser2ProtocolGuid, NULL, (VOID **) &mUefiFormBrowser2);\r
+    if (EFI_ERROR (Status) || mUefiFormBrowser2 == NULL) {\r
+      return NULL;\r
+    }\r
+  }\r
+\r
+  ResultsDataSize = 0;\r
+\r
+  if (SetResultsData != NULL) {\r
+    //\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 hexadecimal 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
+                            hexadecimal 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 hexadecimal 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
+  UINTN                     MaxLen;\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
+  MaxLen = 5 + sizeof (EFI_GUID) * 2 + 6 + NameLength * 4 + 6 + DevicePathSize * 2 + 1;\r
+  String = AllocateZeroPool (MaxLen * sizeof (CHAR16));\r
+  if (String == NULL) {\r
+    return NULL;\r
+  }\r
+\r
+  //\r
+  // Start with L"GUID="\r
+  //\r
+  StrCpyS (String, MaxLen, L"GUID=");\r
+  ReturnString = String;\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
+      UnicodeValueToStringS (\r
+        String,\r
+        MaxLen * sizeof (CHAR16) - ((UINTN)String - (UINTN)ReturnString),\r
+        PREFIX_ZERO | RADIX_HEX,\r
+        *(Buffer++),\r
+        2\r
+        );\r
+      String += StrnLenS (String, MaxLen - ((UINTN)String - (UINTN)ReturnString) / sizeof (CHAR16));\r
+    }\r
+  }\r
+\r
+  //\r
+  // Append L"&NAME="\r
+  //\r
+  StrCatS (ReturnString, MaxLen, 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
+      UnicodeValueToStringS (\r
+        String,\r
+        sizeof (CHAR16) * MaxLen - ((UINTN)String - (UINTN)ReturnString),\r
+        PREFIX_ZERO | RADIX_HEX,\r
+        *Name,\r
+        4\r
+        );\r
+      String += StrnLenS (String, MaxLen - ((UINTN)String - (UINTN)ReturnString) / sizeof (CHAR16));\r
+    }\r
+  }\r
+\r
+  //\r
+  // Append L"&PATH="\r
+  //\r
+  StrCatS (ReturnString, MaxLen, 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
+    UnicodeValueToStringS (\r
+      String,\r
+      sizeof (CHAR16) * MaxLen - ((UINTN)String - (UINTN)ReturnString),\r
+      PREFIX_ZERO | RADIX_HEX,\r
+      *(Buffer++),\r
+      2\r
+      );\r
+    String += StrnLenS (String, MaxLen - ((UINTN)String - (UINTN)ReturnString) / sizeof (CHAR16));\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
+      StrnCpyS (TemStr, sizeof (TemStr) / sizeof (CHAR16), 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
+  }\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
+  Get value from config request resp string.\r
+\r
+  @param ConfigElement           ConfigResp string contains the current setting.\r
+  @param VarName                 The variable name which need to get value.\r
+  @param VarValue                The return value.\r
+\r
+  @retval EFI_SUCCESS            Get the value for the VarName\r
+  @retval EFI_OUT_OF_RESOURCES   The memory is not enough.\r
+**/\r
+EFI_STATUS\r
+GetValueFromRequest (\r
+  IN CHAR16                       *ConfigElement,\r
+  IN CHAR16                       *VarName,\r
+  OUT UINT64                      *VarValue\r
+  )\r
+{\r
+  UINT8                        *TmpBuffer;\r
+  CHAR16                       *StringPtr;\r
+  UINTN                        Length;\r
+  EFI_STATUS                   Status;\r
+\r
+  //\r
+  // Find VarName related string.\r
+  //\r
+  StringPtr = StrStr (ConfigElement, VarName);\r
+  ASSERT (StringPtr != NULL);\r
+\r
+  //\r
+  // Skip the "VarName=" string\r
+  //\r
+  StringPtr += StrLen (VarName) + 1;\r
+\r
+  //\r
+  // Get Offset\r
+  //\r
+  Status = InternalHiiGetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  *VarValue = 0;\r
+  CopyMem (VarValue, TmpBuffer, (((Length + 1) / 2) < sizeof (UINT64)) ? ((Length + 1) / 2) : sizeof (UINT64));\r
+\r
+  FreePool (TmpBuffer);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  This internal function parses IFR data to validate current setting.\r
+\r
+  Base on the NameValueType, if it is TRUE, RequestElement and HiiHandle is valid;\r
+  else the VarBuffer and CurrentBlockArray is valid.\r
+\r
+  @param HiiPackageList     Point to Hii package list.\r
+  @param PackageListLength  The length of the pacakge.\r
+  @param VarGuid            Guid of the buffer storage.\r
+  @param VarName            Name of the buffer storage.\r
+  @param VarBuffer          The data buffer for the storage.\r
+  @param CurrentBlockArray  The block array from the config Requst string.\r
+  @param RequestElement     The config string for this storage.\r
+  @param HiiHandle          The HiiHandle for this formset.\r
+  @param NameValueType      Whether current storage is name/value varstore or not.\r
+\r
+  @retval EFI_SUCCESS            The current setting is valid.\r
+  @retval EFI_OUT_OF_RESOURCES   The memory is not enough.\r
+  @retval EFI_INVALID_PARAMETER  The config string or the Hii package is invalid.\r
+**/\r
+EFI_STATUS\r
+ValidateQuestionFromVfr (\r
+  IN EFI_HII_PACKAGE_LIST_HEADER   *HiiPackageList,\r
+  IN UINTN                         PackageListLength,\r
+  IN EFI_GUID                      *VarGuid,\r
+  IN CHAR16                        *VarName,\r
+  IN UINT8                         *VarBuffer,\r
+  IN IFR_BLOCK_DATA                *CurrentBlockArray,\r
+  IN CHAR16                        *RequestElement,\r
+  IN EFI_HII_HANDLE                HiiHandle,\r
+  IN BOOLEAN                       NameValueType\r
+  )\r
+{\r
+  IFR_BLOCK_DATA               VarBlockData;\r
+  UINT16                       Offset;\r
+  UINT16                       Width;\r
+  UINT64                       VarValue;\r
+  EFI_IFR_TYPE_VALUE           TmpValue;\r
+  EFI_STATUS                   Status;\r
+  EFI_HII_PACKAGE_HEADER       PackageHeader;\r
+  UINT32                       PackageOffset;\r
+  UINT8                        *PackageData;\r
+  UINTN                        IfrOffset;\r
+  EFI_IFR_OP_HEADER            *IfrOpHdr;\r
+  EFI_IFR_VARSTORE             *IfrVarStore;\r
+  EFI_IFR_VARSTORE_NAME_VALUE  *IfrNameValueStore;\r
+  EFI_IFR_VARSTORE_EFI         *IfrEfiVarStore;\r
+  IFR_VARSTORAGE_DATA          VarStoreData;\r
+  EFI_IFR_ONE_OF               *IfrOneOf;\r
+  EFI_IFR_NUMERIC              *IfrNumeric;\r
+  EFI_IFR_ONE_OF_OPTION        *IfrOneOfOption;\r
+  EFI_IFR_CHECKBOX             *IfrCheckBox;\r
+  EFI_IFR_STRING               *IfrString;\r
+  CHAR8                        *VarStoreName;\r
+  UINTN                        Index;\r
+  CHAR16                       *QuestionName;\r
+  CHAR16                       *StringPtr;\r
+  UINT16                       BitOffset;\r
+  UINT16                       BitWidth;\r
+  UINT16                       TotalBits;\r
+  UINTN                        StartBit;\r
+  UINTN                        EndBit;\r
+  BOOLEAN                      QuestionReferBitField;\r
+  UINT32                       BufferValue;\r
+\r
+  //\r
+  // Initialize the local variables.\r
+  //\r
+  Index             = 0;\r
+  VarStoreName      = NULL;\r
+  Status            = EFI_SUCCESS;\r
+  VarValue          = 0;\r
+  IfrVarStore       = NULL;\r
+  IfrNameValueStore = NULL;\r
+  IfrEfiVarStore    = NULL;\r
+  ZeroMem (&VarStoreData, sizeof (IFR_VARSTORAGE_DATA));\r
+  ZeroMem (&VarBlockData, sizeof (VarBlockData));\r
+  BitOffset = 0;\r
+  BitWidth = 0;\r
+  QuestionReferBitField = FALSE;\r
+\r
+  //\r
+  // Check IFR value is in block data, then Validate Value\r
+  //\r
+  PackageOffset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);\r
+  while (PackageOffset < PackageListLength) {\r
+    CopyMem (&PackageHeader, (UINT8 *) HiiPackageList + PackageOffset, sizeof (PackageHeader));\r
+\r
+    //\r
+    // Parse IFR opcode from the form package.\r
+    //\r
+    if (PackageHeader.Type == EFI_HII_PACKAGE_FORMS) {\r
+      IfrOffset   = sizeof (PackageHeader);\r
+      PackageData = (UINT8 *) HiiPackageList + PackageOffset;\r
+      while (IfrOffset < PackageHeader.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 (VarStoreData.VarStoreId != 0) {\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
+\r
+          if (IfrVarStore != NULL) {\r
+            VarStoreData.VarStoreId = IfrVarStore->VarStoreId;\r
+            VarStoreData.Size       = IfrVarStore->Size;\r
+          }\r
+          break;\r
+        case EFI_IFR_VARSTORE_NAME_VALUE_OP:\r
+          //\r
+          // VarStoreId has been found. No further found.\r
+          //\r
+          if (VarStoreData.VarStoreId != 0) {\r
+            break;\r
+          }\r
+          //\r
+          // Find the matched VarStoreId to the input VarGuid\r
+          //\r
+          IfrNameValueStore = (EFI_IFR_VARSTORE_NAME_VALUE *) IfrOpHdr;\r
+          if (!CompareGuid ((EFI_GUID *) (VOID *) &IfrNameValueStore->Guid, VarGuid)) {\r
+            IfrNameValueStore = NULL;\r
+          }\r
+\r
+          if (IfrNameValueStore != NULL) {\r
+            VarStoreData.VarStoreId = IfrNameValueStore->VarStoreId;\r
+          }\r
+          break;\r
+        case EFI_IFR_VARSTORE_EFI_OP:\r
+          //\r
+          // VarStore is found. Don't need to search any more.\r
+          //\r
+          if (VarStoreData.VarStoreId != 0) {\r
+            break;\r
+          }\r
+\r
+          IfrEfiVarStore = (EFI_IFR_VARSTORE_EFI *) IfrOpHdr;\r
+\r
+          //\r
+          // If the length is small than the structure, this is from old efi\r
+          // varstore definition. Old efi varstore get config directly from\r
+          // GetVariable function.\r
+          //\r
+          if (IfrOpHdr->Length < sizeof (EFI_IFR_VARSTORE_EFI)) {\r
+            break;\r
+          }\r
+\r
+          if (CompareGuid ((EFI_GUID *) (VOID *) &IfrEfiVarStore->Guid, VarGuid)) {\r
+            VarStoreName = (CHAR8 *) IfrEfiVarStore->Name;\r
+            for (Index = 0; VarStoreName[Index] != 0; Index ++) {\r
+              if ((CHAR16) VarStoreName[Index] != VarName[Index]) {\r
+                break;\r
+              }\r
+            }\r
+            //\r
+            // The matched VarStore is found.\r
+            //\r
+            if ((VarStoreName[Index] != 0) || (VarName[Index] != 0)) {\r
+              IfrEfiVarStore = NULL;\r
+            }\r
+          } else {\r
+            IfrEfiVarStore = NULL;\r
+          }\r
+\r
+          if (IfrEfiVarStore != NULL) {\r
+            //\r
+            // Find the matched VarStore\r
+            //\r
+            VarStoreData.VarStoreId = IfrEfiVarStore->VarStoreId;\r
+            VarStoreData.Size       = IfrEfiVarStore->Size;\r
+          }\r
+          break;\r
+        case EFI_IFR_FORM_OP:\r
+        case EFI_IFR_FORM_MAP_OP:\r
+          //\r
+          // Check the matched VarStoreId is found.\r
+          //\r
+          if (VarStoreData.VarStoreId == 0) {\r
+            return EFI_SUCCESS;\r
+          }\r
+          break;\r
+        case EFI_IFR_ONE_OF_OP:\r
+          //\r
+          // Check whether current value is the one of option.\r
+          //\r
+\r
+          //\r
+          // OneOf question is not in IFR Form. This IFR form is not valid.\r
+          //\r
+          if (VarStoreData.VarStoreId == 0) {\r
+            return EFI_INVALID_PARAMETER;\r
+          }\r
+          //\r
+          // Check whether this question is for the requested varstore.\r
+          //\r
+          IfrOneOf = (EFI_IFR_ONE_OF *) IfrOpHdr;\r
+          if (IfrOneOf->Question.VarStoreId != VarStoreData.VarStoreId) {\r
+            break;\r
+          }\r
+\r
+          if (NameValueType) {\r
+            QuestionName = HiiGetString (HiiHandle, IfrOneOf->Question.VarStoreInfo.VarName, NULL);\r
+            ASSERT (QuestionName != NULL);\r
+\r
+            if (StrStr (RequestElement, QuestionName) == NULL) {\r
+              //\r
+              // This question is not in the current configuration string. Skip it.\r
+              //\r
+              break;\r
+            }\r
+\r
+            Status = GetValueFromRequest (RequestElement, QuestionName, &VarValue);\r
+            if (EFI_ERROR (Status)) {\r
+              return Status;\r
+            }\r
+          } else {\r
+            //\r
+            // Get Offset by Question header and Width by DataType Flags\r
+            //\r
+            if (QuestionReferBitField) {\r
+              //\r
+              // Get the byte offset/width for bit field.\r
+              //\r
+              BitOffset = IfrOneOf->Question.VarStoreInfo.VarOffset;\r
+              BitWidth = IfrOneOf->Flags & EDKII_IFR_NUMERIC_SIZE_BIT;\r
+              Offset = BitOffset / 8;\r
+              TotalBits = BitOffset % 8 + BitWidth;\r
+              Width = (TotalBits % 8 == 0 ? TotalBits / 8: TotalBits / 8 + 1);\r
+            } else {\r
+              Offset = IfrOneOf->Question.VarStoreInfo.VarOffset;\r
+              Width  = (UINT16) (1 << (IfrOneOf->Flags & EFI_IFR_NUMERIC_SIZE));\r
+            }\r
+            //\r
+            // Check whether this question is in current block array.\r
+            //\r
+            if (!BlockArrayCheck (CurrentBlockArray, Offset, Width)) {\r
+              //\r
+              // This question is not in the current configuration string. Skip it.\r
+              //\r
+              break;\r
+            }\r
+            //\r
+            // Check this var question is in the var storage\r
+            //\r
+            if ((Offset + Width) > VarStoreData.Size) {\r
+              //\r
+              // This question exceeds the var store size.\r
+              //\r
+              return EFI_INVALID_PARAMETER;\r
+            }\r
+\r
+            //\r
+            // Get the current value for oneof opcode\r
+            //\r
+            VarValue = 0;\r
+            if (QuestionReferBitField) {\r
+              //\r
+              // Get the value in bit fields.\r
+              //\r
+              StartBit = BitOffset % 8;\r
+              EndBit = StartBit + BitWidth - 1;\r
+              CopyMem ((UINT8 *) &BufferValue, VarBuffer + Offset, Width);\r
+              VarValue = BitFieldRead32 (BufferValue, StartBit, EndBit);\r
+            } else {\r
+              CopyMem (&VarValue, VarBuffer +  Offset, Width);\r
+            }\r
+          }\r
+          //\r
+          // Set Block Data, to be checked in the following Oneof option opcode.\r
+          //\r
+          VarBlockData.OpCode     = IfrOpHdr->OpCode;\r
+          VarBlockData.Scope      = IfrOpHdr->Scope;\r
+          break;\r
+        case EFI_IFR_NUMERIC_OP:\r
+          //\r
+          // Check the current value is in the numeric range.\r
+          //\r
+\r
+          //\r
+          // Numeric question is not in IFR Form. This IFR form is not valid.\r
+          //\r
+          if (VarStoreData.VarStoreId == 0) {\r
+            return EFI_INVALID_PARAMETER;\r
+          }\r
+          //\r
+          // Check whether this question is for the requested varstore.\r
+          //\r
+          IfrNumeric = (EFI_IFR_NUMERIC *) IfrOpHdr;\r
+          if (IfrNumeric->Question.VarStoreId != VarStoreData.VarStoreId) {\r
+            break;\r
+          }\r
+\r
+          if (NameValueType) {\r
+            QuestionName = HiiGetString (HiiHandle, IfrNumeric->Question.VarStoreInfo.VarName, NULL);\r
+            ASSERT (QuestionName != NULL);\r
+\r
+            if (StrStr (RequestElement, QuestionName) == NULL) {\r
+              //\r
+              // This question is not in the current configuration string. Skip it.\r
+              //\r
+              break;\r
+            }\r
+\r
+            Status = GetValueFromRequest (RequestElement, QuestionName, &VarValue);\r
+            if (EFI_ERROR (Status)) {\r
+              return Status;\r
+            }\r
+          } else {\r
+            //\r
+            // Get Offset by Question header and Width by DataType Flags\r
+            //\r
+            if (QuestionReferBitField) {\r
+              //\r
+              // Get the byte offset/width for bit field.\r
+              //\r
+              BitOffset = IfrNumeric->Question.VarStoreInfo.VarOffset;\r
+              BitWidth = IfrNumeric->Flags & EDKII_IFR_NUMERIC_SIZE_BIT;\r
+              Offset = BitOffset / 8;\r
+              TotalBits = BitOffset % 8 + BitWidth;\r
+              Width  = (TotalBits % 8 == 0 ? TotalBits / 8: TotalBits / 8 + 1);\r
+            } else {\r
+              Offset = IfrNumeric->Question.VarStoreInfo.VarOffset;\r
+              Width  = (UINT16) (1 << (IfrNumeric->Flags & EFI_IFR_NUMERIC_SIZE));\r
+            }\r
+            //\r
+            // Check whether this question is in current block array.\r
+            //\r
+            if (!BlockArrayCheck (CurrentBlockArray, Offset, Width)) {\r
+              //\r
+              // This question is not in the current configuration string. Skip it.\r
+              //\r
+              break;\r
+            }\r
+            //\r
+            // Check this var question is in the var storage\r
+            //\r
+            if ((Offset + Width) > VarStoreData.Size) {\r
+              //\r
+              // This question exceeds the var store size.\r
+              //\r
+              return EFI_INVALID_PARAMETER;\r
+            }\r
+\r
+            //\r
+            // Check the current value is in the numeric range.\r
+            //\r
+            VarValue = 0;\r
+            if (QuestionReferBitField) {\r
+              //\r
+              // Get the value in the bit fields.\r
+              //\r
+              StartBit = BitOffset % 8;\r
+              EndBit = StartBit + BitWidth - 1;\r
+              CopyMem ((UINT8 *) &BufferValue, VarBuffer + Offset, Width);\r
+              VarValue = BitFieldRead32 (BufferValue, StartBit, EndBit);\r
+            } else {\r
+              CopyMem (&VarValue, VarBuffer +  Offset, Width);\r
+            }\r
+          }\r
+          if ( QuestionReferBitField) {\r
+             //\r
+             // Value in bit fields was stored as UINt32 type.\r
+             //\r
+             if ((IfrNumeric->Flags & EDKII_IFR_DISPLAY_BIT) == 0) {\r
+               if ((INT32) VarValue < (INT32) IfrNumeric->data.u32.MinValue || (INT32) VarValue > (INT32) IfrNumeric->data.u32.MaxValue) {\r
+                  //\r
+                  // Not in the valid range.\r
+                  //\r
+                  return EFI_INVALID_PARAMETER;\r
+                }\r
+             } else {\r
+               if (VarValue < IfrNumeric->data.u32.MinValue || VarValue > IfrNumeric->data.u32.MaxValue) {\r
+                  //\r
+                  // Not in the valid range.\r
+                  //\r
+                  return EFI_INVALID_PARAMETER;\r
+                }\r
+             }\r
+          } else {\r
+            if ((IfrNumeric->Flags & EFI_IFR_DISPLAY) == 0) {\r
+              switch (IfrNumeric->Flags & EFI_IFR_NUMERIC_SIZE) {\r
+              case EFI_IFR_NUMERIC_SIZE_1:\r
+                if ((INT8) VarValue < (INT8) IfrNumeric->data.u8.MinValue || (INT8) VarValue > (INT8) IfrNumeric->data.u8.MaxValue) {\r
+                  //\r
+                  // Not in the valid range.\r
+                  //\r
+                  return EFI_INVALID_PARAMETER;\r
+                }\r
+                break;\r
+              case EFI_IFR_NUMERIC_SIZE_2:\r
+                if ((INT16) VarValue < (INT16) IfrNumeric->data.u16.MinValue || (INT16) VarValue > (INT16) IfrNumeric->data.u16.MaxValue) {\r
+                  //\r
+                  // Not in the valid range.\r
+                  //\r
+                  return EFI_INVALID_PARAMETER;\r
+                }\r
+                break;\r
+              case EFI_IFR_NUMERIC_SIZE_4:\r
+                if ((INT32) VarValue < (INT32) IfrNumeric->data.u32.MinValue || (INT32) VarValue > (INT32) IfrNumeric->data.u32.MaxValue) {\r
+                  //\r
+                  // Not in the valid range.\r
+                  //\r
+                  return EFI_INVALID_PARAMETER;\r
+                }\r
+                break;\r
+              case EFI_IFR_NUMERIC_SIZE_8:\r
+                if ((INT64) VarValue < (INT64) IfrNumeric->data.u64.MinValue || (INT64) VarValue > (INT64) IfrNumeric->data.u64.MaxValue) {\r
+                  //\r
+                  // Not in the valid range.\r
+                  //\r
+                  return EFI_INVALID_PARAMETER;\r
+                }\r
+                break;\r
+              }\r
+            } else {\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
+                  return EFI_INVALID_PARAMETER;\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
+                  return EFI_INVALID_PARAMETER;\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
+                  return EFI_INVALID_PARAMETER;\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
+                  return EFI_INVALID_PARAMETER;\r
+                }\r
+                break;\r
+              }\r
+            }\r
+          }\r
+          break;\r
+        case EFI_IFR_CHECKBOX_OP:\r
+          //\r
+          // Check value is BOOLEAN type, only 0 and 1 is valid.\r
+          //\r
+\r
+          //\r
+          // CheckBox question is not in IFR Form. This IFR form is not valid.\r
+          //\r
+          if (VarStoreData.VarStoreId == 0) {\r
+            return EFI_INVALID_PARAMETER;\r
+          }\r
+\r
+          //\r
+          // Check whether this question is for the requested varstore.\r
+          //\r
+          IfrCheckBox = (EFI_IFR_CHECKBOX *) IfrOpHdr;\r
+          if (IfrCheckBox->Question.VarStoreId != VarStoreData.VarStoreId) {\r
+            break;\r
+          }\r
+\r
+          if (NameValueType) {\r
+            QuestionName = HiiGetString (HiiHandle, IfrCheckBox->Question.VarStoreInfo.VarName, NULL);\r
+            ASSERT (QuestionName != NULL);\r
+\r
+            if (StrStr (RequestElement, QuestionName) == NULL) {\r
+              //\r
+              // This question is not in the current configuration string. Skip it.\r
+              //\r
+              break;\r
+            }\r
+\r
+            Status = GetValueFromRequest (RequestElement, QuestionName, &VarValue);\r
+            if (EFI_ERROR (Status)) {\r
+              return Status;\r
+            }\r
+          } else {\r
+            //\r
+            // Get Offset by Question header\r
+            //\r
+           if (QuestionReferBitField) {\r
+              //\r
+              // Get the byte offset/width for bit field.\r
+              //\r
+              BitOffset = IfrCheckBox->Question.VarStoreInfo.VarOffset;\r
+              BitWidth = 1;\r
+              Offset = BitOffset / 8;\r
+              TotalBits = BitOffset % 8 + BitWidth;\r
+              Width = (TotalBits % 8 == 0 ? TotalBits / 8: TotalBits / 8 + 1);\r
+            } else {\r
+              Offset = IfrCheckBox->Question.VarStoreInfo.VarOffset;\r
+              Width  = (UINT16) sizeof (BOOLEAN);\r
+            }\r
+            //\r
+            // Check whether this question is in current block array.\r
+            //\r
+            if (!BlockArrayCheck (CurrentBlockArray, Offset, Width)) {\r
+              //\r
+              // This question is not in the current configuration string. Skip it.\r
+              //\r
+              break;\r
+            }\r
+            //\r
+            // Check this var question is in the var storage\r
+            //\r
+            if ((Offset + Width) > VarStoreData.Size) {\r
+              //\r
+              // This question exceeds the var store size.\r
+              //\r
+              return EFI_INVALID_PARAMETER;\r
+            }\r
+            //\r
+            // Check the current value is in the numeric range.\r
+            //\r
+            VarValue = 0;\r
+            if (QuestionReferBitField) {\r
+              //\r
+              // Get the value in bit fields.\r
+              //\r
+              StartBit = BitOffset % 8;\r
+              EndBit = StartBit + BitWidth - 1;\r
+              CopyMem ((UINT8 *) &BufferValue, VarBuffer + Offset, Width);\r
+              VarValue = BitFieldRead32 (BufferValue, StartBit, EndBit);\r
+            } else {\r
+              CopyMem (&VarValue, VarBuffer +  Offset, Width);\r
+            }\r
+          }\r
+          //\r
+          // Boolean type, only 1 and 0 is valid.\r
+          //\r
+          if (VarValue > 1) {\r
+            return EFI_INVALID_PARAMETER;\r
+          }\r
+          break;\r
+        case EFI_IFR_STRING_OP:\r
+          //\r
+          // Check current string length is less than maxsize\r
+          //\r
+\r
+          //\r
+          // CheckBox question is not in IFR Form. This IFR form is not valid.\r
+          //\r
+          if (VarStoreData.VarStoreId == 0) {\r
+            return EFI_INVALID_PARAMETER;\r
+          }\r
+\r
+          //\r
+          // Check whether this question is for the requested varstore.\r
+          //\r
+          IfrString = (EFI_IFR_STRING *) IfrOpHdr;\r
+          if (IfrString->Question.VarStoreId != VarStoreData.VarStoreId) {\r
+            break;\r
+          }\r
+          //\r
+          // Get the Max size of the string.\r
+          //\r
+          Width  = (UINT16) (IfrString->MaxSize * sizeof (UINT16));\r
+          if (NameValueType) {\r
+            QuestionName = HiiGetString (HiiHandle, IfrString->Question.VarStoreInfo.VarName, NULL);\r
+            ASSERT (QuestionName != NULL);\r
+\r
+            StringPtr = StrStr (RequestElement, QuestionName);\r
+            if (StringPtr == NULL) {\r
+              //\r
+              // This question is not in the current configuration string. Skip it.\r
+              //\r
+              break;\r
+            }\r
+            //\r
+            // Skip the VarName.\r
+            //\r
+            StringPtr += StrLen (QuestionName);\r
+\r
+            //\r
+            // Skip the "=".\r
+            //\r
+            StringPtr += 1;\r
+\r
+            //\r
+            // Check current string length is less than maxsize\r
+            // e.g Config String: "0041004200430044", Unicode String: "ABCD". Unicode String length = Config String length / 4.\r
+            // Config string format in UEFI spec.\r
+            // <NvConfig> ::= <Label>'='<String>\r
+            // <String> ::= [<Char>]+\r
+            // <Char> ::= <HexCh>4\r
+            //\r
+            if (StrLen (StringPtr) / 4 > IfrString->MaxSize) {\r
+              return EFI_INVALID_PARAMETER;\r
+            }\r
+          } else {\r
+            //\r
+            // Get Offset/Width by Question header and OneOf Flags\r
+            //\r
+            Offset = IfrString->Question.VarStoreInfo.VarOffset;\r
+            //\r
+            // Check whether this question is in current block array.\r
+            //\r
+            if (!BlockArrayCheck (CurrentBlockArray, Offset, Width)) {\r
+              //\r
+              // This question is not in the current configuration string. Skip it.\r
+              //\r
+              break;\r
+            }\r
+            //\r
+            // Check this var question is in the var storage\r
+            //\r
+            if ((Offset + Width) > VarStoreData.Size) {\r
+              //\r
+              // This question exceeds the var store size.\r
+              //\r
+              return EFI_INVALID_PARAMETER;\r
+            }\r
+\r
+            //\r
+            // Check current string length is less than maxsize\r
+            //\r
+            if (StrLen ((CHAR16 *) (VarBuffer + Offset)) > IfrString->MaxSize) {\r
+              return EFI_INVALID_PARAMETER;\r
+            }\r
+          }\r
+          break;\r
+        case EFI_IFR_ONE_OF_OPTION_OP:\r
+          //\r
+          // Opcode Scope is zero. This one of option is not to be checked.\r
+          //\r
+          if (VarBlockData.Scope == 0) {\r
+            break;\r
+          }\r
+\r
+          //\r
+          // Only check for OneOf and OrderList opcode\r
+          //\r
+          IfrOneOfOption = (EFI_IFR_ONE_OF_OPTION *) IfrOpHdr;\r
+          if (VarBlockData.OpCode == EFI_IFR_ONE_OF_OP) {\r
+            //\r
+            // Check current value is the value of one of option.\r
+            //\r
+            ASSERT (IfrOneOfOption->Type <= EFI_IFR_TYPE_NUM_SIZE_64);\r
+            ZeroMem (&TmpValue, sizeof (EFI_IFR_TYPE_VALUE));\r
+            CopyMem (&TmpValue, &IfrOneOfOption->Value, IfrOneOfOption->Header.Length - OFFSET_OF (EFI_IFR_ONE_OF_OPTION, Value));\r
+            if (VarValue == TmpValue.u64) {\r
+              //\r
+              // The value is one of option value.\r
+              // Set OpCode to Zero, don't need check again.\r
+              //\r
+              VarBlockData.OpCode = 0;\r
+            }\r
+          }\r
+          break;\r
+        case EFI_IFR_END_OP:\r
+          QuestionReferBitField = FALSE;\r
+          //\r
+          // Decrease opcode scope for the validated opcode\r
+          //\r
+          if (VarBlockData.Scope > 0) {\r
+            VarBlockData.Scope --;\r
+          }\r
+\r
+          //\r
+          // OneOf value doesn't belong to one of option value.\r
+          //\r
+          if ((VarBlockData.Scope == 0) && (VarBlockData.OpCode == EFI_IFR_ONE_OF_OP)) {\r
+            return EFI_INVALID_PARAMETER;\r
+          }\r
+          break;\r
+        case EFI_IFR_GUID_OP:\r
+          if (CompareGuid ((EFI_GUID *)((UINT8*)IfrOpHdr + sizeof (EFI_IFR_OP_HEADER)), &gEdkiiIfrBitVarstoreGuid)) {\r
+            QuestionReferBitField = TRUE;\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 += PackageHeader.Length;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  This internal function parses IFR data to validate current setting.\r
+\r
+  @param ConfigElement         ConfigResp element string contains the current setting.\r
+  @param CurrentBlockArray     Current block array.\r
+  @param VarBuffer             Data buffer for this varstore.\r
+\r
+  @retval EFI_SUCCESS            The current setting is valid.\r
+  @retval EFI_OUT_OF_RESOURCES   The memory is not enough.\r
+  @retval EFI_INVALID_PARAMETER  The config string or the Hii package is invalid.\r
+**/\r
+EFI_STATUS\r
+GetBlockDataInfo (\r
+  IN  CHAR16                        *ConfigElement,\r
+  OUT IFR_BLOCK_DATA                **CurrentBlockArray,\r
+  OUT UINT8                         **VarBuffer\r
+  )\r
+{\r
+  IFR_BLOCK_DATA               *BlockData;\r
+  IFR_BLOCK_DATA               *NewBlockData;\r
+  EFI_STRING                   StringPtr;\r
+  UINTN                        Length;\r
+  UINT8                        *TmpBuffer;\r
+  UINT16                       Offset;\r
+  UINT16                       Width;\r
+  LIST_ENTRY                   *Link;\r
+  UINTN                        MaxBufferSize;\r
+  EFI_STATUS                   Status;\r
+  IFR_BLOCK_DATA               *BlockArray;\r
+  UINT8                        *DataBuffer;\r
+\r
+  //\r
+  // Initialize the local variables.\r
+  //\r
+  Status        = EFI_SUCCESS;\r
+  BlockData     = NULL;\r
+  NewBlockData  = NULL;\r
+  TmpBuffer     = NULL;\r
+  BlockArray    = NULL;\r
+  MaxBufferSize = HII_LIB_DEFAULT_VARSTORE_SIZE;\r
+  DataBuffer     = AllocateZeroPool (MaxBufferSize);\r
+  if (DataBuffer == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  //\r
+  // Init BlockArray\r
+  //\r
+  BlockArray = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));\r
+  if (BlockArray == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto Done;\r
+  }\r
+  InitializeListHead (&BlockArray->Entry);\r
+\r
+  StringPtr = StrStr (ConfigElement, L"&OFFSET=");\r
+  ASSERT (StringPtr != NULL);\r
+\r
+  //\r
+  // Parse each <RequestElement> if exists\r
+  // Only <BlockName> format is supported by this help function.\r
+  // <BlockName> ::= &'OFFSET='<Number>&'WIDTH='<Number>\r
+  //\r
+  while (*StringPtr != 0 && StrnCmp (StringPtr, L"&OFFSET=", StrLen (L"&OFFSET=")) == 0) {\r
+    //\r
+    // Skip the &OFFSET= string\r
+    //\r
+    StringPtr += StrLen (L"&OFFSET=");\r
+\r
+    //\r
+    // Get Offset\r
+    //\r
+    Status = InternalHiiGetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
+    if (EFI_ERROR (Status)) {\r
+      goto Done;\r
+    }\r
+    Offset = 0;\r
+    CopyMem (\r
+      &Offset,\r
+      TmpBuffer,\r
+      (((Length + 1) / 2) < sizeof (UINT16)) ? ((Length + 1) / 2) : sizeof (UINT16)\r
+      );\r
+    FreePool (TmpBuffer);\r
+    TmpBuffer = NULL;\r
+\r
+    StringPtr += Length;\r
+    if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {\r
+      Status = EFI_INVALID_PARAMETER;\r
+      goto Done;\r
+    }\r
+    StringPtr += StrLen (L"&WIDTH=");\r
+\r
+    //\r
+    // Get Width\r
+    //\r
+    Status = InternalHiiGetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
+    if (EFI_ERROR (Status)) {\r
+      goto Done;\r
+    }\r
+    Width = 0;\r
+    CopyMem (\r
+      &Width,\r
+      TmpBuffer,\r
+      (((Length + 1) / 2) < sizeof (UINT16)) ? ((Length + 1) / 2) : sizeof (UINT16)\r
+      );\r
+    FreePool (TmpBuffer);\r
+    TmpBuffer = NULL;\r
+\r
+    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 ((UINT32)Offset + Width > MaxBufferSize) {\r
+      DataBuffer = ReallocatePool (\r
+                    MaxBufferSize,\r
+                    Offset + Width + HII_LIB_DEFAULT_VARSTORE_SIZE,\r
+                    DataBuffer\r
+                    );\r
+      if (DataBuffer == NULL) {\r
+        Status = EFI_OUT_OF_RESOURCES;\r
+        goto Done;\r
+      }\r
+      MaxBufferSize = Offset + Width + HII_LIB_DEFAULT_VARSTORE_SIZE;\r
+    }\r
+\r
+    //\r
+    // Update the Block with configuration info\r
+    //\r
+    CopyMem (DataBuffer + Offset, TmpBuffer, Width);\r
+    FreePool (TmpBuffer);\r
+    TmpBuffer = NULL;\r
+\r
+    //\r
+    // Set new Block Data\r
+    //\r
+    NewBlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));\r
+    if (NewBlockData == NULL) {\r
+      Status = EFI_OUT_OF_RESOURCES;\r
+      goto Done;\r
+    }\r
+    NewBlockData->Offset = Offset;\r
+    NewBlockData->Width  = Width;\r
+\r
+    //\r
+    // Insert the new block data into the block data array.\r
+    //\r
+    for (Link = BlockArray->Entry.ForwardLink; Link != &BlockArray->Entry; Link = Link->ForwardLink) {\r
+      BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);\r
+      if (NewBlockData->Offset == BlockData->Offset) {\r
+        if (NewBlockData->Width > BlockData->Width) {\r
+          BlockData->Width = NewBlockData->Width;\r
+        }\r
+        FreePool (NewBlockData);\r
+        break;\r
+      } else if (NewBlockData->Offset < BlockData->Offset) {\r
+        //\r
+        // 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 == &BlockArray->Entry) {\r
+      InsertTailList (Link, &NewBlockData->Entry);\r
+    }\r
+\r
+    //\r
+    // If '\0', parsing is finished.\r
+    //\r
+    if (*StringPtr == 0) {\r
+      break;\r
+    }\r
+    //\r
+    // Go to next ConfigBlock\r
+    //\r
+  }\r
+\r
+  //\r
+  // Merge the aligned block data into the single block data.\r
+  //\r
+  Link = BlockArray->Entry.ForwardLink;\r
+  while ((Link != &BlockArray->Entry) && (Link->ForwardLink != &BlockArray->Entry)) {\r
+    BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);\r
+    NewBlockData = BASE_CR (Link->ForwardLink, IFR_BLOCK_DATA, Entry);\r
+    if ((NewBlockData->Offset >= BlockData->Offset) && (NewBlockData->Offset <= (BlockData->Offset + BlockData->Width))) {\r
+      if ((NewBlockData->Offset + NewBlockData->Width) > (BlockData->Offset + BlockData->Width)) {\r
+        BlockData->Width = (UINT16) (NewBlockData->Offset + NewBlockData->Width - BlockData->Offset);\r
+      }\r
+      RemoveEntryList (Link->ForwardLink);\r
+      FreePool (NewBlockData);\r
+      continue;\r
+    }\r
+    Link = Link->ForwardLink;\r
+  }\r
+\r
+  *VarBuffer         = DataBuffer;\r
+  *CurrentBlockArray = BlockArray;\r
+  return EFI_SUCCESS;\r
+\r
+Done:\r
+  if (DataBuffer != NULL) {\r
+    FreePool (DataBuffer);\r
+  }\r
+\r
+  if (BlockArray != NULL) {\r
+    //\r
+    // Free Link Array CurrentBlockArray\r
+    //\r
+    while (!IsListEmpty (&BlockArray->Entry)) {\r
+      BlockData = BASE_CR (BlockArray->Entry.ForwardLink, IFR_BLOCK_DATA, Entry);\r
+      RemoveEntryList (&BlockData->Entry);\r
+      FreePool (BlockData);\r
+    }\r
+    FreePool (BlockArray);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  This internal function parses IFR data to validate current setting.\r
+\r
+  @param ConfigResp         ConfigResp string contains the current setting.\r
+  @param HiiPackageList     Point to Hii package list.\r
+  @param PackageListLength  The length of the pacakge.\r
+  @param VarGuid            Guid of the buffer storage.\r
+  @param VarName            Name of the buffer storage.\r
+  @param HiiHandle          The HiiHandle for this package.\r
+\r
+  @retval EFI_SUCCESS            The current setting is valid.\r
+  @retval EFI_OUT_OF_RESOURCES   The memory is not enough.\r
+  @retval EFI_INVALID_PARAMETER  The config string or the Hii package is invalid.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+InternalHiiValidateCurrentSetting (\r
+  IN EFI_STRING                    ConfigResp,\r
+  IN EFI_HII_PACKAGE_LIST_HEADER   *HiiPackageList,\r
+  IN UINTN                         PackageListLength,\r
+  IN EFI_GUID                      *VarGuid,\r
+  IN CHAR16                        *VarName,\r
+  IN EFI_HII_HANDLE                HiiHandle\r
+  )\r
+{\r
+  CHAR16              *StringPtr;\r
+  EFI_STATUS          Status;\r
+  IFR_BLOCK_DATA      *CurrentBlockArray;\r
+  IFR_BLOCK_DATA      *BlockData;\r
+  UINT8               *VarBuffer;\r
+  BOOLEAN             NameValueType;\r
+\r
+  CurrentBlockArray = NULL;\r
+  VarBuffer         = NULL;\r
+  StringPtr         = NULL;\r
+  Status            = EFI_SUCCESS;\r
+\r
+  //\r
+  // If StringPtr != NULL, get the request elements.\r
+  //\r
+  if (StrStr (ConfigResp, L"&OFFSET=") != NULL) {\r
+    Status = GetBlockDataInfo(ConfigResp, &CurrentBlockArray, &VarBuffer);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+    NameValueType = FALSE;\r
+  } else {\r
+    //\r
+    // Skip header part.\r
+    //\r
+    StringPtr = StrStr (ConfigResp, L"PATH=");\r
+    ASSERT (StringPtr != NULL);\r
+\r
+    if (StrStr (StringPtr, L"&") != NULL) {\r
+      NameValueType = TRUE;\r
+    } else {\r
+      //\r
+      // Not found Request element, return success.\r
+      //\r
+      return EFI_SUCCESS;\r
+    }\r
+  }\r
+\r
+  Status = ValidateQuestionFromVfr(\r
+                          HiiPackageList,\r
+                          PackageListLength,\r
+                          VarGuid,\r
+                          VarName,\r
+                          VarBuffer,\r
+                          CurrentBlockArray,\r
+                          ConfigResp,\r
+                          HiiHandle,\r
+                          NameValueType\r
+                          );\r
+\r
+  if (VarBuffer != NULL) {\r
+    FreePool (VarBuffer);\r
+  }\r
+\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
+  Check whether the ConfigRequest string has the request elements.\r
+  For EFI_HII_VARSTORE_BUFFER type, the request has "&OFFSET=****&WIDTH=****..." format.\r
+  For EFI_HII_VARSTORE_NAME_VALUE type, the request has "&NAME1**&NAME2..." format.\r
+\r
+  @param  ConfigRequest      The input config request string.\r
+\r
+  @retval  TRUE              The input include config request elements.\r
+  @retval  FALSE             The input string not includes.\r
+\r
+**/\r
+BOOLEAN\r
+GetElementsFromRequest (\r
+  IN EFI_STRING    ConfigRequest\r
+  )\r
+{\r
+  EFI_STRING   TmpRequest;\r
+\r
+  TmpRequest = StrStr (ConfigRequest, L"PATH=");\r
+  ASSERT (TmpRequest != NULL);\r
+\r
+  if ((StrStr (TmpRequest, L"&OFFSET=") != NULL) || (StrStr (TmpRequest, L"&") != NULL)) {\r
+    return TRUE;\r
+  }\r
+\r
+  return FALSE;\r
+}\r
+\r
+/**\r
+  This function parses the input ConfigRequest string and its matched IFR code\r
+  string for setting default value and validating current setting.\r
+\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 TRUE    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
+\r
+  EFI_HII_PACKAGE_LIST_HEADER  *HiiPackageList;\r
+  UINTN                        PackageListLength;\r
+  UINTN                        MaxLen;\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
+  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
+  ASSERT (StringPtr != NULL);\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
+      Status = EFI_SUCCESS;\r
+      goto NextConfigAltResp;\r
+    }\r
+\r
+    //\r
+    // 2. 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
+    // 3. Call ConfigRouting GetAltCfg(ConfigRoute, <ConfigResponse>, Guid, Name, DevicePath, AltCfgId, AltCfgResp)\r
+    //    Get the default configuration string according to the default ID.\r
+    //\r
+    Status = gHiiConfigRouting->GetAltConfig (\r
+                                  gHiiConfigRouting,\r
+                                  ConfigAltResp,\r
+                                  VarGuid,\r
+                                  VarName,\r
+                                  DevicePath,\r
+                                  (ActionType == ACTION_SET_DEFAUTL_VALUE) ? &DefaultId:NULL,  // it can be NULL to get the current setting.\r
+                                  &ConfigResp\r
+                                );\r
+\r
+    //\r
+    // The required setting can't be found. So, it is not required to be validated and set.\r
+    //\r
+    if (EFI_ERROR (Status)) {\r
+      Status = EFI_SUCCESS;\r
+      goto NextConfigAltResp;\r
+    }\r
+    //\r
+    // Only the ConfigHdr is found. Not any block data is found. No data is required to be validated and set.\r
+    //\r
+    if (!GetElementsFromRequest (ConfigResp)) {\r
+      goto NextConfigAltResp;\r
+    }\r
+\r
+    //\r
+    // 4. Set the default configuration information or Validate current setting by parse IFR code.\r
+    //    Current Setting is in ConfigResp, will be set into buffer, then check it again.\r
+    //\r
+    if (ActionType == ACTION_SET_DEFAUTL_VALUE) {\r
+      //\r
+      // 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, HiiHandle);\r
+    }\r
+\r
+    if (EFI_ERROR (Status)) {\r
+      goto Done;\r
+    }\r
+\r
+NextConfigAltResp:\r
+    //\r
+    // Free the allocated pacakge buffer and the got ConfigResp string.\r
+    //\r
+    if (HiiPackageList != NULL) {\r
+      FreePool (HiiPackageList);\r
+      HiiPackageList = NULL;\r
+    }\r
+\r
+    if (ConfigResp != NULL) {\r
+      FreePool (ConfigResp);\r
+      ConfigResp = NULL;\r
+    }\r
+\r
+    //\r
+    // Free the allocated buffer.\r
+    //\r
+    FreePool (VarGuid);\r
+    VarGuid = NULL;\r
+\r
+    FreePool (VarName);\r
+    VarName = NULL;\r
+\r
+    FreePool (DevicePath);\r
+    DevicePath = NULL;\r
+\r
+    //\r
+    // 5. Jump to next ConfigAltResp for another Guid, Name, Path.\r
+    //\r
+\r
+    //\r
+    // Get and Skip ConfigHdr\r
+    //\r
+    while (*StringPtr != L'\0' && *StringPtr != L'&') {\r
+      StringPtr++;\r
+    }\r
+    if (*StringPtr == L'\0') {\r
+      break;\r
+    }\r
+\r
+    //\r
+    // Construct ConfigAltHdr string  "&<ConfigHdr>&ALTCFG=\0"\r
+    //                               | 1 | StrLen (ConfigHdr) | 8 | 1 |\r
+    //\r
+    MaxLen = 1 + StringPtr - StringHdr + 8 + 1;\r
+    ConfigAltHdr = AllocateZeroPool ( MaxLen * sizeof (CHAR16));\r
+    if (ConfigAltHdr == NULL) {\r
+      Status = EFI_OUT_OF_RESOURCES;\r
+      goto Done;\r
+    }\r
+    StrCpyS (ConfigAltHdr, MaxLen, L"&");\r
+    StrnCatS (ConfigAltHdr, MaxLen, StringHdr, StringPtr - StringHdr);\r
+    StrCatS (ConfigAltHdr, MaxLen, L"&ALTCFG=");\r
+\r
+    //\r
+    // Skip all AltResp (AltConfigHdr ConfigBody) for the same ConfigHdr\r
+    //\r
+    while ((StringHdr = StrStr (StringPtr, ConfigAltHdr)) != NULL) {\r
+      StringPtr = StringHdr + StrLen (ConfigAltHdr);\r
+      if (*StringPtr == L'\0') {\r
+        break;\r
+      }\r
+    }\r
+\r
+    //\r
+    // Free the allocated ConfigAltHdr string\r
+    //\r
+    FreePool (ConfigAltHdr);\r
+    if (*StringPtr == L'\0') {\r
+      break;\r
+    }\r
+\r
+    //\r
+    // Find &GUID as the next ConfigHdr\r
+    //\r
+    StringPtr = StrStr (StringPtr, L"&GUID");\r
+    if (StringPtr == NULL) {\r
+      break;\r
+    }\r
+\r
+    //\r
+    // Skip char '&'\r
+    //\r
+    StringPtr ++;\r
+  }\r
+\r
+Done:\r
+  if (VarGuid != NULL) {\r
+    FreePool (VarGuid);\r
+  }\r
+\r
+  if (VarName != NULL) {\r
+    FreePool (VarName);\r
+  }\r
+\r
+  if (DevicePath != NULL) {\r
+    FreePool (DevicePath);\r
+  }\r
+\r
+  if (ConfigResp != NULL) {\r
+    FreePool (ConfigResp);\r
+  }\r
+\r
+  if (ConfigAltResp != NULL) {\r
+    FreePool (ConfigAltResp);\r
+  }\r
+\r
+  if (HiiPackageList != NULL) {\r
+    FreePool (HiiPackageList);\r
+  }\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return FALSE;\r
+  }\r
+\r
+  return TRUE;\r
+}\r
+\r
+/**\r
+  Validate the current configuration by parsing HII form IFR opcode.\r
+\r
+  NULL request string support depends on the ExportConfig interface of\r
+  HiiConfigRouting protocol in UEFI specification.\r
+\r
+  @param  Request   A null-terminated Unicode string in\r
+                    <MultiConfigRequest> format. It can be NULL.\r
+                    If it is NULL, all current configuration for the\r
+                    entirety of the current HII database will be validated.\r
+\r
+  @retval TRUE    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 TRUE    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
+  Determines if two values in config strings match.\r
+\r
+  Compares the substring between StartSearchString and StopSearchString in\r
+  FirstString to the substring between StartSearchString and StopSearchString\r
+  in SecondString.  If the two substrings match, then TRUE is returned.  If the\r
+  two substrings do not match, then FALSE is returned.\r
+\r
+  If FirstString is NULL, then ASSERT().\r
+  If SecondString is NULL, then ASSERT().\r
+  If StartSearchString is NULL, then ASSERT().\r
+  If StopSearchString is NULL, then ASSERT().\r
+\r
+  @param FirstString        Pointer to the first Null-terminated Unicode string.\r
+  @param SecondString       Pointer to the second Null-terminated Unicode string.\r
+  @param StartSearchString  Pointer to the Null-terminated Unicode string that\r
+                            marks the start of the value string to compare.\r
+  @param StopSearchString   Pointer to the Null-terminated Unicode string that\r
+                            marks the end of the value string to compare.\r
+\r
+  @retval FALSE             StartSearchString is not present in FirstString.\r
+  @retval FALSE             StartSearchString is not present in SecondString.\r
+  @retval FALSE             StopSearchString is not present in FirstString.\r
+  @retval FALSE             StopSearchString is not present in SecondString.\r
+  @retval FALSE             The length of the substring in FirstString is not the\r
+                            same length as the substring in SecondString.\r
+  @retval FALSE             The value string in FirstString does not matche the\r
+                            value string in SecondString.\r
+  @retval TRUE              The value string in FirstString matches the value\r
+                            string in SecondString.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+InternalHiiCompareSubString (\r
+  IN CHAR16  *FirstString,\r
+  IN CHAR16  *SecondString,\r
+  IN CHAR16  *StartSearchString,\r
+  IN CHAR16  *StopSearchString\r
+  )\r
+{\r
+  CHAR16  *EndFirstString;\r
+  CHAR16  *EndSecondString;\r
+\r
+  ASSERT (FirstString != NULL);\r
+  ASSERT (SecondString != NULL);\r
+  ASSERT (StartSearchString != NULL);\r
+  ASSERT (StopSearchString != NULL);\r
+\r
+  FirstString = StrStr (FirstString, StartSearchString);\r
+  if (FirstString == NULL) {\r
+    return FALSE;\r
+  }\r
+\r
+  SecondString = StrStr (SecondString, StartSearchString);\r
+  if (SecondString == NULL) {\r
+    return FALSE;\r
+  }\r
+\r
+  EndFirstString = StrStr (FirstString, StopSearchString);\r
+  if (EndFirstString == NULL) {\r
+    return FALSE;\r
+  }\r
+\r
+  EndSecondString = StrStr (SecondString, StopSearchString);\r
+  if (EndSecondString == NULL) {\r
+    return FALSE;\r
+  }\r
+\r
+  if ((EndFirstString - FirstString) != (EndSecondString - SecondString)) {\r
+    return FALSE;\r
+  }\r
+\r
+  return (BOOLEAN)(StrnCmp (FirstString, SecondString, EndFirstString - FirstString) == 0);\r
+}\r
+\r
+/**\r
+  Determines if the routing data specified by GUID and NAME match a <ConfigHdr>.\r
+\r
+  If ConfigHdr is NULL, then ASSERT().\r
+\r
+  @param[in] ConfigHdr  Either <ConfigRequest> or <ConfigResp>.\r
+  @param[in] Guid       GUID of the storage.\r
+  @param[in] Name       NAME of the storage.\r
+\r
+  @retval TRUE   Routing information matches <ConfigHdr>.\r
+  @retval FALSE  Routing information does not match <ConfigHdr>.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+HiiIsConfigHdrMatch (\r
+  IN CONST EFI_STRING  ConfigHdr,\r
+  IN CONST EFI_GUID    *Guid,     OPTIONAL\r
+  IN CONST CHAR16      *Name      OPTIONAL\r
+  )\r
+{\r
+  EFI_STRING  CompareConfigHdr;\r
+  BOOLEAN     Result;\r
+\r
+  ASSERT (ConfigHdr != NULL);\r
+\r
+  //\r
+  // Use Guid and Name to generate a <ConfigHdr> string\r
+  //\r
+  CompareConfigHdr = HiiConstructConfigHdr (Guid, Name, NULL);\r
+  if (CompareConfigHdr == NULL) {\r
+    return FALSE;\r
+  }\r
+\r
+  Result = TRUE;\r
+  if (Guid != NULL) {\r
+    //\r
+    // Compare GUID value strings\r
+    //\r
+    Result = InternalHiiCompareSubString (ConfigHdr, CompareConfigHdr, L"GUID=", L"&NAME=");\r
+  }\r
+\r
+  if (Result && Name != NULL) {\r
+    //\r
+    // Compare NAME value strings\r
+    //\r
+    Result = InternalHiiCompareSubString (ConfigHdr, CompareConfigHdr, L"&NAME=", L"&PATH=");\r
+  }\r
+\r
+  //\r
+  // Free the <ConfigHdr> string\r
+  //\r
+  FreePool (CompareConfigHdr);\r
+\r
+  return Result;\r
+}\r
+\r
+/**\r
+  Retrieves uncommitted data from the Form Browser and converts it to a binary\r
+  buffer.\r
+\r
+  @param[in]  VariableGuid  Pointer to an EFI_GUID structure.  This is an optional\r
+                            parameter that may be NULL.\r
+  @param[in]  VariableName  Pointer to a Null-terminated Unicode string.  This\r
+                            is an optional parameter that may be NULL.\r
+  @param[in]  BufferSize    Length in bytes of buffer to hold retrieved data.\r
+  @param[out] Buffer        Buffer of data to be updated.\r
+\r
+  @retval FALSE  The uncommitted data could not be retrieved.\r
+  @retval TRUE   The uncommitted data was retrieved.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+HiiGetBrowserData (\r
+  IN CONST EFI_GUID  *VariableGuid,  OPTIONAL\r
+  IN CONST CHAR16    *VariableName,  OPTIONAL\r
+  IN UINTN           BufferSize,\r
+  OUT UINT8          *Buffer\r
+  )\r
+{\r
+  EFI_STRING  ResultsData;\r
+  UINTN       Size;\r
+  EFI_STRING  ConfigResp;\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 FALSE;\r
+  }\r
+\r
+  //\r
+  // Construct <ConfigResp> mConfigHdrTemplate L'&' ResultsData L'\0'\r
+  //\r
+  Size = (StrLen (mConfigHdrTemplate) + 1) * sizeof (CHAR16);\r
+  Size = Size + (StrLen (ResultsData) + 1) * sizeof (CHAR16);\r
+  ConfigResp = AllocateZeroPool (Size);\r
+  UnicodeSPrint (ConfigResp, Size, L"%s&%s", mConfigHdrTemplate, ResultsData);\r
+\r
+  //\r
+  // Free the allocated buffer\r
+  //\r
+  FreePool (ResultsData);\r
+  if (ConfigResp == NULL) {\r
+    return FALSE;\r
+  }\r
+\r
+  //\r
+  // Convert <ConfigResp> to a buffer\r
+  //\r
+  Status = gHiiConfigRouting->ConfigToBlock (\r
+                                gHiiConfigRouting,\r
+                                ConfigResp,\r
+                                Buffer,\r
+                                &BufferSize,\r
+                                &Progress\r
+                                );\r
+  //\r
+  // Free the allocated buffer\r
+  //\r
+  FreePool (ConfigResp);\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return FALSE;\r
+  }\r
+\r
+  return TRUE;\r
+}\r
+\r
+/**\r
+  Updates uncommitted data in the Form Browser.\r
+\r
+  If Buffer is NULL, then ASSERT().\r
+\r
+  @param[in]  VariableGuid    Pointer to an EFI_GUID structure.  This is an optional\r
+                              parameter that may be NULL.\r
+  @param[in]  VariableName    Pointer to a Null-terminated Unicode string.  This\r
+                              is an optional parameter that may be NULL.\r
+  @param[in]  BufferSize      Length, in bytes, of Buffer.\r
+  @param[in]  Buffer          Buffer of data to commit.\r
+  @param[in]  RequestElement  An optional field to specify which part of the\r
+                              buffer data will be send back to Browser. If NULL,\r
+                              the whole buffer of data will be committed to\r
+                              Browser.\r
+                              <RequestElement> ::= &OFFSET=<Number>&WIDTH=<Number>*\r
+\r
+  @retval FALSE  The uncommitted data could not be updated.\r
+  @retval TRUE   The uncommitted data was updated.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+HiiSetBrowserData (\r
+  IN CONST EFI_GUID  *VariableGuid, OPTIONAL\r
+  IN CONST CHAR16    *VariableName, OPTIONAL\r
+  IN UINTN           BufferSize,\r
+  IN CONST UINT8     *Buffer,\r
+  IN CONST CHAR16    *RequestElement  OPTIONAL\r
+  )\r
+{\r
+  UINTN       Size;\r
+  EFI_STRING  ConfigRequest;\r
+  EFI_STRING  ConfigResp;\r
+  EFI_STRING  ResultsData;\r
+\r
+  ASSERT (Buffer != NULL);\r
+\r
+  //\r
+  // Construct <ConfigRequest>\r
+  //\r
+  if (RequestElement == NULL) {\r
+    //\r
+    // Allocate and fill a buffer large enough to hold the <ConfigHdr> template\r
+    // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator\r
+    //\r
+    Size = (StrLen (mConfigHdrTemplate) + 32 + 1) * sizeof (CHAR16);\r
+    ConfigRequest = AllocateZeroPool (Size);\r
+    UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", mConfigHdrTemplate, (UINT64)BufferSize);\r
+  } else {\r
+    //\r
+    // Allocate and fill a buffer large enough to hold the <ConfigHdr> template\r
+    // followed by <RequestElement> followed by a Null-terminator\r
+    //\r
+    Size = StrLen (mConfigHdrTemplate) * sizeof (CHAR16);\r
+    Size = Size + (StrLen (RequestElement) + 1) * sizeof (CHAR16);\r
+    ConfigRequest = AllocateZeroPool (Size);\r
+    UnicodeSPrint (ConfigRequest, Size, L"%s%s", mConfigHdrTemplate, RequestElement);\r
+  }\r
+  if (ConfigRequest == NULL) {\r
+    return FALSE;\r
+  }\r
+\r
+  //\r
+  // Convert <ConfigRequest> to <ConfigResp>\r
+  //\r
+  ConfigResp = InternalHiiBlockToConfig (ConfigRequest, Buffer, BufferSize);\r
+  FreePool (ConfigRequest);\r
+  if (ConfigResp == NULL) {\r
+    return FALSE;\r
+  }\r
+\r
+  //\r
+  // Set data in the uncommitted browser state information\r
+  //\r
+  ResultsData = InternalHiiBrowserCallback (VariableGuid, VariableName, ConfigResp + StrLen(mConfigHdrTemplate) + 1);\r
+  FreePool (ConfigResp);\r
+\r
+  return (BOOLEAN)(ResultsData != NULL);\r
+}\r
+\r
+/////////////////////////////////////////\r
+/////////////////////////////////////////\r
+/// IFR Functions\r
+/////////////////////////////////////////\r
+/////////////////////////////////////////\r
+\r
+#define HII_LIB_OPCODE_ALLOCATION_SIZE  0x200\r
+\r
+typedef struct {\r
+  UINT8  *Buffer;\r
+  UINTN  BufferSize;\r
+  UINTN  Position;\r
+} HII_LIB_OPCODE_BUFFER;\r
+\r
+///\r
+/// Lookup table that converts EFI_IFR_TYPE_X enum values to a width in bytes\r
+///\r
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 mHiiDefaultTypeToWidth[] = {\r
+  1, // EFI_IFR_TYPE_NUM_SIZE_8\r
+  2, // EFI_IFR_TYPE_NUM_SIZE_16\r
+  4, // EFI_IFR_TYPE_NUM_SIZE_32\r
+  8, // EFI_IFR_TYPE_NUM_SIZE_64\r
+  1, // EFI_IFR_TYPE_BOOLEAN\r
+  3, // EFI_IFR_TYPE_TIME\r
+  4, // EFI_IFR_TYPE_DATE\r
+  2  // EFI_IFR_TYPE_STRING\r
+};\r
+\r
+/**\r
+  Allocates and returns a new OpCode Handle.  OpCode Handles must be freed with\r
+  HiiFreeOpCodeHandle().\r
+\r
+  @retval NULL   There are not enough resources to allocate a new OpCode Handle.\r
+  @retval Other  A new OpCode handle.\r
+\r
+**/\r
+VOID *\r
+EFIAPI\r
+HiiAllocateOpCodeHandle (\r
+  VOID\r
+  )\r
+{\r
+  HII_LIB_OPCODE_BUFFER  *OpCodeBuffer;\r
+\r
+  OpCodeBuffer = (HII_LIB_OPCODE_BUFFER *)AllocatePool (sizeof (HII_LIB_OPCODE_BUFFER));\r
+  if (OpCodeBuffer == NULL) {\r
+    return NULL;\r
+  }\r
+  OpCodeBuffer->Buffer = (UINT8 *)AllocatePool (HII_LIB_OPCODE_ALLOCATION_SIZE);\r
+  if (OpCodeBuffer->Buffer == NULL) {\r
+    FreePool (OpCodeBuffer);\r
+    return NULL;\r
+  }\r
+  OpCodeBuffer->BufferSize = HII_LIB_OPCODE_ALLOCATION_SIZE;\r
+  OpCodeBuffer->Position = 0;\r
+  return (VOID *)OpCodeBuffer;\r
+}\r
+\r
+/**\r
+  Frees an OpCode Handle that was previously allocated with HiiAllocateOpCodeHandle().\r
+  When an OpCode Handle is freed, all of the opcodes associated with the OpCode\r
+  Handle are also freed.\r
+\r
+  If OpCodeHandle is NULL, then ASSERT().\r
+\r
+  @param[in]  OpCodeHandle   Handle to the buffer of opcodes.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+HiiFreeOpCodeHandle (\r
+  VOID  *OpCodeHandle\r
+  )\r
+{\r
+  HII_LIB_OPCODE_BUFFER  *OpCodeBuffer;\r
+\r
+  ASSERT (OpCodeHandle != NULL);\r
+\r
+  OpCodeBuffer = (HII_LIB_OPCODE_BUFFER *)OpCodeHandle;\r
+  if (OpCodeBuffer->Buffer != NULL) {\r
+    FreePool (OpCodeBuffer->Buffer);\r
+  }\r
+  FreePool (OpCodeBuffer);\r
+}\r
+\r
+/**\r
+  Internal function gets the current position of opcode buffer.\r
+\r
+  @param[in]  OpCodeHandle   Handle to the buffer of opcodes.\r
+\r
+  @return Current position of opcode buffer.\r
+**/\r
+UINTN\r
+EFIAPI\r
+InternalHiiOpCodeHandlePosition (\r
+  IN VOID  *OpCodeHandle\r
+  )\r
+{\r
+  return ((HII_LIB_OPCODE_BUFFER  *)OpCodeHandle)->Position;\r
+}\r
+\r
+/**\r
+  Internal function gets the start pointer of opcode buffer.\r
+\r
+  @param[in]  OpCodeHandle   Handle to the buffer of opcodes.\r
+\r
+  @return Pointer to the opcode buffer base.\r
+**/\r
+UINT8 *\r
+EFIAPI\r
+InternalHiiOpCodeHandleBuffer (\r
+  IN VOID  *OpCodeHandle\r
+  )\r
+{\r
+  return ((HII_LIB_OPCODE_BUFFER  *)OpCodeHandle)->Buffer;\r
+}\r
+\r
+/**\r
+  Internal function reserves the enough buffer for current opcode.\r
+  When the buffer is not enough, Opcode buffer will be extended.\r
+\r
+  @param[in]  OpCodeHandle   Handle to the buffer of opcodes.\r
+  @param[in]  Size           Size of current opcode.\r
+\r
+  @return Pointer to the current opcode.\r
+**/\r
+UINT8 *\r
+EFIAPI\r
+InternalHiiGrowOpCodeHandle (\r
+  IN VOID   *OpCodeHandle,\r
+  IN UINTN  Size\r
+  )\r
+{\r
+  HII_LIB_OPCODE_BUFFER  *OpCodeBuffer;\r
+  UINT8                  *Buffer;\r
+\r
+  ASSERT (OpCodeHandle != NULL);\r
+\r
+  OpCodeBuffer = (HII_LIB_OPCODE_BUFFER *)OpCodeHandle;\r
+  if (OpCodeBuffer->Position + Size > OpCodeBuffer->BufferSize) {\r
+    Buffer = ReallocatePool (\r
+              OpCodeBuffer->BufferSize,\r
+              OpCodeBuffer->BufferSize + (Size + HII_LIB_OPCODE_ALLOCATION_SIZE),\r
+              OpCodeBuffer->Buffer\r
+              );\r
+    ASSERT (Buffer != NULL);\r
+    OpCodeBuffer->Buffer = Buffer;\r
+    OpCodeBuffer->BufferSize += (Size + HII_LIB_OPCODE_ALLOCATION_SIZE);\r
+  }\r
+  Buffer = OpCodeBuffer->Buffer + OpCodeBuffer->Position;\r
+  OpCodeBuffer->Position += Size;\r
+  return Buffer;\r
+}\r
+\r
+/**\r
+  Internal function creates opcode based on the template opcode.\r
+\r
+  @param[in]  OpCodeHandle    Handle to the buffer of opcodes.\r
+  @param[in]  OpCodeTemplate  Pointer to the template buffer of opcode.\r
+  @param[in]  OpCode          OpCode IFR value.\r
+  @param[in]  OpCodeSize      Size of opcode.\r
+  @param[in]  ExtensionSize   Size of extended opcode.\r
+  @param[in]  Scope           Scope bit of opcode.\r
+\r
+  @return Pointer to the current opcode with opcode data.\r
+**/\r
+UINT8 *\r
+EFIAPI\r
+InternalHiiCreateOpCodeExtended (\r
+  IN VOID   *OpCodeHandle,\r
+  IN VOID   *OpCodeTemplate,\r
+  IN UINT8  OpCode,\r
+  IN UINTN  OpCodeSize,\r
+  IN UINTN  ExtensionSize,\r
+  IN UINT8  Scope\r
+  )\r
+{\r
+  EFI_IFR_OP_HEADER  *Header;\r
+  UINT8              *Buffer;\r
+\r
+  ASSERT (OpCodeTemplate != NULL);\r
+  ASSERT ((OpCodeSize + ExtensionSize) <= 0x7F);\r
+\r
+  Header = (EFI_IFR_OP_HEADER *)OpCodeTemplate;\r
+  Header->OpCode = OpCode;\r
+  Header->Scope  = Scope;\r
+  Header->Length = (UINT8)(OpCodeSize + ExtensionSize);\r
+  Buffer = InternalHiiGrowOpCodeHandle (OpCodeHandle, Header->Length);\r
+  return (UINT8 *)CopyMem (Buffer, Header, OpCodeSize);\r
+}\r
+\r
+/**\r
+  Internal function creates opcode based on the template opcode for the normal opcode.\r
+\r
+  @param[in]  OpCodeHandle    Handle to the buffer of opcodes.\r
+  @param[in]  OpCodeTemplate  Pointer to the template buffer of opcode.\r
+  @param[in]  OpCode          OpCode IFR value.\r
+  @param[in]  OpCodeSize      Size of opcode.\r
+\r
+  @return Pointer to the current opcode with opcode data.\r
+**/\r
+UINT8 *\r
+EFIAPI\r
+InternalHiiCreateOpCode (\r
+  IN VOID   *OpCodeHandle,\r
+  IN VOID   *OpCodeTemplate,\r
+  IN UINT8  OpCode,\r
+  IN UINTN  OpCodeSize\r
+  )\r
+{\r
+  return InternalHiiCreateOpCodeExtended (OpCodeHandle, OpCodeTemplate, OpCode, OpCodeSize, 0, 0);\r
+}\r
+\r
+/**\r
+  Append raw opcodes to an OpCodeHandle.\r
+\r
+  If OpCodeHandle is NULL, then ASSERT().\r
+  If RawBuffer is NULL, then ASSERT();\r
+\r
+  @param[in]  OpCodeHandle   Handle to the buffer of opcodes.\r
+  @param[in]  RawBuffer      Buffer of opcodes to append.\r
+  @param[in]  RawBufferSize  The size, in bytes, of Buffer.\r
+\r
+  @retval NULL   There is not enough space left in Buffer to add the opcode.\r
+  @retval Other  A pointer to the appended opcodes.\r
+\r
+**/\r
+UINT8 *\r
+EFIAPI\r
+HiiCreateRawOpCodes (\r
+  IN VOID   *OpCodeHandle,\r
+  IN UINT8  *RawBuffer,\r
+  IN UINTN  RawBufferSize\r
+  )\r
+{\r
+  UINT8  *Buffer;\r
+\r
+  ASSERT (RawBuffer != NULL);\r
+\r
+  Buffer = InternalHiiGrowOpCodeHandle (OpCodeHandle, RawBufferSize);\r
+  return (UINT8 *)CopyMem (Buffer, RawBuffer, RawBufferSize);\r
+}\r
+\r
+/**\r
+  Append opcodes from one OpCode Handle to another OpCode handle.\r
+\r
+  If OpCodeHandle is NULL, then ASSERT().\r
+  If RawOpCodeHandle is NULL, then ASSERT();\r
+\r
+  @param[in]  OpCodeHandle     Handle to the buffer of opcodes.\r
+  @param[in]  RawOpCodeHandle  Handle to the buffer of opcodes.\r
+\r
+  @retval NULL   There is not enough space left in Buffer to add the opcode.\r
+  @retval Other  A pointer to the appended opcodes.\r
+\r
+**/\r
+UINT8 *\r
+EFIAPI\r
+InternalHiiAppendOpCodes (\r
+  IN VOID  *OpCodeHandle,\r
+  IN VOID  *RawOpCodeHandle\r
+  )\r
+{\r
+  HII_LIB_OPCODE_BUFFER  *RawOpCodeBuffer;\r
+\r
+  ASSERT (RawOpCodeHandle != NULL);\r
+\r
+  RawOpCodeBuffer = (HII_LIB_OPCODE_BUFFER *)RawOpCodeHandle;\r
+  return HiiCreateRawOpCodes (OpCodeHandle, RawOpCodeBuffer->Buffer, RawOpCodeBuffer->Position);\r
+}\r
+\r
+/**\r
+  Create EFI_IFR_END_OP opcode.\r
+\r
+  If OpCodeHandle is NULL, then ASSERT().\r
+\r
+  @param[in]  OpCodeHandle  Handle to the buffer of opcodes.\r
+\r
+  @retval NULL   There is not enough space left in Buffer to add the opcode.\r
+  @retval Other  A pointer to the created opcode.\r
+\r
+**/\r
+UINT8 *\r
+EFIAPI\r
+HiiCreateEndOpCode (\r
+  IN VOID  *OpCodeHandle\r
+  )\r
+{\r
+  EFI_IFR_END  OpCode;\r
+\r
+  return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_END_OP, sizeof (OpCode));\r
+}\r
+\r
+/**\r
+  Create EFI_IFR_ONE_OF_OPTION_OP opcode.\r
+\r
+  If OpCodeHandle is NULL, then ASSERT().\r
+  If Type is invalid, then ASSERT().\r
+  If Flags is invalid, then ASSERT().\r
+\r
+  @param[in]  OpCodeHandle  Handle to the buffer of opcodes.\r
+  @param[in]  StringId      StringId for the option\r
+  @param[in]  Flags         Flags for the option\r
+  @param[in]  Type          Type for the option\r
+  @param[in]  Value         Value for the option\r
+\r
+  @retval NULL   There is not enough space left in Buffer to add the opcode.\r
+  @retval Other  A pointer to the created opcode.\r
+\r
+**/\r
+UINT8 *\r
+EFIAPI\r
+HiiCreateOneOfOptionOpCode (\r
+  IN VOID    *OpCodeHandle,\r
+  IN UINT16  StringId,\r
+  IN UINT8   Flags,\r
+  IN UINT8   Type,\r
+  IN UINT64  Value\r
+  )\r
+{\r
+  EFI_IFR_ONE_OF_OPTION  OpCode;\r
+\r
+  ASSERT (Type < EFI_IFR_TYPE_OTHER);\r
+\r
+  ZeroMem (&OpCode, sizeof (OpCode));\r
+  OpCode.Option = StringId;\r
+  OpCode.Flags  = (UINT8) (Flags & (EFI_IFR_OPTION_DEFAULT | EFI_IFR_OPTION_DEFAULT_MFG));\r
+  OpCode.Type   = Type;\r
+  CopyMem (&OpCode.Value, &Value, mHiiDefaultTypeToWidth[Type]);\r
+\r
+  return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_ONE_OF_OPTION_OP, OFFSET_OF(EFI_IFR_ONE_OF_OPTION, Value) + mHiiDefaultTypeToWidth[Type]);\r
+}\r
+\r
+/**\r
+  Create EFI_IFR_DEFAULT_OP opcode.\r
+\r
+  If OpCodeHandle is NULL, then ASSERT().\r
+  If Type is invalid, then ASSERT().\r
+\r
+  @param[in]  OpCodeHandle  Handle to the buffer of opcodes.\r
+  @param[in]  DefaultId     DefaultId for the default\r
+  @param[in]  Type          Type for the default\r
+  @param[in]  Value         Value for the default\r
+\r
+  @retval NULL   There is not enough space left in Buffer to add the opcode.\r
+  @retval Other  A pointer to the created opcode.\r
+\r
+**/\r
+UINT8 *\r
+EFIAPI\r
+HiiCreateDefaultOpCode (\r
+  IN VOID    *OpCodeHandle,\r
+  IN UINT16  DefaultId,\r
+  IN UINT8   Type,\r
+  IN UINT64  Value\r
+  )\r
+{\r
+  EFI_IFR_DEFAULT  OpCode;\r
+\r
+  ASSERT (Type < EFI_IFR_TYPE_OTHER);\r
+\r
+  ZeroMem (&OpCode, sizeof (OpCode));\r
+  OpCode.Type      = Type;\r
+  OpCode.DefaultId = DefaultId;\r
+  CopyMem (&OpCode.Value, &Value, mHiiDefaultTypeToWidth[Type]);\r
+\r
+  return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_DEFAULT_OP, OFFSET_OF(EFI_IFR_DEFAULT, Value) + mHiiDefaultTypeToWidth[Type]);\r
+}\r
+\r
+/**\r
+  Create EFI_IFR_GUID opcode.\r
+\r
+  If OpCodeHandle is NULL, then ASSERT().\r
+  If Guid is NULL, then ASSERT().\r
+  If OpCodeSize < sizeof (EFI_IFR_GUID), then ASSERT().\r
+\r
+  @param[in]  OpCodeHandle  Handle to the buffer of opcodes.\r
+  @param[in]  Guid          Pointer to EFI_GUID of this guided opcode.\r
+  @param[in]  GuidOpCode    Pointer to an EFI_IFR_GUID opcode.  This is an\r
+                            optional parameter that may be NULL.  If this\r
+                            parameter is NULL, then the GUID extension\r
+                            region of the created opcode is filled with zeros.\r
+                            If this parameter is not NULL, then the GUID\r
+                            extension region of GuidData will be copied to\r
+                            the GUID extension region of the created opcode.\r
+  @param[in]  OpCodeSize    The size, in bytes, of created opcode.  This value\r
+                            must be >= sizeof(EFI_IFR_GUID).\r
+\r
+  @retval NULL   There is not enough space left in Buffer to add the opcode.\r
+  @retval Other  A pointer to the created opcode.\r
+\r
+**/\r
+UINT8 *\r
+EFIAPI\r
+HiiCreateGuidOpCode (\r
+  IN VOID            *OpCodeHandle,\r
+  IN CONST EFI_GUID  *Guid,\r
+  IN CONST VOID      *GuidOpCode,    OPTIONAL\r
+  IN UINTN           OpCodeSize\r
+  )\r
+{\r
+  EFI_IFR_GUID  OpCode;\r
+  EFI_IFR_GUID  *OpCodePointer;\r
+\r
+  ASSERT (Guid != NULL);\r
+  ASSERT (OpCodeSize >= sizeof (OpCode));\r
+\r
+  ZeroMem (&OpCode, sizeof (OpCode));\r
+  CopyGuid ((EFI_GUID *)(VOID *)&OpCode.Guid, Guid);\r
+\r
+  OpCodePointer = (EFI_IFR_GUID *)InternalHiiCreateOpCodeExtended (\r
+                                    OpCodeHandle,\r
+                                    &OpCode,\r
+                                    EFI_IFR_GUID_OP,\r
+                                    sizeof (OpCode),\r
+                                    OpCodeSize - sizeof (OpCode),\r
+                                    0\r
+                                    );\r
+  if (OpCodePointer != NULL && GuidOpCode != NULL) {\r
+    CopyMem (OpCodePointer + 1, (EFI_IFR_GUID *)GuidOpCode + 1, OpCodeSize - sizeof (OpCode));\r
+  }\r
+  return (UINT8 *)OpCodePointer;\r
+}\r
+\r
+/**\r
+  Create EFI_IFR_ACTION_OP opcode.\r
+\r
+  If OpCodeHandle is NULL, then ASSERT().\r
+  If any reserved bits are set in QuestionFlags, then ASSERT().\r
+\r
+  @param[in]  OpCodeHandle  Handle to the buffer of opcodes.\r
+  @param[in]  QuestionId      Question ID\r
+  @param[in]  Prompt          String ID for Prompt\r
+  @param[in]  Help            String ID for Help\r
+  @param[in]  QuestionFlags   Flags in Question Header\r
+  @param[in]  QuestionConfig  String ID for configuration\r
+\r
+  @retval NULL   There is not enough space left in Buffer to add the opcode.\r
+  @retval Other  A pointer to the created opcode.\r
+\r
+**/\r
+UINT8 *\r
+EFIAPI\r
+HiiCreateActionOpCode (\r
+  IN VOID             *OpCodeHandle,\r
+  IN EFI_QUESTION_ID  QuestionId,\r
+  IN EFI_STRING_ID    Prompt,\r
+  IN EFI_STRING_ID    Help,\r
+  IN UINT8            QuestionFlags,\r
+  IN EFI_STRING_ID    QuestionConfig\r
+  )\r
+{\r
+  EFI_IFR_ACTION  OpCode;\r
+\r
+  ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED))) == 0);\r
+\r
+  ZeroMem (&OpCode, sizeof (OpCode));\r
+  OpCode.Question.QuestionId    = QuestionId;\r
+  OpCode.Question.Header.Prompt = Prompt;\r
+  OpCode.Question.Header.Help   = Help;\r
+  OpCode.Question.Flags         = QuestionFlags;\r
+  OpCode.QuestionConfig         = QuestionConfig;\r
+\r
+  return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_ACTION_OP, sizeof (OpCode));\r
+}\r
+\r
+/**\r
+  Create EFI_IFR_SUBTITLE_OP opcode.\r
+\r
+  If OpCodeHandle is NULL, then ASSERT().\r
+  If any reserved bits are set in Flags, then ASSERT().\r
+  If Scope > 1, then ASSERT().\r
+\r
+  @param[in]  OpCodeHandle  Handle to the buffer of opcodes.\r
+  @param[in]  Prompt      String ID for Prompt\r
+  @param[in]  Help        String ID for Help\r
+  @param[in]  Flags       Subtitle opcode flags\r
+  @param[in]  Scope       1 if this opcpde is the beginning of a new scope.\r
+                          0 if this opcode is within the current scope.\r
+\r
+  @retval NULL   There is not enough space left in Buffer to add the opcode.\r
+  @retval Other  A pointer to the created opcode.\r
 \r
 **/\r
+UINT8 *\r
+EFIAPI\r
+HiiCreateSubTitleOpCode (\r
+  IN VOID           *OpCodeHandle,\r
+  IN EFI_STRING_ID  Prompt,\r
+  IN EFI_STRING_ID  Help,\r
+  IN UINT8          Flags,\r
+  IN UINT8          Scope\r
+  )\r
+{\r
+  EFI_IFR_SUBTITLE  OpCode;\r
+\r
+  ASSERT (Scope <= 1);\r
+  ASSERT ((Flags & (~(EFI_IFR_FLAGS_HORIZONTAL))) == 0);\r
 \r
-#include "InternalHiiLib.h"\r
+  ZeroMem (&OpCode, sizeof (OpCode));\r
+  OpCode.Statement.Prompt = Prompt;\r
+  OpCode.Statement.Help   = Help;\r
+  OpCode.Flags            = Flags;\r
 \r
-CONST EFI_HII_DATABASE_PROTOCOL   *mHiiDatabaseProt = NULL;\r
-CONST EFI_HII_STRING_PROTOCOL     *mHiiStringProt = NULL;\r
+  return InternalHiiCreateOpCodeExtended (\r
+           OpCodeHandle,\r
+           &OpCode,\r
+           EFI_IFR_SUBTITLE_OP,\r
+           sizeof (OpCode),\r
+           0,\r
+           Scope\r
+           );\r
+}\r
 \r
 /**\r
-  This function locate Hii relative protocols for later usage.\r
-    \r
-  The constructor function caches the protocol pointer of HII Database Protocol\r
-  and Hii String Protocol.\r
-  \r
-  It will ASSERT() if either of the protocol can't be located.\r
+  Create EFI_IFR_REF_OP opcode.\r
 \r
-  @param  ImageHandle   The firmware allocated handle for the EFI image.\r
-  @param  SystemTable   A pointer to the EFI System Table.\r
+  If OpCodeHandle is NULL, then ASSERT().\r
+  If any reserved bits are set in QuestionFlags, then ASSERT().\r
 \r
-  @retval EFI_SUCCESS   The constructor always returns EFI_SUCCESS.\r
+  @param[in]  OpCodeHandle   Handle to the buffer of opcodes.\r
+  @param[in]  FormId         Destination Form ID\r
+  @param[in]  Prompt         String ID for Prompt\r
+  @param[in]  Help           String ID for Help\r
+  @param[in]  QuestionFlags  Flags in Question Header\r
+  @param[in]  QuestionId     Question ID\r
+\r
+  @retval NULL   There is not enough space left in Buffer to add the opcode.\r
+  @retval Other  A pointer to the created opcode.\r
 \r
 **/\r
-EFI_STATUS\r
+UINT8 *\r
 EFIAPI\r
-HiiLibConstructor (\r
-  IN EFI_HANDLE        ImageHandle,\r
-  IN EFI_SYSTEM_TABLE  *SystemTable\r
+HiiCreateGotoOpCode (\r
+  IN VOID             *OpCodeHandle,\r
+  IN EFI_FORM_ID      FormId,\r
+  IN EFI_STRING_ID    Prompt,\r
+  IN EFI_STRING_ID    Help,\r
+  IN UINT8            QuestionFlags,\r
+  IN EFI_QUESTION_ID  QuestionId\r
   )\r
 {\r
-  EFI_STATUS  Status;\r
+  EFI_IFR_REF  OpCode;\r
 \r
-  Status = gBS->LocateProtocol (&gEfiHiiDatabaseProtocolGuid, NULL, (VOID **) &mHiiDatabaseProt);\r
-  ASSERT_EFI_ERROR (Status);\r
+  ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED))) == 0);\r
 \r
-  Status = gBS->LocateProtocol (&gEfiHiiStringProtocolGuid, NULL, (VOID **) &mHiiStringProt);\r
-  ASSERT_EFI_ERROR (Status);\r
+  ZeroMem (&OpCode, sizeof (OpCode));\r
+  OpCode.Question.Header.Prompt = Prompt;\r
+  OpCode.Question.Header.Help   = Help;\r
+  OpCode.Question.QuestionId    = QuestionId;\r
+  OpCode.Question.Flags         = QuestionFlags;\r
+  OpCode.FormId                 = FormId;\r
 \r
-  return EFI_SUCCESS;\r
+  return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_REF_OP, sizeof (OpCode));\r
 }\r
 \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
+  Create EFI_IFR_REF_OP, EFI_IFR_REF2_OP, EFI_IFR_REF3_OP and EFI_IFR_REF4_OP opcode.\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
+  When RefDevicePath is not zero, EFI_IFR_REF4 opcode will be created.\r
+  When RefDevicePath is zero and RefFormSetId is not NULL, EFI_IFR_REF3 opcode will be created.\r
+  When RefDevicePath is zero, RefFormSetId is NULL and RefQuestionId is not zero, EFI_IFR_REF2 opcode will be created.\r
+  When RefDevicePath is zero, RefFormSetId is NULL and RefQuestionId is zero, EFI_IFR_REF opcode will be created.\r
 \r
-  If there is not enough resource for the new package list,\r
-  the function will ASSERT.\r
+  If OpCodeHandle is NULL, then ASSERT().\r
+  If any reserved bits are set in QuestionFlags, 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[in]  OpCodeHandle   The handle to the buffer of opcodes.\r
+  @param[in]  RefFormId      The Destination Form ID.\r
+  @param[in]  Prompt         The string ID for Prompt.\r
+  @param[in]  Help           The string ID for Help.\r
+  @param[in]  QuestionFlags  The flags in Question Header\r
+  @param[in]  QuestionId     Question ID.\r
+  @param[in]  RefQuestionId  The question on the form to which this link is referring.\r
+                             If its value is zero, then the link refers to the top of the form.\r
+  @param[in]  RefFormSetId   The form set to which this link is referring. If its value is NULL, and RefDevicePath is\r
+                             zero, then the link is to the current form set.\r
+  @param[in]  RefDevicePath  The string identifier that specifies the string containing the text representation of\r
+                             the device path to which the form set containing the form specified by FormId.\r
+                             If its value is zero, then the link refers to the current page.\r
 \r
-  @return The pointer to the package list header.\r
+  @retval NULL   There is not enough space left in Buffer to add the opcode.\r
+  @retval Other  A pointer to the created opcode.\r
 \r
 **/\r
-EFI_HII_PACKAGE_LIST_HEADER *\r
-InternalHiiLibPreparePackages (\r
-  IN UINTN           NumberOfPackages,\r
-  IN CONST EFI_GUID  *GuidId,\r
-  IN VA_LIST         Marker\r
+UINT8 *\r
+EFIAPI\r
+HiiCreateGotoExOpCode (\r
+  IN VOID             *OpCodeHandle,\r
+  IN EFI_FORM_ID      RefFormId,\r
+  IN EFI_STRING_ID    Prompt,\r
+  IN EFI_STRING_ID    Help,\r
+  IN UINT8            QuestionFlags,\r
+  IN EFI_QUESTION_ID  QuestionId,\r
+  IN EFI_QUESTION_ID  RefQuestionId,\r
+  IN EFI_GUID         *RefFormSetId,    OPTIONAL\r
+  IN EFI_STRING_ID    RefDevicePath\r
   )\r
 {\r
-  EFI_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_IFR_REF4  OpCode;\r
+  UINTN         OpCodeSize;\r
 \r
-  MarkerBackup = Marker;\r
+  ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED))) == 0);\r
 \r
-  //\r
-  // Count the length of the final package list.\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
+  ZeroMem (&OpCode, sizeof (OpCode));\r
+  OpCode.Question.Header.Prompt = Prompt;\r
+  OpCode.Question.Header.Help   = Help;\r
+  OpCode.Question.QuestionId    = QuestionId;\r
+  OpCode.Question.Flags         = QuestionFlags;\r
+  OpCode.FormId                 = RefFormId;\r
+  OpCode.QuestionId             = RefQuestionId;\r
+  OpCode.DevicePath             = RefDevicePath;\r
+  if (RefFormSetId != NULL) {\r
+    CopyMem (&OpCode.FormSetId, RefFormSetId, sizeof (OpCode.FormSetId));\r
   }\r
 \r
   //\r
-  // 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
-  \r
-  CopyGuid (&PackageListHeader->PackageListGuid, GuidId);\r
-  PackageListHeader->PackageLength = PackageListLength;\r
-\r
-  PackageListData = ((UINT8 *) PackageListHeader) + sizeof (EFI_HII_PACKAGE_LIST_HEADER);\r
-\r
-  Marker = MarkerBackup;\r
-  //\r
-  // Prepare the final package list.\r
+  // Cacluate OpCodeSize based on the input Ref value.\r
+  // Try to use the small OpCode to save size.\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
+  OpCodeSize = sizeof (EFI_IFR_REF);\r
+  if (RefDevicePath != 0) {\r
+    OpCodeSize = sizeof (EFI_IFR_REF4);\r
+  } else if (RefFormSetId != NULL) {\r
+    OpCodeSize = sizeof (EFI_IFR_REF3);\r
+  } else if (RefQuestionId != 0) {\r
+    OpCodeSize = sizeof (EFI_IFR_REF2);\r
   }\r
 \r
-  //\r
-  // Append EFI_HII_PACKAGE_END\r
-  //\r
-  PackageHeader.Type = EFI_HII_PACKAGE_END;\r
-  PackageHeader.Length = sizeof (EFI_HII_PACKAGE_HEADER);\r
-  CopyMem (PackageListData, &PackageHeader, PackageHeader.Length);\r
-\r
-  return PackageListHeader;\r
+  return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_REF_OP, OpCodeSize);\r
 }\r
 \r
 /**\r
-  Assemble EFI_HII_PACKAGE_LIST according to the passed in packages.\r
+  Create EFI_IFR_CHECKBOX_OP opcode.\r
 \r
-  If GuidId is NULL, then ASSERT.\r
-  If not enough resource to complete the operation, then ASSERT.\r
+  If OpCodeHandle is NULL, then ASSERT().\r
+  If any reserved bits are set in QuestionFlags, then ASSERT().\r
+  If any reserved bits are set in CheckBoxFlags, then ASSERT().\r
 \r
-  @param  NumberOfPackages       Number of packages.\r
-  @param  GuidId                 Package GUID.\r
-  @param  ...                    Variable argument list for packages to be assembled.\r
+  @param[in]  OpCodeHandle          Handle to the buffer of opcodes.\r
+  @param[in]  QuestionId            Question ID\r
+  @param[in]  VarStoreId            Storage ID\r
+  @param[in]  VarOffset             Offset in Storage or String ID of the name (VarName)\r
+                                    for this name/value pair.\r
+  @param[in]  Prompt                String ID for Prompt\r
+  @param[in]  Help                  String ID for Help\r
+  @param[in]  QuestionFlags         Flags in Question Header\r
+  @param[in]  CheckBoxFlags         Flags for checkbox opcode\r
+  @param[in]  DefaultsOpCodeHandle  Handle for a buffer of DEFAULT opcodes.  This\r
+                                    is an optional parameter that may be NULL.\r
 \r
-  @return Pointer of EFI_HII_PACKAGE_LIST_HEADER.\r
+  @retval NULL   There is not enough space left in Buffer to add the opcode.\r
+  @retval Other  A pointer to the created opcode.\r
 \r
 **/\r
-EFI_HII_PACKAGE_LIST_HEADER *\r
+UINT8 *\r
 EFIAPI\r
-HiiLibPreparePackageList (\r
-  IN UINTN                    NumberOfPackages,\r
-  IN CONST EFI_GUID           *GuidId,\r
-  ...\r
+HiiCreateCheckBoxOpCode (\r
+  IN VOID             *OpCodeHandle,\r
+  IN EFI_QUESTION_ID  QuestionId,\r
+  IN EFI_VARSTORE_ID  VarStoreId,\r
+  IN UINT16           VarOffset,\r
+  IN EFI_STRING_ID    Prompt,\r
+  IN EFI_STRING_ID    Help,\r
+  IN UINT8            QuestionFlags,\r
+  IN UINT8            CheckBoxFlags,\r
+  IN VOID             *DefaultsOpCodeHandle  OPTIONAL\r
   )\r
 {\r
-  EFI_HII_PACKAGE_LIST_HEADER *PackageListHeader;\r
-  VA_LIST                     Marker;\r
+  EFI_IFR_CHECKBOX  OpCode;\r
+  UINTN             Position;\r
 \r
-  ASSERT (GuidId != NULL);\r
+  ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED))) == 0);\r
 \r
-  VA_START (Marker, GuidId);\r
-  PackageListHeader = InternalHiiLibPreparePackages (NumberOfPackages, GuidId, Marker);\r
-  VA_END (Marker);\r
+  ZeroMem (&OpCode, sizeof (OpCode));\r
+  OpCode.Question.QuestionId             = QuestionId;\r
+  OpCode.Question.VarStoreId             = VarStoreId;\r
+  OpCode.Question.VarStoreInfo.VarOffset = VarOffset;\r
+  OpCode.Question.Header.Prompt          = Prompt;\r
+  OpCode.Question.Header.Help            = Help;\r
+  OpCode.Question.Flags                  = QuestionFlags;\r
+  OpCode.Flags                           = CheckBoxFlags;\r
 \r
-  return PackageListHeader;\r
-}\r
+  if (DefaultsOpCodeHandle == NULL) {\r
+    return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_CHECKBOX_OP, sizeof (OpCode));\r
+  }\r
 \r
+  Position = InternalHiiOpCodeHandlePosition (OpCodeHandle);\r
+  InternalHiiCreateOpCodeExtended (OpCodeHandle, &OpCode, EFI_IFR_CHECKBOX_OP, sizeof (OpCode), 0, 1);\r
+  InternalHiiAppendOpCodes (OpCodeHandle, DefaultsOpCodeHandle);\r
+  HiiCreateEndOpCode (OpCodeHandle);\r
+  return InternalHiiOpCodeHandleBuffer (OpCodeHandle) + Position;\r
+}\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
-  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
+  Create EFI_IFR_NUMERIC_OP opcode.\r
 \r
-  If HiiHandle is NULL, then ASSERT.\r
+  If OpCodeHandle is NULL, then ASSERT().\r
+  If any reserved bits are set in QuestionFlags, then ASSERT().\r
+  If any reserved bits are set in NumericFlags, then ASSERT().\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
+  @param[in]  OpCodeHandle          Handle to the buffer of opcodes.\r
+  @param[in]  QuestionId            Question ID\r
+  @param[in]  VarStoreId            Storage ID\r
+  @param[in]  VarOffset             Offset in Storage or String ID of the name (VarName)\r
+                                    for this name/value pair.\r
+  @param[in]  Prompt                String ID for Prompt\r
+  @param[in]  Help                  String ID for Help\r
+  @param[in]  QuestionFlags         Flags in Question Header\r
+  @param[in]  NumericFlags          Flags for numeric opcode\r
+  @param[in]  Minimum               Numeric minimum value\r
+  @param[in]  Maximum               Numeric maximum value\r
+  @param[in]  Step                  Numeric step for edit\r
+  @param[in]  DefaultsOpCodeHandle  Handle for a buffer of DEFAULT opcodes.  This\r
+                                    is an optional parameter that may be NULL.\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
+  @retval NULL   There is not enough space left in Buffer to add the opcode.\r
+  @retval Other  A pointer to the created opcode.\r
 \r
 **/\r
-EFI_STATUS\r
+UINT8 *\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
+HiiCreateNumericOpCode (\r
+  IN VOID             *OpCodeHandle,\r
+  IN EFI_QUESTION_ID  QuestionId,\r
+  IN EFI_VARSTORE_ID  VarStoreId,\r
+  IN UINT16           VarOffset,\r
+  IN EFI_STRING_ID    Prompt,\r
+  IN EFI_STRING_ID    Help,\r
+  IN UINT8            QuestionFlags,\r
+  IN UINT8            NumericFlags,\r
+  IN UINT64           Minimum,\r
+  IN UINT64           Maximum,\r
+  IN UINT64           Step,\r
+  IN VOID             *DefaultsOpCodeHandle  OPTIONAL\r
   )\r
 {\r
-  VA_LIST                   Args;\r
-  EFI_HII_PACKAGE_LIST_HEADER *PackageListHeader;\r
-  EFI_STATUS                Status;\r
+  EFI_IFR_NUMERIC  OpCode;\r
+  UINTN            Position;\r
+  UINTN            Length;\r
 \r
-  ASSERT (HiiHandle != NULL);\r
+  ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED))) == 0);\r
 \r
-  VA_START (Args, HiiHandle);\r
-  PackageListHeader = InternalHiiLibPreparePackages (NumberOfPackages, GuidId, Args);\r
+  Length  = 0;\r
+  ZeroMem (&OpCode, sizeof (OpCode));\r
+  OpCode.Question.QuestionId             = QuestionId;\r
+  OpCode.Question.VarStoreId             = VarStoreId;\r
+  OpCode.Question.VarStoreInfo.VarOffset = VarOffset;\r
+  OpCode.Question.Header.Prompt          = Prompt;\r
+  OpCode.Question.Header.Help            = Help;\r
+  OpCode.Question.Flags                  = QuestionFlags;\r
+  OpCode.Flags                           = NumericFlags;\r
 \r
-  Status      = mHiiDatabaseProt->NewPackageList (mHiiDatabaseProt, PackageListHeader, DriverHandle, HiiHandle);\r
-  if (HiiHandle != NULL) {\r
-    if (EFI_ERROR (Status)) {\r
-      *HiiHandle = NULL;\r
-    }\r
+  switch (NumericFlags & EFI_IFR_NUMERIC_SIZE) {\r
+  case EFI_IFR_NUMERIC_SIZE_1:\r
+    OpCode.data.u8.MinValue = (UINT8)Minimum;\r
+    OpCode.data.u8.MaxValue = (UINT8)Maximum;\r
+    OpCode.data.u8.Step     = (UINT8)Step;\r
+    Length                  = 3;\r
+    break;\r
+\r
+  case EFI_IFR_NUMERIC_SIZE_2:\r
+    OpCode.data.u16.MinValue = (UINT16)Minimum;\r
+    OpCode.data.u16.MaxValue = (UINT16)Maximum;\r
+    OpCode.data.u16.Step     = (UINT16)Step;\r
+    Length                   = 6;\r
+    break;\r
+\r
+  case EFI_IFR_NUMERIC_SIZE_4:\r
+    OpCode.data.u32.MinValue = (UINT32)Minimum;\r
+    OpCode.data.u32.MaxValue = (UINT32)Maximum;\r
+    OpCode.data.u32.Step     = (UINT32)Step;\r
+    Length                   = 12;\r
+    break;\r
+\r
+  case EFI_IFR_NUMERIC_SIZE_8:\r
+    OpCode.data.u64.MinValue = Minimum;\r
+    OpCode.data.u64.MaxValue = Maximum;\r
+    OpCode.data.u64.Step     = Step;\r
+    Length                   = 24;\r
+    break;\r
   }\r
 \r
-  FreePool (PackageListHeader);\r
-  VA_END (Args);\r
-  \r
-  return Status;\r
+  Length += OFFSET_OF (EFI_IFR_NUMERIC, data);\r
+\r
+  if (DefaultsOpCodeHandle == NULL) {\r
+    return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_NUMERIC_OP, Length);\r
+  }\r
+\r
+  Position = InternalHiiOpCodeHandlePosition (OpCodeHandle);\r
+  InternalHiiCreateOpCodeExtended (OpCodeHandle, &OpCode, EFI_IFR_NUMERIC_OP, Length, 0, 1);\r
+  InternalHiiAppendOpCodes (OpCodeHandle, DefaultsOpCodeHandle);\r
+  HiiCreateEndOpCode (OpCodeHandle);\r
+  return InternalHiiOpCodeHandleBuffer (OpCodeHandle) + Position;\r
 }\r
 \r
 /**\r
-  Removes a package list from the default HII database.\r
+  Create EFI_IFR_STRING_OP opcode.\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 OpCodeHandle is NULL, then ASSERT().\r
+  If any reserved bits are set in QuestionFlags, then ASSERT().\r
+  If any reserved bits are set in StringFlags, 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]  OpCodeHandle          Handle to the buffer of opcodes.\r
+  @param[in]  QuestionId            Question ID\r
+  @param[in]  VarStoreId            Storage ID\r
+  @param[in]  VarOffset             Offset in Storage or String ID of the name (VarName)\r
+                                    for this name/value pair.\r
+  @param[in]  Prompt                String ID for Prompt\r
+  @param[in]  Help                  String ID for Help\r
+  @param[in]  QuestionFlags         Flags in Question Header\r
+  @param[in]  StringFlags           Flags for string opcode\r
+  @param[in]  MinSize               String minimum length\r
+  @param[in]  MaxSize               String maximum length\r
+  @param[in]  DefaultsOpCodeHandle  Handle for a buffer of DEFAULT opcodes.  This\r
+                                    is an optional parameter that may be NULL.\r
+\r
+  @retval NULL   There is not enough space left in Buffer to add the opcode.\r
+  @retval Other  A pointer to the created opcode.\r
 \r
 **/\r
-VOID\r
+UINT8 *\r
 EFIAPI\r
-HiiLibRemovePackages (\r
-  IN      EFI_HII_HANDLE      HiiHandle\r
+HiiCreateStringOpCode (\r
+  IN VOID             *OpCodeHandle,\r
+  IN EFI_QUESTION_ID  QuestionId,\r
+  IN EFI_VARSTORE_ID  VarStoreId,\r
+  IN UINT16           VarOffset,\r
+  IN EFI_STRING_ID    Prompt,\r
+  IN EFI_STRING_ID    Help,\r
+  IN UINT8            QuestionFlags,\r
+  IN UINT8            StringFlags,\r
+  IN UINT8            MinSize,\r
+  IN UINT8            MaxSize,\r
+  IN VOID             *DefaultsOpCodeHandle  OPTIONAL\r
   )\r
 {\r
-  EFI_STATUS Status;\r
-  ASSERT (IsHiiHandleRegistered (HiiHandle));\r
+  EFI_IFR_STRING  OpCode;\r
+  UINTN           Position;\r
 \r
-  Status = mHiiDatabaseProt->RemovePackageList (mHiiDatabaseProt, HiiHandle);\r
-  ASSERT_EFI_ERROR (Status);\r
-}\r
+  ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED))) == 0);\r
+\r
+  ZeroMem (&OpCode, sizeof (OpCode));\r
+  OpCode.Question.Header.Prompt          = Prompt;\r
+  OpCode.Question.Header.Help            = Help;\r
+  OpCode.Question.QuestionId             = QuestionId;\r
+  OpCode.Question.VarStoreId             = VarStoreId;\r
+  OpCode.Question.VarStoreInfo.VarOffset = VarOffset;\r
+  OpCode.Question.Flags                  = QuestionFlags;\r
+  OpCode.MinSize                         = MinSize;\r
+  OpCode.MaxSize                         = MaxSize;\r
+  OpCode.Flags                           = (UINT8) (StringFlags & EFI_IFR_STRING_MULTI_LINE);\r
+\r
+  if (DefaultsOpCodeHandle == NULL) {\r
+    return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_STRING_OP, sizeof (OpCode));\r
+  }\r
 \r
+  Position = InternalHiiOpCodeHandlePosition (OpCodeHandle);\r
+  InternalHiiCreateOpCodeExtended (OpCodeHandle, &OpCode, EFI_IFR_STRING_OP, sizeof (OpCode), 0, 1);\r
+  InternalHiiAppendOpCodes (OpCodeHandle, DefaultsOpCodeHandle);\r
+  HiiCreateEndOpCode (OpCodeHandle);\r
+  return InternalHiiOpCodeHandleBuffer (OpCodeHandle) + Position;\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
+  Create EFI_IFR_ONE_OF_OP opcode.\r
 \r
-  If HandleBufferLength is NULL, then ASSERT.\r
-  If HiiHandleBuffer is NULL, then ASSERT.\r
+  If OpCodeHandle is NULL, then ASSERT().\r
+  If any reserved bits are set in QuestionFlags, then ASSERT().\r
+  If any reserved bits are set in OneOfFlags, 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
+  @param[in]  OpCodeHandle          Handle to the buffer of opcodes.\r
+  @param[in]  QuestionId            Question ID\r
+  @param[in]  VarStoreId            Storage ID\r
+  @param[in]  VarOffset             Offset in Storage or String ID of the name (VarName)\r
+                                    for this name/value pair.\r
+  @param[in]  Prompt                String ID for Prompt\r
+  @param[in]  Help                  String ID for Help\r
+  @param[in]  QuestionFlags         Flags in Question Header\r
+  @param[in]  OneOfFlags            Flags for oneof opcode\r
+  @param[in]  OptionsOpCodeHandle   Handle for a buffer of ONE_OF_OPTION opcodes.\r
+  @param[in]  DefaultsOpCodeHandle  Handle for a buffer of DEFAULT opcodes.  This\r
+                                    is an optional parameter that may be NULL.\r
 \r
-  @retval EFI_SUCCESS            Get an array of Hii Handles successfully.\r
+  @retval NULL   There is not enough space left in Buffer to add the opcode.\r
+  @retval Other  A pointer to the created opcode.\r
 \r
 **/\r
-EFI_STATUS\r
+UINT8 *\r
 EFIAPI\r
-HiiLibGetHiiHandles (\r
-  IN OUT UINTN                     *HandleBufferLength,\r
-  OUT    EFI_HII_HANDLE            **HiiHandleBuffer\r
+HiiCreateOneOfOpCode (\r
+  IN VOID             *OpCodeHandle,\r
+  IN EFI_QUESTION_ID  QuestionId,\r
+  IN EFI_VARSTORE_ID  VarStoreId,\r
+  IN UINT16           VarOffset,\r
+  IN EFI_STRING_ID    Prompt,\r
+  IN EFI_STRING_ID    Help,\r
+  IN UINT8            QuestionFlags,\r
+  IN UINT8            OneOfFlags,\r
+  IN VOID             *OptionsOpCodeHandle,\r
+  IN VOID             *DefaultsOpCodeHandle  OPTIONAL\r
   )\r
 {\r
-  EFI_STATUS  Status;\r
+  EFI_IFR_ONE_OF  OpCode;\r
+  UINTN           Position;\r
+  UINTN           Length;\r
 \r
-  ASSERT (HandleBufferLength != NULL);\r
-  ASSERT (HiiHandleBuffer != NULL);\r
+  ASSERT (OptionsOpCodeHandle != NULL);\r
+  ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED | EFI_IFR_FLAG_OPTIONS_ONLY))) == 0);\r
 \r
-  *HandleBufferLength = 0;\r
-  *HiiHandleBuffer = NULL;\r
+  ZeroMem (&OpCode, sizeof (OpCode));\r
+  OpCode.Question.Header.Prompt          = Prompt;\r
+  OpCode.Question.Header.Help            = Help;\r
+  OpCode.Question.QuestionId             = QuestionId;\r
+  OpCode.Question.VarStoreId             = VarStoreId;\r
+  OpCode.Question.VarStoreInfo.VarOffset = VarOffset;\r
+  OpCode.Question.Flags                  = QuestionFlags;\r
+  OpCode.Flags                           = OneOfFlags;\r
 \r
-  //\r
-  // Try to find the actual buffer size for HiiHandle Buffer.\r
-  //\r
-  Status = mHiiDatabaseProt->ListPackageLists (\r
-                                 mHiiDatabaseProt,\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 = mHiiDatabaseProt->ListPackageLists (\r
-                                     mHiiDatabaseProt,\r
-                                     EFI_HII_PACKAGE_TYPE_ALL,\r
-                                     NULL,\r
-                                     HandleBufferLength,\r
-                                     *HiiHandleBuffer\r
-                                     );\r
-\r
-      if (EFI_ERROR (Status)) {\r
-        FreePool (*HiiHandleBuffer);\r
-        *HiiHandleBuffer = NULL;\r
-      }\r
-  }\r
+  Length  = OFFSET_OF (EFI_IFR_ONE_OF, data);\r
+  Length += (1 << (OneOfFlags & EFI_IFR_NUMERIC_SIZE)) * 3;\r
 \r
-  return Status;\r
+  Position = InternalHiiOpCodeHandlePosition (OpCodeHandle);\r
+  InternalHiiCreateOpCodeExtended (OpCodeHandle, &OpCode, EFI_IFR_ONE_OF_OP, Length, 0, 1);\r
+  InternalHiiAppendOpCodes (OpCodeHandle, OptionsOpCodeHandle);\r
+  if (DefaultsOpCodeHandle != NULL) {\r
+    InternalHiiAppendOpCodes (OpCodeHandle, DefaultsOpCodeHandle);\r
+  }\r
+  HiiCreateEndOpCode (OpCodeHandle);\r
+  return InternalHiiOpCodeHandleBuffer (OpCodeHandle) + Position;\r
 }\r
 \r
 /**\r
-  Extract Hii package list GUID for given HII handle.\r
+  Create EFI_IFR_ORDERED_LIST_OP opcode.\r
 \r
-  If HiiHandle could not be found in the default HII database, then ASSERT.\r
-  If Guid is NULL, then ASSERT.\r
+  If OpCodeHandle is NULL, then ASSERT().\r
+  If any reserved bits are set in QuestionFlags, then ASSERT().\r
+  If any reserved bits are set in OrderedListFlags, then ASSERT().\r
 \r
-  @param  Handle              Hii handle\r
-  @param  Guid                Package list GUID\r
+  @param[in]  OpCodeHandle          Handle to the buffer of opcodes.\r
+  @param[in]  QuestionId            Question ID\r
+  @param[in]  VarStoreId            Storage ID\r
+  @param[in]  VarOffset             Offset in Storage or String ID of the name (VarName)\r
+                                    for this name/value pair.\r
+  @param[in]  Prompt                String ID for Prompt\r
+  @param[in]  Help                  String ID for Help\r
+  @param[in]  QuestionFlags         Flags in Question Header\r
+  @param[in]  OrderedListFlags      Flags for ordered list opcode\r
+  @param[in]  DataType              Type for option value\r
+  @param[in]  MaxContainers         Maximum count for options in this ordered list\r
+  @param[in]  OptionsOpCodeHandle   Handle for a buffer of ONE_OF_OPTION opcodes.\r
+  @param[in]  DefaultsOpCodeHandle  Handle for a buffer of DEFAULT opcodes.  This\r
+                                    is an optional parameter that may be NULL.\r
 \r
-  @retval EFI_SUCCESS            Successfully extract GUID from Hii database.\r
+  @retval NULL   There is not enough space left in Buffer to add the opcode.\r
+  @retval Other  A pointer to the created opcode.\r
 \r
 **/\r
-EFI_STATUS\r
+UINT8 *\r
 EFIAPI\r
-HiiLibExtractGuidFromHiiHandle (\r
-  IN      EFI_HII_HANDLE      Handle,\r
-  OUT     EFI_GUID            *Guid\r
+HiiCreateOrderedListOpCode (\r
+  IN VOID             *OpCodeHandle,\r
+  IN EFI_QUESTION_ID  QuestionId,\r
+  IN EFI_VARSTORE_ID  VarStoreId,\r
+  IN UINT16           VarOffset,\r
+  IN EFI_STRING_ID    Prompt,\r
+  IN EFI_STRING_ID    Help,\r
+  IN UINT8            QuestionFlags,\r
+  IN UINT8            OrderedListFlags,\r
+  IN UINT8            DataType,\r
+  IN UINT8            MaxContainers,\r
+  IN VOID             *OptionsOpCodeHandle,\r
+  IN VOID             *DefaultsOpCodeHandle  OPTIONAL\r
   )\r
 {\r
-  EFI_STATUS                   Status;\r
-  UINTN                        BufferSize;\r
-  EFI_HII_PACKAGE_LIST_HEADER  *HiiPackageList;\r
-\r
-  ASSERT (Guid != NULL);\r
-  ASSERT (IsHiiHandleRegistered (Handle));\r
+  EFI_IFR_ORDERED_LIST  OpCode;\r
+  UINTN                 Position;\r
 \r
-  //\r
-  // Get HII PackageList\r
-  //\r
-  BufferSize = 0;\r
-  HiiPackageList = NULL;\r
+  ASSERT (OptionsOpCodeHandle != NULL);\r
+  ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED | EFI_IFR_FLAG_OPTIONS_ONLY))) == 0);\r
 \r
-  Status = mHiiDatabaseProt->ExportPackageLists (mHiiDatabaseProt, 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
+  ZeroMem (&OpCode, sizeof (OpCode));\r
+  OpCode.Question.Header.Prompt          = Prompt;\r
+  OpCode.Question.Header.Help            = Help;\r
+  OpCode.Question.QuestionId             = QuestionId;\r
+  OpCode.Question.VarStoreId             = VarStoreId;\r
+  OpCode.Question.VarStoreInfo.VarOffset = VarOffset;\r
+  OpCode.Question.Flags                  = QuestionFlags;\r
+  OpCode.MaxContainers                   = MaxContainers;\r
+  OpCode.Flags                           = OrderedListFlags;\r
 \r
-    Status = mHiiDatabaseProt->ExportPackageLists (mHiiDatabaseProt, Handle, &BufferSize, HiiPackageList);\r
-  }\r
-  if (EFI_ERROR (Status)) {\r
-    FreePool (HiiPackageList);\r
-    return Status;\r
+  Position = InternalHiiOpCodeHandlePosition (OpCodeHandle);\r
+  InternalHiiCreateOpCodeExtended (OpCodeHandle, &OpCode, EFI_IFR_ORDERED_LIST_OP, sizeof (OpCode), 0, 1);\r
+  InternalHiiAppendOpCodes (OpCodeHandle, OptionsOpCodeHandle);\r
+  if (DefaultsOpCodeHandle != NULL) {\r
+    InternalHiiAppendOpCodes (OpCodeHandle, DefaultsOpCodeHandle);\r
   }\r
-\r
-  //\r
-  // Extract GUID\r
-  //\r
-  CopyGuid (Guid, &HiiPackageList->PackageListGuid);\r
-\r
-  FreePool (HiiPackageList);\r
-\r
-  return EFI_SUCCESS;\r
+  HiiCreateEndOpCode (OpCodeHandle);\r
+  return InternalHiiOpCodeHandleBuffer (OpCodeHandle) + Position;\r
 }\r
 \r
 /**\r
-  Find HII Handle in the default HII database associated with given Device Path.\r
+  Create EFI_IFR_TEXT_OP opcode.\r
 \r
-  If DevicePath is NULL, then ASSERT.\r
+  If OpCodeHandle is NULL, then ASSERT().\r
 \r
-  @param  DevicePath             Device Path associated with the HII package list\r
-                                 handle.\r
+  @param[in]  OpCodeHandle  Handle to the buffer of opcodes.\r
+  @param[in]  Prompt        String ID for Prompt.\r
+  @param[in]  Help          String ID for Help.\r
+  @param[in]  TextTwo       String ID for TextTwo.\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   There is not enough space left in Buffer to add the opcode.\r
+  @retval Other  A pointer to the created opcode.\r
 \r
 **/\r
-EFI_HII_HANDLE\r
+UINT8 *\r
 EFIAPI\r
-HiiLibDevicePathToHiiHandle (\r
-  IN EFI_DEVICE_PATH_PROTOCOL   *DevicePath\r
+HiiCreateTextOpCode (\r
+  IN VOID           *OpCodeHandle,\r
+  IN EFI_STRING_ID  Prompt,\r
+  IN EFI_STRING_ID  Help,\r
+  IN EFI_STRING_ID  TextTwo\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
+  EFI_IFR_TEXT  OpCode;\r
 \r
-  ASSERT (DevicePath != NULL);\r
+  ZeroMem (&OpCode, sizeof (OpCode));\r
+  OpCode.Statement.Prompt = Prompt;\r
+  OpCode.Statement.Help   = Help;\r
+  OpCode.TextTwo          = TextTwo;\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
+  return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_TEXT_OP, sizeof (OpCode));\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
+  Create EFI_IFR_DATE_OP opcode.\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
+  If OpCodeHandle is NULL, then ASSERT().\r
+  If any reserved bits are set in QuestionFlags, then ASSERT().\r
+  If any reserved bits are set in DateFlags, then ASSERT().\r
 \r
-  if (DriverHandle == NULL) {\r
-    return NULL;\r
-  }\r
+  @param[in]  OpCodeHandle          Handle to the buffer of opcodes.\r
+  @param[in]  QuestionId            Question ID\r
+  @param[in]  VarStoreId            Storage ID, optional. If DateFlags is not\r
+                                    QF_DATE_STORAGE_NORMAL, this parameter is ignored.\r
+  @param[in]  VarOffset             Offset in Storage or String ID of the name (VarName)\r
+                                    for this name/value pair, optional. If DateFlags is not\r
+                                    QF_DATE_STORAGE_NORMAL, this parameter is ignored.\r
+  @param[in]  Prompt                String ID for Prompt\r
+  @param[in]  Help                  String ID for Help\r
+  @param[in]  QuestionFlags         Flags in Question Header\r
+  @param[in]  DateFlags             Flags for date opcode\r
+  @param[in]  DefaultsOpCodeHandle  Handle for a buffer of DEFAULT opcodes.  This\r
+                                    is an optional parameter that may be 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 = mHiiDatabaseProt->ListPackageLists (\r
-                          mHiiDatabaseProt,\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 = mHiiDatabaseProt->ListPackageLists (\r
-                            mHiiDatabaseProt,\r
-                            EFI_HII_PACKAGE_TYPE_ALL,\r
-                            NULL,\r
-                            &BufferSize,\r
-                            HiiHandles\r
-                            );\r
-  }\r
+  @retval NULL   There is not enough space left in Buffer to add the opcode.\r
+  @retval Other  A pointer to the created opcode.\r
 \r
-  if (EFI_ERROR (Status)) {\r
-    FreePool (HiiHandles);\r
-    return NULL;\r
-  }\r
+**/\r
+UINT8 *\r
+EFIAPI\r
+HiiCreateDateOpCode (\r
+  IN VOID             *OpCodeHandle,\r
+  IN EFI_QUESTION_ID  QuestionId,\r
+  IN EFI_VARSTORE_ID  VarStoreId,   OPTIONAL\r
+  IN UINT16           VarOffset,    OPTIONAL\r
+  IN EFI_STRING_ID    Prompt,\r
+  IN EFI_STRING_ID    Help,\r
+  IN UINT8            QuestionFlags,\r
+  IN UINT8            DateFlags,\r
+  IN VOID             *DefaultsOpCodeHandle  OPTIONAL\r
+  )\r
+{\r
+  EFI_IFR_DATE    OpCode;\r
+  UINTN           Position;\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 = mHiiDatabaseProt->GetPackageListHandle (\r
-                            mHiiDatabaseProt,\r
-                            HiiHandles[Index],\r
-                            &Handle\r
-                            );\r
-    if (!EFI_ERROR (Status) && (Handle == DriverHandle)) {\r
-      HiiHandle = HiiHandles[Index];\r
-      break;\r
-    }\r
+  ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED))) == 0);\r
+  ASSERT ((DateFlags & (~(EFI_QF_DATE_YEAR_SUPPRESS | EFI_QF_DATE_MONTH_SUPPRESS | EFI_QF_DATE_DAY_SUPPRESS | EFI_QF_DATE_STORAGE))) == 0);\r
+\r
+  ZeroMem (&OpCode, sizeof (OpCode));\r
+  OpCode.Question.Header.Prompt          = Prompt;\r
+  OpCode.Question.Header.Help            = Help;\r
+  OpCode.Question.QuestionId             = QuestionId;\r
+  OpCode.Question.VarStoreId             = VarStoreId;\r
+  OpCode.Question.VarStoreInfo.VarOffset = VarOffset;\r
+  OpCode.Question.Flags                  = QuestionFlags;\r
+  OpCode.Flags                           = DateFlags;\r
+\r
+  if (DefaultsOpCodeHandle == NULL) {\r
+    return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_DATE_OP, sizeof (OpCode));\r
   }\r
 \r
-  FreePool (HiiHandles);\r
-  return HiiHandle;\r
+  Position = InternalHiiOpCodeHandlePosition (OpCodeHandle);\r
+  InternalHiiCreateOpCodeExtended (OpCodeHandle, &OpCode, EFI_IFR_DATE_OP, sizeof (OpCode), 0, 1);\r
+  InternalHiiAppendOpCodes (OpCodeHandle, DefaultsOpCodeHandle);\r
+  HiiCreateEndOpCode (OpCodeHandle);\r
+  return InternalHiiOpCodeHandleBuffer (OpCodeHandle) + Position;\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
+  Create EFI_IFR_TIME_OP opcode.\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
+  If OpCodeHandle is NULL, then ASSERT().\r
+  If any reserved bits are set in QuestionFlags, then ASSERT().\r
+  If any reserved bits are set in TimeFlags, then ASSERT().\r
 \r
-  @retval EFI_SUCCESS            Package exported.\r
+  @param[in]  OpCodeHandle          Handle to the buffer of opcodes.\r
+  @param[in]  QuestionId            Question ID\r
+  @param[in]  VarStoreId            Storage ID, optional. If TimeFlags is not\r
+                                    QF_TIME_STORAGE_NORMAL, this parameter is ignored.\r
+  @param[in]  VarOffset             Offset in Storage or String ID of the name (VarName)\r
+                                    for this name/value pair, optional. If TimeFlags is not\r
+                                    QF_TIME_STORAGE_NORMAL, this parameter is ignored.\r
+  @param[in]  Prompt                String ID for Prompt\r
+  @param[in]  Help                  String ID for Help\r
+  @param[in]  QuestionFlags         Flags in Question Header\r
+  @param[in]  TimeFlags             Flags for time opcode\r
+  @param[in]  DefaultsOpCodeHandle  Handle for a buffer of DEFAULT opcodes.  This\r
+                                    is an optional parameter that may be NULL.\r
 \r
-  @retval EFI_OUT_OF_RESOURCES   Not enought memory to complete the operations.\r
+  @retval NULL   There is not enough space left in Buffer to add the opcode.\r
+  @retval Other  A pointer to the created opcode.\r
 \r
 **/\r
-EFI_STATUS \r
+UINT8 *\r
 EFIAPI\r
-HiiLibExportPackageLists (\r
-  IN EFI_HII_HANDLE                    Handle,\r
-  OUT EFI_HII_PACKAGE_LIST_HEADER      **PackageListHeader,\r
-  OUT UINTN                            *PackageListSize\r
+HiiCreateTimeOpCode (\r
+  IN VOID             *OpCodeHandle,\r
+  IN EFI_QUESTION_ID  QuestionId,\r
+  IN EFI_VARSTORE_ID  VarStoreId,   OPTIONAL\r
+  IN UINT16           VarOffset,    OPTIONAL\r
+  IN EFI_STRING_ID    Prompt,\r
+  IN EFI_STRING_ID    Help,\r
+  IN UINT8            QuestionFlags,\r
+  IN UINT8            TimeFlags,\r
+  IN VOID             *DefaultsOpCodeHandle  OPTIONAL\r
   )\r
 {\r
-  EFI_STATUS                       Status;\r
-  UINTN                            Size;\r
-  EFI_HII_PACKAGE_LIST_HEADER      *PackageListHdr;\r
+  EFI_IFR_TIME    OpCode;\r
+  UINTN           Position;\r
 \r
-  ASSERT (PackageListSize != NULL);\r
-  ASSERT (PackageListHeader != NULL);\r
+  ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED))) == 0);\r
+  ASSERT ((TimeFlags & (~(QF_TIME_HOUR_SUPPRESS | QF_TIME_MINUTE_SUPPRESS | QF_TIME_SECOND_SUPPRESS | QF_TIME_STORAGE))) == 0);\r
 \r
-  if (Handle != NULL) {\r
-    ASSERT (IsHiiHandleRegistered (Handle));\r
-  }\r
-\r
-  Size = 0;\r
-  PackageListHdr = NULL;\r
-  Status = mHiiDatabaseProt->ExportPackageLists (\r
-                                      mHiiDatabaseProt,\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 = mHiiDatabaseProt->ExportPackageLists (\r
-                                          mHiiDatabaseProt,\r
-                                          Handle,\r
-                                          &Size,\r
-                                          PackageListHdr\r
-                                           );\r
-    }\r
-  }\r
+  ZeroMem (&OpCode, sizeof (OpCode));\r
+  OpCode.Question.Header.Prompt          = Prompt;\r
+  OpCode.Question.Header.Help            = Help;\r
+  OpCode.Question.QuestionId             = QuestionId;\r
+  OpCode.Question.VarStoreId             = VarStoreId;\r
+  OpCode.Question.VarStoreInfo.VarOffset = VarOffset;\r
+  OpCode.Question.Flags                  = QuestionFlags;\r
+  OpCode.Flags                           = TimeFlags;\r
 \r
-  if (!EFI_ERROR (Status)) {\r
-    *PackageListHeader = PackageListHdr;\r
-    *PackageListSize   = Size;\r
-  } else {\r
-    FreePool (PackageListHdr);\r
+  if (DefaultsOpCodeHandle == NULL) {\r
+    return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_TIME_OP, sizeof (OpCode));\r
   }\r
 \r
-  return Status;\r
+  Position = InternalHiiOpCodeHandlePosition (OpCodeHandle);\r
+  InternalHiiCreateOpCodeExtended (OpCodeHandle, &OpCode, EFI_IFR_TIME_OP, sizeof (OpCode), 0, 1);\r
+  InternalHiiAppendOpCodes (OpCodeHandle, DefaultsOpCodeHandle);\r
+  HiiCreateEndOpCode (OpCodeHandle);\r
+  return InternalHiiOpCodeHandleBuffer (OpCodeHandle) + Position;\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
+  This is the internal worker function to update the data in\r
+  a form specified by FormSetGuid, FormId and Label.\r
+\r
+  @param[in] FormSetGuid       The optional Formset GUID.\r
+  @param[in] FormId            The Form ID.\r
+  @param[in] Package           The package header.\r
+  @param[in] OpCodeBufferStart An OpCode buffer that contains the set of IFR\r
+                               opcodes to be inserted or replaced in the form.\r
+  @param[in] OpCodeBufferEnd   An OpCcode buffer that contains the IFR opcode\r
+                               that marks the end of a replace operation in the form.\r
+  @param[out] TempPackage      The resultant package.\r
+\r
+  @retval EFI_SUCCESS    The function completes successfully.\r
+  @retval EFI_NOT_FOUND  The updated opcode or endopcode is not found.\r
+\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
+InternalHiiUpdateFormPackageData (\r
+  IN  EFI_GUID               *FormSetGuid, OPTIONAL\r
+  IN  EFI_FORM_ID            FormId,\r
+  IN  EFI_HII_PACKAGE_HEADER *Package,\r
+  IN  HII_LIB_OPCODE_BUFFER  *OpCodeBufferStart,\r
+  IN  HII_LIB_OPCODE_BUFFER  *OpCodeBufferEnd,    OPTIONAL\r
+  OUT EFI_HII_PACKAGE_HEADER *TempPackage\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
+  UINTN                     AddSize;\r
+  UINT8                     *BufferPos;\r
+  EFI_HII_PACKAGE_HEADER    PackageHeader;\r
+  UINTN                     Offset;\r
+  EFI_IFR_OP_HEADER         *IfrOpHdr;\r
+  EFI_IFR_OP_HEADER         *UpdateIfrOpHdr;\r
+  BOOLEAN                   GetFormSet;\r
+  BOOLEAN                   GetForm;\r
+  BOOLEAN                   Updated;\r
+  UINTN                     UpdatePackageLength;\r
+\r
+  CopyMem (TempPackage, Package, sizeof (EFI_HII_PACKAGE_HEADER));\r
+  UpdatePackageLength = sizeof (EFI_HII_PACKAGE_HEADER);\r
+  BufferPos           = (UINT8 *) (TempPackage + 1);\r
+\r
+  CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));\r
+  IfrOpHdr   = (EFI_IFR_OP_HEADER *)((UINT8 *) Package + sizeof (EFI_HII_PACKAGE_HEADER));\r
+  Offset     = sizeof (EFI_HII_PACKAGE_HEADER);\r
+  GetFormSet = (BOOLEAN) ((FormSetGuid == NULL) ? TRUE : FALSE);\r
+  GetForm    = FALSE;\r
+  Updated    = FALSE;\r
+\r
+  while (Offset < PackageHeader.Length) {\r
+    CopyMem (BufferPos, IfrOpHdr, IfrOpHdr->Length);\r
+    BufferPos           += IfrOpHdr->Length;\r
+    UpdatePackageLength += IfrOpHdr->Length;\r
 \r
-  Status = mHiiDatabaseProt->ListPackageLists (\r
-                            mHiiDatabaseProt,\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
+    // Find the matched FormSet and Form\r
     //\r
-    return Status;\r
+    if ((IfrOpHdr->OpCode == EFI_IFR_FORM_SET_OP) && (FormSetGuid != NULL)) {\r
+      if (CompareGuid((GUID *)(VOID *)&((EFI_IFR_FORM_SET *) IfrOpHdr)->Guid, FormSetGuid)) {\r
+        GetFormSet = TRUE;\r
+      } else {\r
+        GetFormSet = FALSE;\r
+      }\r
+    } else if (IfrOpHdr->OpCode == EFI_IFR_FORM_OP || IfrOpHdr->OpCode == EFI_IFR_FORM_MAP_OP) {\r
+      if (CompareMem (&((EFI_IFR_FORM *) IfrOpHdr)->FormId, &FormId, sizeof (EFI_FORM_ID)) == 0) {\r
+        GetForm = TRUE;\r
+      } else {\r
+        GetForm = FALSE;\r
+      }\r
+    }\r
+\r
+    //\r
+    // The matched Form is found, and Update data in this form\r
+    //\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
+        //\r
+        // Remove the original data when End OpCode buffer exist.\r
+        //\r
+        if (OpCodeBufferEnd != NULL) {\r
+          Offset        += IfrOpHdr->Length;\r
+          IfrOpHdr       = (EFI_IFR_OP_HEADER *) ((UINT8 *) (IfrOpHdr) + IfrOpHdr->Length);\r
+          UpdateIfrOpHdr = (EFI_IFR_OP_HEADER *) OpCodeBufferEnd->Buffer;\r
+          while (Offset < PackageHeader.Length) {\r
+            //\r
+            // Search the matched end opcode\r
+            //\r
+            if ((UpdateIfrOpHdr->Length == IfrOpHdr->Length) && \\r
+                (CompareMem (IfrOpHdr, UpdateIfrOpHdr, UpdateIfrOpHdr->Length) == 0)) {\r
+              break;\r
+            }\r
+            //\r
+            // Go to the next Op-Code\r
+            //\r
+            Offset        += IfrOpHdr->Length;\r
+            IfrOpHdr       = (EFI_IFR_OP_HEADER *) ((UINT8 *) (IfrOpHdr) + IfrOpHdr->Length);\r
+          }\r
+\r
+          if (Offset >= PackageHeader.Length) {\r
+            //\r
+            // The end opcode is not found.\r
+            //\r
+            return EFI_NOT_FOUND;\r
+          }\r
+        }\r
+\r
+        //\r
+        // Insert the updated data\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
+          // Add the end opcode\r
+          //\r
+          CopyMem (BufferPos, IfrOpHdr, IfrOpHdr->Length);\r
+          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
+    //\r
+    // Go to the next Op-Code\r
+    //\r
+    Offset   += IfrOpHdr->Length;\r
+    IfrOpHdr = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (IfrOpHdr) + IfrOpHdr->Length);\r
   }\r
 \r
-  *HandleBuffer = AllocateZeroPool (*HandleBufferLength);\r
-  \r
-  if (*HandleBuffer == NULL) {\r
-    return EFI_OUT_OF_RESOURCES;\r
+  if (!Updated) {\r
+    //\r
+    // The updated opcode buffer is not found.\r
+    //\r
+    return EFI_NOT_FOUND;\r
   }\r
-  \r
-  return mHiiDatabaseProt->ListPackageLists (\r
-                            mHiiDatabaseProt,\r
-                            PackageType,\r
-                            PackageGuid,\r
-                            HandleBufferLength,\r
-                            *HandleBuffer\r
-                            );\r
-  \r
+  //\r
+  // Update the package length.\r
+  //\r
+  PackageHeader.Length = (UINT32) UpdatePackageLength;\r
+  CopyMem (TempPackage, &PackageHeader, sizeof (EFI_HII_PACKAGE_HEADER));\r
+\r
+  return EFI_SUCCESS;\r
 }\r
+\r
 /**\r
-  This function check if the Hii Handle is a valid handle registered\r
-  in the HII database.\r
+  This function updates a form that has previously been registered with the HII\r
+  Database.  This function will perform at most one update operation.\r
+\r
+  The form to update is specified by Handle, FormSetGuid, and FormId.  Binary\r
+  comparisons of IFR opcodes are performed from the beginning of the form being\r
+  updated until an IFR opcode is found that exactly matches the first IFR opcode\r
+  specified by StartOpCodeHandle.  The following rules are used to determine if\r
+  an insert, replace, or delete operation is performed.\r
+\r
+  1) If no matches are found, then NULL is returned.\r
+  2) If a match is found, and EndOpCodeHandle is NULL, then all of the IFR opcodes\r
+     from StartOpCodeHandle except the first opcode are inserted immediately after\r
+     the matching IFR opcode in the form to be updated.\r
+  3) If a match is found, and EndOpCodeHandle is not NULL, then a search is made\r
+     from the matching IFR opcode until an IFR opcode exactly matches the first\r
+     IFR opcode specified by EndOpCodeHandle.  If no match is found for the first\r
+     IFR opcode specified by EndOpCodeHandle, then NULL is returned.  If a match\r
+     is found, then all of the IFR opcodes between the start match and the end\r
+     match are deleted from the form being updated and all of the IFR opcodes\r
+     from StartOpCodeHandle except the first opcode are inserted immediately after\r
+     the matching start IFR opcode.  If StartOpCcodeHandle only contains one\r
+     IFR instruction, then the result of this operation will delete all of the IFR\r
+     opcodes between the start end matches.\r
 \r
-  @param HiiHandle The HII Handle.\r
+  If HiiHandle is NULL, then ASSERT().\r
+  If StartOpCodeHandle is NULL, then ASSERT().\r
+\r
+  @param[in]  HiiHandle          The HII Handle of the form to update.\r
+  @param[in]  FormSetGuid        The Formset GUID of the form to update.  This\r
+                                 is an optional parameter that may be NULL.\r
+                                 If it is NULL, all FormSet will be updated.\r
+  @param[in]  FormId             The ID of the form to update.\r
+  @param[in]  StartOpCodeHandle  An OpCode Handle that contains the set of IFR\r
+                                 opcodes to be inserted or replaced in the form.\r
+                                 The first IFR instruction in StartOpCodeHandle\r
+                                 is used to find matching IFR opcode in the\r
+                                 form.\r
+  @param[in]  EndOpCodeHandle    An OpCcode Handle that contains the IFR opcode\r
+                                 that marks the end of a replace operation in\r
+                                 the form.  This is an optional parameter that\r
+                                 may be NULL.  If it is NULL, then an the IFR\r
+                                 opcodes specified by StartOpCodeHandle are\r
+                                 inserted into the form.\r
+\r
+  @retval EFI_OUT_OF_RESOURCES   No enough memory resource is allocated.\r
+  @retval EFI_NOT_FOUND          The following cases will return EFI_NOT_FOUND.\r
+                                 1) The form specified by HiiHandle, FormSetGuid,\r
+                                 and FormId could not be found in the HII Database.\r
+                                 2) No IFR opcodes in the target form match the first\r
+                                 IFR opcode in StartOpCodeHandle.\r
+                                 3) EndOpCOde is not NULL, and no IFR opcodes in the\r
+                                 target form following a matching start opcode match\r
+                                 the first IFR opcode in EndOpCodeHandle.\r
+  @retval EFI_SUCCESS            The matched form is updated by StartOpcode.\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
+EFI_STATUS\r
+EFIAPI\r
+HiiUpdateForm (\r
+  IN EFI_HII_HANDLE  HiiHandle,\r
+  IN EFI_GUID        *FormSetGuid,        OPTIONAL\r
+  IN EFI_FORM_ID     FormId,\r
+  IN VOID            *StartOpCodeHandle,\r
+  IN VOID            *EndOpCodeHandle     OPTIONAL\r
   )\r
 {\r
   EFI_STATUS                   Status;\r
-  UINTN                        BufferSize;\r
   EFI_HII_PACKAGE_LIST_HEADER  *HiiPackageList;\r
+  UINT32                       PackageListLength;\r
+  UINT32                       Offset;\r
+  EFI_HII_PACKAGE_LIST_HEADER  *UpdatePackageList;\r
+  UINTN                        BufferSize;\r
+  UINT8                        *UpdateBufferPos;\r
+  EFI_HII_PACKAGE_HEADER       *Package;\r
+  EFI_HII_PACKAGE_HEADER       *TempPackage;\r
+  EFI_HII_PACKAGE_HEADER       PackageHeader;\r
+  BOOLEAN                      Updated;\r
+  HII_LIB_OPCODE_BUFFER        *OpCodeBufferStart;\r
+  HII_LIB_OPCODE_BUFFER        *OpCodeBufferEnd;\r
 \r
+  //\r
+  // Input update data can't be NULL.\r
+  //\r
   ASSERT (HiiHandle != NULL);\r
+  ASSERT (StartOpCodeHandle != NULL);\r
+  UpdatePackageList = NULL;\r
+  TempPackage       = NULL;\r
+  HiiPackageList    = NULL;\r
 \r
-  HiiPackageList = NULL;\r
+  //\r
+  // Retrieve buffer data from Opcode Handle\r
+  //\r
+  OpCodeBufferStart = (HII_LIB_OPCODE_BUFFER *) StartOpCodeHandle;\r
+  OpCodeBufferEnd   = (HII_LIB_OPCODE_BUFFER *) EndOpCodeHandle;\r
+\r
+  //\r
+  // Get the original package list\r
+  //\r
   BufferSize = 0;\r
+  HiiPackageList   = NULL;\r
+  Status = gHiiDatabase->ExportPackageLists (gHiiDatabase, HiiHandle, &BufferSize, HiiPackageList);\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
+    return Status;\r
+  }\r
+\r
+  HiiPackageList = AllocatePool (BufferSize);\r
+  if (HiiPackageList == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto Finish;\r
+  }\r
 \r
-  Status = mHiiDatabaseProt->ExportPackageLists (\r
-             mHiiDatabaseProt,\r
-             HiiHandle,\r
-             &BufferSize,\r
-             HiiPackageList\r
-             );\r
+  Status = gHiiDatabase->ExportPackageLists (gHiiDatabase, HiiHandle, &BufferSize, HiiPackageList);\r
+  if (EFI_ERROR (Status)) {\r
+    goto Finish;\r
+  }\r
 \r
-  return (BOOLEAN) (Status == EFI_BUFFER_TOO_SMALL);\r
-}\r
+  //\r
+  // Calculate and allocate space for retrieval of IFR data\r
+  //\r
+  BufferSize += OpCodeBufferStart->Position;\r
+  UpdatePackageList = AllocateZeroPool (BufferSize);\r
+  if (UpdatePackageList == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto Finish;\r
+  }\r
+\r
+  //\r
+  // Allocate temp buffer to store the temp updated package buffer\r
+  //\r
+  TempPackage = AllocateZeroPool (BufferSize);\r
+  if (TempPackage == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto Finish;\r
+  }\r
+\r
+  UpdateBufferPos = (UINT8 *) UpdatePackageList;\r
 \r
+  //\r
+  // Copy the package list header\r
+  //\r
+  CopyMem (UpdateBufferPos, HiiPackageList, sizeof (EFI_HII_PACKAGE_LIST_HEADER));\r
+  UpdateBufferPos += sizeof (EFI_HII_PACKAGE_LIST_HEADER);\r
+\r
+  //\r
+  // Go through each package to find the matched package and update one by one\r
+  //\r
+  Updated = FALSE;\r
+  Offset  = sizeof (EFI_HII_PACKAGE_LIST_HEADER);\r
+  PackageListLength = ReadUnaligned32 (&HiiPackageList->PackageLength);\r
+  while (Offset < PackageListLength) {\r
+    Package = (EFI_HII_PACKAGE_HEADER *) (((UINT8 *) HiiPackageList) + Offset);\r
+    CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));\r
+    Offset += Package->Length;\r
+\r
+    if (Package->Type == EFI_HII_PACKAGE_FORMS) {\r
+      //\r
+      // Check this package is the matched package.\r
+      //\r
+      Status = InternalHiiUpdateFormPackageData (FormSetGuid, FormId, Package, OpCodeBufferStart, OpCodeBufferEnd, TempPackage);\r
+      //\r
+      // The matched package is found. Its package buffer will be updated by the input new data.\r
+      //\r
+      if (!EFI_ERROR(Status)) {\r
+        //\r
+        // Set Update Flag\r
+        //\r
+        Updated = TRUE;\r
+        //\r
+        // Add updated package buffer\r
+        //\r
+        Package = TempPackage;\r
+      }\r
+    }\r
+\r
+    //\r
+    // Add pacakge buffer\r
+    //\r
+    CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));\r
+    CopyMem (UpdateBufferPos, Package, PackageHeader.Length);\r
+    UpdateBufferPos += PackageHeader.Length;\r
+  }\r
+\r
+  if (Updated) {\r
+    //\r
+    // Update package list length\r
+    //\r
+    BufferSize = UpdateBufferPos - (UINT8 *) UpdatePackageList;\r
+    WriteUnaligned32 (&UpdatePackageList->PackageLength, (UINT32) BufferSize);\r
+\r
+    //\r
+    // Update Package to show form\r
+    //\r
+    Status = gHiiDatabase->UpdatePackageList (gHiiDatabase, HiiHandle, UpdatePackageList);\r
+  } else {\r
+    //\r
+    // Not matched form is found and updated.\r
+    //\r
+    Status = EFI_NOT_FOUND;\r
+  }\r
+\r
+Finish:\r
+  if (HiiPackageList != NULL) {\r
+    FreePool (HiiPackageList);\r
+  }\r
+\r
+  if (UpdatePackageList != NULL) {\r
+    FreePool (UpdatePackageList);\r
+  }\r
+\r
+  if (TempPackage != NULL) {\r
+    FreePool (TempPackage);\r
+  }\r
+\r
+  return Status;\r
+}\r