Home | History | Annotate | Download | only in UefiHiiLib
      1 /** @file
      2   HII Library implementation that uses DXE protocols and services.
      3 
      4   Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
      5   This program and the accompanying materials
      6   are licensed and made available under the terms and conditions of the BSD License
      7   which accompanies this distribution.  The full text of the license may be found at
      8   http://opensource.org/licenses/bsd-license.php
      9 
     10   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     11   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     12 
     13 **/
     14 
     15 #include "InternalHiiLib.h"
     16 
     17 #define GUID_CONFIG_STRING_TYPE 0x00
     18 #define NAME_CONFIG_STRING_TYPE 0x01
     19 #define PATH_CONFIG_STRING_TYPE 0x02
     20 
     21 #define ACTION_SET_DEFAUTL_VALUE 0x01
     22 #define ACTION_VALIDATE_SETTING  0x02
     23 
     24 #define HII_LIB_DEFAULT_VARSTORE_SIZE  0x200
     25 
     26 typedef struct {
     27   LIST_ENTRY          Entry;      // Link to Block array
     28   UINT16              Offset;
     29   UINT16              Width;
     30   UINT8               OpCode;
     31   UINT8               Scope;
     32 } IFR_BLOCK_DATA;
     33 
     34 typedef struct {
     35   EFI_VARSTORE_ID     VarStoreId;
     36   UINT16              Size;
     37 } IFR_VARSTORAGE_DATA;
     38 
     39 //
     40 // <ConfigHdr> Template
     41 //
     42 GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR16 mConfigHdrTemplate[] = L"GUID=00000000000000000000000000000000&NAME=0000&PATH=00";
     43 
     44 EFI_FORM_BROWSER2_PROTOCOL  *mUefiFormBrowser2 = NULL;
     45 
     46 //
     47 // Template used to mark the end of a list of packages
     48 //
     49 GLOBAL_REMOVE_IF_UNREFERENCED CONST EFI_HII_PACKAGE_HEADER  mEndOfPakageList = {
     50   sizeof (EFI_HII_PACKAGE_HEADER),
     51   EFI_HII_PACKAGE_END
     52 };
     53 
     54 /**
     55   Extract Hii package list GUID for given HII handle.
     56 
     57   If HiiHandle could not be found in the HII database, then ASSERT.
     58   If Guid is NULL, then ASSERT.
     59 
     60   @param  Handle              Hii handle
     61   @param  Guid                Package list GUID
     62 
     63   @retval EFI_SUCCESS         Successfully extract GUID from Hii database.
     64 
     65 **/
     66 EFI_STATUS
     67 EFIAPI
     68 InternalHiiExtractGuidFromHiiHandle (
     69   IN      EFI_HII_HANDLE      Handle,
     70   OUT     EFI_GUID            *Guid
     71   )
     72 {
     73   EFI_STATUS                   Status;
     74   UINTN                        BufferSize;
     75   EFI_HII_PACKAGE_LIST_HEADER  *HiiPackageList;
     76 
     77   ASSERT (Guid != NULL);
     78   ASSERT (Handle != NULL);
     79 
     80   //
     81   // Get HII PackageList
     82   //
     83   BufferSize = 0;
     84   HiiPackageList = NULL;
     85 
     86   Status = gHiiDatabase->ExportPackageLists (gHiiDatabase, Handle, &BufferSize, HiiPackageList);
     87   ASSERT (Status != EFI_NOT_FOUND);
     88 
     89   if (Status == EFI_BUFFER_TOO_SMALL) {
     90     HiiPackageList = AllocatePool (BufferSize);
     91     ASSERT (HiiPackageList != NULL);
     92 
     93     Status = gHiiDatabase->ExportPackageLists (gHiiDatabase, Handle, &BufferSize, HiiPackageList);
     94   }
     95   if (EFI_ERROR (Status)) {
     96     FreePool (HiiPackageList);
     97     return Status;
     98   }
     99 
    100   //
    101   // Extract GUID
    102   //
    103   CopyGuid (Guid, &HiiPackageList->PackageListGuid);
    104 
    105   FreePool (HiiPackageList);
    106 
    107   return EFI_SUCCESS;
    108 }
    109 
    110 /**
    111   Registers a list of packages in the HII Database and returns the HII Handle
    112   associated with that registration.  If an HII Handle has already been registered
    113   with the same PackageListGuid and DeviceHandle, then NULL is returned.  If there
    114   are not enough resources to perform the registration, then NULL is returned.
    115   If an empty list of packages is passed in, then NULL is returned.  If the size of
    116   the list of package is 0, then NULL is returned.
    117 
    118   The variable arguments are pointers which point to package header that defined
    119   by UEFI VFR compiler and StringGather tool.
    120 
    121   #pragma pack (push, 1)
    122   typedef struct {
    123     UINT32                  BinaryLength;
    124     EFI_HII_PACKAGE_HEADER  PackageHeader;
    125   } EDKII_AUTOGEN_PACKAGES_HEADER;
    126   #pragma pack (pop)
    127 
    128   @param[in]  PackageListGuid  The GUID of the package list.
    129   @param[in]  DeviceHandle     If not NULL, the Device Handle on which
    130                                an instance of DEVICE_PATH_PROTOCOL is installed.
    131                                This Device Handle uniquely defines the device that
    132                                the added packages are associated with.
    133   @param[in]  ...              The variable argument list that contains pointers
    134                                to packages terminated by a NULL.
    135 
    136   @retval NULL   A HII Handle has already been registered in the HII Database with
    137                  the same PackageListGuid and DeviceHandle.
    138   @retval NULL   The HII Handle could not be created.
    139   @retval NULL   An empty list of packages was passed in.
    140   @retval NULL   All packages are empty.
    141   @retval Other  The HII Handle associated with the newly registered package list.
    142 
    143 **/
    144 EFI_HII_HANDLE
    145 EFIAPI
    146 HiiAddPackages (
    147   IN CONST EFI_GUID    *PackageListGuid,
    148   IN       EFI_HANDLE  DeviceHandle  OPTIONAL,
    149   ...
    150   )
    151 {
    152   EFI_STATUS                   Status;
    153   VA_LIST                      Args;
    154   UINT32                       *Package;
    155   EFI_HII_PACKAGE_LIST_HEADER  *PackageListHeader;
    156   EFI_HII_HANDLE               HiiHandle;
    157   UINT32                       Length;
    158   UINT8                        *Data;
    159 
    160   ASSERT (PackageListGuid != NULL);
    161 
    162   //
    163   // Calculate the length of all the packages in the variable argument list
    164   //
    165   for (Length = 0, VA_START (Args, DeviceHandle); (Package = VA_ARG (Args, UINT32 *)) != NULL; ) {
    166     Length += (ReadUnaligned32 (Package) - sizeof (UINT32));
    167   }
    168   VA_END (Args);
    169 
    170   //
    171   // If there are no packages in the variable argument list or all the packages
    172   // are empty, then return a NULL HII Handle
    173   //
    174   if (Length == 0) {
    175     return NULL;
    176   }
    177 
    178   //
    179   // Add the length of the Package List Header and the terminating Package Header
    180   //
    181   Length += sizeof (EFI_HII_PACKAGE_LIST_HEADER) + sizeof (EFI_HII_PACKAGE_HEADER);
    182 
    183   //
    184   // Allocate the storage for the entire Package List
    185   //
    186   PackageListHeader = AllocateZeroPool (Length);
    187 
    188   //
    189   // If the Package List can not be allocated, then return a NULL HII Handle
    190   //
    191   if (PackageListHeader == NULL) {
    192     return NULL;
    193   }
    194 
    195   //
    196   // Fill in the GUID and Length of the Package List Header
    197   //
    198   CopyGuid (&PackageListHeader->PackageListGuid, PackageListGuid);
    199   PackageListHeader->PackageLength = Length;
    200 
    201   //
    202   // Initialize a pointer to the beginning if the Package List data
    203   //
    204   Data = (UINT8 *)(PackageListHeader + 1);
    205 
    206   //
    207   // Copy the data from each package in the variable argument list
    208   //
    209   for (VA_START (Args, DeviceHandle); (Package = VA_ARG (Args, UINT32 *)) != NULL; ) {
    210     Length = ReadUnaligned32 (Package) - sizeof (UINT32);
    211     CopyMem (Data, Package + 1, Length);
    212     Data += Length;
    213   }
    214   VA_END (Args);
    215 
    216   //
    217   // Append a package of type EFI_HII_PACKAGE_END to mark the end of the package list
    218   //
    219   CopyMem (Data, &mEndOfPakageList, sizeof (mEndOfPakageList));
    220 
    221   //
    222   // Register the package list with the HII Database
    223   //
    224   Status = gHiiDatabase->NewPackageList (
    225                            gHiiDatabase,
    226                            PackageListHeader,
    227                            DeviceHandle,
    228                            &HiiHandle
    229                            );
    230   if (EFI_ERROR (Status)) {
    231     HiiHandle = NULL;
    232   }
    233 
    234   //
    235   // Free the allocated package list
    236   //
    237   FreePool (PackageListHeader);
    238 
    239   //
    240   // Return the new HII Handle
    241   //
    242   return HiiHandle;
    243 }
    244 
    245 /**
    246   Removes a package list from the HII database.
    247 
    248   If HiiHandle is NULL, then ASSERT.
    249   If HiiHandle is not a valid EFI_HII_HANDLE in the HII database, then ASSERT.
    250 
    251   @param[in]  HiiHandle   The handle that was previously registered in the HII database
    252 
    253 **/
    254 VOID
    255 EFIAPI
    256 HiiRemovePackages (
    257   IN      EFI_HII_HANDLE      HiiHandle
    258   )
    259 {
    260   EFI_STATUS Status;
    261 
    262   ASSERT (HiiHandle != NULL);
    263   Status = gHiiDatabase->RemovePackageList (gHiiDatabase, HiiHandle);
    264   ASSERT_EFI_ERROR (Status);
    265 }
    266 
    267 
    268 /**
    269   Retrieves the array of all the HII Handles or the HII handles of a specific
    270   package list GUID in the HII Database.
    271   This array is terminated with a NULL HII Handle.
    272   This function allocates the returned array using AllocatePool().
    273   The caller is responsible for freeing the array with FreePool().
    274 
    275   @param[in]  PackageListGuid  An optional parameter that is used to request
    276                                HII Handles associated with a specific
    277                                Package List GUID.  If this parameter is NULL,
    278                                then all the HII Handles in the HII Database
    279                                are returned.  If this parameter is not NULL,
    280                                then zero or more HII Handles associated with
    281                                PackageListGuid are returned.
    282 
    283   @retval NULL   No HII handles were found in the HII database
    284   @retval NULL   The array of HII Handles could not be retrieved
    285   @retval Other  A pointer to the NULL terminated array of HII Handles
    286 
    287 **/
    288 EFI_HII_HANDLE *
    289 EFIAPI
    290 HiiGetHiiHandles (
    291   IN CONST EFI_GUID  *PackageListGuid  OPTIONAL
    292   )
    293 {
    294   EFI_STATUS      Status;
    295   UINTN           HandleBufferLength;
    296   EFI_HII_HANDLE  TempHiiHandleBuffer;
    297   EFI_HII_HANDLE  *HiiHandleBuffer;
    298   EFI_GUID        Guid;
    299   UINTN           Index1;
    300   UINTN           Index2;
    301 
    302   //
    303   // Retrieve the size required for the buffer of all HII handles.
    304   //
    305   HandleBufferLength = 0;
    306   Status = gHiiDatabase->ListPackageLists (
    307                            gHiiDatabase,
    308                            EFI_HII_PACKAGE_TYPE_ALL,
    309                            NULL,
    310                            &HandleBufferLength,
    311                            &TempHiiHandleBuffer
    312                            );
    313 
    314   //
    315   // If ListPackageLists() returns EFI_SUCCESS for a zero size,
    316   // then there are no HII handles in the HII database.  If ListPackageLists()
    317   // returns an error other than EFI_BUFFER_TOO_SMALL, then there are no HII
    318   // handles in the HII database.
    319   //
    320   if (Status != EFI_BUFFER_TOO_SMALL) {
    321     //
    322     // Return NULL if the size can not be retrieved, or if there are no HII
    323     // handles in the HII Database
    324     //
    325     return NULL;
    326   }
    327 
    328   //
    329   // Allocate the array of HII handles to hold all the HII Handles and a NULL terminator
    330   //
    331   HiiHandleBuffer = AllocateZeroPool (HandleBufferLength + sizeof (EFI_HII_HANDLE));
    332   if (HiiHandleBuffer == NULL) {
    333     //
    334     // Return NULL if allocation fails.
    335     //
    336     return NULL;
    337   }
    338 
    339   //
    340   // Retrieve the array of HII Handles in the HII Database
    341   //
    342   Status = gHiiDatabase->ListPackageLists (
    343                            gHiiDatabase,
    344                            EFI_HII_PACKAGE_TYPE_ALL,
    345                            NULL,
    346                            &HandleBufferLength,
    347                            HiiHandleBuffer
    348                            );
    349   if (EFI_ERROR (Status)) {
    350     //
    351     // Free the buffer and return NULL if the HII handles can not be retrieved.
    352     //
    353     FreePool (HiiHandleBuffer);
    354     return NULL;
    355   }
    356 
    357   if (PackageListGuid == NULL) {
    358     //
    359     // Return the NULL terminated array of HII handles in the HII Database
    360     //
    361     return HiiHandleBuffer;
    362   } else {
    363     for (Index1 = 0, Index2 = 0; HiiHandleBuffer[Index1] != NULL; Index1++) {
    364       Status = InternalHiiExtractGuidFromHiiHandle (HiiHandleBuffer[Index1], &Guid);
    365       ASSERT_EFI_ERROR (Status);
    366       if (CompareGuid (&Guid, PackageListGuid)) {
    367         HiiHandleBuffer[Index2++] = HiiHandleBuffer[Index1];
    368       }
    369     }
    370     if (Index2 > 0) {
    371       HiiHandleBuffer[Index2] = NULL;
    372       return HiiHandleBuffer;
    373     } else {
    374       FreePool (HiiHandleBuffer);
    375       return NULL;
    376     }
    377   }
    378 }
    379 
    380 /**
    381   This function allows a caller to extract the form set opcode form the Hii Handle.
    382   The returned buffer is allocated using AllocatePool().The caller is responsible
    383   for freeing the allocated buffer using FreePool().
    384 
    385   @param Handle            The HII handle.
    386   @param Buffer            On return, points to a pointer which point to the buffer that contain the formset opcode.
    387   @param BufferSize        On return, points to the length of the buffer.
    388 
    389   @retval EFI_OUT_OF_RESOURCES   No enough memory resource is allocated.
    390   @retval EFI_NOT_FOUND          Can't find the package data for the input Handle.
    391   @retval EFI_INVALID_PARAMETER  The input parameters are not correct.
    392   @retval EFI_SUCCESS            Get the formset opcode from the hii handle successfully.
    393 
    394 **/
    395 EFI_STATUS
    396 EFIAPI
    397 HiiGetFormSetFromHiiHandle(
    398   IN  EFI_HII_HANDLE     Handle,
    399   OUT EFI_IFR_FORM_SET   **Buffer,
    400   OUT UINTN              *BufferSize
    401   )
    402 {
    403   EFI_STATUS                   Status;
    404   UINTN                        PackageListSize;
    405   UINTN                        TempSize;
    406   EFI_HII_PACKAGE_LIST_HEADER  *HiiPackageList;
    407   UINT8                        *Package;
    408   UINT8                        *OpCodeData;
    409   UINT8                        *FormSetBuffer;
    410   UINT8                        *TempBuffer;
    411   UINT32                       Offset;
    412   UINT32                       Offset2;
    413   UINT32                       PackageListLength;
    414   EFI_HII_PACKAGE_HEADER       PackageHeader;
    415 
    416   TempSize = 0;
    417   FormSetBuffer = NULL;
    418   TempBuffer    = NULL;
    419 
    420   //
    421   // Get HII PackageList
    422   //
    423   PackageListSize = 0;
    424   HiiPackageList = NULL;
    425   Status = gHiiDatabase->ExportPackageLists (gHiiDatabase, Handle, &PackageListSize, HiiPackageList);
    426   if (EFI_ERROR (Status) && (Status != EFI_BUFFER_TOO_SMALL)) {
    427     return Status;
    428   }
    429 
    430   HiiPackageList = AllocatePool (PackageListSize);
    431   if (HiiPackageList == NULL) {
    432     return EFI_OUT_OF_RESOURCES;
    433   }
    434 
    435   Status = gHiiDatabase->ExportPackageLists (gHiiDatabase, Handle, &PackageListSize, HiiPackageList);
    436   ASSERT_EFI_ERROR (Status);
    437 
    438   //
    439   // Get Form package from this HII package List
    440   //
    441   Status = EFI_NOT_FOUND;
    442   Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);
    443   PackageListLength = ReadUnaligned32 (&HiiPackageList->PackageLength);
    444 
    445   while (Offset < PackageListLength) {
    446     Package = ((UINT8 *) HiiPackageList) + Offset;
    447     CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));
    448     Offset += PackageHeader.Length;
    449 
    450     if (PackageHeader.Type != EFI_HII_PACKAGE_FORMS) {
    451       continue;
    452     }
    453 
    454     //
    455     // Search FormSet Opcode in this Form Package
    456     //
    457     Offset2 = sizeof (EFI_HII_PACKAGE_HEADER);
    458     while (Offset2 < PackageHeader.Length) {
    459       OpCodeData = Package + Offset2;
    460       Offset2 += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;
    461 
    462       if (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode != EFI_IFR_FORM_SET_OP) {
    463         continue;
    464       }
    465 
    466       if (FormSetBuffer != NULL){
    467         TempBuffer = AllocateCopyPool (TempSize + ((EFI_IFR_OP_HEADER *) OpCodeData)->Length, FormSetBuffer);
    468         FreePool(FormSetBuffer);
    469         FormSetBuffer = NULL;
    470         if (TempBuffer == NULL) {
    471           Status = EFI_OUT_OF_RESOURCES;
    472           goto Done;
    473         }
    474         CopyMem (TempBuffer + TempSize,  OpCodeData, ((EFI_IFR_OP_HEADER *) OpCodeData)->Length);
    475       } else {
    476         TempBuffer = AllocateCopyPool (TempSize + ((EFI_IFR_OP_HEADER *) OpCodeData)->Length, OpCodeData);
    477         if (TempBuffer == NULL) {
    478           Status = EFI_OUT_OF_RESOURCES;
    479           goto Done;
    480         }
    481       }
    482       TempSize += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;
    483       FormSetBuffer = TempBuffer;
    484 
    485       Status = EFI_SUCCESS;
    486       //
    487       //One form package has one formset, exit current form package to search other form package in the packagelist.
    488       //
    489       break;
    490     }
    491   }
    492 Done:
    493   FreePool (HiiPackageList);
    494 
    495   *BufferSize = TempSize;
    496   *Buffer = (EFI_IFR_FORM_SET *)FormSetBuffer;
    497 
    498   return Status;
    499 }
    500 
    501 /**
    502   Converts all hex dtring characters in range ['A'..'F'] to ['a'..'f'] for
    503   hex digits that appear between a '=' and a '&' in a config string.
    504 
    505   If ConfigString is NULL, then ASSERT().
    506 
    507   @param[in] ConfigString  Pointer to a Null-terminated Unicode string.
    508 
    509   @return  Pointer to the Null-terminated Unicode result string.
    510 
    511 **/
    512 EFI_STRING
    513 EFIAPI
    514 InternalHiiLowerConfigString (
    515   IN EFI_STRING  ConfigString
    516   )
    517 {
    518   EFI_STRING  String;
    519   BOOLEAN     Lower;
    520 
    521   ASSERT (ConfigString != NULL);
    522 
    523   //
    524   // Convert all hex digits in range [A-F] in the configuration header to [a-f]
    525   //
    526   for (String = ConfigString, Lower = FALSE; *String != L'\0'; String++) {
    527     if (*String == L'=') {
    528       Lower = TRUE;
    529     } else if (*String == L'&') {
    530       Lower = FALSE;
    531     } else if (Lower && *String >= L'A' && *String <= L'F') {
    532       *String = (CHAR16) (*String - L'A' + L'a');
    533     }
    534   }
    535 
    536   return ConfigString;
    537 }
    538 
    539 /**
    540   Uses the BlockToConfig() service of the Config Routing Protocol to
    541   convert <ConfigRequest> and a buffer to a <ConfigResp>
    542 
    543   If ConfigRequest is NULL, then ASSERT().
    544   If Block is NULL, then ASSERT().
    545 
    546   @param[in] ConfigRequest  Pointer to a Null-terminated Unicode string.
    547   @param[in] Block          Pointer to a block of data.
    548   @param[in] BlockSize      The zie, in bytes, of Block.
    549 
    550   @retval NULL   The <ConfigResp> string could not be generated.
    551   @retval Other  Pointer to the Null-terminated Unicode <ConfigResp> string.
    552 
    553 **/
    554 EFI_STRING
    555 EFIAPI
    556 InternalHiiBlockToConfig (
    557   IN CONST EFI_STRING  ConfigRequest,
    558   IN CONST UINT8       *Block,
    559   IN UINTN             BlockSize
    560   )
    561 {
    562   EFI_STATUS  Status;
    563   EFI_STRING  ConfigResp;
    564   CHAR16      *Progress;
    565 
    566   ASSERT (ConfigRequest != NULL);
    567   ASSERT (Block != NULL);
    568 
    569   //
    570   // Convert <ConfigRequest> to <ConfigResp>
    571   //
    572   Status = gHiiConfigRouting->BlockToConfig (
    573                                 gHiiConfigRouting,
    574                                 ConfigRequest,
    575                                 Block,
    576                                 BlockSize,
    577                                 &ConfigResp,
    578                                 &Progress
    579                                 );
    580   if (EFI_ERROR (Status)) {
    581     return NULL;
    582   }
    583   return ConfigResp;
    584 }
    585 
    586 /**
    587   Uses the BrowserCallback() service of the Form Browser Protocol to retrieve
    588   or set uncommitted data.  If sata i being retrieved, then the buffer is
    589   allocated using AllocatePool().  The caller is then responsible for freeing
    590   the buffer using FreePool().
    591 
    592   @param[in]  VariableGuid    Pointer to an EFI_GUID structure.  This is an optional
    593                               parameter that may be NULL.
    594   @param[in]  VariableName    Pointer to a Null-terminated Unicode string.  This
    595                               is an optional parameter that may be NULL.
    596   @param[in]  SetResultsData  If not NULL, then this parameter specified the buffer
    597                               of uncommited data to set.  If this parameter is NULL,
    598                               then the caller is requesting to get the uncommited data
    599                               from the Form Browser.
    600 
    601   @retval NULL   The uncommitted data could not be retrieved.
    602   @retval Other  A pointer to a buffer containing the uncommitted data.
    603 
    604 **/
    605 EFI_STRING
    606 EFIAPI
    607 InternalHiiBrowserCallback (
    608   IN CONST EFI_GUID    *VariableGuid,  OPTIONAL
    609   IN CONST CHAR16      *VariableName,  OPTIONAL
    610   IN CONST EFI_STRING  SetResultsData  OPTIONAL
    611   )
    612 {
    613   EFI_STATUS  Status;
    614   UINTN       ResultsDataSize;
    615   EFI_STRING  ResultsData;
    616   CHAR16      TempResultsData;
    617 
    618   //
    619   // Locate protocols
    620   //
    621   if (mUefiFormBrowser2 == NULL) {
    622     Status = gBS->LocateProtocol (&gEfiFormBrowser2ProtocolGuid, NULL, (VOID **) &mUefiFormBrowser2);
    623     if (EFI_ERROR (Status) || mUefiFormBrowser2 == NULL) {
    624       return NULL;
    625     }
    626   }
    627 
    628   ResultsDataSize = 0;
    629 
    630   if (SetResultsData != NULL) {
    631     //
    632     // Request to to set data in the uncommitted browser state information
    633     //
    634     ResultsData = SetResultsData;
    635   } else {
    636     //
    637     // Retrieve the length of the buffer required ResultsData from the Browser Callback
    638     //
    639     Status = mUefiFormBrowser2->BrowserCallback (
    640                               mUefiFormBrowser2,
    641                               &ResultsDataSize,
    642                               &TempResultsData,
    643                               TRUE,
    644                               VariableGuid,
    645                               VariableName
    646                               );
    647 
    648     if (!EFI_ERROR (Status)) {
    649       //
    650       // No Resluts Data, only allocate one char for '\0'
    651       //
    652       ResultsData = AllocateZeroPool (sizeof (CHAR16));
    653       return ResultsData;
    654     }
    655 
    656     if (Status != EFI_BUFFER_TOO_SMALL) {
    657       return NULL;
    658     }
    659 
    660     //
    661     // Allocate the ResultsData buffer
    662     //
    663     ResultsData = AllocateZeroPool (ResultsDataSize);
    664     if (ResultsData == NULL) {
    665       return NULL;
    666     }
    667   }
    668 
    669   //
    670   // Retrieve or set the ResultsData from the Browser Callback
    671   //
    672   Status = mUefiFormBrowser2->BrowserCallback (
    673                             mUefiFormBrowser2,
    674                             &ResultsDataSize,
    675                             ResultsData,
    676                             (BOOLEAN)(SetResultsData == NULL),
    677                             VariableGuid,
    678                             VariableName
    679                             );
    680   if (EFI_ERROR (Status)) {
    681     return NULL;
    682   }
    683 
    684   return ResultsData;
    685 }
    686 
    687 /**
    688   Allocates and returns a Null-terminated Unicode <ConfigHdr> string using routing
    689   information that includes a GUID, an optional Unicode string name, and a device
    690   path.  The string returned is allocated with AllocatePool().  The caller is
    691   responsible for freeing the allocated string with FreePool().
    692 
    693   The format of a <ConfigHdr> is as follows:
    694 
    695     GUID=<HexCh>32&NAME=<Char>NameLength&PATH=<HexChar>DevicePathSize<Null>
    696 
    697   @param[in]  Guid          Pointer to an EFI_GUID that is the routing information
    698                             GUID.  Each of the 16 bytes in Guid is converted to
    699                             a 2 Unicode character hexadecimal string.  This is
    700                             an optional parameter that may be NULL.
    701   @param[in]  Name          Pointer to a Null-terminated Unicode string that is
    702                             the routing information NAME.  This is an optional
    703                             parameter that may be NULL.  Each 16-bit Unicode
    704                             character in Name is converted to a 4 character Unicode
    705                             hexadecimal string.
    706   @param[in]  DriverHandle  The driver handle which supports a Device Path Protocol
    707                             that is the routing information PATH.  Each byte of
    708                             the Device Path associated with DriverHandle is converted
    709                             to a 2 Unicode character hexadecimal string.
    710 
    711   @retval NULL   DriverHandle does not support the Device Path Protocol.
    712   @retval Other  A pointer to the Null-terminate Unicode <ConfigHdr> string
    713 
    714 **/
    715 EFI_STRING
    716 EFIAPI
    717 HiiConstructConfigHdr (
    718   IN CONST EFI_GUID  *Guid,  OPTIONAL
    719   IN CONST CHAR16    *Name,  OPTIONAL
    720   IN EFI_HANDLE      DriverHandle
    721   )
    722 {
    723   UINTN                     NameLength;
    724   EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
    725   UINTN                     DevicePathSize;
    726   CHAR16                    *String;
    727   CHAR16                    *ReturnString;
    728   UINTN                     Index;
    729   UINT8                     *Buffer;
    730   UINTN                     MaxLen;
    731 
    732   //
    733   // Compute the length of Name in Unicode characters.
    734   // If Name is NULL, then the length is 0.
    735   //
    736   NameLength = 0;
    737   if (Name != NULL) {
    738     NameLength = StrLen (Name);
    739   }
    740 
    741   DevicePath = NULL;
    742   DevicePathSize = 0;
    743   //
    744   // Retrieve DevicePath Protocol associated with DriverHandle
    745   //
    746   if (DriverHandle != NULL) {
    747     DevicePath = DevicePathFromHandle (DriverHandle);
    748     if (DevicePath == NULL) {
    749       return NULL;
    750     }
    751     //
    752     // Compute the size of the device path in bytes
    753     //
    754     DevicePathSize = GetDevicePathSize (DevicePath);
    755   }
    756 
    757   //
    758   // GUID=<HexCh>32&NAME=<Char>NameLength&PATH=<HexChar>DevicePathSize <Null>
    759   // | 5 | sizeof (EFI_GUID) * 2 | 6 | NameStrLen*4 | 6 | DevicePathSize * 2 | 1 |
    760   //
    761   MaxLen = 5 + sizeof (EFI_GUID) * 2 + 6 + NameLength * 4 + 6 + DevicePathSize * 2 + 1;
    762   String = AllocateZeroPool (MaxLen * sizeof (CHAR16));
    763   if (String == NULL) {
    764     return NULL;
    765   }
    766 
    767   //
    768   // Start with L"GUID="
    769   //
    770   StrCpyS (String, MaxLen, L"GUID=");
    771   ReturnString = String;
    772   String += StrLen (String);
    773 
    774   if (Guid != NULL) {
    775     //
    776     // Append Guid converted to <HexCh>32
    777     //
    778     for (Index = 0, Buffer = (UINT8 *)Guid; Index < sizeof (EFI_GUID); Index++) {
    779       String += UnicodeValueToString (String, PREFIX_ZERO | RADIX_HEX, *(Buffer++), 2);
    780     }
    781   }
    782 
    783   //
    784   // Append L"&NAME="
    785   //
    786   StrCatS (ReturnString, MaxLen, L"&NAME=");
    787   String += StrLen (String);
    788 
    789   if (Name != NULL) {
    790     //
    791     // Append Name converted to <Char>NameLength
    792     //
    793     for (; *Name != L'\0'; Name++) {
    794       String += UnicodeValueToString (String, PREFIX_ZERO | RADIX_HEX, *Name, 4);
    795     }
    796   }
    797 
    798   //
    799   // Append L"&PATH="
    800   //
    801   StrCatS (ReturnString, MaxLen, L"&PATH=");
    802   String += StrLen (String);
    803 
    804   //
    805   // Append the device path associated with DriverHandle converted to <HexChar>DevicePathSize
    806   //
    807   for (Index = 0, Buffer = (UINT8 *)DevicePath; Index < DevicePathSize; Index++) {
    808     String += UnicodeValueToString (String, PREFIX_ZERO | RADIX_HEX, *(Buffer++), 2);
    809   }
    810 
    811   //
    812   // Null terminate the Unicode string
    813   //
    814   *String = L'\0';
    815 
    816   //
    817   // Convert all hex digits in range [A-F] in the configuration header to [a-f]
    818   //
    819   return InternalHiiLowerConfigString (ReturnString);
    820 }
    821 
    822 /**
    823   Convert the hex UNICODE encoding string of UEFI GUID, NAME or device path
    824   to binary buffer from <ConfigHdr>.
    825 
    826   This is a internal function.
    827 
    828   @param  String                 UEFI configuration string.
    829   @param  Flag                   Flag specifies what type buffer will be retrieved.
    830   @param  Buffer                 Binary of Guid, Name or Device path.
    831 
    832   @retval EFI_INVALID_PARAMETER  Any incoming parameter is invalid.
    833   @retval EFI_OUT_OF_RESOURCES   Lake of resources to store neccesary structures.
    834   @retval EFI_SUCCESS            The buffer data is retrieved and translated to
    835                                  binary format.
    836 
    837 **/
    838 EFI_STATUS
    839 InternalHiiGetBufferFromString (
    840   IN  EFI_STRING                 String,
    841   IN  UINT8                      Flag,
    842   OUT UINT8                      **Buffer
    843   )
    844 {
    845   UINTN      Length;
    846   EFI_STRING ConfigHdr;
    847   CHAR16     *StringPtr;
    848   UINT8      *DataBuffer;
    849   CHAR16     TemStr[5];
    850   UINTN      Index;
    851   UINT8      DigitUint8;
    852 
    853   if (String == NULL || Buffer == NULL) {
    854     return EFI_INVALID_PARAMETER;
    855   }
    856 
    857   DataBuffer = NULL;
    858   StringPtr  = NULL;
    859   ConfigHdr  = String;
    860   //
    861   // The content between 'GUID', 'NAME', 'PATH' of <ConfigHdr> and '&' of next element
    862   // or '\0' (end of configuration string) is the UNICODE %02x bytes encoding string.
    863   //
    864   for (Length = 0; *String != 0 && *String != L'&'; String++, Length++);
    865 
    866   switch (Flag) {
    867   case GUID_CONFIG_STRING_TYPE:
    868   case PATH_CONFIG_STRING_TYPE:
    869     //
    870     // The data in <ConfigHdr> is encoded as hex UNICODE %02x bytes in the same order
    871     // as the device path and Guid resides in RAM memory.
    872     // Translate the data into binary.
    873     //
    874     DataBuffer = (UINT8 *) AllocateZeroPool ((Length + 1) / 2);
    875     if (DataBuffer == NULL) {
    876       return EFI_OUT_OF_RESOURCES;
    877     }
    878     //
    879     // Convert binary byte one by one
    880     //
    881     ZeroMem (TemStr, sizeof (TemStr));
    882     for (Index = 0; Index < Length; Index ++) {
    883       TemStr[0] = ConfigHdr[Index];
    884       DigitUint8 = (UINT8) StrHexToUint64 (TemStr);
    885       if ((Index & 1) == 0) {
    886         DataBuffer [Index/2] = DigitUint8;
    887       } else {
    888         DataBuffer [Index/2] = (UINT8) ((DataBuffer [Index/2] << 4) + DigitUint8);
    889       }
    890     }
    891 
    892     *Buffer = DataBuffer;
    893     break;
    894 
    895   case NAME_CONFIG_STRING_TYPE:
    896     //
    897     // Convert Config String to Unicode String, e.g. "0041004200430044" => "ABCD"
    898     //
    899 
    900     //
    901     // Add the tailling char L'\0'
    902     //
    903     DataBuffer = (UINT8 *) AllocateZeroPool ((Length/4 + 1) * sizeof (CHAR16));
    904     if (DataBuffer == NULL) {
    905       return EFI_OUT_OF_RESOURCES;
    906     }
    907     //
    908     // Convert character one by one
    909     //
    910     StringPtr = (CHAR16 *) DataBuffer;
    911     ZeroMem (TemStr, sizeof (TemStr));
    912     for (Index = 0; Index < Length; Index += 4) {
    913       StrnCpyS (TemStr, sizeof (TemStr) / sizeof (CHAR16), ConfigHdr + Index, 4);
    914       StringPtr[Index/4] = (CHAR16) StrHexToUint64 (TemStr);
    915     }
    916     //
    917     // Add tailing L'\0' character
    918     //
    919     StringPtr[Index/4] = L'\0';
    920 
    921     *Buffer = DataBuffer;
    922     break;
    923 
    924   default:
    925     return EFI_INVALID_PARAMETER;
    926   }
    927 
    928   return EFI_SUCCESS;
    929 }
    930 
    931 /**
    932   This function checks VarOffset and VarWidth is in the block range.
    933 
    934   @param  BlockArray         The block array is to be checked.
    935   @param  VarOffset          Offset of var to the structure
    936   @param  VarWidth           Width of var.
    937 
    938   @retval TRUE   This Var is in the block range.
    939   @retval FALSE  This Var is not in the block range.
    940 **/
    941 BOOLEAN
    942 BlockArrayCheck (
    943   IN IFR_BLOCK_DATA  *BlockArray,
    944   IN UINT16          VarOffset,
    945   IN UINT16          VarWidth
    946   )
    947 {
    948   LIST_ENTRY          *Link;
    949   IFR_BLOCK_DATA      *BlockData;
    950 
    951   //
    952   // No Request Block array, all vars are got.
    953   //
    954   if (BlockArray == NULL) {
    955     return TRUE;
    956   }
    957 
    958   //
    959   // Check the input var is in the request block range.
    960   //
    961   for (Link = BlockArray->Entry.ForwardLink; Link != &BlockArray->Entry; Link = Link->ForwardLink) {
    962     BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);
    963     if ((VarOffset >= BlockData->Offset) && ((VarOffset + VarWidth) <= (BlockData->Offset + BlockData->Width))) {
    964       return TRUE;
    965     }
    966   }
    967 
    968   return FALSE;
    969 }
    970 
    971 /**
    972   Get the value of <Number> in <BlockConfig> format, i.e. the value of OFFSET
    973   or WIDTH or VALUE.
    974   <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>
    975 
    976   @param  ValueString            String in <BlockConfig> format and points to the
    977                                  first character of <Number>.
    978   @param  ValueData              The output value. Caller takes the responsibility
    979                                  to free memory.
    980   @param  ValueLength            Length of the <Number>, in characters.
    981 
    982   @retval EFI_OUT_OF_RESOURCES   Insufficient resources to store neccessary
    983                                  structures.
    984   @retval EFI_SUCCESS            Value of <Number> is outputted in Number
    985                                  successfully.
    986 
    987 **/
    988 EFI_STATUS
    989 EFIAPI
    990 InternalHiiGetValueOfNumber (
    991   IN  EFI_STRING           ValueString,
    992   OUT UINT8                **ValueData,
    993   OUT UINTN                *ValueLength
    994   )
    995 {
    996   EFI_STRING               StringPtr;
    997   UINTN                    Length;
    998   UINT8                    *Buf;
    999   UINT8                    DigitUint8;
   1000   UINTN                    Index;
   1001   CHAR16                   TemStr[2];
   1002 
   1003   ASSERT (ValueString != NULL && ValueData != NULL && ValueLength != NULL);
   1004   ASSERT (*ValueString != L'\0');
   1005 
   1006   //
   1007   // Get the length of value string
   1008   //
   1009   StringPtr = ValueString;
   1010   while (*StringPtr != L'\0' && *StringPtr != L'&') {
   1011     StringPtr++;
   1012   }
   1013   Length = StringPtr - ValueString;
   1014 
   1015   //
   1016   // Allocate buffer to store the value
   1017   //
   1018   Buf = (UINT8 *) AllocateZeroPool ((Length + 1) / 2);
   1019   if (Buf == NULL) {
   1020     return EFI_OUT_OF_RESOURCES;
   1021   }
   1022 
   1023   //
   1024   // Convert character one by one to the value buffer
   1025   //
   1026   ZeroMem (TemStr, sizeof (TemStr));
   1027   for (Index = 0; Index < Length; Index ++) {
   1028     TemStr[0] = ValueString[Length - Index - 1];
   1029     DigitUint8 = (UINT8) StrHexToUint64 (TemStr);
   1030     if ((Index & 1) == 0) {
   1031       Buf [Index/2] = DigitUint8;
   1032     } else {
   1033       Buf [Index/2] = (UINT8) ((DigitUint8 << 4) + Buf [Index/2]);
   1034     }
   1035   }
   1036 
   1037   //
   1038   // Set the converted value and string length.
   1039   //
   1040   *ValueData    = Buf;
   1041   *ValueLength  = Length;
   1042   return EFI_SUCCESS;
   1043 }
   1044 
   1045 /**
   1046   Get value from config request resp string.
   1047 
   1048   @param ConfigElement           ConfigResp string contains the current setting.
   1049   @param VarName                 The variable name which need to get value.
   1050   @param VarValue                The return value.
   1051 
   1052   @retval EFI_SUCCESS            Get the value for the VarName
   1053   @retval EFI_OUT_OF_RESOURCES   The memory is not enough.
   1054 **/
   1055 EFI_STATUS
   1056 GetValueFromRequest (
   1057   IN CHAR16                       *ConfigElement,
   1058   IN CHAR16                       *VarName,
   1059   OUT UINT64                      *VarValue
   1060   )
   1061 {
   1062   UINT8                        *TmpBuffer;
   1063   CHAR16                       *StringPtr;
   1064   UINTN                        Length;
   1065   EFI_STATUS                   Status;
   1066 
   1067   //
   1068   // Find VarName related string.
   1069   //
   1070   StringPtr = StrStr (ConfigElement, VarName);
   1071   ASSERT (StringPtr != NULL);
   1072 
   1073   //
   1074   // Skip the "VarName=" string
   1075   //
   1076   StringPtr += StrLen (VarName) + 1;
   1077 
   1078   //
   1079   // Get Offset
   1080   //
   1081   Status = InternalHiiGetValueOfNumber (StringPtr, &TmpBuffer, &Length);
   1082   if (EFI_ERROR (Status)) {
   1083     return Status;
   1084   }
   1085 
   1086   *VarValue = 0;
   1087   CopyMem (VarValue, TmpBuffer, (((Length + 1) / 2) < sizeof (UINT64)) ? ((Length + 1) / 2) : sizeof (UINT64));
   1088 
   1089   FreePool (TmpBuffer);
   1090 
   1091   return EFI_SUCCESS;
   1092 }
   1093 
   1094 /**
   1095   This internal function parses IFR data to validate current setting.
   1096 
   1097   Base on the NameValueType, if it is TRUE, RequestElement and HiiHandle is valid;
   1098   else the VarBuffer and CurrentBlockArray is valid.
   1099 
   1100   @param HiiPackageList     Point to Hii package list.
   1101   @param PackageListLength  The length of the pacakge.
   1102   @param VarGuid            Guid of the buffer storage.
   1103   @param VarName            Name of the buffer storage.
   1104   @param VarBuffer          The data buffer for the storage.
   1105   @param CurrentBlockArray  The block array from the config Requst string.
   1106   @param RequestElement     The config string for this storage.
   1107   @param HiiHandle          The HiiHandle for this formset.
   1108   @param NameValueType      Whether current storage is name/value varstore or not.
   1109 
   1110   @retval EFI_SUCCESS            The current setting is valid.
   1111   @retval EFI_OUT_OF_RESOURCES   The memory is not enough.
   1112   @retval EFI_INVALID_PARAMETER  The config string or the Hii package is invalid.
   1113 **/
   1114 EFI_STATUS
   1115 ValidateQuestionFromVfr (
   1116   IN EFI_HII_PACKAGE_LIST_HEADER   *HiiPackageList,
   1117   IN UINTN                         PackageListLength,
   1118   IN EFI_GUID                      *VarGuid,
   1119   IN CHAR16                        *VarName,
   1120   IN UINT8                         *VarBuffer,
   1121   IN IFR_BLOCK_DATA                *CurrentBlockArray,
   1122   IN CHAR16                        *RequestElement,
   1123   IN EFI_HII_HANDLE                HiiHandle,
   1124   IN BOOLEAN                       NameValueType
   1125   )
   1126 {
   1127   IFR_BLOCK_DATA               VarBlockData;
   1128   UINT16                       Offset;
   1129   UINT16                       Width;
   1130   UINT64                       VarValue;
   1131   EFI_IFR_TYPE_VALUE           TmpValue;
   1132   EFI_STATUS                   Status;
   1133   EFI_HII_PACKAGE_HEADER       PackageHeader;
   1134   UINT32                       PackageOffset;
   1135   UINT8                        *PackageData;
   1136   UINTN                        IfrOffset;
   1137   EFI_IFR_OP_HEADER            *IfrOpHdr;
   1138   EFI_IFR_VARSTORE             *IfrVarStore;
   1139   EFI_IFR_VARSTORE_NAME_VALUE  *IfrNameValueStore;
   1140   EFI_IFR_VARSTORE_EFI         *IfrEfiVarStore;
   1141   IFR_VARSTORAGE_DATA          VarStoreData;
   1142   EFI_IFR_ONE_OF               *IfrOneOf;
   1143   EFI_IFR_NUMERIC              *IfrNumeric;
   1144   EFI_IFR_ONE_OF_OPTION        *IfrOneOfOption;
   1145   EFI_IFR_CHECKBOX             *IfrCheckBox;
   1146   EFI_IFR_STRING               *IfrString;
   1147   CHAR8                        *VarStoreName;
   1148   UINTN                        Index;
   1149   CHAR16                       *QuestionName;
   1150   CHAR16                       *StringPtr;
   1151 
   1152   //
   1153   // Initialize the local variables.
   1154   //
   1155   Index             = 0;
   1156   VarStoreName      = NULL;
   1157   Status            = EFI_SUCCESS;
   1158   VarValue          = 0;
   1159   IfrVarStore       = NULL;
   1160   IfrNameValueStore = NULL;
   1161   IfrEfiVarStore    = NULL;
   1162   ZeroMem (&VarStoreData, sizeof (IFR_VARSTORAGE_DATA));
   1163   ZeroMem (&VarBlockData, sizeof (VarBlockData));
   1164 
   1165   //
   1166   // Check IFR value is in block data, then Validate Value
   1167   //
   1168   PackageOffset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);
   1169   while (PackageOffset < PackageListLength) {
   1170     CopyMem (&PackageHeader, (UINT8 *) HiiPackageList + PackageOffset, sizeof (PackageHeader));
   1171 
   1172     //
   1173     // Parse IFR opcode from the form package.
   1174     //
   1175     if (PackageHeader.Type == EFI_HII_PACKAGE_FORMS) {
   1176       IfrOffset   = sizeof (PackageHeader);
   1177       PackageData = (UINT8 *) HiiPackageList + PackageOffset;
   1178       while (IfrOffset < PackageHeader.Length) {
   1179         IfrOpHdr = (EFI_IFR_OP_HEADER *) (PackageData + IfrOffset);
   1180         //
   1181         // Validate current setting to the value built in IFR opcode
   1182         //
   1183         switch (IfrOpHdr->OpCode) {
   1184         case EFI_IFR_VARSTORE_OP:
   1185           //
   1186           // VarStoreId has been found. No further found.
   1187           //
   1188           if (VarStoreData.VarStoreId != 0) {
   1189             break;
   1190           }
   1191           //
   1192           // Find the matched VarStoreId to the input VarGuid and VarName
   1193           //
   1194           IfrVarStore = (EFI_IFR_VARSTORE *) IfrOpHdr;
   1195           if (CompareGuid ((EFI_GUID *) (VOID *) &IfrVarStore->Guid, VarGuid)) {
   1196             VarStoreName = (CHAR8 *) IfrVarStore->Name;
   1197             for (Index = 0; VarStoreName[Index] != 0; Index ++) {
   1198               if ((CHAR16) VarStoreName[Index] != VarName[Index]) {
   1199                 break;
   1200               }
   1201             }
   1202             //
   1203             // The matched VarStore is found.
   1204             //
   1205             if ((VarStoreName[Index] != 0) || (VarName[Index] != 0)) {
   1206               IfrVarStore = NULL;
   1207             }
   1208           } else {
   1209             IfrVarStore = NULL;
   1210           }
   1211 
   1212           if (IfrVarStore != NULL) {
   1213             VarStoreData.VarStoreId = IfrVarStore->VarStoreId;
   1214             VarStoreData.Size       = IfrVarStore->Size;
   1215           }
   1216           break;
   1217         case EFI_IFR_VARSTORE_NAME_VALUE_OP:
   1218           //
   1219           // VarStoreId has been found. No further found.
   1220           //
   1221           if (VarStoreData.VarStoreId != 0) {
   1222             break;
   1223           }
   1224           //
   1225           // Find the matched VarStoreId to the input VarGuid
   1226           //
   1227           IfrNameValueStore = (EFI_IFR_VARSTORE_NAME_VALUE *) IfrOpHdr;
   1228           if (!CompareGuid ((EFI_GUID *) (VOID *) &IfrNameValueStore->Guid, VarGuid)) {
   1229             IfrNameValueStore = NULL;
   1230           }
   1231 
   1232           if (IfrNameValueStore != NULL) {
   1233             VarStoreData.VarStoreId = IfrNameValueStore->VarStoreId;
   1234           }
   1235           break;
   1236         case EFI_IFR_VARSTORE_EFI_OP:
   1237           //
   1238           // VarStore is found. Don't need to search any more.
   1239           //
   1240           if (VarStoreData.VarStoreId != 0) {
   1241             break;
   1242           }
   1243 
   1244           IfrEfiVarStore = (EFI_IFR_VARSTORE_EFI *) IfrOpHdr;
   1245 
   1246           //
   1247           // If the length is small than the structure, this is from old efi
   1248           // varstore definition. Old efi varstore get config directly from
   1249           // GetVariable function.
   1250           //
   1251           if (IfrOpHdr->Length < sizeof (EFI_IFR_VARSTORE_EFI)) {
   1252             break;
   1253           }
   1254 
   1255           if (CompareGuid ((EFI_GUID *) (VOID *) &IfrEfiVarStore->Guid, VarGuid)) {
   1256             VarStoreName = (CHAR8 *) IfrEfiVarStore->Name;
   1257             for (Index = 0; VarStoreName[Index] != 0; Index ++) {
   1258               if ((CHAR16) VarStoreName[Index] != VarName[Index]) {
   1259                 break;
   1260               }
   1261             }
   1262             //
   1263             // The matched VarStore is found.
   1264             //
   1265             if ((VarStoreName[Index] != 0) || (VarName[Index] != 0)) {
   1266               IfrEfiVarStore = NULL;
   1267             }
   1268           } else {
   1269             IfrEfiVarStore = NULL;
   1270           }
   1271 
   1272           if (IfrEfiVarStore != NULL) {
   1273             //
   1274             // Find the matched VarStore
   1275             //
   1276             VarStoreData.VarStoreId = IfrEfiVarStore->VarStoreId;
   1277             VarStoreData.Size       = IfrEfiVarStore->Size;
   1278           }
   1279           break;
   1280         case EFI_IFR_FORM_OP:
   1281         case EFI_IFR_FORM_MAP_OP:
   1282           //
   1283           // Check the matched VarStoreId is found.
   1284           //
   1285           if (VarStoreData.VarStoreId == 0) {
   1286             return EFI_SUCCESS;
   1287           }
   1288           break;
   1289         case EFI_IFR_ONE_OF_OP:
   1290           //
   1291           // Check whether current value is the one of option.
   1292           //
   1293 
   1294           //
   1295           // OneOf question is not in IFR Form. This IFR form is not valid.
   1296           //
   1297           if (VarStoreData.VarStoreId == 0) {
   1298             return EFI_INVALID_PARAMETER;
   1299           }
   1300           //
   1301           // Check whether this question is for the requested varstore.
   1302           //
   1303           IfrOneOf = (EFI_IFR_ONE_OF *) IfrOpHdr;
   1304           if (IfrOneOf->Question.VarStoreId != VarStoreData.VarStoreId) {
   1305             break;
   1306           }
   1307 
   1308           if (NameValueType) {
   1309             QuestionName = HiiGetString (HiiHandle, IfrOneOf->Question.VarStoreInfo.VarName, NULL);
   1310             ASSERT (QuestionName != NULL);
   1311 
   1312             if (StrStr (RequestElement, QuestionName) == NULL) {
   1313               //
   1314               // This question is not in the current configuration string. Skip it.
   1315               //
   1316               break;
   1317             }
   1318 
   1319             Status = GetValueFromRequest (RequestElement, QuestionName, &VarValue);
   1320             if (EFI_ERROR (Status)) {
   1321               return Status;
   1322             }
   1323           } else {
   1324             //
   1325             // Get Offset by Question header and Width by DataType Flags
   1326             //
   1327             Offset = IfrOneOf->Question.VarStoreInfo.VarOffset;
   1328             Width  = (UINT16) (1 << (IfrOneOf->Flags & EFI_IFR_NUMERIC_SIZE));
   1329             //
   1330             // Check whether this question is in current block array.
   1331             //
   1332             if (!BlockArrayCheck (CurrentBlockArray, Offset, Width)) {
   1333               //
   1334               // This question is not in the current configuration string. Skip it.
   1335               //
   1336               break;
   1337             }
   1338             //
   1339             // Check this var question is in the var storage
   1340             //
   1341             if ((Offset + Width) > VarStoreData.Size) {
   1342               //
   1343               // This question exceeds the var store size.
   1344               //
   1345               return EFI_INVALID_PARAMETER;
   1346             }
   1347 
   1348             //
   1349             // Get the current value for oneof opcode
   1350             //
   1351             VarValue = 0;
   1352             CopyMem (&VarValue, VarBuffer +  Offset, Width);
   1353           }
   1354           //
   1355           // Set Block Data, to be checked in the following Oneof option opcode.
   1356           //
   1357           VarBlockData.OpCode     = IfrOpHdr->OpCode;
   1358           VarBlockData.Scope      = IfrOpHdr->Scope;
   1359           break;
   1360         case EFI_IFR_NUMERIC_OP:
   1361           //
   1362           // Check the current value is in the numeric range.
   1363           //
   1364 
   1365           //
   1366           // Numeric question is not in IFR Form. This IFR form is not valid.
   1367           //
   1368           if (VarStoreData.VarStoreId == 0) {
   1369             return EFI_INVALID_PARAMETER;
   1370           }
   1371           //
   1372           // Check whether this question is for the requested varstore.
   1373           //
   1374           IfrNumeric = (EFI_IFR_NUMERIC *) IfrOpHdr;
   1375           if (IfrNumeric->Question.VarStoreId != VarStoreData.VarStoreId) {
   1376             break;
   1377           }
   1378 
   1379           if (NameValueType) {
   1380             QuestionName = HiiGetString (HiiHandle, IfrNumeric->Question.VarStoreInfo.VarName, NULL);
   1381             ASSERT (QuestionName != NULL);
   1382 
   1383             if (StrStr (RequestElement, QuestionName) == NULL) {
   1384               //
   1385               // This question is not in the current configuration string. Skip it.
   1386               //
   1387               break;
   1388             }
   1389 
   1390             Status = GetValueFromRequest (RequestElement, QuestionName, &VarValue);
   1391             if (EFI_ERROR (Status)) {
   1392               return Status;
   1393             }
   1394           } else {
   1395             //
   1396             // Get Offset by Question header and Width by DataType Flags
   1397             //
   1398             Offset = IfrNumeric->Question.VarStoreInfo.VarOffset;
   1399             Width  = (UINT16) (1 << (IfrNumeric->Flags & EFI_IFR_NUMERIC_SIZE));
   1400             //
   1401             // Check whether this question is in current block array.
   1402             //
   1403             if (!BlockArrayCheck (CurrentBlockArray, Offset, Width)) {
   1404               //
   1405               // This question is not in the current configuration string. Skip it.
   1406               //
   1407               break;
   1408             }
   1409             //
   1410             // Check this var question is in the var storage
   1411             //
   1412             if ((Offset + Width) > VarStoreData.Size) {
   1413               //
   1414               // This question exceeds the var store size.
   1415               //
   1416               return EFI_INVALID_PARAMETER;
   1417             }
   1418 
   1419             //
   1420             // Check the current value is in the numeric range.
   1421             //
   1422             VarValue = 0;
   1423             CopyMem (&VarValue, VarBuffer +  Offset, Width);
   1424           }
   1425           if ((IfrNumeric->Flags & EFI_IFR_DISPLAY) == 0) {
   1426             switch (IfrNumeric->Flags & EFI_IFR_NUMERIC_SIZE) {
   1427             case EFI_IFR_NUMERIC_SIZE_1:
   1428               if ((INT8) VarValue < (INT8) IfrNumeric->data.u8.MinValue || (INT8) VarValue > (INT8) IfrNumeric->data.u8.MaxValue) {
   1429                 //
   1430                 // Not in the valid range.
   1431                 //
   1432                 return EFI_INVALID_PARAMETER;
   1433               }
   1434               break;
   1435             case EFI_IFR_NUMERIC_SIZE_2:
   1436               if ((INT16) VarValue < (INT16) IfrNumeric->data.u16.MinValue || (INT16) VarValue > (INT16) IfrNumeric->data.u16.MaxValue) {
   1437                 //
   1438                 // Not in the valid range.
   1439                 //
   1440                 return EFI_INVALID_PARAMETER;
   1441               }
   1442               break;
   1443             case EFI_IFR_NUMERIC_SIZE_4:
   1444               if ((INT32) VarValue < (INT32) IfrNumeric->data.u32.MinValue || (INT32) VarValue > (INT32) IfrNumeric->data.u32.MaxValue) {
   1445                 //
   1446                 // Not in the valid range.
   1447                 //
   1448                 return EFI_INVALID_PARAMETER;
   1449               }
   1450               break;
   1451             case EFI_IFR_NUMERIC_SIZE_8:
   1452               if ((INT64) VarValue < (INT64) IfrNumeric->data.u64.MinValue || (INT64) VarValue > (INT64) IfrNumeric->data.u64.MaxValue) {
   1453                 //
   1454                 // Not in the valid range.
   1455                 //
   1456                 return EFI_INVALID_PARAMETER;
   1457               }
   1458               break;
   1459             }
   1460           } else {
   1461             switch (IfrNumeric->Flags & EFI_IFR_NUMERIC_SIZE) {
   1462             case EFI_IFR_NUMERIC_SIZE_1:
   1463               if ((UINT8) VarValue < IfrNumeric->data.u8.MinValue || (UINT8) VarValue > IfrNumeric->data.u8.MaxValue) {
   1464                 //
   1465                 // Not in the valid range.
   1466                 //
   1467                 return EFI_INVALID_PARAMETER;
   1468               }
   1469               break;
   1470             case EFI_IFR_NUMERIC_SIZE_2:
   1471               if ((UINT16) VarValue < IfrNumeric->data.u16.MinValue || (UINT16) VarValue > IfrNumeric->data.u16.MaxValue) {
   1472                 //
   1473                 // Not in the valid range.
   1474                 //
   1475                 return EFI_INVALID_PARAMETER;
   1476               }
   1477               break;
   1478             case EFI_IFR_NUMERIC_SIZE_4:
   1479               if ((UINT32) VarValue < IfrNumeric->data.u32.MinValue || (UINT32) VarValue > IfrNumeric->data.u32.MaxValue) {
   1480                 //
   1481                 // Not in the valid range.
   1482                 //
   1483                 return EFI_INVALID_PARAMETER;
   1484               }
   1485               break;
   1486             case EFI_IFR_NUMERIC_SIZE_8:
   1487               if ((UINT64) VarValue < IfrNumeric->data.u64.MinValue || (UINT64) VarValue > IfrNumeric->data.u64.MaxValue) {
   1488                 //
   1489                 // Not in the valid range.
   1490                 //
   1491                 return EFI_INVALID_PARAMETER;
   1492               }
   1493               break;
   1494             }
   1495           }
   1496           break;
   1497         case EFI_IFR_CHECKBOX_OP:
   1498           //
   1499           // Check value is BOOLEAN type, only 0 and 1 is valid.
   1500           //
   1501 
   1502           //
   1503           // CheckBox question is not in IFR Form. This IFR form is not valid.
   1504           //
   1505           if (VarStoreData.VarStoreId == 0) {
   1506             return EFI_INVALID_PARAMETER;
   1507           }
   1508 
   1509           //
   1510           // Check whether this question is for the requested varstore.
   1511           //
   1512           IfrCheckBox = (EFI_IFR_CHECKBOX *) IfrOpHdr;
   1513           if (IfrCheckBox->Question.VarStoreId != VarStoreData.VarStoreId) {
   1514             break;
   1515           }
   1516 
   1517           if (NameValueType) {
   1518             QuestionName = HiiGetString (HiiHandle, IfrCheckBox->Question.VarStoreInfo.VarName, NULL);
   1519             ASSERT (QuestionName != NULL);
   1520 
   1521             if (StrStr (RequestElement, QuestionName) == NULL) {
   1522               //
   1523               // This question is not in the current configuration string. Skip it.
   1524               //
   1525               break;
   1526             }
   1527 
   1528             Status = GetValueFromRequest (RequestElement, QuestionName, &VarValue);
   1529             if (EFI_ERROR (Status)) {
   1530               return Status;
   1531             }
   1532           } else {
   1533             //
   1534             // Get Offset by Question header
   1535             //
   1536             Offset = IfrCheckBox->Question.VarStoreInfo.VarOffset;
   1537             Width  = (UINT16) sizeof (BOOLEAN);
   1538             //
   1539             // Check whether this question is in current block array.
   1540             //
   1541             if (!BlockArrayCheck (CurrentBlockArray, Offset, Width)) {
   1542               //
   1543               // This question is not in the current configuration string. Skip it.
   1544               //
   1545               break;
   1546             }
   1547             //
   1548             // Check this var question is in the var storage
   1549             //
   1550             if ((Offset + Width) > VarStoreData.Size) {
   1551               //
   1552               // This question exceeds the var store size.
   1553               //
   1554               return EFI_INVALID_PARAMETER;
   1555             }
   1556             //
   1557             // Check the current value is in the numeric range.
   1558             //
   1559             VarValue = 0;
   1560             CopyMem (&VarValue, VarBuffer +  Offset, Width);
   1561           }
   1562           //
   1563           // Boolean type, only 1 and 0 is valid.
   1564           //
   1565           if (VarValue > 1) {
   1566             return EFI_INVALID_PARAMETER;
   1567           }
   1568           break;
   1569         case EFI_IFR_STRING_OP:
   1570           //
   1571           // Check current string length is less than maxsize
   1572           //
   1573 
   1574           //
   1575           // CheckBox question is not in IFR Form. This IFR form is not valid.
   1576           //
   1577           if (VarStoreData.VarStoreId == 0) {
   1578             return EFI_INVALID_PARAMETER;
   1579           }
   1580 
   1581           //
   1582           // Check whether this question is for the requested varstore.
   1583           //
   1584           IfrString = (EFI_IFR_STRING *) IfrOpHdr;
   1585           if (IfrString->Question.VarStoreId != VarStoreData.VarStoreId) {
   1586             break;
   1587           }
   1588           //
   1589           // Get Width by OneOf Flags
   1590           //
   1591           Width  = (UINT16) (IfrString->MaxSize * sizeof (UINT16));
   1592           if (NameValueType) {
   1593             QuestionName = HiiGetString (HiiHandle, IfrString->Question.VarStoreInfo.VarName, NULL);
   1594             ASSERT (QuestionName != NULL);
   1595 
   1596             StringPtr = StrStr (RequestElement, QuestionName);
   1597             if (StringPtr == NULL) {
   1598               //
   1599               // This question is not in the current configuration string. Skip it.
   1600               //
   1601               break;
   1602             }
   1603 
   1604             //
   1605             // Skip the "=".
   1606             //
   1607             StringPtr += 1;
   1608 
   1609             //
   1610             // Check current string length is less than maxsize
   1611             //
   1612             if (StrSize (StringPtr) > Width) {
   1613               return EFI_INVALID_PARAMETER;
   1614             }
   1615           } else {
   1616             //
   1617             // Get Offset/Width by Question header and OneOf Flags
   1618             //
   1619             Offset = IfrString->Question.VarStoreInfo.VarOffset;
   1620             //
   1621             // Check whether this question is in current block array.
   1622             //
   1623             if (!BlockArrayCheck (CurrentBlockArray, Offset, Width)) {
   1624               //
   1625               // This question is not in the current configuration string. Skip it.
   1626               //
   1627               break;
   1628             }
   1629             //
   1630             // Check this var question is in the var storage
   1631             //
   1632             if ((Offset + Width) > VarStoreData.Size) {
   1633               //
   1634               // This question exceeds the var store size.
   1635               //
   1636               return EFI_INVALID_PARAMETER;
   1637             }
   1638 
   1639             //
   1640             // Check current string length is less than maxsize
   1641             //
   1642             if (StrSize ((CHAR16 *) (VarBuffer + Offset)) > Width) {
   1643               return EFI_INVALID_PARAMETER;
   1644             }
   1645           }
   1646           break;
   1647         case EFI_IFR_ONE_OF_OPTION_OP:
   1648           //
   1649           // Opcode Scope is zero. This one of option is not to be checked.
   1650           //
   1651           if (VarBlockData.Scope == 0) {
   1652             break;
   1653           }
   1654 
   1655           //
   1656           // Only check for OneOf and OrderList opcode
   1657           //
   1658           IfrOneOfOption = (EFI_IFR_ONE_OF_OPTION *) IfrOpHdr;
   1659           if (VarBlockData.OpCode == EFI_IFR_ONE_OF_OP) {
   1660             //
   1661             // Check current value is the value of one of option.
   1662             //
   1663             ASSERT (IfrOneOfOption->Type <= EFI_IFR_TYPE_NUM_SIZE_64);
   1664             ZeroMem (&TmpValue, sizeof (EFI_IFR_TYPE_VALUE));
   1665             CopyMem (&TmpValue, &IfrOneOfOption->Value, IfrOneOfOption->Header.Length - OFFSET_OF (EFI_IFR_ONE_OF_OPTION, Value));
   1666             if (VarValue == TmpValue.u64) {
   1667               //
   1668               // The value is one of option value.
   1669               // Set OpCode to Zero, don't need check again.
   1670               //
   1671               VarBlockData.OpCode = 0;
   1672             }
   1673           }
   1674           break;
   1675         case EFI_IFR_END_OP:
   1676           //
   1677           // Decrease opcode scope for the validated opcode
   1678           //
   1679           if (VarBlockData.Scope > 0) {
   1680             VarBlockData.Scope --;
   1681           }
   1682 
   1683           //
   1684           // OneOf value doesn't belong to one of option value.
   1685           //
   1686           if ((VarBlockData.Scope == 0) && (VarBlockData.OpCode == EFI_IFR_ONE_OF_OP)) {
   1687             return EFI_INVALID_PARAMETER;
   1688           }
   1689           break;
   1690         default:
   1691           //
   1692           // Increase Scope for the validated opcode
   1693           //
   1694           if (VarBlockData.Scope > 0) {
   1695             VarBlockData.Scope = (UINT8) (VarBlockData.Scope + IfrOpHdr->Scope);
   1696           }
   1697           break;
   1698         }
   1699         //
   1700         // Go to the next opcode
   1701         //
   1702         IfrOffset += IfrOpHdr->Length;
   1703       }
   1704       //
   1705       // Only one form is in a package list.
   1706       //
   1707       break;
   1708     }
   1709 
   1710     //
   1711     // Go to next package.
   1712     //
   1713     PackageOffset += PackageHeader.Length;
   1714   }
   1715 
   1716   return EFI_SUCCESS;
   1717 }
   1718 
   1719 /**
   1720   This internal function parses IFR data to validate current setting.
   1721 
   1722   @param ConfigElement         ConfigResp element string contains the current setting.
   1723   @param CurrentBlockArray     Current block array.
   1724   @param VarBuffer             Data buffer for this varstore.
   1725 
   1726   @retval EFI_SUCCESS            The current setting is valid.
   1727   @retval EFI_OUT_OF_RESOURCES   The memory is not enough.
   1728   @retval EFI_INVALID_PARAMETER  The config string or the Hii package is invalid.
   1729 **/
   1730 EFI_STATUS
   1731 GetBlockDataInfo (
   1732   IN  CHAR16                        *ConfigElement,
   1733   OUT IFR_BLOCK_DATA                **CurrentBlockArray,
   1734   OUT UINT8                         **VarBuffer
   1735   )
   1736 {
   1737   IFR_BLOCK_DATA               *BlockData;
   1738   IFR_BLOCK_DATA               *NewBlockData;
   1739   EFI_STRING                   StringPtr;
   1740   UINTN                        Length;
   1741   UINT8                        *TmpBuffer;
   1742   UINT16                       Offset;
   1743   UINT16                       Width;
   1744   LIST_ENTRY                   *Link;
   1745   UINTN                        MaxBufferSize;
   1746   EFI_STATUS                   Status;
   1747   IFR_BLOCK_DATA               *BlockArray;
   1748   UINT8                        *DataBuffer;
   1749 
   1750   //
   1751   // Initialize the local variables.
   1752   //
   1753   Status        = EFI_SUCCESS;
   1754   BlockData     = NULL;
   1755   NewBlockData  = NULL;
   1756   TmpBuffer     = NULL;
   1757   BlockArray    = NULL;
   1758   MaxBufferSize = HII_LIB_DEFAULT_VARSTORE_SIZE;
   1759   DataBuffer     = AllocateZeroPool (MaxBufferSize);
   1760   if (DataBuffer == NULL) {
   1761     return EFI_OUT_OF_RESOURCES;
   1762   }
   1763 
   1764   //
   1765   // Init BlockArray
   1766   //
   1767   BlockArray = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));
   1768   if (BlockArray == NULL) {
   1769     Status = EFI_OUT_OF_RESOURCES;
   1770     goto Done;
   1771   }
   1772   InitializeListHead (&BlockArray->Entry);
   1773 
   1774   StringPtr = StrStr (ConfigElement, L"&OFFSET=");
   1775   ASSERT (StringPtr != NULL);
   1776 
   1777   //
   1778   // Parse each <RequestElement> if exists
   1779   // Only <BlockName> format is supported by this help function.
   1780   // <BlockName> ::= &'OFFSET='<Number>&'WIDTH='<Number>
   1781   //
   1782   while (*StringPtr != 0 && StrnCmp (StringPtr, L"&OFFSET=", StrLen (L"&OFFSET=")) == 0) {
   1783     //
   1784     // Skip the &OFFSET= string
   1785     //
   1786     StringPtr += StrLen (L"&OFFSET=");
   1787 
   1788     //
   1789     // Get Offset
   1790     //
   1791     Status = InternalHiiGetValueOfNumber (StringPtr, &TmpBuffer, &Length);
   1792     if (EFI_ERROR (Status)) {
   1793       goto Done;
   1794     }
   1795     Offset = 0;
   1796     CopyMem (
   1797       &Offset,
   1798       TmpBuffer,
   1799       (((Length + 1) / 2) < sizeof (UINT16)) ? ((Length + 1) / 2) : sizeof (UINT16)
   1800       );
   1801     FreePool (TmpBuffer);
   1802     TmpBuffer = NULL;
   1803 
   1804     StringPtr += Length;
   1805     if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {
   1806       Status = EFI_INVALID_PARAMETER;
   1807       goto Done;
   1808     }
   1809     StringPtr += StrLen (L"&WIDTH=");
   1810 
   1811     //
   1812     // Get Width
   1813     //
   1814     Status = InternalHiiGetValueOfNumber (StringPtr, &TmpBuffer, &Length);
   1815     if (EFI_ERROR (Status)) {
   1816       goto Done;
   1817     }
   1818     Width = 0;
   1819     CopyMem (
   1820       &Width,
   1821       TmpBuffer,
   1822       (((Length + 1) / 2) < sizeof (UINT16)) ? ((Length + 1) / 2) : sizeof (UINT16)
   1823       );
   1824     FreePool (TmpBuffer);
   1825     TmpBuffer = NULL;
   1826 
   1827     StringPtr += Length;
   1828     if (*StringPtr != 0 && *StringPtr != L'&') {
   1829       Status = EFI_INVALID_PARAMETER;
   1830       goto Done;
   1831     }
   1832 
   1833     if (StrnCmp (StringPtr, L"&VALUE=", StrLen (L"&VALUE=")) != 0) {
   1834       Status = EFI_INVALID_PARAMETER;
   1835       goto Done;
   1836     }
   1837     StringPtr += StrLen (L"&VALUE=");
   1838 
   1839     //
   1840     // Get Value
   1841     //
   1842     Status = InternalHiiGetValueOfNumber (StringPtr, &TmpBuffer, &Length);
   1843     if (EFI_ERROR (Status)) {
   1844       goto Done;
   1845     }
   1846 
   1847     StringPtr += Length;
   1848     if (*StringPtr != 0 && *StringPtr != L'&') {
   1849       Status = EFI_INVALID_PARAMETER;
   1850       goto Done;
   1851     }
   1852 
   1853     //
   1854     // Check whether VarBuffer is enough
   1855     //
   1856     if ((UINTN) (Offset + Width) > MaxBufferSize) {
   1857       DataBuffer = ReallocatePool (
   1858                     MaxBufferSize,
   1859                     Offset + Width + HII_LIB_DEFAULT_VARSTORE_SIZE,
   1860                     DataBuffer
   1861                     );
   1862       if (DataBuffer == NULL) {
   1863         Status = EFI_OUT_OF_RESOURCES;
   1864         goto Done;
   1865       }
   1866       MaxBufferSize = Offset + Width + HII_LIB_DEFAULT_VARSTORE_SIZE;
   1867     }
   1868 
   1869     //
   1870     // Update the Block with configuration info
   1871     //
   1872     CopyMem (DataBuffer + Offset, TmpBuffer, Width);
   1873     FreePool (TmpBuffer);
   1874     TmpBuffer = NULL;
   1875 
   1876     //
   1877     // Set new Block Data
   1878     //
   1879     NewBlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));
   1880     if (NewBlockData == NULL) {
   1881       Status = EFI_OUT_OF_RESOURCES;
   1882       goto Done;
   1883     }
   1884     NewBlockData->Offset = Offset;
   1885     NewBlockData->Width  = Width;
   1886 
   1887     //
   1888     // Insert the new block data into the block data array.
   1889     //
   1890     for (Link = BlockArray->Entry.ForwardLink; Link != &BlockArray->Entry; Link = Link->ForwardLink) {
   1891       BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);
   1892       if (NewBlockData->Offset == BlockData->Offset) {
   1893         if (NewBlockData->Width > BlockData->Width) {
   1894           BlockData->Width = NewBlockData->Width;
   1895         }
   1896         FreePool (NewBlockData);
   1897         break;
   1898       } else if (NewBlockData->Offset < BlockData->Offset) {
   1899         //
   1900         // Insert new block data as the previous one of this link.
   1901         //
   1902         InsertTailList (Link, &NewBlockData->Entry);
   1903         break;
   1904       }
   1905     }
   1906 
   1907     //
   1908     // Insert new block data into the array tail.
   1909     //
   1910     if (Link == &BlockArray->Entry) {
   1911       InsertTailList (Link, &NewBlockData->Entry);
   1912     }
   1913 
   1914     //
   1915     // If '\0', parsing is finished.
   1916     //
   1917     if (*StringPtr == 0) {
   1918       break;
   1919     }
   1920     //
   1921     // Go to next ConfigBlock
   1922     //
   1923   }
   1924 
   1925   //
   1926   // Merge the aligned block data into the single block data.
   1927   //
   1928   Link = BlockArray->Entry.ForwardLink;
   1929   while ((Link != &BlockArray->Entry) && (Link->ForwardLink != &BlockArray->Entry)) {
   1930     BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);
   1931     NewBlockData = BASE_CR (Link->ForwardLink, IFR_BLOCK_DATA, Entry);
   1932     if ((NewBlockData->Offset >= BlockData->Offset) && (NewBlockData->Offset <= (BlockData->Offset + BlockData->Width))) {
   1933       if ((NewBlockData->Offset + NewBlockData->Width) > (BlockData->Offset + BlockData->Width)) {
   1934         BlockData->Width = (UINT16) (NewBlockData->Offset + NewBlockData->Width - BlockData->Offset);
   1935       }
   1936       RemoveEntryList (Link->ForwardLink);
   1937       FreePool (NewBlockData);
   1938       continue;
   1939     }
   1940     Link = Link->ForwardLink;
   1941   }
   1942 
   1943   *VarBuffer         = DataBuffer;
   1944   *CurrentBlockArray = BlockArray;
   1945   return EFI_SUCCESS;
   1946 
   1947 Done:
   1948   if (DataBuffer != NULL) {
   1949     FreePool (DataBuffer);
   1950   }
   1951 
   1952   if (BlockArray != NULL) {
   1953     //
   1954     // Free Link Array CurrentBlockArray
   1955     //
   1956     while (!IsListEmpty (&BlockArray->Entry)) {
   1957       BlockData = BASE_CR (BlockArray->Entry.ForwardLink, IFR_BLOCK_DATA, Entry);
   1958       RemoveEntryList (&BlockData->Entry);
   1959       FreePool (BlockData);
   1960     }
   1961     FreePool (BlockArray);
   1962   }
   1963 
   1964   return Status;
   1965 }
   1966 
   1967 /**
   1968   This internal function parses IFR data to validate current setting.
   1969 
   1970   @param ConfigResp         ConfigResp string contains the current setting.
   1971   @param HiiPackageList     Point to Hii package list.
   1972   @param PackageListLength  The length of the pacakge.
   1973   @param VarGuid            Guid of the buffer storage.
   1974   @param VarName            Name of the buffer storage.
   1975   @param HiiHandle          The HiiHandle for this package.
   1976 
   1977   @retval EFI_SUCCESS            The current setting is valid.
   1978   @retval EFI_OUT_OF_RESOURCES   The memory is not enough.
   1979   @retval EFI_INVALID_PARAMETER  The config string or the Hii package is invalid.
   1980 **/
   1981 EFI_STATUS
   1982 EFIAPI
   1983 InternalHiiValidateCurrentSetting (
   1984   IN EFI_STRING                    ConfigResp,
   1985   IN EFI_HII_PACKAGE_LIST_HEADER   *HiiPackageList,
   1986   IN UINTN                         PackageListLength,
   1987   IN EFI_GUID                      *VarGuid,
   1988   IN CHAR16                        *VarName,
   1989   IN EFI_HII_HANDLE                HiiHandle
   1990   )
   1991 {
   1992   CHAR16              *StringPtr;
   1993   EFI_STATUS          Status;
   1994   IFR_BLOCK_DATA      *CurrentBlockArray;
   1995   IFR_BLOCK_DATA      *BlockData;
   1996   UINT8               *VarBuffer;
   1997   BOOLEAN             NameValueType;
   1998 
   1999   CurrentBlockArray = NULL;
   2000   VarBuffer         = NULL;
   2001   StringPtr         = NULL;
   2002   Status            = EFI_SUCCESS;
   2003 
   2004   //
   2005   // If StringPtr != NULL, get the request elements.
   2006   //
   2007   if (StrStr (ConfigResp, L"&OFFSET=") != NULL) {
   2008     Status = GetBlockDataInfo(ConfigResp, &CurrentBlockArray, &VarBuffer);
   2009     if (EFI_ERROR (Status)) {
   2010       return Status;
   2011     }
   2012     NameValueType = FALSE;
   2013   } else {
   2014     //
   2015     // Skip header part.
   2016     //
   2017     StringPtr = StrStr (ConfigResp, L"PATH=");
   2018     ASSERT (StringPtr != NULL);
   2019 
   2020     if (StrStr (StringPtr, L"&") != NULL) {
   2021       NameValueType = TRUE;
   2022     } else {
   2023       //
   2024       // Not found Request element, return success.
   2025       //
   2026       return EFI_SUCCESS;
   2027     }
   2028   }
   2029 
   2030   Status = ValidateQuestionFromVfr(
   2031                           HiiPackageList,
   2032                           PackageListLength,
   2033                           VarGuid,
   2034                           VarName,
   2035                           VarBuffer,
   2036                           CurrentBlockArray,
   2037                           ConfigResp,
   2038                           HiiHandle,
   2039                           NameValueType
   2040                           );
   2041 
   2042   if (VarBuffer != NULL) {
   2043     FreePool (VarBuffer);
   2044   }
   2045 
   2046   if (CurrentBlockArray != NULL) {
   2047     //
   2048     // Free Link Array CurrentBlockArray
   2049     //
   2050     while (!IsListEmpty (&CurrentBlockArray->Entry)) {
   2051       BlockData = BASE_CR (CurrentBlockArray->Entry.ForwardLink, IFR_BLOCK_DATA, Entry);
   2052       RemoveEntryList (&BlockData->Entry);
   2053       FreePool (BlockData);
   2054     }
   2055     FreePool (CurrentBlockArray);
   2056   }
   2057 
   2058   return Status;
   2059 }
   2060 
   2061 /**
   2062   Check whether the ConfigRequest string has the request elements.
   2063   For EFI_HII_VARSTORE_BUFFER type, the request has "&OFFSET=****&WIDTH=****..." format.
   2064   For EFI_HII_VARSTORE_NAME_VALUE type, the request has "&NAME1**&NAME2..." format.
   2065 
   2066   @param  ConfigRequest      The input config request string.
   2067 
   2068   @retval  TRUE              The input include config request elements.
   2069   @retval  FALSE             The input string not includes.
   2070 
   2071 **/
   2072 BOOLEAN
   2073 GetElementsFromRequest (
   2074   IN EFI_STRING    ConfigRequest
   2075   )
   2076 {
   2077   EFI_STRING   TmpRequest;
   2078 
   2079   TmpRequest = StrStr (ConfigRequest, L"PATH=");
   2080   ASSERT (TmpRequest != NULL);
   2081 
   2082   if ((StrStr (TmpRequest, L"&OFFSET=") != NULL) || (StrStr (TmpRequest, L"&") != NULL)) {
   2083     return TRUE;
   2084   }
   2085 
   2086   return FALSE;
   2087 }
   2088 
   2089 /**
   2090   This function parses the input ConfigRequest string and its matched IFR code
   2091   string for setting default value and validating current setting.
   2092 
   2093   1. For setting default action, Reset the default value specified by DefaultId
   2094   to the driver configuration got by Request string.
   2095   2. For validating current setting, Validate the current configuration
   2096   by parsing HII form IFR opcode.
   2097 
   2098   NULL request string support depends on the ExportConfig interface of
   2099   HiiConfigRouting protocol in UEFI specification.
   2100 
   2101   @param Request    A null-terminated Unicode string in
   2102                     <MultiConfigRequest> format. It can be NULL.
   2103                     If it is NULL, all current configuration for the
   2104                     entirety of the current HII database will be validated.
   2105                     If it is NULL, all configuration for the
   2106                     entirety of the current HII database will be reset.
   2107   @param DefaultId  Specifies the type of defaults to retrieve only for setting default action.
   2108   @param ActionType Action supports setting defaults and validate current setting.
   2109 
   2110   @retval TRUE    Action runs successfully.
   2111   @retval FALSE   Action is not valid or Action can't be executed successfully..
   2112 **/
   2113 BOOLEAN
   2114 EFIAPI
   2115 InternalHiiIfrValueAction (
   2116   IN CONST EFI_STRING Request,  OPTIONAL
   2117   IN UINT16           DefaultId,
   2118   IN UINT8            ActionType
   2119   )
   2120 {
   2121   EFI_STRING     ConfigAltResp;
   2122   EFI_STRING     ConfigAltHdr;
   2123   EFI_STRING     ConfigResp;
   2124   EFI_STRING     Progress;
   2125   EFI_STRING     StringPtr;
   2126   EFI_STRING     StringHdr;
   2127   EFI_STATUS     Status;
   2128   EFI_HANDLE     DriverHandle;
   2129   EFI_HANDLE     TempDriverHandle;
   2130   EFI_HII_HANDLE *HiiHandleBuffer;
   2131   EFI_HII_HANDLE HiiHandle;
   2132   UINT32         Index;
   2133   EFI_GUID       *VarGuid;
   2134   EFI_STRING     VarName;
   2135 
   2136   EFI_HII_PACKAGE_LIST_HEADER  *HiiPackageList;
   2137   UINTN                        PackageListLength;
   2138   UINTN                        MaxLen;
   2139   EFI_DEVICE_PATH_PROTOCOL     *DevicePath;
   2140   EFI_DEVICE_PATH_PROTOCOL     *TempDevicePath;
   2141 
   2142   ConfigAltResp = NULL;
   2143   ConfigResp    = NULL;
   2144   VarGuid       = NULL;
   2145   VarName       = NULL;
   2146   DevicePath    = NULL;
   2147   ConfigAltHdr  = NULL;
   2148   HiiHandleBuffer  = NULL;
   2149   Index            = 0;
   2150   TempDriverHandle = NULL;
   2151   HiiHandle        = NULL;
   2152   HiiPackageList   = NULL;
   2153 
   2154   //
   2155   // Only support set default and validate setting action.
   2156   //
   2157   if ((ActionType != ACTION_SET_DEFAUTL_VALUE) && (ActionType != ACTION_VALIDATE_SETTING)) {
   2158     return FALSE;
   2159   }
   2160 
   2161   //
   2162   // Get the full requested value and deault value string.
   2163   //
   2164   if (Request != NULL) {
   2165     Status = gHiiConfigRouting->ExtractConfig (
   2166                                   gHiiConfigRouting,
   2167                                   Request,
   2168                                   &Progress,
   2169                                   &ConfigAltResp
   2170                                 );
   2171   } else {
   2172     Status = gHiiConfigRouting->ExportConfig (
   2173                                   gHiiConfigRouting,
   2174                                   &ConfigAltResp
   2175                                 );
   2176   }
   2177 
   2178   if (EFI_ERROR (Status)) {
   2179     return FALSE;
   2180   }
   2181 
   2182   StringPtr = ConfigAltResp;
   2183   ASSERT (StringPtr != NULL);
   2184 
   2185   while (*StringPtr != L'\0') {
   2186     //
   2187     // 1. Find <ConfigHdr> GUID=...&NAME=...&PATH=...
   2188     //
   2189     StringHdr = StringPtr;
   2190 
   2191     //
   2192     // Get Guid value
   2193     //
   2194     if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {
   2195       Status = EFI_INVALID_PARAMETER;
   2196       goto Done;
   2197     }
   2198     StringPtr += StrLen (L"GUID=");
   2199     Status = InternalHiiGetBufferFromString (StringPtr, GUID_CONFIG_STRING_TYPE, (UINT8 **) &VarGuid);
   2200     if (EFI_ERROR (Status)) {
   2201       goto Done;
   2202     }
   2203 
   2204     //
   2205     // Get Name value VarName
   2206     //
   2207     while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&NAME=", StrLen (L"&NAME=")) != 0) {
   2208       StringPtr++;
   2209     }
   2210     if (*StringPtr == L'\0') {
   2211       Status = EFI_INVALID_PARAMETER;
   2212       goto Done;
   2213     }
   2214     StringPtr += StrLen (L"&NAME=");
   2215     Status = InternalHiiGetBufferFromString (StringPtr, NAME_CONFIG_STRING_TYPE, (UINT8 **) &VarName);
   2216     if (EFI_ERROR (Status)) {
   2217       goto Done;
   2218     }
   2219 
   2220     //
   2221     // Get Path value DevicePath
   2222     //
   2223     while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&PATH=", StrLen (L"&PATH=")) != 0) {
   2224       StringPtr++;
   2225     }
   2226     if (*StringPtr == L'\0') {
   2227       Status = EFI_INVALID_PARAMETER;
   2228       goto Done;
   2229     }
   2230     StringPtr += StrLen (L"&PATH=");
   2231     Status = InternalHiiGetBufferFromString (StringPtr, PATH_CONFIG_STRING_TYPE, (UINT8 **) &DevicePath);
   2232     if (EFI_ERROR (Status)) {
   2233       goto Done;
   2234     }
   2235 
   2236     //
   2237     // Get the Driver handle by the got device path.
   2238     //
   2239     TempDevicePath = DevicePath;
   2240     Status = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &TempDevicePath, &DriverHandle);
   2241     if (EFI_ERROR (Status)) {
   2242       goto Done;
   2243     }
   2244 
   2245     //
   2246     // Find the matched Hii Handle for the found Driver handle
   2247     //
   2248     HiiHandleBuffer = HiiGetHiiHandles (NULL);
   2249     if (HiiHandleBuffer == NULL) {
   2250       Status = EFI_NOT_FOUND;
   2251       goto Done;
   2252     }
   2253 
   2254     for (Index = 0; HiiHandleBuffer[Index] != NULL; Index ++) {
   2255       gHiiDatabase->GetPackageListHandle (gHiiDatabase, HiiHandleBuffer[Index], &TempDriverHandle);
   2256       if (TempDriverHandle == DriverHandle) {
   2257         break;
   2258       }
   2259     }
   2260 
   2261     HiiHandle = HiiHandleBuffer[Index];
   2262     FreePool (HiiHandleBuffer);
   2263 
   2264     if (HiiHandle == NULL) {
   2265       //
   2266       // This request string has no its Hii package.
   2267       // Its default value and validating can't execute by parsing IFR data.
   2268       // Directly jump into the next ConfigAltResp string for another pair Guid, Name, and Path.
   2269       //
   2270       Status = EFI_SUCCESS;
   2271       goto NextConfigAltResp;
   2272     }
   2273 
   2274     //
   2275     // 2. Get HiiPackage by HiiHandle
   2276     //
   2277     PackageListLength  = 0;
   2278     HiiPackageList     = NULL;
   2279     Status = gHiiDatabase->ExportPackageLists (gHiiDatabase, HiiHandle, &PackageListLength, HiiPackageList);
   2280 
   2281     //
   2282     // The return status should always be EFI_BUFFER_TOO_SMALL as input buffer's size is 0.
   2283     //
   2284     if (Status != EFI_BUFFER_TOO_SMALL) {
   2285       Status = EFI_INVALID_PARAMETER;
   2286       goto Done;
   2287     }
   2288 
   2289     HiiPackageList = AllocatePool (PackageListLength);
   2290     if (HiiPackageList == NULL) {
   2291       Status = EFI_OUT_OF_RESOURCES;
   2292       goto Done;
   2293     }
   2294 
   2295     //
   2296     // Get PackageList on HiiHandle
   2297     //
   2298     Status = gHiiDatabase->ExportPackageLists (gHiiDatabase, HiiHandle, &PackageListLength, HiiPackageList);
   2299     if (EFI_ERROR (Status)) {
   2300       goto Done;
   2301     }
   2302 
   2303     //
   2304     // 3. Call ConfigRouting GetAltCfg(ConfigRoute, <ConfigResponse>, Guid, Name, DevicePath, AltCfgId, AltCfgResp)
   2305     //    Get the default configuration string according to the default ID.
   2306     //
   2307     Status = gHiiConfigRouting->GetAltConfig (
   2308                                   gHiiConfigRouting,
   2309                                   ConfigAltResp,
   2310                                   VarGuid,
   2311                                   VarName,
   2312                                   DevicePath,
   2313                                   (ActionType == ACTION_SET_DEFAUTL_VALUE) ? &DefaultId:NULL,  // it can be NULL to get the current setting.
   2314                                   &ConfigResp
   2315                                 );
   2316 
   2317     //
   2318     // The required setting can't be found. So, it is not required to be validated and set.
   2319     //
   2320     if (EFI_ERROR (Status)) {
   2321       Status = EFI_SUCCESS;
   2322       goto NextConfigAltResp;
   2323     }
   2324     //
   2325     // Only the ConfigHdr is found. Not any block data is found. No data is required to be validated and set.
   2326     //
   2327     if (!GetElementsFromRequest (ConfigResp)) {
   2328       goto NextConfigAltResp;
   2329     }
   2330 
   2331     //
   2332     // 4. Set the default configuration information or Validate current setting by parse IFR code.
   2333     //    Current Setting is in ConfigResp, will be set into buffer, then check it again.
   2334     //
   2335     if (ActionType == ACTION_SET_DEFAUTL_VALUE) {
   2336       //
   2337       // Set the default configuration information.
   2338       //
   2339       Status = gHiiConfigRouting->RouteConfig (gHiiConfigRouting, ConfigResp, &Progress);
   2340     } else {
   2341       //
   2342       // Current Setting is in ConfigResp, will be set into buffer, then check it again.
   2343       //
   2344       Status = InternalHiiValidateCurrentSetting (ConfigResp, HiiPackageList, PackageListLength, VarGuid, VarName, HiiHandle);
   2345     }
   2346 
   2347     if (EFI_ERROR (Status)) {
   2348       goto Done;
   2349     }
   2350 
   2351 NextConfigAltResp:
   2352     //
   2353     // Free the allocated pacakge buffer and the got ConfigResp string.
   2354     //
   2355     if (HiiPackageList != NULL) {
   2356       FreePool (HiiPackageList);
   2357       HiiPackageList = NULL;
   2358     }
   2359 
   2360     if (ConfigResp != NULL) {
   2361       FreePool (ConfigResp);
   2362       ConfigResp = NULL;
   2363     }
   2364 
   2365     //
   2366     // Free the allocated buffer.
   2367     //
   2368     FreePool (VarGuid);
   2369     VarGuid = NULL;
   2370 
   2371     FreePool (VarName);
   2372     VarName = NULL;
   2373 
   2374     FreePool (DevicePath);
   2375     DevicePath = NULL;
   2376 
   2377     //
   2378     // 5. Jump to next ConfigAltResp for another Guid, Name, Path.
   2379     //
   2380 
   2381     //
   2382     // Get and Skip ConfigHdr
   2383     //
   2384     while (*StringPtr != L'\0' && *StringPtr != L'&') {
   2385       StringPtr++;
   2386     }
   2387     if (*StringPtr == L'\0') {
   2388       break;
   2389     }
   2390 
   2391     //
   2392     // Construct ConfigAltHdr string  "&<ConfigHdr>&ALTCFG=\0"
   2393     //                               | 1 | StrLen (ConfigHdr) | 8 | 1 |
   2394     //
   2395     MaxLen = 1 + StringPtr - StringHdr + 8 + 1;
   2396     ConfigAltHdr = AllocateZeroPool ( MaxLen * sizeof (CHAR16));
   2397     if (ConfigAltHdr == NULL) {
   2398       Status = EFI_OUT_OF_RESOURCES;
   2399       goto Done;
   2400     }
   2401     StrCpyS (ConfigAltHdr, MaxLen, L"&");
   2402     StrnCatS (ConfigAltHdr, MaxLen, StringHdr, StringPtr - StringHdr);
   2403     StrCatS (ConfigAltHdr, MaxLen, L"&ALTCFG=");
   2404 
   2405     //
   2406     // Skip all AltResp (AltConfigHdr ConfigBody) for the same ConfigHdr
   2407     //
   2408     while ((StringHdr = StrStr (StringPtr, ConfigAltHdr)) != NULL) {
   2409       StringPtr = StringHdr + StrLen (ConfigAltHdr);
   2410       if (*StringPtr == L'\0') {
   2411         break;
   2412       }
   2413     }
   2414 
   2415     //
   2416     // Free the allocated ConfigAltHdr string
   2417     //
   2418     FreePool (ConfigAltHdr);
   2419     if (*StringPtr == L'\0') {
   2420       break;
   2421     }
   2422 
   2423     //
   2424     // Find &GUID as the next ConfigHdr
   2425     //
   2426     StringPtr = StrStr (StringPtr, L"&GUID");
   2427     if (StringPtr == NULL) {
   2428       break;
   2429     }
   2430 
   2431     //
   2432     // Skip char '&'
   2433     //
   2434     StringPtr ++;
   2435   }
   2436 
   2437 Done:
   2438   if (VarGuid != NULL) {
   2439     FreePool (VarGuid);
   2440   }
   2441 
   2442   if (VarName != NULL) {
   2443     FreePool (VarName);
   2444   }
   2445 
   2446   if (DevicePath != NULL) {
   2447     FreePool (DevicePath);
   2448   }
   2449 
   2450   if (ConfigResp != NULL) {
   2451     FreePool (ConfigResp);
   2452   }
   2453 
   2454   if (ConfigAltResp != NULL) {
   2455     FreePool (ConfigAltResp);
   2456   }
   2457 
   2458   if (HiiPackageList != NULL) {
   2459     FreePool (HiiPackageList);
   2460   }
   2461 
   2462   if (EFI_ERROR (Status)) {
   2463     return FALSE;
   2464   }
   2465 
   2466   return TRUE;
   2467 }
   2468 
   2469 /**
   2470   Validate the current configuration by parsing HII form IFR opcode.
   2471 
   2472   NULL request string support depends on the ExportConfig interface of
   2473   HiiConfigRouting protocol in UEFI specification.
   2474 
   2475   @param  Request   A null-terminated Unicode string in
   2476                     <MultiConfigRequest> format. It can be NULL.
   2477                     If it is NULL, all current configuration for the
   2478                     entirety of the current HII database will be validated.
   2479 
   2480   @retval TRUE    Current configuration is valid.
   2481   @retval FALSE   Current configuration is invalid.
   2482 **/
   2483 BOOLEAN
   2484 EFIAPI
   2485 HiiValidateSettings (
   2486   IN CONST EFI_STRING Request  OPTIONAL
   2487   )
   2488 {
   2489   return InternalHiiIfrValueAction (Request, 0, ACTION_VALIDATE_SETTING);
   2490 }
   2491 
   2492 /**
   2493   Reset the default value specified by DefaultId to the driver
   2494   configuration got by Request string.
   2495 
   2496   NULL request string support depends on the ExportConfig interface of
   2497   HiiConfigRouting protocol in UEFI specification.
   2498 
   2499   @param Request    A null-terminated Unicode string in
   2500                     <MultiConfigRequest> format. It can be NULL.
   2501                     If it is NULL, all configuration for the
   2502                     entirety of the current HII database will be reset.
   2503   @param DefaultId  Specifies the type of defaults to retrieve.
   2504 
   2505   @retval TRUE    The default value is set successfully.
   2506   @retval FALSE   The default value can't be found and set.
   2507 **/
   2508 BOOLEAN
   2509 EFIAPI
   2510 HiiSetToDefaults (
   2511   IN CONST EFI_STRING Request,  OPTIONAL
   2512   IN UINT16        DefaultId
   2513   )
   2514 {
   2515   return InternalHiiIfrValueAction (Request, DefaultId, ACTION_SET_DEFAUTL_VALUE);
   2516 }
   2517 
   2518 /**
   2519   Determines if two values in config strings match.
   2520 
   2521   Compares the substring between StartSearchString and StopSearchString in
   2522   FirstString to the substring between StartSearchString and StopSearchString
   2523   in SecondString.  If the two substrings match, then TRUE is returned.  If the
   2524   two substrings do not match, then FALSE is returned.
   2525 
   2526   If FirstString is NULL, then ASSERT().
   2527   If SecondString is NULL, then ASSERT().
   2528   If StartSearchString is NULL, then ASSERT().
   2529   If StopSearchString is NULL, then ASSERT().
   2530 
   2531   @param FirstString        Pointer to the first Null-terminated Unicode string.
   2532   @param SecondString       Pointer to the second Null-terminated Unicode string.
   2533   @param StartSearchString  Pointer to the Null-terminated Unicode string that
   2534                             marks the start of the value string to compare.
   2535   @param StopSearchString   Pointer to the Null-terminated Unicode string that
   2536                             marks the end of the value string to compare.
   2537 
   2538   @retval FALSE             StartSearchString is not present in FirstString.
   2539   @retval FALSE             StartSearchString is not present in SecondString.
   2540   @retval FALSE             StopSearchString is not present in FirstString.
   2541   @retval FALSE             StopSearchString is not present in SecondString.
   2542   @retval FALSE             The length of the substring in FirstString is not the
   2543                             same length as the substring in SecondString.
   2544   @retval FALSE             The value string in FirstString does not matche the
   2545                             value string in SecondString.
   2546   @retval TRUE              The value string in FirstString matches the value
   2547                             string in SecondString.
   2548 
   2549 **/
   2550 BOOLEAN
   2551 EFIAPI
   2552 InternalHiiCompareSubString (
   2553   IN CHAR16  *FirstString,
   2554   IN CHAR16  *SecondString,
   2555   IN CHAR16  *StartSearchString,
   2556   IN CHAR16  *StopSearchString
   2557   )
   2558 {
   2559   CHAR16  *EndFirstString;
   2560   CHAR16  *EndSecondString;
   2561 
   2562   ASSERT (FirstString != NULL);
   2563   ASSERT (SecondString != NULL);
   2564   ASSERT (StartSearchString != NULL);
   2565   ASSERT (StopSearchString != NULL);
   2566 
   2567   FirstString = StrStr (FirstString, StartSearchString);
   2568   if (FirstString == NULL) {
   2569     return FALSE;
   2570   }
   2571 
   2572   SecondString = StrStr (SecondString, StartSearchString);
   2573   if (SecondString == NULL) {
   2574     return FALSE;
   2575   }
   2576 
   2577   EndFirstString = StrStr (FirstString, StopSearchString);
   2578   if (EndFirstString == NULL) {
   2579     return FALSE;
   2580   }
   2581 
   2582   EndSecondString = StrStr (SecondString, StopSearchString);
   2583   if (EndSecondString == NULL) {
   2584     return FALSE;
   2585   }
   2586 
   2587   if ((EndFirstString - FirstString) != (EndSecondString - SecondString)) {
   2588     return FALSE;
   2589   }
   2590 
   2591   return (BOOLEAN)(StrnCmp (FirstString, SecondString, EndFirstString - FirstString) == 0);
   2592 }
   2593 
   2594 /**
   2595   Determines if the routing data specified by GUID and NAME match a <ConfigHdr>.
   2596 
   2597   If ConfigHdr is NULL, then ASSERT().
   2598 
   2599   @param[in] ConfigHdr  Either <ConfigRequest> or <ConfigResp>.
   2600   @param[in] Guid       GUID of the storage.
   2601   @param[in] Name       NAME of the storage.
   2602 
   2603   @retval TRUE   Routing information matches <ConfigHdr>.
   2604   @retval FALSE  Routing information does not match <ConfigHdr>.
   2605 
   2606 **/
   2607 BOOLEAN
   2608 EFIAPI
   2609 HiiIsConfigHdrMatch (
   2610   IN CONST EFI_STRING  ConfigHdr,
   2611   IN CONST EFI_GUID    *Guid,     OPTIONAL
   2612   IN CONST CHAR16      *Name      OPTIONAL
   2613   )
   2614 {
   2615   EFI_STRING  CompareConfigHdr;
   2616   BOOLEAN     Result;
   2617 
   2618   ASSERT (ConfigHdr != NULL);
   2619 
   2620   //
   2621   // Use Guid and Name to generate a <ConfigHdr> string
   2622   //
   2623   CompareConfigHdr = HiiConstructConfigHdr (Guid, Name, NULL);
   2624   if (CompareConfigHdr == NULL) {
   2625     return FALSE;
   2626   }
   2627 
   2628   Result = TRUE;
   2629   if (Guid != NULL) {
   2630     //
   2631     // Compare GUID value strings
   2632     //
   2633     Result = InternalHiiCompareSubString (ConfigHdr, CompareConfigHdr, L"GUID=", L"&NAME=");
   2634   }
   2635 
   2636   if (Result && Name != NULL) {
   2637     //
   2638     // Compare NAME value strings
   2639     //
   2640     Result = InternalHiiCompareSubString (ConfigHdr, CompareConfigHdr, L"&NAME=", L"&PATH=");
   2641   }
   2642 
   2643   //
   2644   // Free the <ConfigHdr> string
   2645   //
   2646   FreePool (CompareConfigHdr);
   2647 
   2648   return Result;
   2649 }
   2650 
   2651 /**
   2652   Retrieves uncommitted data from the Form Browser and converts it to a binary
   2653   buffer.
   2654 
   2655   @param[in]  VariableGuid  Pointer to an EFI_GUID structure.  This is an optional
   2656                             parameter that may be NULL.
   2657   @param[in]  VariableName  Pointer to a Null-terminated Unicode string.  This
   2658                             is an optional parameter that may be NULL.
   2659   @param[in]  BufferSize    Length in bytes of buffer to hold retrieved data.
   2660   @param[out] Buffer        Buffer of data to be updated.
   2661 
   2662   @retval FALSE  The uncommitted data could not be retrieved.
   2663   @retval TRUE   The uncommitted data was retrieved.
   2664 
   2665 **/
   2666 BOOLEAN
   2667 EFIAPI
   2668 HiiGetBrowserData (
   2669   IN CONST EFI_GUID  *VariableGuid,  OPTIONAL
   2670   IN CONST CHAR16    *VariableName,  OPTIONAL
   2671   IN UINTN           BufferSize,
   2672   OUT UINT8          *Buffer
   2673   )
   2674 {
   2675   EFI_STRING  ResultsData;
   2676   UINTN       Size;
   2677   EFI_STRING  ConfigResp;
   2678   EFI_STATUS  Status;
   2679   CHAR16      *Progress;
   2680 
   2681   //
   2682   // Retrieve the results data from the Browser Callback
   2683   //
   2684   ResultsData = InternalHiiBrowserCallback (VariableGuid, VariableName, NULL);
   2685   if (ResultsData == NULL) {
   2686     return FALSE;
   2687   }
   2688 
   2689   //
   2690   // Construct <ConfigResp> mConfigHdrTemplate L'&' ResultsData L'\0'
   2691   //
   2692   Size = (StrLen (mConfigHdrTemplate) + 1) * sizeof (CHAR16);
   2693   Size = Size + (StrLen (ResultsData) + 1) * sizeof (CHAR16);
   2694   ConfigResp = AllocateZeroPool (Size);
   2695   UnicodeSPrint (ConfigResp, Size, L"%s&%s", mConfigHdrTemplate, ResultsData);
   2696 
   2697   //
   2698   // Free the allocated buffer
   2699   //
   2700   FreePool (ResultsData);
   2701   if (ConfigResp == NULL) {
   2702     return FALSE;
   2703   }
   2704 
   2705   //
   2706   // Convert <ConfigResp> to a buffer
   2707   //
   2708   Status = gHiiConfigRouting->ConfigToBlock (
   2709                                 gHiiConfigRouting,
   2710                                 ConfigResp,
   2711                                 Buffer,
   2712                                 &BufferSize,
   2713                                 &Progress
   2714                                 );
   2715   //
   2716   // Free the allocated buffer
   2717   //
   2718   FreePool (ConfigResp);
   2719 
   2720   if (EFI_ERROR (Status)) {
   2721     return FALSE;
   2722   }
   2723 
   2724   return TRUE;
   2725 }
   2726 
   2727 /**
   2728   Updates uncommitted data in the Form Browser.
   2729 
   2730   If Buffer is NULL, then ASSERT().
   2731 
   2732   @param[in]  VariableGuid    Pointer to an EFI_GUID structure.  This is an optional
   2733                               parameter that may be NULL.
   2734   @param[in]  VariableName    Pointer to a Null-terminated Unicode string.  This
   2735                               is an optional parameter that may be NULL.
   2736   @param[in]  BufferSize      Length, in bytes, of Buffer.
   2737   @param[in]  Buffer          Buffer of data to commit.
   2738   @param[in]  RequestElement  An optional field to specify which part of the
   2739                               buffer data will be send back to Browser. If NULL,
   2740                               the whole buffer of data will be committed to
   2741                               Browser.
   2742                               <RequestElement> ::= &OFFSET=<Number>&WIDTH=<Number>*
   2743 
   2744   @retval FALSE  The uncommitted data could not be updated.
   2745   @retval TRUE   The uncommitted data was updated.
   2746 
   2747 **/
   2748 BOOLEAN
   2749 EFIAPI
   2750 HiiSetBrowserData (
   2751   IN CONST EFI_GUID  *VariableGuid, OPTIONAL
   2752   IN CONST CHAR16    *VariableName, OPTIONAL
   2753   IN UINTN           BufferSize,
   2754   IN CONST UINT8     *Buffer,
   2755   IN CONST CHAR16    *RequestElement  OPTIONAL
   2756   )
   2757 {
   2758   UINTN       Size;
   2759   EFI_STRING  ConfigRequest;
   2760   EFI_STRING  ConfigResp;
   2761   EFI_STRING  ResultsData;
   2762 
   2763   ASSERT (Buffer != NULL);
   2764 
   2765   //
   2766   // Construct <ConfigRequest>
   2767   //
   2768   if (RequestElement == NULL) {
   2769     //
   2770     // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
   2771     // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
   2772     //
   2773     Size = (StrLen (mConfigHdrTemplate) + 32 + 1) * sizeof (CHAR16);
   2774     ConfigRequest = AllocateZeroPool (Size);
   2775     UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", mConfigHdrTemplate, (UINT64)BufferSize);
   2776   } else {
   2777     //
   2778     // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
   2779     // followed by <RequestElement> followed by a Null-terminator
   2780     //
   2781     Size = StrLen (mConfigHdrTemplate) * sizeof (CHAR16);
   2782     Size = Size + (StrLen (RequestElement) + 1) * sizeof (CHAR16);
   2783     ConfigRequest = AllocateZeroPool (Size);
   2784     UnicodeSPrint (ConfigRequest, Size, L"%s%s", mConfigHdrTemplate, RequestElement);
   2785   }
   2786   if (ConfigRequest == NULL) {
   2787     return FALSE;
   2788   }
   2789 
   2790   //
   2791   // Convert <ConfigRequest> to <ConfigResp>
   2792   //
   2793   ConfigResp = InternalHiiBlockToConfig (ConfigRequest, Buffer, BufferSize);
   2794   FreePool (ConfigRequest);
   2795   if (ConfigResp == NULL) {
   2796     return FALSE;
   2797   }
   2798 
   2799   //
   2800   // Set data in the uncommitted browser state information
   2801   //
   2802   ResultsData = InternalHiiBrowserCallback (VariableGuid, VariableName, ConfigResp + StrLen(mConfigHdrTemplate) + 1);
   2803   FreePool (ConfigResp);
   2804 
   2805   return (BOOLEAN)(ResultsData != NULL);
   2806 }
   2807 
   2808 /////////////////////////////////////////
   2809 /////////////////////////////////////////
   2810 /// IFR Functions
   2811 /////////////////////////////////////////
   2812 /////////////////////////////////////////
   2813 
   2814 #define HII_LIB_OPCODE_ALLOCATION_SIZE  0x200
   2815 
   2816 typedef struct {
   2817   UINT8  *Buffer;
   2818   UINTN  BufferSize;
   2819   UINTN  Position;
   2820 } HII_LIB_OPCODE_BUFFER;
   2821 
   2822 ///
   2823 /// Lookup table that converts EFI_IFR_TYPE_X enum values to a width in bytes
   2824 ///
   2825 GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 mHiiDefaultTypeToWidth[] = {
   2826   1, // EFI_IFR_TYPE_NUM_SIZE_8
   2827   2, // EFI_IFR_TYPE_NUM_SIZE_16
   2828   4, // EFI_IFR_TYPE_NUM_SIZE_32
   2829   8, // EFI_IFR_TYPE_NUM_SIZE_64
   2830   1, // EFI_IFR_TYPE_BOOLEAN
   2831   3, // EFI_IFR_TYPE_TIME
   2832   4, // EFI_IFR_TYPE_DATE
   2833   2  // EFI_IFR_TYPE_STRING
   2834 };
   2835 
   2836 /**
   2837   Allocates and returns a new OpCode Handle.  OpCode Handles must be freed with
   2838   HiiFreeOpCodeHandle().
   2839 
   2840   @retval NULL   There are not enough resources to allocate a new OpCode Handle.
   2841   @retval Other  A new OpCode handle.
   2842 
   2843 **/
   2844 VOID *
   2845 EFIAPI
   2846 HiiAllocateOpCodeHandle (
   2847   VOID
   2848   )
   2849 {
   2850   HII_LIB_OPCODE_BUFFER  *OpCodeBuffer;
   2851 
   2852   OpCodeBuffer = (HII_LIB_OPCODE_BUFFER *)AllocatePool (sizeof (HII_LIB_OPCODE_BUFFER));
   2853   if (OpCodeBuffer == NULL) {
   2854     return NULL;
   2855   }
   2856   OpCodeBuffer->Buffer = (UINT8 *)AllocatePool (HII_LIB_OPCODE_ALLOCATION_SIZE);
   2857   if (OpCodeBuffer->Buffer == NULL) {
   2858     FreePool (OpCodeBuffer);
   2859     return NULL;
   2860   }
   2861   OpCodeBuffer->BufferSize = HII_LIB_OPCODE_ALLOCATION_SIZE;
   2862   OpCodeBuffer->Position = 0;
   2863   return (VOID *)OpCodeBuffer;
   2864 }
   2865 
   2866 /**
   2867   Frees an OpCode Handle that was previously allocated with HiiAllocateOpCodeHandle().
   2868   When an OpCode Handle is freed, all of the opcodes associated with the OpCode
   2869   Handle are also freed.
   2870 
   2871   If OpCodeHandle is NULL, then ASSERT().
   2872 
   2873   @param[in]  OpCodeHandle   Handle to the buffer of opcodes.
   2874 
   2875 **/
   2876 VOID
   2877 EFIAPI
   2878 HiiFreeOpCodeHandle (
   2879   VOID  *OpCodeHandle
   2880   )
   2881 {
   2882   HII_LIB_OPCODE_BUFFER  *OpCodeBuffer;
   2883 
   2884   ASSERT (OpCodeHandle != NULL);
   2885 
   2886   OpCodeBuffer = (HII_LIB_OPCODE_BUFFER *)OpCodeHandle;
   2887   if (OpCodeBuffer->Buffer != NULL) {
   2888     FreePool (OpCodeBuffer->Buffer);
   2889   }
   2890   FreePool (OpCodeBuffer);
   2891 }
   2892 
   2893 /**
   2894   Internal function gets the current position of opcode buffer.
   2895 
   2896   @param[in]  OpCodeHandle   Handle to the buffer of opcodes.
   2897 
   2898   @return Current position of opcode buffer.
   2899 **/
   2900 UINTN
   2901 EFIAPI
   2902 InternalHiiOpCodeHandlePosition (
   2903   IN VOID  *OpCodeHandle
   2904   )
   2905 {
   2906   return ((HII_LIB_OPCODE_BUFFER  *)OpCodeHandle)->Position;
   2907 }
   2908 
   2909 /**
   2910   Internal function gets the start pointer of opcode buffer.
   2911 
   2912   @param[in]  OpCodeHandle   Handle to the buffer of opcodes.
   2913 
   2914   @return Pointer to the opcode buffer base.
   2915 **/
   2916 UINT8 *
   2917 EFIAPI
   2918 InternalHiiOpCodeHandleBuffer (
   2919   IN VOID  *OpCodeHandle
   2920   )
   2921 {
   2922   return ((HII_LIB_OPCODE_BUFFER  *)OpCodeHandle)->Buffer;
   2923 }
   2924 
   2925 /**
   2926   Internal function reserves the enough buffer for current opcode.
   2927   When the buffer is not enough, Opcode buffer will be extended.
   2928 
   2929   @param[in]  OpCodeHandle   Handle to the buffer of opcodes.
   2930   @param[in]  Size           Size of current opcode.
   2931 
   2932   @return Pointer to the current opcode.
   2933 **/
   2934 UINT8 *
   2935 EFIAPI
   2936 InternalHiiGrowOpCodeHandle (
   2937   IN VOID   *OpCodeHandle,
   2938   IN UINTN  Size
   2939   )
   2940 {
   2941   HII_LIB_OPCODE_BUFFER  *OpCodeBuffer;
   2942   UINT8                  *Buffer;
   2943 
   2944   ASSERT (OpCodeHandle != NULL);
   2945 
   2946   OpCodeBuffer = (HII_LIB_OPCODE_BUFFER *)OpCodeHandle;
   2947   if (OpCodeBuffer->Position + Size > OpCodeBuffer->BufferSize) {
   2948     Buffer = ReallocatePool (
   2949               OpCodeBuffer->BufferSize,
   2950               OpCodeBuffer->BufferSize + (Size + HII_LIB_OPCODE_ALLOCATION_SIZE),
   2951               OpCodeBuffer->Buffer
   2952               );
   2953     ASSERT (Buffer != NULL);
   2954     OpCodeBuffer->Buffer = Buffer;
   2955     OpCodeBuffer->BufferSize += (Size + HII_LIB_OPCODE_ALLOCATION_SIZE);
   2956   }
   2957   Buffer = OpCodeBuffer->Buffer + OpCodeBuffer->Position;
   2958   OpCodeBuffer->Position += Size;
   2959   return Buffer;
   2960 }
   2961 
   2962 /**
   2963   Internal function creates opcode based on the template opcode.
   2964 
   2965   @param[in]  OpCodeHandle    Handle to the buffer of opcodes.
   2966   @param[in]  OpCodeTemplate  Pointer to the template buffer of opcode.
   2967   @param[in]  OpCode          OpCode IFR value.
   2968   @param[in]  OpCodeSize      Size of opcode.
   2969   @param[in]  ExtensionSize   Size of extended opcode.
   2970   @param[in]  Scope           Scope bit of opcode.
   2971 
   2972   @return Pointer to the current opcode with opcode data.
   2973 **/
   2974 UINT8 *
   2975 EFIAPI
   2976 InternalHiiCreateOpCodeExtended (
   2977   IN VOID   *OpCodeHandle,
   2978   IN VOID   *OpCodeTemplate,
   2979   IN UINT8  OpCode,
   2980   IN UINTN  OpCodeSize,
   2981   IN UINTN  ExtensionSize,
   2982   IN UINT8  Scope
   2983   )
   2984 {
   2985   EFI_IFR_OP_HEADER  *Header;
   2986   UINT8              *Buffer;
   2987 
   2988   ASSERT (OpCodeTemplate != NULL);
   2989   ASSERT ((OpCodeSize + ExtensionSize) <= 0x7F);
   2990 
   2991   Header = (EFI_IFR_OP_HEADER *)OpCodeTemplate;
   2992   Header->OpCode = OpCode;
   2993   Header->Scope  = Scope;
   2994   Header->Length = (UINT8)(OpCodeSize + ExtensionSize);
   2995   Buffer = InternalHiiGrowOpCodeHandle (OpCodeHandle, Header->Length);
   2996   return (UINT8 *)CopyMem (Buffer, Header, OpCodeSize);
   2997 }
   2998 
   2999 /**
   3000   Internal function creates opcode based on the template opcode for the normal opcode.
   3001 
   3002   @param[in]  OpCodeHandle    Handle to the buffer of opcodes.
   3003   @param[in]  OpCodeTemplate  Pointer to the template buffer of opcode.
   3004   @param[in]  OpCode          OpCode IFR value.
   3005   @param[in]  OpCodeSize      Size of opcode.
   3006 
   3007   @return Pointer to the current opcode with opcode data.
   3008 **/
   3009 UINT8 *
   3010 EFIAPI
   3011 InternalHiiCreateOpCode (
   3012   IN VOID   *OpCodeHandle,
   3013   IN VOID   *OpCodeTemplate,
   3014   IN UINT8  OpCode,
   3015   IN UINTN  OpCodeSize
   3016   )
   3017 {
   3018   return InternalHiiCreateOpCodeExtended (OpCodeHandle, OpCodeTemplate, OpCode, OpCodeSize, 0, 0);
   3019 }
   3020 
   3021 /**
   3022   Append raw opcodes to an OpCodeHandle.
   3023 
   3024   If OpCodeHandle is NULL, then ASSERT().
   3025   If RawBuffer is NULL, then ASSERT();
   3026 
   3027   @param[in]  OpCodeHandle   Handle to the buffer of opcodes.
   3028   @param[in]  RawBuffer      Buffer of opcodes to append.
   3029   @param[in]  RawBufferSize  The size, in bytes, of Buffer.
   3030 
   3031   @retval NULL   There is not enough space left in Buffer to add the opcode.
   3032   @retval Other  A pointer to the appended opcodes.
   3033 
   3034 **/
   3035 UINT8 *
   3036 EFIAPI
   3037 HiiCreateRawOpCodes (
   3038   IN VOID   *OpCodeHandle,
   3039   IN UINT8  *RawBuffer,
   3040   IN UINTN  RawBufferSize
   3041   )
   3042 {
   3043   UINT8  *Buffer;
   3044 
   3045   ASSERT (RawBuffer != NULL);
   3046 
   3047   Buffer = InternalHiiGrowOpCodeHandle (OpCodeHandle, RawBufferSize);
   3048   return (UINT8 *)CopyMem (Buffer, RawBuffer, RawBufferSize);
   3049 }
   3050 
   3051 /**
   3052   Append opcodes from one OpCode Handle to another OpCode handle.
   3053 
   3054   If OpCodeHandle is NULL, then ASSERT().
   3055   If RawOpCodeHandle is NULL, then ASSERT();
   3056 
   3057   @param[in]  OpCodeHandle     Handle to the buffer of opcodes.
   3058   @param[in]  RawOpCodeHandle  Handle to the buffer of opcodes.
   3059 
   3060   @retval NULL   There is not enough space left in Buffer to add the opcode.
   3061   @retval Other  A pointer to the appended opcodes.
   3062 
   3063 **/
   3064 UINT8 *
   3065 EFIAPI
   3066 InternalHiiAppendOpCodes (
   3067   IN VOID  *OpCodeHandle,
   3068   IN VOID  *RawOpCodeHandle
   3069   )
   3070 {
   3071   HII_LIB_OPCODE_BUFFER  *RawOpCodeBuffer;
   3072 
   3073   ASSERT (RawOpCodeHandle != NULL);
   3074 
   3075   RawOpCodeBuffer = (HII_LIB_OPCODE_BUFFER *)RawOpCodeHandle;
   3076   return HiiCreateRawOpCodes (OpCodeHandle, RawOpCodeBuffer->Buffer, RawOpCodeBuffer->Position);
   3077 }
   3078 
   3079 /**
   3080   Create EFI_IFR_END_OP opcode.
   3081 
   3082   If OpCodeHandle is NULL, then ASSERT().
   3083 
   3084   @param[in]  OpCodeHandle  Handle to the buffer of opcodes.
   3085 
   3086   @retval NULL   There is not enough space left in Buffer to add the opcode.
   3087   @retval Other  A pointer to the created opcode.
   3088 
   3089 **/
   3090 UINT8 *
   3091 EFIAPI
   3092 HiiCreateEndOpCode (
   3093   IN VOID  *OpCodeHandle
   3094   )
   3095 {
   3096   EFI_IFR_END  OpCode;
   3097 
   3098   return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_END_OP, sizeof (OpCode));
   3099 }
   3100 
   3101 /**
   3102   Create EFI_IFR_ONE_OF_OPTION_OP opcode.
   3103 
   3104   If OpCodeHandle is NULL, then ASSERT().
   3105   If Type is invalid, then ASSERT().
   3106   If Flags is invalid, then ASSERT().
   3107 
   3108   @param[in]  OpCodeHandle  Handle to the buffer of opcodes.
   3109   @param[in]  StringId      StringId for the option
   3110   @param[in]  Flags         Flags for the option
   3111   @param[in]  Type          Type for the option
   3112   @param[in]  Value         Value for the option
   3113 
   3114   @retval NULL   There is not enough space left in Buffer to add the opcode.
   3115   @retval Other  A pointer to the created opcode.
   3116 
   3117 **/
   3118 UINT8 *
   3119 EFIAPI
   3120 HiiCreateOneOfOptionOpCode (
   3121   IN VOID    *OpCodeHandle,
   3122   IN UINT16  StringId,
   3123   IN UINT8   Flags,
   3124   IN UINT8   Type,
   3125   IN UINT64  Value
   3126   )
   3127 {
   3128   EFI_IFR_ONE_OF_OPTION  OpCode;
   3129 
   3130   ASSERT (Type < EFI_IFR_TYPE_OTHER);
   3131 
   3132   ZeroMem (&OpCode, sizeof (OpCode));
   3133   OpCode.Option = StringId;
   3134   OpCode.Flags  = (UINT8) (Flags & (EFI_IFR_OPTION_DEFAULT | EFI_IFR_OPTION_DEFAULT_MFG));
   3135   OpCode.Type   = Type;
   3136   CopyMem (&OpCode.Value, &Value, mHiiDefaultTypeToWidth[Type]);
   3137 
   3138   return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_ONE_OF_OPTION_OP, OFFSET_OF(EFI_IFR_ONE_OF_OPTION, Value) + mHiiDefaultTypeToWidth[Type]);
   3139 }
   3140 
   3141 /**
   3142   Create EFI_IFR_DEFAULT_OP opcode.
   3143 
   3144   If OpCodeHandle is NULL, then ASSERT().
   3145   If Type is invalid, then ASSERT().
   3146 
   3147   @param[in]  OpCodeHandle  Handle to the buffer of opcodes.
   3148   @param[in]  DefaultId     DefaultId for the default
   3149   @param[in]  Type          Type for the default
   3150   @param[in]  Value         Value for the default
   3151 
   3152   @retval NULL   There is not enough space left in Buffer to add the opcode.
   3153   @retval Other  A pointer to the created opcode.
   3154 
   3155 **/
   3156 UINT8 *
   3157 EFIAPI
   3158 HiiCreateDefaultOpCode (
   3159   IN VOID    *OpCodeHandle,
   3160   IN UINT16  DefaultId,
   3161   IN UINT8   Type,
   3162   IN UINT64  Value
   3163   )
   3164 {
   3165   EFI_IFR_DEFAULT  OpCode;
   3166 
   3167   ASSERT (Type < EFI_IFR_TYPE_OTHER);
   3168 
   3169   ZeroMem (&OpCode, sizeof (OpCode));
   3170   OpCode.Type      = Type;
   3171   OpCode.DefaultId = DefaultId;
   3172   CopyMem (&OpCode.Value, &Value, mHiiDefaultTypeToWidth[Type]);
   3173 
   3174   return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_DEFAULT_OP, OFFSET_OF(EFI_IFR_DEFAULT, Value) + mHiiDefaultTypeToWidth[Type]);
   3175 }
   3176 
   3177 /**
   3178   Create EFI_IFR_GUID opcode.
   3179 
   3180   If OpCodeHandle is NULL, then ASSERT().
   3181   If Guid is NULL, then ASSERT().
   3182   If OpCodeSize < sizeof (EFI_IFR_GUID), then ASSERT().
   3183 
   3184   @param[in]  OpCodeHandle  Handle to the buffer of opcodes.
   3185   @param[in]  Guid          Pointer to EFI_GUID of this guided opcode.
   3186   @param[in]  GuidOpCode    Pointer to an EFI_IFR_GUID opcode.  This is an
   3187                             optional parameter that may be NULL.  If this
   3188                             parameter is NULL, then the GUID extension
   3189                             region of the created opcode is filled with zeros.
   3190                             If this parameter is not NULL, then the GUID
   3191                             extension region of GuidData will be copied to
   3192                             the GUID extension region of the created opcode.
   3193   @param[in]  OpCodeSize    The size, in bytes, of created opcode.  This value
   3194                             must be >= sizeof(EFI_IFR_GUID).
   3195 
   3196   @retval NULL   There is not enough space left in Buffer to add the opcode.
   3197   @retval Other  A pointer to the created opcode.
   3198 
   3199 **/
   3200 UINT8 *
   3201 EFIAPI
   3202 HiiCreateGuidOpCode (
   3203   IN VOID            *OpCodeHandle,
   3204   IN CONST EFI_GUID  *Guid,
   3205   IN CONST VOID      *GuidOpCode,    OPTIONAL
   3206   IN UINTN           OpCodeSize
   3207   )
   3208 {
   3209   EFI_IFR_GUID  OpCode;
   3210   EFI_IFR_GUID  *OpCodePointer;
   3211 
   3212   ASSERT (Guid != NULL);
   3213   ASSERT (OpCodeSize >= sizeof (OpCode));
   3214 
   3215   ZeroMem (&OpCode, sizeof (OpCode));
   3216   CopyGuid ((EFI_GUID *)(VOID *)&OpCode.Guid, Guid);
   3217 
   3218   OpCodePointer = (EFI_IFR_GUID *)InternalHiiCreateOpCodeExtended (
   3219                                     OpCodeHandle,
   3220                                     &OpCode,
   3221                                     EFI_IFR_GUID_OP,
   3222                                     sizeof (OpCode),
   3223                                     OpCodeSize - sizeof (OpCode),
   3224                                     0
   3225                                     );
   3226   if (OpCodePointer != NULL && GuidOpCode != NULL) {
   3227     CopyMem (OpCodePointer + 1, (EFI_IFR_GUID *)GuidOpCode + 1, OpCodeSize - sizeof (OpCode));
   3228   }
   3229   return (UINT8 *)OpCodePointer;
   3230 }
   3231 
   3232 /**
   3233   Create EFI_IFR_ACTION_OP opcode.
   3234 
   3235   If OpCodeHandle is NULL, then ASSERT().
   3236   If any reserved bits are set in QuestionFlags, then ASSERT().
   3237 
   3238   @param[in]  OpCodeHandle  Handle to the buffer of opcodes.
   3239   @param[in]  QuestionId      Question ID
   3240   @param[in]  Prompt          String ID for Prompt
   3241   @param[in]  Help            String ID for Help
   3242   @param[in]  QuestionFlags   Flags in Question Header
   3243   @param[in]  QuestionConfig  String ID for configuration
   3244 
   3245   @retval NULL   There is not enough space left in Buffer to add the opcode.
   3246   @retval Other  A pointer to the created opcode.
   3247 
   3248 **/
   3249 UINT8 *
   3250 EFIAPI
   3251 HiiCreateActionOpCode (
   3252   IN VOID             *OpCodeHandle,
   3253   IN EFI_QUESTION_ID  QuestionId,
   3254   IN EFI_STRING_ID    Prompt,
   3255   IN EFI_STRING_ID    Help,
   3256   IN UINT8            QuestionFlags,
   3257   IN EFI_STRING_ID    QuestionConfig
   3258   )
   3259 {
   3260   EFI_IFR_ACTION  OpCode;
   3261 
   3262   ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED))) == 0);
   3263 
   3264   ZeroMem (&OpCode, sizeof (OpCode));
   3265   OpCode.Question.QuestionId    = QuestionId;
   3266   OpCode.Question.Header.Prompt = Prompt;
   3267   OpCode.Question.Header.Help   = Help;
   3268   OpCode.Question.Flags         = QuestionFlags;
   3269   OpCode.QuestionConfig         = QuestionConfig;
   3270 
   3271   return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_ACTION_OP, sizeof (OpCode));
   3272 }
   3273 
   3274 /**
   3275   Create EFI_IFR_SUBTITLE_OP opcode.
   3276 
   3277   If OpCodeHandle is NULL, then ASSERT().
   3278   If any reserved bits are set in Flags, then ASSERT().
   3279   If Scope > 1, then ASSERT().
   3280 
   3281   @param[in]  OpCodeHandle  Handle to the buffer of opcodes.
   3282   @param[in]  Prompt      String ID for Prompt
   3283   @param[in]  Help        String ID for Help
   3284   @param[in]  Flags       Subtitle opcode flags
   3285   @param[in]  Scope       1 if this opcpde is the beginning of a new scope.
   3286                           0 if this opcode is within the current scope.
   3287 
   3288   @retval NULL   There is not enough space left in Buffer to add the opcode.
   3289   @retval Other  A pointer to the created opcode.
   3290 
   3291 **/
   3292 UINT8 *
   3293 EFIAPI
   3294 HiiCreateSubTitleOpCode (
   3295   IN VOID           *OpCodeHandle,
   3296   IN EFI_STRING_ID  Prompt,
   3297   IN EFI_STRING_ID  Help,
   3298   IN UINT8          Flags,
   3299   IN UINT8          Scope
   3300   )
   3301 {
   3302   EFI_IFR_SUBTITLE  OpCode;
   3303 
   3304   ASSERT (Scope <= 1);
   3305   ASSERT ((Flags & (~(EFI_IFR_FLAGS_HORIZONTAL))) == 0);
   3306 
   3307   ZeroMem (&OpCode, sizeof (OpCode));
   3308   OpCode.Statement.Prompt = Prompt;
   3309   OpCode.Statement.Help   = Help;
   3310   OpCode.Flags            = Flags;
   3311 
   3312   return InternalHiiCreateOpCodeExtended (
   3313            OpCodeHandle,
   3314            &OpCode,
   3315            EFI_IFR_SUBTITLE_OP,
   3316            sizeof (OpCode),
   3317            0,
   3318            Scope
   3319            );
   3320 }
   3321 
   3322 /**
   3323   Create EFI_IFR_REF_OP opcode.
   3324 
   3325   If OpCodeHandle is NULL, then ASSERT().
   3326   If any reserved bits are set in QuestionFlags, then ASSERT().
   3327 
   3328   @param[in]  OpCodeHandle   Handle to the buffer of opcodes.
   3329   @param[in]  FormId         Destination Form ID
   3330   @param[in]  Prompt         String ID for Prompt
   3331   @param[in]  Help           String ID for Help
   3332   @param[in]  QuestionFlags  Flags in Question Header
   3333   @param[in]  QuestionId     Question ID
   3334 
   3335   @retval NULL   There is not enough space left in Buffer to add the opcode.
   3336   @retval Other  A pointer to the created opcode.
   3337 
   3338 **/
   3339 UINT8 *
   3340 EFIAPI
   3341 HiiCreateGotoOpCode (
   3342   IN VOID             *OpCodeHandle,
   3343   IN EFI_FORM_ID      FormId,
   3344   IN EFI_STRING_ID    Prompt,
   3345   IN EFI_STRING_ID    Help,
   3346   IN UINT8            QuestionFlags,
   3347   IN EFI_QUESTION_ID  QuestionId
   3348   )
   3349 {
   3350   EFI_IFR_REF  OpCode;
   3351 
   3352   ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED))) == 0);
   3353 
   3354   ZeroMem (&OpCode, sizeof (OpCode));
   3355   OpCode.Question.Header.Prompt = Prompt;
   3356   OpCode.Question.Header.Help   = Help;
   3357   OpCode.Question.QuestionId    = QuestionId;
   3358   OpCode.Question.Flags         = QuestionFlags;
   3359   OpCode.FormId                 = FormId;
   3360 
   3361   return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_REF_OP, sizeof (OpCode));
   3362 }
   3363 
   3364 /**
   3365   Create EFI_IFR_REF_OP, EFI_IFR_REF2_OP, EFI_IFR_REF3_OP and EFI_IFR_REF4_OP opcode.
   3366 
   3367   When RefDevicePath is not zero, EFI_IFR_REF4 opcode will be created.
   3368   When RefDevicePath is zero and RefFormSetId is not NULL, EFI_IFR_REF3 opcode will be created.
   3369   When RefDevicePath is zero, RefFormSetId is NULL and RefQuestionId is not zero, EFI_IFR_REF2 opcode will be created.
   3370   When RefDevicePath is zero, RefFormSetId is NULL and RefQuestionId is zero, EFI_IFR_REF opcode will be created.
   3371 
   3372   If OpCodeHandle is NULL, then ASSERT().
   3373   If any reserved bits are set in QuestionFlags, then ASSERT().
   3374 
   3375   @param[in]  OpCodeHandle   The handle to the buffer of opcodes.
   3376   @param[in]  RefFormId      The Destination Form ID.
   3377   @param[in]  Prompt         The string ID for Prompt.
   3378   @param[in]  Help           The string ID for Help.
   3379   @param[in]  QuestionFlags  The flags in Question Header
   3380   @param[in]  QuestionId     Question ID.
   3381   @param[in]  RefQuestionId  The question on the form to which this link is referring.
   3382                              If its value is zero, then the link refers to the top of the form.
   3383   @param[in]  RefFormSetId   The form set to which this link is referring. If its value is NULL, and RefDevicePath is
   3384                              zero, then the link is to the current form set.
   3385   @param[in]  RefDevicePath  The string identifier that specifies the string containing the text representation of
   3386                              the device path to which the form set containing the form specified by FormId.
   3387                              If its value is zero, then the link refers to the current page.
   3388 
   3389   @retval NULL   There is not enough space left in Buffer to add the opcode.
   3390   @retval Other  A pointer to the created opcode.
   3391 
   3392 **/
   3393 UINT8 *
   3394 EFIAPI
   3395 HiiCreateGotoExOpCode (
   3396   IN VOID             *OpCodeHandle,
   3397   IN EFI_FORM_ID      RefFormId,
   3398   IN EFI_STRING_ID    Prompt,
   3399   IN EFI_STRING_ID    Help,
   3400   IN UINT8            QuestionFlags,
   3401   IN EFI_QUESTION_ID  QuestionId,
   3402   IN EFI_QUESTION_ID  RefQuestionId,
   3403   IN EFI_GUID         *RefFormSetId,    OPTIONAL
   3404   IN EFI_STRING_ID    RefDevicePath
   3405   )
   3406 {
   3407   EFI_IFR_REF4  OpCode;
   3408   UINTN         OpCodeSize;
   3409 
   3410   ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED))) == 0);
   3411 
   3412   ZeroMem (&OpCode, sizeof (OpCode));
   3413   OpCode.Question.Header.Prompt = Prompt;
   3414   OpCode.Question.Header.Help   = Help;
   3415   OpCode.Question.QuestionId    = QuestionId;
   3416   OpCode.Question.Flags         = QuestionFlags;
   3417   OpCode.FormId                 = RefFormId;
   3418   OpCode.QuestionId             = RefQuestionId;
   3419   OpCode.DevicePath             = RefDevicePath;
   3420   if (RefFormSetId != NULL) {
   3421     CopyMem (&OpCode.FormSetId, RefFormSetId, sizeof (OpCode.FormSetId));
   3422   }
   3423 
   3424   //
   3425   // Cacluate OpCodeSize based on the input Ref value.
   3426   // Try to use the small OpCode to save size.
   3427   //
   3428   OpCodeSize = sizeof (EFI_IFR_REF);
   3429   if (RefDevicePath != 0) {
   3430     OpCodeSize = sizeof (EFI_IFR_REF4);
   3431   } else if (RefFormSetId != NULL) {
   3432     OpCodeSize = sizeof (EFI_IFR_REF3);
   3433   } else if (RefQuestionId != 0) {
   3434     OpCodeSize = sizeof (EFI_IFR_REF2);
   3435   }
   3436 
   3437   return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_REF_OP, OpCodeSize);
   3438 }
   3439 
   3440 /**
   3441   Create EFI_IFR_CHECKBOX_OP opcode.
   3442 
   3443   If OpCodeHandle is NULL, then ASSERT().
   3444   If any reserved bits are set in QuestionFlags, then ASSERT().
   3445   If any reserved bits are set in CheckBoxFlags, then ASSERT().
   3446 
   3447   @param[in]  OpCodeHandle          Handle to the buffer of opcodes.
   3448   @param[in]  QuestionId            Question ID
   3449   @param[in]  VarStoreId            Storage ID
   3450   @param[in]  VarOffset             Offset in Storage or String ID of the name (VarName)
   3451                                     for this name/value pair.
   3452   @param[in]  Prompt                String ID for Prompt
   3453   @param[in]  Help                  String ID for Help
   3454   @param[in]  QuestionFlags         Flags in Question Header
   3455   @param[in]  CheckBoxFlags         Flags for checkbox opcode
   3456   @param[in]  DefaultsOpCodeHandle  Handle for a buffer of DEFAULT opcodes.  This
   3457                                     is an optional parameter that may be NULL.
   3458 
   3459   @retval NULL   There is not enough space left in Buffer to add the opcode.
   3460   @retval Other  A pointer to the created opcode.
   3461 
   3462 **/
   3463 UINT8 *
   3464 EFIAPI
   3465 HiiCreateCheckBoxOpCode (
   3466   IN VOID             *OpCodeHandle,
   3467   IN EFI_QUESTION_ID  QuestionId,
   3468   IN EFI_VARSTORE_ID  VarStoreId,
   3469   IN UINT16           VarOffset,
   3470   IN EFI_STRING_ID    Prompt,
   3471   IN EFI_STRING_ID    Help,
   3472   IN UINT8            QuestionFlags,
   3473   IN UINT8            CheckBoxFlags,
   3474   IN VOID             *DefaultsOpCodeHandle  OPTIONAL
   3475   )
   3476 {
   3477   EFI_IFR_CHECKBOX  OpCode;
   3478   UINTN             Position;
   3479 
   3480   ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED))) == 0);
   3481 
   3482   ZeroMem (&OpCode, sizeof (OpCode));
   3483   OpCode.Question.QuestionId             = QuestionId;
   3484   OpCode.Question.VarStoreId             = VarStoreId;
   3485   OpCode.Question.VarStoreInfo.VarOffset = VarOffset;
   3486   OpCode.Question.Header.Prompt          = Prompt;
   3487   OpCode.Question.Header.Help            = Help;
   3488   OpCode.Question.Flags                  = QuestionFlags;
   3489   OpCode.Flags                           = CheckBoxFlags;
   3490 
   3491   if (DefaultsOpCodeHandle == NULL) {
   3492     return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_CHECKBOX_OP, sizeof (OpCode));
   3493   }
   3494 
   3495   Position = InternalHiiOpCodeHandlePosition (OpCodeHandle);
   3496   InternalHiiCreateOpCodeExtended (OpCodeHandle, &OpCode, EFI_IFR_CHECKBOX_OP, sizeof (OpCode), 0, 1);
   3497   InternalHiiAppendOpCodes (OpCodeHandle, DefaultsOpCodeHandle);
   3498   HiiCreateEndOpCode (OpCodeHandle);
   3499   return InternalHiiOpCodeHandleBuffer (OpCodeHandle) + Position;
   3500 }
   3501 
   3502 /**
   3503   Create EFI_IFR_NUMERIC_OP opcode.
   3504 
   3505   If OpCodeHandle is NULL, then ASSERT().
   3506   If any reserved bits are set in QuestionFlags, then ASSERT().
   3507   If any reserved bits are set in NumericFlags, then ASSERT().
   3508 
   3509   @param[in]  OpCodeHandle          Handle to the buffer of opcodes.
   3510   @param[in]  QuestionId            Question ID
   3511   @param[in]  VarStoreId            Storage ID
   3512   @param[in]  VarOffset             Offset in Storage or String ID of the name (VarName)
   3513                                     for this name/value pair.
   3514   @param[in]  Prompt                String ID for Prompt
   3515   @param[in]  Help                  String ID for Help
   3516   @param[in]  QuestionFlags         Flags in Question Header
   3517   @param[in]  NumericFlags          Flags for numeric opcode
   3518   @param[in]  Minimum               Numeric minimum value
   3519   @param[in]  Maximum               Numeric maximum value
   3520   @param[in]  Step                  Numeric step for edit
   3521   @param[in]  DefaultsOpCodeHandle  Handle for a buffer of DEFAULT opcodes.  This
   3522                                     is an optional parameter that may be NULL.
   3523 
   3524   @retval NULL   There is not enough space left in Buffer to add the opcode.
   3525   @retval Other  A pointer to the created opcode.
   3526 
   3527 **/
   3528 UINT8 *
   3529 EFIAPI
   3530 HiiCreateNumericOpCode (
   3531   IN VOID             *OpCodeHandle,
   3532   IN EFI_QUESTION_ID  QuestionId,
   3533   IN EFI_VARSTORE_ID  VarStoreId,
   3534   IN UINT16           VarOffset,
   3535   IN EFI_STRING_ID    Prompt,
   3536   IN EFI_STRING_ID    Help,
   3537   IN UINT8            QuestionFlags,
   3538   IN UINT8            NumericFlags,
   3539   IN UINT64           Minimum,
   3540   IN UINT64           Maximum,
   3541   IN UINT64           Step,
   3542   IN VOID             *DefaultsOpCodeHandle  OPTIONAL
   3543   )
   3544 {
   3545   EFI_IFR_NUMERIC  OpCode;
   3546   UINTN            Position;
   3547   UINTN            Length;
   3548 
   3549   ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED))) == 0);
   3550 
   3551   Length  = 0;
   3552   ZeroMem (&OpCode, sizeof (OpCode));
   3553   OpCode.Question.QuestionId             = QuestionId;
   3554   OpCode.Question.VarStoreId             = VarStoreId;
   3555   OpCode.Question.VarStoreInfo.VarOffset = VarOffset;
   3556   OpCode.Question.Header.Prompt          = Prompt;
   3557   OpCode.Question.Header.Help            = Help;
   3558   OpCode.Question.Flags                  = QuestionFlags;
   3559   OpCode.Flags                           = NumericFlags;
   3560 
   3561   switch (NumericFlags & EFI_IFR_NUMERIC_SIZE) {
   3562   case EFI_IFR_NUMERIC_SIZE_1:
   3563     OpCode.data.u8.MinValue = (UINT8)Minimum;
   3564     OpCode.data.u8.MaxValue = (UINT8)Maximum;
   3565     OpCode.data.u8.Step     = (UINT8)Step;
   3566     Length                  = 3;
   3567     break;
   3568 
   3569   case EFI_IFR_NUMERIC_SIZE_2:
   3570     OpCode.data.u16.MinValue = (UINT16)Minimum;
   3571     OpCode.data.u16.MaxValue = (UINT16)Maximum;
   3572     OpCode.data.u16.Step     = (UINT16)Step;
   3573     Length                   = 6;
   3574     break;
   3575 
   3576   case EFI_IFR_NUMERIC_SIZE_4:
   3577     OpCode.data.u32.MinValue = (UINT32)Minimum;
   3578     OpCode.data.u32.MaxValue = (UINT32)Maximum;
   3579     OpCode.data.u32.Step     = (UINT32)Step;
   3580     Length                   = 12;
   3581     break;
   3582 
   3583   case EFI_IFR_NUMERIC_SIZE_8:
   3584     OpCode.data.u64.MinValue = Minimum;
   3585     OpCode.data.u64.MaxValue = Maximum;
   3586     OpCode.data.u64.Step     = Step;
   3587     Length                   = 24;
   3588     break;
   3589   }
   3590 
   3591   Length += OFFSET_OF (EFI_IFR_NUMERIC, data);
   3592 
   3593   if (DefaultsOpCodeHandle == NULL) {
   3594     return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_NUMERIC_OP, Length);
   3595   }
   3596 
   3597   Position = InternalHiiOpCodeHandlePosition (OpCodeHandle);
   3598   InternalHiiCreateOpCodeExtended (OpCodeHandle, &OpCode, EFI_IFR_NUMERIC_OP, Length, 0, 1);
   3599   InternalHiiAppendOpCodes (OpCodeHandle, DefaultsOpCodeHandle);
   3600   HiiCreateEndOpCode (OpCodeHandle);
   3601   return InternalHiiOpCodeHandleBuffer (OpCodeHandle) + Position;
   3602 }
   3603 
   3604 /**
   3605   Create EFI_IFR_STRING_OP opcode.
   3606 
   3607   If OpCodeHandle is NULL, then ASSERT().
   3608   If any reserved bits are set in QuestionFlags, then ASSERT().
   3609   If any reserved bits are set in StringFlags, then ASSERT().
   3610 
   3611   @param[in]  OpCodeHandle          Handle to the buffer of opcodes.
   3612   @param[in]  QuestionId            Question ID
   3613   @param[in]  VarStoreId            Storage ID
   3614   @param[in]  VarOffset             Offset in Storage or String ID of the name (VarName)
   3615                                     for this name/value pair.
   3616   @param[in]  Prompt                String ID for Prompt
   3617   @param[in]  Help                  String ID for Help
   3618   @param[in]  QuestionFlags         Flags in Question Header
   3619   @param[in]  StringFlags           Flags for string opcode
   3620   @param[in]  MinSize               String minimum length
   3621   @param[in]  MaxSize               String maximum length
   3622   @param[in]  DefaultsOpCodeHandle  Handle for a buffer of DEFAULT opcodes.  This
   3623                                     is an optional parameter that may be NULL.
   3624 
   3625   @retval NULL   There is not enough space left in Buffer to add the opcode.
   3626   @retval Other  A pointer to the created opcode.
   3627 
   3628 **/
   3629 UINT8 *
   3630 EFIAPI
   3631 HiiCreateStringOpCode (
   3632   IN VOID             *OpCodeHandle,
   3633   IN EFI_QUESTION_ID  QuestionId,
   3634   IN EFI_VARSTORE_ID  VarStoreId,
   3635   IN UINT16           VarOffset,
   3636   IN EFI_STRING_ID    Prompt,
   3637   IN EFI_STRING_ID    Help,
   3638   IN UINT8            QuestionFlags,
   3639   IN UINT8            StringFlags,
   3640   IN UINT8            MinSize,
   3641   IN UINT8            MaxSize,
   3642   IN VOID             *DefaultsOpCodeHandle  OPTIONAL
   3643   )
   3644 {
   3645   EFI_IFR_STRING  OpCode;
   3646   UINTN           Position;
   3647 
   3648   ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED))) == 0);
   3649 
   3650   ZeroMem (&OpCode, sizeof (OpCode));
   3651   OpCode.Question.Header.Prompt          = Prompt;
   3652   OpCode.Question.Header.Help            = Help;
   3653   OpCode.Question.QuestionId             = QuestionId;
   3654   OpCode.Question.VarStoreId             = VarStoreId;
   3655   OpCode.Question.VarStoreInfo.VarOffset = VarOffset;
   3656   OpCode.Question.Flags                  = QuestionFlags;
   3657   OpCode.MinSize                         = MinSize;
   3658   OpCode.MaxSize                         = MaxSize;
   3659   OpCode.Flags                           = (UINT8) (StringFlags & EFI_IFR_STRING_MULTI_LINE);
   3660 
   3661   if (DefaultsOpCodeHandle == NULL) {
   3662     return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_STRING_OP, sizeof (OpCode));
   3663   }
   3664 
   3665   Position = InternalHiiOpCodeHandlePosition (OpCodeHandle);
   3666   InternalHiiCreateOpCodeExtended (OpCodeHandle, &OpCode, EFI_IFR_STRING_OP, sizeof (OpCode), 0, 1);
   3667   InternalHiiAppendOpCodes (OpCodeHandle, DefaultsOpCodeHandle);
   3668   HiiCreateEndOpCode (OpCodeHandle);
   3669   return InternalHiiOpCodeHandleBuffer (OpCodeHandle) + Position;
   3670 }
   3671 
   3672 /**
   3673   Create EFI_IFR_ONE_OF_OP opcode.
   3674 
   3675   If OpCodeHandle is NULL, then ASSERT().
   3676   If any reserved bits are set in QuestionFlags, then ASSERT().
   3677   If any reserved bits are set in OneOfFlags, then ASSERT().
   3678 
   3679   @param[in]  OpCodeHandle          Handle to the buffer of opcodes.
   3680   @param[in]  QuestionId            Question ID
   3681   @param[in]  VarStoreId            Storage ID
   3682   @param[in]  VarOffset             Offset in Storage or String ID of the name (VarName)
   3683                                     for this name/value pair.
   3684   @param[in]  Prompt                String ID for Prompt
   3685   @param[in]  Help                  String ID for Help
   3686   @param[in]  QuestionFlags         Flags in Question Header
   3687   @param[in]  OneOfFlags            Flags for oneof opcode
   3688   @param[in]  OptionsOpCodeHandle   Handle for a buffer of ONE_OF_OPTION opcodes.
   3689   @param[in]  DefaultsOpCodeHandle  Handle for a buffer of DEFAULT opcodes.  This
   3690                                     is an optional parameter that may be NULL.
   3691 
   3692   @retval NULL   There is not enough space left in Buffer to add the opcode.
   3693   @retval Other  A pointer to the created opcode.
   3694 
   3695 **/
   3696 UINT8 *
   3697 EFIAPI
   3698 HiiCreateOneOfOpCode (
   3699   IN VOID             *OpCodeHandle,
   3700   IN EFI_QUESTION_ID  QuestionId,
   3701   IN EFI_VARSTORE_ID  VarStoreId,
   3702   IN UINT16           VarOffset,
   3703   IN EFI_STRING_ID    Prompt,
   3704   IN EFI_STRING_ID    Help,
   3705   IN UINT8            QuestionFlags,
   3706   IN UINT8            OneOfFlags,
   3707   IN VOID             *OptionsOpCodeHandle,
   3708   IN VOID             *DefaultsOpCodeHandle  OPTIONAL
   3709   )
   3710 {
   3711   EFI_IFR_ONE_OF  OpCode;
   3712   UINTN           Position;
   3713   UINTN           Length;
   3714 
   3715   ASSERT (OptionsOpCodeHandle != NULL);
   3716   ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED | EFI_IFR_FLAG_OPTIONS_ONLY))) == 0);
   3717 
   3718   ZeroMem (&OpCode, sizeof (OpCode));
   3719   OpCode.Question.Header.Prompt          = Prompt;
   3720   OpCode.Question.Header.Help            = Help;
   3721   OpCode.Question.QuestionId             = QuestionId;
   3722   OpCode.Question.VarStoreId             = VarStoreId;
   3723   OpCode.Question.VarStoreInfo.VarOffset = VarOffset;
   3724   OpCode.Question.Flags                  = QuestionFlags;
   3725   OpCode.Flags                           = OneOfFlags;
   3726 
   3727   Length  = OFFSET_OF (EFI_IFR_ONE_OF, data);
   3728   Length += (1 << (OneOfFlags & EFI_IFR_NUMERIC_SIZE)) * 3;
   3729 
   3730   Position = InternalHiiOpCodeHandlePosition (OpCodeHandle);
   3731   InternalHiiCreateOpCodeExtended (OpCodeHandle, &OpCode, EFI_IFR_ONE_OF_OP, Length, 0, 1);
   3732   InternalHiiAppendOpCodes (OpCodeHandle, OptionsOpCodeHandle);
   3733   if (DefaultsOpCodeHandle != NULL) {
   3734     InternalHiiAppendOpCodes (OpCodeHandle, DefaultsOpCodeHandle);
   3735   }
   3736   HiiCreateEndOpCode (OpCodeHandle);
   3737   return InternalHiiOpCodeHandleBuffer (OpCodeHandle) + Position;
   3738 }
   3739 
   3740 /**
   3741   Create EFI_IFR_ORDERED_LIST_OP opcode.
   3742 
   3743   If OpCodeHandle is NULL, then ASSERT().
   3744   If any reserved bits are set in QuestionFlags, then ASSERT().
   3745   If any reserved bits are set in OrderedListFlags, then ASSERT().
   3746 
   3747   @param[in]  OpCodeHandle          Handle to the buffer of opcodes.
   3748   @param[in]  QuestionId            Question ID
   3749   @param[in]  VarStoreId            Storage ID
   3750   @param[in]  VarOffset             Offset in Storage or String ID of the name (VarName)
   3751                                     for this name/value pair.
   3752   @param[in]  Prompt                String ID for Prompt
   3753   @param[in]  Help                  String ID for Help
   3754   @param[in]  QuestionFlags         Flags in Question Header
   3755   @param[in]  OrderedListFlags      Flags for ordered list opcode
   3756   @param[in]  DataType              Type for option value
   3757   @param[in]  MaxContainers         Maximum count for options in this ordered list
   3758   @param[in]  OptionsOpCodeHandle   Handle for a buffer of ONE_OF_OPTION opcodes.
   3759   @param[in]  DefaultsOpCodeHandle  Handle for a buffer of DEFAULT opcodes.  This
   3760                                     is an optional parameter that may be NULL.
   3761 
   3762   @retval NULL   There is not enough space left in Buffer to add the opcode.
   3763   @retval Other  A pointer to the created opcode.
   3764 
   3765 **/
   3766 UINT8 *
   3767 EFIAPI
   3768 HiiCreateOrderedListOpCode (
   3769   IN VOID             *OpCodeHandle,
   3770   IN EFI_QUESTION_ID  QuestionId,
   3771   IN EFI_VARSTORE_ID  VarStoreId,
   3772   IN UINT16           VarOffset,
   3773   IN EFI_STRING_ID    Prompt,
   3774   IN EFI_STRING_ID    Help,
   3775   IN UINT8            QuestionFlags,
   3776   IN UINT8            OrderedListFlags,
   3777   IN UINT8            DataType,
   3778   IN UINT8            MaxContainers,
   3779   IN VOID             *OptionsOpCodeHandle,
   3780   IN VOID             *DefaultsOpCodeHandle  OPTIONAL
   3781   )
   3782 {
   3783   EFI_IFR_ORDERED_LIST  OpCode;
   3784   UINTN                 Position;
   3785 
   3786   ASSERT (OptionsOpCodeHandle != NULL);
   3787   ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED | EFI_IFR_FLAG_OPTIONS_ONLY))) == 0);
   3788 
   3789   ZeroMem (&OpCode, sizeof (OpCode));
   3790   OpCode.Question.Header.Prompt          = Prompt;
   3791   OpCode.Question.Header.Help            = Help;
   3792   OpCode.Question.QuestionId             = QuestionId;
   3793   OpCode.Question.VarStoreId             = VarStoreId;
   3794   OpCode.Question.VarStoreInfo.VarOffset = VarOffset;
   3795   OpCode.Question.Flags                  = QuestionFlags;
   3796   OpCode.MaxContainers                   = MaxContainers;
   3797   OpCode.Flags                           = OrderedListFlags;
   3798 
   3799   Position = InternalHiiOpCodeHandlePosition (OpCodeHandle);
   3800   InternalHiiCreateOpCodeExtended (OpCodeHandle, &OpCode, EFI_IFR_ORDERED_LIST_OP, sizeof (OpCode), 0, 1);
   3801   InternalHiiAppendOpCodes (OpCodeHandle, OptionsOpCodeHandle);
   3802   if (DefaultsOpCodeHandle != NULL) {
   3803     InternalHiiAppendOpCodes (OpCodeHandle, DefaultsOpCodeHandle);
   3804   }
   3805   HiiCreateEndOpCode (OpCodeHandle);
   3806   return InternalHiiOpCodeHandleBuffer (OpCodeHandle) + Position;
   3807 }
   3808 
   3809 /**
   3810   Create EFI_IFR_TEXT_OP opcode.
   3811 
   3812   If OpCodeHandle is NULL, then ASSERT().
   3813 
   3814   @param[in]  OpCodeHandle  Handle to the buffer of opcodes.
   3815   @param[in]  Prompt        String ID for Prompt.
   3816   @param[in]  Help          String ID for Help.
   3817   @param[in]  TextTwo       String ID for TextTwo.
   3818 
   3819   @retval NULL   There is not enough space left in Buffer to add the opcode.
   3820   @retval Other  A pointer to the created opcode.
   3821 
   3822 **/
   3823 UINT8 *
   3824 EFIAPI
   3825 HiiCreateTextOpCode (
   3826   IN VOID           *OpCodeHandle,
   3827   IN EFI_STRING_ID  Prompt,
   3828   IN EFI_STRING_ID  Help,
   3829   IN EFI_STRING_ID  TextTwo
   3830   )
   3831 {
   3832   EFI_IFR_TEXT  OpCode;
   3833 
   3834   ZeroMem (&OpCode, sizeof (OpCode));
   3835   OpCode.Statement.Prompt = Prompt;
   3836   OpCode.Statement.Help   = Help;
   3837   OpCode.TextTwo          = TextTwo;
   3838 
   3839   return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_TEXT_OP, sizeof (OpCode));
   3840 }
   3841 
   3842 /**
   3843   Create EFI_IFR_DATE_OP opcode.
   3844 
   3845   If OpCodeHandle is NULL, then ASSERT().
   3846   If any reserved bits are set in QuestionFlags, then ASSERT().
   3847   If any reserved bits are set in DateFlags, then ASSERT().
   3848 
   3849   @param[in]  OpCodeHandle          Handle to the buffer of opcodes.
   3850   @param[in]  QuestionId            Question ID
   3851   @param[in]  VarStoreId            Storage ID, optional. If DateFlags is not
   3852                                     QF_DATE_STORAGE_NORMAL, this parameter is ignored.
   3853   @param[in]  VarOffset             Offset in Storage or String ID of the name (VarName)
   3854                                     for this name/value pair, optional. If DateFlags is not
   3855                                     QF_DATE_STORAGE_NORMAL, this parameter is ignored.
   3856   @param[in]  Prompt                String ID for Prompt
   3857   @param[in]  Help                  String ID for Help
   3858   @param[in]  QuestionFlags         Flags in Question Header
   3859   @param[in]  DateFlags             Flags for date opcode
   3860   @param[in]  DefaultsOpCodeHandle  Handle for a buffer of DEFAULT opcodes.  This
   3861                                     is an optional parameter that may be NULL.
   3862 
   3863   @retval NULL   There is not enough space left in Buffer to add the opcode.
   3864   @retval Other  A pointer to the created opcode.
   3865 
   3866 **/
   3867 UINT8 *
   3868 EFIAPI
   3869 HiiCreateDateOpCode (
   3870   IN VOID             *OpCodeHandle,
   3871   IN EFI_QUESTION_ID  QuestionId,
   3872   IN EFI_VARSTORE_ID  VarStoreId,   OPTIONAL
   3873   IN UINT16           VarOffset,    OPTIONAL
   3874   IN EFI_STRING_ID    Prompt,
   3875   IN EFI_STRING_ID    Help,
   3876   IN UINT8            QuestionFlags,
   3877   IN UINT8            DateFlags,
   3878   IN VOID             *DefaultsOpCodeHandle  OPTIONAL
   3879   )
   3880 {
   3881   EFI_IFR_DATE    OpCode;
   3882   UINTN           Position;
   3883 
   3884   ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED))) == 0);
   3885   ASSERT ((DateFlags & (~(EFI_QF_DATE_YEAR_SUPPRESS | EFI_QF_DATE_MONTH_SUPPRESS | EFI_QF_DATE_DAY_SUPPRESS | EFI_QF_DATE_STORAGE))) == 0);
   3886 
   3887   ZeroMem (&OpCode, sizeof (OpCode));
   3888   OpCode.Question.Header.Prompt          = Prompt;
   3889   OpCode.Question.Header.Help            = Help;
   3890   OpCode.Question.QuestionId             = QuestionId;
   3891   OpCode.Question.VarStoreId             = VarStoreId;
   3892   OpCode.Question.VarStoreInfo.VarOffset = VarOffset;
   3893   OpCode.Question.Flags                  = QuestionFlags;
   3894   OpCode.Flags                           = DateFlags;
   3895 
   3896   if (DefaultsOpCodeHandle == NULL) {
   3897     return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_DATE_OP, sizeof (OpCode));
   3898   }
   3899 
   3900   Position = InternalHiiOpCodeHandlePosition (OpCodeHandle);
   3901   InternalHiiCreateOpCodeExtended (OpCodeHandle, &OpCode, EFI_IFR_DATE_OP, sizeof (OpCode), 0, 1);
   3902   InternalHiiAppendOpCodes (OpCodeHandle, DefaultsOpCodeHandle);
   3903   HiiCreateEndOpCode (OpCodeHandle);
   3904   return InternalHiiOpCodeHandleBuffer (OpCodeHandle) + Position;
   3905 }
   3906 
   3907 /**
   3908   Create EFI_IFR_TIME_OP opcode.
   3909 
   3910   If OpCodeHandle is NULL, then ASSERT().
   3911   If any reserved bits are set in QuestionFlags, then ASSERT().
   3912   If any reserved bits are set in TimeFlags, then ASSERT().
   3913 
   3914   @param[in]  OpCodeHandle          Handle to the buffer of opcodes.
   3915   @param[in]  QuestionId            Question ID
   3916   @param[in]  VarStoreId            Storage ID, optional. If TimeFlags is not
   3917                                     QF_TIME_STORAGE_NORMAL, this parameter is ignored.
   3918   @param[in]  VarOffset             Offset in Storage or String ID of the name (VarName)
   3919                                     for this name/value pair, optional. If TimeFlags is not
   3920                                     QF_TIME_STORAGE_NORMAL, this parameter is ignored.
   3921   @param[in]  Prompt                String ID for Prompt
   3922   @param[in]  Help                  String ID for Help
   3923   @param[in]  QuestionFlags         Flags in Question Header
   3924   @param[in]  TimeFlags             Flags for time opcode
   3925   @param[in]  DefaultsOpCodeHandle  Handle for a buffer of DEFAULT opcodes.  This
   3926                                     is an optional parameter that may be NULL.
   3927 
   3928   @retval NULL   There is not enough space left in Buffer to add the opcode.
   3929   @retval Other  A pointer to the created opcode.
   3930 
   3931 **/
   3932 UINT8 *
   3933 EFIAPI
   3934 HiiCreateTimeOpCode (
   3935   IN VOID             *OpCodeHandle,
   3936   IN EFI_QUESTION_ID  QuestionId,
   3937   IN EFI_VARSTORE_ID  VarStoreId,   OPTIONAL
   3938   IN UINT16           VarOffset,    OPTIONAL
   3939   IN EFI_STRING_ID    Prompt,
   3940   IN EFI_STRING_ID    Help,
   3941   IN UINT8            QuestionFlags,
   3942   IN UINT8            TimeFlags,
   3943   IN VOID             *DefaultsOpCodeHandle  OPTIONAL
   3944   )
   3945 {
   3946   EFI_IFR_TIME    OpCode;
   3947   UINTN           Position;
   3948 
   3949   ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED))) == 0);
   3950   ASSERT ((TimeFlags & (~(QF_TIME_HOUR_SUPPRESS | QF_TIME_MINUTE_SUPPRESS | QF_TIME_SECOND_SUPPRESS | QF_TIME_STORAGE))) == 0);
   3951 
   3952   ZeroMem (&OpCode, sizeof (OpCode));
   3953   OpCode.Question.Header.Prompt          = Prompt;
   3954   OpCode.Question.Header.Help            = Help;
   3955   OpCode.Question.QuestionId             = QuestionId;
   3956   OpCode.Question.VarStoreId             = VarStoreId;
   3957   OpCode.Question.VarStoreInfo.VarOffset = VarOffset;
   3958   OpCode.Question.Flags                  = QuestionFlags;
   3959   OpCode.Flags                           = TimeFlags;
   3960 
   3961   if (DefaultsOpCodeHandle == NULL) {
   3962     return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_TIME_OP, sizeof (OpCode));
   3963   }
   3964 
   3965   Position = InternalHiiOpCodeHandlePosition (OpCodeHandle);
   3966   InternalHiiCreateOpCodeExtended (OpCodeHandle, &OpCode, EFI_IFR_TIME_OP, sizeof (OpCode), 0, 1);
   3967   InternalHiiAppendOpCodes (OpCodeHandle, DefaultsOpCodeHandle);
   3968   HiiCreateEndOpCode (OpCodeHandle);
   3969   return InternalHiiOpCodeHandleBuffer (OpCodeHandle) + Position;
   3970 }
   3971 
   3972 /**
   3973   This is the internal worker function to update the data in
   3974   a form specified by FormSetGuid, FormId and Label.
   3975 
   3976   @param[in] FormSetGuid       The optional Formset GUID.
   3977   @param[in] FormId            The Form ID.
   3978   @param[in] Package           The package header.
   3979   @param[in] OpCodeBufferStart An OpCode buffer that contains the set of IFR
   3980                                opcodes to be inserted or replaced in the form.
   3981   @param[in] OpCodeBufferEnd   An OpCcode buffer that contains the IFR opcode
   3982                                that marks the end of a replace operation in the form.
   3983   @param[out] TempPackage      The resultant package.
   3984 
   3985   @retval EFI_SUCCESS    The function completes successfully.
   3986   @retval EFI_NOT_FOUND  The updated opcode or endopcode is not found.
   3987 
   3988 **/
   3989 EFI_STATUS
   3990 EFIAPI
   3991 InternalHiiUpdateFormPackageData (
   3992   IN  EFI_GUID               *FormSetGuid, OPTIONAL
   3993   IN  EFI_FORM_ID            FormId,
   3994   IN  EFI_HII_PACKAGE_HEADER *Package,
   3995   IN  HII_LIB_OPCODE_BUFFER  *OpCodeBufferStart,
   3996   IN  HII_LIB_OPCODE_BUFFER  *OpCodeBufferEnd,    OPTIONAL
   3997   OUT EFI_HII_PACKAGE_HEADER *TempPackage
   3998   )
   3999 {
   4000   UINTN                     AddSize;
   4001   UINT8                     *BufferPos;
   4002   EFI_HII_PACKAGE_HEADER    PackageHeader;
   4003   UINTN                     Offset;
   4004   EFI_IFR_OP_HEADER         *IfrOpHdr;
   4005   EFI_IFR_OP_HEADER         *UpdateIfrOpHdr;
   4006   BOOLEAN                   GetFormSet;
   4007   BOOLEAN                   GetForm;
   4008   BOOLEAN                   Updated;
   4009   UINTN                     UpdatePackageLength;
   4010 
   4011   CopyMem (TempPackage, Package, sizeof (EFI_HII_PACKAGE_HEADER));
   4012   UpdatePackageLength = sizeof (EFI_HII_PACKAGE_HEADER);
   4013   BufferPos           = (UINT8 *) (TempPackage + 1);
   4014 
   4015   CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));
   4016   IfrOpHdr   = (EFI_IFR_OP_HEADER *)((UINT8 *) Package + sizeof (EFI_HII_PACKAGE_HEADER));
   4017   Offset     = sizeof (EFI_HII_PACKAGE_HEADER);
   4018   GetFormSet = (BOOLEAN) ((FormSetGuid == NULL) ? TRUE : FALSE);
   4019   GetForm    = FALSE;
   4020   Updated    = FALSE;
   4021 
   4022   while (Offset < PackageHeader.Length) {
   4023     CopyMem (BufferPos, IfrOpHdr, IfrOpHdr->Length);
   4024     BufferPos           += IfrOpHdr->Length;
   4025     UpdatePackageLength += IfrOpHdr->Length;
   4026 
   4027     //
   4028     // Find the matched FormSet and Form
   4029     //
   4030     if ((IfrOpHdr->OpCode == EFI_IFR_FORM_SET_OP) && (FormSetGuid != NULL)) {
   4031       if (CompareGuid((GUID *)(VOID *)&((EFI_IFR_FORM_SET *) IfrOpHdr)->Guid, FormSetGuid)) {
   4032         GetFormSet = TRUE;
   4033       } else {
   4034         GetFormSet = FALSE;
   4035       }
   4036     } else if (IfrOpHdr->OpCode == EFI_IFR_FORM_OP || IfrOpHdr->OpCode == EFI_IFR_FORM_MAP_OP) {
   4037       if (CompareMem (&((EFI_IFR_FORM *) IfrOpHdr)->FormId, &FormId, sizeof (EFI_FORM_ID)) == 0) {
   4038         GetForm = TRUE;
   4039       } else {
   4040         GetForm = FALSE;
   4041       }
   4042     }
   4043 
   4044     //
   4045     // The matched Form is found, and Update data in this form
   4046     //
   4047     if (GetFormSet && GetForm) {
   4048       UpdateIfrOpHdr = (EFI_IFR_OP_HEADER *) OpCodeBufferStart->Buffer;
   4049       if ((UpdateIfrOpHdr->Length == IfrOpHdr->Length) && \
   4050           (CompareMem (IfrOpHdr, UpdateIfrOpHdr, UpdateIfrOpHdr->Length) == 0)) {
   4051         //
   4052         // Remove the original data when End OpCode buffer exist.
   4053         //
   4054         if (OpCodeBufferEnd != NULL) {
   4055           Offset        += IfrOpHdr->Length;
   4056           IfrOpHdr       = (EFI_IFR_OP_HEADER *) ((UINT8 *) (IfrOpHdr) + IfrOpHdr->Length);
   4057           UpdateIfrOpHdr = (EFI_IFR_OP_HEADER *) OpCodeBufferEnd->Buffer;
   4058           while (Offset < PackageHeader.Length) {
   4059             //
   4060             // Search the matched end opcode
   4061             //
   4062             if ((UpdateIfrOpHdr->Length == IfrOpHdr->Length) && \
   4063                 (CompareMem (IfrOpHdr, UpdateIfrOpHdr, UpdateIfrOpHdr->Length) == 0)) {
   4064               break;
   4065             }
   4066             //
   4067             // Go to the next Op-Code
   4068             //
   4069             Offset        += IfrOpHdr->Length;
   4070             IfrOpHdr       = (EFI_IFR_OP_HEADER *) ((UINT8 *) (IfrOpHdr) + IfrOpHdr->Length);
   4071           }
   4072 
   4073           if (Offset >= PackageHeader.Length) {
   4074             //
   4075             // The end opcode is not found.
   4076             //
   4077             return EFI_NOT_FOUND;
   4078           }
   4079         }
   4080 
   4081         //
   4082         // Insert the updated data
   4083         //
   4084         AddSize = ((EFI_IFR_OP_HEADER *) OpCodeBufferStart->Buffer)->Length;
   4085         CopyMem (BufferPos, OpCodeBufferStart->Buffer + AddSize, OpCodeBufferStart->Position - AddSize);
   4086         BufferPos           += OpCodeBufferStart->Position - AddSize;
   4087         UpdatePackageLength += OpCodeBufferStart->Position - AddSize;
   4088 
   4089         if (OpCodeBufferEnd != NULL) {
   4090           //
   4091           // Add the end opcode
   4092           //
   4093           CopyMem (BufferPos, IfrOpHdr, IfrOpHdr->Length);
   4094           BufferPos           += IfrOpHdr->Length;
   4095           UpdatePackageLength += IfrOpHdr->Length;
   4096         }
   4097 
   4098         //
   4099         // Copy the left package data.
   4100         //
   4101         Offset += IfrOpHdr->Length;
   4102         CopyMem (BufferPos, (UINT8 *) Package + Offset, PackageHeader.Length - Offset);
   4103         UpdatePackageLength += PackageHeader.Length - Offset;
   4104 
   4105         //
   4106         // Set update flag
   4107         //
   4108         Updated = TRUE;
   4109         break;
   4110       }
   4111     }
   4112 
   4113     //
   4114     // Go to the next Op-Code
   4115     //
   4116     Offset   += IfrOpHdr->Length;
   4117     IfrOpHdr = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (IfrOpHdr) + IfrOpHdr->Length);
   4118   }
   4119 
   4120   if (!Updated) {
   4121     //
   4122     // The updated opcode buffer is not found.
   4123     //
   4124     return EFI_NOT_FOUND;
   4125   }
   4126   //
   4127   // Update the package length.
   4128   //
   4129   PackageHeader.Length = (UINT32) UpdatePackageLength;
   4130   CopyMem (TempPackage, &PackageHeader, sizeof (EFI_HII_PACKAGE_HEADER));
   4131 
   4132   return EFI_SUCCESS;
   4133 }
   4134 
   4135 /**
   4136   This function updates a form that has previously been registered with the HII
   4137   Database.  This function will perform at most one update operation.
   4138 
   4139   The form to update is specified by Handle, FormSetGuid, and FormId.  Binary
   4140   comparisons of IFR opcodes are performed from the beginning of the form being
   4141   updated until an IFR opcode is found that exactly matches the first IFR opcode
   4142   specified by StartOpCodeHandle.  The following rules are used to determine if
   4143   an insert, replace, or delete operation is performed.
   4144 
   4145   1) If no matches are found, then NULL is returned.
   4146   2) If a match is found, and EndOpCodeHandle is NULL, then all of the IFR opcodes
   4147      from StartOpCodeHandle except the first opcode are inserted immediately after
   4148      the matching IFR opcode in the form to be updated.
   4149   3) If a match is found, and EndOpCodeHandle is not NULL, then a search is made
   4150      from the matching IFR opcode until an IFR opcode exactly matches the first
   4151      IFR opcode specified by EndOpCodeHandle.  If no match is found for the first
   4152      IFR opcode specified by EndOpCodeHandle, then NULL is returned.  If a match
   4153      is found, then all of the IFR opcodes between the start match and the end
   4154      match are deleted from the form being updated and all of the IFR opcodes
   4155      from StartOpCodeHandle except the first opcode are inserted immediately after
   4156      the matching start IFR opcode.  If StartOpCcodeHandle only contains one
   4157      IFR instruction, then the result of this operation will delete all of the IFR
   4158      opcodes between the start end matches.
   4159 
   4160   If HiiHandle is NULL, then ASSERT().
   4161   If StartOpCodeHandle is NULL, then ASSERT().
   4162 
   4163   @param[in]  HiiHandle          The HII Handle of the form to update.
   4164   @param[in]  FormSetGuid        The Formset GUID of the form to update.  This
   4165                                  is an optional parameter that may be NULL.
   4166                                  If it is NULL, all FormSet will be updated.
   4167   @param[in]  FormId             The ID of the form to update.
   4168   @param[in]  StartOpCodeHandle  An OpCode Handle that contains the set of IFR
   4169                                  opcodes to be inserted or replaced in the form.
   4170                                  The first IFR instruction in StartOpCodeHandle
   4171                                  is used to find matching IFR opcode in the
   4172                                  form.
   4173   @param[in]  EndOpCodeHandle    An OpCcode Handle that contains the IFR opcode
   4174                                  that marks the end of a replace operation in
   4175                                  the form.  This is an optional parameter that
   4176                                  may be NULL.  If it is NULL, then an the IFR
   4177                                  opcodes specified by StartOpCodeHandle are
   4178                                  inserted into the form.
   4179 
   4180   @retval EFI_OUT_OF_RESOURCES   No enough memory resource is allocated.
   4181   @retval EFI_NOT_FOUND          The following cases will return EFI_NOT_FOUND.
   4182                                  1) The form specified by HiiHandle, FormSetGuid,
   4183                                  and FormId could not be found in the HII Database.
   4184                                  2) No IFR opcodes in the target form match the first
   4185                                  IFR opcode in StartOpCodeHandle.
   4186                                  3) EndOpCOde is not NULL, and no IFR opcodes in the
   4187                                  target form following a matching start opcode match
   4188                                  the first IFR opcode in EndOpCodeHandle.
   4189   @retval EFI_SUCCESS            The matched form is updated by StartOpcode.
   4190 
   4191 **/
   4192 EFI_STATUS
   4193 EFIAPI
   4194 HiiUpdateForm (
   4195   IN EFI_HII_HANDLE  HiiHandle,
   4196   IN EFI_GUID        *FormSetGuid,        OPTIONAL
   4197   IN EFI_FORM_ID     FormId,
   4198   IN VOID            *StartOpCodeHandle,
   4199   IN VOID            *EndOpCodeHandle     OPTIONAL
   4200   )
   4201 {
   4202   EFI_STATUS                   Status;
   4203   EFI_HII_PACKAGE_LIST_HEADER  *HiiPackageList;
   4204   UINT32                       PackageListLength;
   4205   UINT32                       Offset;
   4206   EFI_HII_PACKAGE_LIST_HEADER  *UpdatePackageList;
   4207   UINTN                        BufferSize;
   4208   UINT8                        *UpdateBufferPos;
   4209   EFI_HII_PACKAGE_HEADER       *Package;
   4210   EFI_HII_PACKAGE_HEADER       *TempPackage;
   4211   EFI_HII_PACKAGE_HEADER       PackageHeader;
   4212   BOOLEAN                      Updated;
   4213   HII_LIB_OPCODE_BUFFER        *OpCodeBufferStart;
   4214   HII_LIB_OPCODE_BUFFER        *OpCodeBufferEnd;
   4215 
   4216   //
   4217   // Input update data can't be NULL.
   4218   //
   4219   ASSERT (HiiHandle != NULL);
   4220   ASSERT (StartOpCodeHandle != NULL);
   4221   UpdatePackageList = NULL;
   4222   TempPackage       = NULL;
   4223   HiiPackageList    = NULL;
   4224 
   4225   //
   4226   // Retrieve buffer data from Opcode Handle
   4227   //
   4228   OpCodeBufferStart = (HII_LIB_OPCODE_BUFFER *) StartOpCodeHandle;
   4229   OpCodeBufferEnd   = (HII_LIB_OPCODE_BUFFER *) EndOpCodeHandle;
   4230 
   4231   //
   4232   // Get the original package list
   4233   //
   4234   BufferSize = 0;
   4235   HiiPackageList   = NULL;
   4236   Status = gHiiDatabase->ExportPackageLists (gHiiDatabase, HiiHandle, &BufferSize, HiiPackageList);
   4237   //
   4238   // The return status should always be EFI_BUFFER_TOO_SMALL as input buffer's size is 0.
   4239   //
   4240   if (Status != EFI_BUFFER_TOO_SMALL) {
   4241     return Status;
   4242   }
   4243 
   4244   HiiPackageList = AllocatePool (BufferSize);
   4245   if (HiiPackageList == NULL) {
   4246     Status = EFI_OUT_OF_RESOURCES;
   4247     goto Finish;
   4248   }
   4249 
   4250   Status = gHiiDatabase->ExportPackageLists (gHiiDatabase, HiiHandle, &BufferSize, HiiPackageList);
   4251   if (EFI_ERROR (Status)) {
   4252     goto Finish;
   4253   }
   4254 
   4255   //
   4256   // Calculate and allocate space for retrieval of IFR data
   4257   //
   4258   BufferSize += OpCodeBufferStart->Position;
   4259   UpdatePackageList = AllocateZeroPool (BufferSize);
   4260   if (UpdatePackageList == NULL) {
   4261     Status = EFI_OUT_OF_RESOURCES;
   4262     goto Finish;
   4263   }
   4264 
   4265   //
   4266   // Allocate temp buffer to store the temp updated package buffer
   4267   //
   4268   TempPackage = AllocateZeroPool (BufferSize);
   4269   if (TempPackage == NULL) {
   4270     Status = EFI_OUT_OF_RESOURCES;
   4271     goto Finish;
   4272   }
   4273 
   4274   UpdateBufferPos = (UINT8 *) UpdatePackageList;
   4275 
   4276   //
   4277   // Copy the package list header
   4278   //
   4279   CopyMem (UpdateBufferPos, HiiPackageList, sizeof (EFI_HII_PACKAGE_LIST_HEADER));
   4280   UpdateBufferPos += sizeof (EFI_HII_PACKAGE_LIST_HEADER);
   4281 
   4282   //
   4283   // Go through each package to find the matched package and update one by one
   4284   //
   4285   Updated = FALSE;
   4286   Offset  = sizeof (EFI_HII_PACKAGE_LIST_HEADER);
   4287   PackageListLength = ReadUnaligned32 (&HiiPackageList->PackageLength);
   4288   while (Offset < PackageListLength) {
   4289     Package = (EFI_HII_PACKAGE_HEADER *) (((UINT8 *) HiiPackageList) + Offset);
   4290     CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));
   4291     Offset += Package->Length;
   4292 
   4293     if (Package->Type == EFI_HII_PACKAGE_FORMS) {
   4294       //
   4295       // Check this package is the matched package.
   4296       //
   4297       Status = InternalHiiUpdateFormPackageData (FormSetGuid, FormId, Package, OpCodeBufferStart, OpCodeBufferEnd, TempPackage);
   4298       //
   4299       // The matched package is found. Its package buffer will be updated by the input new data.
   4300       //
   4301       if (!EFI_ERROR(Status)) {
   4302         //
   4303         // Set Update Flag
   4304         //
   4305         Updated = TRUE;
   4306         //
   4307         // Add updated package buffer
   4308         //
   4309         Package = TempPackage;
   4310       }
   4311     }
   4312 
   4313     //
   4314     // Add pacakge buffer
   4315     //
   4316     CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));
   4317     CopyMem (UpdateBufferPos, Package, PackageHeader.Length);
   4318     UpdateBufferPos += PackageHeader.Length;
   4319   }
   4320 
   4321   if (Updated) {
   4322     //
   4323     // Update package list length
   4324     //
   4325     BufferSize = UpdateBufferPos - (UINT8 *) UpdatePackageList;
   4326     WriteUnaligned32 (&UpdatePackageList->PackageLength, (UINT32) BufferSize);
   4327 
   4328     //
   4329     // Update Package to show form
   4330     //
   4331     Status = gHiiDatabase->UpdatePackageList (gHiiDatabase, HiiHandle, UpdatePackageList);
   4332   } else {
   4333     //
   4334     // Not matched form is found and updated.
   4335     //
   4336     Status = EFI_NOT_FOUND;
   4337   }
   4338 
   4339 Finish:
   4340   if (HiiPackageList != NULL) {
   4341     FreePool (HiiPackageList);
   4342   }
   4343 
   4344   if (UpdatePackageList != NULL) {
   4345     FreePool (UpdatePackageList);
   4346   }
   4347 
   4348   if (TempPackage != NULL) {
   4349     FreePool (TempPackage);
   4350   }
   4351 
   4352   return Status;
   4353 }
   4354