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