]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Library/UefiHiiLib/HiiLib.c
Fix Bug to convert low Hex string to handle L'A' - L'F'
[mirror_edk2.git] / MdeModulePkg / Library / UefiHiiLib / HiiLib.c
index 83e33d2a6ee67b7501df037fe0a83ab93dba2a27..384bab4ed6f3d80bb83b9e683c62c1200d008e6b 100644 (file)
 \r
 #include "InternalHiiLib.h"\r
 \r
-CONST EFI_HII_DATABASE_PROTOCOL   *mHiiDatabaseProt = NULL;\r
-CONST EFI_HII_STRING_PROTOCOL     *mHiiStringProt = NULL;\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
-\r
-  @param  ImageHandle   The firmware allocated handle for the EFI image.\r
-  @param  SystemTable   A pointer to the EFI System Table.\r
-\r
-  @retval EFI_SUCCESS   The constructor always returns EFI_SUCCESS.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-HiiLibConstructor (\r
-  IN EFI_HANDLE        ImageHandle,\r
-  IN EFI_SYSTEM_TABLE  *SystemTable\r
-  )\r
-{\r
-  EFI_STATUS  Status;\r
-\r
-  Status = gBS->LocateProtocol (&gEfiHiiDatabaseProtocolGuid, NULL, (VOID **) &mHiiDatabaseProt);\r
-  ASSERT_EFI_ERROR (Status);\r
-\r
-  Status = gBS->LocateProtocol (&gEfiHiiStringProtocolGuid, NULL, (VOID **) &mHiiStringProt);\r
-  ASSERT_EFI_ERROR (Status);\r
-\r
-  return EFI_SUCCESS;\r
-}\r
-\r
+//\r
+// <ConfigHdr> Template\r
+//\r
+GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR16 mConfigHdrTemplate[] = L"GUID=00000000000000000000000000000000&NAME=0000&PATH=00";\r
 \r
+//\r
+// Form Browser2 Protocol\r
+//\r
+EFI_FORM_BROWSER2_PROTOCOL  *mUefiFormBrowser2 = NULL;\r
 \r
 /**\r
   This funciton build the package list based on the package number,\r
@@ -222,7 +195,7 @@ HiiLibAddPackages (
   VA_START (Args, HiiHandle);\r
   PackageListHeader = InternalHiiLibPreparePackages (NumberOfPackages, GuidId, Args);\r
 \r
-  Status      = mHiiDatabaseProt->NewPackageList (mHiiDatabaseProt, PackageListHeader, DriverHandle, HiiHandle);\r
+  Status      = gHiiDatabase->NewPackageList (gHiiDatabase, PackageListHeader, DriverHandle, HiiHandle);\r
   if (HiiHandle != NULL) {\r
     if (EFI_ERROR (Status)) {\r
       *HiiHandle = NULL;\r
@@ -254,7 +227,7 @@ HiiLibRemovePackages (
   EFI_STATUS Status;\r
   ASSERT (IsHiiHandleRegistered (HiiHandle));\r
 \r
-  Status = mHiiDatabaseProt->RemovePackageList (mHiiDatabaseProt, HiiHandle);\r
+  Status = gHiiDatabase->RemovePackageList (gHiiDatabase, HiiHandle);\r
   ASSERT_EFI_ERROR (Status);\r
 }\r
 \r
@@ -292,8 +265,8 @@ HiiLibGetHiiHandles (
   //\r
   // Try to find the actual buffer size for HiiHandle Buffer.\r
   //\r
-  Status = mHiiDatabaseProt->ListPackageLists (\r
-                                 mHiiDatabaseProt,\r
+  Status = gHiiDatabase->ListPackageLists (\r
+                                 gHiiDatabase,\r
                                  EFI_HII_PACKAGE_TYPE_ALL,\r
                                  NULL,\r
                                  HandleBufferLength,\r
@@ -303,8 +276,8 @@ HiiLibGetHiiHandles (
   if (Status == EFI_BUFFER_TOO_SMALL) {\r
       *HiiHandleBuffer = AllocateZeroPool (*HandleBufferLength);\r
       ASSERT (*HiiHandleBuffer != NULL);\r
-      Status = mHiiDatabaseProt->ListPackageLists (\r
-                                     mHiiDatabaseProt,\r
+      Status = gHiiDatabase->ListPackageLists (\r
+                                     gHiiDatabase,\r
                                      EFI_HII_PACKAGE_TYPE_ALL,\r
                                      NULL,\r
                                      HandleBufferLength,\r
@@ -352,14 +325,14 @@ HiiLibExtractGuidFromHiiHandle (
   BufferSize = 0;\r
   HiiPackageList = NULL;\r
 \r
-  Status = mHiiDatabaseProt->ExportPackageLists (mHiiDatabaseProt, Handle, &BufferSize, HiiPackageList);\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 = mHiiDatabaseProt->ExportPackageLists (mHiiDatabaseProt, Handle, &BufferSize, HiiPackageList);\r
+    Status = gHiiDatabase->ExportPackageLists (gHiiDatabase, Handle, &BufferSize, HiiPackageList);\r
   }\r
   if (EFI_ERROR (Status)) {\r
     FreePool (HiiPackageList);\r
@@ -453,8 +426,8 @@ HiiLibDevicePathToHiiHandle (
   BufferSize = 0x1000;\r
   HiiHandles = AllocatePool (BufferSize);\r
   ASSERT (HiiHandles != NULL);\r
-  Status = mHiiDatabaseProt->ListPackageLists (\r
-                          mHiiDatabaseProt,\r
+  Status = gHiiDatabase->ListPackageLists (\r
+                          gHiiDatabase,\r
                           EFI_HII_PACKAGE_TYPE_ALL,\r
                           NULL,\r
                           &BufferSize,\r
@@ -465,8 +438,8 @@ HiiLibDevicePathToHiiHandle (
     HiiHandles = AllocatePool (BufferSize);\r
     ASSERT (HiiHandles != NULL);\r
 \r
-    Status = mHiiDatabaseProt->ListPackageLists (\r
-                            mHiiDatabaseProt,\r
+    Status = gHiiDatabase->ListPackageLists (\r
+                            gHiiDatabase,\r
                             EFI_HII_PACKAGE_TYPE_ALL,\r
                             NULL,\r
                             &BufferSize,\r
@@ -485,8 +458,8 @@ HiiLibDevicePathToHiiHandle (
   HiiHandle = NULL;\r
   HandleCount = BufferSize / sizeof (EFI_HII_HANDLE);\r
   for (Index = 0; Index < HandleCount; Index++) {\r
-    Status = mHiiDatabaseProt->GetPackageListHandle (\r
-                            mHiiDatabaseProt,\r
+    Status = gHiiDatabase->GetPackageListHandle (\r
+                            gHiiDatabase,\r
                             HiiHandles[Index],\r
                             &Handle\r
                             );\r
@@ -539,8 +512,8 @@ HiiLibExportPackageLists (
 \r
   Size = 0;\r
   PackageListHdr = NULL;\r
-  Status = mHiiDatabaseProt->ExportPackageLists (\r
-                                      mHiiDatabaseProt,\r
+  Status = gHiiDatabase->ExportPackageLists (\r
+                                      gHiiDatabase,\r
                                       Handle,\r
                                       &Size,\r
                                       PackageListHdr\r
@@ -553,8 +526,8 @@ HiiLibExportPackageLists (
     if (PackageListHeader == NULL) {\r
       return EFI_OUT_OF_RESOURCES;\r
     } else {\r
-      Status = mHiiDatabaseProt->ExportPackageLists (\r
-                                          mHiiDatabaseProt,\r
+      Status = gHiiDatabase->ExportPackageLists (\r
+                                          gHiiDatabase,\r
                                           Handle,\r
                                           &Size,\r
                                           PackageListHdr\r
@@ -632,8 +605,8 @@ HiiLibListPackageLists (
     ASSERT (PackageGuid == NULL);\r
   }\r
 \r
-  Status = mHiiDatabaseProt->ListPackageLists (\r
-                            mHiiDatabaseProt,\r
+  Status = gHiiDatabase->ListPackageLists (\r
+                            gHiiDatabase,\r
                             PackageType,\r
                             PackageGuid,\r
                             HandleBufferLength,\r
@@ -653,8 +626,8 @@ HiiLibListPackageLists (
     return EFI_OUT_OF_RESOURCES;\r
   }\r
   \r
-  return mHiiDatabaseProt->ListPackageLists (\r
-                            mHiiDatabaseProt,\r
+  return gHiiDatabase->ListPackageLists (\r
+                            gHiiDatabase,\r
                             PackageType,\r
                             PackageGuid,\r
                             HandleBufferLength,\r
@@ -685,8 +658,8 @@ IsHiiHandleRegistered (
   HiiPackageList = NULL;\r
   BufferSize = 0;\r
 \r
-  Status = mHiiDatabaseProt->ExportPackageLists (\r
-             mHiiDatabaseProt,\r
+  Status = gHiiDatabase->ExportPackageLists (\r
+             gHiiDatabase,\r
              HiiHandle,\r
              &BufferSize,\r
              HiiPackageList\r
@@ -695,3 +668,2251 @@ IsHiiHandleRegistered (
   return (BOOLEAN) (Status == EFI_BUFFER_TOO_SMALL);\r
 }\r
 \r
+\r
+/**\r
+  Converts all hex dtring characters in range ['A'..'F'] to ['a'..'f'] for \r
+  hex digits that appear between a '=' and a '&' in a config string.\r
+\r
+  If String is NULL, then ASSERT().\r
+\r
+  @param[in] String  Pointer to a Null-terminated Unicode string.\r
+\r
+  @return  Pointer to the Null-terminated Unicode result string.\r
+\r
+**/\r
+EFI_STRING\r
+EFIAPI\r
+InternalHiiLowerConfigString (\r
+  IN EFI_STRING  ConfigString\r
+  )\r
+{\r
+  EFI_STRING  String;\r
+  BOOLEAN     Lower;\r
+\r
+  ASSERT (ConfigString != NULL);\r
+\r
+  //\r
+  // Convert all hex digits in range [A-F] in the configuration header to [a-f]\r
+  //\r
+  for (String = ConfigString, Lower = FALSE; *String != L'\0'; String++) {\r
+    if (*String == L'=') {\r
+      Lower = TRUE;\r
+    } else if (*String == L'&') {\r
+      Lower = FALSE;\r
+    } else if (Lower && *String >= L'A' && *String <= L'F') {\r
+      *String = (CHAR16) (*String - L'A' + L'a');\r
+    }\r
+  }\r
+\r
+  return ConfigString;\r
+}\r
+\r
+/**\r
+  Uses the BlockToConfig() service of the Config Routing Protocol to \r
+  convert <ConfigRequest> and a buffer to a <ConfigResp>\r
+\r
+  If ConfigRequest is NULL, then ASSERT().\r
+  If Block is NULL, then ASSERT().\r
+\r
+  @param[in] ConfigRequest  Pointer to a Null-terminated Unicode string.\r
+  @param[in] Block          Pointer to a block of data.\r
+  @param[in] BlockSize      The zie, in bytes, of Block.\r
+\r
+  @retval NULL   The <ConfigResp> string could not be generated.\r
+  @retval Other  Pointer to the Null-terminated Unicode <ConfigResp> string.\r
+\r
+**/\r
+EFI_STRING\r
+EFIAPI\r
+InternalHiiBlockToConfig (\r
+  IN CONST EFI_STRING  ConfigRequest,\r
+  IN CONST UINT8       *Block,\r
+  IN UINTN             BlockSize\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+  EFI_STRING  ConfigResp;\r
+  CHAR16      *Progress;\r
+\r
+  ASSERT (ConfigRequest != NULL);\r
+  ASSERT (Block != NULL);\r
+\r
+  //\r
+  // Convert <ConfigRequest> to <ConfigResp>\r
+  //\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 ConfigToBlock() service of the Config Routing Protocol to \r
+  convert <ConfigResp> to a block.  The block is allocated using\r
+  AllocatePool().  The caller is responsible for freeing the block\r
+  using FreePool().\r
+\r
+  If ConfigResp is NULL, then ASSERT().\r
+\r
+  @param[in] ConfigResp  Pointer to a Null-terminated Unicode string.\r
+  @param[in] BufferSize  Length in bytes of buffer to hold retrived data. \r
+\r
+  @retval NULL   The block could not be generated..\r
+  @retval Other  Pointer to the allocated block.\r
+\r
+**/\r
+UINT8 *\r
+EFIAPI\r
+InternalHiiConfigToBlock (\r
+  IN  EFI_STRING  ConfigResp,\r
+  IN  UINTN       BlockSize\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+  CHAR16      *Progress;\r
+  UINT8       *Block;\r
+\r
+  ASSERT (ConfigResp != NULL);\r
+\r
+  //\r
+  // Allocate a buffer to hold the <ConfigResp> conversion\r
+  //\r
+  Block = AllocateZeroPool (BlockSize);\r
+  if (Block == NULL) {\r
+    return NULL;\r
+  }\r
+\r
+  //\r
+  // Convert <ConfigResp> to a buffer\r
+  //\r
+  Status = gHiiConfigRouting->ConfigToBlock (\r
+                                gHiiConfigRouting,\r
+                                ConfigResp,\r
+                                Block,\r
+                                &BlockSize,\r
+                                &Progress\r
+                                );\r
+  if (EFI_ERROR (Status)) {\r
+    FreePool (Block);\r
+    return NULL;\r
+  }\r
+\r
+  //\r
+  // Return converted buffer\r
+  //\r
+  return Block;\r
+}\r
+\r
+/**\r
+  Uses the BrowserCallback() service of the Form Browser Protocol to retrieve \r
+  or set uncommitted data.  If sata i being retrieved, then the buffer is \r
+  allocated using AllocatePool().  The caller is then responsible for freeing \r
+  the buffer using FreePool().\r
+\r
+  @param[in]  VariableName    Pointer to a Null-terminated Unicode string.  This \r
+                              is an optional parameter that may be NULL.\r
+  @param[in]  VariableGuid    Pointer to an EFI_GUID structure.  This is an optional \r
+                              parameter that may be NULL.\r
+  @param[in]  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
+    if (Status != EFI_BUFFER_TOO_SMALL) {\r
+      return NULL;\r
+    }\r
+\r
+    //\r
+    // Allocate the ResultsData buffer\r
+    //\r
+    ResultsData = AllocateZeroPool (ResultsDataSize);\r
+    if (ResultsData == NULL) {\r
+      return NULL;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Retrieve or set the ResultsData from the Browser Callback\r
+  //\r
+  Status = mUefiFormBrowser2->BrowserCallback (\r
+                            mUefiFormBrowser2,\r
+                            &ResultsDataSize,\r
+                            ResultsData,\r
+                            (BOOLEAN)(SetResultsData == NULL),\r
+                            VariableGuid,\r
+                            VariableName\r
+                            );\r
+  if (EFI_ERROR (Status)) {\r
+    return NULL;\r
+  }\r
+\r
+  return ResultsData;\r
+}\r
+\r
+/**\r
+  Allocates and returns a Null-terminated Unicode <ConfigHdr> string using routing \r
+  information that includes a GUID, an optional Unicode string name, and a device\r
+  path.  The string returned is allocated with AllocatePool().  The caller is \r
+  responsible for freeing the allocated string with FreePool().\r
+  \r
+  The format of a <ConfigHdr> is as follows:\r
+\r
+    GUID=<HexCh>32&NAME=<Char>NameLength&PATH=<HexChar>DevicePathSize<Null>\r
+\r
+  @param[in]  Guid          Pointer to an EFI_GUID that is the routing information\r
+                            GUID.  Each of the 16 bytes in Guid is converted to \r
+                            a 2 Unicode character hexidecimal string.  This is \r
+                            an optional parameter that may be NULL.\r
+  @param[in]  Name          Pointer to a Null-terminated Unicode string that is \r
+                            the routing information NAME.  This is an optional \r
+                            parameter that may be NULL.  Each 16-bit Unicode \r
+                            character in Name is converted to a 4 character Unicode \r
+                            hexidecimal string.                        \r
+  @param[in]  DriverHandle  The driver handle which supports a Device Path Protocol\r
+                            that is the routing information PATH.  Each byte of\r
+                            the Device Path associated with DriverHandle is converted\r
+                            to a 2 Unicode character hexidecimal string.\r
+\r
+  @retval NULL   DriverHandle does not support the Device Path Protocol.\r
+  @retval Other  A pointer to the Null-terminate Unicode <ConfigHdr> string\r
+\r
+**/\r
+EFI_STRING\r
+EFIAPI\r
+HiiConstructConfigHdr (\r
+  IN CONST EFI_GUID  *Guid,  OPTIONAL\r
+  IN CONST CHAR16    *Name,  OPTIONAL\r
+  IN EFI_HANDLE      DriverHandle\r
+  )\r
+{\r
+  UINTN                     NameLength;\r
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;\r
+  UINTN                     DevicePathSize;\r
+  CHAR16                    *String;\r
+  CHAR16                    *ReturnString;\r
+  UINTN                     Index;\r
+  UINT8                     *Buffer;\r
+\r
+  //\r
+  // Compute the length of Name in Unicode characters.  \r
+  // If Name is NULL, then the length is 0.\r
+  //\r
+  NameLength = 0;\r
+  if (Name != NULL) {\r
+    NameLength = StrLen (Name);\r
+  }\r
+\r
+  DevicePath = NULL;\r
+  DevicePathSize = 0;\r
+  //\r
+  // Retrieve DevicePath Protocol associated with DriverHandle\r
+  //\r
+  if (DriverHandle != NULL) {\r
+    DevicePath = DevicePathFromHandle (DriverHandle);\r
+    if (DevicePath == NULL) {\r
+      return NULL;\r
+    }\r
+    //\r
+    // Compute the size of the device path in bytes\r
+    //\r
+    DevicePathSize = GetDevicePathSize (DevicePath);\r
+  }\r
+\r
+  //\r
+  // GUID=<HexCh>32&NAME=<Char>NameLength&PATH=<HexChar>DevicePathSize <Null>\r
+  // | 5 | sizeof (EFI_GUID) * 2 | 6 | NameStrLen*4 | 6 | DevicePathSize * 2 | 1 |\r
+  //\r
+  String = AllocateZeroPool ((5 + sizeof (EFI_GUID) * 2 + 6 + NameLength * 4 + 6 + DevicePathSize * 2 + 1) * sizeof (CHAR16));\r
+  if (String == NULL) {\r
+    return NULL;\r
+  }\r
+\r
+  //\r
+  // Start with L"GUID="\r
+  //\r
+  ReturnString = StrCpy (String, L"GUID=");\r
+  String += StrLen (String);\r
+\r
+  if (Guid != NULL) {\r
+    //\r
+    // Append Guid converted to <HexCh>32\r
+    //\r
+    for (Index = 0, Buffer = (UINT8 *)Guid; Index < sizeof (EFI_GUID); Index++) {\r
+      String += UnicodeValueToString (String, PREFIX_ZERO | RADIX_HEX, *(Buffer++), 2);\r
+    }\r
+  }\r
+  \r
+  //\r
+  // Append L"&NAME="\r
+  //\r
+  StrCpy (String, L"&NAME=");\r
+  String += StrLen (String);\r
+\r
+  if (Name != NULL) {\r
+    //\r
+    // Append Name converted to <Char>NameLength\r
+    //\r
+    for (; *Name != L'\0'; Name++) {\r
+      String += UnicodeValueToString (String, PREFIX_ZERO | RADIX_HEX, *Name, 4);\r
+    }\r
+  }\r
+\r
+  //\r
+  // Append L"&PATH="\r
+  //\r
+  StrCpy (String, L"&PATH=");\r
+  String += StrLen (String);\r
+\r
+  //\r
+  // Append the device path associated with DriverHandle converted to <HexChar>DevicePathSize\r
+  //\r
+  for (Index = 0, Buffer = (UINT8 *)DevicePath; Index < DevicePathSize; Index++) {\r
+    String += UnicodeValueToString (String, PREFIX_ZERO | RADIX_HEX, *(Buffer++), 2);\r
+  }\r
+\r
+  //\r
+  // Null terminate the Unicode string\r
+  //\r
+  *String = L'\0';\r
+\r
+  //\r
+  // Convert all hex digits in range [A-F] in the configuration header to [a-f]\r
+  //\r
+  return InternalHiiLowerConfigString (ReturnString);\r
+}\r
+\r
+/**\r
+  Allocates and returns a Null-terminated Unicode <ConfigAltResp> string.\r
+\r
+  If Guid is NULL, then ASSERT().\r
+  If Name is NULL, then ASSERT().\r
+  If BlockNameArray is NULL, then ASSERT().\r
+\r
+  @param[in] Guid               GUID of the buffer storage.\r
+  @param[in] Name               Name of the buffer storage.\r
+  @param[in] DriverHandle       The DriverHandle that support a Device Path\r
+                                Protocol.    \r
+  @param[in] BufferStorage      Content of the buffer storage.\r
+  @param[in] BufferStorageSize  Length in bytes of the buffer storage.\r
+  @param[in] BlockNameArray     Array generated by VFR compiler.  This array\r
+                                contains a UINT32 value that is the length\r
+                                of BlockNameArray in bytes, followed by pairs\r
+                                of 16-bit values that are the offset and length\r
+                                values used to contruct a <ConfigRequest> string.\r
+  @param[in]  ...               A variable argument list that contains pairs of 16-bit\r
+                                ALTCFG identifiers and pointers to DefaultValueArrays.\r
+                                The variable argument list is terminated by a NULL \r
+                                DefaultValueArray pointer.  A DefaultValueArray \r
+                                contains a UINT32 value that is the length, in bytes,\r
+                                of the DefaultValueArray.  The UINT32 length value \r
+                                is followed by a series of records that contain\r
+                                a 16-bit WIDTH value followed by a byte array with \r
+                                WIDTH entries.  The records must be parsed from\r
+                                beginning to end until the UINT32 length limit\r
+                                is reached.  \r
+\r
+  @retval NULL          There are not enough resources to process the request.\r
+  @retval NULL          A <ConfigResp> could not be retrieved from the Config \r
+                        Routing Protocol.\r
+  @retval Other         A pointer to the Null-terminate Unicode <ConfigAltResp>\r
+                        string.\r
+\r
+**/\r
+EFI_STRING\r
+EFIAPI\r
+HiiConstructConfigAltResp (\r
+  IN CONST EFI_GUID  *Guid,\r
+  IN CONST CHAR16    *Name,\r
+  IN EFI_HANDLE      DriverHandle,\r
+  IN CONST VOID      *BufferStorage,\r
+  IN UINTN           BufferStorageSize,\r
+  IN CONST VOID      *BlockNameArray, \r
+  ...\r
+  )\r
+{\r
+  UINTN         Length;\r
+  CHAR16        *String;\r
+  CHAR16        *ConfigHdr;\r
+  UINT8         *Buffer;\r
+  UINT8         *BufferEnd;\r
+  CHAR16        *ConfigRequest;\r
+  EFI_STRING    ConfigResp;\r
+  EFI_STRING    ConfigAltResp;\r
+  VA_LIST       Args;\r
+  UINTN         AltCfgId;\r
+  UINT16        Width;\r
+  UINT16        OffsetValue;\r
+  UINT16        WidthValue;\r
+\r
+  ASSERT (Guid != NULL);\r
+  ASSERT (Name != NULL);\r
+  ASSERT (BlockNameArray != NULL);\r
+\r
+  //\r
+  // Initialize local variables\r
+  //\r
+  ConfigHdr     = NULL;\r
+  ConfigRequest = NULL; \r
+  ConfigResp    = NULL;\r
+\r
+  //\r
+  // Construct <ConfigHdr> : "GUID=...&NAME=...&PATH=..."\r
+  //\r
+  ConfigHdr = HiiConstructConfigHdr (Guid, Name, DriverHandle);\r
+  if (ConfigHdr == NULL) {\r
+    goto Exit;\r
+  }\r
+\r
+  //\r
+  // Compute the length of the entire request starting with <ConfigHdr> and a \r
+  // Null-terminator\r
+  //\r
+  Length = StrLen (ConfigHdr) + 1;\r
+\r
+  //\r
+  // Determine the size <BlockName> Offset/Width pairs\r
+  //\r
+  Buffer = (UINT8 *)BlockNameArray;\r
+  BufferEnd = Buffer + ReadUnaligned32 ((UINT32 *)Buffer);\r
+  Buffer += sizeof (UINT32);\r
+\r
+  //\r
+  // Add <BlockName> length that is composed of one or more Offset/Width pairs\r
+  //\r
+  // <BlockName> ::= &OFFSET=1234&WIDTH=1234\r
+  //                 |  8   | 4 |   7  | 4 |\r
+  //\r
+  Length += (((BufferEnd - Buffer) / (sizeof (UINT16) + sizeof (UINT16))) * (8 + 4 + 7 + 4));\r
+\r
+  //\r
+  // Allocate buffer for the entire <ConfigRequest>\r
+  //\r
+  ConfigRequest = AllocateZeroPool (Length * sizeof (CHAR16));\r
+  if (ConfigRequest == NULL) {\r
+    goto Exit;\r
+  }\r
+  String = ConfigRequest;\r
+\r
+  //\r
+  // Start with <ConfigHdr>\r
+  //\r
+  StrCpy (String, ConfigHdr);\r
+  String += StrLen (String);\r
+\r
+  //\r
+  // Loop through all the Offset/Width pairs and append them to ConfigRequest\r
+  //\r
+  while (Buffer < BufferEnd) {\r
+    //\r
+    // Append &OFFSET=XXXX&WIDTH=YYYY\r
+    //\r
+    OffsetValue = ReadUnaligned16 ((UINT16 *)Buffer);\r
+    WidthValue  = ReadUnaligned16 ((UINT16 *)(Buffer + sizeof (UINT16)));\r
+    UnicodeSPrint (\r
+      String, \r
+      (8 + 4 + 7 + 4) * sizeof (CHAR16), \r
+      L"&OFFSET=%04X&WIDTH=%04X", \r
+      OffsetValue, \r
+      WidthValue\r
+    );\r
+\r
+    String += StrLen (String);\r
+    Buffer += (sizeof (UINT16) + sizeof (UINT16));\r
+  }\r
+\r
+  //\r
+  // Get the <ConfigResp>\r
+  //\r
+  ConfigResp = InternalHiiBlockToConfig (ConfigRequest, BufferStorage, BufferStorageSize);\r
+  if (ConfigResp == NULL) {\r
+    goto Exit;\r
+  }\r
+\r
+  //\r
+  // Compute the length of the entire response starting with <ConfigResp> and a \r
+  // Null-terminator\r
+  //\r
+  Length = StrLen (ConfigResp) + 1;\r
+\r
+  //\r
+  // Add the length associated with each pair of variable argument parameters\r
+  //\r
+  VA_START (Args, BlockNameArray);\r
+  while (TRUE) {\r
+    AltCfgId = VA_ARG (Args, UINT16);\r
+    Buffer   = VA_ARG (Args, UINT8 *);\r
+    if (Buffer == NULL) {\r
+      break;\r
+    }\r
+\r
+    //\r
+    // Add length for "&<ConfigHdr>&ALTCFG=XXXX"\r
+    //                |1| StrLen (ConfigHdr) | 8 | 4 |\r
+    //\r
+    Length += (1 + StrLen (ConfigHdr) + 8 + 4);\r
+\r
+    BufferEnd = Buffer + ReadUnaligned32 ((UINT32 *)Buffer);\r
+    Buffer += sizeof (UINT32);\r
+    while (Buffer < BufferEnd) {\r
+      //\r
+      // Extract Width field\r
+      //\r
+      Width = ReadUnaligned16 ((UINT16 *)(Buffer + sizeof (UINT16)));\r
+\r
+      //\r
+      // Add length for "&OFFSET=XXXX&WIDTH=YYYY&VALUE=zzzzzzzzzzzz"\r
+      //                |    8  | 4 |   7  | 4 |   7  | Width * 2 |\r
+      //\r
+      Length += (8 + 4 + 7 + 4 + 7 + Width * 2);\r
+\r
+      //\r
+      // Update Buffer to the next record\r
+      //\r
+      Buffer += (sizeof (UINT16) + sizeof (UINT16) + Width);\r
+    }\r
+  }\r
+  VA_END (Args);\r
+\r
+  //\r
+  // Allocate a buffer for the entire response\r
+  //\r
+  ConfigAltResp = AllocateZeroPool (Length * sizeof (CHAR16));\r
+  if (ConfigAltResp == NULL) {\r
+    goto Exit;\r
+  }\r
+  String = ConfigAltResp;\r
+\r
+  //\r
+  // Add <ConfigResp>\r
+  //\r
+  StrCpy (String, ConfigResp);\r
+  String += StrLen (String);\r
+\r
+  //\r
+  // Add <AltResp> for each pair of variable argument parameters\r
+  //\r
+  VA_START (Args, BlockNameArray);\r
+  while (TRUE) {\r
+    AltCfgId = VA_ARG (Args, UINT16);\r
+    Buffer   = VA_ARG (Args, UINT8 *);\r
+    if (Buffer == NULL) {\r
+      break;\r
+    }\r
+\r
+    //\r
+    // Add <AltConfigHdr> of the form "&<ConfigHdr>&ALTCFG=XXXX"\r
+    //                                |1| StrLen (ConfigHdr) | 8 | 4 |\r
+    //\r
+    UnicodeSPrint (\r
+      String, \r
+      (1 + StrLen (ConfigHdr) + 8 + 4) * sizeof (CHAR16), \r
+      L"&%s&ALTCFG=%04X", \r
+      ConfigHdr, \r
+      AltCfgId\r
+      );\r
+    String += StrLen (String);\r
+\r
+    //\r
+    // Add <ConfigBody> ::= <ConfigElement>*\r
+    //\r
+    BufferEnd = Buffer + ReadUnaligned32 ((UINT32 *)Buffer);\r
+    Buffer += sizeof (UINT32);\r
+    while (Buffer < BufferEnd) {\r
+      //\r
+      // Extract Width field\r
+      //\r
+      Width = ReadUnaligned16 ((UINT16 *)(Buffer + sizeof (UINT16)));\r
+\r
+      //\r
+      // Add <BlockConfig>\r
+      //\r
+      UnicodeSPrint (\r
+        String, \r
+        (8 + 4 + 7 + 4 + 7 + Width * 2) * sizeof (CHAR16),\r
+        L"&OFFSET=%04X&WIDTH=%04X&VALUE=", \r
+        ReadUnaligned16 ((UINT16 *)Buffer), \r
+        Width\r
+        );\r
+      String += StrLen (String);\r
+\r
+      //\r
+      // Update Buffer to point to the value in the current record\r
+      //\r
+      Buffer += (sizeof (UINT16) + sizeof (UINT16));\r
+\r
+      //\r
+      // Convert Value to a hex string in "%x" format\r
+      //   NOTE: This is in the opposite byte that GUID and PATH use\r
+      //\r
+      for (; Width > 0; Width--) {\r
+        String += UnicodeValueToString (String, PREFIX_ZERO | RADIX_HEX, Buffer[Width - 1], 2);\r
+      }\r
+      //\r
+      // Update Buffer to the next record\r
+      //\r
+      Buffer += Width;\r
+    }\r
+  }\r
+  VA_END (Args);\r
+\r
+  //\r
+  // Convert all hex digits in range [A-F] in the configuration header to [a-f]\r
+  //\r
+  return InternalHiiLowerConfigString (ConfigAltResp);\r
+\r
+Exit:\r
+  if (ConfigHdr != NULL) {\r
+    FreePool (ConfigHdr);\r
+  }\r
+  if (ConfigRequest != NULL) {\r
+    FreePool (ConfigRequest);\r
+  }\r
+  if (ConfigResp != NULL) {\r
+    FreePool (ConfigResp);\r
+  }\r
+\r
+  return NULL;\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 vakue 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 uncommited data from the Form Browser and converts it to a binary\r
+  buffer.  The returned buffer is allocated using AllocatePool().  The caller\r
+  is responsible for freeing the returned buffer using FreePool().\r
+\r
+  @param[in]  VariableName  Pointer to a Null-terminated Unicode string.  This \r
+                            is an optional parameter that may be NULL.\r
+  @param[in]  VariableGuid  Pointer to an EFI_GUID structure.  This is an optional \r
+                            parameter that may be NULL.\r
+  @param[in]  BufferSize    Length in bytes of buffer to hold retrived data. \r
+\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
+UINT8 *\r
+EFIAPI\r
+HiiGetBrowserData (\r
+  IN CONST EFI_GUID  *VariableGuid,  OPTIONAL\r
+  IN CONST CHAR16    *VariableName,  OPTIONAL\r
+  IN UINTN           BlockSize\r
+  )\r
+{\r
+  EFI_STRING  ResultsData;\r
+  UINTN       Size;\r
+  EFI_STRING  ConfigResp;\r
+  UINT8       *Block;\r
+\r
+  //\r
+  // Retrieve the results data from the Browser Callback\r
+  //\r
+  ResultsData = InternalHiiBrowserCallback (VariableGuid, VariableName, NULL);\r
+  if (ResultsData == NULL) {\r
+    return NULL;\r
+  }\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 NULL;\r
+  }\r
+\r
+  //\r
+  // Convert <ConfigResp> to a buffer\r
+  //\r
+  Block = InternalHiiConfigToBlock (ConfigResp, BlockSize);\r
+  FreePool (ConfigResp);\r
+\r
+  return Block;\r
+}\r
+\r
+/**\r
+  Updates uncommitted data in the Form Browser.\r
+\r
+  If Buffer is NULL, then ASSERT().\r
+\r
+  @param[in]  VariableName    Pointer to a Null-terminated Unicode string.  This\r
+                              is an optional parameter that may be NULL.\r
+  @param[in]  VariableGuid    Pointer to an EFI_GUID structure.  This is an optional\r
+                              parameter that may be NULL.\r
+  @param[in]  BufferSize      Length, in bytes, of Buffer.\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 peviously 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
+**/\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
+UINTN\r
+EFIAPI\r
+InternalHiiOpCodeHandlePosition (\r
+  IN VOID  *OpCodeHandle\r
+  )\r
+{\r
+  return ((HII_LIB_OPCODE_BUFFER  *)OpCodeHandle)->Position;\r
+}\r
+\r
+UINT8 *\r
+EFIAPI\r
+InternalHiiOpCodeHandleBuffer (\r
+  IN VOID  *OpCodeHandle\r
+  )\r
+{\r
+  return ((HII_LIB_OPCODE_BUFFER  *)OpCodeHandle)->Buffer;\r
+}\r
+\r
+UINT8 *\r
+EFIAPI\r
+InternalHiiGrowOpCodeHandle (\r
+  VOID   *OpCodeHandle,\r
+  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
+    if (Buffer == NULL) {\r
+      return NULL;\r
+    }\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
+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
+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
+InternalHiiCreateRawOpCodes (\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 InternalHiiCreateRawOpCodes (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, sizeof (OpCode));\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, sizeof (OpCode));\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 | EFI_IFR_FLAG_OPTIONS_ONLY))) == 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
+  ZeroMem (&OpCode, sizeof (OpCode));\r
+  OpCode.Statement.Prompt = Prompt;\r
+  OpCode.Statement.Help   = Help;\r
+  OpCode.Flags            = Flags;\r
+\r
+  return InternalHiiCreateOpCodeExtended (\r
+           OpCodeHandle, \r
+           &OpCode,\r
+           EFI_IFR_SUBTITLE_OP, \r
+           sizeof (OpCode), \r
+           0, \r
+           Scope\r
+           );\r
+}\r
+\r
+/**\r
+  Create EFI_IFR_REF_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]  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
+UINT8 *\r
+EFIAPI\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_IFR_REF  OpCode;\r
+\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
+  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 InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_REF_OP, sizeof (OpCode));\r
+}\r
+\r
+/**\r
+  Create EFI_IFR_CHECKBOX_OP opcode.\r
+\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[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\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
+  @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
+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_IFR_CHECKBOX  OpCode;\r
+  UINTN             Position;\r
+\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
+  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
+  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
+  Create EFI_IFR_NUMERIC_OP opcode.\r
+\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[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\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
+  @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
+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
+  EFI_IFR_NUMERIC  OpCode;\r
+  UINTN            Position;\r
+\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
+  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
+  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
+    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
+    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
+    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
+    break;\r
+  }\r
+\r
+  if (DefaultsOpCodeHandle == NULL) {\r
+    return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_NUMERIC_OP, sizeof (OpCode));\r
+  }\r
+\r
+  Position = InternalHiiOpCodeHandlePosition (OpCodeHandle);\r
+  InternalHiiCreateOpCodeExtended (OpCodeHandle, &OpCode, EFI_IFR_NUMERIC_OP, sizeof (OpCode), 0, 1);\r
+  InternalHiiAppendOpCodes (OpCodeHandle, DefaultsOpCodeHandle);\r
+  HiiCreateEndOpCode (OpCodeHandle);\r
+  return InternalHiiOpCodeHandleBuffer (OpCodeHandle) + Position;\r
+}\r
+\r
+/**\r
+  Create EFI_IFR_STRING_OP opcode.\r
+\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[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\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
+UINT8 *\r
+EFIAPI\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_IFR_STRING  OpCode;\r
+  UINTN           Position;\r
+\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
+  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
+  Create EFI_IFR_ONE_OF_OP opcode.\r
+\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[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\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 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
+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_IFR_ONE_OF  OpCode;\r
+  UINTN           Position;\r
+\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
+  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
+  Position = InternalHiiOpCodeHandlePosition (OpCodeHandle);\r
+  InternalHiiCreateOpCodeExtended (OpCodeHandle, &OpCode, EFI_IFR_ONE_OF_OP, sizeof (OpCode), 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
+  Create EFI_IFR_ORDERED_LIST_OP opcode.\r
+\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[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\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 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
+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_IFR_ORDERED_LIST  OpCode;\r
+  UINTN                 Position;\r
+\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
+  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
+  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
+  HiiCreateEndOpCode (OpCodeHandle);\r
+  return InternalHiiOpCodeHandleBuffer (OpCodeHandle) + Position;\r
+}\r
+\r
+/**\r
+  This is the internal worker function to update the data in\r
+  a form specified by FormSetGuid, FormId and Label.\r
+\r
+  @param FormSetGuid     The optional Formset GUID.\r
+  @param FormId          The Form ID.\r
+  @param Package         The package header.\r
+\r
+  @param TempPacakge     The resultant package.\r
+\r
+  @retval EFI_SUCCESS    The function completes successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\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
+  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
+  EFI_IFR_OP_HEADER         *AddOpCode;\r
+  UINT32                    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
+    //\r
+    // Find the matched FormSet and Form\r
+    //\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) {\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 && !Updated) {\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
+        // Insert the updated data\r
+        //\r
+        UpdateIfrOpHdr = (EFI_IFR_OP_HEADER *) OpCodeBufferStart->Buffer;\r
+        AddOpCode      = (EFI_IFR_OP_HEADER *) (OpCodeBufferStart->Buffer + UpdateIfrOpHdr->Length);\r
+        AddSize        = UpdateIfrOpHdr->Length;\r
+        while (AddSize < OpCodeBufferStart->Position) {\r
+          CopyMem (BufferPos, AddOpCode, AddOpCode->Length);\r
+          BufferPos           += AddOpCode->Length;\r
+          UpdatePackageLength += AddOpCode->Length;\r
+\r
+          AddOpCode = (EFI_IFR_OP_HEADER *) ((UINT8 *) (AddOpCode) + AddOpCode->Length);\r
+          AddSize += AddOpCode->Length;          \r
+        }\r
+\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
+        // Set update flag\r
+        //\r
+        Updated = TRUE;\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
+  if (!Updated) {\r
+    //\r
+    // The updated opcode buffer is not found.\r
+    //\r
+    return EFI_NOT_FOUND;\r
+  }\r
+  //\r
+  // Update the package length.\r
+  //\r
+  PackageHeader.Length = UpdatePackageLength;\r
+  CopyMem (TempPackage, &PackageHeader, sizeof (EFI_HII_PACKAGE_HEADER));\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\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
+  specifed 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 beng 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 exatly 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 ths operation will delete all of the IFR\r
+     opcodes between the start end matches.\r
+\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
+**/\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
+  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       *TempPacakge;\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
+  TempPacakge       = NULL;\r
+  HiiPackageList    = NULL;\r
+  \r
+  //\r
+  // Restrive 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 orginal 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 = gHiiDatabase->ExportPackageLists (gHiiDatabase, HiiHandle, &BufferSize, HiiPackageList);\r
+  if (EFI_ERROR (Status)) {\r
+    goto Finish;\r
+  }\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
+  TempPacakge = AllocateZeroPool (BufferSize);\r
+  if (TempPacakge == 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 pacakge 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, TempPacakge);\r
+      //\r
+      // The matched package is found. Its pacakge 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 = TempPacakge;\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 Pacakge 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 (TempPacakge != NULL) {\r
+    FreePool (TempPacakge);\r
+  }\r
+\r
+  return Status; \r
+}\r
+\r
+/**\r
+  Configure the buffer accrording to ConfigBody strings in the format of\r
+  <Length:4 bytes>, <Offset: 2 bytes>, <Width:2 bytes>, <Data:n bytes>.\r
+  This ConfigBody strings is generated by UEFI VfrCompiler for the default\r
+  values in a Form Set. The name of the ConfigBody strings is VfrMyIfrNVDataDefault0000\r
+  constructed following this rule: \r
+   "Vfr" + varstore.name + "Default" + defaultstore.attributes.\r
+  Check the generated C file in Output for details.\r
+\r
+  @param  Buffer                 The start address of buffer.\r
+  @param  BufferSize             The size of buffer.\r
+  @param  Number                 The number of the strings.\r
+  @param  ...                    Variable argument list for default value in <AltResp> format \r
+                                 generated by the tool.\r
+\r
+  @retval EFI_BUFFER_TOO_SMALL   the BufferSize is too small to operate.\r
+  @retval EFI_INVALID_PARAMETER  Buffer is NULL or BufferSize is 0.\r
+  @retval EFI_SUCCESS            Operation successful.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HiiIfrLibExtractDefault(\r
+  IN VOID                         *Buffer,\r
+  IN UINTN                        *BufferSize,\r
+  UINTN                           Number,\r
+  ...\r
+  )\r
+{\r
+  VA_LIST                         Args;\r
+  UINTN                           Index;\r
+  UINT32                          TotalLen;\r
+  UINT8                           *BufCfgArray;\r
+  UINT8                           *BufferPos;\r
+  UINT16                          Offset;\r
+  UINT16                          Width;\r
+  UINT8                           *Value;\r
+\r
+  if ((Buffer == NULL) || (BufferSize == NULL)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Offset = 0;\r
+  Width  = 0;\r
+  Value  = NULL;\r
+\r
+  VA_START (Args, Number);\r
+  for (Index = 0; Index < Number; Index++) {\r
+    BufCfgArray = (UINT8 *) VA_ARG (Args, VOID *);\r
+    TotalLen = ReadUnaligned32 ((UINT32 *)BufCfgArray);\r
+    BufferPos = BufCfgArray + sizeof (UINT32);\r
+\r
+    while ((UINT32)(BufferPos - BufCfgArray) < TotalLen) {\r
+      Offset = ReadUnaligned16 ((UINT16 *)BufferPos);\r
+      BufferPos += sizeof (UINT16);\r
+      Width = ReadUnaligned16 ((UINT16 *)BufferPos);\r
+      BufferPos += sizeof (UINT16);\r
+      Value = BufferPos;\r
+      BufferPos += Width;\r
+\r
+      if ((UINTN)(Offset + Width) > *BufferSize) {\r
+        return EFI_BUFFER_TOO_SMALL;\r
+      }\r
+\r
+      CopyMem ((UINT8 *)Buffer + Offset, Value, Width);\r
+    }\r
+  }\r
+  VA_END (Args);\r
+\r
+  *BufferSize = (UINTN)Offset;\r
+\r
+  return EFI_SUCCESS;\r
+}\r