Home | History | Annotate | Download | only in HiiDatabaseDxe
      1 /** @file
      2 Implementation of interfaces function for EFI_HII_CONFIG_ROUTING_PROTOCOL.
      3 
      4 Copyright (c) 2007 - 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 
     16 #include "HiiDatabase.h"
     17 extern HII_DATABASE_PRIVATE_DATA mPrivate;
     18 
     19 /**
     20   Calculate the number of Unicode characters of the incoming Configuration string,
     21   not including NULL terminator.
     22 
     23   This is a internal function.
     24 
     25   @param  String                 String in <MultiConfigRequest> or
     26                                  <MultiConfigResp> format.
     27 
     28   @return The number of Unicode characters.
     29 
     30 **/
     31 UINTN
     32 CalculateConfigStringLen (
     33   IN EFI_STRING                    String
     34   )
     35 {
     36   EFI_STRING  TmpPtr;
     37 
     38   //
     39   // "GUID=" should be the first element of incoming string.
     40   //
     41   ASSERT (String != NULL);
     42   ASSERT (StrnCmp (String, L"GUID=", StrLen (L"GUID=")) == 0);
     43 
     44   //
     45   // The beginning of next <ConfigRequest>/<ConfigResp> should be "&GUID=".
     46   // Will meet '\0' if there is only one <ConfigRequest>/<ConfigResp>.
     47   //
     48   TmpPtr = StrStr (String, L"&GUID=");
     49   if (TmpPtr == NULL) {
     50     return StrLen (String);
     51   }
     52 
     53   return (TmpPtr - String);
     54 }
     55 
     56 
     57 /**
     58   Convert the hex UNICODE %02x encoding of a UEFI device path to binary
     59   from <PathHdr> of <ConfigHdr>.
     60 
     61   This is a internal function.
     62 
     63   @param  String                 UEFI configuration string
     64   @param  DevicePathData         Binary of a UEFI device path.
     65 
     66   @retval EFI_NOT_FOUND          The device path is not invalid.
     67   @retval EFI_INVALID_PARAMETER  Any incoming parameter is invalid.
     68   @retval EFI_OUT_OF_RESOURCES   Lake of resources to store neccesary structures.
     69   @retval EFI_SUCCESS            The device path is retrieved and translated to
     70                                  binary format.
     71 
     72 **/
     73 EFI_STATUS
     74 GetDevicePath (
     75   IN  EFI_STRING                   String,
     76   OUT UINT8                        **DevicePathData
     77   )
     78 {
     79   UINTN                    Length;
     80   EFI_STRING               PathHdr;
     81   UINT8                    *DevicePathBuffer;
     82   CHAR16                   TemStr[2];
     83   UINTN                    Index;
     84   UINT8                    DigitUint8;
     85   EFI_DEVICE_PATH_PROTOCOL *DevicePath;
     86 
     87 
     88   if (String == NULL || DevicePathData == NULL) {
     89     return EFI_INVALID_PARAMETER;
     90   }
     91 
     92   //
     93   // Find the 'PATH=' of <PathHdr> and skip it.
     94   //
     95   for (; (*String != 0 && StrnCmp (String, L"PATH=", StrLen (L"PATH=")) != 0); String++);
     96   if (*String == 0) {
     97     return EFI_INVALID_PARAMETER;
     98   }
     99   //
    100   // Check whether path data does exist.
    101   //
    102   String += StrLen (L"PATH=");
    103   if (*String == 0) {
    104     return EFI_INVALID_PARAMETER;
    105   }
    106   PathHdr = String;
    107 
    108   //
    109   // The content between 'PATH=' of <ConfigHdr> and '&' of next element
    110   // or '\0' (end of configuration string) is the UNICODE %02x bytes encoding
    111   // of UEFI device path.
    112   //
    113   for (Length = 0; *String != 0 && *String != L'&'; String++, Length++);
    114   //
    115   // Check DevicePath Length
    116   //
    117   if (((Length + 1) / 2) < sizeof (EFI_DEVICE_PATH_PROTOCOL)) {
    118     return EFI_NOT_FOUND;
    119   }
    120 
    121   //
    122   // The data in <PathHdr> is encoded as hex UNICODE %02x bytes in the same order
    123   // as the device path resides in RAM memory.
    124   // Translate the data into binary.
    125   //
    126   DevicePathBuffer = (UINT8 *) AllocateZeroPool ((Length + 1) / 2);
    127   if (DevicePathBuffer == NULL) {
    128     return EFI_OUT_OF_RESOURCES;
    129   }
    130 
    131   //
    132   // Convert DevicePath
    133   //
    134   ZeroMem (TemStr, sizeof (TemStr));
    135   for (Index = 0; Index < Length; Index ++) {
    136     TemStr[0] = PathHdr[Index];
    137     DigitUint8 = (UINT8) StrHexToUint64 (TemStr);
    138     if ((Index & 1) == 0) {
    139       DevicePathBuffer [Index/2] = DigitUint8;
    140     } else {
    141       DevicePathBuffer [Index/2] = (UINT8) ((DevicePathBuffer [Index/2] << 4) + DigitUint8);
    142     }
    143   }
    144 
    145   //
    146   // Validate DevicePath
    147   //
    148   DevicePath  = (EFI_DEVICE_PATH_PROTOCOL *) DevicePathBuffer;
    149   while (!IsDevicePathEnd (DevicePath)) {
    150     if ((DevicePath->Type == 0) || (DevicePath->SubType == 0) || (DevicePathNodeLength (DevicePath) < sizeof (EFI_DEVICE_PATH_PROTOCOL))) {
    151       //
    152       // Invalid device path
    153       //
    154       FreePool (DevicePathBuffer);
    155       return EFI_NOT_FOUND;
    156     }
    157     DevicePath = NextDevicePathNode (DevicePath);
    158   }
    159 
    160   //
    161   // return the device path
    162   //
    163   *DevicePathData = DevicePathBuffer;
    164   return EFI_SUCCESS;
    165 }
    166 
    167 /**
    168   Converts the unicode character of the string from uppercase to lowercase.
    169   This is a internal function.
    170 
    171   @param ConfigString  String to be converted
    172 
    173 **/
    174 VOID
    175 EFIAPI
    176 HiiToLower (
    177   IN EFI_STRING  ConfigString
    178   )
    179 {
    180   EFI_STRING  String;
    181   BOOLEAN     Lower;
    182 
    183   ASSERT (ConfigString != NULL);
    184 
    185   //
    186   // Convert all hex digits in range [A-F] in the configuration header to [a-f]
    187   //
    188   for (String = ConfigString, Lower = FALSE; *String != L'\0'; String++) {
    189     if (*String == L'=') {
    190       Lower = TRUE;
    191     } else if (*String == L'&') {
    192       Lower = FALSE;
    193     } else if (Lower && *String >= L'A' && *String <= L'F') {
    194       *String = (CHAR16) (*String - L'A' + L'a');
    195     }
    196   }
    197 
    198   return;
    199 }
    200 
    201 /**
    202   Generate a sub string then output it.
    203 
    204   This is a internal function.
    205 
    206   @param  String                 A constant string which is the prefix of the to be
    207                                  generated string, e.g. GUID=
    208 
    209   @param  BufferLen              The length of the Buffer in bytes.
    210 
    211   @param  Buffer                 Points to a buffer which will be converted to be the
    212                                  content of the generated string.
    213 
    214   @param  Flag                   If 1, the buffer contains data for the value of GUID or PATH stored in
    215                                  UINT8 *; if 2, the buffer contains unicode string for the value of NAME;
    216                                  if 3, the buffer contains other data.
    217 
    218   @param  SubStr                 Points to the output string. It's caller's
    219                                  responsibility to free this buffer.
    220 
    221 
    222 **/
    223 VOID
    224 GenerateSubStr (
    225   IN CONST EFI_STRING              String,
    226   IN  UINTN                        BufferLen,
    227   IN  VOID                         *Buffer,
    228   IN  UINT8                        Flag,
    229   OUT EFI_STRING                   *SubStr
    230   )
    231 {
    232   UINTN       Length;
    233   EFI_STRING  Str;
    234   EFI_STRING  StringHeader;
    235   CHAR16      *TemString;
    236   CHAR16      *TemName;
    237   UINT8       *TemBuffer;
    238   UINTN       Index;
    239 
    240   ASSERT (String != NULL && SubStr != NULL);
    241 
    242   if (Buffer == NULL) {
    243     *SubStr = AllocateCopyPool (StrSize (String), String);
    244     ASSERT (*SubStr != NULL);
    245     return;
    246   }
    247 
    248   //
    249   // Header + Data + '&' + '\0'
    250   //
    251   Length = StrLen (String) + BufferLen * 2 + 1 + 1;
    252   Str    = AllocateZeroPool (Length * sizeof (CHAR16));
    253   ASSERT (Str != NULL);
    254 
    255   StrCpyS (Str, Length, String);
    256 
    257   StringHeader = Str + StrLen (String);
    258   TemString    = (CHAR16 *) StringHeader;
    259 
    260   switch (Flag) {
    261   case 1:
    262     //
    263     // Convert Buffer to Hex String in reverse order
    264     //
    265     TemBuffer = ((UINT8 *) Buffer);
    266     for (Index = 0; Index < BufferLen; Index ++, TemBuffer ++) {
    267       TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemBuffer, 2);
    268     }
    269     break;
    270   case 2:
    271     //
    272     // Check buffer is enough
    273     //
    274     TemName = (CHAR16 *) Buffer;
    275     ASSERT ((BufferLen * 2 + 1) >= (StrLen (TemName) * 4 + 1));
    276     //
    277     // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
    278     //
    279     for (; *TemName != L'\0'; TemName++) {
    280       TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemName, 4);
    281     }
    282     break;
    283   case 3:
    284     //
    285     // Convert Buffer to Hex String
    286     //
    287     TemBuffer = ((UINT8 *) Buffer) + BufferLen - 1;
    288     for (Index = 0; Index < BufferLen; Index ++, TemBuffer --) {
    289       TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemBuffer, 2);
    290     }
    291     break;
    292   default:
    293     break;
    294   }
    295 
    296   //
    297   // Convert the uppercase to lowercase since <HexAf> is defined in lowercase format.
    298   //
    299   StrCatS (Str, Length, L"&");
    300   HiiToLower (Str);
    301 
    302   *SubStr = Str;
    303 }
    304 
    305 
    306 /**
    307   Retrieve the <ConfigBody> from String then output it.
    308 
    309   This is a internal function.
    310 
    311   @param  String                 A sub string of a configuration string in
    312                                  <MultiConfigAltResp> format.
    313   @param  ConfigBody             Points to the output string. It's caller's
    314                                  responsibility to free this buffer.
    315 
    316   @retval EFI_INVALID_PARAMETER  There is no form package in current hii database.
    317   @retval EFI_OUT_OF_RESOURCES   Not enough memory to finish this operation.
    318   @retval EFI_SUCCESS            All existing storage is exported.
    319 
    320 **/
    321 EFI_STATUS
    322 OutputConfigBody (
    323   IN  EFI_STRING                   String,
    324   OUT EFI_STRING                   *ConfigBody
    325   )
    326 {
    327   EFI_STRING  TmpPtr;
    328   EFI_STRING  Result;
    329   UINTN       Length;
    330 
    331   if (String == NULL || ConfigBody == NULL) {
    332     return EFI_INVALID_PARAMETER;
    333   }
    334 
    335   //
    336   // The setting information should start OFFSET, not ALTCFG.
    337   //
    338   if (StrnCmp (String, L"&ALTCFG=", StrLen (L"&ALTCFG=")) == 0) {
    339     return EFI_INVALID_PARAMETER;
    340   }
    341 
    342   TmpPtr = StrStr (String, L"GUID=");
    343   if (TmpPtr == NULL) {
    344     //
    345     // It is the last <ConfigResp> of the incoming configuration string.
    346     //
    347     Result = AllocateCopyPool (StrSize (String), String);
    348     if (Result == NULL) {
    349       return EFI_OUT_OF_RESOURCES;
    350     } else {
    351       *ConfigBody = Result;
    352       return EFI_SUCCESS;
    353     }
    354   }
    355 
    356   Length = TmpPtr - String;
    357   if (Length == 0) {
    358     return EFI_NOT_FOUND;
    359   }
    360   Result = AllocateCopyPool (Length * sizeof (CHAR16), String);
    361   if (Result == NULL) {
    362     return EFI_OUT_OF_RESOURCES;
    363   }
    364 
    365   *(Result + Length - 1) = 0;
    366   *ConfigBody = Result;
    367   return EFI_SUCCESS;
    368 }
    369 
    370 /**
    371   Append a string to a multi-string format.
    372 
    373   This is a internal function.
    374 
    375   @param  MultiString            String in <MultiConfigRequest>,
    376                                  <MultiConfigAltResp>, or <MultiConfigResp>. On
    377                                  input, the buffer length of  this string is
    378                                  MAX_STRING_LENGTH. On output, the  buffer length
    379                                  might be updated.
    380   @param  AppendString           NULL-terminated Unicode string.
    381 
    382   @retval EFI_INVALID_PARAMETER  Any incoming parameter is invalid.
    383   @retval EFI_SUCCESS            AppendString is append to the end of MultiString
    384 
    385 **/
    386 EFI_STATUS
    387 AppendToMultiString (
    388   IN OUT EFI_STRING                *MultiString,
    389   IN EFI_STRING                    AppendString
    390   )
    391 {
    392   UINTN AppendStringSize;
    393   UINTN MultiStringSize;
    394   UINTN MaxLen;
    395 
    396   if (MultiString == NULL || *MultiString == NULL || AppendString == NULL) {
    397     return EFI_INVALID_PARAMETER;
    398   }
    399 
    400   AppendStringSize = StrSize (AppendString);
    401   MultiStringSize  = StrSize (*MultiString);
    402   MaxLen = MAX_STRING_LENGTH / sizeof (CHAR16);
    403 
    404   //
    405   // Enlarge the buffer each time when length exceeds MAX_STRING_LENGTH.
    406   //
    407   if (MultiStringSize + AppendStringSize > MAX_STRING_LENGTH ||
    408       MultiStringSize > MAX_STRING_LENGTH) {
    409     *MultiString = (EFI_STRING) ReallocatePool (
    410                                   MultiStringSize,
    411                                   MultiStringSize + AppendStringSize,
    412                                   (VOID *) (*MultiString)
    413                                   );
    414     MaxLen = (MultiStringSize + AppendStringSize) / sizeof (CHAR16);
    415     ASSERT (*MultiString != NULL);
    416   }
    417   //
    418   // Append the incoming string
    419   //
    420   StrCatS (*MultiString, MaxLen, AppendString);
    421 
    422   return EFI_SUCCESS;
    423 }
    424 
    425 
    426 /**
    427   Get the value of <Number> in <BlockConfig> format, i.e. the value of OFFSET
    428   or WIDTH or VALUE.
    429   <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>
    430 
    431   This is a internal function.
    432 
    433   @param  StringPtr              String in <BlockConfig> format and points to the
    434                                  first character of <Number>.
    435   @param  Number                 The output value. Caller takes the responsibility
    436                                  to free memory.
    437   @param  Len                    Length of the <Number>, in characters.
    438 
    439   @retval EFI_OUT_OF_RESOURCES   Insufficient resources to store neccessary
    440                                  structures.
    441   @retval EFI_SUCCESS            Value of <Number> is outputted in Number
    442                                  successfully.
    443 
    444 **/
    445 EFI_STATUS
    446 GetValueOfNumber (
    447   IN EFI_STRING                    StringPtr,
    448   OUT UINT8                        **Number,
    449   OUT UINTN                        *Len
    450   )
    451 {
    452   EFI_STRING               TmpPtr;
    453   UINTN                    Length;
    454   EFI_STRING               Str;
    455   UINT8                    *Buf;
    456   EFI_STATUS               Status;
    457   UINT8                    DigitUint8;
    458   UINTN                    Index;
    459   CHAR16                   TemStr[2];
    460 
    461   if (StringPtr == NULL || *StringPtr == L'\0' || Number == NULL || Len == NULL) {
    462     return EFI_INVALID_PARAMETER;
    463   }
    464 
    465   Buf = NULL;
    466 
    467   TmpPtr = StringPtr;
    468   while (*StringPtr != L'\0' && *StringPtr != L'&') {
    469     StringPtr++;
    470   }
    471   *Len   = StringPtr - TmpPtr;
    472   Length = *Len + 1;
    473 
    474   Str = (EFI_STRING) AllocateZeroPool (Length * sizeof (CHAR16));
    475   if (Str == NULL) {
    476     Status = EFI_OUT_OF_RESOURCES;
    477     goto Exit;
    478   }
    479   CopyMem (Str, TmpPtr, *Len * sizeof (CHAR16));
    480   *(Str + *Len) = L'\0';
    481 
    482   Length = (Length + 1) / 2;
    483   Buf = (UINT8 *) AllocateZeroPool (Length);
    484   if (Buf == NULL) {
    485     Status = EFI_OUT_OF_RESOURCES;
    486     goto Exit;
    487   }
    488 
    489   Length = *Len;
    490   ZeroMem (TemStr, sizeof (TemStr));
    491   for (Index = 0; Index < Length; Index ++) {
    492     TemStr[0] = Str[Length - Index - 1];
    493     DigitUint8 = (UINT8) StrHexToUint64 (TemStr);
    494     if ((Index & 1) == 0) {
    495       Buf [Index/2] = DigitUint8;
    496     } else {
    497       Buf [Index/2] = (UINT8) ((DigitUint8 << 4) + Buf [Index/2]);
    498     }
    499   }
    500 
    501   *Number = Buf;
    502   Status  = EFI_SUCCESS;
    503 
    504 Exit:
    505   if (Str != NULL) {
    506     FreePool (Str);
    507   }
    508 
    509   return Status;
    510 }
    511 
    512 /**
    513   This function merges DefaultAltCfgResp string into AltCfgResp string for
    514   the missing AltCfgId in AltCfgResq.
    515 
    516   @param  AltCfgResp             Pointer to a null-terminated Unicode string in
    517                                  <ConfigAltResp> format. The default value string
    518                                  will be merged into it.
    519   @param  DefaultAltCfgResp      Pointer to a null-terminated Unicode string in
    520                                  <MultiConfigAltResp> format. The default value
    521                                  string may contain more than one ConfigAltResp
    522                                  string for the different varstore buffer.
    523 
    524   @retval EFI_SUCCESS            The merged string returns.
    525   @retval EFI_INVALID_PARAMETER  *AltCfgResp is to NULL.
    526 **/
    527 EFI_STATUS
    528 EFIAPI
    529 MergeDefaultString (
    530   IN OUT EFI_STRING  *AltCfgResp,
    531   IN     EFI_STRING  DefaultAltCfgResp
    532   )
    533 {
    534   EFI_STRING   StringPtrDefault;
    535   EFI_STRING   StringPtrEnd;
    536   CHAR16       TempChar;
    537   EFI_STRING   StringPtr;
    538   EFI_STRING   AltConfigHdr;
    539   UINTN        HeaderLength;
    540   UINTN        SizeAltCfgResp;
    541   UINTN        MaxLen;
    542   UINTN        TotalSize;
    543 
    544   if (*AltCfgResp == NULL) {
    545     return EFI_INVALID_PARAMETER;
    546   }
    547 
    548   //
    549   // Get the requestr ConfigHdr
    550   //
    551   SizeAltCfgResp  = 0;
    552   StringPtr       = *AltCfgResp;
    553 
    554   //
    555   // Find <ConfigHdr> GUID=...&NAME=...&PATH=...
    556   //
    557   if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {
    558     return EFI_INVALID_PARAMETER;
    559   }
    560   while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&NAME=", StrLen (L"&NAME=")) != 0) {
    561     StringPtr++;
    562   }
    563   while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&PATH=", StrLen (L"&PATH=")) != 0) {
    564     StringPtr++;
    565   }
    566   if (*StringPtr == L'\0') {
    567     return EFI_INVALID_PARAMETER;
    568   }
    569   StringPtr += StrLen (L"&PATH=");
    570   while (*StringPtr != L'\0' && *StringPtr != L'&') {
    571     StringPtr ++;
    572   }
    573   HeaderLength = StringPtr - *AltCfgResp;
    574 
    575   //
    576   // Construct AltConfigHdr string  "&<ConfigHdr>&ALTCFG=XXXX\0"
    577   //                                  |1| StrLen (ConfigHdr) | 8 | 4 | 1 |
    578   //
    579   MaxLen = 1 + HeaderLength + 8 + 4 + 1;
    580   AltConfigHdr = AllocateZeroPool (MaxLen * sizeof (CHAR16));
    581   if (AltConfigHdr == NULL) {
    582     return EFI_OUT_OF_RESOURCES;
    583   }
    584   StrCpyS (AltConfigHdr, MaxLen, L"&");
    585   StrnCatS (AltConfigHdr, MaxLen, *AltCfgResp, HeaderLength);
    586   StrCatS (AltConfigHdr, MaxLen, L"&ALTCFG=");
    587   HeaderLength = StrLen (AltConfigHdr);
    588 
    589   StringPtrDefault = StrStr (DefaultAltCfgResp, AltConfigHdr);
    590   while (StringPtrDefault != NULL) {
    591     //
    592     // Get AltCfg Name
    593     //
    594     StrnCatS (AltConfigHdr, MaxLen, StringPtrDefault + HeaderLength, 4);
    595     StringPtr = StrStr (*AltCfgResp, AltConfigHdr);
    596 
    597     //
    598     // Append the found default value string to the input AltCfgResp
    599     //
    600     if (StringPtr == NULL) {
    601       StringPtrEnd   = StrStr (StringPtrDefault + 1, L"&GUID");
    602       SizeAltCfgResp = StrSize (*AltCfgResp);
    603       TotalSize = SizeAltCfgResp + StrSize (StringPtrDefault);
    604       if (StringPtrEnd == NULL) {
    605         //
    606         // No more default string is found.
    607         //
    608         *AltCfgResp    = (EFI_STRING) ReallocatePool (
    609                                      SizeAltCfgResp,
    610                                      TotalSize,
    611                                      (VOID *) (*AltCfgResp)
    612                                      );
    613         if (*AltCfgResp == NULL) {
    614           FreePool (AltConfigHdr);
    615           return EFI_OUT_OF_RESOURCES;
    616         }
    617         StrCatS (*AltCfgResp, TotalSize / sizeof (CHAR16), StringPtrDefault);
    618         break;
    619       } else {
    620         TempChar = *StringPtrEnd;
    621         *StringPtrEnd = L'\0';
    622         *AltCfgResp = (EFI_STRING) ReallocatePool (
    623                                      SizeAltCfgResp,
    624                                      TotalSize,
    625                                      (VOID *) (*AltCfgResp)
    626                                      );
    627         if (*AltCfgResp == NULL) {
    628           FreePool (AltConfigHdr);
    629           return EFI_OUT_OF_RESOURCES;
    630         }
    631         StrCatS (*AltCfgResp, TotalSize / sizeof (CHAR16), StringPtrDefault);
    632         *StringPtrEnd = TempChar;
    633       }
    634     }
    635 
    636     //
    637     // Find next AltCfg String
    638     //
    639     *(AltConfigHdr + HeaderLength) = L'\0';
    640     StringPtrDefault = StrStr (StringPtrDefault + 1, AltConfigHdr);
    641   }
    642 
    643   FreePool (AltConfigHdr);
    644   return EFI_SUCCESS;
    645 }
    646 
    647 /**
    648   This function inserts new DefaultValueData into the BlockData DefaultValue array.
    649 
    650   @param  BlockData         The BlockData is updated to add new default value.
    651   @param  DefaultValueData  The DefaultValue is added.
    652 
    653 **/
    654 VOID
    655 InsertDefaultValue (
    656   IN IFR_BLOCK_DATA         *BlockData,
    657   IN IFR_DEFAULT_DATA       *DefaultValueData
    658   )
    659 {
    660   LIST_ENTRY             *Link;
    661   IFR_DEFAULT_DATA       *DefaultValueArray;
    662   LIST_ENTRY             *DefaultLink;
    663 
    664   DefaultLink   = &BlockData->DefaultValueEntry;
    665 
    666   for (Link = DefaultLink->ForwardLink; Link != DefaultLink; Link = Link->ForwardLink) {
    667     DefaultValueArray = BASE_CR (Link, IFR_DEFAULT_DATA, Entry);
    668     if (DefaultValueArray->DefaultId == DefaultValueData->DefaultId) {
    669       //
    670       // DEFAULT_VALUE_FROM_OPCODE has high priority, DEFAULT_VALUE_FROM_DEFAULT has low priority.
    671       //
    672       if (DefaultValueData->Type > DefaultValueArray->Type) {
    673         //
    674         // Update the default value array in BlockData.
    675         //
    676         CopyMem (&DefaultValueArray->Value, &DefaultValueData->Value, sizeof (EFI_IFR_TYPE_VALUE));
    677         DefaultValueArray->Type  = DefaultValueData->Type;
    678         DefaultValueArray->Cleaned = DefaultValueData->Cleaned;
    679       }
    680       return;
    681     }
    682   }
    683 
    684   //
    685   // Insert new default value data in tail.
    686   //
    687   DefaultValueArray = AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));
    688   ASSERT (DefaultValueArray != NULL);
    689   CopyMem (DefaultValueArray, DefaultValueData, sizeof (IFR_DEFAULT_DATA));
    690   InsertTailList (Link, &DefaultValueArray->Entry);
    691 }
    692 
    693 /**
    694   This function inserts new BlockData into the block link
    695 
    696   @param  BlockLink      The list entry points to block array.
    697   @param  BlockData      The point to BlockData is added.
    698 
    699 **/
    700 VOID
    701 InsertBlockData (
    702   IN LIST_ENTRY        *BlockLink,
    703   IN IFR_BLOCK_DATA    **BlockData
    704   )
    705 {
    706   LIST_ENTRY          *Link;
    707   IFR_BLOCK_DATA      *BlockArray;
    708   IFR_BLOCK_DATA      *BlockSingleData;
    709 
    710   BlockSingleData = *BlockData;
    711 
    712   if (BlockSingleData->Name != NULL) {
    713     InsertTailList (BlockLink, &BlockSingleData->Entry);
    714     return;
    715   }
    716 
    717   //
    718   // Insert block data in its Offset and Width order.
    719   //
    720   for (Link = BlockLink->ForwardLink; Link != BlockLink; Link = Link->ForwardLink) {
    721     BlockArray = BASE_CR (Link, IFR_BLOCK_DATA, Entry);
    722     if (BlockArray->Offset == BlockSingleData->Offset) {
    723       if (BlockArray->Width > BlockSingleData->Width) {
    724         //
    725         // Insert this block data in the front of block array
    726         //
    727         InsertTailList (Link, &BlockSingleData->Entry);
    728         return;
    729       }
    730 
    731       if (BlockArray->Width == BlockSingleData->Width) {
    732         //
    733         // The same block array has been added.
    734         //
    735         if (BlockSingleData != BlockArray) {
    736           FreePool (BlockSingleData);
    737           *BlockData = BlockArray;
    738         }
    739         return;
    740       }
    741     } else if (BlockArray->Offset > BlockSingleData->Offset) {
    742       //
    743       // Insert new block data in the front of block array
    744       //
    745       InsertTailList (Link, &BlockSingleData->Entry);
    746       return;
    747     }
    748   }
    749 
    750   //
    751   // Add new block data into the tail.
    752   //
    753   InsertTailList (Link, &BlockSingleData->Entry);
    754 }
    755 
    756 /**
    757   Retrieves a pointer to the a Null-terminated ASCII string containing the list
    758   of languages that an HII handle in the HII Database supports.  The returned
    759   string is allocated using AllocatePool().  The caller is responsible for freeing
    760   the returned string using FreePool().  The format of the returned string follows
    761   the language format assumed the HII Database.
    762 
    763   If HiiHandle is NULL, then ASSERT().
    764 
    765   @param[in]  HiiHandle  A handle that was previously registered in the HII Database.
    766 
    767   @retval NULL   HiiHandle is not registered in the HII database
    768   @retval NULL   There are not enough resources available to retrieve the suported
    769                  languages.
    770   @retval NULL   The list of suported languages could not be retrieved.
    771   @retval Other  A pointer to the Null-terminated ASCII string of supported languages.
    772 
    773 **/
    774 CHAR8 *
    775 GetSupportedLanguages (
    776   IN EFI_HII_HANDLE           HiiHandle
    777   )
    778 {
    779   EFI_STATUS  Status;
    780   UINTN       LanguageSize;
    781   CHAR8       TempSupportedLanguages;
    782   CHAR8       *SupportedLanguages;
    783 
    784   ASSERT (HiiHandle != NULL);
    785 
    786   //
    787   // Retrieve the size required for the supported languages buffer.
    788   //
    789   LanguageSize = 0;
    790   Status = mPrivate.HiiString.GetLanguages (&mPrivate.HiiString, HiiHandle, &TempSupportedLanguages, &LanguageSize);
    791 
    792   //
    793   // If GetLanguages() returns EFI_SUCCESS for a zero size,
    794   // then there are no supported languages registered for HiiHandle.  If GetLanguages()
    795   // returns an error other than EFI_BUFFER_TOO_SMALL, then HiiHandle is not present
    796   // in the HII Database
    797   //
    798   if (Status != EFI_BUFFER_TOO_SMALL) {
    799     //
    800     // Return NULL if the size can not be retrieved, or if HiiHandle is not in the HII Database
    801     //
    802     return NULL;
    803   }
    804 
    805   //
    806   // Allocate the supported languages buffer.
    807   //
    808   SupportedLanguages = AllocateZeroPool (LanguageSize);
    809   if (SupportedLanguages == NULL) {
    810     //
    811     // Return NULL if allocation fails.
    812     //
    813     return NULL;
    814   }
    815 
    816   //
    817   // Retrieve the supported languages string
    818   //
    819   Status = mPrivate.HiiString.GetLanguages (&mPrivate.HiiString, HiiHandle, SupportedLanguages, &LanguageSize);
    820   if (EFI_ERROR (Status)) {
    821     //
    822     // Free the buffer and return NULL if the supported languages can not be retrieved.
    823     //
    824     FreePool (SupportedLanguages);
    825     return NULL;
    826   }
    827 
    828   //
    829   // Return the Null-terminated ASCII string of supported languages
    830   //
    831   return SupportedLanguages;
    832 }
    833 
    834 /**
    835   Retrieves a string from a string package.
    836 
    837   If HiiHandle is NULL, then ASSERT().
    838   If StringId is 0, then ASSET.
    839 
    840   @param[in]  HiiHandle  A handle that was previously registered in the HII Database.
    841   @param[in]  StringId   The identifier of the string to retrieved from the string
    842                          package associated with HiiHandle.
    843 
    844   @retval NULL   The string specified by StringId is not present in the string package.
    845   @retval Other  The string was returned.
    846 
    847 **/
    848 EFI_STRING
    849 InternalGetString (
    850   IN EFI_HII_HANDLE  HiiHandle,
    851   IN EFI_STRING_ID   StringId
    852   )
    853 {
    854   EFI_STATUS  Status;
    855   UINTN       StringSize;
    856   CHAR16      TempString;
    857   EFI_STRING  String;
    858   CHAR8       *SupportedLanguages;
    859   CHAR8       *PlatformLanguage;
    860   CHAR8       *BestLanguage;
    861   CHAR8       *Language;
    862 
    863   ASSERT (HiiHandle != NULL);
    864   ASSERT (StringId != 0);
    865 
    866   //
    867   // Initialize all allocated buffers to NULL
    868   //
    869   SupportedLanguages = NULL;
    870   PlatformLanguage   = NULL;
    871   BestLanguage       = NULL;
    872   String             = NULL;
    873   Language           = "";
    874 
    875   //
    876   // Get the languages that the package specified by HiiHandle supports
    877   //
    878   SupportedLanguages = GetSupportedLanguages (HiiHandle);
    879   if (SupportedLanguages == NULL) {
    880     goto Error;
    881   }
    882 
    883   //
    884   // Get the current platform language setting
    885   //
    886   GetEfiGlobalVariable2 (L"PlatformLang", (VOID**)&PlatformLanguage, NULL);
    887 
    888   //
    889   // Get the best matching language from SupportedLanguages
    890   //
    891   BestLanguage = GetBestLanguage (
    892                    SupportedLanguages,
    893                    FALSE,                                             // RFC 4646 mode
    894                    Language,                                          // Highest priority
    895                    PlatformLanguage != NULL ? PlatformLanguage : "",  // Next highest priority
    896                    SupportedLanguages,                                // Lowest priority
    897                    NULL
    898                    );
    899   if (BestLanguage == NULL) {
    900     goto Error;
    901   }
    902 
    903   //
    904   // Retrieve the size of the string in the string package for the BestLanguage
    905   //
    906   StringSize = 0;
    907   Status = mPrivate.HiiString.GetString (
    908                          &mPrivate.HiiString,
    909                          BestLanguage,
    910                          HiiHandle,
    911                          StringId,
    912                          &TempString,
    913                          &StringSize,
    914                          NULL
    915                          );
    916   //
    917   // If GetString() returns EFI_SUCCESS for a zero size,
    918   // then there are no supported languages registered for HiiHandle.  If GetString()
    919   // returns an error other than EFI_BUFFER_TOO_SMALL, then HiiHandle is not present
    920   // in the HII Database
    921   //
    922   if (Status != EFI_BUFFER_TOO_SMALL) {
    923     goto Error;
    924   }
    925 
    926   //
    927   // Allocate a buffer for the return string
    928   //
    929   String = AllocateZeroPool (StringSize);
    930   if (String == NULL) {
    931     goto Error;
    932   }
    933 
    934   //
    935   // Retrieve the string from the string package
    936   //
    937   Status = mPrivate.HiiString.GetString (
    938                          &mPrivate.HiiString,
    939                          BestLanguage,
    940                          HiiHandle,
    941                          StringId,
    942                          String,
    943                          &StringSize,
    944                          NULL
    945                          );
    946   if (EFI_ERROR (Status)) {
    947     //
    948     // Free the buffer and return NULL if the supported languages can not be retrieved.
    949     //
    950     FreePool (String);
    951     String = NULL;
    952   }
    953 
    954 Error:
    955   //
    956   // Free allocated buffers
    957   //
    958   if (SupportedLanguages != NULL) {
    959     FreePool (SupportedLanguages);
    960   }
    961   if (PlatformLanguage != NULL) {
    962     FreePool (PlatformLanguage);
    963   }
    964   if (BestLanguage != NULL) {
    965     FreePool (BestLanguage);
    966   }
    967 
    968   //
    969   // Return the Null-terminated Unicode string
    970   //
    971   return String;
    972 }
    973 
    974 /**
    975   This function checks VarOffset and VarWidth is in the block range.
    976 
    977   @param  RequestBlockArray  The block array is to be checked.
    978   @param  VarOffset          Offset of var to the structure
    979   @param  VarWidth           Width of var.
    980   @param  IsNameValueType    Whether this varstore is name/value varstore or not.
    981   @param  HiiHandle          Hii handle for this hii package.
    982 
    983   @retval TRUE   This Var is in the block range.
    984   @retval FALSE  This Var is not in the block range.
    985 **/
    986 BOOLEAN
    987 BlockArrayCheck (
    988   IN IFR_BLOCK_DATA  *RequestBlockArray,
    989   IN UINT16          VarOffset,
    990   IN UINT16          VarWidth,
    991   IN BOOLEAN         IsNameValueType,
    992   IN EFI_HII_HANDLE  HiiHandle
    993   )
    994 {
    995   LIST_ENTRY          *Link;
    996   IFR_BLOCK_DATA      *BlockData;
    997   EFI_STRING          Name;
    998 
    999   //
   1000   // No Request Block array, all vars are got.
   1001   //
   1002   if (RequestBlockArray == NULL) {
   1003     return TRUE;
   1004   }
   1005 
   1006   //
   1007   // Check the input var is in the request block range.
   1008   //
   1009   for (Link = RequestBlockArray->Entry.ForwardLink; Link != &RequestBlockArray->Entry; Link = Link->ForwardLink) {
   1010     BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);
   1011 
   1012     if (IsNameValueType) {
   1013       Name = InternalGetString (HiiHandle, VarOffset);
   1014       ASSERT (Name != NULL);
   1015 
   1016       if (StrnCmp (BlockData->Name, Name, StrLen (Name)) == 0) {
   1017         FreePool (Name);
   1018         return TRUE;
   1019       }
   1020       FreePool (Name);
   1021     } else {
   1022       if ((VarOffset >= BlockData->Offset) && ((VarOffset + VarWidth) <= (BlockData->Offset + BlockData->Width))) {
   1023         return TRUE;
   1024       }
   1025     }
   1026   }
   1027 
   1028   return FALSE;
   1029 }
   1030 
   1031 /**
   1032   Get form package data from data base.
   1033 
   1034   @param  DataBaseRecord         The DataBaseRecord instance contains the found Hii handle and package.
   1035   @param  HiiFormPackage         The buffer saves the package data.
   1036   @param  PackageSize            The buffer size of the package data.
   1037 
   1038 **/
   1039 EFI_STATUS
   1040 GetFormPackageData (
   1041   IN     HII_DATABASE_RECORD        *DataBaseRecord,
   1042   IN OUT UINT8                      **HiiFormPackage,
   1043   OUT    UINTN                      *PackageSize
   1044   )
   1045 {
   1046   EFI_STATUS                   Status;
   1047   UINTN                        Size;
   1048   UINTN                        ResultSize;
   1049 
   1050   if (DataBaseRecord == NULL || HiiFormPackage == NULL || PackageSize == NULL) {
   1051     return EFI_INVALID_PARAMETER;
   1052   }
   1053 
   1054   Size       = 0;
   1055   ResultSize = 0;
   1056   //
   1057   // 0. Get Hii Form Package by HiiHandle
   1058   //
   1059   Status = ExportFormPackages (
   1060              &mPrivate,
   1061              DataBaseRecord->Handle,
   1062              DataBaseRecord->PackageList,
   1063              0,
   1064              Size,
   1065              HiiFormPackage,
   1066              &ResultSize
   1067            );
   1068   if (EFI_ERROR (Status)) {
   1069     return Status;
   1070   }
   1071 
   1072   (*HiiFormPackage) = AllocatePool (ResultSize);
   1073   if (*HiiFormPackage == NULL) {
   1074     Status = EFI_OUT_OF_RESOURCES;
   1075     return Status;
   1076   }
   1077 
   1078   //
   1079   // Get HiiFormPackage by HiiHandle
   1080   //
   1081   Size   = ResultSize;
   1082   ResultSize    = 0;
   1083   Status = ExportFormPackages (
   1084              &mPrivate,
   1085              DataBaseRecord->Handle,
   1086              DataBaseRecord->PackageList,
   1087              0,
   1088              Size,
   1089              *HiiFormPackage,
   1090              &ResultSize
   1091            );
   1092   if (EFI_ERROR (Status)) {
   1093     FreePool (*HiiFormPackage);
   1094   }
   1095 
   1096   *PackageSize = Size;
   1097 
   1098   return Status;
   1099 }
   1100 
   1101 
   1102 /**
   1103   This function parses Form Package to get the efi varstore info according to the request ConfigHdr.
   1104 
   1105   @param  DataBaseRecord        The DataBaseRecord instance contains the found Hii handle and package.
   1106   @param  ConfigHdr             Request string ConfigHdr. If it is NULL,
   1107                                 the first found varstore will be as ConfigHdr.
   1108   @param  IsEfiVarstore         Whether the request storage type is efi varstore type.
   1109   @param  EfiVarStore           The efi varstore info which will return.
   1110 **/
   1111 EFI_STATUS
   1112 GetVarStoreType (
   1113   IN     HII_DATABASE_RECORD        *DataBaseRecord,
   1114   IN     EFI_STRING                 ConfigHdr,
   1115   OUT    BOOLEAN                    *IsEfiVarstore,
   1116   OUT    EFI_IFR_VARSTORE_EFI       **EfiVarStore
   1117   )
   1118 {
   1119   EFI_STATUS               Status;
   1120   UINTN                    IfrOffset;
   1121   UINTN                    PackageOffset;
   1122   EFI_IFR_OP_HEADER        *IfrOpHdr;
   1123   CHAR16                   *VarStoreName;
   1124   EFI_STRING               GuidStr;
   1125   EFI_STRING               NameStr;
   1126   EFI_STRING               TempStr;
   1127   UINTN                    LengthString;
   1128   UINT8                    *HiiFormPackage;
   1129   UINTN                    PackageSize;
   1130   EFI_IFR_VARSTORE_EFI     *IfrEfiVarStore;
   1131   EFI_HII_PACKAGE_HEADER   *PackageHeader;
   1132 
   1133   HiiFormPackage = NULL;
   1134   LengthString     = 0;
   1135   Status           = EFI_SUCCESS;
   1136   GuidStr          = NULL;
   1137   NameStr          = NULL;
   1138   TempStr          = NULL;
   1139   *IsEfiVarstore   = FALSE;
   1140 
   1141   Status = GetFormPackageData(DataBaseRecord, &HiiFormPackage, &PackageSize);
   1142   if (EFI_ERROR (Status)) {
   1143     return Status;
   1144   }
   1145 
   1146   IfrOffset     = sizeof (EFI_HII_PACKAGE_HEADER);
   1147   PackageOffset = IfrOffset;
   1148   PackageHeader = (EFI_HII_PACKAGE_HEADER *) HiiFormPackage;
   1149 
   1150   while (IfrOffset < PackageSize) {
   1151     //
   1152     // More than one form packages exist.
   1153     //
   1154     if (PackageOffset >= PackageHeader->Length) {
   1155         //
   1156         // Process the new form package.
   1157         //
   1158         PackageOffset = sizeof (EFI_HII_PACKAGE_HEADER);
   1159         IfrOffset    += PackageOffset;
   1160         PackageHeader = (EFI_HII_PACKAGE_HEADER *) (HiiFormPackage + IfrOffset);
   1161     }
   1162 
   1163     IfrOpHdr  = (EFI_IFR_OP_HEADER *) (HiiFormPackage + IfrOffset);
   1164     IfrOffset += IfrOpHdr->Length;
   1165     PackageOffset += IfrOpHdr->Length;
   1166 
   1167     if (IfrOpHdr->OpCode == EFI_IFR_VARSTORE_EFI_OP ) {
   1168       IfrEfiVarStore = (EFI_IFR_VARSTORE_EFI *) IfrOpHdr;
   1169       //
   1170       // If the length is small than the structure, this is from old efi
   1171       // varstore definition. Old efi varstore get config directly from
   1172       // GetVariable function.
   1173       //
   1174       if (IfrOpHdr->Length < sizeof (EFI_IFR_VARSTORE_EFI)) {
   1175         continue;
   1176       }
   1177 
   1178       VarStoreName = AllocateZeroPool (AsciiStrSize ((CHAR8 *)IfrEfiVarStore->Name) * sizeof (CHAR16));
   1179       if (VarStoreName == NULL) {
   1180         Status = EFI_OUT_OF_RESOURCES;
   1181         goto Done;
   1182       }
   1183       AsciiStrToUnicodeStr ((CHAR8 *) IfrEfiVarStore->Name, VarStoreName);
   1184 
   1185       GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (VOID *) &IfrEfiVarStore->Guid, 1, &GuidStr);
   1186       GenerateSubStr (L"NAME=", StrLen (VarStoreName) * sizeof (CHAR16), (VOID *) VarStoreName, 2, &NameStr);
   1187       LengthString = StrLen (GuidStr);
   1188       LengthString = LengthString + StrLen (NameStr) + 1;
   1189       TempStr = AllocateZeroPool (LengthString * sizeof (CHAR16));
   1190       if (TempStr == NULL) {
   1191         FreePool (GuidStr);
   1192         FreePool (NameStr);
   1193         FreePool (VarStoreName);
   1194         Status = EFI_OUT_OF_RESOURCES;
   1195         goto Done;
   1196       }
   1197       StrCpyS (TempStr, LengthString, GuidStr);
   1198       StrCatS (TempStr, LengthString, NameStr);
   1199       if (ConfigHdr == NULL || StrnCmp (ConfigHdr, TempStr, StrLen (TempStr)) == 0) {
   1200         *EfiVarStore = (EFI_IFR_VARSTORE_EFI *) AllocateZeroPool (IfrOpHdr->Length);
   1201         if (*EfiVarStore == NULL) {
   1202           FreePool (VarStoreName);
   1203           FreePool (GuidStr);
   1204           FreePool (NameStr);
   1205           FreePool (TempStr);
   1206           Status = EFI_OUT_OF_RESOURCES;
   1207           goto Done;
   1208         }
   1209         *IsEfiVarstore = TRUE;
   1210         CopyMem (*EfiVarStore, IfrEfiVarStore, IfrOpHdr->Length);
   1211       }
   1212 
   1213       //
   1214       // Free alllocated temp string.
   1215       //
   1216       FreePool (VarStoreName);
   1217       FreePool (GuidStr);
   1218       FreePool (NameStr);
   1219       FreePool (TempStr);
   1220 
   1221       //
   1222       // Already found the varstore, break;
   1223       //
   1224       if (*IsEfiVarstore) {
   1225         break;
   1226       }
   1227     }
   1228   }
   1229 Done:
   1230   if (HiiFormPackage != NULL) {
   1231     FreePool (HiiFormPackage);
   1232   }
   1233 
   1234   return Status;
   1235 }
   1236 
   1237 /**
   1238   Check whether the ConfigRequest string has the request elements.
   1239   For EFI_HII_VARSTORE_BUFFER type, the request has "&OFFSET=****&WIDTH=****..." format.
   1240   For EFI_HII_VARSTORE_NAME_VALUE type, the request has "&NAME1**&NAME2..." format.
   1241 
   1242   @param  ConfigRequest      The input config request string.
   1243 
   1244   @retval  TRUE              The input include config request elements.
   1245   @retval  FALSE             The input string not includes.
   1246 
   1247 **/
   1248 BOOLEAN
   1249 GetElementsFromRequest (
   1250   IN EFI_STRING    ConfigRequest
   1251   )
   1252 {
   1253   EFI_STRING   TmpRequest;
   1254 
   1255   TmpRequest = StrStr (ConfigRequest, L"PATH=");
   1256   ASSERT (TmpRequest != NULL);
   1257 
   1258   if ((StrStr (TmpRequest, L"&OFFSET=") != NULL) || (StrStr (TmpRequest, L"&") != NULL)) {
   1259     return TRUE;
   1260   }
   1261 
   1262   return FALSE;
   1263 }
   1264 
   1265 /**
   1266   Check whether the this varstore is the request varstore.
   1267 
   1268   @param  VarstoreGuid      Varstore guid.
   1269   @param  Name              Varstore name.
   1270   @param  ConfigHdr         Current configRequest info.
   1271 
   1272   @retval  TRUE              This varstore is the requst one.
   1273   @retval  FALSE             This varstore is not the requst one.
   1274 
   1275 **/
   1276 BOOLEAN
   1277 IsThisVarstore (
   1278   IN EFI_GUID    *VarstoreGuid,
   1279   IN CHAR16      *Name,
   1280   IN CHAR16      *ConfigHdr
   1281   )
   1282 {
   1283   EFI_STRING               GuidStr;
   1284   EFI_STRING               NameStr;
   1285   EFI_STRING               TempStr;
   1286   UINTN                    LengthString;
   1287   BOOLEAN                  RetVal;
   1288 
   1289   RetVal       = FALSE;
   1290   GuidStr      = NULL;
   1291   TempStr      = NULL;
   1292 
   1293   //
   1294   // If ConfigHdr has name field and varstore not has name, return FALSE.
   1295   //
   1296   if (Name == NULL && ConfigHdr != NULL && StrStr (ConfigHdr, L"NAME=&") == NULL) {
   1297     return FALSE;
   1298   }
   1299 
   1300   GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (VOID *)VarstoreGuid, 1, &GuidStr);
   1301   if (Name != NULL) {
   1302     GenerateSubStr (L"NAME=", StrLen (Name) * sizeof (CHAR16), (VOID *) Name, 2, &NameStr);
   1303   } else {
   1304     GenerateSubStr (L"NAME=", 0, NULL, 2, &NameStr);
   1305   }
   1306   LengthString = StrLen (GuidStr);
   1307   LengthString = LengthString + StrLen (NameStr) + 1;
   1308   TempStr = AllocateZeroPool (LengthString * sizeof (CHAR16));
   1309   if (TempStr == NULL) {
   1310     goto Done;
   1311   }
   1312 
   1313   StrCpyS (TempStr, LengthString, GuidStr);
   1314   StrCatS (TempStr, LengthString, NameStr);
   1315 
   1316   if (ConfigHdr == NULL || StrnCmp (ConfigHdr, TempStr, StrLen (TempStr)) == 0) {
   1317     RetVal = TRUE;
   1318   }
   1319 
   1320 Done:
   1321   if (GuidStr != NULL) {
   1322     FreePool (GuidStr);
   1323   }
   1324 
   1325   if (NameStr != NULL) {
   1326     FreePool (NameStr);
   1327   }
   1328 
   1329   if (TempStr != NULL) {
   1330     FreePool (TempStr);
   1331   }
   1332 
   1333   return RetVal;
   1334 }
   1335 
   1336 /**
   1337   This function parses Form Package to get the efi varstore info according to the request ConfigHdr.
   1338 
   1339   @param  DataBaseRecord        The DataBaseRecord instance contains the found Hii handle and package.
   1340   @param  ConfigHdr             Request string ConfigHdr. If it is NULL,
   1341                                 the first found varstore will be as ConfigHdr.
   1342   @retval  TRUE                 This hii package is the reqeust one.
   1343   @retval  FALSE                This hii package is not the reqeust one.
   1344 **/
   1345 BOOLEAN
   1346 IsThisPackageList (
   1347   IN     HII_DATABASE_RECORD        *DataBaseRecord,
   1348   IN     EFI_STRING                 ConfigHdr
   1349   )
   1350 {
   1351   EFI_STATUS               Status;
   1352   UINTN                    IfrOffset;
   1353   UINTN                    PackageOffset;
   1354   EFI_IFR_OP_HEADER        *IfrOpHdr;
   1355   CHAR16                   *VarStoreName;
   1356   UINT8                    *HiiFormPackage;
   1357   UINTN                    PackageSize;
   1358   EFI_IFR_VARSTORE_EFI     *IfrEfiVarStore;
   1359   EFI_HII_PACKAGE_HEADER   *PackageHeader;
   1360   EFI_IFR_VARSTORE         *IfrVarStore;
   1361   EFI_IFR_VARSTORE_NAME_VALUE *IfrNameValueVarStore;
   1362   BOOLEAN                  FindVarstore;
   1363 
   1364   HiiFormPackage   = NULL;
   1365   VarStoreName     = NULL;
   1366   Status           = EFI_SUCCESS;
   1367   FindVarstore     = FALSE;
   1368 
   1369   Status = GetFormPackageData(DataBaseRecord, &HiiFormPackage, &PackageSize);
   1370   if (EFI_ERROR (Status)) {
   1371     return FALSE;
   1372   }
   1373 
   1374   IfrOffset     = sizeof (EFI_HII_PACKAGE_HEADER);
   1375   PackageOffset = IfrOffset;
   1376   PackageHeader = (EFI_HII_PACKAGE_HEADER *) HiiFormPackage;
   1377 
   1378   while (IfrOffset < PackageSize) {
   1379     //
   1380     // More than one form packages exist.
   1381     //
   1382     if (PackageOffset >= PackageHeader->Length) {
   1383         //
   1384         // Process the new form package.
   1385         //
   1386         PackageOffset = sizeof (EFI_HII_PACKAGE_HEADER);
   1387         IfrOffset    += PackageOffset;
   1388         PackageHeader = (EFI_HII_PACKAGE_HEADER *) (HiiFormPackage + IfrOffset);
   1389     }
   1390 
   1391     IfrOpHdr  = (EFI_IFR_OP_HEADER *) (HiiFormPackage + IfrOffset);
   1392     IfrOffset += IfrOpHdr->Length;
   1393     PackageOffset += IfrOpHdr->Length;
   1394 
   1395     switch (IfrOpHdr->OpCode) {
   1396 
   1397     case EFI_IFR_VARSTORE_OP:
   1398       IfrVarStore = (EFI_IFR_VARSTORE *) IfrOpHdr;
   1399 
   1400       VarStoreName = AllocateZeroPool (AsciiStrSize ((CHAR8 *)IfrVarStore->Name) * sizeof (CHAR16));
   1401       if (VarStoreName == NULL) {
   1402         goto Done;
   1403       }
   1404       AsciiStrToUnicodeStr ((CHAR8 *)IfrVarStore->Name, VarStoreName);
   1405 
   1406       if (IsThisVarstore((VOID *)&IfrVarStore->Guid, VarStoreName, ConfigHdr)) {
   1407         FindVarstore = TRUE;
   1408         goto Done;
   1409       }
   1410       break;
   1411 
   1412     case EFI_IFR_VARSTORE_EFI_OP:
   1413       IfrEfiVarStore = (EFI_IFR_VARSTORE_EFI *) IfrOpHdr;
   1414       VarStoreName = AllocateZeroPool (AsciiStrSize ((CHAR8 *)IfrEfiVarStore->Name) * sizeof (CHAR16));
   1415       if (VarStoreName == NULL) {
   1416         goto Done;
   1417       }
   1418       AsciiStrToUnicodeStr ((CHAR8 *)IfrEfiVarStore->Name, VarStoreName);
   1419 
   1420       if (IsThisVarstore (&IfrEfiVarStore->Guid, VarStoreName, ConfigHdr)) {
   1421         FindVarstore = TRUE;
   1422         goto Done;
   1423       }
   1424       break;
   1425 
   1426     case EFI_IFR_VARSTORE_NAME_VALUE_OP:
   1427       IfrNameValueVarStore = (EFI_IFR_VARSTORE_NAME_VALUE *) IfrOpHdr;
   1428 
   1429       if (IsThisVarstore (&IfrNameValueVarStore->Guid, NULL, ConfigHdr)) {
   1430         FindVarstore = TRUE;
   1431         goto Done;
   1432       }
   1433       break;
   1434 
   1435     case EFI_IFR_FORM_OP:
   1436     case EFI_IFR_FORM_MAP_OP:
   1437       //
   1438       // No matched varstore is found and directly return.
   1439       //
   1440       goto Done;
   1441 
   1442     default:
   1443       break;
   1444     }
   1445   }
   1446 Done:
   1447   if (HiiFormPackage != NULL) {
   1448     FreePool (HiiFormPackage);
   1449   }
   1450 
   1451   if (VarStoreName != NULL) {
   1452     FreePool (VarStoreName);
   1453   }
   1454 
   1455   return FindVarstore;
   1456 }
   1457 
   1458 /**
   1459   Check whether the this op code is required.
   1460 
   1461   @param  RequestBlockArray      The array includes all the request info or NULL.
   1462   @param  HiiHandle              The hii handle for this form package.
   1463   @param  VarStorageData         The varstore data strucure.
   1464   @param  IfrOpHdr               Ifr opcode header for this opcode.
   1465   @param  VarWidth               The buffer width for this opcode.
   1466   @param  ReturnData             The data block added for this opcode.
   1467 
   1468   @retval  EFI_SUCCESS           This opcode is required.
   1469   @retval  Others                This opcode is not required or error occur.
   1470 
   1471 **/
   1472 EFI_STATUS
   1473 IsThisOpcodeRequired (
   1474   IN     IFR_BLOCK_DATA           *RequestBlockArray,
   1475   IN     EFI_HII_HANDLE           HiiHandle,
   1476   IN OUT IFR_VARSTORAGE_DATA      *VarStorageData,
   1477   IN     EFI_IFR_OP_HEADER        *IfrOpHdr,
   1478   IN     UINT16                   VarWidth,
   1479   OUT    IFR_BLOCK_DATA           **ReturnData
   1480   )
   1481 {
   1482   IFR_BLOCK_DATA           *BlockData;
   1483   UINT16                   VarOffset;
   1484   EFI_STRING_ID            NameId;
   1485   EFI_IFR_QUESTION_HEADER  *IfrQuestionHdr;
   1486 
   1487   NameId    = 0;
   1488   VarOffset = 0;
   1489   IfrQuestionHdr = (EFI_IFR_QUESTION_HEADER  *)((CHAR8 *) IfrOpHdr + sizeof (EFI_IFR_OP_HEADER));
   1490 
   1491   if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {
   1492     NameId = IfrQuestionHdr->VarStoreInfo.VarName;
   1493 
   1494     //
   1495     // Check whether this question is in requested block array.
   1496     //
   1497     if (!BlockArrayCheck (RequestBlockArray, NameId, 0, TRUE, HiiHandle)) {
   1498       //
   1499       // This question is not in the requested string. Skip it.
   1500       //
   1501       return EFI_SUCCESS;
   1502     }
   1503   } else {
   1504     VarOffset = IfrQuestionHdr->VarStoreInfo.VarOffset;
   1505 
   1506     //
   1507     // Check whether this question is in requested block array.
   1508     //
   1509     if (!BlockArrayCheck (RequestBlockArray, VarOffset, VarWidth, FALSE, HiiHandle)) {
   1510       //
   1511       // This question is not in the requested string. Skip it.
   1512       //
   1513       return EFI_SUCCESS;
   1514     }
   1515 
   1516     //
   1517     // Check this var question is in the var storage
   1518     //
   1519     if (((VarOffset + VarWidth) > VarStorageData->Size)) {
   1520       return EFI_INVALID_PARAMETER;
   1521     }
   1522   }
   1523 
   1524   BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));
   1525   if (BlockData == NULL) {
   1526     return EFI_OUT_OF_RESOURCES;
   1527   }
   1528 
   1529   if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {
   1530     BlockData->Name   = InternalGetString(HiiHandle, NameId);
   1531   } else {
   1532     BlockData->Offset = VarOffset;
   1533   }
   1534 
   1535   BlockData->Width      = VarWidth;
   1536   BlockData->QuestionId = IfrQuestionHdr->QuestionId;
   1537   BlockData->OpCode     = IfrOpHdr->OpCode;
   1538   BlockData->Scope      = IfrOpHdr->Scope;
   1539   InitializeListHead (&BlockData->DefaultValueEntry);
   1540   //
   1541   // Add Block Data into VarStorageData BlockEntry
   1542   //
   1543   InsertBlockData (&VarStorageData->BlockEntry, &BlockData);
   1544   *ReturnData = BlockData;
   1545 
   1546   return EFI_SUCCESS;
   1547 }
   1548 
   1549 /**
   1550   This function parses Form Package to get the block array and the default
   1551   value array according to the request ConfigHdr.
   1552 
   1553   @param  HiiHandle             Hii Handle for this hii package.
   1554   @param  Package               Pointer to the form package data.
   1555   @param  PackageLength         Length of the pacakge.
   1556   @param  ConfigHdr             Request string ConfigHdr. If it is NULL,
   1557                                 the first found varstore will be as ConfigHdr.
   1558   @param  RequestBlockArray     The block array is retrieved from the request string.
   1559   @param  VarStorageData        VarStorage structure contains the got block and default value.
   1560   @param  DefaultIdArray        Point to the got default id and default name array.
   1561 
   1562   @retval EFI_SUCCESS           The block array and the default value array are got.
   1563   @retval EFI_INVALID_PARAMETER The varstore defintion in the differnt form pacakges
   1564                                 are conflicted.
   1565   @retval EFI_OUT_OF_RESOURCES  No enough memory.
   1566 **/
   1567 EFI_STATUS
   1568 EFIAPI
   1569 ParseIfrData (
   1570   IN     EFI_HII_HANDLE      HiiHandle,
   1571   IN     UINT8               *Package,
   1572   IN     UINT32              PackageLength,
   1573   IN     EFI_STRING          ConfigHdr,
   1574   IN     IFR_BLOCK_DATA      *RequestBlockArray,
   1575   IN OUT IFR_VARSTORAGE_DATA *VarStorageData,
   1576   OUT    IFR_DEFAULT_DATA    *DefaultIdArray
   1577   )
   1578 {
   1579   EFI_STATUS               Status;
   1580   UINTN                    IfrOffset;
   1581   UINTN                    PackageOffset;
   1582   EFI_IFR_VARSTORE         *IfrVarStore;
   1583   EFI_IFR_VARSTORE_EFI     *IfrEfiVarStore;
   1584   EFI_IFR_OP_HEADER        *IfrOpHdr;
   1585   EFI_IFR_ONE_OF           *IfrOneOf;
   1586   EFI_IFR_REF4             *IfrRef;
   1587   EFI_IFR_ONE_OF_OPTION    *IfrOneOfOption;
   1588   EFI_IFR_DEFAULT          *IfrDefault;
   1589   EFI_IFR_ORDERED_LIST     *IfrOrderedList;
   1590   EFI_IFR_CHECKBOX         *IfrCheckBox;
   1591   EFI_IFR_PASSWORD         *IfrPassword;
   1592   EFI_IFR_STRING           *IfrString;
   1593   EFI_IFR_DATE             *IfrDate;
   1594   EFI_IFR_TIME             *IfrTime;
   1595   IFR_DEFAULT_DATA         DefaultData;
   1596   IFR_DEFAULT_DATA         *DefaultDataPtr;
   1597   IFR_BLOCK_DATA           *BlockData;
   1598   CHAR16                   *VarStoreName;
   1599   UINT16                   VarWidth;
   1600   UINT16                   VarDefaultId;
   1601   BOOLEAN                  FirstOneOfOption;
   1602   BOOLEAN                  FirstOrderedList;
   1603   LIST_ENTRY               *LinkData;
   1604   LIST_ENTRY               *LinkDefault;
   1605   EFI_IFR_VARSTORE_NAME_VALUE *IfrNameValueVarStore;
   1606   EFI_HII_PACKAGE_HEADER   *PackageHeader;
   1607   EFI_VARSTORE_ID          VarStoreId;
   1608 
   1609   Status           = EFI_SUCCESS;
   1610   BlockData        = NULL;
   1611   DefaultDataPtr   = NULL;
   1612   FirstOneOfOption = FALSE;
   1613   VarStoreId       = 0;
   1614   FirstOrderedList = FALSE;
   1615   ZeroMem (&DefaultData, sizeof (IFR_DEFAULT_DATA));
   1616 
   1617   //
   1618   // Go through the form package to parse OpCode one by one.
   1619   //
   1620   PackageOffset = sizeof (EFI_HII_PACKAGE_HEADER);
   1621   PackageHeader = (EFI_HII_PACKAGE_HEADER *) Package;
   1622   IfrOffset     = PackageOffset;
   1623   while (IfrOffset < PackageLength) {
   1624 
   1625     //
   1626     // More than one form package found.
   1627     //
   1628     if (PackageOffset >= PackageHeader->Length) {
   1629         //
   1630         // Already found varstore for this request, break;
   1631         //
   1632         if (VarStoreId != 0) {
   1633           VarStoreId = 0;
   1634         }
   1635 
   1636         //
   1637         // Get next package header info.
   1638         //
   1639         IfrOffset    += sizeof (EFI_HII_PACKAGE_HEADER);
   1640         PackageOffset = sizeof (EFI_HII_PACKAGE_HEADER);
   1641         PackageHeader = (EFI_HII_PACKAGE_HEADER *) (Package + IfrOffset);
   1642     }
   1643 
   1644     IfrOpHdr  = (EFI_IFR_OP_HEADER *) (Package + IfrOffset);
   1645     switch (IfrOpHdr->OpCode) {
   1646     case EFI_IFR_VARSTORE_OP:
   1647       //
   1648       // VarStore is found. Don't need to search any more.
   1649       //
   1650       if (VarStoreId != 0) {
   1651         break;
   1652       }
   1653 
   1654       IfrVarStore = (EFI_IFR_VARSTORE *) IfrOpHdr;
   1655 
   1656       VarStoreName = AllocateZeroPool (AsciiStrSize ((CHAR8 *)IfrVarStore->Name) * sizeof (CHAR16));
   1657       if (VarStoreName == NULL) {
   1658         Status = EFI_OUT_OF_RESOURCES;
   1659         goto Done;
   1660       }
   1661       AsciiStrToUnicodeStr ((CHAR8 *)IfrVarStore->Name, VarStoreName);
   1662 
   1663       if (IsThisVarstore((VOID *)&IfrVarStore->Guid, VarStoreName, ConfigHdr)) {
   1664         //
   1665         // Find the matched VarStore
   1666         //
   1667         CopyGuid (&VarStorageData->Guid, (EFI_GUID *) (VOID *) &IfrVarStore->Guid);
   1668         VarStorageData->Size       = IfrVarStore->Size;
   1669         VarStorageData->Name       = VarStoreName;
   1670         VarStorageData->Type       = EFI_HII_VARSTORE_BUFFER;
   1671         VarStoreId                 = IfrVarStore->VarStoreId;
   1672       }
   1673       break;
   1674 
   1675     case EFI_IFR_VARSTORE_EFI_OP:
   1676       //
   1677       // VarStore is found. Don't need to search any more.
   1678       //
   1679       if (VarStoreId != 0) {
   1680         break;
   1681       }
   1682 
   1683       IfrEfiVarStore = (EFI_IFR_VARSTORE_EFI *) IfrOpHdr;
   1684 
   1685       //
   1686       // If the length is small than the structure, this is from old efi
   1687       // varstore definition. Old efi varstore get config directly from
   1688       // GetVariable function.
   1689       //
   1690       if (IfrOpHdr->Length < sizeof (EFI_IFR_VARSTORE_EFI)) {
   1691         break;
   1692       }
   1693 
   1694       VarStoreName = AllocateZeroPool (AsciiStrSize ((CHAR8 *)IfrEfiVarStore->Name) * sizeof (CHAR16));
   1695       if (VarStoreName == NULL) {
   1696         Status = EFI_OUT_OF_RESOURCES;
   1697         goto Done;
   1698       }
   1699       AsciiStrToUnicodeStr ((CHAR8 *)IfrEfiVarStore->Name, VarStoreName);
   1700 
   1701       if (IsThisVarstore (&IfrEfiVarStore->Guid, VarStoreName, ConfigHdr)) {
   1702         //
   1703         // Find the matched VarStore
   1704         //
   1705         CopyGuid (&VarStorageData->Guid, (EFI_GUID *) (VOID *) &IfrEfiVarStore->Guid);
   1706         VarStorageData->Size       = IfrEfiVarStore->Size;
   1707         VarStorageData->Name       = VarStoreName;
   1708         VarStorageData->Type       = EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER;
   1709         VarStoreId                 = IfrEfiVarStore->VarStoreId;
   1710       }
   1711       break;
   1712 
   1713     case EFI_IFR_VARSTORE_NAME_VALUE_OP:
   1714       //
   1715       // VarStore is found. Don't need to search any more.
   1716       //
   1717       if (VarStoreId != 0) {
   1718         break;
   1719       }
   1720 
   1721       IfrNameValueVarStore = (EFI_IFR_VARSTORE_NAME_VALUE *) IfrOpHdr;
   1722 
   1723       if (IsThisVarstore (&IfrNameValueVarStore->Guid, NULL, ConfigHdr)) {
   1724         //
   1725         // Find the matched VarStore
   1726         //
   1727         CopyGuid (&VarStorageData->Guid, (EFI_GUID *) (VOID *) &IfrNameValueVarStore->Guid);
   1728         VarStorageData->Type       = EFI_HII_VARSTORE_NAME_VALUE;
   1729         VarStoreId                 = IfrNameValueVarStore->VarStoreId;
   1730       }
   1731       break;
   1732 
   1733     case EFI_IFR_DEFAULTSTORE_OP:
   1734       //
   1735       // Add new the map between default id and default name.
   1736       //
   1737       DefaultDataPtr = (IFR_DEFAULT_DATA *) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));
   1738       if (DefaultDataPtr == NULL) {
   1739         Status = EFI_OUT_OF_RESOURCES;
   1740         goto Done;
   1741       }
   1742       DefaultDataPtr->DefaultId   = ((EFI_IFR_DEFAULTSTORE *) IfrOpHdr)->DefaultId;
   1743       InsertTailList (&DefaultIdArray->Entry, &DefaultDataPtr->Entry);
   1744       DefaultDataPtr = NULL;
   1745       break;
   1746 
   1747     case EFI_IFR_FORM_OP:
   1748     case EFI_IFR_FORM_MAP_OP:
   1749       //
   1750       // No matched varstore is found and directly return.
   1751       //
   1752       if ( VarStoreId == 0) {
   1753         Status = EFI_SUCCESS;
   1754         goto Done;
   1755       }
   1756       break;
   1757 
   1758     case EFI_IFR_REF_OP:
   1759       //
   1760       // Ref question is not in IFR Form. This IFR form is not valid.
   1761       //
   1762       if ( VarStoreId == 0) {
   1763         Status = EFI_INVALID_PARAMETER;
   1764         goto Done;
   1765       }
   1766       //
   1767       // Check whether this question is for the requested varstore.
   1768       //
   1769       IfrRef = (EFI_IFR_REF4 *) IfrOpHdr;
   1770       if (IfrRef->Question.VarStoreId != VarStoreId) {
   1771         break;
   1772       }
   1773       VarWidth  = (UINT16) (sizeof (EFI_HII_REF));
   1774 
   1775       Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);
   1776       if (EFI_ERROR (Status)) {
   1777         goto Done;
   1778       }
   1779       break;
   1780 
   1781     case EFI_IFR_ONE_OF_OP:
   1782     case EFI_IFR_NUMERIC_OP:
   1783       //
   1784       // Numeric and OneOf has the same opcode structure.
   1785       //
   1786 
   1787       //
   1788       // Numeric and OneOf question is not in IFR Form. This IFR form is not valid.
   1789       //
   1790       if (VarStoreId == 0) {
   1791         Status = EFI_INVALID_PARAMETER;
   1792         goto Done;
   1793       }
   1794       //
   1795       // Check whether this question is for the requested varstore.
   1796       //
   1797       IfrOneOf = (EFI_IFR_ONE_OF *) IfrOpHdr;
   1798       if (IfrOneOf->Question.VarStoreId != VarStoreId) {
   1799         break;
   1800       }
   1801       VarWidth  = (UINT16) (1 << (IfrOneOf->Flags & EFI_IFR_NUMERIC_SIZE));
   1802 
   1803       Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);
   1804       if (EFI_ERROR (Status)) {
   1805         goto Done;
   1806       }
   1807 
   1808       if (BlockData == NULL) {
   1809         //
   1810         // BlockData == NULL means this opcode is not in the requst array.
   1811         //
   1812         break;
   1813       }
   1814 
   1815       if (IfrOpHdr->OpCode == EFI_IFR_ONE_OF_OP) {
   1816         //
   1817         // Set this flag to TRUE for the first oneof option.
   1818         //
   1819         FirstOneOfOption = TRUE;
   1820       } else if (IfrOpHdr->OpCode == EFI_IFR_NUMERIC_OP) {
   1821         //
   1822         // Numeric minimum value will be used as default value when no default is specified.
   1823         //
   1824         DefaultData.Type        = DefaultValueFromDefault;
   1825         switch (IfrOneOf->Flags & EFI_IFR_NUMERIC_SIZE) {
   1826         case EFI_IFR_NUMERIC_SIZE_1:
   1827           DefaultData.Value.u8 = IfrOneOf->data.u8.MinValue;
   1828           break;
   1829 
   1830         case EFI_IFR_NUMERIC_SIZE_2:
   1831           CopyMem (&DefaultData.Value.u16, &IfrOneOf->data.u16.MinValue, sizeof (UINT16));
   1832           break;
   1833 
   1834         case EFI_IFR_NUMERIC_SIZE_4:
   1835           CopyMem (&DefaultData.Value.u32, &IfrOneOf->data.u32.MinValue, sizeof (UINT32));
   1836           break;
   1837 
   1838         case EFI_IFR_NUMERIC_SIZE_8:
   1839           CopyMem (&DefaultData.Value.u64, &IfrOneOf->data.u64.MinValue, sizeof (UINT64));
   1840           break;
   1841 
   1842         default:
   1843           Status = EFI_INVALID_PARAMETER;
   1844           goto Done;
   1845         }
   1846         //
   1847         // Set default value base on the DefaultId list get from IFR data.
   1848         //
   1849         for (LinkData = DefaultIdArray->Entry.ForwardLink; LinkData != &DefaultIdArray->Entry; LinkData = LinkData->ForwardLink) {
   1850           DefaultDataPtr = BASE_CR (LinkData, IFR_DEFAULT_DATA, Entry);
   1851           DefaultData.DefaultId   = DefaultDataPtr->DefaultId;
   1852           InsertDefaultValue (BlockData, &DefaultData);
   1853         }
   1854       }
   1855       break;
   1856 
   1857     case EFI_IFR_ORDERED_LIST_OP:
   1858       //
   1859       // offset by question header
   1860       // width by EFI_IFR_ORDERED_LIST MaxContainers * OneofOption Type
   1861       //
   1862 
   1863       FirstOrderedList = TRUE;
   1864       //
   1865       // OrderedList question is not in IFR Form. This IFR form is not valid.
   1866       //
   1867       if (VarStoreId == 0) {
   1868         Status = EFI_INVALID_PARAMETER;
   1869         goto Done;
   1870       }
   1871       //
   1872       // Check whether this question is for the requested varstore.
   1873       //
   1874       IfrOrderedList = (EFI_IFR_ORDERED_LIST *) IfrOpHdr;
   1875       if (IfrOrderedList->Question.VarStoreId != VarStoreId) {
   1876         BlockData = NULL;
   1877         break;
   1878       }
   1879       VarWidth  = IfrOrderedList->MaxContainers;
   1880       Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);
   1881       if (EFI_ERROR (Status)) {
   1882         goto Done;
   1883       }
   1884       break;
   1885 
   1886     case EFI_IFR_CHECKBOX_OP:
   1887       //
   1888       // EFI_IFR_DEFAULT_OP
   1889       // offset by question header
   1890       // width is 1 sizeof (BOOLEAN)
   1891       // default id by CheckBox Flags if CheckBox flags (Default or Mau) is set, the default value is 1 to be set.
   1892       // value by DefaultOption
   1893       // default id by DeaultOption DefaultId can override CheckBox Flags and Default value.
   1894       //
   1895 
   1896       //
   1897       // CheckBox question is not in IFR Form. This IFR form is not valid.
   1898       //
   1899       if (VarStoreId == 0) {
   1900         Status = EFI_INVALID_PARAMETER;
   1901         goto Done;
   1902       }
   1903       //
   1904       // Check whether this question is for the requested varstore.
   1905       //
   1906       IfrCheckBox = (EFI_IFR_CHECKBOX *) IfrOpHdr;
   1907       if (IfrCheckBox->Question.VarStoreId != VarStoreId) {
   1908         break;
   1909       }
   1910       VarWidth  = (UINT16) sizeof (BOOLEAN);
   1911       Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);
   1912       if (EFI_ERROR (Status)) {
   1913         goto Done;
   1914       }
   1915 
   1916       if (BlockData == NULL) {
   1917         //
   1918         // BlockData == NULL means this opcode is not in the requst array.
   1919         //
   1920         break;
   1921       }
   1922 
   1923       //
   1924       // Add default value for standard ID by CheckBox Flag
   1925       //
   1926       VarDefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;
   1927       //
   1928       // Prepare new DefaultValue
   1929       //
   1930       DefaultData.DefaultId   = VarDefaultId;
   1931       if ((IfrCheckBox->Flags & EFI_IFR_CHECKBOX_DEFAULT) == EFI_IFR_CHECKBOX_DEFAULT) {
   1932         //
   1933         // When flag is set, defautl value is TRUE.
   1934         //
   1935         DefaultData.Type    = DefaultValueFromFlag;
   1936         DefaultData.Value.b = TRUE;
   1937       } else {
   1938         //
   1939         // When flag is not set, defautl value is FASLE.
   1940         //
   1941         DefaultData.Type    = DefaultValueFromDefault;
   1942         DefaultData.Value.b = FALSE;
   1943       }
   1944       //
   1945       // Add DefaultValue into current BlockData
   1946       //
   1947       InsertDefaultValue (BlockData, &DefaultData);
   1948 
   1949       //
   1950       // Add default value for Manufacture ID by CheckBox Flag
   1951       //
   1952       VarDefaultId = EFI_HII_DEFAULT_CLASS_MANUFACTURING;
   1953       //
   1954       // Prepare new DefaultValue
   1955       //
   1956       DefaultData.DefaultId   = VarDefaultId;
   1957       if ((IfrCheckBox->Flags & EFI_IFR_CHECKBOX_DEFAULT_MFG) == EFI_IFR_CHECKBOX_DEFAULT_MFG) {
   1958         //
   1959         // When flag is set, defautl value is TRUE.
   1960         //
   1961         DefaultData.Type    = DefaultValueFromFlag;
   1962         DefaultData.Value.b = TRUE;
   1963       } else {
   1964         //
   1965         // When flag is not set, defautl value is FASLE.
   1966         //
   1967         DefaultData.Type    = DefaultValueFromDefault;
   1968         DefaultData.Value.b = FALSE;
   1969       }
   1970       //
   1971       // Add DefaultValue into current BlockData
   1972       //
   1973       InsertDefaultValue (BlockData, &DefaultData);
   1974       break;
   1975 
   1976     case EFI_IFR_DATE_OP:
   1977       //
   1978       // offset by question header
   1979       // width MaxSize * sizeof (CHAR16)
   1980       // no default value, only block array
   1981       //
   1982 
   1983       //
   1984       // Date question is not in IFR Form. This IFR form is not valid.
   1985       //
   1986       if (VarStoreId == 0) {
   1987         Status = EFI_INVALID_PARAMETER;
   1988         goto Done;
   1989       }
   1990       //
   1991       // Check whether this question is for the requested varstore.
   1992       //
   1993       IfrDate = (EFI_IFR_DATE *) IfrOpHdr;
   1994       if (IfrDate->Question.VarStoreId != VarStoreId) {
   1995         break;
   1996       }
   1997 
   1998       VarWidth  = (UINT16) sizeof (EFI_HII_DATE);
   1999       Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);
   2000       if (EFI_ERROR (Status)) {
   2001         goto Done;
   2002       }
   2003       break;
   2004 
   2005     case EFI_IFR_TIME_OP:
   2006       //
   2007       // offset by question header
   2008       // width MaxSize * sizeof (CHAR16)
   2009       // no default value, only block array
   2010       //
   2011 
   2012       //
   2013       // Time question is not in IFR Form. This IFR form is not valid.
   2014       //
   2015       if (VarStoreId == 0) {
   2016         Status = EFI_INVALID_PARAMETER;
   2017         goto Done;
   2018       }
   2019       //
   2020       // Check whether this question is for the requested varstore.
   2021       //
   2022       IfrTime = (EFI_IFR_TIME *) IfrOpHdr;
   2023       if (IfrTime->Question.VarStoreId != VarStoreId) {
   2024         break;
   2025       }
   2026 
   2027       VarWidth  = (UINT16) sizeof (EFI_HII_TIME);
   2028       Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);
   2029       if (EFI_ERROR (Status)) {
   2030         goto Done;
   2031       }
   2032       break;
   2033 
   2034     case EFI_IFR_STRING_OP:
   2035       //
   2036       // offset by question header
   2037       // width MaxSize * sizeof (CHAR16)
   2038       // no default value, only block array
   2039       //
   2040 
   2041       //
   2042       // String question is not in IFR Form. This IFR form is not valid.
   2043       //
   2044       if (VarStoreId == 0) {
   2045         Status = EFI_INVALID_PARAMETER;
   2046         goto Done;
   2047       }
   2048       //
   2049       // Check whether this question is for the requested varstore.
   2050       //
   2051       IfrString = (EFI_IFR_STRING *) IfrOpHdr;
   2052       if (IfrString->Question.VarStoreId != VarStoreId) {
   2053         break;
   2054       }
   2055 
   2056       VarWidth  = (UINT16) (IfrString->MaxSize * sizeof (UINT16));
   2057       Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);
   2058       if (EFI_ERROR (Status)) {
   2059         goto Done;
   2060       }
   2061       break;
   2062 
   2063     case EFI_IFR_PASSWORD_OP:
   2064       //
   2065       // offset by question header
   2066       // width MaxSize * sizeof (CHAR16)
   2067       // no default value, only block array
   2068       //
   2069 
   2070       //
   2071       // Password question is not in IFR Form. This IFR form is not valid.
   2072       //
   2073       if (VarStoreId == 0) {
   2074         Status = EFI_INVALID_PARAMETER;
   2075         goto Done;
   2076       }
   2077       //
   2078       // Check whether this question is for the requested varstore.
   2079       //
   2080       IfrPassword = (EFI_IFR_PASSWORD *) IfrOpHdr;
   2081       if (IfrPassword->Question.VarStoreId != VarStoreId) {
   2082         break;
   2083       }
   2084 
   2085       VarWidth  = (UINT16) (IfrPassword->MaxSize * sizeof (UINT16));
   2086       Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);
   2087       if (EFI_ERROR (Status)) {
   2088         goto Done;
   2089       }
   2090 
   2091       //
   2092       // No default value for string.
   2093       //
   2094       BlockData = NULL;
   2095       break;
   2096 
   2097     case EFI_IFR_ONE_OF_OPTION_OP:
   2098       //
   2099       // No matched block data is ignored.
   2100       //
   2101       if (BlockData == NULL || BlockData->Scope == 0) {
   2102         break;
   2103       }
   2104 
   2105       IfrOneOfOption = (EFI_IFR_ONE_OF_OPTION *) IfrOpHdr;
   2106       if (BlockData->OpCode == EFI_IFR_ORDERED_LIST_OP) {
   2107 
   2108         if (!FirstOrderedList){
   2109           break;
   2110         }
   2111         //
   2112         // Get ordered list option data type.
   2113         //
   2114         if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_8 || IfrOneOfOption->Type == EFI_IFR_TYPE_BOOLEAN) {
   2115           VarWidth = 1;
   2116         } else if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_16) {
   2117           VarWidth = 2;
   2118         } else if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_32) {
   2119           VarWidth = 4;
   2120         } else if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_64) {
   2121           VarWidth = 8;
   2122         } else {
   2123           //
   2124           // Invalid ordered list option data type.
   2125           //
   2126           Status = EFI_INVALID_PARAMETER;
   2127           if (BlockData->Name != NULL) {
   2128             FreePool (BlockData->Name);
   2129           }
   2130           FreePool (BlockData);
   2131           goto Done;
   2132         }
   2133 
   2134         //
   2135         // Calculate Ordered list QuestionId width.
   2136         //
   2137         BlockData->Width = (UINT16) (BlockData->Width * VarWidth);
   2138         //
   2139         // Check whether this question is in requested block array.
   2140         //
   2141         if (!BlockArrayCheck (RequestBlockArray, BlockData->Offset, BlockData->Width, (BOOLEAN)(BlockData->Name != NULL), HiiHandle)) {
   2142           //
   2143           // This question is not in the requested string. Skip it.
   2144           //
   2145           if (BlockData->Name != NULL) {
   2146             FreePool (BlockData->Name);
   2147           }
   2148           FreePool (BlockData);
   2149           BlockData = NULL;
   2150           break;
   2151         }
   2152         //
   2153         // Check this var question is in the var storage
   2154         //
   2155         if ((BlockData->Name == NULL) && ((BlockData->Offset + BlockData->Width) > VarStorageData->Size)) {
   2156           Status = EFI_INVALID_PARAMETER;
   2157           if (BlockData->Name != NULL) {
   2158             FreePool (BlockData->Name);
   2159           }
   2160           FreePool (BlockData);
   2161           goto Done;
   2162         }
   2163         //
   2164         // Add Block Data into VarStorageData BlockEntry
   2165         //
   2166         InsertBlockData (&VarStorageData->BlockEntry, &BlockData);
   2167 
   2168         FirstOrderedList = FALSE;
   2169 
   2170         break;
   2171       }
   2172 
   2173       //
   2174       // 1. Set default value for OneOf option when flag field has default attribute.
   2175       //
   2176       if (((IfrOneOfOption->Flags & EFI_IFR_OPTION_DEFAULT) == EFI_IFR_OPTION_DEFAULT) ||
   2177           ((IfrOneOfOption->Flags & EFI_IFR_OPTION_DEFAULT_MFG) == EFI_IFR_OPTION_DEFAULT_MFG)) {
   2178         //
   2179         // This flag is used to specify whether this option is the first. Set it to FALSE for the following options.
   2180         // The first oneof option value will be used as default value when no default value is specified.
   2181         //
   2182         FirstOneOfOption = FALSE;
   2183 
   2184         // Prepare new DefaultValue
   2185         //
   2186         DefaultData.Type     = DefaultValueFromFlag;
   2187         CopyMem (&DefaultData.Value, &IfrOneOfOption->Value, IfrOneOfOption->Header.Length - OFFSET_OF (EFI_IFR_ONE_OF_OPTION, Value));
   2188         if ((IfrOneOfOption->Flags & EFI_IFR_OPTION_DEFAULT) == EFI_IFR_OPTION_DEFAULT) {
   2189           DefaultData.DefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;
   2190           InsertDefaultValue (BlockData, &DefaultData);
   2191         }
   2192         if ((IfrOneOfOption->Flags & EFI_IFR_OPTION_DEFAULT_MFG) == EFI_IFR_OPTION_DEFAULT_MFG) {
   2193           DefaultData.DefaultId = EFI_HII_DEFAULT_CLASS_MANUFACTURING;
   2194           InsertDefaultValue (BlockData, &DefaultData);
   2195         }
   2196       }
   2197 
   2198       //
   2199       // 2. Set as the default value when this is the first option.
   2200       // The first oneof option value will be used as default value when no default value is specified.
   2201       //
   2202       if (FirstOneOfOption) {
   2203         // This flag is used to specify whether this option is the first. Set it to FALSE for the following options.
   2204         FirstOneOfOption = FALSE;
   2205 
   2206         //
   2207         // Prepare new DefaultValue
   2208         //
   2209         DefaultData.Type     = DefaultValueFromDefault;
   2210         CopyMem (&DefaultData.Value, &IfrOneOfOption->Value, IfrOneOfOption->Header.Length - OFFSET_OF (EFI_IFR_ONE_OF_OPTION, Value));
   2211         for (LinkData = DefaultIdArray->Entry.ForwardLink; LinkData != &DefaultIdArray->Entry; LinkData = LinkData->ForwardLink) {
   2212           DefaultDataPtr = BASE_CR (LinkData, IFR_DEFAULT_DATA, Entry);
   2213           DefaultData.DefaultId   = DefaultDataPtr->DefaultId;
   2214           InsertDefaultValue (BlockData, &DefaultData);
   2215         }
   2216       }
   2217       break;
   2218 
   2219     case EFI_IFR_DEFAULT_OP:
   2220       //
   2221       // Update Current BlockData to the default value.
   2222       //
   2223       if (BlockData == NULL || BlockData->Scope == 0) {
   2224         //
   2225         // No matched block data is ignored.
   2226         //
   2227         break;
   2228       }
   2229 
   2230       //
   2231       // Get the DefaultId
   2232       //
   2233       IfrDefault     = (EFI_IFR_DEFAULT *) IfrOpHdr;
   2234       VarDefaultId   = IfrDefault->DefaultId;
   2235       //
   2236       // Prepare new DefaultValue
   2237       //
   2238       DefaultData.Type        = DefaultValueFromOpcode;
   2239       DefaultData.DefaultId   = VarDefaultId;
   2240       CopyMem (&DefaultData.Value, &IfrDefault->Value, IfrDefault->Header.Length - OFFSET_OF (EFI_IFR_DEFAULT, Value));
   2241 
   2242       // If the value field is expression, set the cleaned flag.
   2243       if (IfrDefault->Type ==  EFI_IFR_TYPE_OTHER) {
   2244         DefaultData.Cleaned = TRUE;
   2245       }
   2246       //
   2247       // Add DefaultValue into current BlockData
   2248       //
   2249       InsertDefaultValue (BlockData, &DefaultData);
   2250 
   2251       //
   2252       // After insert the default value, reset the cleaned value for next
   2253       // time used. If not set here, need to set the value before everytime
   2254       // use it.
   2255       //
   2256       DefaultData.Cleaned     = FALSE;
   2257       break;
   2258 
   2259     case EFI_IFR_END_OP:
   2260       //
   2261       // End Opcode is for Var question.
   2262       //
   2263       if (BlockData != NULL) {
   2264         if (BlockData->Scope > 0) {
   2265           BlockData->Scope--;
   2266         }
   2267         if (BlockData->Scope == 0) {
   2268           BlockData = NULL;
   2269         }
   2270       }
   2271 
   2272       break;
   2273 
   2274     default:
   2275       if (BlockData != NULL) {
   2276         if (BlockData->Scope > 0) {
   2277           BlockData->Scope = (UINT8) (BlockData->Scope + IfrOpHdr->Scope);
   2278         }
   2279 
   2280         if (BlockData->Scope == 0) {
   2281           BlockData = NULL;
   2282         }
   2283       }
   2284       break;
   2285     }
   2286 
   2287     IfrOffset     += IfrOpHdr->Length;
   2288     PackageOffset += IfrOpHdr->Length;
   2289   }
   2290 
   2291 Done:
   2292   for (LinkData = VarStorageData->BlockEntry.ForwardLink; LinkData != &VarStorageData->BlockEntry; LinkData = LinkData->ForwardLink) {
   2293     BlockData = BASE_CR (LinkData, IFR_BLOCK_DATA, Entry);
   2294     for (LinkDefault = BlockData->DefaultValueEntry.ForwardLink; LinkDefault != &BlockData->DefaultValueEntry; ) {
   2295       DefaultDataPtr = BASE_CR (LinkDefault, IFR_DEFAULT_DATA, Entry);
   2296       LinkDefault = LinkDefault->ForwardLink;
   2297       if (DefaultDataPtr->Cleaned == TRUE) {
   2298         RemoveEntryList (&DefaultDataPtr->Entry);
   2299         FreePool (DefaultDataPtr);
   2300       }
   2301     }
   2302   }
   2303 
   2304   return Status;
   2305 }
   2306 
   2307 /**
   2308   parse the configrequest string, get the elements.
   2309 
   2310   @param      ConfigRequest         The input configrequest string.
   2311   @param      Progress              Return the progress data.
   2312 
   2313   @retval     Block data pointer.
   2314 **/
   2315 IFR_BLOCK_DATA *
   2316 GetBlockElement (
   2317   IN  EFI_STRING          ConfigRequest,
   2318   OUT EFI_STRING          *Progress
   2319   )
   2320 {
   2321   EFI_STRING           StringPtr;
   2322   IFR_BLOCK_DATA       *BlockData;
   2323   IFR_BLOCK_DATA       *RequestBlockArray;
   2324   EFI_STATUS           Status;
   2325   UINT8                *TmpBuffer;
   2326   UINT16               Offset;
   2327   UINT16               Width;
   2328   LIST_ENTRY           *Link;
   2329   IFR_BLOCK_DATA       *NextBlockData;
   2330   UINTN                Length;
   2331 
   2332   TmpBuffer = NULL;
   2333 
   2334   //
   2335   // Init RequestBlockArray
   2336   //
   2337   RequestBlockArray = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));
   2338   if (RequestBlockArray == NULL) {
   2339     goto Done;
   2340   }
   2341   InitializeListHead (&RequestBlockArray->Entry);
   2342 
   2343   //
   2344   // Get the request Block array from the request string
   2345   // Offset and Width
   2346   //
   2347 
   2348   //
   2349   // Parse each <RequestElement> if exists
   2350   // Only <BlockName> format is supported by this help function.
   2351   // <BlockName> ::= &'OFFSET='<Number>&'WIDTH='<Number>
   2352   //
   2353   StringPtr = ConfigRequest;
   2354   while (*StringPtr != 0 && StrnCmp (StringPtr, L"&OFFSET=", StrLen (L"&OFFSET=")) == 0) {
   2355     //
   2356     // Skip the OFFSET string
   2357     //
   2358     *Progress   = StringPtr;
   2359     StringPtr += StrLen (L"&OFFSET=");
   2360     //
   2361     // Get Offset
   2362     //
   2363     Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
   2364     if (EFI_ERROR (Status)) {
   2365       goto Done;
   2366     }
   2367     Offset = 0;
   2368     CopyMem (
   2369       &Offset,
   2370       TmpBuffer,
   2371       (((Length + 1) / 2) < sizeof (UINT16)) ? ((Length + 1) / 2) : sizeof (UINT16)
   2372       );
   2373     FreePool (TmpBuffer);
   2374 
   2375     StringPtr += Length;
   2376     if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {
   2377       goto Done;
   2378     }
   2379     StringPtr += StrLen (L"&WIDTH=");
   2380 
   2381     //
   2382     // Get Width
   2383     //
   2384     Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
   2385     if (EFI_ERROR (Status)) {
   2386       goto Done;
   2387     }
   2388     Width = 0;
   2389     CopyMem (
   2390       &Width,
   2391       TmpBuffer,
   2392       (((Length + 1) / 2) < sizeof (UINT16)) ? ((Length + 1) / 2) : sizeof (UINT16)
   2393       );
   2394     FreePool (TmpBuffer);
   2395 
   2396     StringPtr += Length;
   2397     if (*StringPtr != 0 && *StringPtr != L'&') {
   2398       goto Done;
   2399     }
   2400 
   2401     //
   2402     // Set Block Data
   2403     //
   2404     BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));
   2405     if (BlockData == NULL) {
   2406       goto Done;
   2407     }
   2408     BlockData->Offset = Offset;
   2409     BlockData->Width  = Width;
   2410     InsertBlockData (&RequestBlockArray->Entry, &BlockData);
   2411 
   2412     //
   2413     // Skip &VALUE string if &VALUE does exists.
   2414     //
   2415     if (StrnCmp (StringPtr, L"&VALUE=", StrLen (L"&VALUE=")) == 0) {
   2416       StringPtr += StrLen (L"&VALUE=");
   2417 
   2418       //
   2419       // Get Value
   2420       //
   2421       Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
   2422       if (EFI_ERROR (Status)) {
   2423         goto Done;
   2424       }
   2425 
   2426       StringPtr += Length;
   2427       if (*StringPtr != 0 && *StringPtr != L'&') {
   2428         goto Done;
   2429       }
   2430     }
   2431     //
   2432     // If '\0', parsing is finished.
   2433     //
   2434     if (*StringPtr == 0) {
   2435       break;
   2436     }
   2437   }
   2438 
   2439   //
   2440   // Merge the requested block data.
   2441   //
   2442   Link = RequestBlockArray->Entry.ForwardLink;
   2443   while ((Link != &RequestBlockArray->Entry) && (Link->ForwardLink != &RequestBlockArray->Entry)) {
   2444     BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);
   2445     NextBlockData = BASE_CR (Link->ForwardLink, IFR_BLOCK_DATA, Entry);
   2446     if ((NextBlockData->Offset >= BlockData->Offset) && (NextBlockData->Offset <= (BlockData->Offset + BlockData->Width))) {
   2447       if ((NextBlockData->Offset + NextBlockData->Width) > (BlockData->Offset + BlockData->Width)) {
   2448         BlockData->Width = (UINT16) (NextBlockData->Offset + NextBlockData->Width - BlockData->Offset);
   2449       }
   2450       RemoveEntryList (Link->ForwardLink);
   2451       FreePool (NextBlockData);
   2452       continue;
   2453     }
   2454     Link = Link->ForwardLink;
   2455   }
   2456 
   2457   return RequestBlockArray;
   2458 
   2459 Done:
   2460   if (RequestBlockArray != NULL) {
   2461     //
   2462     // Free Link Array RequestBlockArray
   2463     //
   2464     while (!IsListEmpty (&RequestBlockArray->Entry)) {
   2465       BlockData = BASE_CR (RequestBlockArray->Entry.ForwardLink, IFR_BLOCK_DATA, Entry);
   2466       RemoveEntryList (&BlockData->Entry);
   2467       FreePool (BlockData);
   2468     }
   2469 
   2470     FreePool (RequestBlockArray);
   2471   }
   2472 
   2473   return NULL;
   2474 }
   2475 
   2476 /**
   2477   parse the configrequest string, get the elements.
   2478 
   2479   @param      ConfigRequest         The input config request string.
   2480   @param      Progress              Return the progress data.
   2481 
   2482   @retval     return data block array.
   2483 **/
   2484 IFR_BLOCK_DATA *
   2485 GetNameElement (
   2486   IN  EFI_STRING           ConfigRequest,
   2487   OUT EFI_STRING           *Progress
   2488   )
   2489 {
   2490   EFI_STRING           StringPtr;
   2491   EFI_STRING           NextTag;
   2492   IFR_BLOCK_DATA       *BlockData;
   2493   IFR_BLOCK_DATA       *RequestBlockArray;
   2494   BOOLEAN              HasValue;
   2495 
   2496   StringPtr = ConfigRequest;
   2497 
   2498   //
   2499   // Init RequestBlockArray
   2500   //
   2501   RequestBlockArray = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));
   2502   if (RequestBlockArray == NULL) {
   2503     goto Done;
   2504   }
   2505   InitializeListHead (&RequestBlockArray->Entry);
   2506 
   2507   //
   2508   // Get the request Block array from the request string
   2509   //
   2510 
   2511   //
   2512   // Parse each <RequestElement> if exists
   2513   // Only <BlockName> format is supported by this help function.
   2514   // <BlockName> ::= &'Name***=***
   2515   //
   2516   while (StringPtr != NULL && *StringPtr == L'&') {
   2517 
   2518     *Progress   = StringPtr;
   2519     //
   2520     // Skip the L"&" string
   2521     //
   2522     StringPtr += 1;
   2523 
   2524     HasValue = FALSE;
   2525     if ((NextTag = StrStr (StringPtr, L"=")) != NULL) {
   2526       *NextTag = L'\0';
   2527       HasValue = TRUE;
   2528     } else if ((NextTag = StrStr (StringPtr, L"&")) != NULL) {
   2529       *NextTag = L'\0';
   2530     }
   2531 
   2532     //
   2533     // Set Block Data
   2534     //
   2535     BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));
   2536     if (BlockData == NULL) {
   2537       goto Done;
   2538     }
   2539 
   2540     //
   2541     // Get Name
   2542     //
   2543     BlockData->Name = AllocateCopyPool(StrSize (StringPtr), StringPtr);
   2544     InsertBlockData (&RequestBlockArray->Entry, &BlockData);
   2545 
   2546     if (HasValue) {
   2547       //
   2548       // If has value, skip the value.
   2549       //
   2550       StringPtr = NextTag + 1;
   2551       *NextTag  = L'=';
   2552       StringPtr = StrStr (StringPtr, L"&");
   2553     } else if (NextTag != NULL) {
   2554       //
   2555       // restore the '&' text.
   2556       //
   2557       StringPtr = NextTag;
   2558       *NextTag  = L'&';
   2559     }
   2560   }
   2561 
   2562   return RequestBlockArray;
   2563 
   2564 Done:
   2565   if (RequestBlockArray != NULL) {
   2566     //
   2567     // Free Link Array RequestBlockArray
   2568     //
   2569     while (!IsListEmpty (&RequestBlockArray->Entry)) {
   2570       BlockData = BASE_CR (RequestBlockArray->Entry.ForwardLink, IFR_BLOCK_DATA, Entry);
   2571       RemoveEntryList (&BlockData->Entry);
   2572       if (BlockData->Name != NULL) {
   2573         FreePool (BlockData->Name);
   2574       }
   2575       FreePool (BlockData);
   2576     }
   2577 
   2578     FreePool (RequestBlockArray);
   2579   }
   2580 
   2581   return NULL;
   2582 }
   2583 
   2584 /**
   2585   Generate ConfigRequest string base on the varstore info.
   2586 
   2587   @param      ConfigHdr             The config header for this varstore.
   2588   @param      VarStorageData        The varstore info.
   2589   @param      Status                Return Status.
   2590   @param      ConfigRequest         The ConfigRequest info may be return.
   2591 
   2592   @retval     TRUE                  Need to continue
   2593   @retval     Others                NO need to continue or error occur.
   2594 **/
   2595 BOOLEAN
   2596 GenerateConfigRequest (
   2597   IN  CHAR16                       *ConfigHdr,
   2598   IN  IFR_VARSTORAGE_DATA          *VarStorageData,
   2599   OUT EFI_STATUS                   *Status,
   2600   IN OUT EFI_STRING                *ConfigRequest
   2601   )
   2602 {
   2603   BOOLEAN               DataExist;
   2604   UINTN                 Length;
   2605   LIST_ENTRY            *Link;
   2606   CHAR16                *FullConfigRequest;
   2607   CHAR16                *StringPtr;
   2608   IFR_BLOCK_DATA        *BlockData;
   2609 
   2610   //
   2611   // Append VarStorageData BlockEntry into *Request string
   2612   // Now support only one varstore in a form package.
   2613   //
   2614 
   2615   //
   2616   // Go through all VarStorageData Entry and get BlockEntry for each one for the multiple varstore in a single form package
   2617   // Then construct them all to return MultiRequest string : ConfigHdr BlockConfig
   2618   //
   2619 
   2620   //
   2621   // Compute the length of the entire request starting with <ConfigHdr> and a
   2622   // Null-terminator
   2623   //
   2624   DataExist = FALSE;
   2625   Length    = StrLen (ConfigHdr) + 1;
   2626 
   2627   for (Link = VarStorageData->BlockEntry.ForwardLink; Link != &VarStorageData->BlockEntry; Link = Link->ForwardLink) {
   2628     DataExist = TRUE;
   2629     BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);
   2630     if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {
   2631       //
   2632       // Add <BlockName> length for each Name
   2633       //
   2634       // <BlockName> ::= &Name1&Name2&...
   2635       //                 |1| StrLen(Name1)
   2636       //
   2637       Length = Length + (1 + StrLen (BlockData->Name));
   2638     } else {
   2639       //
   2640       // Add <BlockName> length for each Offset/Width pair
   2641       //
   2642       // <BlockName> ::= &OFFSET=1234&WIDTH=1234
   2643       //                 |  8   | 4 |   7  | 4 |
   2644       //
   2645       Length = Length + (8 + 4 + 7 + 4);
   2646     }
   2647   }
   2648   //
   2649   // No any request block data is found. The request string can't be constructed.
   2650   //
   2651   if (!DataExist) {
   2652     *Status = EFI_SUCCESS;
   2653     return FALSE;
   2654   }
   2655 
   2656   //
   2657   // Allocate buffer for the entire <ConfigRequest>
   2658   //
   2659   FullConfigRequest = AllocateZeroPool (Length * sizeof (CHAR16));
   2660   if (FullConfigRequest == NULL) {
   2661     *Status = EFI_OUT_OF_RESOURCES;
   2662     return FALSE;
   2663   }
   2664   StringPtr = FullConfigRequest;
   2665 
   2666   //
   2667   // Start with <ConfigHdr>
   2668   //
   2669   StrCpyS (StringPtr, Length, ConfigHdr);
   2670   StringPtr += StrLen (StringPtr);
   2671 
   2672   //
   2673   // Loop through all the Offset/Width pairs and append them to ConfigRequest
   2674   //
   2675   for (Link = VarStorageData->BlockEntry.ForwardLink; Link != &VarStorageData->BlockEntry; Link = Link->ForwardLink) {
   2676     BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);
   2677     if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {
   2678       //
   2679       // Append &Name1\0
   2680       //
   2681       UnicodeSPrint (
   2682         StringPtr,
   2683         (1 + StrLen (BlockData->Name) + 1) * sizeof (CHAR16),
   2684         L"&%s",
   2685         BlockData->Name
   2686       );
   2687     } else {
   2688       //
   2689       // Append &OFFSET=XXXX&WIDTH=YYYY\0
   2690       //
   2691       UnicodeSPrint (
   2692         StringPtr,
   2693         (8 + 4 + 7 + 4 + 1) * sizeof (CHAR16),
   2694         L"&OFFSET=%04X&WIDTH=%04X",
   2695         BlockData->Offset,
   2696         BlockData->Width
   2697       );
   2698     }
   2699     StringPtr += StrLen (StringPtr);
   2700   }
   2701   //
   2702   // Set to the got full request string.
   2703   //
   2704   HiiToLower (FullConfigRequest);
   2705 
   2706   if (*ConfigRequest != NULL) {
   2707     FreePool (*ConfigRequest);
   2708   }
   2709   *ConfigRequest = FullConfigRequest;
   2710 
   2711   return TRUE;
   2712 }
   2713 
   2714 /**
   2715   Generate ConfigRequest Header base on the varstore info.
   2716 
   2717   @param      VarStorageData        The varstore info.
   2718   @param      DevicePath            Device path for this varstore.
   2719   @param      ConfigHdr             The config header for this varstore.
   2720 
   2721   @retval     EFI_SUCCESS           Generate the header success.
   2722   @retval     EFI_OUT_OF_RESOURCES  Allocate buffer fail.
   2723 **/
   2724 EFI_STATUS
   2725 GenerateHdr (
   2726   IN   IFR_VARSTORAGE_DATA          *VarStorageData,
   2727   IN   EFI_DEVICE_PATH_PROTOCOL     *DevicePath,
   2728   OUT  EFI_STRING                   *ConfigHdr
   2729   )
   2730 {
   2731   EFI_STRING                   GuidStr;
   2732   EFI_STRING                   NameStr;
   2733   EFI_STRING                   PathStr;
   2734   UINTN                        Length;
   2735   EFI_STATUS                   Status;
   2736 
   2737   Status  = EFI_SUCCESS;
   2738   NameStr = NULL;
   2739   GuidStr = NULL;
   2740   PathStr = NULL;
   2741 
   2742   //
   2743   // Construct <ConfigHdr> : "GUID=...&NAME=...&PATH=..." by VarStorageData Guid, Name and DriverHandle
   2744   //
   2745   GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (VOID *) &VarStorageData->Guid, 1, &GuidStr);
   2746   if (VarStorageData->Name != NULL) {
   2747     GenerateSubStr (L"NAME=", StrLen (VarStorageData->Name) * sizeof (CHAR16), (VOID *) VarStorageData->Name, 2, &NameStr);
   2748   } else {
   2749     GenerateSubStr (L"NAME=", 0, NULL, 2, &NameStr);
   2750   }
   2751   GenerateSubStr (
   2752     L"PATH=",
   2753     GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) DevicePath),
   2754     (VOID *) DevicePath,
   2755     1,
   2756     &PathStr
   2757     );
   2758   Length = StrLen (GuidStr) + StrLen (NameStr) + StrLen (PathStr) + 1;
   2759   if (VarStorageData->Name == NULL) {
   2760     Length += 1;
   2761   }
   2762 
   2763   *ConfigHdr = AllocateZeroPool (Length * sizeof (CHAR16));
   2764   if (*ConfigHdr == NULL) {
   2765     Status = EFI_OUT_OF_RESOURCES;
   2766     goto Done;
   2767   }
   2768   StrCpyS (*ConfigHdr, Length, GuidStr);
   2769   StrCatS (*ConfigHdr, Length, NameStr);
   2770   if (VarStorageData->Name == NULL) {
   2771     StrCatS (*ConfigHdr, Length, L"&");
   2772   }
   2773   StrCatS (*ConfigHdr, Length, PathStr);
   2774 
   2775   //
   2776   // Remove the last character L'&'
   2777   //
   2778   *(*ConfigHdr + StrLen (*ConfigHdr) - 1) = L'\0';
   2779 
   2780 Done:
   2781   if (GuidStr != NULL) {
   2782     FreePool (GuidStr);
   2783   }
   2784 
   2785   if (NameStr != NULL) {
   2786     FreePool (NameStr);
   2787   }
   2788 
   2789   if (PathStr != NULL) {
   2790     FreePool (PathStr);
   2791   }
   2792 
   2793   return Status;
   2794 }
   2795 
   2796 /**
   2797   Get Data buffer size based on data type.
   2798 
   2799   @param      ValueType             The input data type.
   2800 
   2801   @retval     The data buffer size for the input type.
   2802 **/
   2803 UINT16
   2804 GetStorageWidth (
   2805   IN UINT8       ValueType
   2806   )
   2807 {
   2808   UINT16         StorageWidth;
   2809 
   2810   switch (ValueType) {
   2811   case EFI_IFR_NUMERIC_SIZE_1:
   2812   case EFI_IFR_TYPE_BOOLEAN:
   2813     StorageWidth = (UINT16) sizeof (UINT8);
   2814     break;
   2815 
   2816   case EFI_IFR_NUMERIC_SIZE_2:
   2817     StorageWidth = (UINT16) sizeof (UINT16);
   2818     break;
   2819 
   2820   case EFI_IFR_NUMERIC_SIZE_4:
   2821     StorageWidth = (UINT16) sizeof (UINT32);
   2822     break;
   2823 
   2824   case EFI_IFR_NUMERIC_SIZE_8:
   2825     StorageWidth = (UINT16) sizeof (UINT64);
   2826     break;
   2827 
   2828   case EFI_IFR_TYPE_TIME:
   2829     StorageWidth = (UINT16) sizeof (EFI_IFR_TIME);
   2830     break;
   2831 
   2832   case EFI_IFR_TYPE_DATE:
   2833     StorageWidth = (UINT16) sizeof (EFI_IFR_DATE);
   2834     break;
   2835 
   2836   default:
   2837     StorageWidth = 0;
   2838     break;
   2839   }
   2840 
   2841   return StorageWidth;
   2842 }
   2843 
   2844 /**
   2845   Generate ConfigAltResp string base on the varstore info.
   2846 
   2847   @param      HiiHandle             Hii Handle for this hii package.
   2848   @param      ConfigHdr             The config header for this varstore.
   2849   @param      VarStorageData        The varstore info.
   2850   @param      DefaultIdArray        The Default id array.
   2851   @param      DefaultAltCfgResp     The DefaultAltCfgResp info may be return.
   2852 
   2853   @retval     TRUE                  Need to continue
   2854   @retval     Others                NO need to continue or error occur.
   2855 **/
   2856 EFI_STATUS
   2857 GenerateAltConfigResp (
   2858   IN  EFI_HII_HANDLE               HiiHandle,
   2859   IN  CHAR16                       *ConfigHdr,
   2860   IN  IFR_VARSTORAGE_DATA          *VarStorageData,
   2861   IN  IFR_DEFAULT_DATA             *DefaultIdArray,
   2862   IN OUT EFI_STRING                *DefaultAltCfgResp
   2863   )
   2864 {
   2865   BOOLEAN               DataExist;
   2866   UINTN                 Length;
   2867   LIST_ENTRY            *Link;
   2868   LIST_ENTRY            *LinkData;
   2869   LIST_ENTRY            *LinkDefault;
   2870   LIST_ENTRY            *ListEntry;
   2871   CHAR16                *StringPtr;
   2872   IFR_BLOCK_DATA        *BlockData;
   2873   IFR_DEFAULT_DATA      *DefaultId;
   2874   IFR_DEFAULT_DATA      *DefaultValueData;
   2875   UINTN                 Width;
   2876   UINT8                 *TmpBuffer;
   2877   CHAR16                *DefaultString;
   2878 
   2879   BlockData     = NULL;
   2880   DataExist     = FALSE;
   2881   DefaultString = NULL;
   2882   //
   2883   // Add length for <ConfigHdr> + '\0'
   2884   //
   2885   Length = StrLen (ConfigHdr) + 1;
   2886 
   2887   for (Link = DefaultIdArray->Entry.ForwardLink; Link != &DefaultIdArray->Entry; Link = Link->ForwardLink) {
   2888     DefaultId = BASE_CR (Link, IFR_DEFAULT_DATA, Entry);
   2889     //
   2890     // Add length for "&<ConfigHdr>&ALTCFG=XXXX"
   2891     //                |1| StrLen (ConfigHdr) | 8 | 4 |
   2892     //
   2893     Length += (1 + StrLen (ConfigHdr) + 8 + 4);
   2894 
   2895     for (LinkData = VarStorageData->BlockEntry.ForwardLink; LinkData != &VarStorageData->BlockEntry; LinkData = LinkData->ForwardLink) {
   2896       BlockData = BASE_CR (LinkData, IFR_BLOCK_DATA, Entry);
   2897       ListEntry     = &BlockData->DefaultValueEntry;
   2898       for (LinkDefault = ListEntry->ForwardLink; LinkDefault != ListEntry; LinkDefault = LinkDefault->ForwardLink) {
   2899         DefaultValueData = BASE_CR (LinkDefault, IFR_DEFAULT_DATA, Entry);
   2900         if (DefaultValueData->DefaultId != DefaultId->DefaultId) {
   2901           continue;
   2902         }
   2903         if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {
   2904           //
   2905           // Add length for "&Name1=zzzzzzzzzzzz"
   2906           //                |1|Name|1|Value|
   2907           //
   2908           Length += (1 + StrLen (BlockData->Name) + 1 + BlockData->Width * 2);
   2909         } else {
   2910           //
   2911           // Add length for "&OFFSET=XXXX&WIDTH=YYYY&VALUE=zzzzzzzzzzzz"
   2912           //                |    8  | 4 |   7  | 4 |   7  | Width * 2 |
   2913           //
   2914           Length += (8 + 4 + 7 + 4 + 7 + BlockData->Width * 2);
   2915         }
   2916         DataExist = TRUE;
   2917       }
   2918     }
   2919   }
   2920 
   2921   //
   2922   // No default value is found. The default string doesn't exist.
   2923   //
   2924   if (!DataExist) {
   2925     return EFI_SUCCESS;
   2926   }
   2927 
   2928   //
   2929   // Allocate buffer for the entire <DefaultAltCfgResp>
   2930   //
   2931   *DefaultAltCfgResp = AllocateZeroPool (Length * sizeof (CHAR16));
   2932   if (*DefaultAltCfgResp == NULL) {
   2933     return EFI_OUT_OF_RESOURCES;
   2934   }
   2935   StringPtr = *DefaultAltCfgResp;
   2936 
   2937   //
   2938   // Start with <ConfigHdr>
   2939   //
   2940   StrCpyS (StringPtr, Length, ConfigHdr);
   2941   StringPtr += StrLen (StringPtr);
   2942 
   2943   for (Link = DefaultIdArray->Entry.ForwardLink; Link != &DefaultIdArray->Entry; Link = Link->ForwardLink) {
   2944     DefaultId = BASE_CR (Link, IFR_DEFAULT_DATA, Entry);
   2945     //
   2946     // Add <AltConfigHdr> of the form "&<ConfigHdr>&ALTCFG=XXXX\0"
   2947     //                                |1| StrLen (ConfigHdr) | 8 | 4 |
   2948     //
   2949     UnicodeSPrint (
   2950       StringPtr,
   2951       (1 + StrLen (ConfigHdr) + 8 + 4 + 1) * sizeof (CHAR16),
   2952       L"&%s&ALTCFG=%04X",
   2953       ConfigHdr,
   2954       DefaultId->DefaultId
   2955       );
   2956     StringPtr += StrLen (StringPtr);
   2957 
   2958     for (LinkData = VarStorageData->BlockEntry.ForwardLink; LinkData != &VarStorageData->BlockEntry; LinkData = LinkData->ForwardLink) {
   2959       BlockData = BASE_CR (LinkData, IFR_BLOCK_DATA, Entry);
   2960       ListEntry     = &BlockData->DefaultValueEntry;
   2961       for (LinkDefault = ListEntry->ForwardLink; LinkDefault != ListEntry; LinkDefault = LinkDefault->ForwardLink) {
   2962         DefaultValueData = BASE_CR (LinkDefault, IFR_DEFAULT_DATA, Entry);
   2963         if (DefaultValueData->DefaultId != DefaultId->DefaultId) {
   2964           continue;
   2965         }
   2966         if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {
   2967           UnicodeSPrint (
   2968             StringPtr,
   2969             (1 + StrLen (ConfigHdr) + 1) * sizeof (CHAR16),
   2970             L"&%s=",
   2971             BlockData->Name
   2972             );
   2973           StringPtr += StrLen (StringPtr);
   2974         } else {
   2975           //
   2976           // Add <BlockConfig>
   2977           // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>
   2978           //
   2979           UnicodeSPrint (
   2980             StringPtr,
   2981             (8 + 4 + 7 + 4 + 7 + 1) * sizeof (CHAR16),
   2982             L"&OFFSET=%04X&WIDTH=%04X&VALUE=",
   2983             BlockData->Offset,
   2984             BlockData->Width
   2985             );
   2986           StringPtr += StrLen (StringPtr);
   2987         }
   2988         Width = BlockData->Width;
   2989         //
   2990         // Convert Value to a hex string in "%x" format
   2991         // NOTE: This is in the opposite byte that GUID and PATH use
   2992         //
   2993         if (BlockData->OpCode == EFI_IFR_STRING_OP){
   2994           DefaultString   = InternalGetString(HiiHandle, DefaultValueData->Value.string);
   2995           TmpBuffer = (UINT8 *) DefaultString;
   2996         } else {
   2997           TmpBuffer = (UINT8 *) &(DefaultValueData->Value);
   2998         }
   2999         for (; Width > 0 && (TmpBuffer != NULL); Width--) {
   3000           StringPtr += UnicodeValueToString (StringPtr, PREFIX_ZERO | RADIX_HEX, TmpBuffer[Width - 1], 2);
   3001         }
   3002         if (DefaultString != NULL){
   3003           FreePool(DefaultString);
   3004           DefaultString = NULL;
   3005         }
   3006       }
   3007     }
   3008   }
   3009 
   3010   HiiToLower (*DefaultAltCfgResp);
   3011 
   3012   return EFI_SUCCESS;
   3013 }
   3014 
   3015 /**
   3016   This function gets the full request string and full default value string by
   3017   parsing IFR data in HII form packages.
   3018 
   3019   When Request points to NULL string, the request string and default value string
   3020   for each varstore in form package will return.
   3021 
   3022   @param  DataBaseRecord         The DataBaseRecord instance contains the found Hii handle and package.
   3023   @param  DevicePath             Device Path which Hii Config Access Protocol is registered.
   3024   @param  Request                Pointer to a null-terminated Unicode string in
   3025                                  <ConfigRequest> format. When it doesn't contain
   3026                                  any RequestElement, it will be updated to return
   3027                                  the full RequestElement retrieved from IFR data.
   3028                                  If it points to NULL, the request string for the first
   3029                                  varstore in form package will be merged into a
   3030                                  <MultiConfigRequest> format string and return.
   3031   @param  AltCfgResp             Pointer to a null-terminated Unicode string in
   3032                                  <ConfigAltResp> format. When the pointer is to NULL,
   3033                                  the full default value string retrieved from IFR data
   3034                                  will return. When the pinter is to a string, the
   3035                                  full default value string retrieved from IFR data
   3036                                  will be merged into the input string and return.
   3037                                  When Request points to NULL, the default value string
   3038                                  for each varstore in form package will be merged into
   3039                                  a <MultiConfigAltResp> format string and return.
   3040   @param  PointerProgress        Optional parameter, it can be be NULL.
   3041                                  When it is not NULL, if Request is NULL, it returns NULL.
   3042                                  On return, points to a character in the Request
   3043                                  string. Points to the string's null terminator if
   3044                                  request was successful. Points to the most recent
   3045                                  & before the first failing name / value pair (or
   3046                                  the beginning of the string if the failure is in
   3047                                  the first name / value pair) if the request was
   3048                                  not successful.
   3049   @retval EFI_SUCCESS            The Results string is set to the full request string.
   3050                                  And AltCfgResp contains all default value string.
   3051   @retval EFI_OUT_OF_RESOURCES   Not enough memory for the return string.
   3052   @retval EFI_NOT_FOUND          The varstore (Guid and Name) in Request string
   3053                                  can't be found in Form package.
   3054   @retval EFI_NOT_FOUND          HiiPackage can't be got on the input HiiHandle.
   3055   @retval EFI_INVALID_PARAMETER  Request points to NULL.
   3056 
   3057 **/
   3058 EFI_STATUS
   3059 EFIAPI
   3060 GetFullStringFromHiiFormPackages (
   3061   IN     HII_DATABASE_RECORD        *DataBaseRecord,
   3062   IN     EFI_DEVICE_PATH_PROTOCOL   *DevicePath,
   3063   IN OUT EFI_STRING                 *Request,
   3064   IN OUT EFI_STRING                 *AltCfgResp,
   3065   OUT    EFI_STRING                 *PointerProgress OPTIONAL
   3066   )
   3067 {
   3068   EFI_STATUS                   Status;
   3069   UINT8                        *HiiFormPackage;
   3070   UINTN                        PackageSize;
   3071   IFR_BLOCK_DATA               *RequestBlockArray;
   3072   IFR_BLOCK_DATA               *BlockData;
   3073   IFR_DEFAULT_DATA             *DefaultValueData;
   3074   IFR_DEFAULT_DATA             *DefaultId;
   3075   IFR_DEFAULT_DATA             *DefaultIdArray;
   3076   IFR_VARSTORAGE_DATA          *VarStorageData;
   3077   EFI_STRING                   DefaultAltCfgResp;
   3078   EFI_STRING                   ConfigHdr;
   3079   EFI_STRING                   StringPtr;
   3080   EFI_STRING                   Progress;
   3081 
   3082   if (DataBaseRecord == NULL || DevicePath == NULL || Request == NULL || AltCfgResp == NULL) {
   3083     return EFI_INVALID_PARAMETER;
   3084   }
   3085 
   3086   //
   3087   // Initialize the local variables.
   3088   //
   3089   RequestBlockArray = NULL;
   3090   DefaultIdArray    = NULL;
   3091   VarStorageData    = NULL;
   3092   DefaultAltCfgResp = NULL;
   3093   ConfigHdr         = NULL;
   3094   HiiFormPackage    = NULL;
   3095   PackageSize       = 0;
   3096   Progress          = *Request;
   3097 
   3098   Status = GetFormPackageData (DataBaseRecord, &HiiFormPackage, &PackageSize);
   3099   if (EFI_ERROR (Status)) {
   3100     goto Done;
   3101   }
   3102 
   3103   //
   3104   // 1. Get the request block array by Request String when Request string containts the block array.
   3105   //
   3106   StringPtr = NULL;
   3107   if (*Request != NULL) {
   3108     StringPtr = *Request;
   3109     //
   3110     // Jump <ConfigHdr>
   3111     //
   3112     if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {
   3113       Status   = EFI_INVALID_PARAMETER;
   3114       goto Done;
   3115     }
   3116     StringPtr += StrLen (L"GUID=");
   3117     while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&NAME=", StrLen (L"&NAME=")) != 0) {
   3118       StringPtr++;
   3119     }
   3120     if (*StringPtr == L'\0') {
   3121       Status = EFI_INVALID_PARAMETER;
   3122       goto Done;
   3123     }
   3124     StringPtr += StrLen (L"&NAME=");
   3125     while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&PATH=", StrLen (L"&PATH=")) != 0) {
   3126       StringPtr++;
   3127     }
   3128     if (*StringPtr == L'\0') {
   3129       Status = EFI_INVALID_PARAMETER;
   3130       goto Done;
   3131     }
   3132     StringPtr += StrLen (L"&PATH=");
   3133     while (*StringPtr != L'\0' && *StringPtr != L'&') {
   3134       StringPtr ++;
   3135     }
   3136 
   3137     if (*StringPtr == L'\0') {
   3138       //
   3139       // No request block is found.
   3140       //
   3141       StringPtr = NULL;
   3142     }
   3143   }
   3144 
   3145   //
   3146   // If StringPtr != NULL, get the request elements.
   3147   //
   3148   if (StringPtr != NULL) {
   3149     if (StrStr (StringPtr, L"&OFFSET=") != NULL) {
   3150       RequestBlockArray = GetBlockElement(StringPtr, &Progress);
   3151     } else {
   3152       RequestBlockArray = GetNameElement(StringPtr, &Progress);
   3153     }
   3154 
   3155     if (RequestBlockArray == NULL) {
   3156       Status = EFI_INVALID_PARAMETER;
   3157       goto Done;
   3158     }
   3159   }
   3160 
   3161   //
   3162   // Initialize DefaultIdArray to store the map between DeaultId and DefaultName
   3163   //
   3164   DefaultIdArray   = (IFR_DEFAULT_DATA *) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));
   3165   if (DefaultIdArray == NULL) {
   3166     Status = EFI_OUT_OF_RESOURCES;
   3167     goto Done;
   3168   }
   3169   InitializeListHead (&DefaultIdArray->Entry);
   3170 
   3171   //
   3172   // Initialize VarStorageData to store the var store Block and Default value information.
   3173   //
   3174   VarStorageData = (IFR_VARSTORAGE_DATA *) AllocateZeroPool (sizeof (IFR_VARSTORAGE_DATA));
   3175   if (VarStorageData == NULL) {
   3176     Status = EFI_OUT_OF_RESOURCES;
   3177     goto Done;
   3178   }
   3179   InitializeListHead (&VarStorageData->Entry);
   3180   InitializeListHead (&VarStorageData->BlockEntry);
   3181 
   3182   //
   3183   // 2. Parse FormPackage to get BlockArray and DefaultId Array for the request BlockArray.
   3184   //
   3185 
   3186   //
   3187   // Parse the opcode in form pacakge to get the default setting.
   3188   //
   3189   Status = ParseIfrData (DataBaseRecord->Handle,
   3190                          HiiFormPackage,
   3191                          (UINT32) PackageSize,
   3192                          *Request,
   3193                          RequestBlockArray,
   3194                          VarStorageData,
   3195                          DefaultIdArray);
   3196   if (EFI_ERROR (Status)) {
   3197     goto Done;
   3198   }
   3199 
   3200   //
   3201   // No requested varstore in IFR data and directly return
   3202   //
   3203   if (VarStorageData->Type == 0 && VarStorageData->Name == NULL) {
   3204     Status = EFI_SUCCESS;
   3205     goto Done;
   3206   }
   3207 
   3208   //
   3209   // 3. Construct Request Element (Block Name) for 2.1 and 2.2 case.
   3210   //
   3211   Status = GenerateHdr (VarStorageData, DevicePath, &ConfigHdr);
   3212   if (EFI_ERROR (Status)) {
   3213     goto Done;
   3214   }
   3215 
   3216   if (RequestBlockArray == NULL) {
   3217     if (!GenerateConfigRequest(ConfigHdr, VarStorageData, &Status, Request)) {
   3218       goto Done;
   3219     }
   3220   }
   3221 
   3222   //
   3223   // 4. Construct Default Value string in AltResp according to request element.
   3224   // Go through all VarStorageData Entry and get the DefaultId array for each one
   3225   // Then construct them all to : ConfigHdr AltConfigHdr ConfigBody AltConfigHdr ConfigBody
   3226   //
   3227   Status = GenerateAltConfigResp (DataBaseRecord->Handle,ConfigHdr, VarStorageData, DefaultIdArray, &DefaultAltCfgResp);
   3228   if (EFI_ERROR (Status)) {
   3229     goto Done;
   3230   }
   3231 
   3232   //
   3233   // 5. Merge string into the input AltCfgResp if the iput *AltCfgResp is not NULL.
   3234   //
   3235   if (*AltCfgResp != NULL && DefaultAltCfgResp != NULL) {
   3236     Status = MergeDefaultString (AltCfgResp, DefaultAltCfgResp);
   3237     FreePool (DefaultAltCfgResp);
   3238   } else if (*AltCfgResp == NULL) {
   3239     *AltCfgResp = DefaultAltCfgResp;
   3240   }
   3241 
   3242 Done:
   3243   if (RequestBlockArray != NULL) {
   3244     //
   3245     // Free Link Array RequestBlockArray
   3246     //
   3247     while (!IsListEmpty (&RequestBlockArray->Entry)) {
   3248       BlockData = BASE_CR (RequestBlockArray->Entry.ForwardLink, IFR_BLOCK_DATA, Entry);
   3249       RemoveEntryList (&BlockData->Entry);
   3250       if (BlockData->Name != NULL) {
   3251         FreePool (BlockData->Name);
   3252       }
   3253       FreePool (BlockData);
   3254     }
   3255 
   3256     FreePool (RequestBlockArray);
   3257   }
   3258 
   3259   if (VarStorageData != NULL) {
   3260     //
   3261     // Free link array VarStorageData
   3262     //
   3263     while (!IsListEmpty (&VarStorageData->BlockEntry)) {
   3264       BlockData = BASE_CR (VarStorageData->BlockEntry.ForwardLink, IFR_BLOCK_DATA, Entry);
   3265       RemoveEntryList (&BlockData->Entry);
   3266       if (BlockData->Name != NULL) {
   3267         FreePool (BlockData->Name);
   3268       }
   3269       //
   3270       // Free default value link array
   3271       //
   3272       while (!IsListEmpty (&BlockData->DefaultValueEntry)) {
   3273         DefaultValueData = BASE_CR (BlockData->DefaultValueEntry.ForwardLink, IFR_DEFAULT_DATA, Entry);
   3274         RemoveEntryList (&DefaultValueData->Entry);
   3275         FreePool (DefaultValueData);
   3276       }
   3277       FreePool (BlockData);
   3278     }
   3279     FreePool (VarStorageData);
   3280   }
   3281 
   3282   if (DefaultIdArray != NULL) {
   3283     //
   3284     // Free DefaultId Array
   3285     //
   3286     while (!IsListEmpty (&DefaultIdArray->Entry)) {
   3287       DefaultId = BASE_CR (DefaultIdArray->Entry.ForwardLink, IFR_DEFAULT_DATA, Entry);
   3288       RemoveEntryList (&DefaultId->Entry);
   3289       FreePool (DefaultId);
   3290     }
   3291     FreePool (DefaultIdArray);
   3292   }
   3293 
   3294   //
   3295   // Free the allocated string
   3296   //
   3297   if (ConfigHdr != NULL) {
   3298     FreePool (ConfigHdr);
   3299   }
   3300 
   3301   //
   3302   // Free Pacakge data
   3303   //
   3304   if (HiiFormPackage != NULL) {
   3305     FreePool (HiiFormPackage);
   3306   }
   3307 
   3308   if (PointerProgress != NULL) {
   3309     if (*Request == NULL) {
   3310       *PointerProgress = NULL;
   3311     } else if (EFI_ERROR (Status)) {
   3312       *PointerProgress = *Request;
   3313     } else {
   3314       *PointerProgress = *Request + StrLen (*Request);
   3315     }
   3316   }
   3317 
   3318   return Status;
   3319 }
   3320 
   3321 /**
   3322   This function gets the full request resp string by
   3323   parsing IFR data in HII form packages.
   3324 
   3325   @param  This                   A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
   3326                                  instance.
   3327   @param  EfiVarStoreInfo        The efi varstore info which is save in the EFI
   3328                                  varstore data structure.
   3329   @param  Request                Pointer to a null-terminated Unicode string in
   3330                                  <ConfigRequest> format.
   3331   @param  RequestResp            Pointer to a null-terminated Unicode string in
   3332                                  <ConfigResp> format.
   3333   @param  AccessProgress         On return, points to a character in the Request
   3334                                  string. Points to the string's null terminator if
   3335                                  request was successful. Points to the most recent
   3336                                  & before the first failing name / value pair (or
   3337                                  the beginning of the string if the failure is in
   3338                                  the first name / value pair) if the request was
   3339                                  not successful.
   3340 
   3341   @retval EFI_SUCCESS            The Results string is set to the full request string.
   3342                                  And AltCfgResp contains all default value string.
   3343   @retval EFI_OUT_OF_RESOURCES   Not enough memory for the return string.
   3344   @retval EFI_INVALID_PARAMETER  Request points to NULL.
   3345 
   3346 **/
   3347 EFI_STATUS
   3348 GetConfigRespFromEfiVarStore (
   3349   IN  CONST EFI_HII_CONFIG_ROUTING_PROTOCOL  *This,
   3350   IN  EFI_IFR_VARSTORE_EFI                   *EfiVarStoreInfo,
   3351   IN  EFI_STRING                             Request,
   3352   OUT EFI_STRING                             *RequestResp,
   3353   OUT EFI_STRING                             *AccessProgress
   3354   )
   3355 {
   3356   EFI_STATUS Status;
   3357   EFI_STRING VarStoreName;
   3358   UINT8      *VarStore;
   3359   UINTN      BufferSize;
   3360 
   3361   Status          = EFI_SUCCESS;
   3362   BufferSize      = 0;
   3363   VarStore        = NULL;
   3364   VarStoreName    = NULL;
   3365   *AccessProgress = Request;
   3366 
   3367   VarStoreName = AllocateZeroPool (AsciiStrSize ((CHAR8 *)EfiVarStoreInfo->Name) * sizeof (CHAR16));
   3368   if (VarStoreName == NULL) {
   3369     Status = EFI_OUT_OF_RESOURCES;
   3370     goto Done;
   3371   }
   3372   AsciiStrToUnicodeStr ((CHAR8 *) EfiVarStoreInfo->Name, VarStoreName);
   3373 
   3374 
   3375   Status = gRT->GetVariable (VarStoreName, &EfiVarStoreInfo->Guid, NULL, &BufferSize, NULL);
   3376   if (Status != EFI_BUFFER_TOO_SMALL) {
   3377     goto Done;
   3378   }
   3379 
   3380   VarStore = AllocateZeroPool (BufferSize);
   3381   ASSERT (VarStore != NULL);
   3382   Status = gRT->GetVariable (VarStoreName, &EfiVarStoreInfo->Guid, NULL, &BufferSize, VarStore);
   3383   if (EFI_ERROR (Status)) {
   3384     goto Done;
   3385   }
   3386 
   3387   Status = HiiBlockToConfig(This, Request, VarStore, BufferSize, RequestResp, AccessProgress);
   3388   if (EFI_ERROR (Status)) {
   3389     goto Done;
   3390   }
   3391 
   3392 Done:
   3393   if (VarStoreName != NULL) {
   3394     FreePool (VarStoreName);
   3395   }
   3396 
   3397   if (VarStore != NULL) {
   3398     FreePool (VarStore);
   3399   }
   3400 
   3401   return Status;
   3402 }
   3403 
   3404 
   3405 /**
   3406   This function route the full request resp string for efi varstore.
   3407 
   3408   @param  This                   A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
   3409                                  instance.
   3410   @param  EfiVarStoreInfo        The efi varstore info which is save in the EFI
   3411                                  varstore data structure.
   3412   @param  RequestResp            Pointer to a null-terminated Unicode string in
   3413                                  <ConfigResp> format.
   3414   @param  Result                 Pointer to a null-terminated Unicode string in
   3415                                  <ConfigResp> format.
   3416 
   3417   @retval EFI_SUCCESS            The Results string is set to the full request string.
   3418                                  And AltCfgResp contains all default value string.
   3419   @retval EFI_OUT_OF_RESOURCES   Not enough memory for the return string.
   3420   @retval EFI_INVALID_PARAMETER  Request points to NULL.
   3421 
   3422 **/
   3423 EFI_STATUS
   3424 RouteConfigRespForEfiVarStore (
   3425   IN  CONST EFI_HII_CONFIG_ROUTING_PROTOCOL  *This,
   3426   IN  EFI_IFR_VARSTORE_EFI                   *EfiVarStoreInfo,
   3427   IN  EFI_STRING                             RequestResp,
   3428   OUT EFI_STRING                             *Result
   3429   )
   3430 {
   3431   EFI_STATUS Status;
   3432   EFI_STRING VarStoreName;
   3433   UINT8      *VarStore;
   3434   UINTN      BufferSize;
   3435   UINTN      BlockSize;
   3436 
   3437   Status       = EFI_SUCCESS;
   3438   BufferSize   = 0;
   3439   VarStore     = NULL;
   3440   VarStoreName = NULL;
   3441 
   3442   VarStoreName = AllocateZeroPool (AsciiStrSize ((CHAR8 *)EfiVarStoreInfo->Name) * sizeof (CHAR16));
   3443   if (VarStoreName == NULL) {
   3444     Status = EFI_OUT_OF_RESOURCES;
   3445     goto Done;
   3446   }
   3447   AsciiStrToUnicodeStr ((CHAR8 *) EfiVarStoreInfo->Name, VarStoreName);
   3448 
   3449   Status = gRT->GetVariable (VarStoreName, &EfiVarStoreInfo->Guid, NULL, &BufferSize, NULL);
   3450   if (Status != EFI_BUFFER_TOO_SMALL) {
   3451     goto Done;
   3452   }
   3453 
   3454   BlockSize = BufferSize;
   3455   VarStore = AllocateZeroPool (BufferSize);
   3456   ASSERT (VarStore != NULL);
   3457   Status = gRT->GetVariable (VarStoreName, &EfiVarStoreInfo->Guid, NULL, &BufferSize, VarStore);
   3458   if (EFI_ERROR (Status)) {
   3459     goto Done;
   3460   }
   3461 
   3462   Status = HiiConfigToBlock(This, RequestResp, VarStore, &BlockSize, Result);
   3463   if (EFI_ERROR (Status)) {
   3464     goto Done;
   3465   }
   3466 
   3467   Status = gRT->SetVariable (VarStoreName, &EfiVarStoreInfo->Guid, EfiVarStoreInfo->Attributes, BufferSize, VarStore);
   3468   if (EFI_ERROR (Status)) {
   3469     goto Done;
   3470   }
   3471 
   3472 Done:
   3473   if (VarStoreName != NULL) {
   3474     FreePool (VarStoreName);
   3475   }
   3476 
   3477   if (VarStore != NULL) {
   3478     FreePool (VarStore);
   3479   }
   3480 
   3481   return Status;
   3482 }
   3483 
   3484 /**
   3485   Validate the config request elements.
   3486 
   3487   @param  ConfigElements                A null-terminated Unicode string in <ConfigRequest> format,
   3488                                         without configHdr field.
   3489 
   3490   @retval     CHAR16 *    THE first Name/value pair not correct.
   3491   @retval     NULL        Success parse the name/value pair
   3492 **/
   3493 CHAR16 *
   3494 OffsetWidthValidate (
   3495   CHAR16          *ConfigElements
   3496   )
   3497 {
   3498   CHAR16    *StringPtr;
   3499   CHAR16    *RetVal;
   3500 
   3501   StringPtr = ConfigElements;
   3502 
   3503   while (1) {
   3504     RetVal    = StringPtr;
   3505     if (StrnCmp (StringPtr, L"&OFFSET=", StrLen (L"&OFFSET=")) != 0) {
   3506       return RetVal;
   3507     }
   3508 
   3509     while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {
   3510       StringPtr++;
   3511     }
   3512     if (*StringPtr == L'\0') {
   3513       return RetVal;
   3514     }
   3515 
   3516     StringPtr += StrLen (L"&WIDTH=");
   3517     while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&OFFSET=", StrLen (L"&OFFSET=")) != 0) {
   3518       StringPtr ++;
   3519     }
   3520 
   3521     if (*StringPtr == L'\0') {
   3522       return NULL;
   3523     }
   3524   }
   3525 }
   3526 
   3527 /**
   3528   Validate the config request elements.
   3529 
   3530   @param  ConfigElements                A null-terminated Unicode string in <ConfigRequest> format,
   3531                                         without configHdr field.
   3532 
   3533   @retval     CHAR16 *    THE first Name/value pair not correct.
   3534   @retval     NULL        Success parse the name/value pair
   3535 
   3536 **/
   3537 CHAR16 *
   3538 NameValueValidate (
   3539   CHAR16          *ConfigElements
   3540   )
   3541 {
   3542   CHAR16    *StringPtr;
   3543   CHAR16    *RetVal;
   3544 
   3545   StringPtr = ConfigElements;
   3546 
   3547   while (1) {
   3548     RetVal = StringPtr;
   3549     if (*StringPtr != L'&') {
   3550       return RetVal;
   3551     }
   3552     StringPtr += 1;
   3553 
   3554     StringPtr = StrStr (StringPtr, L"&");
   3555 
   3556     if (StringPtr == NULL) {
   3557       return NULL;
   3558     }
   3559   }
   3560 }
   3561 
   3562 /**
   3563   Validate the config request string.
   3564 
   3565   @param  ConfigRequest                A null-terminated Unicode string in <ConfigRequest> format.
   3566 
   3567   @retval     CHAR16 *    THE first element not correct.
   3568   @retval     NULL        Success parse the name/value pair
   3569 
   3570 **/
   3571 CHAR16 *
   3572 ConfigRequestValidate (
   3573   CHAR16          *ConfigRequest
   3574   )
   3575 {
   3576   BOOLEAN            HasNameField;
   3577   CHAR16             *StringPtr;
   3578 
   3579   HasNameField = TRUE;
   3580   StringPtr    = ConfigRequest;
   3581 
   3582   //
   3583   // Check <ConfigHdr>
   3584   //
   3585   if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {
   3586     return ConfigRequest;
   3587   }
   3588   StringPtr += StrLen (L"GUID=");
   3589   while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&NAME=", StrLen (L"&NAME=")) != 0) {
   3590     StringPtr++;
   3591   }
   3592   if (*StringPtr == L'\0') {
   3593     return ConfigRequest;
   3594   }
   3595   StringPtr += StrLen (L"&NAME=");
   3596   if (*StringPtr == L'&') {
   3597     HasNameField = FALSE;
   3598   }
   3599   while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&PATH=", StrLen (L"&PATH=")) != 0) {
   3600     StringPtr++;
   3601   }
   3602   if (*StringPtr == L'\0') {
   3603     return ConfigRequest;
   3604   }
   3605   StringPtr += StrLen (L"&PATH=");
   3606   while (*StringPtr != L'\0' && *StringPtr != L'&') {
   3607     StringPtr ++;
   3608   }
   3609 
   3610   if (*StringPtr == L'\0') {
   3611     return NULL;
   3612   }
   3613 
   3614   if (HasNameField) {
   3615     //
   3616     // Should be Buffer varstore, config request should be "OFFSET/Width" pairs.
   3617     //
   3618     return OffsetWidthValidate(StringPtr);
   3619   } else {
   3620     //
   3621     // Should be Name/Value varstore, config request should be "&name1&name2..." pairs.
   3622     //
   3623     return NameValueValidate(StringPtr);
   3624   }
   3625 }
   3626 
   3627 /**
   3628   This function allows a caller to extract the current configuration
   3629   for one or more named elements from one or more drivers.
   3630 
   3631   @param  This                   A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
   3632                                  instance.
   3633   @param  Request                A null-terminated Unicode string in
   3634                                  <MultiConfigRequest> format.
   3635   @param  Progress               On return, points to a character in the Request
   3636                                  string. Points to the string's null terminator if
   3637                                  request was successful. Points to the most recent
   3638                                  & before the first failing name / value pair (or
   3639                                  the beginning of the string if the failure is in
   3640                                  the first name / value pair) if the request was
   3641                                  not successful.
   3642   @param  Results                Null-terminated Unicode string in
   3643                                  <MultiConfigAltResp> format which has all values
   3644                                  filled in for the names in the Request string.
   3645                                  String to be allocated by the called function.
   3646 
   3647   @retval EFI_SUCCESS            The Results string is filled with the values
   3648                                  corresponding to all requested names.
   3649   @retval EFI_OUT_OF_RESOURCES   Not enough memory to store the parts of the
   3650                                  results that must be stored awaiting possible
   3651                                  future        protocols.
   3652   @retval EFI_NOT_FOUND          Routing data doesn't match any known driver.
   3653                                    Progress set to the "G" in "GUID" of the routing
   3654                                   header that doesn't match. Note: There is no
   3655                                     requirement that all routing data be validated
   3656                                  before any configuration extraction.
   3657   @retval EFI_INVALID_PARAMETER  For example, passing in a NULL for the Request
   3658                                  parameter would result in this type of error. The
   3659                                  Progress parameter is set to NULL.
   3660   @retval EFI_INVALID_PARAMETER  Illegal syntax. Progress set to most recent &
   3661                                  before the error or the beginning of the string.
   3662   @retval EFI_INVALID_PARAMETER  The ExtractConfig function of the underlying HII
   3663                                  Configuration Access Protocol returned
   3664                                  EFI_INVALID_PARAMETER. Progress set to most recent
   3665                                  & before the error or the beginning of the string.
   3666 
   3667 **/
   3668 EFI_STATUS
   3669 EFIAPI
   3670 HiiConfigRoutingExtractConfig (
   3671   IN  CONST EFI_HII_CONFIG_ROUTING_PROTOCOL  *This,
   3672   IN  CONST EFI_STRING                       Request,
   3673   OUT EFI_STRING                             *Progress,
   3674   OUT EFI_STRING                             *Results
   3675   )
   3676 {
   3677   HII_DATABASE_PRIVATE_DATA           *Private;
   3678   EFI_STRING                          StringPtr;
   3679   EFI_STRING                          ConfigRequest;
   3680   UINTN                               Length;
   3681   EFI_DEVICE_PATH_PROTOCOL            *DevicePath;
   3682   EFI_DEVICE_PATH_PROTOCOL            *TempDevicePath;
   3683   EFI_STATUS                          Status;
   3684   LIST_ENTRY                          *Link;
   3685   HII_DATABASE_RECORD                 *Database;
   3686   UINT8                               *DevicePathPkg;
   3687   UINT8                               *CurrentDevicePath;
   3688   EFI_HANDLE                          DriverHandle;
   3689   EFI_HII_HANDLE                      HiiHandle;
   3690   EFI_HII_CONFIG_ACCESS_PROTOCOL      *ConfigAccess;
   3691   EFI_STRING                          AccessProgress;
   3692   EFI_STRING                          AccessResults;
   3693   EFI_STRING                          DefaultResults;
   3694   BOOLEAN                             FirstElement;
   3695   BOOLEAN                             IfrDataParsedFlag;
   3696   BOOLEAN                             IsEfiVarStore;
   3697   EFI_IFR_VARSTORE_EFI                *EfiVarStoreInfo;
   3698   EFI_STRING                          ErrorPtr;
   3699   UINTN                               DevicePathSize;
   3700 
   3701   if (This == NULL || Progress == NULL || Results == NULL) {
   3702     return EFI_INVALID_PARAMETER;
   3703   }
   3704 
   3705   if (Request == NULL) {
   3706     *Progress = NULL;
   3707     return EFI_INVALID_PARAMETER;
   3708   }
   3709 
   3710   Private   = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);
   3711   StringPtr = Request;
   3712   *Progress = StringPtr;
   3713   DefaultResults = NULL;
   3714   ConfigRequest  = NULL;
   3715   Status         = EFI_SUCCESS;
   3716   AccessResults  = NULL;
   3717   AccessProgress = NULL;
   3718   DevicePath     = NULL;
   3719   IfrDataParsedFlag = FALSE;
   3720   IsEfiVarStore     = FALSE;
   3721   EfiVarStoreInfo   = NULL;
   3722 
   3723   //
   3724   // The first element of <MultiConfigRequest> should be
   3725   // <GuidHdr>, which is in 'GUID='<Guid> syntax.
   3726   //
   3727   if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {
   3728     return EFI_INVALID_PARAMETER;
   3729   }
   3730 
   3731   FirstElement = TRUE;
   3732 
   3733   //
   3734   // Allocate a fix length of memory to store Results. Reallocate memory for
   3735   // Results if this fix length is insufficient.
   3736   //
   3737   *Results = (EFI_STRING) AllocateZeroPool (MAX_STRING_LENGTH);
   3738   if (*Results == NULL) {
   3739     return EFI_OUT_OF_RESOURCES;
   3740   }
   3741 
   3742   while (*StringPtr != 0 && StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) == 0) {
   3743     //
   3744     // If parsing error, set Progress to the beginning of the <MultiConfigRequest>
   3745     // or most recent & before the error.
   3746     //
   3747     if (StringPtr == Request) {
   3748       *Progress = StringPtr;
   3749     } else {
   3750       *Progress = StringPtr - 1;
   3751     }
   3752 
   3753     //
   3754     // Process each <ConfigRequest> of <MultiConfigRequest>
   3755     //
   3756     Length = CalculateConfigStringLen (StringPtr);
   3757     ConfigRequest = AllocateCopyPool ((Length + 1) * sizeof (CHAR16), StringPtr);
   3758     if (ConfigRequest == NULL) {
   3759       Status = EFI_OUT_OF_RESOURCES;
   3760       goto Done;
   3761     }
   3762     *(ConfigRequest + Length) = 0;
   3763 
   3764     //
   3765     // Get the UEFI device path
   3766     //
   3767     Status = GetDevicePath (ConfigRequest, (UINT8 **) &DevicePath);
   3768     if (EFI_ERROR (Status)) {
   3769       goto Done;
   3770     }
   3771 
   3772     //
   3773     // Find driver which matches the routing data.
   3774     //
   3775     DriverHandle     = NULL;
   3776     HiiHandle        = NULL;
   3777     Database         = NULL;
   3778     for (Link = Private->DatabaseList.ForwardLink;
   3779          Link != &Private->DatabaseList;
   3780          Link = Link->ForwardLink
   3781         ) {
   3782       Database = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
   3783       if ((DevicePathPkg = Database->PackageList->DevicePathPkg) != NULL) {
   3784         CurrentDevicePath = DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);
   3785         DevicePathSize    = GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) CurrentDevicePath);
   3786         if ((CompareMem (DevicePath,CurrentDevicePath,DevicePathSize) == 0) && IsThisPackageList(Database, ConfigRequest)) {
   3787           DriverHandle = Database->DriverHandle;
   3788           HiiHandle    = Database->Handle;
   3789           break;
   3790         }
   3791       }
   3792     }
   3793 
   3794     //
   3795     // Try to find driver handle by device path.
   3796     //
   3797     if (DriverHandle == NULL) {
   3798       TempDevicePath = DevicePath;
   3799       Status = gBS->LocateDevicePath (
   3800                       &gEfiDevicePathProtocolGuid,
   3801                       &TempDevicePath,
   3802                       &DriverHandle
   3803                       );
   3804       if (EFI_ERROR (Status) || (DriverHandle == NULL)) {
   3805         //
   3806         // Routing data does not match any known driver.
   3807         // Set Progress to the 'G' in "GUID" of the routing header.
   3808         //
   3809         *Progress = StringPtr;
   3810         Status = EFI_NOT_FOUND;
   3811         goto Done;
   3812       }
   3813     }
   3814 
   3815     //
   3816     // Validate ConfigRequest String.
   3817     //
   3818     ErrorPtr = ConfigRequestValidate(ConfigRequest);
   3819     if (ErrorPtr != NULL) {
   3820       *Progress = StrStr (StringPtr, ErrorPtr);
   3821       Status = EFI_INVALID_PARAMETER;
   3822       goto Done;
   3823     }
   3824 
   3825     //
   3826     // Check whether ConfigRequest contains request string.
   3827     //
   3828     IfrDataParsedFlag = FALSE;
   3829     if ((HiiHandle != NULL) && !GetElementsFromRequest(ConfigRequest)) {
   3830       //
   3831       // Get the full request string from IFR when HiiPackage is registered to HiiHandle
   3832       //
   3833       IfrDataParsedFlag = TRUE;
   3834       Status = GetFullStringFromHiiFormPackages (Database, DevicePath, &ConfigRequest, &DefaultResults, &AccessProgress);
   3835       if (EFI_ERROR (Status)) {
   3836         //
   3837         // AccessProgress indicates the parsing progress on <ConfigRequest>.
   3838         // Map it to the progress on <MultiConfigRequest> then return it.
   3839         //
   3840         ASSERT (AccessProgress != NULL);
   3841         *Progress = StrStr (StringPtr, AccessProgress);
   3842         goto Done;
   3843       }
   3844       //
   3845       // Not any request block is found.
   3846       //
   3847       if (!GetElementsFromRequest(ConfigRequest)) {
   3848         AccessResults = AllocateCopyPool (StrSize (ConfigRequest), ConfigRequest);
   3849         goto NextConfigString;
   3850       }
   3851     }
   3852 
   3853     //
   3854     // Check whether this ConfigRequest is search from Efi varstore type storage.
   3855     //
   3856     Status = GetVarStoreType(Database, ConfigRequest, &IsEfiVarStore, &EfiVarStoreInfo);
   3857     if (EFI_ERROR (Status)) {
   3858       goto Done;
   3859     }
   3860 
   3861     if (IsEfiVarStore) {
   3862       //
   3863       // Call the GetVariable function to extract settings.
   3864       //
   3865       Status = GetConfigRespFromEfiVarStore(This, EfiVarStoreInfo, ConfigRequest, &AccessResults, &AccessProgress);
   3866       FreePool (EfiVarStoreInfo);
   3867     } else {
   3868       //
   3869       // Call corresponding ConfigAccess protocol to extract settings
   3870       //
   3871       Status = gBS->HandleProtocol (
   3872                       DriverHandle,
   3873                       &gEfiHiiConfigAccessProtocolGuid,
   3874                       (VOID **) &ConfigAccess
   3875                       );
   3876       if (EFI_ERROR (Status)) {
   3877         goto Done;
   3878       }
   3879 
   3880       Status = ConfigAccess->ExtractConfig (
   3881                                ConfigAccess,
   3882                                ConfigRequest,
   3883                                &AccessProgress,
   3884                                &AccessResults
   3885                                );
   3886     }
   3887     if (EFI_ERROR (Status)) {
   3888       //
   3889       // AccessProgress indicates the parsing progress on <ConfigRequest>.
   3890       // Map it to the progress on <MultiConfigRequest> then return it.
   3891       //
   3892       *Progress = StrStr (StringPtr, AccessProgress);
   3893       goto Done;
   3894     }
   3895 
   3896     //
   3897     // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'
   3898     // which seperates the first <ConfigAltResp> and the following ones.
   3899     //
   3900     ASSERT (*AccessProgress == 0);
   3901 
   3902     //
   3903     // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
   3904     //
   3905     if (!IfrDataParsedFlag && HiiHandle != NULL) {
   3906       Status = GetFullStringFromHiiFormPackages (Database, DevicePath, &ConfigRequest, &DefaultResults, NULL);
   3907       ASSERT_EFI_ERROR (Status);
   3908     }
   3909 
   3910     FreePool (DevicePath);
   3911     DevicePath = NULL;
   3912 
   3913     if (DefaultResults != NULL) {
   3914       Status = MergeDefaultString (&AccessResults, DefaultResults);
   3915       ASSERT_EFI_ERROR (Status);
   3916       FreePool (DefaultResults);
   3917       DefaultResults = NULL;
   3918     }
   3919 
   3920 NextConfigString:
   3921     if (!FirstElement) {
   3922       Status = AppendToMultiString (Results, L"&");
   3923       ASSERT_EFI_ERROR (Status);
   3924     }
   3925 
   3926     Status = AppendToMultiString (Results, AccessResults);
   3927     ASSERT_EFI_ERROR (Status);
   3928 
   3929     FirstElement = FALSE;
   3930 
   3931     FreePool (AccessResults);
   3932     AccessResults = NULL;
   3933     FreePool (ConfigRequest);
   3934     ConfigRequest = NULL;
   3935 
   3936     //
   3937     // Go to next <ConfigRequest> (skip '&').
   3938     //
   3939     StringPtr += Length;
   3940     if (*StringPtr == 0) {
   3941       *Progress = StringPtr;
   3942       break;
   3943     }
   3944 
   3945     StringPtr++;
   3946   }
   3947 
   3948 Done:
   3949   if (EFI_ERROR (Status)) {
   3950     FreePool (*Results);
   3951     *Results = NULL;
   3952   }
   3953 
   3954   if (ConfigRequest != NULL) {
   3955     FreePool (ConfigRequest);
   3956   }
   3957 
   3958   if (AccessResults != NULL) {
   3959     FreePool (AccessResults);
   3960   }
   3961 
   3962   if (DefaultResults != NULL) {
   3963     FreePool (DefaultResults);
   3964   }
   3965 
   3966   if (DevicePath != NULL) {
   3967     FreePool (DevicePath);
   3968   }
   3969 
   3970   return Status;
   3971 }
   3972 
   3973 
   3974 /**
   3975   This function allows the caller to request the current configuration for the
   3976   entirety of the current HII database and returns the data in a
   3977   null-terminated Unicode string.
   3978 
   3979   @param  This                   A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
   3980                                  instance.
   3981   @param  Results                Null-terminated Unicode string in
   3982                                  <MultiConfigAltResp> format which has all values
   3983                                  filled in for the entirety of the current HII
   3984                                  database. String to be allocated by the  called
   3985                                  function. De-allocation is up to the caller.
   3986 
   3987   @retval EFI_SUCCESS            The Results string is filled with the values
   3988                                  corresponding to all requested names.
   3989   @retval EFI_OUT_OF_RESOURCES   Not enough memory to store the parts of the
   3990                                  results that must be stored awaiting possible
   3991                                  future        protocols.
   3992   @retval EFI_INVALID_PARAMETER  For example, passing in a NULL for the Results
   3993                                  parameter would result in this type of error.
   3994 
   3995 **/
   3996 EFI_STATUS
   3997 EFIAPI
   3998 HiiConfigRoutingExportConfig (
   3999   IN  CONST EFI_HII_CONFIG_ROUTING_PROTOCOL  *This,
   4000   OUT EFI_STRING                             *Results
   4001   )
   4002 {
   4003   EFI_STATUS                          Status;
   4004   EFI_HII_CONFIG_ACCESS_PROTOCOL      *ConfigAccess;
   4005   EFI_STRING                          AccessResults;
   4006   EFI_STRING                          Progress;
   4007   EFI_STRING                          StringPtr;
   4008   EFI_STRING                          ConfigRequest;
   4009   UINTN                               Index;
   4010   EFI_HANDLE                          *ConfigAccessHandles;
   4011   UINTN                               NumberConfigAccessHandles;
   4012   BOOLEAN                             FirstElement;
   4013   EFI_DEVICE_PATH_PROTOCOL            *DevicePath;
   4014   EFI_HII_HANDLE                      HiiHandle;
   4015   EFI_STRING                          DefaultResults;
   4016   HII_DATABASE_PRIVATE_DATA           *Private;
   4017   LIST_ENTRY                          *Link;
   4018   HII_DATABASE_RECORD                 *Database;
   4019   UINT8                               *DevicePathPkg;
   4020   UINT8                               *CurrentDevicePath;
   4021   BOOLEAN                             IfrDataParsedFlag;
   4022 
   4023   if (This == NULL || Results == NULL) {
   4024     return EFI_INVALID_PARAMETER;
   4025   }
   4026 
   4027   Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);
   4028 
   4029   //
   4030   // Allocate a fix length of memory to store Results. Reallocate memory for
   4031   // Results if this fix length is insufficient.
   4032   //
   4033   *Results = (EFI_STRING) AllocateZeroPool (MAX_STRING_LENGTH);
   4034   if (*Results == NULL) {
   4035     return EFI_OUT_OF_RESOURCES;
   4036   }
   4037 
   4038   NumberConfigAccessHandles = 0;
   4039   Status = gBS->LocateHandleBuffer (
   4040              ByProtocol,
   4041              &gEfiHiiConfigAccessProtocolGuid,
   4042              NULL,
   4043              &NumberConfigAccessHandles,
   4044              &ConfigAccessHandles
   4045              );
   4046   if (EFI_ERROR (Status)) {
   4047     return Status;
   4048   }
   4049 
   4050   FirstElement = TRUE;
   4051 
   4052   for (Index = 0; Index < NumberConfigAccessHandles; Index++) {
   4053     Status = gBS->HandleProtocol (
   4054                     ConfigAccessHandles[Index],
   4055                     &gEfiHiiConfigAccessProtocolGuid,
   4056                     (VOID **) &ConfigAccess
   4057                     );
   4058     if (EFI_ERROR (Status)) {
   4059       continue;
   4060     }
   4061 
   4062     //
   4063     // Get DevicePath and HiiHandle for this ConfigAccess driver handle
   4064     //
   4065     IfrDataParsedFlag = FALSE;
   4066     Progress         = NULL;
   4067     HiiHandle        = NULL;
   4068     DefaultResults   = NULL;
   4069     Database         = NULL;
   4070     ConfigRequest    = NULL;
   4071     DevicePath       = DevicePathFromHandle (ConfigAccessHandles[Index]);
   4072     if (DevicePath != NULL) {
   4073       for (Link = Private->DatabaseList.ForwardLink;
   4074            Link != &Private->DatabaseList;
   4075            Link = Link->ForwardLink
   4076           ) {
   4077         Database = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
   4078         if ((DevicePathPkg = Database->PackageList->DevicePathPkg) != NULL) {
   4079           CurrentDevicePath = DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);
   4080           if (CompareMem (
   4081                 DevicePath,
   4082                 CurrentDevicePath,
   4083                 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) CurrentDevicePath)
   4084                 ) == 0) {
   4085             HiiHandle = Database->Handle;
   4086             break;
   4087           }
   4088         }
   4089       }
   4090     }
   4091 
   4092     Status = ConfigAccess->ExtractConfig (
   4093                              ConfigAccess,
   4094                              NULL,
   4095                              &Progress,
   4096                              &AccessResults
   4097                              );
   4098     if (EFI_ERROR (Status)) {
   4099       //
   4100       // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
   4101       //
   4102       if (HiiHandle != NULL && DevicePath != NULL) {
   4103         IfrDataParsedFlag = TRUE;
   4104         Status = GetFullStringFromHiiFormPackages (Database, DevicePath, &ConfigRequest, &DefaultResults, NULL);
   4105         //
   4106         // Get the full request string to get the Current setting again.
   4107         //
   4108         if (!EFI_ERROR (Status) && ConfigRequest != NULL) {
   4109           Status = ConfigAccess->ExtractConfig (
   4110                                    ConfigAccess,
   4111                                    ConfigRequest,
   4112                                    &Progress,
   4113                                    &AccessResults
   4114                                    );
   4115           FreePool (ConfigRequest);
   4116         } else {
   4117           Status = EFI_NOT_FOUND;
   4118         }
   4119       }
   4120     }
   4121 
   4122     if (!EFI_ERROR (Status)) {
   4123       //
   4124       // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
   4125       //
   4126       if (!IfrDataParsedFlag && HiiHandle != NULL && DevicePath != NULL) {
   4127         StringPtr = StrStr (AccessResults, L"&GUID=");
   4128         if (StringPtr != NULL) {
   4129           *StringPtr = 0;
   4130         }
   4131         if (GetElementsFromRequest (AccessResults)) {
   4132           Status = GetFullStringFromHiiFormPackages (Database, DevicePath, &AccessResults, &DefaultResults, NULL);
   4133           ASSERT_EFI_ERROR (Status);
   4134         }
   4135         if (StringPtr != NULL) {
   4136           *StringPtr = L'&';
   4137         }
   4138       }
   4139       //
   4140       // Merge the default sting from IFR code into the got setting from driver.
   4141       //
   4142       if (DefaultResults != NULL) {
   4143         Status = MergeDefaultString (&AccessResults, DefaultResults);
   4144         ASSERT_EFI_ERROR (Status);
   4145         FreePool (DefaultResults);
   4146         DefaultResults = NULL;
   4147       }
   4148 
   4149       //
   4150       // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'
   4151       // which seperates the first <ConfigAltResp> and the following ones.
   4152       //
   4153       if (!FirstElement) {
   4154         Status = AppendToMultiString (Results, L"&");
   4155         ASSERT_EFI_ERROR (Status);
   4156       }
   4157 
   4158       Status = AppendToMultiString (Results, AccessResults);
   4159       ASSERT_EFI_ERROR (Status);
   4160 
   4161       FirstElement = FALSE;
   4162 
   4163       FreePool (AccessResults);
   4164       AccessResults = NULL;
   4165     }
   4166   }
   4167   FreePool (ConfigAccessHandles);
   4168 
   4169   return EFI_SUCCESS;
   4170 }
   4171 
   4172 
   4173 /**
   4174   This function processes the results of processing forms and routes it to the
   4175   appropriate handlers or storage.
   4176 
   4177   @param  This                   A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
   4178                                  instance.
   4179   @param  Configuration          A null-terminated Unicode string in
   4180                                  <MulltiConfigResp> format.
   4181   @param  Progress               A pointer to a string filled in with the offset of
   4182                                  the most recent & before the first failing name /
   4183                                  value pair (or the beginning of the string if the
   4184                                  failure is in the first name / value pair) or the
   4185                                  terminating NULL if all was successful.
   4186 
   4187   @retval EFI_SUCCESS            The results have been distributed or are awaiting
   4188                                  distribution.
   4189   @retval EFI_OUT_OF_RESOURCES   Not enough memory to store the parts of the
   4190                                  results that must be stored awaiting possible
   4191                                  future        protocols.
   4192   @retval EFI_INVALID_PARAMETER  Passing in a NULL for the Configuration parameter
   4193                                  would result in this type of error.
   4194   @retval EFI_NOT_FOUND          Target for the specified routing data was not
   4195                                  found.
   4196 
   4197 **/
   4198 EFI_STATUS
   4199 EFIAPI
   4200 HiiConfigRoutingRouteConfig (
   4201   IN  CONST EFI_HII_CONFIG_ROUTING_PROTOCOL  *This,
   4202   IN  CONST EFI_STRING                       Configuration,
   4203   OUT EFI_STRING                             *Progress
   4204   )
   4205 {
   4206   HII_DATABASE_PRIVATE_DATA           *Private;
   4207   EFI_STRING                          StringPtr;
   4208   EFI_STRING                          ConfigResp;
   4209   UINTN                               Length;
   4210   EFI_STATUS                          Status;
   4211   EFI_DEVICE_PATH_PROTOCOL            *DevicePath;
   4212   EFI_DEVICE_PATH_PROTOCOL            *TempDevicePath;
   4213   LIST_ENTRY                          *Link;
   4214   HII_DATABASE_RECORD                 *Database;
   4215   UINT8                               *DevicePathPkg;
   4216   UINT8                               *CurrentDevicePath;
   4217   EFI_HANDLE                          DriverHandle;
   4218   EFI_HII_CONFIG_ACCESS_PROTOCOL      *ConfigAccess;
   4219   EFI_STRING                          AccessProgress;
   4220   EFI_IFR_VARSTORE_EFI                *EfiVarStoreInfo;
   4221   BOOLEAN                             IsEfiVarstore;
   4222   UINTN                               DevicePathSize;
   4223 
   4224   if (This == NULL || Progress == NULL) {
   4225     return EFI_INVALID_PARAMETER;
   4226   }
   4227 
   4228   if (Configuration == NULL) {
   4229     *Progress = NULL;
   4230     return EFI_INVALID_PARAMETER;
   4231   }
   4232 
   4233   Private   = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);
   4234   StringPtr = Configuration;
   4235   *Progress = StringPtr;
   4236   Database       = NULL;
   4237   AccessProgress = NULL;
   4238   EfiVarStoreInfo= NULL;
   4239   IsEfiVarstore  = FALSE;
   4240 
   4241   //
   4242   // The first element of <MultiConfigResp> should be
   4243   // <GuidHdr>, which is in 'GUID='<Guid> syntax.
   4244   //
   4245   if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {
   4246     return EFI_INVALID_PARAMETER;
   4247   }
   4248 
   4249   while (*StringPtr != 0 && StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) == 0) {
   4250     //
   4251     // If parsing error, set Progress to the beginning of the <MultiConfigResp>
   4252     // or most recent & before the error.
   4253     //
   4254     if (StringPtr == Configuration) {
   4255       *Progress = StringPtr;
   4256     } else {
   4257       *Progress = StringPtr - 1;
   4258     }
   4259 
   4260     //
   4261     // Process each <ConfigResp> of <MultiConfigResp>
   4262     //
   4263     Length = CalculateConfigStringLen (StringPtr);
   4264     ConfigResp = AllocateCopyPool ((Length + 1) * sizeof (CHAR16), StringPtr);
   4265     if (ConfigResp == NULL) {
   4266       return EFI_OUT_OF_RESOURCES;
   4267     }
   4268     //
   4269     // Append '\0' to the end of ConfigRequest
   4270     //
   4271     *(ConfigResp + Length) = 0;
   4272 
   4273     //
   4274     // Get the UEFI device path
   4275     //
   4276     Status = GetDevicePath (ConfigResp, (UINT8 **) &DevicePath);
   4277     if (EFI_ERROR (Status)) {
   4278       FreePool (ConfigResp);
   4279       return Status;
   4280     }
   4281 
   4282     //
   4283     // Find driver which matches the routing data.
   4284     //
   4285     DriverHandle     = NULL;
   4286     for (Link = Private->DatabaseList.ForwardLink;
   4287          Link != &Private->DatabaseList;
   4288          Link = Link->ForwardLink
   4289         ) {
   4290       Database = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
   4291 
   4292       if ((DevicePathPkg = Database->PackageList->DevicePathPkg) != NULL) {
   4293         CurrentDevicePath = DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);
   4294         DevicePathSize    = GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) CurrentDevicePath);
   4295         if ((CompareMem (DevicePath,CurrentDevicePath,DevicePathSize) == 0) && IsThisPackageList(Database, ConfigResp)) {
   4296           DriverHandle = Database->DriverHandle;
   4297           break;
   4298         }
   4299       }
   4300     }
   4301 
   4302     //
   4303     // Try to find driver handle by device path.
   4304     //
   4305     if (DriverHandle == NULL) {
   4306       TempDevicePath = DevicePath;
   4307       Status = gBS->LocateDevicePath (
   4308                       &gEfiDevicePathProtocolGuid,
   4309                       &TempDevicePath,
   4310                       &DriverHandle
   4311                       );
   4312       if (EFI_ERROR (Status) || (DriverHandle == NULL)) {
   4313         //
   4314         // Routing data does not match any known driver.
   4315         // Set Progress to the 'G' in "GUID" of the routing header.
   4316         //
   4317         FreePool (DevicePath);
   4318         *Progress = StringPtr;
   4319         FreePool (ConfigResp);
   4320         return EFI_NOT_FOUND;
   4321       }
   4322     }
   4323 
   4324     FreePool (DevicePath);
   4325 
   4326     //
   4327     // Check whether this ConfigRequest is search from Efi varstore type storage.
   4328     //
   4329     Status = GetVarStoreType(Database, ConfigResp, &IsEfiVarstore, &EfiVarStoreInfo);
   4330     if (EFI_ERROR (Status)) {
   4331       return Status;
   4332     }
   4333 
   4334     if (IsEfiVarstore) {
   4335       //
   4336       // Call the SetVariable function to route settings.
   4337       //
   4338       Status = RouteConfigRespForEfiVarStore(This, EfiVarStoreInfo, ConfigResp, &AccessProgress);
   4339       FreePool (EfiVarStoreInfo);
   4340     } else {
   4341       //
   4342       // Call corresponding ConfigAccess protocol to route settings
   4343       //
   4344       Status = gBS->HandleProtocol (
   4345                       DriverHandle,
   4346                       &gEfiHiiConfigAccessProtocolGuid,
   4347                       (VOID **)  &ConfigAccess
   4348                       );
   4349       if (EFI_ERROR (Status)) {
   4350         *Progress = StringPtr;
   4351         FreePool (ConfigResp);
   4352         return EFI_NOT_FOUND;
   4353       }
   4354 
   4355       Status = ConfigAccess->RouteConfig (
   4356                                ConfigAccess,
   4357                                ConfigResp,
   4358                                &AccessProgress
   4359                                );
   4360     }
   4361     if (EFI_ERROR (Status)) {
   4362       ASSERT (AccessProgress != NULL);
   4363       //
   4364       // AccessProgress indicates the parsing progress on <ConfigResp>.
   4365       // Map it to the progress on <MultiConfigResp> then return it.
   4366       //
   4367       *Progress = StrStr (StringPtr, AccessProgress);
   4368 
   4369       FreePool (ConfigResp);
   4370       return Status;
   4371     }
   4372 
   4373     FreePool (ConfigResp);
   4374     ConfigResp = NULL;
   4375 
   4376     //
   4377     // Go to next <ConfigResp> (skip '&').
   4378     //
   4379     StringPtr += Length;
   4380     if (*StringPtr == 0) {
   4381       *Progress = StringPtr;
   4382       break;
   4383     }
   4384 
   4385     StringPtr++;
   4386 
   4387   }
   4388 
   4389   return EFI_SUCCESS;
   4390 }
   4391 
   4392 
   4393 /**
   4394   This helper function is to be called by drivers to map configuration data
   4395   stored in byte array ("block") formats such as UEFI Variables into current
   4396   configuration strings.
   4397 
   4398   @param  This                   A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
   4399                                  instance.
   4400   @param  ConfigRequest          A null-terminated Unicode string in
   4401                                  <ConfigRequest> format.
   4402   @param  Block                  Array of bytes defining the block's configuration.
   4403   @param  BlockSize              Length in bytes of Block.
   4404   @param  Config                 Filled-in configuration string. String allocated
   4405                                  by  the function. Returned only if call is
   4406                                  successful. It is <ConfigResp> string format.
   4407   @param  Progress               A pointer to a string filled in with the offset of
   4408                                   the most recent & before the first failing
   4409                                  name/value pair (or the beginning of the string if
   4410                                  the failure is in the first name / value pair) or
   4411                                  the terminating NULL if all was successful.
   4412 
   4413   @retval EFI_SUCCESS            The request succeeded. Progress points to the null
   4414                                  terminator at the end of the ConfigRequest
   4415                                  string.
   4416   @retval EFI_OUT_OF_RESOURCES   Not enough memory to allocate Config.     Progress
   4417                                  points to the first character of ConfigRequest.
   4418   @retval EFI_INVALID_PARAMETER  Passing in a NULL for the ConfigRequest or
   4419                                  Block parameter would result in this type of
   4420                                  error. Progress points to the first character of
   4421                                  ConfigRequest.
   4422   @retval EFI_DEVICE_ERROR       Block not large enough. Progress undefined.
   4423   @retval EFI_INVALID_PARAMETER  Encountered non <BlockName> formatted string.
   4424                                      Block is left updated and Progress points at
   4425                                  the "&" preceding the first non-<BlockName>.
   4426 
   4427 **/
   4428 EFI_STATUS
   4429 EFIAPI
   4430 HiiBlockToConfig (
   4431   IN  CONST EFI_HII_CONFIG_ROUTING_PROTOCOL  *This,
   4432   IN  CONST EFI_STRING                       ConfigRequest,
   4433   IN  CONST UINT8                            *Block,
   4434   IN  CONST UINTN                            BlockSize,
   4435   OUT EFI_STRING                             *Config,
   4436   OUT EFI_STRING                             *Progress
   4437   )
   4438 {
   4439   HII_DATABASE_PRIVATE_DATA           *Private;
   4440   EFI_STRING                          StringPtr;
   4441   UINTN                               Length;
   4442   EFI_STATUS                          Status;
   4443   EFI_STRING                          TmpPtr;
   4444   UINT8                               *TmpBuffer;
   4445   UINTN                               Offset;
   4446   UINTN                               Width;
   4447   UINT8                               *Value;
   4448   EFI_STRING                          ValueStr;
   4449   EFI_STRING                          ConfigElement;
   4450   UINTN                               Index;
   4451   UINT8                               *TemBuffer;
   4452   CHAR16                              *TemString;
   4453   CHAR16                              TemChar;
   4454 
   4455   TmpBuffer = NULL;
   4456 
   4457   if (This == NULL || Progress == NULL || Config == NULL) {
   4458     return EFI_INVALID_PARAMETER;
   4459   }
   4460 
   4461   if (Block == NULL || ConfigRequest == NULL) {
   4462     *Progress = ConfigRequest;
   4463     return EFI_INVALID_PARAMETER;
   4464   }
   4465 
   4466 
   4467   Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);
   4468   ASSERT (Private != NULL);
   4469 
   4470   StringPtr     = ConfigRequest;
   4471   ValueStr      = NULL;
   4472   Value         = NULL;
   4473   ConfigElement = NULL;
   4474 
   4475   //
   4476   // Allocate a fix length of memory to store Results. Reallocate memory for
   4477   // Results if this fix length is insufficient.
   4478   //
   4479   *Config = (EFI_STRING) AllocateZeroPool (MAX_STRING_LENGTH);
   4480   if (*Config == NULL) {
   4481     return EFI_OUT_OF_RESOURCES;
   4482   }
   4483 
   4484   //
   4485   // Jump <ConfigHdr>
   4486   //
   4487   if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {
   4488     *Progress = StringPtr;
   4489     Status = EFI_INVALID_PARAMETER;
   4490     goto Exit;
   4491   }
   4492   while (*StringPtr != 0 && StrnCmp (StringPtr, L"PATH=", StrLen (L"PATH=")) != 0) {
   4493     StringPtr++;
   4494   }
   4495   if (*StringPtr == 0) {
   4496     *Progress = StringPtr - 1;
   4497     Status = EFI_INVALID_PARAMETER;
   4498     goto Exit;
   4499   }
   4500 
   4501   while (*StringPtr != L'&' && *StringPtr != 0) {
   4502     StringPtr++;
   4503   }
   4504   if (*StringPtr == 0) {
   4505     *Progress = StringPtr;
   4506 
   4507     AppendToMultiString(Config, ConfigRequest);
   4508     HiiToLower (*Config);
   4509 
   4510     return EFI_SUCCESS;
   4511   }
   4512   //
   4513   // Skip '&'
   4514   //
   4515   StringPtr++;
   4516 
   4517   //
   4518   // Copy <ConfigHdr> and an additional '&' to <ConfigResp>
   4519   //
   4520   TemChar = *StringPtr;
   4521   *StringPtr = '\0';
   4522   AppendToMultiString(Config, ConfigRequest);
   4523   *StringPtr = TemChar;
   4524 
   4525   //
   4526   // Parse each <RequestElement> if exists
   4527   // Only <BlockName> format is supported by this help function.
   4528   // <BlockName> ::= 'OFFSET='<Number>&'WIDTH='<Number>
   4529   //
   4530   while (*StringPtr != 0 && StrnCmp (StringPtr, L"OFFSET=", StrLen (L"OFFSET=")) == 0) {
   4531     //
   4532     // Back up the header of one <BlockName>
   4533     //
   4534     TmpPtr = StringPtr;
   4535 
   4536     StringPtr += StrLen (L"OFFSET=");
   4537     //
   4538     // Get Offset
   4539     //
   4540     Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
   4541     if (EFI_ERROR (Status)) {
   4542       *Progress = TmpPtr - 1;
   4543       goto Exit;
   4544     }
   4545     Offset = 0;
   4546     CopyMem (
   4547       &Offset,
   4548       TmpBuffer,
   4549       (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)
   4550       );
   4551     FreePool (TmpBuffer);
   4552 
   4553     StringPtr += Length;
   4554     if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {
   4555       *Progress = TmpPtr - 1;
   4556       Status = EFI_INVALID_PARAMETER;
   4557       goto Exit;
   4558     }
   4559     StringPtr += StrLen (L"&WIDTH=");
   4560 
   4561     //
   4562     // Get Width
   4563     //
   4564     Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
   4565     if (EFI_ERROR (Status)) {
   4566       *Progress =  TmpPtr - 1;
   4567       goto Exit;
   4568     }
   4569     Width = 0;
   4570     CopyMem (
   4571       &Width,
   4572       TmpBuffer,
   4573       (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)
   4574       );
   4575     FreePool (TmpBuffer);
   4576 
   4577     StringPtr += Length;
   4578     if (*StringPtr != 0 && *StringPtr != L'&') {
   4579       *Progress =  TmpPtr - 1;
   4580       Status = EFI_INVALID_PARAMETER;
   4581       goto Exit;
   4582     }
   4583 
   4584     //
   4585     // Calculate Value and convert it to hex string.
   4586     //
   4587     if (Offset + Width > BlockSize) {
   4588       *Progress = StringPtr;
   4589       Status = EFI_DEVICE_ERROR;
   4590       goto Exit;
   4591     }
   4592 
   4593     Value = (UINT8 *) AllocateZeroPool (Width);
   4594     if (Value == NULL) {
   4595       *Progress = ConfigRequest;
   4596       Status = EFI_OUT_OF_RESOURCES;
   4597       goto Exit;
   4598     }
   4599 
   4600     CopyMem (Value, (UINT8 *) Block + Offset, Width);
   4601 
   4602     Length = Width * 2 + 1;
   4603     ValueStr = (EFI_STRING) AllocateZeroPool (Length  * sizeof (CHAR16));
   4604     if (ValueStr == NULL) {
   4605       *Progress = ConfigRequest;
   4606       Status = EFI_OUT_OF_RESOURCES;
   4607       goto Exit;
   4608     }
   4609 
   4610     TemString = ValueStr;
   4611     TemBuffer = Value + Width - 1;
   4612     for (Index = 0; Index < Width; Index ++, TemBuffer --) {
   4613       TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemBuffer, 2);
   4614     }
   4615 
   4616     FreePool (Value);
   4617     Value = NULL;
   4618 
   4619     //
   4620     // Build a ConfigElement
   4621     //
   4622     Length += StringPtr - TmpPtr + 1 + StrLen (L"VALUE=");
   4623     ConfigElement = (EFI_STRING) AllocateZeroPool (Length * sizeof (CHAR16));
   4624     if (ConfigElement == NULL) {
   4625       Status = EFI_OUT_OF_RESOURCES;
   4626       goto Exit;
   4627     }
   4628     CopyMem (ConfigElement, TmpPtr, (StringPtr - TmpPtr + 1) * sizeof (CHAR16));
   4629     if (*StringPtr == 0) {
   4630       *(ConfigElement + (StringPtr - TmpPtr)) = L'&';
   4631     }
   4632     *(ConfigElement + (StringPtr - TmpPtr) + 1) = 0;
   4633     StrCatS (ConfigElement, Length, L"VALUE=");
   4634     StrCatS (ConfigElement, Length, ValueStr);
   4635 
   4636     AppendToMultiString (Config, ConfigElement);
   4637 
   4638     FreePool (ConfigElement);
   4639     FreePool (ValueStr);
   4640     ConfigElement = NULL;
   4641     ValueStr = NULL;
   4642 
   4643     //
   4644     // If '\0', parsing is finished. Otherwise skip '&' to continue
   4645     //
   4646     if (*StringPtr == 0) {
   4647       break;
   4648     }
   4649     AppendToMultiString (Config, L"&");
   4650     StringPtr++;
   4651 
   4652   }
   4653 
   4654   if (*StringPtr != 0) {
   4655     *Progress = StringPtr - 1;
   4656     Status = EFI_INVALID_PARAMETER;
   4657     goto Exit;
   4658   }
   4659 
   4660   HiiToLower (*Config);
   4661   *Progress = StringPtr;
   4662   return EFI_SUCCESS;
   4663 
   4664 Exit:
   4665   if (*Config != NULL) {
   4666   FreePool (*Config);
   4667   *Config = NULL;
   4668   }
   4669   if (ValueStr != NULL) {
   4670     FreePool (ValueStr);
   4671   }
   4672   if (Value != NULL) {
   4673     FreePool (Value);
   4674   }
   4675   if (ConfigElement != NULL) {
   4676     FreePool (ConfigElement);
   4677   }
   4678 
   4679   return Status;
   4680 
   4681 }
   4682 
   4683 
   4684 /**
   4685   This helper function is to be called by drivers to map configuration strings
   4686   to configurations stored in byte array ("block") formats such as UEFI Variables.
   4687 
   4688   @param  This                   A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
   4689                                  instance.
   4690   @param  ConfigResp             A null-terminated Unicode string in <ConfigResp>
   4691                                  format.
   4692   @param  Block                  A possibly null array of bytes representing the
   4693                                  current  block. Only bytes referenced in the
   4694                                  ConfigResp string  in the block are modified. If
   4695                                  this parameter is null or if the *BlockSize
   4696                                  parameter is (on input) shorter than required by
   4697                                  the Configuration string, only the BlockSize
   4698                                  parameter is updated and an appropriate status
   4699                                  (see below)  is returned.
   4700   @param  BlockSize              The length of the Block in units of UINT8.  On
   4701                                  input, this is the size of the Block. On output,
   4702                                  if successful, contains the largest index of the
   4703                                  modified byte in the Block, or the required buffer
   4704                                  size if the Block is not large enough.
   4705   @param  Progress               On return, points to an element of the ConfigResp
   4706                                  string filled in with the offset of the most
   4707                                  recent '&' before the first failing name / value
   4708                                  pair (or  the beginning of the string if the
   4709                                  failure is in the  first name / value pair) or the
   4710                                  terminating NULL if all was successful.
   4711 
   4712   @retval EFI_SUCCESS            The request succeeded. Progress points to the null
   4713                                  terminator at the end of the ConfigResp string.
   4714   @retval EFI_OUT_OF_RESOURCES   Not enough memory to allocate Config.     Progress
   4715                                  points to the first character of ConfigResp.
   4716   @retval EFI_INVALID_PARAMETER  Passing in a NULL for the ConfigResp or
   4717                                  Block parameter would result in this type of
   4718                                  error. Progress points to the first character of
   4719                                          ConfigResp.
   4720   @retval EFI_INVALID_PARAMETER  Encountered non <BlockName> formatted name /
   4721                                  value pair. Block is left updated and
   4722                                  Progress points at the '&' preceding the first
   4723                                  non-<BlockName>.
   4724   @retval EFI_BUFFER_TOO_SMALL   Block not large enough. Progress undefined.
   4725                                  BlockSize is updated with the required buffer size.
   4726   @retval EFI_NOT_FOUND          Target for the specified routing data was not found.
   4727                                  Progress points to the "G" in "GUID" of the errant
   4728                                  routing data.
   4729 
   4730 **/
   4731 EFI_STATUS
   4732 EFIAPI
   4733 HiiConfigToBlock (
   4734   IN     CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
   4735   IN     CONST EFI_STRING                      ConfigResp,
   4736   IN OUT UINT8                                 *Block,
   4737   IN OUT UINTN                                 *BlockSize,
   4738   OUT    EFI_STRING                            *Progress
   4739   )
   4740 {
   4741   HII_DATABASE_PRIVATE_DATA           *Private;
   4742   EFI_STRING                          StringPtr;
   4743   EFI_STRING                          TmpPtr;
   4744   UINTN                               Length;
   4745   EFI_STATUS                          Status;
   4746   UINT8                               *TmpBuffer;
   4747   UINTN                               Offset;
   4748   UINTN                               Width;
   4749   UINT8                               *Value;
   4750   UINTN                               BufferSize;
   4751   UINTN                               MaxBlockSize;
   4752 
   4753   TmpBuffer = NULL;
   4754 
   4755   if (This == NULL || BlockSize == NULL || Progress == NULL) {
   4756     return EFI_INVALID_PARAMETER;
   4757   }
   4758 
   4759   *Progress = ConfigResp;
   4760   if (ConfigResp == NULL) {
   4761     return EFI_INVALID_PARAMETER;
   4762   }
   4763 
   4764   Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);
   4765   ASSERT (Private != NULL);
   4766 
   4767   StringPtr  = ConfigResp;
   4768   BufferSize = *BlockSize;
   4769   Value      = NULL;
   4770   MaxBlockSize = 0;
   4771 
   4772   //
   4773   // Jump <ConfigHdr>
   4774   //
   4775   if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {
   4776     *Progress = StringPtr;
   4777     Status = EFI_INVALID_PARAMETER;
   4778     goto Exit;
   4779   }
   4780   while (*StringPtr != 0 && StrnCmp (StringPtr, L"PATH=", StrLen (L"PATH=")) != 0) {
   4781     StringPtr++;
   4782   }
   4783   if (*StringPtr == 0) {
   4784     *Progress = StringPtr;
   4785     Status = EFI_INVALID_PARAMETER;
   4786     goto Exit;
   4787   }
   4788 
   4789   while (*StringPtr != L'&' && *StringPtr != 0) {
   4790     StringPtr++;
   4791   }
   4792   if (*StringPtr == 0) {
   4793     *Progress = StringPtr;
   4794     Status = EFI_INVALID_PARAMETER;
   4795     goto Exit;
   4796   }
   4797 
   4798   //
   4799   // Parse each <ConfigElement> if exists
   4800   // Only '&'<BlockConfig> format is supported by this help function.
   4801   // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE='<Number>
   4802   //
   4803   while (*StringPtr != 0 && StrnCmp (StringPtr, L"&OFFSET=", StrLen (L"&OFFSET=")) == 0) {
   4804     TmpPtr     = StringPtr;
   4805     StringPtr += StrLen (L"&OFFSET=");
   4806     //
   4807     // Get Offset
   4808     //
   4809     Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
   4810     if (EFI_ERROR (Status)) {
   4811       *Progress = TmpPtr;
   4812       goto Exit;
   4813     }
   4814     Offset = 0;
   4815     CopyMem (
   4816       &Offset,
   4817       TmpBuffer,
   4818       (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)
   4819       );
   4820     FreePool (TmpBuffer);
   4821 
   4822     StringPtr += Length;
   4823     if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {
   4824       *Progress = TmpPtr;
   4825       Status = EFI_INVALID_PARAMETER;
   4826       goto Exit;
   4827     }
   4828     StringPtr += StrLen (L"&WIDTH=");
   4829 
   4830     //
   4831     // Get Width
   4832     //
   4833     Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
   4834     if (EFI_ERROR (Status)) {
   4835       *Progress = TmpPtr;
   4836       goto Exit;
   4837     }
   4838     Width = 0;
   4839     CopyMem (
   4840       &Width,
   4841       TmpBuffer,
   4842       (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)
   4843       );
   4844     FreePool (TmpBuffer);
   4845 
   4846     StringPtr += Length;
   4847     if (StrnCmp (StringPtr, L"&VALUE=", StrLen (L"&VALUE=")) != 0) {
   4848       *Progress = TmpPtr;
   4849       Status = EFI_INVALID_PARAMETER;
   4850       goto Exit;
   4851     }
   4852     StringPtr += StrLen (L"&VALUE=");
   4853 
   4854     //
   4855     // Get Value
   4856     //
   4857     Status = GetValueOfNumber (StringPtr, &Value, &Length);
   4858     if (EFI_ERROR (Status)) {
   4859       *Progress = TmpPtr;
   4860       goto Exit;
   4861     }
   4862 
   4863     StringPtr += Length;
   4864     if (*StringPtr != 0 && *StringPtr != L'&') {
   4865       *Progress = TmpPtr;
   4866       Status = EFI_INVALID_PARAMETER;
   4867       goto Exit;
   4868     }
   4869 
   4870     //
   4871     // Update the Block with configuration info
   4872     //
   4873     if ((Block != NULL) && (Offset + Width <= BufferSize)) {
   4874       CopyMem (Block + Offset, Value, Width);
   4875     }
   4876     if (Offset + Width > MaxBlockSize) {
   4877       MaxBlockSize = Offset + Width;
   4878     }
   4879 
   4880     FreePool (Value);
   4881     Value = NULL;
   4882 
   4883     //
   4884     // If '\0', parsing is finished.
   4885     //
   4886     if (*StringPtr == 0) {
   4887       break;
   4888     }
   4889   }
   4890 
   4891   //
   4892   // The input string is not ConfigResp format, return error.
   4893   //
   4894   if (*StringPtr != 0) {
   4895     *Progress = StringPtr;
   4896     Status = EFI_INVALID_PARAMETER;
   4897     goto Exit;
   4898   }
   4899 
   4900   *Progress = StringPtr + StrLen (StringPtr);
   4901   *BlockSize = MaxBlockSize - 1;
   4902 
   4903   if (MaxBlockSize > BufferSize) {
   4904     *BlockSize = MaxBlockSize;
   4905     if (Block != NULL) {
   4906       return EFI_BUFFER_TOO_SMALL;
   4907     }
   4908   }
   4909 
   4910   if (Block == NULL) {
   4911     *Progress = ConfigResp;
   4912     return EFI_INVALID_PARAMETER;
   4913   }
   4914 
   4915   return EFI_SUCCESS;
   4916 
   4917 Exit:
   4918 
   4919   if (Value != NULL) {
   4920     FreePool (Value);
   4921   }
   4922   return Status;
   4923 }
   4924 
   4925 
   4926 /**
   4927   This helper function is to be called by drivers to extract portions of
   4928   a larger configuration string.
   4929 
   4930   @param  This                   A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
   4931                                  instance.
   4932   @param  Configuration          A null-terminated Unicode string in
   4933                                  <MultiConfigAltResp> format.
   4934   @param  Guid                   A pointer to the GUID value to search for in the
   4935                                  routing portion of the ConfigResp string when
   4936                                  retrieving  the requested data. If Guid is NULL,
   4937                                  then all GUID  values will be searched for.
   4938   @param  Name                   A pointer to the NAME value to search for in the
   4939                                  routing portion of the ConfigResp string when
   4940                                  retrieving  the requested data. If Name is NULL,
   4941                                  then all Name  values will be searched for.
   4942   @param  DevicePath             A pointer to the PATH value to search for in the
   4943                                  routing portion of the ConfigResp string when
   4944                                  retrieving  the requested data. If DevicePath is
   4945                                  NULL, then all  DevicePath values will be searched
   4946                                  for.
   4947   @param  AltCfgId               A pointer to the ALTCFG value to search for in the
   4948                                   routing portion of the ConfigResp string when
   4949                                  retrieving  the requested data.  If this parameter
   4950                                  is NULL,  then the current setting will be
   4951                                  retrieved.
   4952   @param  AltCfgResp             A pointer to a buffer which will be allocated by
   4953                                  the  function which contains the retrieved string
   4954                                  as requested.   This buffer is only allocated if
   4955                                  the call was successful. It is <ConfigResp> format.
   4956 
   4957   @retval EFI_SUCCESS            The request succeeded. The requested data was
   4958                                  extracted  and placed in the newly allocated
   4959                                  AltCfgResp buffer.
   4960   @retval EFI_OUT_OF_RESOURCES   Not enough memory to allocate AltCfgResp.
   4961   @retval EFI_INVALID_PARAMETER  Any parameter is invalid.
   4962   @retval EFI_NOT_FOUND          Target for the specified routing data was not
   4963                                  found.
   4964 
   4965 **/
   4966 EFI_STATUS
   4967 EFIAPI
   4968 HiiGetAltCfg (
   4969   IN  CONST EFI_HII_CONFIG_ROUTING_PROTOCOL    *This,
   4970   IN  CONST EFI_STRING                         Configuration,
   4971   IN  CONST EFI_GUID                           *Guid,
   4972   IN  CONST EFI_STRING                         Name,
   4973   IN  CONST EFI_DEVICE_PATH_PROTOCOL           *DevicePath,
   4974   IN  CONST UINT16                             *AltCfgId,
   4975   OUT EFI_STRING                               *AltCfgResp
   4976   )
   4977 {
   4978   EFI_STATUS                          Status;
   4979   EFI_STRING                          StringPtr;
   4980   EFI_STRING                          HdrStart;
   4981   EFI_STRING                          HdrEnd;
   4982   EFI_STRING                          TmpPtr;
   4983   UINTN                               Length;
   4984   EFI_STRING                          GuidStr;
   4985   EFI_STRING                          NameStr;
   4986   EFI_STRING                          PathStr;
   4987   EFI_STRING                          AltIdStr;
   4988   EFI_STRING                          Result;
   4989   BOOLEAN                             GuidFlag;
   4990   BOOLEAN                             NameFlag;
   4991   BOOLEAN                             PathFlag;
   4992 
   4993   HdrStart = NULL;
   4994   HdrEnd   = NULL;
   4995   GuidStr  = NULL;
   4996   NameStr  = NULL;
   4997   PathStr  = NULL;
   4998   AltIdStr = NULL;
   4999   Result   = NULL;
   5000   GuidFlag = FALSE;
   5001   NameFlag = FALSE;
   5002   PathFlag = FALSE;
   5003 
   5004   if (This == NULL || Configuration == NULL || AltCfgResp == NULL) {
   5005     return EFI_INVALID_PARAMETER;
   5006   }
   5007 
   5008   StringPtr = Configuration;
   5009   if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {
   5010     return EFI_INVALID_PARAMETER;
   5011   }
   5012 
   5013   //
   5014   // Generate the sub string for later matching.
   5015   //
   5016   GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (VOID *) Guid, 1, &GuidStr);
   5017   GenerateSubStr (
   5018     L"PATH=",
   5019     GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) DevicePath),
   5020     (VOID *) DevicePath,
   5021     1,
   5022     &PathStr
   5023     );
   5024   if (AltCfgId != NULL) {
   5025     GenerateSubStr (L"ALTCFG=", sizeof (UINT16), (VOID *) AltCfgId, 3, &AltIdStr);
   5026   }
   5027   if (Name != NULL) {
   5028     GenerateSubStr (L"NAME=", StrLen (Name) * sizeof (CHAR16), (VOID *) Name, 2, &NameStr);
   5029   } else {
   5030     GenerateSubStr (L"NAME=", 0, NULL, 2, &NameStr);
   5031   }
   5032 
   5033   while (*StringPtr != 0) {
   5034     //
   5035     // Try to match the GUID
   5036     //
   5037     if (!GuidFlag) {
   5038       TmpPtr = StrStr (StringPtr, GuidStr);
   5039       if (TmpPtr == NULL) {
   5040         Status = EFI_NOT_FOUND;
   5041         goto Exit;
   5042       }
   5043       HdrStart = TmpPtr;
   5044 
   5045       //
   5046       // Jump to <NameHdr>
   5047       //
   5048       if (Guid != NULL) {
   5049         StringPtr = TmpPtr + StrLen (GuidStr);
   5050       } else {
   5051         StringPtr = StrStr (TmpPtr, L"NAME=");
   5052         if (StringPtr == NULL) {
   5053           Status = EFI_NOT_FOUND;
   5054           goto Exit;
   5055         }
   5056       }
   5057       GuidFlag = TRUE;
   5058     }
   5059 
   5060     //
   5061     // Try to match the NAME
   5062     //
   5063     if (GuidFlag && !NameFlag) {
   5064       if (StrnCmp (StringPtr, NameStr, StrLen (NameStr)) != 0) {
   5065         GuidFlag = FALSE;
   5066       } else {
   5067         //
   5068         // Jump to <PathHdr>
   5069         //
   5070         if (Name != NULL) {
   5071           StringPtr += StrLen (NameStr);
   5072         } else {
   5073           StringPtr = StrStr (StringPtr, L"PATH=");
   5074           if (StringPtr == NULL) {
   5075             Status = EFI_NOT_FOUND;
   5076             goto Exit;
   5077           }
   5078         }
   5079         NameFlag = TRUE;
   5080       }
   5081     }
   5082 
   5083     //
   5084     // Try to match the DevicePath
   5085     //
   5086     if (GuidFlag && NameFlag && !PathFlag) {
   5087       if (StrnCmp (StringPtr, PathStr, StrLen (PathStr)) != 0) {
   5088         GuidFlag = FALSE;
   5089         NameFlag = FALSE;
   5090       } else {
   5091         //
   5092         // Jump to '&' before <DescHdr> or <ConfigBody>
   5093         //
   5094         if (DevicePath != NULL) {
   5095           StringPtr += StrLen (PathStr);
   5096         } else {
   5097           StringPtr = StrStr (StringPtr, L"&");
   5098           if (StringPtr == NULL) {
   5099             Status = EFI_NOT_FOUND;
   5100             goto Exit;
   5101           }
   5102           StringPtr ++;
   5103         }
   5104         PathFlag = TRUE;
   5105         HdrEnd   = StringPtr;
   5106       }
   5107     }
   5108 
   5109     //
   5110     // Try to match the AltCfgId
   5111     //
   5112     if (GuidFlag && NameFlag && PathFlag) {
   5113       if (AltCfgId == NULL) {
   5114         //
   5115         // Return Current Setting when AltCfgId is NULL.
   5116         //
   5117         Status = OutputConfigBody (StringPtr, &Result);
   5118         goto Exit;
   5119       }
   5120       //
   5121       // Search the <ConfigAltResp> to get the <AltResp> with AltCfgId.
   5122       //
   5123       if (StrnCmp (StringPtr, AltIdStr, StrLen (AltIdStr)) != 0) {
   5124         GuidFlag = FALSE;
   5125         NameFlag = FALSE;
   5126         PathFlag = FALSE;
   5127       } else {
   5128         //
   5129         // Skip AltIdStr and &
   5130         //
   5131         StringPtr = StringPtr + StrLen (AltIdStr);
   5132         Status    = OutputConfigBody (StringPtr, &Result);
   5133         goto Exit;
   5134       }
   5135     }
   5136   }
   5137 
   5138   Status = EFI_NOT_FOUND;
   5139 
   5140 Exit:
   5141   *AltCfgResp = NULL;
   5142   if (!EFI_ERROR (Status) && (Result != NULL)) {
   5143     //
   5144     // Copy the <ConfigHdr> and <ConfigBody>
   5145     //
   5146     Length = HdrEnd - HdrStart + StrLen (Result) + 1;
   5147     *AltCfgResp = AllocateZeroPool (Length * sizeof (CHAR16));
   5148     if (*AltCfgResp == NULL) {
   5149       Status = EFI_OUT_OF_RESOURCES;
   5150     } else {
   5151       StrnCpyS (*AltCfgResp, Length, HdrStart, HdrEnd - HdrStart);
   5152       StrCatS (*AltCfgResp, Length, Result);
   5153       Status = EFI_SUCCESS;
   5154     }
   5155   }
   5156 
   5157   if (GuidStr != NULL) {
   5158     FreePool (GuidStr);
   5159   }
   5160   if (NameStr != NULL) {
   5161     FreePool (NameStr);
   5162   }
   5163   if (PathStr != NULL) {
   5164     FreePool (PathStr);
   5165   }
   5166   if (AltIdStr != NULL) {
   5167     FreePool (AltIdStr);
   5168   }
   5169   if (Result != NULL) {
   5170     FreePool (Result);
   5171   }
   5172 
   5173   return Status;
   5174 
   5175 }
   5176 
   5177 
   5178