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 - 2016, Intel Corporation. All rights reserved.<BR>
      5 This program and the accompanying materials
      6 are licensed and made available under the terms and conditions of the BSD License
      7 which accompanies this distribution.  The full text of the license may be found at
      8 http://opensource.org/licenses/bsd-license.php
      9 
     10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     12 
     13 **/
     14 
     15 
     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 necessary 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 necessary
    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  To find the BlockName in the string with same value.
    514 
    515   @param  String                 Pointer to a Null-terminated Unicode string.
    516   @param  BlockName              Pointer to a Null-terminated Unicode string to search for.
    517   @param  Buffer                 Pointer to the value correspond to the BlockName.
    518   @param  Found                  The Block whether has been found.
    519   @param  BufferLen              The length of the buffer.
    520 
    521   @retval EFI_OUT_OF_RESOURCES   Insufficient resources to store necessary structures.
    522   @retval EFI_SUCCESS            The function finishes successfully.
    523 
    524 **/
    525 EFI_STATUS
    526 FindSameBlockElement(
    527   IN  EFI_STRING   String,
    528   IN  EFI_STRING   BlockName,
    529   IN  UINT8        *Buffer,
    530   OUT BOOLEAN      *Found,
    531   IN  UINTN        BufferLen
    532   )
    533 {
    534   EFI_STRING   BlockPtr;
    535   UINTN        Length;
    536   UINT8        *TempBuffer;
    537   EFI_STATUS   Status;
    538 
    539   TempBuffer = NULL;
    540   *Found = FALSE;
    541   BlockPtr = StrStr (String, BlockName);
    542 
    543   while (BlockPtr != NULL) {
    544     BlockPtr += StrLen (BlockName);
    545     Status = GetValueOfNumber (BlockPtr, &TempBuffer, &Length);
    546     if (EFI_ERROR (Status)) {
    547       return Status;
    548     }
    549     ASSERT (TempBuffer != NULL);
    550     if ((BufferLen == Length) && (0 == CompareMem (Buffer, TempBuffer, Length))) {
    551       *Found = TRUE;
    552       FreePool (TempBuffer);
    553       TempBuffer = NULL;
    554       return EFI_SUCCESS;
    555     } else {
    556       FreePool (TempBuffer);
    557       TempBuffer = NULL;
    558       BlockPtr = StrStr (BlockPtr + 1, BlockName);
    559     }
    560   }
    561   return EFI_SUCCESS;
    562 }
    563 
    564 /**
    565   Compare the <AltResp> in ConfigAltResp and DefaultAltCfgResp, if the <AltResp>
    566   in DefaultAltCfgResp but not in ConfigAltResp,add it to the ConfigAltResp.
    567 
    568   @param  DefaultAltCfgResp      Pointer to a null-terminated Unicode string in
    569                                  <MultiConfigAltResp> format. The default value
    570                                  string may contain more than one ConfigAltResp
    571                                  string for the different varstore buffer.
    572   @param  ConfigAltResp          Pointer to a null-terminated Unicode string in
    573                                  <ConfigAltResp> format.
    574   @param  AltConfigHdr           Pointer to a Unicode string in <AltConfigHdr> format.
    575   @param  ConfigAltRespChanged   Whether the ConfigAltResp has been changed.
    576 
    577   @retval EFI_OUT_OF_RESOURCES   Insufficient resources to store necessary structures.
    578   @retval EFI_SUCCESS            The function finishes  successfully.
    579 
    580 **/
    581 EFI_STATUS
    582 CompareBlockElementDefault (
    583   IN      EFI_STRING  DefaultAltCfgResp,
    584   IN OUT  EFI_STRING  *ConfigAltResp,
    585   IN      EFI_STRING  AltConfigHdr,
    586   IN OUT  BOOLEAN     *ConfigAltRespChanged
    587 )
    588 {
    589   EFI_STATUS    Status;
    590   EFI_STRING    BlockPtr;
    591   EFI_STRING    BlockPtrStart;
    592   EFI_STRING    StringPtr;
    593   EFI_STRING    AppendString;
    594   EFI_STRING    AltConfigHdrPtr;
    595   UINT8         *TempBuffer;
    596   UINTN         OffsetLength;
    597   UINTN         AppendSize;
    598   UINTN         TotalSize;
    599   BOOLEAN       FoundOffset;
    600 
    601   AppendString = NULL;
    602   TempBuffer   = NULL;
    603   //
    604   // Make BlockPtr point to the first <BlockConfig> with AltConfigHdr in DefaultAltCfgResp.
    605   //
    606   AltConfigHdrPtr = StrStr (DefaultAltCfgResp, AltConfigHdr);
    607   ASSERT (AltConfigHdrPtr != NULL);
    608   BlockPtr = StrStr (AltConfigHdrPtr, L"&OFFSET=");
    609   //
    610   // Make StringPtr point to the AltConfigHdr in ConfigAltResp.
    611   //
    612   StringPtr = StrStr (*ConfigAltResp, AltConfigHdr);
    613   ASSERT (StringPtr != NULL);
    614 
    615   while (BlockPtr != NULL) {
    616     //
    617     // Find the "&OFFSET=<Number>" block and get the value of the Number with AltConfigHdr in DefaultAltCfgResp.
    618     //
    619     BlockPtrStart = BlockPtr;
    620     BlockPtr += StrLen (L"&OFFSET=");
    621     Status = GetValueOfNumber (BlockPtr, &TempBuffer, &OffsetLength);
    622     if (EFI_ERROR (Status)) {
    623       Status = EFI_OUT_OF_RESOURCES;
    624       goto Exit;
    625     }
    626     //
    627     // To find the same "&OFFSET=<Number>" block in ConfigAltResp.
    628     //
    629     Status = FindSameBlockElement (StringPtr, L"&OFFSET=", TempBuffer, &FoundOffset, OffsetLength);
    630     if (TempBuffer != NULL) {
    631       FreePool (TempBuffer);
    632       TempBuffer = NULL;
    633     }
    634     if (EFI_ERROR (Status)) {
    635       Status = EFI_OUT_OF_RESOURCES;
    636       goto Exit;
    637     }
    638     if (!FoundOffset) {
    639       //
    640       // Don't find the same "&OFFSET=<Number>" block in ConfigAltResp.
    641       // Calculate the size of <BlockConfig>.
    642       // <BlockConfig>::='OFFSET='<Number>'&WIDTH='<Number>'&VALUE='<Number>.
    643       //
    644       BlockPtr = StrStr (BlockPtr + 1, L"&OFFSET=");
    645       if (BlockPtr != NULL) {
    646         AppendSize = (BlockPtr - BlockPtrStart) * sizeof (CHAR16);
    647       } else {
    648         AppendSize = StrSize (BlockPtrStart);
    649       }
    650       //
    651       // Copy the <BlockConfig> to AppendString.
    652       //
    653       if (AppendString == NULL) {
    654         AppendString = (EFI_STRING) AllocateZeroPool (AppendSize + sizeof (CHAR16));
    655         StrnCatS (AppendString, AppendSize / sizeof (CHAR16) + 1, BlockPtrStart, AppendSize / sizeof (CHAR16));
    656       } else {
    657         TotalSize = StrSize (AppendString) + AppendSize + sizeof (CHAR16);
    658         AppendString = (EFI_STRING) ReallocatePool (
    659                                       StrSize (AppendString),
    660                                       TotalSize,
    661                                       AppendString
    662                                       );
    663         if (AppendString == NULL) {
    664           Status = EFI_OUT_OF_RESOURCES;
    665           goto Exit;
    666         }
    667         StrnCatS (AppendString, TotalSize / sizeof (CHAR16), BlockPtrStart, AppendSize / sizeof (CHAR16));
    668       }
    669     } else {
    670       //
    671       // To find next "&OFFSET=<Number>" block with AltConfigHdr in DefaultAltCfgResp.
    672       //
    673       BlockPtr = StrStr (BlockPtr + 1, L"&OFFSET=");
    674     }
    675   }
    676 
    677   if (AppendString != NULL) {
    678     //
    679     // Reallocate ConfigAltResp to copy the AppendString.
    680     //
    681     TotalSize = StrSize (*ConfigAltResp) + StrSize (AppendString) + sizeof (CHAR16);
    682     *ConfigAltResp = (EFI_STRING) ReallocatePool (
    683                                     StrSize (*ConfigAltResp),
    684                                     TotalSize,
    685                                     *ConfigAltResp
    686                                     );
    687     if (*ConfigAltResp == NULL) {
    688       Status = EFI_OUT_OF_RESOURCES;
    689       goto Exit;
    690     }
    691     StrCatS (*ConfigAltResp, TotalSize / sizeof (CHAR16), AppendString);
    692     *ConfigAltRespChanged = TRUE;
    693   }
    694 
    695   Status = EFI_SUCCESS;
    696 
    697 Exit:
    698   if (AppendString != NULL) {
    699     FreePool (AppendString);
    700   }
    701 
    702   return Status;
    703 }
    704 
    705 /**
    706   Compare the <AltResp> in ConfigAltResp and DefaultAltCfgResp, if the <AltResp>
    707   in DefaultAltCfgResp but not in ConfigAltResp,add it to the ConfigAltResp.
    708 
    709   @param  DefaultAltCfgResp      Pointer to a null-terminated Unicode string in
    710                                  <MultiConfigAltResp> format. The default value
    711                                  string may contain more than one ConfigAltResp
    712                                  string for the different varstore buffer.
    713   @param  ConfigAltResp          Pointer to a null-terminated Unicode string in
    714                                  <ConfigAltResp> format.
    715   @param  AltConfigHdr           Pointer to a Unicode string in <AltConfigHdr> format.
    716   @param  ConfigAltRespChanged   Whether the ConfigAltResp has been changed.
    717 
    718   @retval EFI_OUT_OF_RESOURCES   Insufficient resources to store necessary structures.
    719   @retval EFI_SUCCESS            The function finishes  successfully.
    720 
    721 **/
    722 EFI_STATUS
    723 CompareNameElementDefault (
    724   IN     EFI_STRING  DefaultAltCfgResp,
    725   IN OUT EFI_STRING  *ConfigAltResp,
    726   IN     EFI_STRING  AltConfigHdr,
    727   IN OUT BOOLEAN     *ConfigAltRespChanged
    728 )
    729 {
    730   EFI_STATUS    Status;
    731   EFI_STRING    NvConfigPtr;
    732   EFI_STRING    NvConfigStart;
    733   EFI_STRING    NvConfigValuePtr;
    734   EFI_STRING    StringPtr;
    735   EFI_STRING    NvConfigExist;
    736   EFI_STRING    AppendString;
    737   CHAR16        TempChar;
    738   UINTN         AppendSize;
    739   UINTN         TotalSize;
    740 
    741   AppendString = NULL;
    742   NvConfigExist = NULL;
    743   //
    744   // Make NvConfigPtr point to the first <NvConfig> with AltConfigHdr in DefaultAltCfgResp.
    745   //
    746   NvConfigPtr = StrStr (DefaultAltCfgResp, AltConfigHdr);
    747   ASSERT (NvConfigPtr != NULL);
    748   NvConfigPtr = StrStr (NvConfigPtr + StrLen(AltConfigHdr),L"&");
    749   //
    750   // Make StringPtr point to the first <NvConfig> with AltConfigHdr in ConfigAltResp.
    751   //
    752   StringPtr = StrStr (*ConfigAltResp, AltConfigHdr);
    753   ASSERT (StringPtr != NULL);
    754   StringPtr = StrStr (StringPtr + StrLen (AltConfigHdr), L"&");
    755   ASSERT (StringPtr != NULL);
    756 
    757   while (NvConfigPtr != NULL) {
    758     //
    759     // <NvConfig> ::= <Label>'='<String> | <Label>'='<Number>.
    760     // Get the <Label> with AltConfigHdr in DefaultAltCfgResp.
    761     //
    762     NvConfigStart = NvConfigPtr;
    763     NvConfigValuePtr = StrStr (NvConfigPtr + 1, L"=");
    764     ASSERT (NvConfigValuePtr != NULL);
    765     TempChar = *NvConfigValuePtr;
    766     *NvConfigValuePtr = L'\0';
    767     //
    768     // Get the <Label> with AltConfigHdr in ConfigAltResp.
    769     //
    770     NvConfigExist = StrStr (StringPtr, NvConfigPtr);
    771     if (NvConfigExist == NULL) {
    772       //
    773       // Don't find same <Label> in ConfigAltResp.
    774       // Calculate the size of <NvConfig>.
    775       //
    776       *NvConfigValuePtr = TempChar;
    777       NvConfigPtr = StrStr (NvConfigPtr + 1, L"&");
    778       if (NvConfigPtr != NULL) {
    779         AppendSize = (NvConfigPtr - NvConfigStart) * sizeof (CHAR16);
    780       } else {
    781         AppendSize = StrSize (NvConfigStart);
    782       }
    783       //
    784       // Copy the <NvConfig> to AppendString.
    785       //
    786       if (AppendString == NULL) {
    787         AppendString = (EFI_STRING) AllocateZeroPool (AppendSize + sizeof (CHAR16));
    788         StrnCatS (AppendString, AppendSize / sizeof (CHAR16) + 1, NvConfigStart, AppendSize / sizeof (CHAR16));
    789       } else {
    790          TotalSize = StrSize (AppendString) + AppendSize + sizeof (CHAR16);
    791          AppendString = (EFI_STRING) ReallocatePool (
    792                                        StrSize (AppendString),
    793                                        TotalSize,
    794                                        AppendString
    795                                        );
    796         if (AppendString == NULL) {
    797           Status = EFI_OUT_OF_RESOURCES;
    798           goto Exit;
    799         }
    800         StrnCatS (AppendString, TotalSize / sizeof (CHAR16), NvConfigStart, AppendSize / sizeof (CHAR16));
    801       }
    802     } else {
    803       //
    804       // To find next <Label> in DefaultAltCfgResp.
    805       //
    806       *NvConfigValuePtr = TempChar;
    807       NvConfigPtr = StrStr (NvConfigPtr + 1, L"&");
    808     }
    809   }
    810   if (AppendString != NULL) {
    811     //
    812     // Reallocate ConfigAltResp to copy the AppendString.
    813     //
    814     TotalSize = StrSize (*ConfigAltResp) + StrSize (AppendString) + sizeof (CHAR16);
    815     *ConfigAltResp = (EFI_STRING) ReallocatePool (
    816                                     StrSize (*ConfigAltResp),
    817                                     StrSize (*ConfigAltResp) + StrSize (AppendString) + sizeof (CHAR16),
    818                                     *ConfigAltResp
    819                                     );
    820     if (*ConfigAltResp == NULL) {
    821       Status = EFI_OUT_OF_RESOURCES;
    822       goto Exit;
    823     }
    824     StrCatS (*ConfigAltResp, TotalSize / sizeof (CHAR16), AppendString);
    825     *ConfigAltRespChanged = TRUE;
    826   }
    827   Status = EFI_SUCCESS;
    828 
    829 Exit:
    830   if (AppendString != NULL) {
    831     FreePool (AppendString);
    832   }
    833   return Status;
    834 }
    835 
    836 /**
    837   Compare the <AltResp> in AltCfgResp and DefaultAltCfgResp, if the <AltResp>
    838   in DefaultAltCfgResp but not in AltCfgResp,add it to the AltCfgResp.
    839 
    840   @param  AltCfgResp             Pointer to a null-terminated Unicode string in
    841                                  <ConfigAltResp> format.
    842   @param  DefaultAltCfgResp      Pointer to a null-terminated Unicode string in
    843                                  <MultiConfigAltResp> format. The default value
    844                                  string may contain more than one ConfigAltResp
    845                                  string for the different varstore buffer.
    846   @param  AltConfigHdr           Pointer to a Unicode string in <AltConfigHdr> format.
    847 
    848   @retval EFI_OUT_OF_RESOURCES   Insufficient resources to store necessary
    849                                  structures.
    850   @retval EFI_SUCCESS            The function finishes  successfully.
    851 
    852 **/
    853 EFI_STATUS
    854 CompareAndMergeDefaultString (
    855   IN OUT EFI_STRING  *AltCfgResp,
    856   IN     EFI_STRING  DefaultAltCfgResp,
    857   IN     EFI_STRING  AltConfigHdr
    858   )
    859 {
    860   EFI_STATUS     Status;
    861   EFI_STRING     AltCfgRespBackup;
    862   EFI_STRING     AltConfigHdrPtr;
    863   EFI_STRING     AltConfigHdrPtrNext;
    864   EFI_STRING     ConfigAltResp;
    865   EFI_STRING     StringPtr;
    866   EFI_STRING     StringPtrNext;
    867   EFI_STRING     BlockPtr;
    868   UINTN          ReallocateSize;
    869   CHAR16         TempChar;
    870   CHAR16         TempCharA;
    871   BOOLEAN        ConfigAltRespChanged;
    872 
    873   Status = EFI_OUT_OF_RESOURCES;
    874   BlockPtr             = NULL;
    875   AltConfigHdrPtrNext  = NULL;
    876   StringPtrNext        = NULL;
    877   ConfigAltResp        = NULL;
    878   AltCfgRespBackup     = NULL;
    879   TempChar             = L'\0';
    880   TempCharA            = L'\0';
    881   ConfigAltRespChanged = FALSE;
    882 
    883   //
    884   //To find the <AltResp> with AltConfigHdr in DefaultAltCfgResp, ignore other <AltResp> which follow it.
    885   //
    886   AltConfigHdrPtr = StrStr (DefaultAltCfgResp, AltConfigHdr);
    887   ASSERT (AltConfigHdrPtr != NULL);
    888   AltConfigHdrPtrNext = StrStr (AltConfigHdrPtr + 1, L"&GUID");
    889   if (AltConfigHdrPtrNext != NULL) {
    890     TempChar = *AltConfigHdrPtrNext;
    891     *AltConfigHdrPtrNext = L'\0';
    892   }
    893   //
    894   // To find the <AltResp> with AltConfigHdr in AltCfgResp, ignore other <AltResp> which follow it.
    895   //
    896   StringPtr = StrStr (*AltCfgResp, AltConfigHdr);
    897   StringPtrNext = StrStr (StringPtr + 1, L"&GUID");
    898   if (StringPtrNext != NULL) {
    899     TempCharA = *StringPtrNext;
    900     *StringPtrNext = L'\0';
    901   }
    902   //
    903   // Copy the content of <ConfigAltResp> which contain current AltConfigHdr in AltCfgResp.
    904   //
    905   ConfigAltResp = AllocateCopyPool (StrSize (*AltCfgResp), *AltCfgResp);
    906   if (ConfigAltResp == NULL) {
    907     goto Exit;
    908   }
    909   //
    910   // To find the <ConfigBody> with AltConfigHdr in DefaultAltCfgResp.
    911   //
    912   BlockPtr = StrStr (AltConfigHdrPtr, L"&OFFSET=");
    913   if (BlockPtr != NULL) {
    914     //
    915     // <BlockConfig>::='OFFSET='<Number>'&WIDTH='<Number>'&VALUE='<Number> style.
    916     // Call function CompareBlockElementDefault to compare the <BlockConfig> in DefaultAltCfgResp and ConfigAltResp.
    917     // The ConfigAltResp which may contain the new <BlockConfig> get from DefaultAltCfgResp.
    918     //
    919     Status = CompareBlockElementDefault (DefaultAltCfgResp, &ConfigAltResp, AltConfigHdr, &ConfigAltRespChanged);
    920     if (EFI_ERROR(Status)) {
    921       goto Exit;
    922     }
    923   } else {
    924     //
    925     // <NvConfig> ::= <Label>'='<String> | <Label>'='<Number> style.
    926     // Call function CompareNameElementDefault to compare the <NvConfig> in DefaultAltCfgResp and ConfigAltResp.
    927     // The ConfigAltResp which may contain the new <NvConfig> get from DefaultAltCfgResp.
    928     //
    929     Status = CompareNameElementDefault (DefaultAltCfgResp, &ConfigAltResp, AltConfigHdr, &ConfigAltRespChanged);
    930     if (EFI_ERROR(Status)) {
    931       goto Exit;
    932     }
    933   }
    934   //
    935   // Restore the AltCfgResp.
    936   //
    937   if (StringPtrNext != NULL) {
    938     *StringPtrNext = TempCharA;
    939   }
    940 
    941   //
    942   // If the ConfigAltResp has no change,no need to update the content in AltCfgResp.
    943   //
    944   if (!ConfigAltRespChanged) {
    945     Status = EFI_SUCCESS;
    946     goto Exit;
    947   }
    948   //
    949   // ConfigAltResp has been changed, need to update the content in AltCfgResp.
    950   //
    951   if (StringPtrNext != NULL) {
    952     ReallocateSize = StrSize (ConfigAltResp) + StrSize (StringPtrNext) + sizeof (CHAR16);
    953   } else {
    954     ReallocateSize = StrSize (ConfigAltResp) + sizeof (CHAR16);
    955   }
    956 
    957   AltCfgRespBackup = (EFI_STRING) AllocateZeroPool (ReallocateSize);
    958   if (AltCfgRespBackup == NULL) {
    959     goto Exit;
    960   }
    961 
    962   StrCatS (AltCfgRespBackup, ReallocateSize / sizeof (CHAR16), ConfigAltResp);
    963   if (StringPtrNext != NULL) {
    964     StrCatS (AltCfgRespBackup, ReallocateSize / sizeof (CHAR16), StringPtrNext);
    965   }
    966 
    967   FreePool (*AltCfgResp);
    968   *AltCfgResp = AltCfgRespBackup;
    969 
    970   Status = EFI_SUCCESS;
    971 
    972 Exit:
    973   if (ConfigAltResp != NULL) {
    974     FreePool(ConfigAltResp);
    975   }
    976   //
    977   // Restore the DefaultAltCfgResp.
    978   //
    979   if ( AltConfigHdrPtrNext != NULL) {
    980     *AltConfigHdrPtrNext = TempChar;
    981     AltConfigHdrPtrNext = NULL;
    982   }
    983 
    984   return Status;
    985 }
    986 
    987 /**
    988   This function merges DefaultAltCfgResp string into AltCfgResp string for
    989   the missing AltCfgId in AltCfgResq.
    990 
    991   @param  AltCfgResp             Pointer to a null-terminated Unicode string in
    992                                  <ConfigAltResp> format. The default value string
    993                                  will be merged into it.
    994   @param  DefaultAltCfgResp      Pointer to a null-terminated Unicode string in
    995                                  <MultiConfigAltResp> format. The default value
    996                                  string may contain more than one ConfigAltResp
    997                                  string for the different varstore buffer.
    998 
    999   @retval EFI_SUCCESS            The merged string returns.
   1000   @retval EFI_INVALID_PARAMETER  *AltCfgResp is to NULL.
   1001 **/
   1002 EFI_STATUS
   1003 EFIAPI
   1004 MergeDefaultString (
   1005   IN OUT EFI_STRING  *AltCfgResp,
   1006   IN     EFI_STRING  DefaultAltCfgResp
   1007   )
   1008 {
   1009   EFI_STRING   StringPtrDefault;
   1010   EFI_STRING   StringPtrEnd;
   1011   CHAR16       TempChar;
   1012   EFI_STRING   StringPtr;
   1013   EFI_STRING   AltConfigHdr;
   1014   UINTN        HeaderLength;
   1015   UINTN        SizeAltCfgResp;
   1016   UINTN        MaxLen;
   1017   UINTN        TotalSize;
   1018 
   1019   if (*AltCfgResp == NULL) {
   1020     return EFI_INVALID_PARAMETER;
   1021   }
   1022 
   1023   //
   1024   // Get the request ConfigHdr
   1025   //
   1026   SizeAltCfgResp  = 0;
   1027   StringPtr       = *AltCfgResp;
   1028 
   1029   //
   1030   // Find <ConfigHdr> GUID=...&NAME=...&PATH=...
   1031   //
   1032   if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {
   1033     return EFI_INVALID_PARAMETER;
   1034   }
   1035   while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&NAME=", StrLen (L"&NAME=")) != 0) {
   1036     StringPtr++;
   1037   }
   1038   while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&PATH=", StrLen (L"&PATH=")) != 0) {
   1039     StringPtr++;
   1040   }
   1041   if (*StringPtr == L'\0') {
   1042     return EFI_INVALID_PARAMETER;
   1043   }
   1044   StringPtr += StrLen (L"&PATH=");
   1045   while (*StringPtr != L'\0' && *StringPtr != L'&') {
   1046     StringPtr ++;
   1047   }
   1048   HeaderLength = StringPtr - *AltCfgResp;
   1049 
   1050   //
   1051   // Construct AltConfigHdr string  "&<ConfigHdr>&ALTCFG=XXXX\0"
   1052   //                                  |1| StrLen (ConfigHdr) | 8 | 4 | 1 |
   1053   //
   1054   MaxLen = 1 + HeaderLength + 8 + 4 + 1;
   1055   AltConfigHdr = AllocateZeroPool (MaxLen * sizeof (CHAR16));
   1056   if (AltConfigHdr == NULL) {
   1057     return EFI_OUT_OF_RESOURCES;
   1058   }
   1059   StrCpyS (AltConfigHdr, MaxLen, L"&");
   1060   StrnCatS (AltConfigHdr, MaxLen, *AltCfgResp, HeaderLength);
   1061   StrCatS (AltConfigHdr, MaxLen, L"&ALTCFG=");
   1062   HeaderLength = StrLen (AltConfigHdr);
   1063 
   1064   StringPtrDefault = StrStr (DefaultAltCfgResp, AltConfigHdr);
   1065   while (StringPtrDefault != NULL) {
   1066     //
   1067     // Get AltCfg Name
   1068     //
   1069     StrnCatS (AltConfigHdr, MaxLen, StringPtrDefault + HeaderLength, 4);
   1070     StringPtr = StrStr (*AltCfgResp, AltConfigHdr);
   1071 
   1072     //
   1073     // Append the found default value string to the input AltCfgResp
   1074     //
   1075     if (StringPtr == NULL) {
   1076       StringPtrEnd   = StrStr (StringPtrDefault + 1, L"&GUID");
   1077       SizeAltCfgResp = StrSize (*AltCfgResp);
   1078       if (StringPtrEnd == NULL) {
   1079         //
   1080         // No more default string is found.
   1081         //
   1082         TotalSize = SizeAltCfgResp + StrSize (StringPtrDefault);
   1083         *AltCfgResp    = (EFI_STRING) ReallocatePool (
   1084                                      SizeAltCfgResp,
   1085                                      TotalSize,
   1086                                      (VOID *) (*AltCfgResp)
   1087                                      );
   1088         if (*AltCfgResp == NULL) {
   1089           FreePool (AltConfigHdr);
   1090           return EFI_OUT_OF_RESOURCES;
   1091         }
   1092         StrCatS (*AltCfgResp, TotalSize / sizeof (CHAR16), StringPtrDefault);
   1093         break;
   1094       } else {
   1095         TempChar = *StringPtrEnd;
   1096         *StringPtrEnd = L'\0';
   1097         TotalSize = SizeAltCfgResp + StrSize (StringPtrDefault);
   1098         *AltCfgResp = (EFI_STRING) ReallocatePool (
   1099                                      SizeAltCfgResp,
   1100                                      TotalSize,
   1101                                      (VOID *) (*AltCfgResp)
   1102                                      );
   1103         if (*AltCfgResp == NULL) {
   1104           FreePool (AltConfigHdr);
   1105           return EFI_OUT_OF_RESOURCES;
   1106         }
   1107         StrCatS (*AltCfgResp, TotalSize / sizeof (CHAR16), StringPtrDefault);
   1108         *StringPtrEnd = TempChar;
   1109       }
   1110     } else {
   1111       //
   1112       // The AltCfgResp contains <AltCfgResp>.
   1113       // If the <ConfigElement> in <AltCfgResp> in the DefaultAltCfgResp but not in the
   1114       // related <AltCfgResp> in AltCfgResp, merge it to AltCfgResp. else no need to merge.
   1115       //
   1116       CompareAndMergeDefaultString (AltCfgResp, DefaultAltCfgResp, AltConfigHdr);
   1117     }
   1118 
   1119     //
   1120     // Find next AltCfg String
   1121     //
   1122     *(AltConfigHdr + HeaderLength) = L'\0';
   1123     StringPtrDefault = StrStr (StringPtrDefault + 1, AltConfigHdr);
   1124   }
   1125 
   1126   FreePool (AltConfigHdr);
   1127   return EFI_SUCCESS;
   1128 }
   1129 
   1130 /**
   1131   This function inserts new DefaultValueData into the BlockData DefaultValue array.
   1132 
   1133   @param  BlockData         The BlockData is updated to add new default value.
   1134   @param  DefaultValueData  The DefaultValue is added.
   1135 
   1136 **/
   1137 VOID
   1138 InsertDefaultValue (
   1139   IN IFR_BLOCK_DATA         *BlockData,
   1140   IN IFR_DEFAULT_DATA       *DefaultValueData
   1141   )
   1142 {
   1143   LIST_ENTRY             *Link;
   1144   IFR_DEFAULT_DATA       *DefaultValueArray;
   1145   LIST_ENTRY             *DefaultLink;
   1146 
   1147   DefaultLink   = &BlockData->DefaultValueEntry;
   1148 
   1149   for (Link = DefaultLink->ForwardLink; Link != DefaultLink; Link = Link->ForwardLink) {
   1150     DefaultValueArray = BASE_CR (Link, IFR_DEFAULT_DATA, Entry);
   1151     if (DefaultValueArray->DefaultId == DefaultValueData->DefaultId) {
   1152       //
   1153       // DEFAULT_VALUE_FROM_OPCODE has high priority, DEFAULT_VALUE_FROM_DEFAULT has low priority.
   1154       // When default types are DEFAULT_VALUE_FROM_OTHER_DEFAULT, the default value can be overrode.
   1155       //
   1156       if ((DefaultValueData->Type > DefaultValueArray->Type) || (DefaultValueData->Type == DefaultValueArray->Type && DefaultValueData->Type == DefaultValueFromOtherDefault)) {
   1157         //
   1158         // Update the default value array in BlockData.
   1159         //
   1160         CopyMem (&DefaultValueArray->Value, &DefaultValueData->Value, sizeof (EFI_IFR_TYPE_VALUE));
   1161         DefaultValueArray->Type  = DefaultValueData->Type;
   1162         DefaultValueArray->Cleaned = DefaultValueData->Cleaned;
   1163       }
   1164       return;
   1165     }
   1166   }
   1167 
   1168   //
   1169   // Insert new default value data in tail.
   1170   //
   1171   DefaultValueArray = AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));
   1172   ASSERT (DefaultValueArray != NULL);
   1173   CopyMem (DefaultValueArray, DefaultValueData, sizeof (IFR_DEFAULT_DATA));
   1174   InsertTailList (Link, &DefaultValueArray->Entry);
   1175 }
   1176 
   1177 /**
   1178   This function inserts new BlockData into the block link
   1179 
   1180   @param  BlockLink      The list entry points to block array.
   1181   @param  BlockData      The point to BlockData is added.
   1182 
   1183 **/
   1184 VOID
   1185 InsertBlockData (
   1186   IN LIST_ENTRY        *BlockLink,
   1187   IN IFR_BLOCK_DATA    **BlockData
   1188   )
   1189 {
   1190   LIST_ENTRY          *Link;
   1191   IFR_BLOCK_DATA      *BlockArray;
   1192   IFR_BLOCK_DATA      *BlockSingleData;
   1193 
   1194   BlockSingleData = *BlockData;
   1195 
   1196   if (BlockSingleData->Name != NULL) {
   1197     InsertTailList (BlockLink, &BlockSingleData->Entry);
   1198     return;
   1199   }
   1200 
   1201   //
   1202   // Insert block data in its Offset and Width order.
   1203   //
   1204   for (Link = BlockLink->ForwardLink; Link != BlockLink; Link = Link->ForwardLink) {
   1205     BlockArray = BASE_CR (Link, IFR_BLOCK_DATA, Entry);
   1206     if (BlockArray->Offset == BlockSingleData->Offset) {
   1207       if (BlockArray->Width > BlockSingleData->Width) {
   1208         //
   1209         // Insert this block data in the front of block array
   1210         //
   1211         InsertTailList (Link, &BlockSingleData->Entry);
   1212         return;
   1213       }
   1214 
   1215       if (BlockArray->Width == BlockSingleData->Width) {
   1216         //
   1217         // The same block array has been added.
   1218         //
   1219         if (BlockSingleData != BlockArray) {
   1220           FreePool (BlockSingleData);
   1221           *BlockData = BlockArray;
   1222         }
   1223         return;
   1224       }
   1225     } else if (BlockArray->Offset > BlockSingleData->Offset) {
   1226       //
   1227       // Insert new block data in the front of block array
   1228       //
   1229       InsertTailList (Link, &BlockSingleData->Entry);
   1230       return;
   1231     }
   1232   }
   1233 
   1234   //
   1235   // Add new block data into the tail.
   1236   //
   1237   InsertTailList (Link, &BlockSingleData->Entry);
   1238 }
   1239 
   1240 /**
   1241   Retrieves a pointer to the a Null-terminated ASCII string containing the list
   1242   of languages that an HII handle in the HII Database supports.  The returned
   1243   string is allocated using AllocatePool().  The caller is responsible for freeing
   1244   the returned string using FreePool().  The format of the returned string follows
   1245   the language format assumed the HII Database.
   1246 
   1247   If HiiHandle is NULL, then ASSERT().
   1248 
   1249   @param[in]  HiiHandle  A handle that was previously registered in the HII Database.
   1250 
   1251   @retval NULL   HiiHandle is not registered in the HII database
   1252   @retval NULL   There are not enough resources available to retrieve the supported
   1253                  languages.
   1254   @retval NULL   The list of supported languages could not be retrieved.
   1255   @retval Other  A pointer to the Null-terminated ASCII string of supported languages.
   1256 
   1257 **/
   1258 CHAR8 *
   1259 GetSupportedLanguages (
   1260   IN EFI_HII_HANDLE           HiiHandle
   1261   )
   1262 {
   1263   EFI_STATUS  Status;
   1264   UINTN       LanguageSize;
   1265   CHAR8       TempSupportedLanguages;
   1266   CHAR8       *SupportedLanguages;
   1267 
   1268   ASSERT (HiiHandle != NULL);
   1269 
   1270   //
   1271   // Retrieve the size required for the supported languages buffer.
   1272   //
   1273   LanguageSize = 0;
   1274   Status = mPrivate.HiiString.GetLanguages (&mPrivate.HiiString, HiiHandle, &TempSupportedLanguages, &LanguageSize);
   1275 
   1276   //
   1277   // If GetLanguages() returns EFI_SUCCESS for a zero size,
   1278   // then there are no supported languages registered for HiiHandle.  If GetLanguages()
   1279   // returns an error other than EFI_BUFFER_TOO_SMALL, then HiiHandle is not present
   1280   // in the HII Database
   1281   //
   1282   if (Status != EFI_BUFFER_TOO_SMALL) {
   1283     //
   1284     // Return NULL if the size can not be retrieved, or if HiiHandle is not in the HII Database
   1285     //
   1286     return NULL;
   1287   }
   1288 
   1289   //
   1290   // Allocate the supported languages buffer.
   1291   //
   1292   SupportedLanguages = AllocateZeroPool (LanguageSize);
   1293   if (SupportedLanguages == NULL) {
   1294     //
   1295     // Return NULL if allocation fails.
   1296     //
   1297     return NULL;
   1298   }
   1299 
   1300   //
   1301   // Retrieve the supported languages string
   1302   //
   1303   Status = mPrivate.HiiString.GetLanguages (&mPrivate.HiiString, HiiHandle, SupportedLanguages, &LanguageSize);
   1304   if (EFI_ERROR (Status)) {
   1305     //
   1306     // Free the buffer and return NULL if the supported languages can not be retrieved.
   1307     //
   1308     FreePool (SupportedLanguages);
   1309     return NULL;
   1310   }
   1311 
   1312   //
   1313   // Return the Null-terminated ASCII string of supported languages
   1314   //
   1315   return SupportedLanguages;
   1316 }
   1317 
   1318 /**
   1319   Retrieves a string from a string package.
   1320 
   1321   If HiiHandle is NULL, then ASSERT().
   1322   If StringId is 0, then ASSET.
   1323 
   1324   @param[in]  HiiHandle  A handle that was previously registered in the HII Database.
   1325   @param[in]  StringId   The identifier of the string to retrieved from the string
   1326                          package associated with HiiHandle.
   1327 
   1328   @retval NULL   The string specified by StringId is not present in the string package.
   1329   @retval Other  The string was returned.
   1330 
   1331 **/
   1332 EFI_STRING
   1333 InternalGetString (
   1334   IN EFI_HII_HANDLE  HiiHandle,
   1335   IN EFI_STRING_ID   StringId
   1336   )
   1337 {
   1338   EFI_STATUS  Status;
   1339   UINTN       StringSize;
   1340   CHAR16      TempString;
   1341   EFI_STRING  String;
   1342   CHAR8       *SupportedLanguages;
   1343   CHAR8       *PlatformLanguage;
   1344   CHAR8       *BestLanguage;
   1345   CHAR8       *Language;
   1346 
   1347   ASSERT (HiiHandle != NULL);
   1348   ASSERT (StringId != 0);
   1349 
   1350   //
   1351   // Initialize all allocated buffers to NULL
   1352   //
   1353   SupportedLanguages = NULL;
   1354   PlatformLanguage   = NULL;
   1355   BestLanguage       = NULL;
   1356   String             = NULL;
   1357   Language           = "";
   1358 
   1359   //
   1360   // Get the languages that the package specified by HiiHandle supports
   1361   //
   1362   SupportedLanguages = GetSupportedLanguages (HiiHandle);
   1363   if (SupportedLanguages == NULL) {
   1364     goto Error;
   1365   }
   1366 
   1367   //
   1368   // Get the current platform language setting
   1369   //
   1370   GetEfiGlobalVariable2 (L"PlatformLang", (VOID**)&PlatformLanguage, NULL);
   1371 
   1372   //
   1373   // Get the best matching language from SupportedLanguages
   1374   //
   1375   BestLanguage = GetBestLanguage (
   1376                    SupportedLanguages,
   1377                    FALSE,                                             // RFC 4646 mode
   1378                    Language,                                          // Highest priority
   1379                    PlatformLanguage != NULL ? PlatformLanguage : "",  // Next highest priority
   1380                    SupportedLanguages,                                // Lowest priority
   1381                    NULL
   1382                    );
   1383   if (BestLanguage == NULL) {
   1384     goto Error;
   1385   }
   1386 
   1387   //
   1388   // Retrieve the size of the string in the string package for the BestLanguage
   1389   //
   1390   StringSize = 0;
   1391   Status = mPrivate.HiiString.GetString (
   1392                          &mPrivate.HiiString,
   1393                          BestLanguage,
   1394                          HiiHandle,
   1395                          StringId,
   1396                          &TempString,
   1397                          &StringSize,
   1398                          NULL
   1399                          );
   1400   //
   1401   // If GetString() returns EFI_SUCCESS for a zero size,
   1402   // then there are no supported languages registered for HiiHandle.  If GetString()
   1403   // returns an error other than EFI_BUFFER_TOO_SMALL, then HiiHandle is not present
   1404   // in the HII Database
   1405   //
   1406   if (Status != EFI_BUFFER_TOO_SMALL) {
   1407     goto Error;
   1408   }
   1409 
   1410   //
   1411   // Allocate a buffer for the return string
   1412   //
   1413   String = AllocateZeroPool (StringSize);
   1414   if (String == NULL) {
   1415     goto Error;
   1416   }
   1417 
   1418   //
   1419   // Retrieve the string from the string package
   1420   //
   1421   Status = mPrivate.HiiString.GetString (
   1422                          &mPrivate.HiiString,
   1423                          BestLanguage,
   1424                          HiiHandle,
   1425                          StringId,
   1426                          String,
   1427                          &StringSize,
   1428                          NULL
   1429                          );
   1430   if (EFI_ERROR (Status)) {
   1431     //
   1432     // Free the buffer and return NULL if the supported languages can not be retrieved.
   1433     //
   1434     FreePool (String);
   1435     String = NULL;
   1436   }
   1437 
   1438 Error:
   1439   //
   1440   // Free allocated buffers
   1441   //
   1442   if (SupportedLanguages != NULL) {
   1443     FreePool (SupportedLanguages);
   1444   }
   1445   if (PlatformLanguage != NULL) {
   1446     FreePool (PlatformLanguage);
   1447   }
   1448   if (BestLanguage != NULL) {
   1449     FreePool (BestLanguage);
   1450   }
   1451 
   1452   //
   1453   // Return the Null-terminated Unicode string
   1454   //
   1455   return String;
   1456 }
   1457 
   1458 /**
   1459   This function checks VarOffset and VarWidth is in the block range.
   1460 
   1461   @param  RequestBlockArray  The block array is to be checked.
   1462   @param  VarOffset          Offset of var to the structure
   1463   @param  VarWidth           Width of var.
   1464   @param  IsNameValueType    Whether this varstore is name/value varstore or not.
   1465   @param  HiiHandle          Hii handle for this hii package.
   1466 
   1467   @retval TRUE   This Var is in the block range.
   1468   @retval FALSE  This Var is not in the block range.
   1469 **/
   1470 BOOLEAN
   1471 BlockArrayCheck (
   1472   IN IFR_BLOCK_DATA  *RequestBlockArray,
   1473   IN UINT16          VarOffset,
   1474   IN UINT16          VarWidth,
   1475   IN BOOLEAN         IsNameValueType,
   1476   IN EFI_HII_HANDLE  HiiHandle
   1477   )
   1478 {
   1479   LIST_ENTRY          *Link;
   1480   IFR_BLOCK_DATA      *BlockData;
   1481   EFI_STRING          Name;
   1482 
   1483   //
   1484   // No Request Block array, all vars are got.
   1485   //
   1486   if (RequestBlockArray == NULL) {
   1487     return TRUE;
   1488   }
   1489 
   1490   //
   1491   // Check the input var is in the request block range.
   1492   //
   1493   for (Link = RequestBlockArray->Entry.ForwardLink; Link != &RequestBlockArray->Entry; Link = Link->ForwardLink) {
   1494     BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);
   1495 
   1496     if (IsNameValueType) {
   1497       Name = InternalGetString (HiiHandle, VarOffset);
   1498       ASSERT (Name != NULL);
   1499 
   1500       if (StrnCmp (BlockData->Name, Name, StrLen (Name)) == 0) {
   1501         FreePool (Name);
   1502         return TRUE;
   1503       }
   1504       FreePool (Name);
   1505     } else {
   1506       if ((VarOffset >= BlockData->Offset) && ((VarOffset + VarWidth) <= (BlockData->Offset + BlockData->Width))) {
   1507         return TRUE;
   1508       }
   1509     }
   1510   }
   1511 
   1512   return FALSE;
   1513 }
   1514 
   1515 /**
   1516   Get form package data from data base.
   1517 
   1518   @param  DataBaseRecord         The DataBaseRecord instance contains the found Hii handle and package.
   1519   @param  HiiFormPackage         The buffer saves the package data.
   1520   @param  PackageSize            The buffer size of the package data.
   1521 
   1522 **/
   1523 EFI_STATUS
   1524 GetFormPackageData (
   1525   IN     HII_DATABASE_RECORD        *DataBaseRecord,
   1526   IN OUT UINT8                      **HiiFormPackage,
   1527   OUT    UINTN                      *PackageSize
   1528   )
   1529 {
   1530   EFI_STATUS                   Status;
   1531   UINTN                        Size;
   1532   UINTN                        ResultSize;
   1533 
   1534   if (DataBaseRecord == NULL || HiiFormPackage == NULL || PackageSize == NULL) {
   1535     return EFI_INVALID_PARAMETER;
   1536   }
   1537 
   1538   Size       = 0;
   1539   ResultSize = 0;
   1540   //
   1541   // 0. Get Hii Form Package by HiiHandle
   1542   //
   1543   Status = ExportFormPackages (
   1544              &mPrivate,
   1545              DataBaseRecord->Handle,
   1546              DataBaseRecord->PackageList,
   1547              0,
   1548              Size,
   1549              HiiFormPackage,
   1550              &ResultSize
   1551            );
   1552   if (EFI_ERROR (Status)) {
   1553     return Status;
   1554   }
   1555 
   1556   (*HiiFormPackage) = AllocatePool (ResultSize);
   1557   if (*HiiFormPackage == NULL) {
   1558     Status = EFI_OUT_OF_RESOURCES;
   1559     return Status;
   1560   }
   1561 
   1562   //
   1563   // Get HiiFormPackage by HiiHandle
   1564   //
   1565   Size   = ResultSize;
   1566   ResultSize    = 0;
   1567   Status = ExportFormPackages (
   1568              &mPrivate,
   1569              DataBaseRecord->Handle,
   1570              DataBaseRecord->PackageList,
   1571              0,
   1572              Size,
   1573              *HiiFormPackage,
   1574              &ResultSize
   1575            );
   1576   if (EFI_ERROR (Status)) {
   1577     FreePool (*HiiFormPackage);
   1578   }
   1579 
   1580   *PackageSize = Size;
   1581 
   1582   return Status;
   1583 }
   1584 
   1585 
   1586 /**
   1587   This function parses Form Package to get the efi varstore info according to the request ConfigHdr.
   1588 
   1589   @param  DataBaseRecord        The DataBaseRecord instance contains the found Hii handle and package.
   1590   @param  ConfigHdr             Request string ConfigHdr. If it is NULL,
   1591                                 the first found varstore will be as ConfigHdr.
   1592   @param  IsEfiVarstore         Whether the request storage type is efi varstore type.
   1593   @param  EfiVarStore           The efi varstore info which will return.
   1594 **/
   1595 EFI_STATUS
   1596 GetVarStoreType (
   1597   IN     HII_DATABASE_RECORD        *DataBaseRecord,
   1598   IN     EFI_STRING                 ConfigHdr,
   1599   OUT    BOOLEAN                    *IsEfiVarstore,
   1600   OUT    EFI_IFR_VARSTORE_EFI       **EfiVarStore
   1601   )
   1602 {
   1603   EFI_STATUS               Status;
   1604   UINTN                    IfrOffset;
   1605   UINTN                    PackageOffset;
   1606   EFI_IFR_OP_HEADER        *IfrOpHdr;
   1607   CHAR16                   *VarStoreName;
   1608   UINTN                    NameSize;
   1609   EFI_STRING               GuidStr;
   1610   EFI_STRING               NameStr;
   1611   EFI_STRING               TempStr;
   1612   UINTN                    LengthString;
   1613   UINT8                    *HiiFormPackage;
   1614   UINTN                    PackageSize;
   1615   EFI_IFR_VARSTORE_EFI     *IfrEfiVarStore;
   1616   EFI_HII_PACKAGE_HEADER   *PackageHeader;
   1617 
   1618   HiiFormPackage = NULL;
   1619   LengthString     = 0;
   1620   Status           = EFI_SUCCESS;
   1621   GuidStr          = NULL;
   1622   NameStr          = NULL;
   1623   TempStr          = NULL;
   1624   *IsEfiVarstore   = FALSE;
   1625 
   1626   Status = GetFormPackageData(DataBaseRecord, &HiiFormPackage, &PackageSize);
   1627   if (EFI_ERROR (Status)) {
   1628     return Status;
   1629   }
   1630 
   1631   IfrOffset     = sizeof (EFI_HII_PACKAGE_HEADER);
   1632   PackageOffset = IfrOffset;
   1633   PackageHeader = (EFI_HII_PACKAGE_HEADER *) HiiFormPackage;
   1634 
   1635   while (IfrOffset < PackageSize) {
   1636     //
   1637     // More than one form packages exist.
   1638     //
   1639     if (PackageOffset >= PackageHeader->Length) {
   1640         //
   1641         // Process the new form package.
   1642         //
   1643         PackageOffset = sizeof (EFI_HII_PACKAGE_HEADER);
   1644         IfrOffset    += PackageOffset;
   1645         PackageHeader = (EFI_HII_PACKAGE_HEADER *) (HiiFormPackage + IfrOffset);
   1646     }
   1647 
   1648     IfrOpHdr  = (EFI_IFR_OP_HEADER *) (HiiFormPackage + IfrOffset);
   1649     IfrOffset += IfrOpHdr->Length;
   1650     PackageOffset += IfrOpHdr->Length;
   1651 
   1652     if (IfrOpHdr->OpCode == EFI_IFR_VARSTORE_EFI_OP ) {
   1653       IfrEfiVarStore = (EFI_IFR_VARSTORE_EFI *) IfrOpHdr;
   1654       //
   1655       // If the length is small than the structure, this is from old efi
   1656       // varstore definition. Old efi varstore get config directly from
   1657       // GetVariable function.
   1658       //
   1659       if (IfrOpHdr->Length < sizeof (EFI_IFR_VARSTORE_EFI)) {
   1660         continue;
   1661       }
   1662 
   1663       NameSize = AsciiStrSize ((CHAR8 *)IfrEfiVarStore->Name);
   1664       VarStoreName = AllocateZeroPool (NameSize * sizeof (CHAR16));
   1665       if (VarStoreName == NULL) {
   1666         Status = EFI_OUT_OF_RESOURCES;
   1667         goto Done;
   1668       }
   1669       AsciiStrToUnicodeStrS ((CHAR8 *) IfrEfiVarStore->Name, VarStoreName, NameSize);
   1670 
   1671       GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (VOID *) &IfrEfiVarStore->Guid, 1, &GuidStr);
   1672       GenerateSubStr (L"NAME=", StrLen (VarStoreName) * sizeof (CHAR16), (VOID *) VarStoreName, 2, &NameStr);
   1673       LengthString = StrLen (GuidStr);
   1674       LengthString = LengthString + StrLen (NameStr) + 1;
   1675       TempStr = AllocateZeroPool (LengthString * sizeof (CHAR16));
   1676       if (TempStr == NULL) {
   1677         FreePool (GuidStr);
   1678         FreePool (NameStr);
   1679         FreePool (VarStoreName);
   1680         Status = EFI_OUT_OF_RESOURCES;
   1681         goto Done;
   1682       }
   1683       StrCpyS (TempStr, LengthString, GuidStr);
   1684       StrCatS (TempStr, LengthString, NameStr);
   1685       if (ConfigHdr == NULL || StrnCmp (ConfigHdr, TempStr, StrLen (TempStr)) == 0) {
   1686         *EfiVarStore = (EFI_IFR_VARSTORE_EFI *) AllocateZeroPool (IfrOpHdr->Length);
   1687         if (*EfiVarStore == NULL) {
   1688           FreePool (VarStoreName);
   1689           FreePool (GuidStr);
   1690           FreePool (NameStr);
   1691           FreePool (TempStr);
   1692           Status = EFI_OUT_OF_RESOURCES;
   1693           goto Done;
   1694         }
   1695         *IsEfiVarstore = TRUE;
   1696         CopyMem (*EfiVarStore, IfrEfiVarStore, IfrOpHdr->Length);
   1697       }
   1698 
   1699       //
   1700       // Free allocated temp string.
   1701       //
   1702       FreePool (VarStoreName);
   1703       FreePool (GuidStr);
   1704       FreePool (NameStr);
   1705       FreePool (TempStr);
   1706 
   1707       //
   1708       // Already found the varstore, break;
   1709       //
   1710       if (*IsEfiVarstore) {
   1711         break;
   1712       }
   1713     }
   1714   }
   1715 Done:
   1716   if (HiiFormPackage != NULL) {
   1717     FreePool (HiiFormPackage);
   1718   }
   1719 
   1720   return Status;
   1721 }
   1722 
   1723 /**
   1724   Check whether the ConfigRequest string has the request elements.
   1725   For EFI_HII_VARSTORE_BUFFER type, the request has "&OFFSET=****&WIDTH=****..." format.
   1726   For EFI_HII_VARSTORE_NAME_VALUE type, the request has "&NAME1**&NAME2..." format.
   1727 
   1728   @param  ConfigRequest      The input config request string.
   1729 
   1730   @retval  TRUE              The input include config request elements.
   1731   @retval  FALSE             The input string not includes.
   1732 
   1733 **/
   1734 BOOLEAN
   1735 GetElementsFromRequest (
   1736   IN EFI_STRING    ConfigRequest
   1737   )
   1738 {
   1739   EFI_STRING   TmpRequest;
   1740 
   1741   TmpRequest = StrStr (ConfigRequest, L"PATH=");
   1742   ASSERT (TmpRequest != NULL);
   1743 
   1744   if ((StrStr (TmpRequest, L"&OFFSET=") != NULL) || (StrStr (TmpRequest, L"&") != NULL)) {
   1745     return TRUE;
   1746   }
   1747 
   1748   return FALSE;
   1749 }
   1750 
   1751 /**
   1752   Check whether the this varstore is the request varstore.
   1753 
   1754   @param  VarstoreGuid      Varstore guid.
   1755   @param  Name              Varstore name.
   1756   @param  ConfigHdr         Current configRequest info.
   1757 
   1758   @retval  TRUE              This varstore is the request one.
   1759   @retval  FALSE             This varstore is not the request one.
   1760 
   1761 **/
   1762 BOOLEAN
   1763 IsThisVarstore (
   1764   IN EFI_GUID    *VarstoreGuid,
   1765   IN CHAR16      *Name,
   1766   IN CHAR16      *ConfigHdr
   1767   )
   1768 {
   1769   EFI_STRING               GuidStr;
   1770   EFI_STRING               NameStr;
   1771   EFI_STRING               TempStr;
   1772   UINTN                    LengthString;
   1773   BOOLEAN                  RetVal;
   1774 
   1775   RetVal       = FALSE;
   1776   GuidStr      = NULL;
   1777   TempStr      = NULL;
   1778 
   1779   //
   1780   // If ConfigHdr has name field and varstore not has name, return FALSE.
   1781   //
   1782   if (Name == NULL && ConfigHdr != NULL && StrStr (ConfigHdr, L"NAME=&") == NULL) {
   1783     return FALSE;
   1784   }
   1785 
   1786   GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (VOID *)VarstoreGuid, 1, &GuidStr);
   1787   if (Name != NULL) {
   1788     GenerateSubStr (L"NAME=", StrLen (Name) * sizeof (CHAR16), (VOID *) Name, 2, &NameStr);
   1789   } else {
   1790     GenerateSubStr (L"NAME=", 0, NULL, 2, &NameStr);
   1791   }
   1792   LengthString = StrLen (GuidStr);
   1793   LengthString = LengthString + StrLen (NameStr) + 1;
   1794   TempStr = AllocateZeroPool (LengthString * sizeof (CHAR16));
   1795   if (TempStr == NULL) {
   1796     goto Done;
   1797   }
   1798 
   1799   StrCpyS (TempStr, LengthString, GuidStr);
   1800   StrCatS (TempStr, LengthString, NameStr);
   1801 
   1802   if (ConfigHdr == NULL || StrnCmp (ConfigHdr, TempStr, StrLen (TempStr)) == 0) {
   1803     RetVal = TRUE;
   1804   }
   1805 
   1806 Done:
   1807   if (GuidStr != NULL) {
   1808     FreePool (GuidStr);
   1809   }
   1810 
   1811   if (NameStr != NULL) {
   1812     FreePool (NameStr);
   1813   }
   1814 
   1815   if (TempStr != NULL) {
   1816     FreePool (TempStr);
   1817   }
   1818 
   1819   return RetVal;
   1820 }
   1821 
   1822 /**
   1823   This function parses Form Package to get the efi varstore info according to the request ConfigHdr.
   1824 
   1825   @param  DataBaseRecord        The DataBaseRecord instance contains the found Hii handle and package.
   1826   @param  ConfigHdr             Request string ConfigHdr. If it is NULL,
   1827                                 the first found varstore will be as ConfigHdr.
   1828   @retval  TRUE                 This hii package is the request one.
   1829   @retval  FALSE                This hii package is not the request one.
   1830 **/
   1831 BOOLEAN
   1832 IsThisPackageList (
   1833   IN     HII_DATABASE_RECORD        *DataBaseRecord,
   1834   IN     EFI_STRING                 ConfigHdr
   1835   )
   1836 {
   1837   EFI_STATUS               Status;
   1838   UINTN                    IfrOffset;
   1839   UINTN                    PackageOffset;
   1840   EFI_IFR_OP_HEADER        *IfrOpHdr;
   1841   CHAR16                   *VarStoreName;
   1842   UINTN                    NameSize;
   1843   UINT8                    *HiiFormPackage;
   1844   UINTN                    PackageSize;
   1845   EFI_IFR_VARSTORE_EFI     *IfrEfiVarStore;
   1846   EFI_HII_PACKAGE_HEADER   *PackageHeader;
   1847   EFI_IFR_VARSTORE         *IfrVarStore;
   1848   EFI_IFR_VARSTORE_NAME_VALUE *IfrNameValueVarStore;
   1849   BOOLEAN                  FindVarstore;
   1850 
   1851   HiiFormPackage   = NULL;
   1852   VarStoreName     = NULL;
   1853   Status           = EFI_SUCCESS;
   1854   FindVarstore     = FALSE;
   1855 
   1856   Status = GetFormPackageData(DataBaseRecord, &HiiFormPackage, &PackageSize);
   1857   if (EFI_ERROR (Status)) {
   1858     return FALSE;
   1859   }
   1860 
   1861   IfrOffset     = sizeof (EFI_HII_PACKAGE_HEADER);
   1862   PackageOffset = IfrOffset;
   1863   PackageHeader = (EFI_HII_PACKAGE_HEADER *) HiiFormPackage;
   1864 
   1865   while (IfrOffset < PackageSize) {
   1866     //
   1867     // More than one form packages exist.
   1868     //
   1869     if (PackageOffset >= PackageHeader->Length) {
   1870         //
   1871         // Process the new form package.
   1872         //
   1873         PackageOffset = sizeof (EFI_HII_PACKAGE_HEADER);
   1874         IfrOffset    += PackageOffset;
   1875         PackageHeader = (EFI_HII_PACKAGE_HEADER *) (HiiFormPackage + IfrOffset);
   1876     }
   1877 
   1878     IfrOpHdr  = (EFI_IFR_OP_HEADER *) (HiiFormPackage + IfrOffset);
   1879     IfrOffset += IfrOpHdr->Length;
   1880     PackageOffset += IfrOpHdr->Length;
   1881 
   1882     switch (IfrOpHdr->OpCode) {
   1883 
   1884     case EFI_IFR_VARSTORE_OP:
   1885       IfrVarStore = (EFI_IFR_VARSTORE *) IfrOpHdr;
   1886 
   1887       NameSize = AsciiStrSize ((CHAR8 *)IfrVarStore->Name);
   1888       VarStoreName = AllocateZeroPool (NameSize * sizeof (CHAR16));
   1889       if (VarStoreName == NULL) {
   1890         goto Done;
   1891       }
   1892       AsciiStrToUnicodeStrS ((CHAR8 *)IfrVarStore->Name, VarStoreName, NameSize);
   1893 
   1894       if (IsThisVarstore((VOID *)&IfrVarStore->Guid, VarStoreName, ConfigHdr)) {
   1895         FindVarstore = TRUE;
   1896         goto Done;
   1897       } else {
   1898         FreePool (VarStoreName);
   1899         VarStoreName = NULL;
   1900       }
   1901       break;
   1902 
   1903     case EFI_IFR_VARSTORE_EFI_OP:
   1904       IfrEfiVarStore = (EFI_IFR_VARSTORE_EFI *) IfrOpHdr;
   1905       NameSize = AsciiStrSize ((CHAR8 *)IfrEfiVarStore->Name);
   1906       VarStoreName = AllocateZeroPool (NameSize * sizeof (CHAR16));
   1907       if (VarStoreName == NULL) {
   1908         goto Done;
   1909       }
   1910       AsciiStrToUnicodeStrS ((CHAR8 *)IfrEfiVarStore->Name, VarStoreName, NameSize);
   1911 
   1912       if (IsThisVarstore (&IfrEfiVarStore->Guid, VarStoreName, ConfigHdr)) {
   1913         FindVarstore = TRUE;
   1914         goto Done;
   1915       } else {
   1916         FreePool (VarStoreName);
   1917         VarStoreName = NULL;
   1918       }
   1919       break;
   1920 
   1921     case EFI_IFR_VARSTORE_NAME_VALUE_OP:
   1922       IfrNameValueVarStore = (EFI_IFR_VARSTORE_NAME_VALUE *) IfrOpHdr;
   1923 
   1924       if (IsThisVarstore (&IfrNameValueVarStore->Guid, NULL, ConfigHdr)) {
   1925         FindVarstore = TRUE;
   1926         goto Done;
   1927       }
   1928       break;
   1929 
   1930     case EFI_IFR_FORM_OP:
   1931     case EFI_IFR_FORM_MAP_OP:
   1932       //
   1933       // No matched varstore is found and directly return.
   1934       //
   1935       goto Done;
   1936 
   1937     default:
   1938       break;
   1939     }
   1940   }
   1941 Done:
   1942   if (HiiFormPackage != NULL) {
   1943     FreePool (HiiFormPackage);
   1944   }
   1945 
   1946   if (VarStoreName != NULL) {
   1947     FreePool (VarStoreName);
   1948   }
   1949 
   1950   return FindVarstore;
   1951 }
   1952 
   1953 /**
   1954   Check whether the this op code is required.
   1955 
   1956   @param  RequestBlockArray      The array includes all the request info or NULL.
   1957   @param  HiiHandle              The hii handle for this form package.
   1958   @param  VarStorageData         The varstore data structure.
   1959   @param  IfrOpHdr               Ifr opcode header for this opcode.
   1960   @param  VarWidth               The buffer width for this opcode.
   1961   @param  ReturnData             The data block added for this opcode.
   1962 
   1963   @retval  EFI_SUCCESS           This opcode is required.
   1964   @retval  EFI_NOT_FOUND         This opcode is not required.
   1965   @retval  Others                Contain some error.
   1966 
   1967 **/
   1968 EFI_STATUS
   1969 IsThisOpcodeRequired (
   1970   IN     IFR_BLOCK_DATA           *RequestBlockArray,
   1971   IN     EFI_HII_HANDLE           HiiHandle,
   1972   IN OUT IFR_VARSTORAGE_DATA      *VarStorageData,
   1973   IN     EFI_IFR_OP_HEADER        *IfrOpHdr,
   1974   IN     UINT16                   VarWidth,
   1975   OUT    IFR_BLOCK_DATA           **ReturnData
   1976   )
   1977 {
   1978   IFR_BLOCK_DATA           *BlockData;
   1979   UINT16                   VarOffset;
   1980   EFI_STRING_ID            NameId;
   1981   EFI_IFR_QUESTION_HEADER  *IfrQuestionHdr;
   1982 
   1983   NameId    = 0;
   1984   VarOffset = 0;
   1985   IfrQuestionHdr = (EFI_IFR_QUESTION_HEADER  *)((CHAR8 *) IfrOpHdr + sizeof (EFI_IFR_OP_HEADER));
   1986 
   1987   if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {
   1988     NameId = IfrQuestionHdr->VarStoreInfo.VarName;
   1989 
   1990     //
   1991     // Check whether this question is in requested block array.
   1992     //
   1993     if (!BlockArrayCheck (RequestBlockArray, NameId, 0, TRUE, HiiHandle)) {
   1994       //
   1995       // This question is not in the requested string. Skip it.
   1996       //
   1997       return EFI_NOT_FOUND;
   1998     }
   1999   } else {
   2000     VarOffset = IfrQuestionHdr->VarStoreInfo.VarOffset;
   2001 
   2002     //
   2003     // Check whether this question is in requested block array.
   2004     //
   2005     if (!BlockArrayCheck (RequestBlockArray, VarOffset, VarWidth, FALSE, HiiHandle)) {
   2006       //
   2007       // This question is not in the requested string. Skip it.
   2008       //
   2009       return EFI_NOT_FOUND;
   2010     }
   2011 
   2012     //
   2013     // Check this var question is in the var storage
   2014     //
   2015     if (((VarOffset + VarWidth) > VarStorageData->Size)) {
   2016       return EFI_INVALID_PARAMETER;
   2017     }
   2018   }
   2019 
   2020   BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));
   2021   if (BlockData == NULL) {
   2022     return EFI_OUT_OF_RESOURCES;
   2023   }
   2024 
   2025   if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {
   2026     BlockData->Name   = InternalGetString(HiiHandle, NameId);
   2027   } else {
   2028     BlockData->Offset = VarOffset;
   2029   }
   2030 
   2031   BlockData->Width      = VarWidth;
   2032   BlockData->QuestionId = IfrQuestionHdr->QuestionId;
   2033   BlockData->OpCode     = IfrOpHdr->OpCode;
   2034   BlockData->Scope      = IfrOpHdr->Scope;
   2035   InitializeListHead (&BlockData->DefaultValueEntry);
   2036   //
   2037   // Add Block Data into VarStorageData BlockEntry
   2038   //
   2039   InsertBlockData (&VarStorageData->BlockEntry, &BlockData);
   2040   *ReturnData = BlockData;
   2041 
   2042   return EFI_SUCCESS;
   2043 }
   2044 
   2045 /**
   2046   This function parses Form Package to get the block array and the default
   2047   value array according to the request ConfigHdr.
   2048 
   2049   @param  HiiHandle             Hii Handle for this hii package.
   2050   @param  Package               Pointer to the form package data.
   2051   @param  PackageLength         Length of the package.
   2052   @param  ConfigHdr             Request string ConfigHdr. If it is NULL,
   2053                                 the first found varstore will be as ConfigHdr.
   2054   @param  RequestBlockArray     The block array is retrieved from the request string.
   2055   @param  VarStorageData        VarStorage structure contains the got block and default value.
   2056   @param  DefaultIdArray        Point to the got default id and default name array.
   2057 
   2058   @retval EFI_SUCCESS           The block array and the default value array are got.
   2059   @retval EFI_INVALID_PARAMETER The varstore definition in the different form packages
   2060                                 are conflicted.
   2061   @retval EFI_OUT_OF_RESOURCES  No enough memory.
   2062 **/
   2063 EFI_STATUS
   2064 EFIAPI
   2065 ParseIfrData (
   2066   IN     EFI_HII_HANDLE      HiiHandle,
   2067   IN     UINT8               *Package,
   2068   IN     UINT32              PackageLength,
   2069   IN     EFI_STRING          ConfigHdr,
   2070   IN     IFR_BLOCK_DATA      *RequestBlockArray,
   2071   IN OUT IFR_VARSTORAGE_DATA *VarStorageData,
   2072   OUT    IFR_DEFAULT_DATA    *DefaultIdArray
   2073   )
   2074 {
   2075   EFI_STATUS               Status;
   2076   UINTN                    IfrOffset;
   2077   UINTN                    PackageOffset;
   2078   EFI_IFR_VARSTORE         *IfrVarStore;
   2079   EFI_IFR_VARSTORE_EFI     *IfrEfiVarStore;
   2080   EFI_IFR_OP_HEADER        *IfrOpHdr;
   2081   EFI_IFR_ONE_OF           *IfrOneOf;
   2082   EFI_IFR_REF4             *IfrRef;
   2083   EFI_IFR_ONE_OF_OPTION    *IfrOneOfOption;
   2084   EFI_IFR_DEFAULT          *IfrDefault;
   2085   EFI_IFR_ORDERED_LIST     *IfrOrderedList;
   2086   EFI_IFR_CHECKBOX         *IfrCheckBox;
   2087   EFI_IFR_PASSWORD         *IfrPassword;
   2088   EFI_IFR_STRING           *IfrString;
   2089   EFI_IFR_DATE             *IfrDate;
   2090   EFI_IFR_TIME             *IfrTime;
   2091   IFR_DEFAULT_DATA         DefaultData;
   2092   IFR_DEFAULT_DATA         *DefaultDataPtr;
   2093   IFR_BLOCK_DATA           *BlockData;
   2094   CHAR16                   *VarStoreName;
   2095   UINTN                    NameSize;
   2096   UINT16                   VarWidth;
   2097   UINT16                   VarDefaultId;
   2098   BOOLEAN                  FirstOneOfOption;
   2099   BOOLEAN                  FirstOrderedList;
   2100   LIST_ENTRY               *LinkData;
   2101   LIST_ENTRY               *LinkDefault;
   2102   EFI_IFR_VARSTORE_NAME_VALUE *IfrNameValueVarStore;
   2103   EFI_HII_PACKAGE_HEADER   *PackageHeader;
   2104   EFI_VARSTORE_ID          VarStoreId;
   2105   UINT16                   SmallestDefaultId;
   2106   BOOLEAN                  SmallestIdFromFlag;
   2107   BOOLEAN                  FromOtherDefaultOpcode;
   2108 
   2109   Status           = EFI_SUCCESS;
   2110   BlockData        = NULL;
   2111   DefaultDataPtr   = NULL;
   2112   FirstOneOfOption = FALSE;
   2113   VarStoreId       = 0;
   2114   FirstOrderedList = FALSE;
   2115   VarStoreName     = NULL;
   2116   ZeroMem (&DefaultData, sizeof (IFR_DEFAULT_DATA));
   2117   SmallestDefaultId = 0xFFFF;
   2118   FromOtherDefaultOpcode = FALSE;
   2119 
   2120   //
   2121   // Go through the form package to parse OpCode one by one.
   2122   //
   2123   PackageOffset = sizeof (EFI_HII_PACKAGE_HEADER);
   2124   PackageHeader = (EFI_HII_PACKAGE_HEADER *) Package;
   2125   IfrOffset     = PackageOffset;
   2126   while (IfrOffset < PackageLength) {
   2127 
   2128     //
   2129     // More than one form package found.
   2130     //
   2131     if (PackageOffset >= PackageHeader->Length) {
   2132         //
   2133         // Already found varstore for this request, break;
   2134         //
   2135         if (VarStoreId != 0) {
   2136           VarStoreId = 0;
   2137         }
   2138 
   2139         //
   2140         // Get next package header info.
   2141         //
   2142         IfrOffset    += sizeof (EFI_HII_PACKAGE_HEADER);
   2143         PackageOffset = sizeof (EFI_HII_PACKAGE_HEADER);
   2144         PackageHeader = (EFI_HII_PACKAGE_HEADER *) (Package + IfrOffset);
   2145     }
   2146 
   2147     IfrOpHdr  = (EFI_IFR_OP_HEADER *) (Package + IfrOffset);
   2148     switch (IfrOpHdr->OpCode) {
   2149     case EFI_IFR_VARSTORE_OP:
   2150       //
   2151       // VarStore is found. Don't need to search any more.
   2152       //
   2153       if (VarStoreId != 0) {
   2154         break;
   2155       }
   2156 
   2157       IfrVarStore = (EFI_IFR_VARSTORE *) IfrOpHdr;
   2158 
   2159       NameSize = AsciiStrSize ((CHAR8 *)IfrVarStore->Name);
   2160       VarStoreName = AllocateZeroPool (NameSize * sizeof (CHAR16));
   2161       if (VarStoreName == NULL) {
   2162         Status = EFI_OUT_OF_RESOURCES;
   2163         goto Done;
   2164       }
   2165       AsciiStrToUnicodeStrS ((CHAR8 *)IfrVarStore->Name, VarStoreName, NameSize);
   2166 
   2167       if (IsThisVarstore((VOID *)&IfrVarStore->Guid, VarStoreName, ConfigHdr)) {
   2168         //
   2169         // Find the matched VarStore
   2170         //
   2171         CopyGuid (&VarStorageData->Guid, (EFI_GUID *) (VOID *) &IfrVarStore->Guid);
   2172         VarStorageData->Size       = IfrVarStore->Size;
   2173         VarStorageData->Name       = VarStoreName;
   2174         VarStorageData->Type       = EFI_HII_VARSTORE_BUFFER;
   2175         VarStoreId                 = IfrVarStore->VarStoreId;
   2176       } else {
   2177         FreePool (VarStoreName);
   2178         VarStoreName = NULL;
   2179       }
   2180       break;
   2181 
   2182     case EFI_IFR_VARSTORE_EFI_OP:
   2183       //
   2184       // VarStore is found. Don't need to search any more.
   2185       //
   2186       if (VarStoreId != 0) {
   2187         break;
   2188       }
   2189 
   2190       IfrEfiVarStore = (EFI_IFR_VARSTORE_EFI *) IfrOpHdr;
   2191 
   2192       //
   2193       // If the length is small than the structure, this is from old efi
   2194       // varstore definition. Old efi varstore get config directly from
   2195       // GetVariable function.
   2196       //
   2197       if (IfrOpHdr->Length < sizeof (EFI_IFR_VARSTORE_EFI)) {
   2198         break;
   2199       }
   2200 
   2201       NameSize = AsciiStrSize ((CHAR8 *)IfrEfiVarStore->Name);
   2202       VarStoreName = AllocateZeroPool (NameSize * sizeof (CHAR16));
   2203       if (VarStoreName == NULL) {
   2204         Status = EFI_OUT_OF_RESOURCES;
   2205         goto Done;
   2206       }
   2207       AsciiStrToUnicodeStrS ((CHAR8 *)IfrEfiVarStore->Name, VarStoreName, NameSize);
   2208 
   2209       if (IsThisVarstore (&IfrEfiVarStore->Guid, VarStoreName, ConfigHdr)) {
   2210         //
   2211         // Find the matched VarStore
   2212         //
   2213         CopyGuid (&VarStorageData->Guid, (EFI_GUID *) (VOID *) &IfrEfiVarStore->Guid);
   2214         VarStorageData->Size       = IfrEfiVarStore->Size;
   2215         VarStorageData->Name       = VarStoreName;
   2216         VarStorageData->Type       = EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER;
   2217         VarStoreId                 = IfrEfiVarStore->VarStoreId;
   2218       } else {
   2219         FreePool (VarStoreName);
   2220         VarStoreName = NULL;
   2221       }
   2222       break;
   2223 
   2224     case EFI_IFR_VARSTORE_NAME_VALUE_OP:
   2225       //
   2226       // VarStore is found. Don't need to search any more.
   2227       //
   2228       if (VarStoreId != 0) {
   2229         break;
   2230       }
   2231 
   2232       IfrNameValueVarStore = (EFI_IFR_VARSTORE_NAME_VALUE *) IfrOpHdr;
   2233 
   2234       if (IsThisVarstore (&IfrNameValueVarStore->Guid, NULL, ConfigHdr)) {
   2235         //
   2236         // Find the matched VarStore
   2237         //
   2238         CopyGuid (&VarStorageData->Guid, (EFI_GUID *) (VOID *) &IfrNameValueVarStore->Guid);
   2239         VarStorageData->Type       = EFI_HII_VARSTORE_NAME_VALUE;
   2240         VarStoreId                 = IfrNameValueVarStore->VarStoreId;
   2241       }
   2242       break;
   2243 
   2244     case EFI_IFR_DEFAULTSTORE_OP:
   2245       //
   2246       // Add new the map between default id and default name.
   2247       //
   2248       DefaultDataPtr = (IFR_DEFAULT_DATA *) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));
   2249       if (DefaultDataPtr == NULL) {
   2250         Status = EFI_OUT_OF_RESOURCES;
   2251         goto Done;
   2252       }
   2253       DefaultDataPtr->DefaultId   = ((EFI_IFR_DEFAULTSTORE *) IfrOpHdr)->DefaultId;
   2254       InsertTailList (&DefaultIdArray->Entry, &DefaultDataPtr->Entry);
   2255       DefaultDataPtr = NULL;
   2256       break;
   2257 
   2258     case EFI_IFR_FORM_OP:
   2259     case EFI_IFR_FORM_MAP_OP:
   2260       //
   2261       // No matched varstore is found and directly return.
   2262       //
   2263       if ( VarStoreId == 0) {
   2264         Status = EFI_SUCCESS;
   2265         goto Done;
   2266       }
   2267       break;
   2268 
   2269     case EFI_IFR_REF_OP:
   2270       //
   2271       // Ref question is not in IFR Form. This IFR form is not valid.
   2272       //
   2273       if ( VarStoreId == 0) {
   2274         Status = EFI_INVALID_PARAMETER;
   2275         goto Done;
   2276       }
   2277       //
   2278       // Check whether this question is for the requested varstore.
   2279       //
   2280       IfrRef = (EFI_IFR_REF4 *) IfrOpHdr;
   2281       if (IfrRef->Question.VarStoreId != VarStoreId) {
   2282         break;
   2283       }
   2284       VarWidth  = (UINT16) (sizeof (EFI_HII_REF));
   2285 
   2286       //
   2287       // The BlockData may allocate by other opcode,need to clean.
   2288       //
   2289       if (BlockData != NULL){
   2290         BlockData = NULL;
   2291       }
   2292 
   2293       Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);
   2294       if (EFI_ERROR (Status)) {
   2295         if (Status == EFI_NOT_FOUND){
   2296           //
   2297           //The opcode is not required,exit and parse other opcode.
   2298           //
   2299           break;
   2300         }
   2301         goto Done;
   2302       }
   2303       break;
   2304 
   2305     case EFI_IFR_ONE_OF_OP:
   2306     case EFI_IFR_NUMERIC_OP:
   2307       //
   2308       // Numeric and OneOf has the same opcode structure.
   2309       //
   2310 
   2311       //
   2312       // Numeric and OneOf question is not in IFR Form. This IFR form is not valid.
   2313       //
   2314       if (VarStoreId == 0) {
   2315         Status = EFI_INVALID_PARAMETER;
   2316         goto Done;
   2317       }
   2318       //
   2319       // Check whether this question is for the requested varstore.
   2320       //
   2321       IfrOneOf = (EFI_IFR_ONE_OF *) IfrOpHdr;
   2322       if (IfrOneOf->Question.VarStoreId != VarStoreId) {
   2323         break;
   2324       }
   2325       VarWidth  = (UINT16) (1 << (IfrOneOf->Flags & EFI_IFR_NUMERIC_SIZE));
   2326 
   2327       //
   2328       // The BlockData may allocate by other opcode,need to clean.
   2329       //
   2330       if (BlockData != NULL){
   2331         BlockData = NULL;
   2332       }
   2333 
   2334       Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);
   2335       if (EFI_ERROR (Status)) {
   2336         if (Status == EFI_NOT_FOUND){
   2337           //
   2338           //The opcode is not required,exit and parse other opcode.
   2339           //
   2340           break;
   2341         }
   2342         goto Done;
   2343       }
   2344 
   2345       //
   2346       //when go to there,BlockData can't be NULLL.
   2347       //
   2348       ASSERT (BlockData != NULL);
   2349 
   2350       if (IfrOpHdr->OpCode == EFI_IFR_ONE_OF_OP) {
   2351         //
   2352         // Set this flag to TRUE for the first oneof option.
   2353         //
   2354         FirstOneOfOption = TRUE;
   2355       } else if (IfrOpHdr->OpCode == EFI_IFR_NUMERIC_OP) {
   2356         //
   2357         // Numeric minimum value will be used as default value when no default is specified.
   2358         //
   2359         DefaultData.Type        = DefaultValueFromDefault;
   2360         switch (IfrOneOf->Flags & EFI_IFR_NUMERIC_SIZE) {
   2361         case EFI_IFR_NUMERIC_SIZE_1:
   2362           DefaultData.Value.u8 = IfrOneOf->data.u8.MinValue;
   2363           break;
   2364 
   2365         case EFI_IFR_NUMERIC_SIZE_2:
   2366           CopyMem (&DefaultData.Value.u16, &IfrOneOf->data.u16.MinValue, sizeof (UINT16));
   2367           break;
   2368 
   2369         case EFI_IFR_NUMERIC_SIZE_4:
   2370           CopyMem (&DefaultData.Value.u32, &IfrOneOf->data.u32.MinValue, sizeof (UINT32));
   2371           break;
   2372 
   2373         case EFI_IFR_NUMERIC_SIZE_8:
   2374           CopyMem (&DefaultData.Value.u64, &IfrOneOf->data.u64.MinValue, sizeof (UINT64));
   2375           break;
   2376 
   2377         default:
   2378           Status = EFI_INVALID_PARAMETER;
   2379           goto Done;
   2380         }
   2381         //
   2382         // Set default value base on the DefaultId list get from IFR data.
   2383         //
   2384         for (LinkData = DefaultIdArray->Entry.ForwardLink; LinkData != &DefaultIdArray->Entry; LinkData = LinkData->ForwardLink) {
   2385           DefaultDataPtr = BASE_CR (LinkData, IFR_DEFAULT_DATA, Entry);
   2386           DefaultData.DefaultId   = DefaultDataPtr->DefaultId;
   2387           InsertDefaultValue (BlockData, &DefaultData);
   2388         }
   2389       }
   2390       break;
   2391 
   2392     case EFI_IFR_ORDERED_LIST_OP:
   2393       //
   2394       // offset by question header
   2395       // width by EFI_IFR_ORDERED_LIST MaxContainers * OneofOption Type
   2396       //
   2397 
   2398       FirstOrderedList = TRUE;
   2399       //
   2400       // OrderedList question is not in IFR Form. This IFR form is not valid.
   2401       //
   2402       if (VarStoreId == 0) {
   2403         Status = EFI_INVALID_PARAMETER;
   2404         goto Done;
   2405       }
   2406       //
   2407       // Check whether this question is for the requested varstore.
   2408       //
   2409       IfrOrderedList = (EFI_IFR_ORDERED_LIST *) IfrOpHdr;
   2410       if (IfrOrderedList->Question.VarStoreId != VarStoreId) {
   2411         BlockData = NULL;
   2412         break;
   2413       }
   2414       VarWidth  = IfrOrderedList->MaxContainers;
   2415 
   2416       //
   2417       // The BlockData may allocate by other opcode,need to clean.
   2418       //
   2419       if (BlockData != NULL){
   2420         BlockData = NULL;
   2421       }
   2422 
   2423       Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);
   2424       if (EFI_ERROR (Status)) {
   2425         if (Status == EFI_NOT_FOUND){
   2426           //
   2427           //The opcode is not required,exit and parse other opcode.
   2428           //
   2429           break;
   2430         }
   2431         goto Done;
   2432       }
   2433       break;
   2434 
   2435     case EFI_IFR_CHECKBOX_OP:
   2436       //
   2437       // EFI_IFR_DEFAULT_OP
   2438       // offset by question header
   2439       // width is 1 sizeof (BOOLEAN)
   2440       // default id by CheckBox Flags if CheckBox flags (Default or Mau) is set, the default value is 1 to be set.
   2441       // value by DefaultOption
   2442       // default id by DeaultOption DefaultId can override CheckBox Flags and Default value.
   2443       //
   2444 
   2445       //
   2446       // CheckBox question is not in IFR Form. This IFR form is not valid.
   2447       //
   2448       if (VarStoreId == 0) {
   2449         Status = EFI_INVALID_PARAMETER;
   2450         goto Done;
   2451       }
   2452       //
   2453       // Check whether this question is for the requested varstore.
   2454       //
   2455       IfrCheckBox = (EFI_IFR_CHECKBOX *) IfrOpHdr;
   2456       if (IfrCheckBox->Question.VarStoreId != VarStoreId) {
   2457         break;
   2458       }
   2459       VarWidth  = (UINT16) sizeof (BOOLEAN);
   2460 
   2461       //
   2462       // The BlockData may allocate by other opcode,need to clean.
   2463       //
   2464       if (BlockData != NULL){
   2465         BlockData = NULL;
   2466       }
   2467 
   2468       Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);
   2469       if (EFI_ERROR (Status)) {
   2470         if (Status == EFI_NOT_FOUND){
   2471           //
   2472           //The opcode is not required,exit and parse other opcode.
   2473           //
   2474           break;
   2475         }
   2476         goto Done;
   2477       }
   2478 
   2479       //
   2480       //when go to there,BlockData can't be NULLL.
   2481       //
   2482       ASSERT (BlockData != NULL);
   2483 
   2484       SmallestIdFromFlag = FALSE;
   2485 
   2486       //
   2487       // Add default value for standard ID by CheckBox Flag
   2488       //
   2489       VarDefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;
   2490       //
   2491       // Prepare new DefaultValue
   2492       //
   2493       DefaultData.DefaultId   = VarDefaultId;
   2494       if ((IfrCheckBox->Flags & EFI_IFR_CHECKBOX_DEFAULT) == EFI_IFR_CHECKBOX_DEFAULT) {
   2495         //
   2496         // When flag is set, default value is TRUE.
   2497         //
   2498         DefaultData.Type    = DefaultValueFromFlag;
   2499         DefaultData.Value.b = TRUE;
   2500         InsertDefaultValue (BlockData, &DefaultData);
   2501 
   2502         if (SmallestDefaultId > EFI_HII_DEFAULT_CLASS_STANDARD) {
   2503           //
   2504           // Record the SmallestDefaultId and update the SmallestIdFromFlag.
   2505           //
   2506           SmallestDefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;
   2507           SmallestIdFromFlag = TRUE;
   2508         }
   2509       }
   2510 
   2511       //
   2512       // Add default value for Manufacture ID by CheckBox Flag
   2513       //
   2514       VarDefaultId = EFI_HII_DEFAULT_CLASS_MANUFACTURING;
   2515       //
   2516       // Prepare new DefaultValue
   2517       //
   2518       DefaultData.DefaultId   = VarDefaultId;
   2519       if ((IfrCheckBox->Flags & EFI_IFR_CHECKBOX_DEFAULT_MFG) == EFI_IFR_CHECKBOX_DEFAULT_MFG) {
   2520         //
   2521         // When flag is set, default value is TRUE.
   2522         //
   2523         DefaultData.Type    = DefaultValueFromFlag;
   2524         DefaultData.Value.b = TRUE;
   2525         InsertDefaultValue (BlockData, &DefaultData);
   2526 
   2527         if (SmallestDefaultId > EFI_HII_DEFAULT_CLASS_MANUFACTURING) {
   2528           //
   2529           // Record the SmallestDefaultId and update the SmallestIdFromFlag.
   2530           //
   2531           SmallestDefaultId = EFI_HII_DEFAULT_CLASS_MANUFACTURING;
   2532           SmallestIdFromFlag = TRUE;
   2533         }
   2534       }
   2535       if (SmallestIdFromFlag) {
   2536         //
   2537         // When smallest default Id is given by the  flag of CheckBox, set default value with TRUE for other default Id in the DefaultId list.
   2538         //
   2539         DefaultData.Type    = DefaultValueFromOtherDefault;
   2540         DefaultData.Value.b = TRUE;
   2541         //
   2542         // Set default value for all the default id in the DefaultId list.
   2543         //
   2544         for (LinkData = DefaultIdArray->Entry.ForwardLink; LinkData != &DefaultIdArray->Entry; LinkData = LinkData->ForwardLink) {
   2545           DefaultDataPtr = BASE_CR (LinkData, IFR_DEFAULT_DATA, Entry);
   2546           DefaultData.DefaultId   = DefaultDataPtr->DefaultId;
   2547           InsertDefaultValue (BlockData, &DefaultData);
   2548         }
   2549       } else {
   2550         //
   2551         // When flag is not set, default value is FASLE.
   2552         //
   2553         DefaultData.Type    = DefaultValueFromDefault;
   2554         DefaultData.Value.b = FALSE;
   2555         //
   2556         // Set default value for all the default id in the DefaultId list.
   2557         //
   2558         for (LinkData = DefaultIdArray->Entry.ForwardLink; LinkData != &DefaultIdArray->Entry; LinkData = LinkData->ForwardLink) {
   2559           DefaultDataPtr = BASE_CR (LinkData, IFR_DEFAULT_DATA, Entry);
   2560           DefaultData.DefaultId   = DefaultDataPtr->DefaultId;
   2561           InsertDefaultValue (BlockData, &DefaultData);
   2562         }
   2563       }
   2564       break;
   2565 
   2566     case EFI_IFR_DATE_OP:
   2567       //
   2568       // offset by question header
   2569       // width MaxSize * sizeof (CHAR16)
   2570       // no default value, only block array
   2571       //
   2572 
   2573       //
   2574       // Date question is not in IFR Form. This IFR form is not valid.
   2575       //
   2576       if (VarStoreId == 0) {
   2577         Status = EFI_INVALID_PARAMETER;
   2578         goto Done;
   2579       }
   2580       //
   2581       // Check whether this question is for the requested varstore.
   2582       //
   2583       IfrDate = (EFI_IFR_DATE *) IfrOpHdr;
   2584       if (IfrDate->Question.VarStoreId != VarStoreId) {
   2585         break;
   2586       }
   2587 
   2588       //
   2589       // The BlockData may allocate by other opcode,need to clean.
   2590       //
   2591       if (BlockData != NULL){
   2592         BlockData = NULL;
   2593       }
   2594 
   2595       VarWidth  = (UINT16) sizeof (EFI_HII_DATE);
   2596       Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);
   2597       if (EFI_ERROR (Status)) {
   2598         if (Status == EFI_NOT_FOUND){
   2599           //
   2600           //The opcode is not required,exit and parse other opcode.
   2601           //
   2602           break;
   2603         }
   2604         goto Done;
   2605       }
   2606       break;
   2607 
   2608     case EFI_IFR_TIME_OP:
   2609       //
   2610       // offset by question header
   2611       // width MaxSize * sizeof (CHAR16)
   2612       // no default value, only block array
   2613       //
   2614 
   2615       //
   2616       // Time question is not in IFR Form. This IFR form is not valid.
   2617       //
   2618       if (VarStoreId == 0) {
   2619         Status = EFI_INVALID_PARAMETER;
   2620         goto Done;
   2621       }
   2622       //
   2623       // Check whether this question is for the requested varstore.
   2624       //
   2625       IfrTime = (EFI_IFR_TIME *) IfrOpHdr;
   2626       if (IfrTime->Question.VarStoreId != VarStoreId) {
   2627         break;
   2628       }
   2629 
   2630       //
   2631       // The BlockData may allocate by other opcode,need to clean.
   2632       //
   2633       if (BlockData != NULL){
   2634         BlockData = NULL;
   2635       }
   2636 
   2637       VarWidth  = (UINT16) sizeof (EFI_HII_TIME);
   2638       Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);
   2639       if (EFI_ERROR (Status)) {
   2640         if (Status == EFI_NOT_FOUND){
   2641           //
   2642           //The opcode is not required,exit and parse other opcode.
   2643           //
   2644           break;
   2645         }
   2646         goto Done;
   2647       }
   2648       break;
   2649 
   2650     case EFI_IFR_STRING_OP:
   2651       //
   2652       // offset by question header
   2653       // width MaxSize * sizeof (CHAR16)
   2654       // no default value, only block array
   2655       //
   2656 
   2657       //
   2658       // String question is not in IFR Form. This IFR form is not valid.
   2659       //
   2660       if (VarStoreId == 0) {
   2661         Status = EFI_INVALID_PARAMETER;
   2662         goto Done;
   2663       }
   2664       //
   2665       // Check whether this question is for the requested varstore.
   2666       //
   2667       IfrString = (EFI_IFR_STRING *) IfrOpHdr;
   2668       if (IfrString->Question.VarStoreId != VarStoreId) {
   2669         break;
   2670       }
   2671 
   2672       //
   2673       // The BlockData may allocate by other opcode,need to clean.
   2674       //
   2675       if (BlockData != NULL){
   2676         BlockData = NULL;
   2677       }
   2678 
   2679       VarWidth  = (UINT16) (IfrString->MaxSize * sizeof (UINT16));
   2680       Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);
   2681       if (EFI_ERROR (Status)) {
   2682         if (Status == EFI_NOT_FOUND){
   2683           //
   2684           //The opcode is not required,exit and parse other opcode.
   2685           //
   2686           break;
   2687         }
   2688         goto Done;
   2689       }
   2690       break;
   2691 
   2692     case EFI_IFR_PASSWORD_OP:
   2693       //
   2694       // offset by question header
   2695       // width MaxSize * sizeof (CHAR16)
   2696       // no default value, only block array
   2697       //
   2698 
   2699       //
   2700       // Password question is not in IFR Form. This IFR form is not valid.
   2701       //
   2702       if (VarStoreId == 0) {
   2703         Status = EFI_INVALID_PARAMETER;
   2704         goto Done;
   2705       }
   2706       //
   2707       // Check whether this question is for the requested varstore.
   2708       //
   2709       IfrPassword = (EFI_IFR_PASSWORD *) IfrOpHdr;
   2710       if (IfrPassword->Question.VarStoreId != VarStoreId) {
   2711         break;
   2712       }
   2713 
   2714       //
   2715       // The BlockData may allocate by other opcode,need to clean.
   2716       //
   2717       if (BlockData != NULL){
   2718         BlockData = NULL;
   2719       }
   2720 
   2721       VarWidth  = (UINT16) (IfrPassword->MaxSize * sizeof (UINT16));
   2722       Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);
   2723       if (EFI_ERROR (Status)) {
   2724         if (Status == EFI_NOT_FOUND){
   2725           //
   2726           //The opcode is not required,exit and parse other opcode.
   2727           //
   2728           break;
   2729         }
   2730         goto Done;
   2731       }
   2732 
   2733       //
   2734       // No default value for string.
   2735       //
   2736       BlockData = NULL;
   2737       break;
   2738 
   2739     case EFI_IFR_ONE_OF_OPTION_OP:
   2740       //
   2741       // No matched block data is ignored.
   2742       //
   2743       if (BlockData == NULL || BlockData->Scope == 0) {
   2744         break;
   2745       }
   2746 
   2747       IfrOneOfOption = (EFI_IFR_ONE_OF_OPTION *) IfrOpHdr;
   2748       if (BlockData->OpCode == EFI_IFR_ORDERED_LIST_OP) {
   2749 
   2750         if (!FirstOrderedList){
   2751           break;
   2752         }
   2753         //
   2754         // Get ordered list option data type.
   2755         //
   2756         if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_8 || IfrOneOfOption->Type == EFI_IFR_TYPE_BOOLEAN) {
   2757           VarWidth = 1;
   2758         } else if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_16) {
   2759           VarWidth = 2;
   2760         } else if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_32) {
   2761           VarWidth = 4;
   2762         } else if (IfrOneOfOption->Type == EFI_IFR_TYPE_NUM_SIZE_64) {
   2763           VarWidth = 8;
   2764         } else {
   2765           //
   2766           // Invalid ordered list option data type.
   2767           //
   2768           Status = EFI_INVALID_PARAMETER;
   2769           if (BlockData->Name != NULL) {
   2770             FreePool (BlockData->Name);
   2771           }
   2772           FreePool (BlockData);
   2773           goto Done;
   2774         }
   2775 
   2776         //
   2777         // Calculate Ordered list QuestionId width.
   2778         //
   2779         BlockData->Width = (UINT16) (BlockData->Width * VarWidth);
   2780         //
   2781         // Check whether this question is in requested block array.
   2782         //
   2783         if (!BlockArrayCheck (RequestBlockArray, BlockData->Offset, BlockData->Width, (BOOLEAN)(BlockData->Name != NULL), HiiHandle)) {
   2784           //
   2785           // This question is not in the requested string. Skip it.
   2786           //
   2787           if (BlockData->Name != NULL) {
   2788             FreePool (BlockData->Name);
   2789           }
   2790           FreePool (BlockData);
   2791           BlockData = NULL;
   2792           break;
   2793         }
   2794         //
   2795         // Check this var question is in the var storage
   2796         //
   2797         if ((BlockData->Name == NULL) && ((BlockData->Offset + BlockData->Width) > VarStorageData->Size)) {
   2798           Status = EFI_INVALID_PARAMETER;
   2799           if (BlockData->Name != NULL) {
   2800             FreePool (BlockData->Name);
   2801           }
   2802           FreePool (BlockData);
   2803           goto Done;
   2804         }
   2805         //
   2806         // Add Block Data into VarStorageData BlockEntry
   2807         //
   2808         InsertBlockData (&VarStorageData->BlockEntry, &BlockData);
   2809 
   2810         FirstOrderedList = FALSE;
   2811 
   2812         break;
   2813       }
   2814 
   2815       //
   2816       // 1. Set default value for OneOf option when flag field has default attribute.
   2817       //    And set the default value with the smallest default id for other default id in the DefaultId list.
   2818       //
   2819       if (((IfrOneOfOption->Flags & EFI_IFR_OPTION_DEFAULT) == EFI_IFR_OPTION_DEFAULT) ||
   2820           ((IfrOneOfOption->Flags & EFI_IFR_OPTION_DEFAULT_MFG) == EFI_IFR_OPTION_DEFAULT_MFG)) {
   2821         //
   2822         // This flag is used to specify whether this option is the first. Set it to FALSE for the following options.
   2823         // The first oneof option value will be used as default value when no default value is specified.
   2824         //
   2825         FirstOneOfOption = FALSE;
   2826 
   2827         SmallestIdFromFlag = FALSE;
   2828 
   2829         // Prepare new DefaultValue
   2830         //
   2831         DefaultData.Type     = DefaultValueFromFlag;
   2832         CopyMem (&DefaultData.Value, &IfrOneOfOption->Value, IfrOneOfOption->Header.Length - OFFSET_OF (EFI_IFR_ONE_OF_OPTION, Value));
   2833         if ((IfrOneOfOption->Flags & EFI_IFR_OPTION_DEFAULT) == EFI_IFR_OPTION_DEFAULT) {
   2834           DefaultData.DefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;
   2835           InsertDefaultValue (BlockData, &DefaultData);
   2836           if (SmallestDefaultId > EFI_HII_DEFAULT_CLASS_STANDARD) {
   2837             //
   2838             // Record the SmallestDefaultId and update the SmallestIdFromFlag.
   2839             //
   2840             SmallestDefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;
   2841             SmallestIdFromFlag = TRUE;
   2842           }
   2843         }
   2844         if ((IfrOneOfOption->Flags & EFI_IFR_OPTION_DEFAULT_MFG) == EFI_IFR_OPTION_DEFAULT_MFG) {
   2845           DefaultData.DefaultId = EFI_HII_DEFAULT_CLASS_MANUFACTURING;
   2846           InsertDefaultValue (BlockData, &DefaultData);
   2847           if (SmallestDefaultId > EFI_HII_DEFAULT_CLASS_MANUFACTURING) {
   2848             //
   2849             // Record the SmallestDefaultId and update the SmallestIdFromFlag.
   2850             //
   2851             SmallestDefaultId = EFI_HII_DEFAULT_CLASS_MANUFACTURING;
   2852             SmallestIdFromFlag = TRUE;
   2853           }
   2854         }
   2855 
   2856         if (SmallestIdFromFlag) {
   2857           //
   2858           // When smallest default Id is given by the flag of oneofOption, set this option value for other default Id in the DefaultId list.
   2859           //
   2860           DefaultData.Type = DefaultValueFromOtherDefault;
   2861           //
   2862           // Set default value for other default id in the DefaultId list.
   2863           //
   2864           for (LinkData = DefaultIdArray->Entry.ForwardLink; LinkData != &DefaultIdArray->Entry; LinkData = LinkData->ForwardLink) {
   2865             DefaultDataPtr = BASE_CR (LinkData, IFR_DEFAULT_DATA, Entry);
   2866             DefaultData.DefaultId   = DefaultDataPtr->DefaultId;
   2867             InsertDefaultValue (BlockData, &DefaultData);
   2868           }
   2869         }
   2870       }
   2871 
   2872       //
   2873       // 2. Set as the default value when this is the first option.
   2874       // The first oneof option value will be used as default value when no default value is specified.
   2875       //
   2876       if (FirstOneOfOption) {
   2877         // This flag is used to specify whether this option is the first. Set it to FALSE for the following options.
   2878         FirstOneOfOption = FALSE;
   2879 
   2880         //
   2881         // Prepare new DefaultValue
   2882         //
   2883         DefaultData.Type     = DefaultValueFromDefault;
   2884         CopyMem (&DefaultData.Value, &IfrOneOfOption->Value, IfrOneOfOption->Header.Length - OFFSET_OF (EFI_IFR_ONE_OF_OPTION, Value));
   2885         for (LinkData = DefaultIdArray->Entry.ForwardLink; LinkData != &DefaultIdArray->Entry; LinkData = LinkData->ForwardLink) {
   2886           DefaultDataPtr = BASE_CR (LinkData, IFR_DEFAULT_DATA, Entry);
   2887           DefaultData.DefaultId   = DefaultDataPtr->DefaultId;
   2888           InsertDefaultValue (BlockData, &DefaultData);
   2889         }
   2890       }
   2891       break;
   2892 
   2893     case EFI_IFR_DEFAULT_OP:
   2894       //
   2895       // Update Current BlockData to the default value.
   2896       //
   2897       if (BlockData == NULL || BlockData->Scope == 0) {
   2898         //
   2899         // No matched block data is ignored.
   2900         //
   2901         break;
   2902       }
   2903 
   2904       //
   2905       // Get the DefaultId
   2906       //
   2907       IfrDefault     = (EFI_IFR_DEFAULT *) IfrOpHdr;
   2908       VarDefaultId   = IfrDefault->DefaultId;
   2909       //
   2910       // Prepare new DefaultValue
   2911       //
   2912       DefaultData.Type        = DefaultValueFromOpcode;
   2913       DefaultData.DefaultId   = VarDefaultId;
   2914       CopyMem (&DefaultData.Value, &IfrDefault->Value, IfrDefault->Header.Length - OFFSET_OF (EFI_IFR_DEFAULT, Value));
   2915 
   2916       // If the value field is expression, set the cleaned flag.
   2917       if (IfrDefault->Type ==  EFI_IFR_TYPE_OTHER) {
   2918         DefaultData.Cleaned = TRUE;
   2919       }
   2920       //
   2921       // Add DefaultValue into current BlockData
   2922       //
   2923       InsertDefaultValue (BlockData, &DefaultData);
   2924 
   2925       //
   2926       // Set default value for other default id in the DefaultId list.
   2927       // when SmallestDefaultId == VarDefaultId means there are two defaults with same default Id.
   2928       // If the two defaults are both from default opcode, use the first default as the default value of other default Id.
   2929       // If one from flag and the other form default opcode, use the default opcode value as the default value of other default Id.
   2930       //
   2931       if ((SmallestDefaultId > VarDefaultId) || (SmallestDefaultId == VarDefaultId && !FromOtherDefaultOpcode)) {
   2932         FromOtherDefaultOpcode = TRUE;
   2933         SmallestDefaultId = VarDefaultId;
   2934         for (LinkData = DefaultIdArray->Entry.ForwardLink; LinkData != &DefaultIdArray->Entry; LinkData = LinkData->ForwardLink) {
   2935           DefaultDataPtr = BASE_CR (LinkData, IFR_DEFAULT_DATA, Entry);
   2936           if (DefaultDataPtr->DefaultId != DefaultData.DefaultId){
   2937             DefaultData.Type        = DefaultValueFromOtherDefault;
   2938             DefaultData.DefaultId   = DefaultDataPtr->DefaultId;
   2939             InsertDefaultValue (BlockData, &DefaultData);
   2940           }
   2941         }
   2942       }
   2943 
   2944       //
   2945       // After insert the default value, reset the cleaned value for next
   2946       // time used. If not set here, need to set the value before every time.
   2947       // use it.
   2948       //
   2949       DefaultData.Cleaned     = FALSE;
   2950       break;
   2951 
   2952     case EFI_IFR_END_OP:
   2953       //
   2954       // End Opcode is for Var question.
   2955       //
   2956       if (BlockData != NULL) {
   2957         if (BlockData->Scope > 0) {
   2958           BlockData->Scope--;
   2959         }
   2960         if (BlockData->Scope == 0) {
   2961           BlockData = NULL;
   2962           //
   2963           // when finishing parsing a question, clean the SmallestDefaultId and GetDefaultFromDefaultOpcode.
   2964           //
   2965           SmallestDefaultId = 0xFFFF;
   2966           FromOtherDefaultOpcode = FALSE;
   2967         }
   2968       }
   2969 
   2970       break;
   2971 
   2972     default:
   2973       if (BlockData != NULL) {
   2974         if (BlockData->Scope > 0) {
   2975           BlockData->Scope = (UINT8) (BlockData->Scope + IfrOpHdr->Scope);
   2976         }
   2977 
   2978         if (BlockData->Scope == 0) {
   2979           BlockData = NULL;
   2980         }
   2981       }
   2982       break;
   2983     }
   2984 
   2985     IfrOffset     += IfrOpHdr->Length;
   2986     PackageOffset += IfrOpHdr->Length;
   2987   }
   2988 
   2989   //
   2990   //if Status == EFI_NOT_FOUND, just means the opcode is not required,not contain any error,
   2991   //so set the Status to EFI_SUCCESS.
   2992   //
   2993   if (Status == EFI_NOT_FOUND){
   2994     Status = EFI_SUCCESS;
   2995   }
   2996 
   2997 Done:
   2998   for (LinkData = VarStorageData->BlockEntry.ForwardLink; LinkData != &VarStorageData->BlockEntry; LinkData = LinkData->ForwardLink) {
   2999     BlockData = BASE_CR (LinkData, IFR_BLOCK_DATA, Entry);
   3000     for (LinkDefault = BlockData->DefaultValueEntry.ForwardLink; LinkDefault != &BlockData->DefaultValueEntry; ) {
   3001       DefaultDataPtr = BASE_CR (LinkDefault, IFR_DEFAULT_DATA, Entry);
   3002       LinkDefault = LinkDefault->ForwardLink;
   3003       if (DefaultDataPtr->Cleaned == TRUE) {
   3004         RemoveEntryList (&DefaultDataPtr->Entry);
   3005         FreePool (DefaultDataPtr);
   3006       }
   3007     }
   3008   }
   3009 
   3010   return Status;
   3011 }
   3012 
   3013 /**
   3014   parse the configrequest string, get the elements.
   3015 
   3016   @param      ConfigRequest         The input configrequest string.
   3017   @param      Progress              Return the progress data.
   3018 
   3019   @retval     Block data pointer.
   3020 **/
   3021 IFR_BLOCK_DATA *
   3022 GetBlockElement (
   3023   IN  EFI_STRING          ConfigRequest,
   3024   OUT EFI_STRING          *Progress
   3025   )
   3026 {
   3027   EFI_STRING           StringPtr;
   3028   IFR_BLOCK_DATA       *BlockData;
   3029   IFR_BLOCK_DATA       *RequestBlockArray;
   3030   EFI_STATUS           Status;
   3031   UINT8                *TmpBuffer;
   3032   UINT16               Offset;
   3033   UINT16               Width;
   3034   LIST_ENTRY           *Link;
   3035   IFR_BLOCK_DATA       *NextBlockData;
   3036   UINTN                Length;
   3037 
   3038   TmpBuffer = NULL;
   3039 
   3040   //
   3041   // Init RequestBlockArray
   3042   //
   3043   RequestBlockArray = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));
   3044   if (RequestBlockArray == NULL) {
   3045     goto Done;
   3046   }
   3047   InitializeListHead (&RequestBlockArray->Entry);
   3048 
   3049   //
   3050   // Get the request Block array from the request string
   3051   // Offset and Width
   3052   //
   3053 
   3054   //
   3055   // Parse each <RequestElement> if exists
   3056   // Only <BlockName> format is supported by this help function.
   3057   // <BlockName> ::= &'OFFSET='<Number>&'WIDTH='<Number>
   3058   //
   3059   StringPtr = ConfigRequest;
   3060   while (*StringPtr != 0 && StrnCmp (StringPtr, L"&OFFSET=", StrLen (L"&OFFSET=")) == 0) {
   3061     //
   3062     // Skip the OFFSET string
   3063     //
   3064     *Progress   = StringPtr;
   3065     StringPtr += StrLen (L"&OFFSET=");
   3066     //
   3067     // Get Offset
   3068     //
   3069     Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
   3070     if (EFI_ERROR (Status)) {
   3071       goto Done;
   3072     }
   3073     Offset = 0;
   3074     CopyMem (
   3075       &Offset,
   3076       TmpBuffer,
   3077       (((Length + 1) / 2) < sizeof (UINT16)) ? ((Length + 1) / 2) : sizeof (UINT16)
   3078       );
   3079     FreePool (TmpBuffer);
   3080 
   3081     StringPtr += Length;
   3082     if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {
   3083       goto Done;
   3084     }
   3085     StringPtr += StrLen (L"&WIDTH=");
   3086 
   3087     //
   3088     // Get Width
   3089     //
   3090     Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
   3091     if (EFI_ERROR (Status)) {
   3092       goto Done;
   3093     }
   3094     Width = 0;
   3095     CopyMem (
   3096       &Width,
   3097       TmpBuffer,
   3098       (((Length + 1) / 2) < sizeof (UINT16)) ? ((Length + 1) / 2) : sizeof (UINT16)
   3099       );
   3100     FreePool (TmpBuffer);
   3101 
   3102     StringPtr += Length;
   3103     if (*StringPtr != 0 && *StringPtr != L'&') {
   3104       goto Done;
   3105     }
   3106 
   3107     //
   3108     // Set Block Data
   3109     //
   3110     BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));
   3111     if (BlockData == NULL) {
   3112       goto Done;
   3113     }
   3114     BlockData->Offset = Offset;
   3115     BlockData->Width  = Width;
   3116     InsertBlockData (&RequestBlockArray->Entry, &BlockData);
   3117 
   3118     //
   3119     // Skip &VALUE string if &VALUE does exists.
   3120     //
   3121     if (StrnCmp (StringPtr, L"&VALUE=", StrLen (L"&VALUE=")) == 0) {
   3122       StringPtr += StrLen (L"&VALUE=");
   3123 
   3124       //
   3125       // Get Value
   3126       //
   3127       Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
   3128       if (EFI_ERROR (Status)) {
   3129         goto Done;
   3130       }
   3131       FreePool (TmpBuffer);
   3132       StringPtr += Length;
   3133       if (*StringPtr != 0 && *StringPtr != L'&') {
   3134         goto Done;
   3135       }
   3136     }
   3137     //
   3138     // If '\0', parsing is finished.
   3139     //
   3140     if (*StringPtr == 0) {
   3141       break;
   3142     }
   3143   }
   3144 
   3145   //
   3146   // Merge the requested block data.
   3147   //
   3148   Link = RequestBlockArray->Entry.ForwardLink;
   3149   while ((Link != &RequestBlockArray->Entry) && (Link->ForwardLink != &RequestBlockArray->Entry)) {
   3150     BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);
   3151     NextBlockData = BASE_CR (Link->ForwardLink, IFR_BLOCK_DATA, Entry);
   3152     if ((NextBlockData->Offset >= BlockData->Offset) && (NextBlockData->Offset <= (BlockData->Offset + BlockData->Width))) {
   3153       if ((NextBlockData->Offset + NextBlockData->Width) > (BlockData->Offset + BlockData->Width)) {
   3154         BlockData->Width = (UINT16) (NextBlockData->Offset + NextBlockData->Width - BlockData->Offset);
   3155       }
   3156       RemoveEntryList (Link->ForwardLink);
   3157       FreePool (NextBlockData);
   3158       continue;
   3159     }
   3160     Link = Link->ForwardLink;
   3161   }
   3162 
   3163   return RequestBlockArray;
   3164 
   3165 Done:
   3166   if (RequestBlockArray != NULL) {
   3167     //
   3168     // Free Link Array RequestBlockArray
   3169     //
   3170     while (!IsListEmpty (&RequestBlockArray->Entry)) {
   3171       BlockData = BASE_CR (RequestBlockArray->Entry.ForwardLink, IFR_BLOCK_DATA, Entry);
   3172       RemoveEntryList (&BlockData->Entry);
   3173       FreePool (BlockData);
   3174     }
   3175 
   3176     FreePool (RequestBlockArray);
   3177   }
   3178 
   3179   return NULL;
   3180 }
   3181 
   3182 /**
   3183   parse the configrequest string, get the elements.
   3184 
   3185   @param      ConfigRequest         The input config request string.
   3186   @param      Progress              Return the progress data.
   3187 
   3188   @retval     return data block array.
   3189 **/
   3190 IFR_BLOCK_DATA *
   3191 GetNameElement (
   3192   IN  EFI_STRING           ConfigRequest,
   3193   OUT EFI_STRING           *Progress
   3194   )
   3195 {
   3196   EFI_STRING           StringPtr;
   3197   EFI_STRING           NextTag;
   3198   IFR_BLOCK_DATA       *BlockData;
   3199   IFR_BLOCK_DATA       *RequestBlockArray;
   3200   BOOLEAN              HasValue;
   3201 
   3202   StringPtr = ConfigRequest;
   3203 
   3204   //
   3205   // Init RequestBlockArray
   3206   //
   3207   RequestBlockArray = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));
   3208   if (RequestBlockArray == NULL) {
   3209     goto Done;
   3210   }
   3211   InitializeListHead (&RequestBlockArray->Entry);
   3212 
   3213   //
   3214   // Get the request Block array from the request string
   3215   //
   3216 
   3217   //
   3218   // Parse each <RequestElement> if exists
   3219   // Only <BlockName> format is supported by this help function.
   3220   // <BlockName> ::= &'Name***=***
   3221   //
   3222   while (StringPtr != NULL && *StringPtr == L'&') {
   3223 
   3224     *Progress   = StringPtr;
   3225     //
   3226     // Skip the L"&" string
   3227     //
   3228     StringPtr += 1;
   3229 
   3230     HasValue = FALSE;
   3231     if ((NextTag = StrStr (StringPtr, L"=")) != NULL) {
   3232       *NextTag = L'\0';
   3233       HasValue = TRUE;
   3234     } else if ((NextTag = StrStr (StringPtr, L"&")) != NULL) {
   3235       *NextTag = L'\0';
   3236     }
   3237 
   3238     //
   3239     // Set Block Data
   3240     //
   3241     BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));
   3242     if (BlockData == NULL) {
   3243       goto Done;
   3244     }
   3245 
   3246     //
   3247     // Get Name
   3248     //
   3249     BlockData->Name = AllocateCopyPool(StrSize (StringPtr), StringPtr);
   3250     InsertBlockData (&RequestBlockArray->Entry, &BlockData);
   3251 
   3252     if (HasValue) {
   3253       //
   3254       // If has value, skip the value.
   3255       //
   3256       StringPtr = NextTag + 1;
   3257       *NextTag  = L'=';
   3258       StringPtr = StrStr (StringPtr, L"&");
   3259     } else if (NextTag != NULL) {
   3260       //
   3261       // restore the '&' text.
   3262       //
   3263       StringPtr = NextTag;
   3264       *NextTag  = L'&';
   3265     }
   3266   }
   3267 
   3268   return RequestBlockArray;
   3269 
   3270 Done:
   3271   if (RequestBlockArray != NULL) {
   3272     //
   3273     // Free Link Array RequestBlockArray
   3274     //
   3275     while (!IsListEmpty (&RequestBlockArray->Entry)) {
   3276       BlockData = BASE_CR (RequestBlockArray->Entry.ForwardLink, IFR_BLOCK_DATA, Entry);
   3277       RemoveEntryList (&BlockData->Entry);
   3278       if (BlockData->Name != NULL) {
   3279         FreePool (BlockData->Name);
   3280       }
   3281       FreePool (BlockData);
   3282     }
   3283 
   3284     FreePool (RequestBlockArray);
   3285   }
   3286 
   3287   return NULL;
   3288 }
   3289 
   3290 /**
   3291   Generate ConfigRequest string base on the varstore info.
   3292 
   3293   @param      ConfigHdr             The config header for this varstore.
   3294   @param      VarStorageData        The varstore info.
   3295   @param      Status                Return Status.
   3296   @param      ConfigRequest         The ConfigRequest info may be return.
   3297 
   3298   @retval     TRUE                  Need to continue
   3299   @retval     Others                NO need to continue or error occur.
   3300 **/
   3301 BOOLEAN
   3302 GenerateConfigRequest (
   3303   IN  CHAR16                       *ConfigHdr,
   3304   IN  IFR_VARSTORAGE_DATA          *VarStorageData,
   3305   OUT EFI_STATUS                   *Status,
   3306   IN OUT EFI_STRING                *ConfigRequest
   3307   )
   3308 {
   3309   BOOLEAN               DataExist;
   3310   UINTN                 Length;
   3311   LIST_ENTRY            *Link;
   3312   CHAR16                *FullConfigRequest;
   3313   CHAR16                *StringPtr;
   3314   IFR_BLOCK_DATA        *BlockData;
   3315 
   3316   //
   3317   // Append VarStorageData BlockEntry into *Request string
   3318   // Now support only one varstore in a form package.
   3319   //
   3320 
   3321   //
   3322   // Go through all VarStorageData Entry and get BlockEntry for each one for the multiple varstore in a single form package
   3323   // Then construct them all to return MultiRequest string : ConfigHdr BlockConfig
   3324   //
   3325 
   3326   //
   3327   // Compute the length of the entire request starting with <ConfigHdr> and a
   3328   // Null-terminator
   3329   //
   3330   DataExist = FALSE;
   3331   Length    = StrLen (ConfigHdr) + 1;
   3332 
   3333   for (Link = VarStorageData->BlockEntry.ForwardLink; Link != &VarStorageData->BlockEntry; Link = Link->ForwardLink) {
   3334     DataExist = TRUE;
   3335     BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);
   3336     if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {
   3337       //
   3338       // Add <BlockName> length for each Name
   3339       //
   3340       // <BlockName> ::= &Name1&Name2&...
   3341       //                 |1| StrLen(Name1)
   3342       //
   3343       Length = Length + (1 + StrLen (BlockData->Name));
   3344     } else {
   3345       //
   3346       // Add <BlockName> length for each Offset/Width pair
   3347       //
   3348       // <BlockName> ::= &OFFSET=1234&WIDTH=1234
   3349       //                 |  8   | 4 |   7  | 4 |
   3350       //
   3351       Length = Length + (8 + 4 + 7 + 4);
   3352     }
   3353   }
   3354   //
   3355   // No any request block data is found. The request string can't be constructed.
   3356   //
   3357   if (!DataExist) {
   3358     *Status = EFI_SUCCESS;
   3359     return FALSE;
   3360   }
   3361 
   3362   //
   3363   // Allocate buffer for the entire <ConfigRequest>
   3364   //
   3365   FullConfigRequest = AllocateZeroPool (Length * sizeof (CHAR16));
   3366   if (FullConfigRequest == NULL) {
   3367     *Status = EFI_OUT_OF_RESOURCES;
   3368     return FALSE;
   3369   }
   3370   StringPtr = FullConfigRequest;
   3371 
   3372   //
   3373   // Start with <ConfigHdr>
   3374   //
   3375   StrCpyS (StringPtr, Length, ConfigHdr);
   3376   StringPtr += StrLen (StringPtr);
   3377 
   3378   //
   3379   // Loop through all the Offset/Width pairs and append them to ConfigRequest
   3380   //
   3381   for (Link = VarStorageData->BlockEntry.ForwardLink; Link != &VarStorageData->BlockEntry; Link = Link->ForwardLink) {
   3382     BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);
   3383     if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {
   3384       //
   3385       // Append &Name1\0
   3386       //
   3387       UnicodeSPrint (
   3388         StringPtr,
   3389         (1 + StrLen (BlockData->Name) + 1) * sizeof (CHAR16),
   3390         L"&%s",
   3391         BlockData->Name
   3392       );
   3393     } else {
   3394       //
   3395       // Append &OFFSET=XXXX&WIDTH=YYYY\0
   3396       //
   3397       UnicodeSPrint (
   3398         StringPtr,
   3399         (8 + 4 + 7 + 4 + 1) * sizeof (CHAR16),
   3400         L"&OFFSET=%04X&WIDTH=%04X",
   3401         BlockData->Offset,
   3402         BlockData->Width
   3403       );
   3404     }
   3405     StringPtr += StrLen (StringPtr);
   3406   }
   3407   //
   3408   // Set to the got full request string.
   3409   //
   3410   HiiToLower (FullConfigRequest);
   3411 
   3412   if (*ConfigRequest != NULL) {
   3413     FreePool (*ConfigRequest);
   3414   }
   3415   *ConfigRequest = FullConfigRequest;
   3416 
   3417   return TRUE;
   3418 }
   3419 
   3420 /**
   3421   Generate ConfigRequest Header base on the varstore info.
   3422 
   3423   @param      VarStorageData        The varstore info.
   3424   @param      DevicePath            Device path for this varstore.
   3425   @param      ConfigHdr             The config header for this varstore.
   3426 
   3427   @retval     EFI_SUCCESS           Generate the header success.
   3428   @retval     EFI_OUT_OF_RESOURCES  Allocate buffer fail.
   3429 **/
   3430 EFI_STATUS
   3431 GenerateHdr (
   3432   IN   IFR_VARSTORAGE_DATA          *VarStorageData,
   3433   IN   EFI_DEVICE_PATH_PROTOCOL     *DevicePath,
   3434   OUT  EFI_STRING                   *ConfigHdr
   3435   )
   3436 {
   3437   EFI_STRING                   GuidStr;
   3438   EFI_STRING                   NameStr;
   3439   EFI_STRING                   PathStr;
   3440   UINTN                        Length;
   3441   EFI_STATUS                   Status;
   3442 
   3443   Status  = EFI_SUCCESS;
   3444   NameStr = NULL;
   3445   GuidStr = NULL;
   3446   PathStr = NULL;
   3447 
   3448   //
   3449   // Construct <ConfigHdr> : "GUID=...&NAME=...&PATH=..." by VarStorageData Guid, Name and DriverHandle
   3450   //
   3451   GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (VOID *) &VarStorageData->Guid, 1, &GuidStr);
   3452   if (VarStorageData->Name != NULL) {
   3453     GenerateSubStr (L"NAME=", StrLen (VarStorageData->Name) * sizeof (CHAR16), (VOID *) VarStorageData->Name, 2, &NameStr);
   3454   } else {
   3455     GenerateSubStr (L"NAME=", 0, NULL, 2, &NameStr);
   3456   }
   3457   GenerateSubStr (
   3458     L"PATH=",
   3459     GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) DevicePath),
   3460     (VOID *) DevicePath,
   3461     1,
   3462     &PathStr
   3463     );
   3464   Length = StrLen (GuidStr) + StrLen (NameStr) + StrLen (PathStr) + 1;
   3465   if (VarStorageData->Name == NULL) {
   3466     Length += 1;
   3467   }
   3468 
   3469   *ConfigHdr = AllocateZeroPool (Length * sizeof (CHAR16));
   3470   if (*ConfigHdr == NULL) {
   3471     Status = EFI_OUT_OF_RESOURCES;
   3472     goto Done;
   3473   }
   3474   StrCpyS (*ConfigHdr, Length, GuidStr);
   3475   StrCatS (*ConfigHdr, Length, NameStr);
   3476   if (VarStorageData->Name == NULL) {
   3477     StrCatS (*ConfigHdr, Length, L"&");
   3478   }
   3479   StrCatS (*ConfigHdr, Length, PathStr);
   3480 
   3481   //
   3482   // Remove the last character L'&'
   3483   //
   3484   *(*ConfigHdr + StrLen (*ConfigHdr) - 1) = L'\0';
   3485 
   3486 Done:
   3487   if (GuidStr != NULL) {
   3488     FreePool (GuidStr);
   3489   }
   3490 
   3491   if (NameStr != NULL) {
   3492     FreePool (NameStr);
   3493   }
   3494 
   3495   if (PathStr != NULL) {
   3496     FreePool (PathStr);
   3497   }
   3498 
   3499   return Status;
   3500 }
   3501 
   3502 /**
   3503   Get Data buffer size based on data type.
   3504 
   3505   @param      ValueType             The input data type.
   3506 
   3507   @retval     The data buffer size for the input type.
   3508 **/
   3509 UINT16
   3510 GetStorageWidth (
   3511   IN UINT8       ValueType
   3512   )
   3513 {
   3514   UINT16         StorageWidth;
   3515 
   3516   switch (ValueType) {
   3517   case EFI_IFR_NUMERIC_SIZE_1:
   3518   case EFI_IFR_TYPE_BOOLEAN:
   3519     StorageWidth = (UINT16) sizeof (UINT8);
   3520     break;
   3521 
   3522   case EFI_IFR_NUMERIC_SIZE_2:
   3523     StorageWidth = (UINT16) sizeof (UINT16);
   3524     break;
   3525 
   3526   case EFI_IFR_NUMERIC_SIZE_4:
   3527     StorageWidth = (UINT16) sizeof (UINT32);
   3528     break;
   3529 
   3530   case EFI_IFR_NUMERIC_SIZE_8:
   3531     StorageWidth = (UINT16) sizeof (UINT64);
   3532     break;
   3533 
   3534   case EFI_IFR_TYPE_TIME:
   3535     StorageWidth = (UINT16) sizeof (EFI_IFR_TIME);
   3536     break;
   3537 
   3538   case EFI_IFR_TYPE_DATE:
   3539     StorageWidth = (UINT16) sizeof (EFI_IFR_DATE);
   3540     break;
   3541 
   3542   default:
   3543     StorageWidth = 0;
   3544     break;
   3545   }
   3546 
   3547   return StorageWidth;
   3548 }
   3549 
   3550 /**
   3551   Generate ConfigAltResp string base on the varstore info.
   3552 
   3553   @param      HiiHandle             Hii Handle for this hii package.
   3554   @param      ConfigHdr             The config header for this varstore.
   3555   @param      VarStorageData        The varstore info.
   3556   @param      DefaultIdArray        The Default id array.
   3557   @param      DefaultAltCfgResp     The DefaultAltCfgResp info may be return.
   3558 
   3559   @retval     TRUE                  Need to continue
   3560   @retval     Others                NO need to continue or error occur.
   3561 **/
   3562 EFI_STATUS
   3563 GenerateAltConfigResp (
   3564   IN  EFI_HII_HANDLE               HiiHandle,
   3565   IN  CHAR16                       *ConfigHdr,
   3566   IN  IFR_VARSTORAGE_DATA          *VarStorageData,
   3567   IN  IFR_DEFAULT_DATA             *DefaultIdArray,
   3568   IN OUT EFI_STRING                *DefaultAltCfgResp
   3569   )
   3570 {
   3571   BOOLEAN               DataExist;
   3572   UINTN                 Length;
   3573   LIST_ENTRY            *Link;
   3574   LIST_ENTRY            *LinkData;
   3575   LIST_ENTRY            *LinkDefault;
   3576   LIST_ENTRY            *ListEntry;
   3577   CHAR16                *StringPtr;
   3578   IFR_BLOCK_DATA        *BlockData;
   3579   IFR_DEFAULT_DATA      *DefaultId;
   3580   IFR_DEFAULT_DATA      *DefaultValueData;
   3581   UINTN                 Width;
   3582   UINT8                 *TmpBuffer;
   3583   CHAR16                *DefaultString;
   3584 
   3585   BlockData     = NULL;
   3586   DataExist     = FALSE;
   3587   DefaultString = NULL;
   3588   //
   3589   // Add length for <ConfigHdr> + '\0'
   3590   //
   3591   Length = StrLen (ConfigHdr) + 1;
   3592 
   3593   for (Link = DefaultIdArray->Entry.ForwardLink; Link != &DefaultIdArray->Entry; Link = Link->ForwardLink) {
   3594     DefaultId = BASE_CR (Link, IFR_DEFAULT_DATA, Entry);
   3595     //
   3596     // Add length for "&<ConfigHdr>&ALTCFG=XXXX"
   3597     //                |1| StrLen (ConfigHdr) | 8 | 4 |
   3598     //
   3599     Length += (1 + StrLen (ConfigHdr) + 8 + 4);
   3600 
   3601     for (LinkData = VarStorageData->BlockEntry.ForwardLink; LinkData != &VarStorageData->BlockEntry; LinkData = LinkData->ForwardLink) {
   3602       BlockData = BASE_CR (LinkData, IFR_BLOCK_DATA, Entry);
   3603       ListEntry     = &BlockData->DefaultValueEntry;
   3604       for (LinkDefault = ListEntry->ForwardLink; LinkDefault != ListEntry; LinkDefault = LinkDefault->ForwardLink) {
   3605         DefaultValueData = BASE_CR (LinkDefault, IFR_DEFAULT_DATA, Entry);
   3606         if (DefaultValueData->DefaultId != DefaultId->DefaultId) {
   3607           continue;
   3608         }
   3609         if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {
   3610           //
   3611           // Add length for "&Name1=zzzzzzzzzzzz"
   3612           //                |1|Name|1|Value|
   3613           //
   3614           Length += (1 + StrLen (BlockData->Name) + 1 + BlockData->Width * 2);
   3615         } else {
   3616           //
   3617           // Add length for "&OFFSET=XXXX&WIDTH=YYYY&VALUE=zzzzzzzzzzzz"
   3618           //                |    8  | 4 |   7  | 4 |   7  | Width * 2 |
   3619           //
   3620           Length += (8 + 4 + 7 + 4 + 7 + BlockData->Width * 2);
   3621         }
   3622         DataExist = TRUE;
   3623       }
   3624     }
   3625   }
   3626 
   3627   //
   3628   // No default value is found. The default string doesn't exist.
   3629   //
   3630   if (!DataExist) {
   3631     return EFI_SUCCESS;
   3632   }
   3633 
   3634   //
   3635   // Allocate buffer for the entire <DefaultAltCfgResp>
   3636   //
   3637   *DefaultAltCfgResp = AllocateZeroPool (Length * sizeof (CHAR16));
   3638   if (*DefaultAltCfgResp == NULL) {
   3639     return EFI_OUT_OF_RESOURCES;
   3640   }
   3641   StringPtr = *DefaultAltCfgResp;
   3642 
   3643   //
   3644   // Start with <ConfigHdr>
   3645   //
   3646   StrCpyS (StringPtr, Length, ConfigHdr);
   3647   StringPtr += StrLen (StringPtr);
   3648 
   3649   for (Link = DefaultIdArray->Entry.ForwardLink; Link != &DefaultIdArray->Entry; Link = Link->ForwardLink) {
   3650     DefaultId = BASE_CR (Link, IFR_DEFAULT_DATA, Entry);
   3651     //
   3652     // Add <AltConfigHdr> of the form "&<ConfigHdr>&ALTCFG=XXXX\0"
   3653     //                                |1| StrLen (ConfigHdr) | 8 | 4 |
   3654     //
   3655     UnicodeSPrint (
   3656       StringPtr,
   3657       (1 + StrLen (ConfigHdr) + 8 + 4 + 1) * sizeof (CHAR16),
   3658       L"&%s&ALTCFG=%04X",
   3659       ConfigHdr,
   3660       DefaultId->DefaultId
   3661       );
   3662     StringPtr += StrLen (StringPtr);
   3663 
   3664     for (LinkData = VarStorageData->BlockEntry.ForwardLink; LinkData != &VarStorageData->BlockEntry; LinkData = LinkData->ForwardLink) {
   3665       BlockData = BASE_CR (LinkData, IFR_BLOCK_DATA, Entry);
   3666       ListEntry     = &BlockData->DefaultValueEntry;
   3667       for (LinkDefault = ListEntry->ForwardLink; LinkDefault != ListEntry; LinkDefault = LinkDefault->ForwardLink) {
   3668         DefaultValueData = BASE_CR (LinkDefault, IFR_DEFAULT_DATA, Entry);
   3669         if (DefaultValueData->DefaultId != DefaultId->DefaultId) {
   3670           continue;
   3671         }
   3672         if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {
   3673           UnicodeSPrint (
   3674             StringPtr,
   3675             (1 + StrLen (ConfigHdr) + 1) * sizeof (CHAR16),
   3676             L"&%s=",
   3677             BlockData->Name
   3678             );
   3679           StringPtr += StrLen (StringPtr);
   3680         } else {
   3681           //
   3682           // Add <BlockConfig>
   3683           // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>
   3684           //
   3685           UnicodeSPrint (
   3686             StringPtr,
   3687             (8 + 4 + 7 + 4 + 7 + 1) * sizeof (CHAR16),
   3688             L"&OFFSET=%04X&WIDTH=%04X&VALUE=",
   3689             BlockData->Offset,
   3690             BlockData->Width
   3691             );
   3692           StringPtr += StrLen (StringPtr);
   3693         }
   3694         Width = BlockData->Width;
   3695         //
   3696         // Convert Value to a hex string in "%x" format
   3697         // NOTE: This is in the opposite byte that GUID and PATH use
   3698         //
   3699         if (BlockData->OpCode == EFI_IFR_STRING_OP){
   3700           DefaultString   = InternalGetString(HiiHandle, DefaultValueData->Value.string);
   3701           TmpBuffer = (UINT8 *) DefaultString;
   3702         } else {
   3703           TmpBuffer = (UINT8 *) &(DefaultValueData->Value);
   3704         }
   3705         for (; Width > 0 && (TmpBuffer != NULL); Width--) {
   3706           StringPtr += UnicodeValueToString (StringPtr, PREFIX_ZERO | RADIX_HEX, TmpBuffer[Width - 1], 2);
   3707         }
   3708         if (DefaultString != NULL){
   3709           FreePool(DefaultString);
   3710           DefaultString = NULL;
   3711         }
   3712       }
   3713     }
   3714   }
   3715 
   3716   HiiToLower (*DefaultAltCfgResp);
   3717 
   3718   return EFI_SUCCESS;
   3719 }
   3720 
   3721 /**
   3722   This function gets the full request string and full default value string by
   3723   parsing IFR data in HII form packages.
   3724 
   3725   When Request points to NULL string, the request string and default value string
   3726   for each varstore in form package will return.
   3727 
   3728   @param  DataBaseRecord         The DataBaseRecord instance contains the found Hii handle and package.
   3729   @param  DevicePath             Device Path which Hii Config Access Protocol is registered.
   3730   @param  Request                Pointer to a null-terminated Unicode string in
   3731                                  <ConfigRequest> format. When it doesn't contain
   3732                                  any RequestElement, it will be updated to return
   3733                                  the full RequestElement retrieved from IFR data.
   3734                                  If it points to NULL, the request string for the first
   3735                                  varstore in form package will be merged into a
   3736                                  <MultiConfigRequest> format string and return.
   3737   @param  AltCfgResp             Pointer to a null-terminated Unicode string in
   3738                                  <ConfigAltResp> format. When the pointer is to NULL,
   3739                                  the full default value string retrieved from IFR data
   3740                                  will return. When the pinter is to a string, the
   3741                                  full default value string retrieved from IFR data
   3742                                  will be merged into the input string and return.
   3743                                  When Request points to NULL, the default value string
   3744                                  for each varstore in form package will be merged into
   3745                                  a <MultiConfigAltResp> format string and return.
   3746   @param  PointerProgress        Optional parameter, it can be NULL.
   3747                                  When it is not NULL, if Request is NULL, it returns NULL.
   3748                                  On return, points to a character in the Request
   3749                                  string. Points to the string's null terminator if
   3750                                  request was successful. Points to the most recent
   3751                                  & before the first failing name / value pair (or
   3752                                  the beginning of the string if the failure is in
   3753                                  the first name / value pair) if the request was
   3754                                  not successful.
   3755   @retval EFI_SUCCESS            The Results string is set to the full request string.
   3756                                  And AltCfgResp contains all default value string.
   3757   @retval EFI_OUT_OF_RESOURCES   Not enough memory for the return string.
   3758   @retval EFI_NOT_FOUND          The varstore (Guid and Name) in Request string
   3759                                  can't be found in Form package.
   3760   @retval EFI_NOT_FOUND          HiiPackage can't be got on the input HiiHandle.
   3761   @retval EFI_INVALID_PARAMETER  Request points to NULL.
   3762 
   3763 **/
   3764 EFI_STATUS
   3765 EFIAPI
   3766 GetFullStringFromHiiFormPackages (
   3767   IN     HII_DATABASE_RECORD        *DataBaseRecord,
   3768   IN     EFI_DEVICE_PATH_PROTOCOL   *DevicePath,
   3769   IN OUT EFI_STRING                 *Request,
   3770   IN OUT EFI_STRING                 *AltCfgResp,
   3771   OUT    EFI_STRING                 *PointerProgress OPTIONAL
   3772   )
   3773 {
   3774   EFI_STATUS                   Status;
   3775   UINT8                        *HiiFormPackage;
   3776   UINTN                        PackageSize;
   3777   IFR_BLOCK_DATA               *RequestBlockArray;
   3778   IFR_BLOCK_DATA               *BlockData;
   3779   IFR_DEFAULT_DATA             *DefaultValueData;
   3780   IFR_DEFAULT_DATA             *DefaultId;
   3781   IFR_DEFAULT_DATA             *DefaultIdArray;
   3782   IFR_VARSTORAGE_DATA          *VarStorageData;
   3783   EFI_STRING                   DefaultAltCfgResp;
   3784   EFI_STRING                   ConfigHdr;
   3785   EFI_STRING                   StringPtr;
   3786   EFI_STRING                   Progress;
   3787 
   3788   if (DataBaseRecord == NULL || DevicePath == NULL || Request == NULL || AltCfgResp == NULL) {
   3789     return EFI_INVALID_PARAMETER;
   3790   }
   3791 
   3792   //
   3793   // Initialize the local variables.
   3794   //
   3795   RequestBlockArray = NULL;
   3796   DefaultIdArray    = NULL;
   3797   VarStorageData    = NULL;
   3798   DefaultAltCfgResp = NULL;
   3799   ConfigHdr         = NULL;
   3800   HiiFormPackage    = NULL;
   3801   PackageSize       = 0;
   3802   Progress          = *Request;
   3803 
   3804   Status = GetFormPackageData (DataBaseRecord, &HiiFormPackage, &PackageSize);
   3805   if (EFI_ERROR (Status)) {
   3806     goto Done;
   3807   }
   3808 
   3809   //
   3810   // 1. Get the request block array by Request String when Request string contains the block array.
   3811   //
   3812   StringPtr = NULL;
   3813   if (*Request != NULL) {
   3814     StringPtr = *Request;
   3815     //
   3816     // Jump <ConfigHdr>
   3817     //
   3818     if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {
   3819       Status   = EFI_INVALID_PARAMETER;
   3820       goto Done;
   3821     }
   3822     StringPtr += StrLen (L"GUID=");
   3823     while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&NAME=", StrLen (L"&NAME=")) != 0) {
   3824       StringPtr++;
   3825     }
   3826     if (*StringPtr == L'\0') {
   3827       Status = EFI_INVALID_PARAMETER;
   3828       goto Done;
   3829     }
   3830     StringPtr += StrLen (L"&NAME=");
   3831     while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&PATH=", StrLen (L"&PATH=")) != 0) {
   3832       StringPtr++;
   3833     }
   3834     if (*StringPtr == L'\0') {
   3835       Status = EFI_INVALID_PARAMETER;
   3836       goto Done;
   3837     }
   3838     StringPtr += StrLen (L"&PATH=");
   3839     while (*StringPtr != L'\0' && *StringPtr != L'&') {
   3840       StringPtr ++;
   3841     }
   3842 
   3843     if (*StringPtr == L'\0') {
   3844       //
   3845       // No request block is found.
   3846       //
   3847       StringPtr = NULL;
   3848     }
   3849   }
   3850 
   3851   //
   3852   // If StringPtr != NULL, get the request elements.
   3853   //
   3854   if (StringPtr != NULL) {
   3855     if (StrStr (StringPtr, L"&OFFSET=") != NULL) {
   3856       RequestBlockArray = GetBlockElement(StringPtr, &Progress);
   3857     } else {
   3858       RequestBlockArray = GetNameElement(StringPtr, &Progress);
   3859     }
   3860 
   3861     if (RequestBlockArray == NULL) {
   3862       Status = EFI_INVALID_PARAMETER;
   3863       goto Done;
   3864     }
   3865   }
   3866 
   3867   //
   3868   // Initialize DefaultIdArray to store the map between DeaultId and DefaultName
   3869   //
   3870   DefaultIdArray   = (IFR_DEFAULT_DATA *) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA));
   3871   if (DefaultIdArray == NULL) {
   3872     Status = EFI_OUT_OF_RESOURCES;
   3873     goto Done;
   3874   }
   3875   InitializeListHead (&DefaultIdArray->Entry);
   3876 
   3877   //
   3878   // Initialize VarStorageData to store the var store Block and Default value information.
   3879   //
   3880   VarStorageData = (IFR_VARSTORAGE_DATA *) AllocateZeroPool (sizeof (IFR_VARSTORAGE_DATA));
   3881   if (VarStorageData == NULL) {
   3882     Status = EFI_OUT_OF_RESOURCES;
   3883     goto Done;
   3884   }
   3885   InitializeListHead (&VarStorageData->Entry);
   3886   InitializeListHead (&VarStorageData->BlockEntry);
   3887 
   3888   //
   3889   // 2. Parse FormPackage to get BlockArray and DefaultId Array for the request BlockArray.
   3890   //
   3891 
   3892   //
   3893   // Parse the opcode in form package to get the default setting.
   3894   //
   3895   Status = ParseIfrData (DataBaseRecord->Handle,
   3896                          HiiFormPackage,
   3897                          (UINT32) PackageSize,
   3898                          *Request,
   3899                          RequestBlockArray,
   3900                          VarStorageData,
   3901                          DefaultIdArray);
   3902   if (EFI_ERROR (Status)) {
   3903     goto Done;
   3904   }
   3905 
   3906   //
   3907   // No requested varstore in IFR data and directly return
   3908   //
   3909   if (VarStorageData->Type == 0 && VarStorageData->Name == NULL) {
   3910     Status = EFI_SUCCESS;
   3911     goto Done;
   3912   }
   3913 
   3914   //
   3915   // 3. Construct Request Element (Block Name) for 2.1 and 2.2 case.
   3916   //
   3917   Status = GenerateHdr (VarStorageData, DevicePath, &ConfigHdr);
   3918   if (EFI_ERROR (Status)) {
   3919     goto Done;
   3920   }
   3921 
   3922   if (RequestBlockArray == NULL) {
   3923     if (!GenerateConfigRequest(ConfigHdr, VarStorageData, &Status, Request)) {
   3924       goto Done;
   3925     }
   3926   }
   3927 
   3928   //
   3929   // 4. Construct Default Value string in AltResp according to request element.
   3930   // Go through all VarStorageData Entry and get the DefaultId array for each one
   3931   // Then construct them all to : ConfigHdr AltConfigHdr ConfigBody AltConfigHdr ConfigBody
   3932   //
   3933   Status = GenerateAltConfigResp (DataBaseRecord->Handle,ConfigHdr, VarStorageData, DefaultIdArray, &DefaultAltCfgResp);
   3934   if (EFI_ERROR (Status)) {
   3935     goto Done;
   3936   }
   3937 
   3938   //
   3939   // 5. Merge string into the input AltCfgResp if the input *AltCfgResp is not NULL.
   3940   //
   3941   if (*AltCfgResp != NULL && DefaultAltCfgResp != NULL) {
   3942     Status = MergeDefaultString (AltCfgResp, DefaultAltCfgResp);
   3943     FreePool (DefaultAltCfgResp);
   3944   } else if (*AltCfgResp == NULL) {
   3945     *AltCfgResp = DefaultAltCfgResp;
   3946   }
   3947 
   3948 Done:
   3949   if (RequestBlockArray != NULL) {
   3950     //
   3951     // Free Link Array RequestBlockArray
   3952     //
   3953     while (!IsListEmpty (&RequestBlockArray->Entry)) {
   3954       BlockData = BASE_CR (RequestBlockArray->Entry.ForwardLink, IFR_BLOCK_DATA, Entry);
   3955       RemoveEntryList (&BlockData->Entry);
   3956       if (BlockData->Name != NULL) {
   3957         FreePool (BlockData->Name);
   3958       }
   3959       FreePool (BlockData);
   3960     }
   3961 
   3962     FreePool (RequestBlockArray);
   3963   }
   3964 
   3965   if (VarStorageData != NULL) {
   3966     //
   3967     // Free link array VarStorageData
   3968     //
   3969     while (!IsListEmpty (&VarStorageData->BlockEntry)) {
   3970       BlockData = BASE_CR (VarStorageData->BlockEntry.ForwardLink, IFR_BLOCK_DATA, Entry);
   3971       RemoveEntryList (&BlockData->Entry);
   3972       if (BlockData->Name != NULL) {
   3973         FreePool (BlockData->Name);
   3974       }
   3975       //
   3976       // Free default value link array
   3977       //
   3978       while (!IsListEmpty (&BlockData->DefaultValueEntry)) {
   3979         DefaultValueData = BASE_CR (BlockData->DefaultValueEntry.ForwardLink, IFR_DEFAULT_DATA, Entry);
   3980         RemoveEntryList (&DefaultValueData->Entry);
   3981         FreePool (DefaultValueData);
   3982       }
   3983       FreePool (BlockData);
   3984     }
   3985     if (VarStorageData ->Name != NULL) {
   3986       FreePool (VarStorageData ->Name);
   3987       VarStorageData ->Name = NULL;
   3988     }
   3989     FreePool (VarStorageData);
   3990   }
   3991 
   3992   if (DefaultIdArray != NULL) {
   3993     //
   3994     // Free DefaultId Array
   3995     //
   3996     while (!IsListEmpty (&DefaultIdArray->Entry)) {
   3997       DefaultId = BASE_CR (DefaultIdArray->Entry.ForwardLink, IFR_DEFAULT_DATA, Entry);
   3998       RemoveEntryList (&DefaultId->Entry);
   3999       FreePool (DefaultId);
   4000     }
   4001     FreePool (DefaultIdArray);
   4002   }
   4003 
   4004   //
   4005   // Free the allocated string
   4006   //
   4007   if (ConfigHdr != NULL) {
   4008     FreePool (ConfigHdr);
   4009   }
   4010 
   4011   //
   4012   // Free Package data
   4013   //
   4014   if (HiiFormPackage != NULL) {
   4015     FreePool (HiiFormPackage);
   4016   }
   4017 
   4018   if (PointerProgress != NULL) {
   4019     if (*Request == NULL) {
   4020       *PointerProgress = NULL;
   4021     } else if (EFI_ERROR (Status)) {
   4022       *PointerProgress = *Request;
   4023     } else {
   4024       *PointerProgress = *Request + StrLen (*Request);
   4025     }
   4026   }
   4027 
   4028   return Status;
   4029 }
   4030 
   4031 /**
   4032   This function gets the full request resp string by
   4033   parsing IFR data in HII form packages.
   4034 
   4035   @param  This                   A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
   4036                                  instance.
   4037   @param  EfiVarStoreInfo        The efi varstore info which is save in the EFI
   4038                                  varstore data structure.
   4039   @param  Request                Pointer to a null-terminated Unicode string in
   4040                                  <ConfigRequest> format.
   4041   @param  RequestResp            Pointer to a null-terminated Unicode string in
   4042                                  <ConfigResp> format.
   4043   @param  AccessProgress         On return, points to a character in the Request
   4044                                  string. Points to the string's null terminator if
   4045                                  request was successful. Points to the most recent
   4046                                  & before the first failing name / value pair (or
   4047                                  the beginning of the string if the failure is in
   4048                                  the first name / value pair) if the request was
   4049                                  not successful.
   4050 
   4051   @retval EFI_SUCCESS            The Results string is set to the full request string.
   4052                                  And AltCfgResp contains all default value string.
   4053   @retval EFI_OUT_OF_RESOURCES   Not enough memory for the return string.
   4054   @retval EFI_INVALID_PARAMETER  Request points to NULL.
   4055 
   4056 **/
   4057 EFI_STATUS
   4058 GetConfigRespFromEfiVarStore (
   4059   IN  CONST EFI_HII_CONFIG_ROUTING_PROTOCOL  *This,
   4060   IN  EFI_IFR_VARSTORE_EFI                   *EfiVarStoreInfo,
   4061   IN  EFI_STRING                             Request,
   4062   OUT EFI_STRING                             *RequestResp,
   4063   OUT EFI_STRING                             *AccessProgress
   4064   )
   4065 {
   4066   EFI_STATUS Status;
   4067   EFI_STRING VarStoreName;
   4068   UINTN      NameSize;
   4069   UINT8      *VarStore;
   4070   UINTN      BufferSize;
   4071 
   4072   Status          = EFI_SUCCESS;
   4073   BufferSize      = 0;
   4074   VarStore        = NULL;
   4075   VarStoreName    = NULL;
   4076   *AccessProgress = Request;
   4077 
   4078   NameSize = AsciiStrSize ((CHAR8 *)EfiVarStoreInfo->Name);
   4079   VarStoreName = AllocateZeroPool (NameSize * sizeof (CHAR16));
   4080   if (VarStoreName == NULL) {
   4081     Status = EFI_OUT_OF_RESOURCES;
   4082     goto Done;
   4083   }
   4084   AsciiStrToUnicodeStrS ((CHAR8 *) EfiVarStoreInfo->Name, VarStoreName, NameSize);
   4085 
   4086 
   4087   Status = gRT->GetVariable (VarStoreName, &EfiVarStoreInfo->Guid, NULL, &BufferSize, NULL);
   4088   if (Status != EFI_BUFFER_TOO_SMALL) {
   4089     goto Done;
   4090   }
   4091 
   4092   VarStore = AllocateZeroPool (BufferSize);
   4093   ASSERT (VarStore != NULL);
   4094   Status = gRT->GetVariable (VarStoreName, &EfiVarStoreInfo->Guid, NULL, &BufferSize, VarStore);
   4095   if (EFI_ERROR (Status)) {
   4096     goto Done;
   4097   }
   4098 
   4099   Status = HiiBlockToConfig(This, Request, VarStore, BufferSize, RequestResp, AccessProgress);
   4100   if (EFI_ERROR (Status)) {
   4101     goto Done;
   4102   }
   4103 
   4104 Done:
   4105   if (VarStoreName != NULL) {
   4106     FreePool (VarStoreName);
   4107   }
   4108 
   4109   if (VarStore != NULL) {
   4110     FreePool (VarStore);
   4111   }
   4112 
   4113   return Status;
   4114 }
   4115 
   4116 
   4117 /**
   4118   This function route the full request resp string for efi varstore.
   4119 
   4120   @param  This                   A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
   4121                                  instance.
   4122   @param  EfiVarStoreInfo        The efi varstore info which is save in the EFI
   4123                                  varstore data structure.
   4124   @param  RequestResp            Pointer to a null-terminated Unicode string in
   4125                                  <ConfigResp> format.
   4126   @param  Result                 Pointer to a null-terminated Unicode string in
   4127                                  <ConfigResp> format.
   4128 
   4129   @retval EFI_SUCCESS            The Results string is set to the full request string.
   4130                                  And AltCfgResp contains all default value string.
   4131   @retval EFI_OUT_OF_RESOURCES   Not enough memory for the return string.
   4132   @retval EFI_INVALID_PARAMETER  Request points to NULL.
   4133 
   4134 **/
   4135 EFI_STATUS
   4136 RouteConfigRespForEfiVarStore (
   4137   IN  CONST EFI_HII_CONFIG_ROUTING_PROTOCOL  *This,
   4138   IN  EFI_IFR_VARSTORE_EFI                   *EfiVarStoreInfo,
   4139   IN  EFI_STRING                             RequestResp,
   4140   OUT EFI_STRING                             *Result
   4141   )
   4142 {
   4143   EFI_STATUS Status;
   4144   EFI_STRING VarStoreName;
   4145   UINTN      NameSize;
   4146   UINT8      *VarStore;
   4147   UINTN      BufferSize;
   4148   UINTN      BlockSize;
   4149 
   4150   Status       = EFI_SUCCESS;
   4151   BufferSize   = 0;
   4152   VarStore     = NULL;
   4153   VarStoreName = NULL;
   4154   *Result = RequestResp;
   4155 
   4156   NameSize = AsciiStrSize ((CHAR8 *)EfiVarStoreInfo->Name);
   4157   VarStoreName = AllocateZeroPool (NameSize * sizeof (CHAR16));
   4158   if (VarStoreName == NULL) {
   4159     Status = EFI_OUT_OF_RESOURCES;
   4160     goto Done;
   4161   }
   4162   AsciiStrToUnicodeStrS ((CHAR8 *) EfiVarStoreInfo->Name, VarStoreName, NameSize);
   4163 
   4164   Status = gRT->GetVariable (VarStoreName, &EfiVarStoreInfo->Guid, NULL, &BufferSize, NULL);
   4165   if (Status != EFI_BUFFER_TOO_SMALL) {
   4166     DEBUG ((DEBUG_ERROR, "The variable does not exist!"));
   4167     goto Done;
   4168   }
   4169 
   4170   BlockSize = BufferSize;
   4171   VarStore = AllocateZeroPool (BufferSize);
   4172   ASSERT (VarStore != NULL);
   4173   Status = gRT->GetVariable (VarStoreName, &EfiVarStoreInfo->Guid, NULL, &BufferSize, VarStore);
   4174   if (EFI_ERROR (Status)) {
   4175     goto Done;
   4176   }
   4177 
   4178   Status = HiiConfigToBlock(This, RequestResp, VarStore, &BlockSize, Result);
   4179   if (EFI_ERROR (Status)) {
   4180     goto Done;
   4181   }
   4182 
   4183   Status = gRT->SetVariable (VarStoreName, &EfiVarStoreInfo->Guid, EfiVarStoreInfo->Attributes, BufferSize, VarStore);
   4184   if (EFI_ERROR (Status)) {
   4185     *Result = RequestResp;
   4186     goto Done;
   4187   }
   4188 
   4189 Done:
   4190   if (VarStoreName != NULL) {
   4191     FreePool (VarStoreName);
   4192   }
   4193 
   4194   if (VarStore != NULL) {
   4195     FreePool (VarStore);
   4196   }
   4197 
   4198   return Status;
   4199 }
   4200 
   4201 /**
   4202   Validate the config request elements.
   4203 
   4204   @param  ConfigElements                A null-terminated Unicode string in <ConfigRequest> format,
   4205                                         without configHdr field.
   4206 
   4207   @retval     CHAR16 *    THE first Name/value pair not correct.
   4208   @retval     NULL        Success parse the name/value pair
   4209 **/
   4210 CHAR16 *
   4211 OffsetWidthValidate (
   4212   CHAR16          *ConfigElements
   4213   )
   4214 {
   4215   CHAR16    *StringPtr;
   4216   CHAR16    *RetVal;
   4217 
   4218   StringPtr = ConfigElements;
   4219 
   4220   while (1) {
   4221     RetVal    = StringPtr;
   4222     if (StrnCmp (StringPtr, L"&OFFSET=", StrLen (L"&OFFSET=")) != 0) {
   4223       return RetVal;
   4224     }
   4225 
   4226     while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {
   4227       StringPtr++;
   4228     }
   4229     if (*StringPtr == L'\0') {
   4230       return RetVal;
   4231     }
   4232 
   4233     StringPtr += StrLen (L"&WIDTH=");
   4234     while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&OFFSET=", StrLen (L"&OFFSET=")) != 0) {
   4235       StringPtr ++;
   4236     }
   4237 
   4238     if (*StringPtr == L'\0') {
   4239       return NULL;
   4240     }
   4241   }
   4242 }
   4243 
   4244 /**
   4245   Validate the config request elements.
   4246 
   4247   @param  ConfigElements                A null-terminated Unicode string in <ConfigRequest> format,
   4248                                         without configHdr field.
   4249 
   4250   @retval     CHAR16 *    THE first Name/value pair not correct.
   4251   @retval     NULL        Success parse the name/value pair
   4252 
   4253 **/
   4254 CHAR16 *
   4255 NameValueValidate (
   4256   CHAR16          *ConfigElements
   4257   )
   4258 {
   4259   CHAR16    *StringPtr;
   4260   CHAR16    *RetVal;
   4261 
   4262   StringPtr = ConfigElements;
   4263 
   4264   while (1) {
   4265     RetVal = StringPtr;
   4266     if (*StringPtr != L'&') {
   4267       return RetVal;
   4268     }
   4269     StringPtr += 1;
   4270 
   4271     StringPtr = StrStr (StringPtr, L"&");
   4272 
   4273     if (StringPtr == NULL) {
   4274       return NULL;
   4275     }
   4276   }
   4277 }
   4278 
   4279 /**
   4280   Validate the config request string.
   4281 
   4282   @param  ConfigRequest                A null-terminated Unicode string in <ConfigRequest> format.
   4283 
   4284   @retval     CHAR16 *    THE first element not correct.
   4285   @retval     NULL        Success parse the name/value pair
   4286 
   4287 **/
   4288 CHAR16 *
   4289 ConfigRequestValidate (
   4290   CHAR16          *ConfigRequest
   4291   )
   4292 {
   4293   BOOLEAN            HasNameField;
   4294   CHAR16             *StringPtr;
   4295 
   4296   HasNameField = TRUE;
   4297   StringPtr    = ConfigRequest;
   4298 
   4299   //
   4300   // Check <ConfigHdr>
   4301   //
   4302   if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {
   4303     return ConfigRequest;
   4304   }
   4305   StringPtr += StrLen (L"GUID=");
   4306   while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&NAME=", StrLen (L"&NAME=")) != 0) {
   4307     StringPtr++;
   4308   }
   4309   if (*StringPtr == L'\0') {
   4310     return ConfigRequest;
   4311   }
   4312   StringPtr += StrLen (L"&NAME=");
   4313   if (*StringPtr == L'&') {
   4314     HasNameField = FALSE;
   4315   }
   4316   while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&PATH=", StrLen (L"&PATH=")) != 0) {
   4317     StringPtr++;
   4318   }
   4319   if (*StringPtr == L'\0') {
   4320     return ConfigRequest;
   4321   }
   4322   StringPtr += StrLen (L"&PATH=");
   4323   while (*StringPtr != L'\0' && *StringPtr != L'&') {
   4324     StringPtr ++;
   4325   }
   4326 
   4327   if (*StringPtr == L'\0') {
   4328     return NULL;
   4329   }
   4330 
   4331   if (HasNameField) {
   4332     //
   4333     // Should be Buffer varstore, config request should be "OFFSET/Width" pairs.
   4334     //
   4335     return OffsetWidthValidate(StringPtr);
   4336   } else {
   4337     //
   4338     // Should be Name/Value varstore, config request should be "&name1&name2..." pairs.
   4339     //
   4340     return NameValueValidate(StringPtr);
   4341   }
   4342 }
   4343 
   4344 /**
   4345   This function allows a caller to extract the current configuration
   4346   for one or more named elements from one or more drivers.
   4347 
   4348   @param  This                   A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
   4349                                  instance.
   4350   @param  Request                A null-terminated Unicode string in
   4351                                  <MultiConfigRequest> format.
   4352   @param  Progress               On return, points to a character in the Request
   4353                                  string. Points to the string's null terminator if
   4354                                  request was successful. Points to the most recent
   4355                                  & before the first failing name / value pair (or
   4356                                  the beginning of the string if the failure is in
   4357                                  the first name / value pair) if the request was
   4358                                  not successful.
   4359   @param  Results                Null-terminated Unicode string in
   4360                                  <MultiConfigAltResp> format which has all values
   4361                                  filled in for the names in the Request string.
   4362                                  String to be allocated by the called function.
   4363 
   4364   @retval EFI_SUCCESS            The Results string is filled with the values
   4365                                  corresponding to all requested names.
   4366   @retval EFI_OUT_OF_RESOURCES   Not enough memory to store the parts of the
   4367                                  results that must be stored awaiting possible
   4368                                  future        protocols.
   4369   @retval EFI_NOT_FOUND          Routing data doesn't match any known driver.
   4370                                    Progress set to the "G" in "GUID" of the routing
   4371                                   header that doesn't match. Note: There is no
   4372                                     requirement that all routing data be validated
   4373                                  before any configuration extraction.
   4374   @retval EFI_INVALID_PARAMETER  For example, passing in a NULL for the Request
   4375                                  parameter would result in this type of error. The
   4376                                  Progress parameter is set to NULL.
   4377   @retval EFI_INVALID_PARAMETER  Illegal syntax. Progress set to most recent &
   4378                                  before the error or the beginning of the string.
   4379   @retval EFI_INVALID_PARAMETER  The ExtractConfig function of the underlying HII
   4380                                  Configuration Access Protocol returned
   4381                                  EFI_INVALID_PARAMETER. Progress set to most recent
   4382                                  & before the error or the beginning of the string.
   4383 
   4384 **/
   4385 EFI_STATUS
   4386 EFIAPI
   4387 HiiConfigRoutingExtractConfig (
   4388   IN  CONST EFI_HII_CONFIG_ROUTING_PROTOCOL  *This,
   4389   IN  CONST EFI_STRING                       Request,
   4390   OUT EFI_STRING                             *Progress,
   4391   OUT EFI_STRING                             *Results
   4392   )
   4393 {
   4394   HII_DATABASE_PRIVATE_DATA           *Private;
   4395   EFI_STRING                          StringPtr;
   4396   EFI_STRING                          ConfigRequest;
   4397   UINTN                               Length;
   4398   EFI_DEVICE_PATH_PROTOCOL            *DevicePath;
   4399   EFI_DEVICE_PATH_PROTOCOL            *TempDevicePath;
   4400   EFI_STATUS                          Status;
   4401   LIST_ENTRY                          *Link;
   4402   HII_DATABASE_RECORD                 *Database;
   4403   UINT8                               *DevicePathPkg;
   4404   UINT8                               *CurrentDevicePath;
   4405   EFI_HANDLE                          DriverHandle;
   4406   EFI_HII_HANDLE                      HiiHandle;
   4407   EFI_HII_CONFIG_ACCESS_PROTOCOL      *ConfigAccess;
   4408   EFI_STRING                          AccessProgress;
   4409   EFI_STRING                          AccessResults;
   4410   EFI_STRING                          AccessProgressBackup;
   4411   EFI_STRING                          AccessResultsBackup;
   4412   EFI_STRING                          DefaultResults;
   4413   BOOLEAN                             FirstElement;
   4414   BOOLEAN                             IfrDataParsedFlag;
   4415   BOOLEAN                             IsEfiVarStore;
   4416   EFI_IFR_VARSTORE_EFI                *EfiVarStoreInfo;
   4417   EFI_STRING                          ErrorPtr;
   4418   UINTN                               DevicePathSize;
   4419   UINTN                               ConigStringSize;
   4420   UINTN                               ConigStringSizeNewsize;
   4421   EFI_STRING                          ConfigStringPtr;
   4422 
   4423   if (This == NULL || Progress == NULL || Results == NULL) {
   4424     return EFI_INVALID_PARAMETER;
   4425   }
   4426 
   4427   if (Request == NULL) {
   4428     *Progress = NULL;
   4429     return EFI_INVALID_PARAMETER;
   4430   }
   4431 
   4432   Private   = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);
   4433   StringPtr = Request;
   4434   *Progress = StringPtr;
   4435   DefaultResults = NULL;
   4436   ConfigRequest  = NULL;
   4437   Status         = EFI_SUCCESS;
   4438   AccessResults  = NULL;
   4439   AccessProgress = NULL;
   4440   AccessResultsBackup  = NULL;
   4441   AccessProgressBackup = NULL;
   4442   DevicePath     = NULL;
   4443   IfrDataParsedFlag = FALSE;
   4444   IsEfiVarStore     = FALSE;
   4445   EfiVarStoreInfo   = NULL;
   4446 
   4447   //
   4448   // The first element of <MultiConfigRequest> should be
   4449   // <GuidHdr>, which is in 'GUID='<Guid> syntax.
   4450   //
   4451   if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {
   4452     return EFI_INVALID_PARAMETER;
   4453   }
   4454 
   4455   FirstElement = TRUE;
   4456 
   4457   //
   4458   // Allocate a fix length of memory to store Results. Reallocate memory for
   4459   // Results if this fix length is insufficient.
   4460   //
   4461   *Results = (EFI_STRING) AllocateZeroPool (MAX_STRING_LENGTH);
   4462   if (*Results == NULL) {
   4463     return EFI_OUT_OF_RESOURCES;
   4464   }
   4465 
   4466   while (*StringPtr != 0 && StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) == 0) {
   4467     //
   4468     // If parsing error, set Progress to the beginning of the <MultiConfigRequest>
   4469     // or most recent & before the error.
   4470     //
   4471     if (StringPtr == Request) {
   4472       *Progress = StringPtr;
   4473     } else {
   4474       *Progress = StringPtr - 1;
   4475     }
   4476 
   4477     //
   4478     // Process each <ConfigRequest> of <MultiConfigRequest>
   4479     //
   4480     Length = CalculateConfigStringLen (StringPtr);
   4481     ConfigRequest = AllocateCopyPool ((Length + 1) * sizeof (CHAR16), StringPtr);
   4482     if (ConfigRequest == NULL) {
   4483       Status = EFI_OUT_OF_RESOURCES;
   4484       goto Done;
   4485     }
   4486     *(ConfigRequest + Length) = 0;
   4487 
   4488     //
   4489     // Get the UEFI device path
   4490     //
   4491     Status = GetDevicePath (ConfigRequest, (UINT8 **) &DevicePath);
   4492     if (EFI_ERROR (Status)) {
   4493       goto Done;
   4494     }
   4495 
   4496     //
   4497     // Find driver which matches the routing data.
   4498     //
   4499     DriverHandle     = NULL;
   4500     HiiHandle        = NULL;
   4501     Database         = NULL;
   4502     for (Link = Private->DatabaseList.ForwardLink;
   4503          Link != &Private->DatabaseList;
   4504          Link = Link->ForwardLink
   4505         ) {
   4506       Database = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
   4507       if ((DevicePathPkg = Database->PackageList->DevicePathPkg) != NULL) {
   4508         CurrentDevicePath = DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);
   4509         DevicePathSize    = GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) CurrentDevicePath);
   4510         if ((CompareMem (DevicePath,CurrentDevicePath,DevicePathSize) == 0) && IsThisPackageList(Database, ConfigRequest)) {
   4511           DriverHandle = Database->DriverHandle;
   4512           HiiHandle    = Database->Handle;
   4513           break;
   4514         }
   4515       }
   4516     }
   4517 
   4518     //
   4519     // Try to find driver handle by device path.
   4520     //
   4521     if (DriverHandle == NULL) {
   4522       TempDevicePath = DevicePath;
   4523       Status = gBS->LocateDevicePath (
   4524                       &gEfiDevicePathProtocolGuid,
   4525                       &TempDevicePath,
   4526                       &DriverHandle
   4527                       );
   4528       if (EFI_ERROR (Status) || (DriverHandle == NULL)) {
   4529         //
   4530         // Routing data does not match any known driver.
   4531         // Set Progress to the 'G' in "GUID" of the routing header.
   4532         //
   4533         *Progress = StringPtr;
   4534         Status = EFI_NOT_FOUND;
   4535         goto Done;
   4536       }
   4537     }
   4538 
   4539     //
   4540     // Validate ConfigRequest String.
   4541     //
   4542     ErrorPtr = ConfigRequestValidate(ConfigRequest);
   4543     if (ErrorPtr != NULL) {
   4544       *Progress = StrStr (StringPtr, ErrorPtr);
   4545       Status = EFI_INVALID_PARAMETER;
   4546       goto Done;
   4547     }
   4548 
   4549     //
   4550     // Check whether ConfigRequest contains request string.
   4551     //
   4552     IfrDataParsedFlag = FALSE;
   4553     if ((HiiHandle != NULL) && !GetElementsFromRequest(ConfigRequest)) {
   4554       //
   4555       // Get the full request string from IFR when HiiPackage is registered to HiiHandle
   4556       //
   4557       IfrDataParsedFlag = TRUE;
   4558       Status = GetFullStringFromHiiFormPackages (Database, DevicePath, &ConfigRequest, &DefaultResults, &AccessProgress);
   4559       if (EFI_ERROR (Status)) {
   4560         //
   4561         // AccessProgress indicates the parsing progress on <ConfigRequest>.
   4562         // Map it to the progress on <MultiConfigRequest> then return it.
   4563         //
   4564         ASSERT (AccessProgress != NULL);
   4565         *Progress = StrStr (StringPtr, AccessProgress);
   4566         goto Done;
   4567       }
   4568       //
   4569       // Not any request block is found.
   4570       //
   4571       if (!GetElementsFromRequest(ConfigRequest)) {
   4572         AccessResults = AllocateCopyPool (StrSize (ConfigRequest), ConfigRequest);
   4573         goto NextConfigString;
   4574       }
   4575     }
   4576 
   4577     //
   4578     // Check whether this ConfigRequest is search from Efi varstore type storage.
   4579     //
   4580     Status = GetVarStoreType(Database, ConfigRequest, &IsEfiVarStore, &EfiVarStoreInfo);
   4581     if (EFI_ERROR (Status)) {
   4582       goto Done;
   4583     }
   4584 
   4585     if (IsEfiVarStore) {
   4586       //
   4587       // Call the GetVariable function to extract settings.
   4588       //
   4589       Status = GetConfigRespFromEfiVarStore(This, EfiVarStoreInfo, ConfigRequest, &AccessResults, &AccessProgress);
   4590       FreePool (EfiVarStoreInfo);
   4591       if (EFI_ERROR (Status)) {
   4592         //
   4593         // AccessProgress indicates the parsing progress on <ConfigRequest>.
   4594         // Map it to the progress on <MultiConfigRequest> then return it.
   4595         //
   4596         *Progress = StrStr (StringPtr, AccessProgress);
   4597         goto Done;
   4598       }
   4599 
   4600       //
   4601       // For EfiVarstore, call corresponding ConfigAccess protocol to get the AltCfgResp from driver.
   4602       //
   4603       Status = gBS->HandleProtocol (
   4604                       DriverHandle,
   4605                       &gEfiHiiConfigAccessProtocolGuid,
   4606                       (VOID **) &ConfigAccess
   4607                       );
   4608       if (EFI_ERROR (Status)) {
   4609         //
   4610         // The driver has EfiVarStore, may not install ConfigAccess protocol.
   4611         // So ignore the error status in this case.
   4612         //
   4613         Status = EFI_SUCCESS;
   4614       } else {
   4615         Status = ConfigAccess->ExtractConfig (
   4616                                  ConfigAccess,
   4617                                  ConfigRequest,
   4618                                  &AccessProgressBackup,
   4619                                  &AccessResultsBackup
   4620                                  );
   4621         if (!EFI_ERROR(Status)) {
   4622           //
   4623           //Merge the AltCfgResp in AccessResultsBackup to AccessResults
   4624           //
   4625           if ((AccessResultsBackup != NULL) && (StrStr (AccessResultsBackup, L"&ALTCFG=") != NULL)) {
   4626             ConigStringSize = StrSize (AccessResults);
   4627             ConfigStringPtr = StrStr (AccessResultsBackup, L"&GUID=");
   4628             ConigStringSizeNewsize = StrSize (ConfigStringPtr) + ConigStringSize + sizeof (CHAR16);
   4629             AccessResults = (EFI_STRING) ReallocatePool (
   4630                                          ConigStringSize,
   4631                                          ConigStringSizeNewsize,
   4632                                          AccessResults);
   4633             StrCatS (AccessResults, ConigStringSizeNewsize / sizeof (CHAR16), ConfigStringPtr);
   4634           }
   4635         } else {
   4636           //
   4637           // In the ExtractConfig function of some driver may not support EfiVarStore,
   4638           // may return error status, just ignore the error status in this case.
   4639           //
   4640           Status = EFI_SUCCESS;
   4641         }
   4642         if (AccessResultsBackup != NULL) {
   4643           FreePool (AccessResultsBackup);
   4644           AccessResultsBackup = NULL;
   4645         }
   4646       }
   4647     } else {
   4648       //
   4649       // Call corresponding ConfigAccess protocol to extract settings
   4650       //
   4651       Status = gBS->HandleProtocol (
   4652                       DriverHandle,
   4653                       &gEfiHiiConfigAccessProtocolGuid,
   4654                       (VOID **) &ConfigAccess
   4655                       );
   4656       if (EFI_ERROR (Status)) {
   4657         goto Done;
   4658       }
   4659 
   4660       Status = ConfigAccess->ExtractConfig (
   4661                                ConfigAccess,
   4662                                ConfigRequest,
   4663                                &AccessProgress,
   4664                                &AccessResults
   4665                                );
   4666     }
   4667     if (EFI_ERROR (Status)) {
   4668       //
   4669       // AccessProgress indicates the parsing progress on <ConfigRequest>.
   4670       // Map it to the progress on <MultiConfigRequest> then return it.
   4671       //
   4672       *Progress = StrStr (StringPtr, AccessProgress);
   4673       goto Done;
   4674     }
   4675 
   4676     //
   4677     // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'
   4678     // which separates the first <ConfigAltResp> and the following ones.
   4679     //
   4680     ASSERT (*AccessProgress == 0);
   4681 
   4682     //
   4683     // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
   4684     //
   4685     if (!IfrDataParsedFlag && HiiHandle != NULL) {
   4686       Status = GetFullStringFromHiiFormPackages (Database, DevicePath, &ConfigRequest, &DefaultResults, NULL);
   4687       ASSERT_EFI_ERROR (Status);
   4688     }
   4689 
   4690     FreePool (DevicePath);
   4691     DevicePath = NULL;
   4692 
   4693     if (DefaultResults != NULL) {
   4694       Status = MergeDefaultString (&AccessResults, DefaultResults);
   4695       ASSERT_EFI_ERROR (Status);
   4696       FreePool (DefaultResults);
   4697       DefaultResults = NULL;
   4698     }
   4699 
   4700 NextConfigString:
   4701     if (!FirstElement) {
   4702       Status = AppendToMultiString (Results, L"&");
   4703       ASSERT_EFI_ERROR (Status);
   4704     }
   4705 
   4706     Status = AppendToMultiString (Results, AccessResults);
   4707     ASSERT_EFI_ERROR (Status);
   4708 
   4709     FirstElement = FALSE;
   4710 
   4711     FreePool (AccessResults);
   4712     AccessResults = NULL;
   4713     FreePool (ConfigRequest);
   4714     ConfigRequest = NULL;
   4715 
   4716     //
   4717     // Go to next <ConfigRequest> (skip '&').
   4718     //
   4719     StringPtr += Length;
   4720     if (*StringPtr == 0) {
   4721       *Progress = StringPtr;
   4722       break;
   4723     }
   4724 
   4725     StringPtr++;
   4726   }
   4727 
   4728 Done:
   4729   if (EFI_ERROR (Status)) {
   4730     FreePool (*Results);
   4731     *Results = NULL;
   4732   }
   4733 
   4734   if (ConfigRequest != NULL) {
   4735     FreePool (ConfigRequest);
   4736   }
   4737 
   4738   if (AccessResults != NULL) {
   4739     FreePool (AccessResults);
   4740   }
   4741 
   4742   if (DefaultResults != NULL) {
   4743     FreePool (DefaultResults);
   4744   }
   4745 
   4746   if (DevicePath != NULL) {
   4747     FreePool (DevicePath);
   4748   }
   4749 
   4750   return Status;
   4751 }
   4752 
   4753 
   4754 /**
   4755   This function allows the caller to request the current configuration for the
   4756   entirety of the current HII database and returns the data in a
   4757   null-terminated Unicode string.
   4758 
   4759   @param  This                   A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
   4760                                  instance.
   4761   @param  Results                Null-terminated Unicode string in
   4762                                  <MultiConfigAltResp> format which has all values
   4763                                  filled in for the entirety of the current HII
   4764                                  database. String to be allocated by the  called
   4765                                  function. De-allocation is up to the caller.
   4766 
   4767   @retval EFI_SUCCESS            The Results string is filled with the values
   4768                                  corresponding to all requested names.
   4769   @retval EFI_OUT_OF_RESOURCES   Not enough memory to store the parts of the
   4770                                  results that must be stored awaiting possible
   4771                                  future        protocols.
   4772   @retval EFI_INVALID_PARAMETER  For example, passing in a NULL for the Results
   4773                                  parameter would result in this type of error.
   4774 
   4775 **/
   4776 EFI_STATUS
   4777 EFIAPI
   4778 HiiConfigRoutingExportConfig (
   4779   IN  CONST EFI_HII_CONFIG_ROUTING_PROTOCOL  *This,
   4780   OUT EFI_STRING                             *Results
   4781   )
   4782 {
   4783   EFI_STATUS                          Status;
   4784   EFI_HII_CONFIG_ACCESS_PROTOCOL      *ConfigAccess;
   4785   EFI_STRING                          AccessResults;
   4786   EFI_STRING                          Progress;
   4787   EFI_STRING                          StringPtr;
   4788   EFI_STRING                          ConfigRequest;
   4789   UINTN                               Index;
   4790   EFI_HANDLE                          *ConfigAccessHandles;
   4791   UINTN                               NumberConfigAccessHandles;
   4792   BOOLEAN                             FirstElement;
   4793   EFI_DEVICE_PATH_PROTOCOL            *DevicePath;
   4794   EFI_HII_HANDLE                      HiiHandle;
   4795   EFI_STRING                          DefaultResults;
   4796   HII_DATABASE_PRIVATE_DATA           *Private;
   4797   LIST_ENTRY                          *Link;
   4798   HII_DATABASE_RECORD                 *Database;
   4799   UINT8                               *DevicePathPkg;
   4800   UINT8                               *CurrentDevicePath;
   4801   BOOLEAN                             IfrDataParsedFlag;
   4802 
   4803   if (This == NULL || Results == NULL) {
   4804     return EFI_INVALID_PARAMETER;
   4805   }
   4806 
   4807   Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);
   4808 
   4809   //
   4810   // Allocate a fix length of memory to store Results. Reallocate memory for
   4811   // Results if this fix length is insufficient.
   4812   //
   4813   *Results = (EFI_STRING) AllocateZeroPool (MAX_STRING_LENGTH);
   4814   if (*Results == NULL) {
   4815     return EFI_OUT_OF_RESOURCES;
   4816   }
   4817 
   4818   NumberConfigAccessHandles = 0;
   4819   Status = gBS->LocateHandleBuffer (
   4820              ByProtocol,
   4821              &gEfiHiiConfigAccessProtocolGuid,
   4822              NULL,
   4823              &NumberConfigAccessHandles,
   4824              &ConfigAccessHandles
   4825              );
   4826   if (EFI_ERROR (Status)) {
   4827     return Status;
   4828   }
   4829 
   4830   FirstElement = TRUE;
   4831 
   4832   for (Index = 0; Index < NumberConfigAccessHandles; Index++) {
   4833     Status = gBS->HandleProtocol (
   4834                     ConfigAccessHandles[Index],
   4835                     &gEfiHiiConfigAccessProtocolGuid,
   4836                     (VOID **) &ConfigAccess
   4837                     );
   4838     if (EFI_ERROR (Status)) {
   4839       continue;
   4840     }
   4841 
   4842     //
   4843     // Get DevicePath and HiiHandle for this ConfigAccess driver handle
   4844     //
   4845     IfrDataParsedFlag = FALSE;
   4846     Progress         = NULL;
   4847     HiiHandle        = NULL;
   4848     DefaultResults   = NULL;
   4849     Database         = NULL;
   4850     ConfigRequest    = NULL;
   4851     DevicePath       = DevicePathFromHandle (ConfigAccessHandles[Index]);
   4852     if (DevicePath != NULL) {
   4853       for (Link = Private->DatabaseList.ForwardLink;
   4854            Link != &Private->DatabaseList;
   4855            Link = Link->ForwardLink
   4856           ) {
   4857         Database = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
   4858         if ((DevicePathPkg = Database->PackageList->DevicePathPkg) != NULL) {
   4859           CurrentDevicePath = DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);
   4860           if (CompareMem (
   4861                 DevicePath,
   4862                 CurrentDevicePath,
   4863                 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) CurrentDevicePath)
   4864                 ) == 0) {
   4865             HiiHandle = Database->Handle;
   4866             break;
   4867           }
   4868         }
   4869       }
   4870     }
   4871 
   4872     Status = ConfigAccess->ExtractConfig (
   4873                              ConfigAccess,
   4874                              NULL,
   4875                              &Progress,
   4876                              &AccessResults
   4877                              );
   4878     if (EFI_ERROR (Status)) {
   4879       //
   4880       // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
   4881       //
   4882       if (HiiHandle != NULL && DevicePath != NULL) {
   4883         IfrDataParsedFlag = TRUE;
   4884         Status = GetFullStringFromHiiFormPackages (Database, DevicePath, &ConfigRequest, &DefaultResults, NULL);
   4885         //
   4886         // Get the full request string to get the Current setting again.
   4887         //
   4888         if (!EFI_ERROR (Status) && ConfigRequest != NULL) {
   4889           Status = ConfigAccess->ExtractConfig (
   4890                                    ConfigAccess,
   4891                                    ConfigRequest,
   4892                                    &Progress,
   4893                                    &AccessResults
   4894                                    );
   4895           FreePool (ConfigRequest);
   4896         } else {
   4897           Status = EFI_NOT_FOUND;
   4898         }
   4899       }
   4900     }
   4901 
   4902     if (!EFI_ERROR (Status)) {
   4903       //
   4904       // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
   4905       //
   4906       if (!IfrDataParsedFlag && HiiHandle != NULL && DevicePath != NULL) {
   4907         StringPtr = StrStr (AccessResults, L"&GUID=");
   4908         if (StringPtr != NULL) {
   4909           *StringPtr = 0;
   4910         }
   4911         if (GetElementsFromRequest (AccessResults)) {
   4912           Status = GetFullStringFromHiiFormPackages (Database, DevicePath, &AccessResults, &DefaultResults, NULL);
   4913           ASSERT_EFI_ERROR (Status);
   4914         }
   4915         if (StringPtr != NULL) {
   4916           *StringPtr = L'&';
   4917         }
   4918       }
   4919       //
   4920       // Merge the default sting from IFR code into the got setting from driver.
   4921       //
   4922       if (DefaultResults != NULL) {
   4923         Status = MergeDefaultString (&AccessResults, DefaultResults);
   4924         ASSERT_EFI_ERROR (Status);
   4925         FreePool (DefaultResults);
   4926         DefaultResults = NULL;
   4927       }
   4928 
   4929       //
   4930       // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'
   4931       // which separates the first <ConfigAltResp> and the following ones.
   4932       //
   4933       if (!FirstElement) {
   4934         Status = AppendToMultiString (Results, L"&");
   4935         ASSERT_EFI_ERROR (Status);
   4936       }
   4937 
   4938       Status = AppendToMultiString (Results, AccessResults);
   4939       ASSERT_EFI_ERROR (Status);
   4940 
   4941       FirstElement = FALSE;
   4942 
   4943       FreePool (AccessResults);
   4944       AccessResults = NULL;
   4945     }
   4946   }
   4947   FreePool (ConfigAccessHandles);
   4948 
   4949   return EFI_SUCCESS;
   4950 }
   4951 
   4952 
   4953 /**
   4954   This function processes the results of processing forms and routes it to the
   4955   appropriate handlers or storage.
   4956 
   4957   @param  This                   A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
   4958                                  instance.
   4959   @param  Configuration          A null-terminated Unicode string in
   4960                                  <MulltiConfigResp> format.
   4961   @param  Progress               A pointer to a string filled in with the offset of
   4962                                  the most recent & before the first failing name /
   4963                                  value pair (or the beginning of the string if the
   4964                                  failure is in the first name / value pair) or the
   4965                                  terminating NULL if all was successful.
   4966 
   4967   @retval EFI_SUCCESS            The results have been distributed or are awaiting
   4968                                  distribution.
   4969   @retval EFI_OUT_OF_RESOURCES   Not enough memory to store the parts of the
   4970                                  results that must be stored awaiting possible
   4971                                  future        protocols.
   4972   @retval EFI_INVALID_PARAMETER  Passing in a NULL for the Configuration parameter
   4973                                  would result in this type of error.
   4974   @retval EFI_NOT_FOUND          Target for the specified routing data was not
   4975                                  found.
   4976 
   4977 **/
   4978 EFI_STATUS
   4979 EFIAPI
   4980 HiiConfigRoutingRouteConfig (
   4981   IN  CONST EFI_HII_CONFIG_ROUTING_PROTOCOL  *This,
   4982   IN  CONST EFI_STRING                       Configuration,
   4983   OUT EFI_STRING                             *Progress
   4984   )
   4985 {
   4986   HII_DATABASE_PRIVATE_DATA           *Private;
   4987   EFI_STRING                          StringPtr;
   4988   EFI_STRING                          ConfigResp;
   4989   UINTN                               Length;
   4990   EFI_STATUS                          Status;
   4991   EFI_DEVICE_PATH_PROTOCOL            *DevicePath;
   4992   EFI_DEVICE_PATH_PROTOCOL            *TempDevicePath;
   4993   LIST_ENTRY                          *Link;
   4994   HII_DATABASE_RECORD                 *Database;
   4995   UINT8                               *DevicePathPkg;
   4996   UINT8                               *CurrentDevicePath;
   4997   EFI_HANDLE                          DriverHandle;
   4998   EFI_HII_CONFIG_ACCESS_PROTOCOL      *ConfigAccess;
   4999   EFI_STRING                          AccessProgress;
   5000   EFI_IFR_VARSTORE_EFI                *EfiVarStoreInfo;
   5001   BOOLEAN                             IsEfiVarstore;
   5002   UINTN                               DevicePathSize;
   5003 
   5004   if (This == NULL || Progress == NULL) {
   5005     return EFI_INVALID_PARAMETER;
   5006   }
   5007 
   5008   if (Configuration == NULL) {
   5009     *Progress = NULL;
   5010     return EFI_INVALID_PARAMETER;
   5011   }
   5012 
   5013   Private   = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);
   5014   StringPtr = Configuration;
   5015   *Progress = StringPtr;
   5016   Database       = NULL;
   5017   AccessProgress = NULL;
   5018   EfiVarStoreInfo= NULL;
   5019   IsEfiVarstore  = FALSE;
   5020 
   5021   //
   5022   // The first element of <MultiConfigResp> should be
   5023   // <GuidHdr>, which is in 'GUID='<Guid> syntax.
   5024   //
   5025   if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {
   5026     return EFI_INVALID_PARAMETER;
   5027   }
   5028 
   5029   while (*StringPtr != 0 && StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) == 0) {
   5030     //
   5031     // If parsing error, set Progress to the beginning of the <MultiConfigResp>
   5032     // or most recent & before the error.
   5033     //
   5034     if (StringPtr == Configuration) {
   5035       *Progress = StringPtr;
   5036     } else {
   5037       *Progress = StringPtr - 1;
   5038     }
   5039 
   5040     //
   5041     // Process each <ConfigResp> of <MultiConfigResp>
   5042     //
   5043     Length = CalculateConfigStringLen (StringPtr);
   5044     ConfigResp = AllocateCopyPool ((Length + 1) * sizeof (CHAR16), StringPtr);
   5045     if (ConfigResp == NULL) {
   5046       return EFI_OUT_OF_RESOURCES;
   5047     }
   5048     //
   5049     // Append '\0' to the end of ConfigRequest
   5050     //
   5051     *(ConfigResp + Length) = 0;
   5052 
   5053     //
   5054     // Get the UEFI device path
   5055     //
   5056     Status = GetDevicePath (ConfigResp, (UINT8 **) &DevicePath);
   5057     if (EFI_ERROR (Status)) {
   5058       FreePool (ConfigResp);
   5059       return Status;
   5060     }
   5061 
   5062     //
   5063     // Find driver which matches the routing data.
   5064     //
   5065     DriverHandle     = NULL;
   5066     for (Link = Private->DatabaseList.ForwardLink;
   5067          Link != &Private->DatabaseList;
   5068          Link = Link->ForwardLink
   5069         ) {
   5070       Database = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
   5071 
   5072       if ((DevicePathPkg = Database->PackageList->DevicePathPkg) != NULL) {
   5073         CurrentDevicePath = DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);
   5074         DevicePathSize    = GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) CurrentDevicePath);
   5075         if ((CompareMem (DevicePath,CurrentDevicePath,DevicePathSize) == 0) && IsThisPackageList(Database, ConfigResp)) {
   5076           DriverHandle = Database->DriverHandle;
   5077           break;
   5078         }
   5079       }
   5080     }
   5081 
   5082     //
   5083     // Try to find driver handle by device path.
   5084     //
   5085     if (DriverHandle == NULL) {
   5086       TempDevicePath = DevicePath;
   5087       Status = gBS->LocateDevicePath (
   5088                       &gEfiDevicePathProtocolGuid,
   5089                       &TempDevicePath,
   5090                       &DriverHandle
   5091                       );
   5092       if (EFI_ERROR (Status) || (DriverHandle == NULL)) {
   5093         //
   5094         // Routing data does not match any known driver.
   5095         // Set Progress to the 'G' in "GUID" of the routing header.
   5096         //
   5097         FreePool (DevicePath);
   5098         *Progress = StringPtr;
   5099         FreePool (ConfigResp);
   5100         return EFI_NOT_FOUND;
   5101       }
   5102     }
   5103 
   5104     FreePool (DevicePath);
   5105 
   5106     //
   5107     // Check whether this ConfigRequest is search from Efi varstore type storage.
   5108     //
   5109     Status = GetVarStoreType(Database, ConfigResp, &IsEfiVarstore, &EfiVarStoreInfo);
   5110     if (EFI_ERROR (Status)) {
   5111       return Status;
   5112     }
   5113 
   5114     if (IsEfiVarstore) {
   5115       //
   5116       // Call the SetVariable function to route settings.
   5117       //
   5118       Status = RouteConfigRespForEfiVarStore(This, EfiVarStoreInfo, ConfigResp, &AccessProgress);
   5119       FreePool (EfiVarStoreInfo);
   5120     } else {
   5121       //
   5122       // Call corresponding ConfigAccess protocol to route settings
   5123       //
   5124       Status = gBS->HandleProtocol (
   5125                       DriverHandle,
   5126                       &gEfiHiiConfigAccessProtocolGuid,
   5127                       (VOID **)  &ConfigAccess
   5128                       );
   5129       if (EFI_ERROR (Status)) {
   5130         *Progress = StringPtr;
   5131         FreePool (ConfigResp);
   5132         return EFI_NOT_FOUND;
   5133       }
   5134 
   5135       Status = ConfigAccess->RouteConfig (
   5136                                ConfigAccess,
   5137                                ConfigResp,
   5138                                &AccessProgress
   5139                                );
   5140     }
   5141     if (EFI_ERROR (Status)) {
   5142       ASSERT (AccessProgress != NULL);
   5143       //
   5144       // AccessProgress indicates the parsing progress on <ConfigResp>.
   5145       // Map it to the progress on <MultiConfigResp> then return it.
   5146       //
   5147       *Progress = StrStr (StringPtr, AccessProgress);
   5148 
   5149       FreePool (ConfigResp);
   5150       return Status;
   5151     }
   5152 
   5153     FreePool (ConfigResp);
   5154     ConfigResp = NULL;
   5155 
   5156     //
   5157     // Go to next <ConfigResp> (skip '&').
   5158     //
   5159     StringPtr += Length;
   5160     if (*StringPtr == 0) {
   5161       *Progress = StringPtr;
   5162       break;
   5163     }
   5164 
   5165     StringPtr++;
   5166 
   5167   }
   5168 
   5169   return EFI_SUCCESS;
   5170 }
   5171 
   5172 
   5173 /**
   5174   This helper function is to be called by drivers to map configuration data
   5175   stored in byte array ("block") formats such as UEFI Variables into current
   5176   configuration strings.
   5177 
   5178   @param  This                   A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
   5179                                  instance.
   5180   @param  ConfigRequest          A null-terminated Unicode string in
   5181                                  <ConfigRequest> format.
   5182   @param  Block                  Array of bytes defining the block's configuration.
   5183   @param  BlockSize              Length in bytes of Block.
   5184   @param  Config                 Filled-in configuration string. String allocated
   5185                                  by  the function. Returned only if call is
   5186                                  successful. It is <ConfigResp> string format.
   5187   @param  Progress               A pointer to a string filled in with the offset of
   5188                                   the most recent & before the first failing
   5189                                  name/value pair (or the beginning of the string if
   5190                                  the failure is in the first name / value pair) or
   5191                                  the terminating NULL if all was successful.
   5192 
   5193   @retval EFI_SUCCESS            The request succeeded. Progress points to the null
   5194                                  terminator at the end of the ConfigRequest
   5195                                  string.
   5196   @retval EFI_OUT_OF_RESOURCES   Not enough memory to allocate Config.     Progress
   5197                                  points to the first character of ConfigRequest.
   5198   @retval EFI_INVALID_PARAMETER  Passing in a NULL for the ConfigRequest or
   5199                                  Block parameter would result in this type of
   5200                                  error. Progress points to the first character of
   5201                                  ConfigRequest.
   5202   @retval EFI_DEVICE_ERROR       Block not large enough. Progress undefined.
   5203   @retval EFI_INVALID_PARAMETER  Encountered non <BlockName> formatted string.
   5204                                      Block is left updated and Progress points at
   5205                                  the "&" preceding the first non-<BlockName>.
   5206 
   5207 **/
   5208 EFI_STATUS
   5209 EFIAPI
   5210 HiiBlockToConfig (
   5211   IN  CONST EFI_HII_CONFIG_ROUTING_PROTOCOL  *This,
   5212   IN  CONST EFI_STRING                       ConfigRequest,
   5213   IN  CONST UINT8                            *Block,
   5214   IN  CONST UINTN                            BlockSize,
   5215   OUT EFI_STRING                             *Config,
   5216   OUT EFI_STRING                             *Progress
   5217   )
   5218 {
   5219   HII_DATABASE_PRIVATE_DATA           *Private;
   5220   EFI_STRING                          StringPtr;
   5221   UINTN                               Length;
   5222   EFI_STATUS                          Status;
   5223   EFI_STRING                          TmpPtr;
   5224   UINT8                               *TmpBuffer;
   5225   UINTN                               Offset;
   5226   UINTN                               Width;
   5227   UINT8                               *Value;
   5228   EFI_STRING                          ValueStr;
   5229   EFI_STRING                          ConfigElement;
   5230   UINTN                               Index;
   5231   UINT8                               *TemBuffer;
   5232   CHAR16                              *TemString;
   5233   CHAR16                              TemChar;
   5234 
   5235   TmpBuffer = NULL;
   5236 
   5237   if (This == NULL || Progress == NULL || Config == NULL) {
   5238     return EFI_INVALID_PARAMETER;
   5239   }
   5240 
   5241   if (Block == NULL || ConfigRequest == NULL) {
   5242     *Progress = ConfigRequest;
   5243     return EFI_INVALID_PARAMETER;
   5244   }
   5245 
   5246 
   5247   Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);
   5248   ASSERT (Private != NULL);
   5249 
   5250   StringPtr     = ConfigRequest;
   5251   ValueStr      = NULL;
   5252   Value         = NULL;
   5253   ConfigElement = NULL;
   5254 
   5255   //
   5256   // Allocate a fix length of memory to store Results. Reallocate memory for
   5257   // Results if this fix length is insufficient.
   5258   //
   5259   *Config = (EFI_STRING) AllocateZeroPool (MAX_STRING_LENGTH);
   5260   if (*Config == NULL) {
   5261     return EFI_OUT_OF_RESOURCES;
   5262   }
   5263 
   5264   //
   5265   // Jump <ConfigHdr>
   5266   //
   5267   if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {
   5268     *Progress = StringPtr;
   5269     Status = EFI_INVALID_PARAMETER;
   5270     goto Exit;
   5271   }
   5272   while (*StringPtr != 0 && StrnCmp (StringPtr, L"PATH=", StrLen (L"PATH=")) != 0) {
   5273     StringPtr++;
   5274   }
   5275   if (*StringPtr == 0) {
   5276     *Progress = StringPtr - 1;
   5277     Status = EFI_INVALID_PARAMETER;
   5278     goto Exit;
   5279   }
   5280 
   5281   while (*StringPtr != L'&' && *StringPtr != 0) {
   5282     StringPtr++;
   5283   }
   5284   if (*StringPtr == 0) {
   5285     *Progress = StringPtr;
   5286 
   5287     AppendToMultiString(Config, ConfigRequest);
   5288     HiiToLower (*Config);
   5289 
   5290     return EFI_SUCCESS;
   5291   }
   5292   //
   5293   // Skip '&'
   5294   //
   5295   StringPtr++;
   5296 
   5297   //
   5298   // Copy <ConfigHdr> and an additional '&' to <ConfigResp>
   5299   //
   5300   TemChar = *StringPtr;
   5301   *StringPtr = '\0';
   5302   AppendToMultiString(Config, ConfigRequest);
   5303   *StringPtr = TemChar;
   5304 
   5305   //
   5306   // Parse each <RequestElement> if exists
   5307   // Only <BlockName> format is supported by this help function.
   5308   // <BlockName> ::= 'OFFSET='<Number>&'WIDTH='<Number>
   5309   //
   5310   while (*StringPtr != 0 && StrnCmp (StringPtr, L"OFFSET=", StrLen (L"OFFSET=")) == 0) {
   5311     //
   5312     // Back up the header of one <BlockName>
   5313     //
   5314     TmpPtr = StringPtr;
   5315 
   5316     StringPtr += StrLen (L"OFFSET=");
   5317     //
   5318     // Get Offset
   5319     //
   5320     Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
   5321     if (EFI_ERROR (Status)) {
   5322       *Progress = TmpPtr - 1;
   5323       goto Exit;
   5324     }
   5325     Offset = 0;
   5326     CopyMem (
   5327       &Offset,
   5328       TmpBuffer,
   5329       (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)
   5330       );
   5331     FreePool (TmpBuffer);
   5332 
   5333     StringPtr += Length;
   5334     if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {
   5335       *Progress = TmpPtr - 1;
   5336       Status = EFI_INVALID_PARAMETER;
   5337       goto Exit;
   5338     }
   5339     StringPtr += StrLen (L"&WIDTH=");
   5340 
   5341     //
   5342     // Get Width
   5343     //
   5344     Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
   5345     if (EFI_ERROR (Status)) {
   5346       *Progress =  TmpPtr - 1;
   5347       goto Exit;
   5348     }
   5349     Width = 0;
   5350     CopyMem (
   5351       &Width,
   5352       TmpBuffer,
   5353       (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)
   5354       );
   5355     FreePool (TmpBuffer);
   5356 
   5357     StringPtr += Length;
   5358     if (*StringPtr != 0 && *StringPtr != L'&') {
   5359       *Progress =  TmpPtr - 1;
   5360       Status = EFI_INVALID_PARAMETER;
   5361       goto Exit;
   5362     }
   5363 
   5364     //
   5365     // Calculate Value and convert it to hex string.
   5366     //
   5367     if (Offset + Width > BlockSize) {
   5368       *Progress = StringPtr;
   5369       Status = EFI_DEVICE_ERROR;
   5370       goto Exit;
   5371     }
   5372 
   5373     Value = (UINT8 *) AllocateZeroPool (Width);
   5374     if (Value == NULL) {
   5375       *Progress = ConfigRequest;
   5376       Status = EFI_OUT_OF_RESOURCES;
   5377       goto Exit;
   5378     }
   5379 
   5380     CopyMem (Value, (UINT8 *) Block + Offset, Width);
   5381 
   5382     Length = Width * 2 + 1;
   5383     ValueStr = (EFI_STRING) AllocateZeroPool (Length  * sizeof (CHAR16));
   5384     if (ValueStr == NULL) {
   5385       *Progress = ConfigRequest;
   5386       Status = EFI_OUT_OF_RESOURCES;
   5387       goto Exit;
   5388     }
   5389 
   5390     TemString = ValueStr;
   5391     TemBuffer = Value + Width - 1;
   5392     for (Index = 0; Index < Width; Index ++, TemBuffer --) {
   5393       TemString += UnicodeValueToString (TemString, PREFIX_ZERO | RADIX_HEX, *TemBuffer, 2);
   5394     }
   5395 
   5396     FreePool (Value);
   5397     Value = NULL;
   5398 
   5399     //
   5400     // Build a ConfigElement
   5401     //
   5402     Length += StringPtr - TmpPtr + 1 + StrLen (L"VALUE=");
   5403     ConfigElement = (EFI_STRING) AllocateZeroPool (Length * sizeof (CHAR16));
   5404     if (ConfigElement == NULL) {
   5405       Status = EFI_OUT_OF_RESOURCES;
   5406       goto Exit;
   5407     }
   5408     CopyMem (ConfigElement, TmpPtr, (StringPtr - TmpPtr + 1) * sizeof (CHAR16));
   5409     if (*StringPtr == 0) {
   5410       *(ConfigElement + (StringPtr - TmpPtr)) = L'&';
   5411     }
   5412     *(ConfigElement + (StringPtr - TmpPtr) + 1) = 0;
   5413     StrCatS (ConfigElement, Length, L"VALUE=");
   5414     StrCatS (ConfigElement, Length, ValueStr);
   5415 
   5416     AppendToMultiString (Config, ConfigElement);
   5417 
   5418     FreePool (ConfigElement);
   5419     FreePool (ValueStr);
   5420     ConfigElement = NULL;
   5421     ValueStr = NULL;
   5422 
   5423     //
   5424     // If '\0', parsing is finished. Otherwise skip '&' to continue
   5425     //
   5426     if (*StringPtr == 0) {
   5427       break;
   5428     }
   5429     AppendToMultiString (Config, L"&");
   5430     StringPtr++;
   5431 
   5432   }
   5433 
   5434   if (*StringPtr != 0) {
   5435     *Progress = StringPtr - 1;
   5436     Status = EFI_INVALID_PARAMETER;
   5437     goto Exit;
   5438   }
   5439 
   5440   HiiToLower (*Config);
   5441   *Progress = StringPtr;
   5442   return EFI_SUCCESS;
   5443 
   5444 Exit:
   5445   if (*Config != NULL) {
   5446   FreePool (*Config);
   5447   *Config = NULL;
   5448   }
   5449   if (ValueStr != NULL) {
   5450     FreePool (ValueStr);
   5451   }
   5452   if (Value != NULL) {
   5453     FreePool (Value);
   5454   }
   5455   if (ConfigElement != NULL) {
   5456     FreePool (ConfigElement);
   5457   }
   5458 
   5459   return Status;
   5460 
   5461 }
   5462 
   5463 
   5464 /**
   5465   This helper function is to be called by drivers to map configuration strings
   5466   to configurations stored in byte array ("block") formats such as UEFI Variables.
   5467 
   5468   @param  This                   A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
   5469                                  instance.
   5470   @param  ConfigResp             A null-terminated Unicode string in <ConfigResp>
   5471                                  format.
   5472   @param  Block                  A possibly null array of bytes representing the
   5473                                  current  block. Only bytes referenced in the
   5474                                  ConfigResp string  in the block are modified. If
   5475                                  this parameter is null or if the *BlockSize
   5476                                  parameter is (on input) shorter than required by
   5477                                  the Configuration string, only the BlockSize
   5478                                  parameter is updated and an appropriate status
   5479                                  (see below)  is returned.
   5480   @param  BlockSize              The length of the Block in units of UINT8.  On
   5481                                  input, this is the size of the Block. On output,
   5482                                  if successful, contains the largest index of the
   5483                                  modified byte in the Block, or the required buffer
   5484                                  size if the Block is not large enough.
   5485   @param  Progress               On return, points to an element of the ConfigResp
   5486                                  string filled in with the offset of the most
   5487                                  recent '&' before the first failing name / value
   5488                                  pair (or  the beginning of the string if the
   5489                                  failure is in the  first name / value pair) or the
   5490                                  terminating NULL if all was successful.
   5491 
   5492   @retval EFI_SUCCESS            The request succeeded. Progress points to the null
   5493                                  terminator at the end of the ConfigResp string.
   5494   @retval EFI_OUT_OF_RESOURCES   Not enough memory to allocate Config.     Progress
   5495                                  points to the first character of ConfigResp.
   5496   @retval EFI_INVALID_PARAMETER  Passing in a NULL for the ConfigResp or
   5497                                  Block parameter would result in this type of
   5498                                  error. Progress points to the first character of
   5499                                          ConfigResp.
   5500   @retval EFI_INVALID_PARAMETER  Encountered non <BlockName> formatted name /
   5501                                  value pair. Block is left updated and
   5502                                  Progress points at the '&' preceding the first
   5503                                  non-<BlockName>.
   5504   @retval EFI_BUFFER_TOO_SMALL   Block not large enough. Progress undefined.
   5505                                  BlockSize is updated with the required buffer size.
   5506   @retval EFI_NOT_FOUND          Target for the specified routing data was not found.
   5507                                  Progress points to the "G" in "GUID" of the errant
   5508                                  routing data.
   5509 
   5510 **/
   5511 EFI_STATUS
   5512 EFIAPI
   5513 HiiConfigToBlock (
   5514   IN     CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
   5515   IN     CONST EFI_STRING                      ConfigResp,
   5516   IN OUT UINT8                                 *Block,
   5517   IN OUT UINTN                                 *BlockSize,
   5518   OUT    EFI_STRING                            *Progress
   5519   )
   5520 {
   5521   HII_DATABASE_PRIVATE_DATA           *Private;
   5522   EFI_STRING                          StringPtr;
   5523   EFI_STRING                          TmpPtr;
   5524   UINTN                               Length;
   5525   EFI_STATUS                          Status;
   5526   UINT8                               *TmpBuffer;
   5527   UINTN                               Offset;
   5528   UINTN                               Width;
   5529   UINT8                               *Value;
   5530   UINTN                               BufferSize;
   5531   UINTN                               MaxBlockSize;
   5532 
   5533   TmpBuffer = NULL;
   5534 
   5535   if (This == NULL || BlockSize == NULL || Progress == NULL) {
   5536     return EFI_INVALID_PARAMETER;
   5537   }
   5538 
   5539   *Progress = ConfigResp;
   5540   if (ConfigResp == NULL) {
   5541     return EFI_INVALID_PARAMETER;
   5542   }
   5543 
   5544   Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);
   5545   ASSERT (Private != NULL);
   5546 
   5547   StringPtr  = ConfigResp;
   5548   BufferSize = *BlockSize;
   5549   Value      = NULL;
   5550   MaxBlockSize = 0;
   5551 
   5552   //
   5553   // Jump <ConfigHdr>
   5554   //
   5555   if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {
   5556     *Progress = StringPtr;
   5557     Status = EFI_INVALID_PARAMETER;
   5558     goto Exit;
   5559   }
   5560   while (*StringPtr != 0 && StrnCmp (StringPtr, L"PATH=", StrLen (L"PATH=")) != 0) {
   5561     StringPtr++;
   5562   }
   5563   if (*StringPtr == 0) {
   5564     *Progress = StringPtr;
   5565     Status = EFI_INVALID_PARAMETER;
   5566     goto Exit;
   5567   }
   5568 
   5569   while (*StringPtr != L'&' && *StringPtr != 0) {
   5570     StringPtr++;
   5571   }
   5572   if (*StringPtr == 0) {
   5573     *Progress = StringPtr;
   5574     Status = EFI_INVALID_PARAMETER;
   5575     goto Exit;
   5576   }
   5577 
   5578   //
   5579   // Parse each <ConfigElement> if exists
   5580   // Only '&'<BlockConfig> format is supported by this help function.
   5581   // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE='<Number>
   5582   //
   5583   while (*StringPtr != 0 && StrnCmp (StringPtr, L"&OFFSET=", StrLen (L"&OFFSET=")) == 0) {
   5584     TmpPtr     = StringPtr;
   5585     StringPtr += StrLen (L"&OFFSET=");
   5586     //
   5587     // Get Offset
   5588     //
   5589     Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
   5590     if (EFI_ERROR (Status)) {
   5591       *Progress = TmpPtr;
   5592       goto Exit;
   5593     }
   5594     Offset = 0;
   5595     CopyMem (
   5596       &Offset,
   5597       TmpBuffer,
   5598       (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)
   5599       );
   5600     FreePool (TmpBuffer);
   5601 
   5602     StringPtr += Length;
   5603     if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {
   5604       *Progress = TmpPtr;
   5605       Status = EFI_INVALID_PARAMETER;
   5606       goto Exit;
   5607     }
   5608     StringPtr += StrLen (L"&WIDTH=");
   5609 
   5610     //
   5611     // Get Width
   5612     //
   5613     Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
   5614     if (EFI_ERROR (Status)) {
   5615       *Progress = TmpPtr;
   5616       goto Exit;
   5617     }
   5618     Width = 0;
   5619     CopyMem (
   5620       &Width,
   5621       TmpBuffer,
   5622       (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)
   5623       );
   5624     FreePool (TmpBuffer);
   5625 
   5626     StringPtr += Length;
   5627     if (StrnCmp (StringPtr, L"&VALUE=", StrLen (L"&VALUE=")) != 0) {
   5628       *Progress = TmpPtr;
   5629       Status = EFI_INVALID_PARAMETER;
   5630       goto Exit;
   5631     }
   5632     StringPtr += StrLen (L"&VALUE=");
   5633 
   5634     //
   5635     // Get Value
   5636     //
   5637     Status = GetValueOfNumber (StringPtr, &Value, &Length);
   5638     if (EFI_ERROR (Status)) {
   5639       *Progress = TmpPtr;
   5640       goto Exit;
   5641     }
   5642 
   5643     StringPtr += Length;
   5644     if (*StringPtr != 0 && *StringPtr != L'&') {
   5645       *Progress = TmpPtr;
   5646       Status = EFI_INVALID_PARAMETER;
   5647       goto Exit;
   5648     }
   5649 
   5650     //
   5651     // Update the Block with configuration info
   5652     //
   5653     if ((Block != NULL) && (Offset + Width <= BufferSize)) {
   5654       CopyMem (Block + Offset, Value, Width);
   5655     }
   5656     if (Offset + Width > MaxBlockSize) {
   5657       MaxBlockSize = Offset + Width;
   5658     }
   5659 
   5660     FreePool (Value);
   5661     Value = NULL;
   5662 
   5663     //
   5664     // If '\0', parsing is finished.
   5665     //
   5666     if (*StringPtr == 0) {
   5667       break;
   5668     }
   5669   }
   5670 
   5671   //
   5672   // The input string is not ConfigResp format, return error.
   5673   //
   5674   if (*StringPtr != 0) {
   5675     *Progress = StringPtr;
   5676     Status = EFI_INVALID_PARAMETER;
   5677     goto Exit;
   5678   }
   5679 
   5680   *Progress = StringPtr + StrLen (StringPtr);
   5681   *BlockSize = MaxBlockSize - 1;
   5682 
   5683   if (MaxBlockSize > BufferSize) {
   5684     *BlockSize = MaxBlockSize;
   5685     if (Block != NULL) {
   5686       return EFI_BUFFER_TOO_SMALL;
   5687     }
   5688   }
   5689 
   5690   if (Block == NULL) {
   5691     *Progress = ConfigResp;
   5692     return EFI_INVALID_PARAMETER;
   5693   }
   5694 
   5695   return EFI_SUCCESS;
   5696 
   5697 Exit:
   5698 
   5699   if (Value != NULL) {
   5700     FreePool (Value);
   5701   }
   5702   return Status;
   5703 }
   5704 
   5705 
   5706 /**
   5707   This helper function is to be called by drivers to extract portions of
   5708   a larger configuration string.
   5709 
   5710   @param  This                   A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
   5711                                  instance.
   5712   @param  Configuration          A null-terminated Unicode string in
   5713                                  <MultiConfigAltResp> format.
   5714   @param  Guid                   A pointer to the GUID value to search for in the
   5715                                  routing portion of the ConfigResp string when
   5716                                  retrieving  the requested data. If Guid is NULL,
   5717                                  then all GUID  values will be searched for.
   5718   @param  Name                   A pointer to the NAME value to search for in the
   5719                                  routing portion of the ConfigResp string when
   5720                                  retrieving  the requested data. If Name is NULL,
   5721                                  then all Name  values will be searched for.
   5722   @param  DevicePath             A pointer to the PATH value to search for in the
   5723                                  routing portion of the ConfigResp string when
   5724                                  retrieving  the requested data. If DevicePath is
   5725                                  NULL, then all  DevicePath values will be searched
   5726                                  for.
   5727   @param  AltCfgId               A pointer to the ALTCFG value to search for in the
   5728                                   routing portion of the ConfigResp string when
   5729                                  retrieving  the requested data.  If this parameter
   5730                                  is NULL,  then the current setting will be
   5731                                  retrieved.
   5732   @param  AltCfgResp             A pointer to a buffer which will be allocated by
   5733                                  the  function which contains the retrieved string
   5734                                  as requested.   This buffer is only allocated if
   5735                                  the call was successful. It is <ConfigResp> format.
   5736 
   5737   @retval EFI_SUCCESS            The request succeeded. The requested data was
   5738                                  extracted  and placed in the newly allocated
   5739                                  AltCfgResp buffer.
   5740   @retval EFI_OUT_OF_RESOURCES   Not enough memory to allocate AltCfgResp.
   5741   @retval EFI_INVALID_PARAMETER  Any parameter is invalid.
   5742   @retval EFI_NOT_FOUND          Target for the specified routing data was not
   5743                                  found.
   5744 
   5745 **/
   5746 EFI_STATUS
   5747 EFIAPI
   5748 HiiGetAltCfg (
   5749   IN  CONST EFI_HII_CONFIG_ROUTING_PROTOCOL    *This,
   5750   IN  CONST EFI_STRING                         Configuration,
   5751   IN  CONST EFI_GUID                           *Guid,
   5752   IN  CONST EFI_STRING                         Name,
   5753   IN  CONST EFI_DEVICE_PATH_PROTOCOL           *DevicePath,
   5754   IN  CONST UINT16                             *AltCfgId,
   5755   OUT EFI_STRING                               *AltCfgResp
   5756   )
   5757 {
   5758   EFI_STATUS                          Status;
   5759   EFI_STRING                          StringPtr;
   5760   EFI_STRING                          HdrStart;
   5761   EFI_STRING                          HdrEnd;
   5762   EFI_STRING                          TmpPtr;
   5763   UINTN                               Length;
   5764   EFI_STRING                          GuidStr;
   5765   EFI_STRING                          NameStr;
   5766   EFI_STRING                          PathStr;
   5767   EFI_STRING                          AltIdStr;
   5768   EFI_STRING                          Result;
   5769   BOOLEAN                             GuidFlag;
   5770   BOOLEAN                             NameFlag;
   5771   BOOLEAN                             PathFlag;
   5772 
   5773   HdrStart = NULL;
   5774   HdrEnd   = NULL;
   5775   GuidStr  = NULL;
   5776   NameStr  = NULL;
   5777   PathStr  = NULL;
   5778   AltIdStr = NULL;
   5779   Result   = NULL;
   5780   GuidFlag = FALSE;
   5781   NameFlag = FALSE;
   5782   PathFlag = FALSE;
   5783 
   5784   if (This == NULL || Configuration == NULL || AltCfgResp == NULL) {
   5785     return EFI_INVALID_PARAMETER;
   5786   }
   5787 
   5788   StringPtr = Configuration;
   5789   if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {
   5790     return EFI_INVALID_PARAMETER;
   5791   }
   5792 
   5793   //
   5794   // Generate the sub string for later matching.
   5795   //
   5796   GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (VOID *) Guid, 1, &GuidStr);
   5797   GenerateSubStr (
   5798     L"PATH=",
   5799     GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) DevicePath),
   5800     (VOID *) DevicePath,
   5801     1,
   5802     &PathStr
   5803     );
   5804   if (AltCfgId != NULL) {
   5805     GenerateSubStr (L"ALTCFG=", sizeof (UINT16), (VOID *) AltCfgId, 3, &AltIdStr);
   5806   }
   5807   if (Name != NULL) {
   5808     GenerateSubStr (L"NAME=", StrLen (Name) * sizeof (CHAR16), (VOID *) Name, 2, &NameStr);
   5809   } else {
   5810     GenerateSubStr (L"NAME=", 0, NULL, 2, &NameStr);
   5811   }
   5812 
   5813   while (*StringPtr != 0) {
   5814     //
   5815     // Try to match the GUID
   5816     //
   5817     if (!GuidFlag) {
   5818       TmpPtr = StrStr (StringPtr, GuidStr);
   5819       if (TmpPtr == NULL) {
   5820         Status = EFI_NOT_FOUND;
   5821         goto Exit;
   5822       }
   5823       HdrStart = TmpPtr;
   5824 
   5825       //
   5826       // Jump to <NameHdr>
   5827       //
   5828       if (Guid != NULL) {
   5829         StringPtr = TmpPtr + StrLen (GuidStr);
   5830       } else {
   5831         StringPtr = StrStr (TmpPtr, L"NAME=");
   5832         if (StringPtr == NULL) {
   5833           Status = EFI_NOT_FOUND;
   5834           goto Exit;
   5835         }
   5836       }
   5837       GuidFlag = TRUE;
   5838     }
   5839 
   5840     //
   5841     // Try to match the NAME
   5842     //
   5843     if (GuidFlag && !NameFlag) {
   5844       if (StrnCmp (StringPtr, NameStr, StrLen (NameStr)) != 0) {
   5845         GuidFlag = FALSE;
   5846       } else {
   5847         //
   5848         // Jump to <PathHdr>
   5849         //
   5850         if (Name != NULL) {
   5851           StringPtr += StrLen (NameStr);
   5852         } else {
   5853           StringPtr = StrStr (StringPtr, L"PATH=");
   5854           if (StringPtr == NULL) {
   5855             Status = EFI_NOT_FOUND;
   5856             goto Exit;
   5857           }
   5858         }
   5859         NameFlag = TRUE;
   5860       }
   5861     }
   5862 
   5863     //
   5864     // Try to match the DevicePath
   5865     //
   5866     if (GuidFlag && NameFlag && !PathFlag) {
   5867       if (StrnCmp (StringPtr, PathStr, StrLen (PathStr)) != 0) {
   5868         GuidFlag = FALSE;
   5869         NameFlag = FALSE;
   5870       } else {
   5871         //
   5872         // Jump to '&' before <DescHdr> or <ConfigBody>
   5873         //
   5874         if (DevicePath != NULL) {
   5875           StringPtr += StrLen (PathStr);
   5876         } else {
   5877           StringPtr = StrStr (StringPtr, L"&");
   5878           if (StringPtr == NULL) {
   5879             Status = EFI_NOT_FOUND;
   5880             goto Exit;
   5881           }
   5882           StringPtr ++;
   5883         }
   5884         PathFlag = TRUE;
   5885         HdrEnd   = StringPtr;
   5886       }
   5887     }
   5888 
   5889     //
   5890     // Try to match the AltCfgId
   5891     //
   5892     if (GuidFlag && NameFlag && PathFlag) {
   5893       if (AltCfgId == NULL) {
   5894         //
   5895         // Return Current Setting when AltCfgId is NULL.
   5896         //
   5897         Status = OutputConfigBody (StringPtr, &Result);
   5898         goto Exit;
   5899       }
   5900       //
   5901       // Search the <ConfigAltResp> to get the <AltResp> with AltCfgId.
   5902       //
   5903       if (StrnCmp (StringPtr, AltIdStr, StrLen (AltIdStr)) != 0) {
   5904         GuidFlag = FALSE;
   5905         NameFlag = FALSE;
   5906         PathFlag = FALSE;
   5907       } else {
   5908         //
   5909         // Skip AltIdStr and &
   5910         //
   5911         StringPtr = StringPtr + StrLen (AltIdStr);
   5912         Status    = OutputConfigBody (StringPtr, &Result);
   5913         goto Exit;
   5914       }
   5915     }
   5916   }
   5917 
   5918   Status = EFI_NOT_FOUND;
   5919 
   5920 Exit:
   5921   *AltCfgResp = NULL;
   5922   if (!EFI_ERROR (Status) && (Result != NULL)) {
   5923     //
   5924     // Copy the <ConfigHdr> and <ConfigBody>
   5925     //
   5926     Length = HdrEnd - HdrStart + StrLen (Result) + 1;
   5927     *AltCfgResp = AllocateZeroPool (Length * sizeof (CHAR16));
   5928     if (*AltCfgResp == NULL) {
   5929       Status = EFI_OUT_OF_RESOURCES;
   5930     } else {
   5931       StrnCpyS (*AltCfgResp, Length, HdrStart, HdrEnd - HdrStart);
   5932       StrCatS (*AltCfgResp, Length, Result);
   5933       Status = EFI_SUCCESS;
   5934     }
   5935   }
   5936 
   5937   if (GuidStr != NULL) {
   5938     FreePool (GuidStr);
   5939   }
   5940   if (NameStr != NULL) {
   5941     FreePool (NameStr);
   5942   }
   5943   if (PathStr != NULL) {
   5944     FreePool (PathStr);
   5945   }
   5946   if (AltIdStr != NULL) {
   5947     FreePool (AltIdStr);
   5948   }
   5949   if (Result != NULL) {
   5950     FreePool (Result);
   5951   }
   5952 
   5953   return Status;
   5954 
   5955 }
   5956 
   5957 
   5958