2 Implementation of interfaces function for EFI_HII_CONFIG_ROUTING_PROTOCOL.
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
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.
16 #include "HiiDatabase.h"
17 extern HII_DATABASE_PRIVATE_DATA mPrivate
;
20 Calculate the number of Unicode characters of the incoming Configuration string,
21 not including NULL terminator.
23 This is a internal function.
25 @param String String in <MultiConfigRequest> or
26 <MultiConfigResp> format.
28 @return The number of Unicode characters.
32 CalculateConfigStringLen (
39 // "GUID=" should be the first element of incoming string.
41 ASSERT (String
!= NULL
);
42 ASSERT (StrnCmp (String
, L
"GUID=", StrLen (L
"GUID=")) == 0);
45 // The beginning of next <ConfigRequest>/<ConfigResp> should be "&GUID=".
46 // Will meet '\0' if there is only one <ConfigRequest>/<ConfigResp>.
48 TmpPtr
= StrStr (String
, L
"&GUID=");
50 return StrLen (String
);
53 return (TmpPtr
- String
);
58 Convert the hex UNICODE %02x encoding of a UEFI device path to binary
59 from <PathHdr> of <ConfigHdr>.
61 This is a internal function.
63 @param String UEFI configuration string
64 @param DevicePathData Binary of a UEFI device path.
66 @retval EFI_NOT_FOUND The device path is not invalid.
67 @retval EFI_INVALID_PARAMETER Any incoming parameter is invalid.
68 @retval EFI_OUT_OF_RESOURCES Lake of resources to store neccesary structures.
69 @retval EFI_SUCCESS The device path is retrieved and translated to
76 OUT UINT8
**DevicePathData
81 UINT8
*DevicePathBuffer
;
85 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
88 if (String
== NULL
|| DevicePathData
== NULL
) {
89 return EFI_INVALID_PARAMETER
;
93 // Find the 'PATH=' of <PathHdr> and skip it.
95 for (; (*String
!= 0 && StrnCmp (String
, L
"PATH=", StrLen (L
"PATH=")) != 0); String
++);
97 return EFI_INVALID_PARAMETER
;
100 // Check whether path data does exist.
102 String
+= StrLen (L
"PATH=");
104 return EFI_INVALID_PARAMETER
;
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.
113 for (Length
= 0; *String
!= 0 && *String
!= L
'&'; String
++, Length
++);
115 // Check DevicePath Length
117 if (((Length
+ 1) / 2) < sizeof (EFI_DEVICE_PATH_PROTOCOL
)) {
118 return EFI_NOT_FOUND
;
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.
126 DevicePathBuffer
= (UINT8
*) AllocateZeroPool ((Length
+ 1) / 2);
127 if (DevicePathBuffer
== NULL
) {
128 return EFI_OUT_OF_RESOURCES
;
132 // Convert DevicePath
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
;
141 DevicePathBuffer
[Index
/2] = (UINT8
) ((DevicePathBuffer
[Index
/2] << 4) + DigitUint8
);
146 // Validate DevicePath
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
))) {
152 // Invalid device path
154 FreePool (DevicePathBuffer
);
155 return EFI_NOT_FOUND
;
157 DevicePath
= NextDevicePathNode (DevicePath
);
161 // return the device path
163 *DevicePathData
= DevicePathBuffer
;
168 Converts the unicode character of the string from uppercase to lowercase.
169 This is a internal function.
171 @param ConfigString String to be converted
177 IN EFI_STRING ConfigString
183 ASSERT (ConfigString
!= NULL
);
186 // Convert all hex digits in range [A-F] in the configuration header to [a-f]
188 for (String
= ConfigString
, Lower
= FALSE
; *String
!= L
'\0'; String
++) {
189 if (*String
== L
'=') {
191 } else if (*String
== L
'&') {
193 } else if (Lower
&& *String
>= L
'A' && *String
<= L
'F') {
194 *String
= (CHAR16
) (*String
- L
'A' + L
'a');
202 Generate a sub string then output it.
204 This is a internal function.
206 @param String A constant string which is the prefix of the to be
207 generated string, e.g. GUID=
209 @param BufferLen The length of the Buffer in bytes.
211 @param Buffer Points to a buffer which will be converted to be the
212 content of the generated string.
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.
218 @param SubStr Points to the output string. It's caller's
219 responsibility to free this buffer.
225 IN CONST EFI_STRING String
,
229 OUT EFI_STRING
*SubStr
234 EFI_STRING StringHeader
;
240 ASSERT (String
!= NULL
&& SubStr
!= NULL
);
242 if (Buffer
== NULL
) {
243 *SubStr
= AllocateCopyPool (StrSize (String
), String
);
244 ASSERT (*SubStr
!= NULL
);
249 // Header + Data + '&' + '\0'
251 Length
= StrLen (String
) + BufferLen
* 2 + 1 + 1;
252 Str
= AllocateZeroPool (Length
* sizeof (CHAR16
));
253 ASSERT (Str
!= NULL
);
255 StrCpyS (Str
, Length
, String
);
257 StringHeader
= Str
+ StrLen (String
);
258 TemString
= (CHAR16
*) StringHeader
;
263 // Convert Buffer to Hex String in reverse order
265 TemBuffer
= ((UINT8
*) Buffer
);
266 for (Index
= 0; Index
< BufferLen
; Index
++, TemBuffer
++) {
267 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
272 // Check buffer is enough
274 TemName
= (CHAR16
*) Buffer
;
275 ASSERT ((BufferLen
* 2 + 1) >= (StrLen (TemName
) * 4 + 1));
277 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
279 for (; *TemName
!= L
'\0'; TemName
++) {
280 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemName
, 4);
285 // Convert Buffer to Hex String
287 TemBuffer
= ((UINT8
*) Buffer
) + BufferLen
- 1;
288 for (Index
= 0; Index
< BufferLen
; Index
++, TemBuffer
--) {
289 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
297 // Convert the uppercase to lowercase since <HexAf> is defined in lowercase format.
299 StrCatS (Str
, Length
, L
"&");
307 Retrieve the <ConfigBody> from String then output it.
309 This is a internal function.
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.
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.
323 IN EFI_STRING String
,
324 OUT EFI_STRING
*ConfigBody
331 if (String
== NULL
|| ConfigBody
== NULL
) {
332 return EFI_INVALID_PARAMETER
;
336 // The setting information should start OFFSET, not ALTCFG.
338 if (StrnCmp (String
, L
"&ALTCFG=", StrLen (L
"&ALTCFG=")) == 0) {
339 return EFI_INVALID_PARAMETER
;
342 TmpPtr
= StrStr (String
, L
"GUID=");
343 if (TmpPtr
== NULL
) {
345 // It is the last <ConfigResp> of the incoming configuration string.
347 Result
= AllocateCopyPool (StrSize (String
), String
);
348 if (Result
== NULL
) {
349 return EFI_OUT_OF_RESOURCES
;
351 *ConfigBody
= Result
;
356 Length
= TmpPtr
- String
;
358 return EFI_NOT_FOUND
;
360 Result
= AllocateCopyPool (Length
* sizeof (CHAR16
), String
);
361 if (Result
== NULL
) {
362 return EFI_OUT_OF_RESOURCES
;
365 *(Result
+ Length
- 1) = 0;
366 *ConfigBody
= Result
;
371 Append a string to a multi-string format.
373 This is a internal function.
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
380 @param AppendString NULL-terminated Unicode string.
382 @retval EFI_INVALID_PARAMETER Any incoming parameter is invalid.
383 @retval EFI_SUCCESS AppendString is append to the end of MultiString
387 AppendToMultiString (
388 IN OUT EFI_STRING
*MultiString
,
389 IN EFI_STRING AppendString
392 UINTN AppendStringSize
;
393 UINTN MultiStringSize
;
396 if (MultiString
== NULL
|| *MultiString
== NULL
|| AppendString
== NULL
) {
397 return EFI_INVALID_PARAMETER
;
400 AppendStringSize
= StrSize (AppendString
);
401 MultiStringSize
= StrSize (*MultiString
);
402 MaxLen
= MAX_STRING_LENGTH
/ sizeof (CHAR16
);
405 // Enlarge the buffer each time when length exceeds MAX_STRING_LENGTH.
407 if (MultiStringSize
+ AppendStringSize
> MAX_STRING_LENGTH
||
408 MultiStringSize
> MAX_STRING_LENGTH
) {
409 *MultiString
= (EFI_STRING
) ReallocatePool (
411 MultiStringSize
+ AppendStringSize
,
412 (VOID
*) (*MultiString
)
414 MaxLen
= (MultiStringSize
+ AppendStringSize
) / sizeof (CHAR16
);
415 ASSERT (*MultiString
!= NULL
);
418 // Append the incoming string
420 StrCatS (*MultiString
, MaxLen
, AppendString
);
427 Get the value of <Number> in <BlockConfig> format, i.e. the value of OFFSET
429 <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>
431 This is a internal function.
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
437 @param Len Length of the <Number>, in characters.
439 @retval EFI_OUT_OF_RESOURCES Insufficient resources to store neccessary
441 @retval EFI_SUCCESS Value of <Number> is outputted in Number
447 IN EFI_STRING StringPtr
,
461 if (StringPtr
== NULL
|| *StringPtr
== L
'\0' || Number
== NULL
|| Len
== NULL
) {
462 return EFI_INVALID_PARAMETER
;
468 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
471 *Len
= StringPtr
- TmpPtr
;
474 Str
= (EFI_STRING
) AllocateZeroPool (Length
* sizeof (CHAR16
));
476 Status
= EFI_OUT_OF_RESOURCES
;
479 CopyMem (Str
, TmpPtr
, *Len
* sizeof (CHAR16
));
480 *(Str
+ *Len
) = L
'\0';
482 Length
= (Length
+ 1) / 2;
483 Buf
= (UINT8
*) AllocateZeroPool (Length
);
485 Status
= EFI_OUT_OF_RESOURCES
;
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
;
497 Buf
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Buf
[Index
/2]);
502 Status
= EFI_SUCCESS
;
513 To find the BlockName in the string with same value.
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.
521 @retval EFI_OUT_OF_RESOURCES Insufficient resources to store neccessary structures.
522 @retval EFI_SUCCESS The function finishes successfully.
526 FindSameBlockElement(
527 IN EFI_STRING String
,
528 IN EFI_STRING BlockName
,
541 BlockPtr
= StrStr (String
, BlockName
);
543 while (BlockPtr
!= NULL
) {
544 BlockPtr
+= StrLen (BlockName
);
545 Status
= GetValueOfNumber (BlockPtr
, &TempBuffer
, &Length
);
546 if (EFI_ERROR (Status
)) {
549 ASSERT (TempBuffer
!= NULL
);
550 if ((BufferLen
== Length
) && (0 == CompareMem (Buffer
, TempBuffer
, Length
))) {
554 FreePool (TempBuffer
);
556 BlockPtr
= StrStr (BlockPtr
+ 1, BlockName
);
563 Compare the <AltResp> in ConfigAltResp and DefaultAltCfgResp, if the <AltResp>
564 in DefaultAltCfgResp but not in ConfigAltResp,add it to the ConfigAltResp.
566 @param DefaultAltCfgResp Pointer to a null-terminated Unicode string in
567 <MultiConfigAltResp> format. The default value
568 string may contain more than one ConfigAltResp
569 string for the different varstore buffer.
570 @param ConfigAltResp Pointer to a null-terminated Unicode string in
571 <ConfigAltResp> format.
572 @param AltConfigHdr Pointer to a Unicode string in <AltConfigHdr> format.
573 @param ConfigAltRespChanged Whether the ConfigAltResp has been changed.
575 @retval EFI_OUT_OF_RESOURCES Insufficient resources to store neccessary structures.
576 @retval EFI_SUCCESS The function finishes successfully.
580 CompareBlockElementDefault (
581 IN EFI_STRING DefaultAltCfgResp
,
582 IN OUT EFI_STRING
*ConfigAltResp
,
583 IN EFI_STRING AltConfigHdr
,
584 IN OUT BOOLEAN
*ConfigAltRespChanged
589 EFI_STRING BlockPtrStart
;
590 EFI_STRING StringPtr
;
591 EFI_STRING AppendString
;
592 EFI_STRING AltConfigHdrPtr
;
602 // Make BlockPtr point to the first <BlockConfig> with AltConfigHdr in DefaultAltCfgResp.
604 AltConfigHdrPtr
= StrStr (DefaultAltCfgResp
, AltConfigHdr
);
605 ASSERT (AltConfigHdrPtr
!= NULL
);
606 BlockPtr
= StrStr (AltConfigHdrPtr
, L
"&OFFSET=");
608 // Make StringPtr point to the AltConfigHdr in ConfigAltResp.
610 StringPtr
= StrStr (*ConfigAltResp
, AltConfigHdr
);
611 ASSERT (StringPtr
!= NULL
);
613 while (BlockPtr
!= NULL
) {
615 // Find the "&OFFSET=<Number>" block and get the value of the Number with AltConfigHdr in DefaultAltCfgResp.
617 BlockPtrStart
= BlockPtr
;
618 BlockPtr
+= StrLen (L
"&OFFSET=");
619 Status
= GetValueOfNumber (BlockPtr
, &TempBuffer
, &OffsetLength
);
620 if (EFI_ERROR (Status
)) {
621 Status
= EFI_OUT_OF_RESOURCES
;
625 // To find the same "&OFFSET=<Number>" block in ConfigAltResp.
627 Status
= FindSameBlockElement (StringPtr
, L
"&OFFSET=", TempBuffer
, &FoundOffset
, OffsetLength
);
628 if (TempBuffer
!= NULL
) {
629 FreePool (TempBuffer
);
632 if (EFI_ERROR (Status
)) {
633 Status
= EFI_OUT_OF_RESOURCES
;
638 // Don't find the same "&OFFSET=<Number>" block in ConfigAltResp.
639 // Calculate the size of <BlockConfig>.
640 // <BlockConfig>::='OFFSET='<Number>'&WIDTH='<Number>'&VALUE='<Number>.
642 BlockPtr
= StrStr (BlockPtr
+ 1, L
"&OFFSET=");
643 if (BlockPtr
!= NULL
) {
644 AppendSize
= (BlockPtr
- BlockPtrStart
) * sizeof (CHAR16
);
646 AppendSize
= StrSize (BlockPtrStart
);
649 // Copy the <BlockConfig> to AppendString.
651 if (AppendString
== NULL
) {
652 AppendString
= (EFI_STRING
) AllocateZeroPool (AppendSize
+ sizeof (CHAR16
));
653 StrnCatS (AppendString
, AppendSize
/ sizeof (CHAR16
) + 1, BlockPtrStart
, AppendSize
/ sizeof (CHAR16
));
655 TotalSize
= StrSize (AppendString
) + AppendSize
+ sizeof (CHAR16
);
656 AppendString
= (EFI_STRING
) ReallocatePool (
657 StrSize (AppendString
),
661 if (AppendString
== NULL
) {
662 Status
= EFI_OUT_OF_RESOURCES
;
665 StrnCatS (AppendString
, TotalSize
/ sizeof (CHAR16
), BlockPtrStart
, AppendSize
/ sizeof (CHAR16
));
669 // To find next "&OFFSET=<Number>" block with AltConfigHdr in DefaultAltCfgResp.
671 BlockPtr
= StrStr (BlockPtr
+ 1, L
"&OFFSET=");
675 if (AppendString
!= NULL
) {
677 // Reallocate ConfigAltResp to copy the AppendString.
679 TotalSize
= StrSize (*ConfigAltResp
) + StrSize (AppendString
) + sizeof (CHAR16
);
680 *ConfigAltResp
= (EFI_STRING
) ReallocatePool (
681 StrSize (*ConfigAltResp
),
685 if (*ConfigAltResp
== NULL
) {
686 Status
= EFI_OUT_OF_RESOURCES
;
689 StrCatS (*ConfigAltResp
, TotalSize
/ sizeof (CHAR16
), AppendString
);
690 *ConfigAltRespChanged
= TRUE
;
693 Status
= EFI_SUCCESS
;
696 if (AppendString
!= NULL
) {
697 FreePool (AppendString
);
704 Compare the <AltResp> in ConfigAltResp and DefaultAltCfgResp, if the <AltResp>
705 in DefaultAltCfgResp but not in ConfigAltResp,add it to the ConfigAltResp.
707 @param DefaultAltCfgResp Pointer to a null-terminated Unicode string in
708 <MultiConfigAltResp> format. The default value
709 string may contain more than one ConfigAltResp
710 string for the different varstore buffer.
711 @param ConfigAltResp Pointer to a null-terminated Unicode string in
712 <ConfigAltResp> format.
713 @param AltConfigHdr Pointer to a Unicode string in <AltConfigHdr> format.
714 @param ConfigAltRespChanged Whether the ConfigAltResp has been changed.
716 @retval EFI_OUT_OF_RESOURCES Insufficient resources to store neccessary structures.
717 @retval EFI_SUCCESS The function finishes successfully.
721 CompareNameElementDefault (
722 IN EFI_STRING DefaultAltCfgResp
,
723 IN OUT EFI_STRING
*ConfigAltResp
,
724 IN EFI_STRING AltConfigHdr
,
725 IN OUT BOOLEAN
*ConfigAltRespChanged
729 EFI_STRING NvConfigPtr
;
730 EFI_STRING NvConfigStart
;
731 EFI_STRING NvConfigValuePtr
;
732 EFI_STRING StringPtr
;
733 EFI_STRING NvConfigExist
;
734 EFI_STRING AppendString
;
740 NvConfigExist
= NULL
;
742 // Make NvConfigPtr point to the first <NvConfig> with AltConfigHdr in DefaultAltCfgResp.
744 NvConfigPtr
= StrStr (DefaultAltCfgResp
, AltConfigHdr
);
745 ASSERT (NvConfigPtr
!= NULL
);
746 NvConfigPtr
= StrStr (NvConfigPtr
+ StrLen(AltConfigHdr
),L
"&");
748 // Make StringPtr point to the first <NvConfig> with AltConfigHdr in ConfigAltResp.
750 StringPtr
= StrStr (*ConfigAltResp
, AltConfigHdr
);
751 ASSERT (StringPtr
!= NULL
);
752 StringPtr
= StrStr (StringPtr
+ StrLen (AltConfigHdr
), L
"&");
753 ASSERT (StringPtr
!= NULL
);
755 while (NvConfigPtr
!= NULL
) {
757 // <NvConfig> ::= <Label>'='<String> | <Label>'='<Number>.
758 // Get the <Label> with AltConfigHdr in DefaultAltCfgResp.
760 NvConfigStart
= NvConfigPtr
;
761 NvConfigValuePtr
= StrStr (NvConfigPtr
+ 1, L
"=");
762 ASSERT (NvConfigValuePtr
!= NULL
);
763 TempChar
= *NvConfigValuePtr
;
764 *NvConfigValuePtr
= L
'\0';
766 // Get the <Label> with AltConfigHdr in ConfigAltResp.
768 NvConfigExist
= StrStr (StringPtr
, NvConfigPtr
);
769 if (NvConfigExist
== NULL
) {
771 // Don't find same <Label> in ConfigAltResp.
772 // Calculate the size of <NvConfig>.
774 *NvConfigValuePtr
= TempChar
;
775 NvConfigPtr
= StrStr (NvConfigPtr
+ 1, L
"&");
776 if (NvConfigPtr
!= NULL
) {
777 AppendSize
= (NvConfigPtr
- NvConfigStart
) * sizeof (CHAR16
);
779 AppendSize
= StrSize (NvConfigStart
);
782 // Copy the <NvConfig> to AppendString.
784 if (AppendString
== NULL
) {
785 AppendString
= (EFI_STRING
) AllocateZeroPool (AppendSize
+ sizeof (CHAR16
));
786 StrnCatS (AppendString
, AppendSize
/ sizeof (CHAR16
) + 1, NvConfigStart
, AppendSize
/ sizeof (CHAR16
));
788 TotalSize
= StrSize (AppendString
) + AppendSize
+ sizeof (CHAR16
);
789 AppendString
= (EFI_STRING
) ReallocatePool (
790 StrSize (AppendString
),
794 if (AppendString
== NULL
) {
795 Status
= EFI_OUT_OF_RESOURCES
;
798 StrnCatS (AppendString
, TotalSize
/ sizeof (CHAR16
), NvConfigStart
, AppendSize
/ sizeof (CHAR16
));
802 // To find next <Label> in DefaultAltCfgResp.
804 *NvConfigValuePtr
= TempChar
;
805 NvConfigPtr
= StrStr (NvConfigPtr
+ 1, L
"&");
808 if (AppendString
!= NULL
) {
810 // Reallocate ConfigAltResp to copy the AppendString.
812 TotalSize
= StrSize (*ConfigAltResp
) + StrSize (AppendString
) + sizeof (CHAR16
);
813 *ConfigAltResp
= (EFI_STRING
) ReallocatePool (
814 StrSize (*ConfigAltResp
),
815 StrSize (*ConfigAltResp
) + StrSize (AppendString
) + sizeof (CHAR16
),
818 if (*ConfigAltResp
== NULL
) {
819 Status
= EFI_OUT_OF_RESOURCES
;
822 StrCatS (*ConfigAltResp
, TotalSize
/ sizeof (CHAR16
), AppendString
);
823 *ConfigAltRespChanged
= TRUE
;
825 Status
= EFI_SUCCESS
;
828 if (AppendString
!= NULL
) {
829 FreePool (AppendString
);
835 Compare the <AltResp> in AltCfgResp and DefaultAltCfgResp, if the <AltResp>
836 in DefaultAltCfgResp but not in AltCfgResp,add it to the AltCfgResp.
838 @param AltCfgResp Pointer to a null-terminated Unicode string in
839 <ConfigAltResp> format.
840 @param DefaultAltCfgResp Pointer to a null-terminated Unicode string in
841 <MultiConfigAltResp> format. The default value
842 string may contain more than one ConfigAltResp
843 string for the different varstore buffer.
844 @param AltConfigHdr Pointer to a Unicode string in <AltConfigHdr> format.
846 @retval EFI_OUT_OF_RESOURCES Insufficient resources to store neccessary
848 @retval EFI_SUCCESS The function finishes successfully.
852 CompareAndMergeDefaultString (
853 IN OUT EFI_STRING
*AltCfgResp
,
854 IN EFI_STRING DefaultAltCfgResp
,
855 IN EFI_STRING AltConfigHdr
859 EFI_STRING AltCfgRespBackup
;
860 EFI_STRING AltConfigHdrPtr
;
861 EFI_STRING AltConfigHdrPtrNext
;
862 EFI_STRING ConfigAltResp
;
863 EFI_STRING StringPtr
;
864 EFI_STRING StringPtrNext
;
866 UINTN ReallocateSize
;
869 BOOLEAN ConfigAltRespChanged
;
871 Status
= EFI_OUT_OF_RESOURCES
;
873 AltConfigHdrPtrNext
= NULL
;
874 StringPtrNext
= NULL
;
875 ConfigAltResp
= NULL
;
876 AltCfgRespBackup
= NULL
;
877 ConfigAltRespChanged
= FALSE
;
880 //To find the <AltResp> with AltConfigHdr in DefaultAltCfgResp, ignore other <AltResp> which follow it.
882 AltConfigHdrPtr
= StrStr (DefaultAltCfgResp
, AltConfigHdr
);
883 ASSERT (AltConfigHdrPtr
!= NULL
);
884 AltConfigHdrPtrNext
= StrStr (AltConfigHdrPtr
+ 1, L
"&GUID");
885 if (AltConfigHdrPtrNext
!= NULL
) {
886 TempChar
= *AltConfigHdrPtrNext
;
887 *AltConfigHdrPtrNext
= L
'\0';
890 // To find the <AltResp> with AltConfigHdr in AltCfgResp, ignore other <AltResp> which follow it.
892 StringPtr
= StrStr (*AltCfgResp
, AltConfigHdr
);
893 StringPtrNext
= StrStr (StringPtr
+ 1, L
"&GUID");
894 if (StringPtrNext
!= NULL
) {
895 TempCharA
= *StringPtrNext
;
896 *StringPtrNext
= L
'\0';
899 // Copy the content of <ConfigAltResp> which contain current AltConfigHdr in AltCfgResp.
901 ConfigAltResp
= AllocateCopyPool (StrSize (*AltCfgResp
), *AltCfgResp
);
902 if (ConfigAltResp
== NULL
) {
906 // To find the <ConfigBody> with AltConfigHdr in DefaultAltCfgResp.
908 BlockPtr
= StrStr (AltConfigHdrPtr
, L
"&OFFSET=");
909 if (BlockPtr
!= NULL
) {
911 // <BlockConfig>::='OFFSET='<Number>'&WIDTH='<Number>'&VALUE='<Number> style.
912 // Call function CompareBlockElementDefault to compare the <BlockConfig> in DefaultAltCfgResp and ConfigAltResp.
913 // The ConfigAltResp which may contain the new <BlockConfig> get from DefaultAltCfgResp.
915 Status
= CompareBlockElementDefault (DefaultAltCfgResp
, &ConfigAltResp
, AltConfigHdr
, &ConfigAltRespChanged
);
916 if (EFI_ERROR(Status
)) {
921 // <NvConfig> ::= <Label>'='<String> | <Label>'='<Number> style.
922 // Call function CompareNameElementDefault to compare the <NvConfig> in DefaultAltCfgResp and ConfigAltResp.
923 // The ConfigAltResp which may contain the new <NvConfig> get from DefaultAltCfgResp.
925 Status
= CompareNameElementDefault (DefaultAltCfgResp
, &ConfigAltResp
, AltConfigHdr
, &ConfigAltRespChanged
);
926 if (EFI_ERROR(Status
)) {
931 // Restore the AltCfgResp.
933 if (StringPtrNext
!= NULL
) {
934 *StringPtrNext
= TempCharA
;
938 // If the ConfigAltResp has no change,no need to update the content in AltCfgResp.
940 if (ConfigAltRespChanged
== FALSE
) {
941 Status
= EFI_SUCCESS
;
945 // ConfigAltResp has been changed, need to update the content in AltCfgResp.
947 if (StringPtrNext
!= NULL
) {
948 ReallocateSize
= StrSize (ConfigAltResp
) + StrSize (StringPtrNext
) + sizeof (CHAR16
);
950 ReallocateSize
= StrSize (ConfigAltResp
) + sizeof (CHAR16
);
953 AltCfgRespBackup
= (EFI_STRING
) AllocateZeroPool (ReallocateSize
);
954 if (AltCfgRespBackup
== NULL
) {
958 StrCatS (AltCfgRespBackup
, ReallocateSize
/ sizeof (CHAR16
), ConfigAltResp
);
959 if (StringPtrNext
!= NULL
) {
960 StrCatS (AltCfgRespBackup
, ReallocateSize
/ sizeof (CHAR16
), StringPtrNext
);
963 FreePool (*AltCfgResp
);
964 *AltCfgResp
= AltCfgRespBackup
;
966 Status
= EFI_SUCCESS
;
969 if (ConfigAltResp
!= NULL
) {
970 FreePool(ConfigAltResp
);
973 // Restore the DefaultAltCfgResp.
975 if ( AltConfigHdrPtrNext
!= NULL
) {
976 *AltConfigHdrPtrNext
= TempChar
;
977 AltConfigHdrPtrNext
= NULL
;
984 This function merges DefaultAltCfgResp string into AltCfgResp string for
985 the missing AltCfgId in AltCfgResq.
987 @param AltCfgResp Pointer to a null-terminated Unicode string in
988 <ConfigAltResp> format. The default value string
989 will be merged into it.
990 @param DefaultAltCfgResp Pointer to a null-terminated Unicode string in
991 <MultiConfigAltResp> format. The default value
992 string may contain more than one ConfigAltResp
993 string for the different varstore buffer.
995 @retval EFI_SUCCESS The merged string returns.
996 @retval EFI_INVALID_PARAMETER *AltCfgResp is to NULL.
1000 MergeDefaultString (
1001 IN OUT EFI_STRING
*AltCfgResp
,
1002 IN EFI_STRING DefaultAltCfgResp
1005 EFI_STRING StringPtrDefault
;
1006 EFI_STRING StringPtrEnd
;
1008 EFI_STRING StringPtr
;
1009 EFI_STRING AltConfigHdr
;
1011 UINTN SizeAltCfgResp
;
1015 if (*AltCfgResp
== NULL
) {
1016 return EFI_INVALID_PARAMETER
;
1020 // Get the requestr ConfigHdr
1023 StringPtr
= *AltCfgResp
;
1026 // Find <ConfigHdr> GUID=...&NAME=...&PATH=...
1028 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
1029 return EFI_INVALID_PARAMETER
;
1031 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&NAME=", StrLen (L
"&NAME=")) != 0) {
1034 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&PATH=", StrLen (L
"&PATH=")) != 0) {
1037 if (*StringPtr
== L
'\0') {
1038 return EFI_INVALID_PARAMETER
;
1040 StringPtr
+= StrLen (L
"&PATH=");
1041 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
1044 HeaderLength
= StringPtr
- *AltCfgResp
;
1047 // Construct AltConfigHdr string "&<ConfigHdr>&ALTCFG=XXXX\0"
1048 // |1| StrLen (ConfigHdr) | 8 | 4 | 1 |
1050 MaxLen
= 1 + HeaderLength
+ 8 + 4 + 1;
1051 AltConfigHdr
= AllocateZeroPool (MaxLen
* sizeof (CHAR16
));
1052 if (AltConfigHdr
== NULL
) {
1053 return EFI_OUT_OF_RESOURCES
;
1055 StrCpyS (AltConfigHdr
, MaxLen
, L
"&");
1056 StrnCatS (AltConfigHdr
, MaxLen
, *AltCfgResp
, HeaderLength
);
1057 StrCatS (AltConfigHdr
, MaxLen
, L
"&ALTCFG=");
1058 HeaderLength
= StrLen (AltConfigHdr
);
1060 StringPtrDefault
= StrStr (DefaultAltCfgResp
, AltConfigHdr
);
1061 while (StringPtrDefault
!= NULL
) {
1065 StrnCatS (AltConfigHdr
, MaxLen
, StringPtrDefault
+ HeaderLength
, 4);
1066 StringPtr
= StrStr (*AltCfgResp
, AltConfigHdr
);
1069 // Append the found default value string to the input AltCfgResp
1071 if (StringPtr
== NULL
) {
1072 StringPtrEnd
= StrStr (StringPtrDefault
+ 1, L
"&GUID");
1073 SizeAltCfgResp
= StrSize (*AltCfgResp
);
1074 if (StringPtrEnd
== NULL
) {
1076 // No more default string is found.
1078 TotalSize
= SizeAltCfgResp
+ StrSize (StringPtrDefault
);
1079 *AltCfgResp
= (EFI_STRING
) ReallocatePool (
1082 (VOID
*) (*AltCfgResp
)
1084 if (*AltCfgResp
== NULL
) {
1085 FreePool (AltConfigHdr
);
1086 return EFI_OUT_OF_RESOURCES
;
1088 StrCatS (*AltCfgResp
, TotalSize
/ sizeof (CHAR16
), StringPtrDefault
);
1091 TempChar
= *StringPtrEnd
;
1092 *StringPtrEnd
= L
'\0';
1093 TotalSize
= SizeAltCfgResp
+ StrSize (StringPtrDefault
);
1094 *AltCfgResp
= (EFI_STRING
) ReallocatePool (
1097 (VOID
*) (*AltCfgResp
)
1099 if (*AltCfgResp
== NULL
) {
1100 FreePool (AltConfigHdr
);
1101 return EFI_OUT_OF_RESOURCES
;
1103 StrCatS (*AltCfgResp
, TotalSize
/ sizeof (CHAR16
), StringPtrDefault
);
1104 *StringPtrEnd
= TempChar
;
1108 // The AltCfgResp contains <AltCfgResp>.
1109 // If the <ConfigElement> in <AltCfgResp> in the DefaultAltCfgResp but not in the
1110 // related <AltCfgResp> in AltCfgResp, merge it to AltCfgResp. else no need to merge.
1112 CompareAndMergeDefaultString (AltCfgResp
, DefaultAltCfgResp
, AltConfigHdr
);
1116 // Find next AltCfg String
1118 *(AltConfigHdr
+ HeaderLength
) = L
'\0';
1119 StringPtrDefault
= StrStr (StringPtrDefault
+ 1, AltConfigHdr
);
1122 FreePool (AltConfigHdr
);
1127 This function inserts new DefaultValueData into the BlockData DefaultValue array.
1129 @param BlockData The BlockData is updated to add new default value.
1130 @param DefaultValueData The DefaultValue is added.
1134 InsertDefaultValue (
1135 IN IFR_BLOCK_DATA
*BlockData
,
1136 IN IFR_DEFAULT_DATA
*DefaultValueData
1140 IFR_DEFAULT_DATA
*DefaultValueArray
;
1141 LIST_ENTRY
*DefaultLink
;
1143 DefaultLink
= &BlockData
->DefaultValueEntry
;
1145 for (Link
= DefaultLink
->ForwardLink
; Link
!= DefaultLink
; Link
= Link
->ForwardLink
) {
1146 DefaultValueArray
= BASE_CR (Link
, IFR_DEFAULT_DATA
, Entry
);
1147 if (DefaultValueArray
->DefaultId
== DefaultValueData
->DefaultId
) {
1149 // DEFAULT_VALUE_FROM_OPCODE has high priority, DEFAULT_VALUE_FROM_DEFAULT has low priority.
1151 if (DefaultValueData
->Type
> DefaultValueArray
->Type
) {
1153 // Update the default value array in BlockData.
1155 CopyMem (&DefaultValueArray
->Value
, &DefaultValueData
->Value
, sizeof (EFI_IFR_TYPE_VALUE
));
1156 DefaultValueArray
->Type
= DefaultValueData
->Type
;
1157 DefaultValueArray
->Cleaned
= DefaultValueData
->Cleaned
;
1164 // Insert new default value data in tail.
1166 DefaultValueArray
= AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
1167 ASSERT (DefaultValueArray
!= NULL
);
1168 CopyMem (DefaultValueArray
, DefaultValueData
, sizeof (IFR_DEFAULT_DATA
));
1169 InsertTailList (Link
, &DefaultValueArray
->Entry
);
1173 This function inserts new BlockData into the block link
1175 @param BlockLink The list entry points to block array.
1176 @param BlockData The point to BlockData is added.
1181 IN LIST_ENTRY
*BlockLink
,
1182 IN IFR_BLOCK_DATA
**BlockData
1186 IFR_BLOCK_DATA
*BlockArray
;
1187 IFR_BLOCK_DATA
*BlockSingleData
;
1189 BlockSingleData
= *BlockData
;
1191 if (BlockSingleData
->Name
!= NULL
) {
1192 InsertTailList (BlockLink
, &BlockSingleData
->Entry
);
1197 // Insert block data in its Offset and Width order.
1199 for (Link
= BlockLink
->ForwardLink
; Link
!= BlockLink
; Link
= Link
->ForwardLink
) {
1200 BlockArray
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
1201 if (BlockArray
->Offset
== BlockSingleData
->Offset
) {
1202 if (BlockArray
->Width
> BlockSingleData
->Width
) {
1204 // Insert this block data in the front of block array
1206 InsertTailList (Link
, &BlockSingleData
->Entry
);
1210 if (BlockArray
->Width
== BlockSingleData
->Width
) {
1212 // The same block array has been added.
1214 if (BlockSingleData
!= BlockArray
) {
1215 FreePool (BlockSingleData
);
1216 *BlockData
= BlockArray
;
1220 } else if (BlockArray
->Offset
> BlockSingleData
->Offset
) {
1222 // Insert new block data in the front of block array
1224 InsertTailList (Link
, &BlockSingleData
->Entry
);
1230 // Add new block data into the tail.
1232 InsertTailList (Link
, &BlockSingleData
->Entry
);
1236 Retrieves a pointer to the a Null-terminated ASCII string containing the list
1237 of languages that an HII handle in the HII Database supports. The returned
1238 string is allocated using AllocatePool(). The caller is responsible for freeing
1239 the returned string using FreePool(). The format of the returned string follows
1240 the language format assumed the HII Database.
1242 If HiiHandle is NULL, then ASSERT().
1244 @param[in] HiiHandle A handle that was previously registered in the HII Database.
1246 @retval NULL HiiHandle is not registered in the HII database
1247 @retval NULL There are not enough resources available to retrieve the suported
1249 @retval NULL The list of suported languages could not be retrieved.
1250 @retval Other A pointer to the Null-terminated ASCII string of supported languages.
1254 GetSupportedLanguages (
1255 IN EFI_HII_HANDLE HiiHandle
1260 CHAR8 TempSupportedLanguages
;
1261 CHAR8
*SupportedLanguages
;
1263 ASSERT (HiiHandle
!= NULL
);
1266 // Retrieve the size required for the supported languages buffer.
1269 Status
= mPrivate
.HiiString
.GetLanguages (&mPrivate
.HiiString
, HiiHandle
, &TempSupportedLanguages
, &LanguageSize
);
1272 // If GetLanguages() returns EFI_SUCCESS for a zero size,
1273 // then there are no supported languages registered for HiiHandle. If GetLanguages()
1274 // returns an error other than EFI_BUFFER_TOO_SMALL, then HiiHandle is not present
1275 // in the HII Database
1277 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
1279 // Return NULL if the size can not be retrieved, or if HiiHandle is not in the HII Database
1285 // Allocate the supported languages buffer.
1287 SupportedLanguages
= AllocateZeroPool (LanguageSize
);
1288 if (SupportedLanguages
== NULL
) {
1290 // Return NULL if allocation fails.
1296 // Retrieve the supported languages string
1298 Status
= mPrivate
.HiiString
.GetLanguages (&mPrivate
.HiiString
, HiiHandle
, SupportedLanguages
, &LanguageSize
);
1299 if (EFI_ERROR (Status
)) {
1301 // Free the buffer and return NULL if the supported languages can not be retrieved.
1303 FreePool (SupportedLanguages
);
1308 // Return the Null-terminated ASCII string of supported languages
1310 return SupportedLanguages
;
1314 Retrieves a string from a string package.
1316 If HiiHandle is NULL, then ASSERT().
1317 If StringId is 0, then ASSET.
1319 @param[in] HiiHandle A handle that was previously registered in the HII Database.
1320 @param[in] StringId The identifier of the string to retrieved from the string
1321 package associated with HiiHandle.
1323 @retval NULL The string specified by StringId is not present in the string package.
1324 @retval Other The string was returned.
1329 IN EFI_HII_HANDLE HiiHandle
,
1330 IN EFI_STRING_ID StringId
1337 CHAR8
*SupportedLanguages
;
1338 CHAR8
*PlatformLanguage
;
1339 CHAR8
*BestLanguage
;
1342 ASSERT (HiiHandle
!= NULL
);
1343 ASSERT (StringId
!= 0);
1346 // Initialize all allocated buffers to NULL
1348 SupportedLanguages
= NULL
;
1349 PlatformLanguage
= NULL
;
1350 BestLanguage
= NULL
;
1355 // Get the languages that the package specified by HiiHandle supports
1357 SupportedLanguages
= GetSupportedLanguages (HiiHandle
);
1358 if (SupportedLanguages
== NULL
) {
1363 // Get the current platform language setting
1365 GetEfiGlobalVariable2 (L
"PlatformLang", (VOID
**)&PlatformLanguage
, NULL
);
1368 // Get the best matching language from SupportedLanguages
1370 BestLanguage
= GetBestLanguage (
1372 FALSE
, // RFC 4646 mode
1373 Language
, // Highest priority
1374 PlatformLanguage
!= NULL
? PlatformLanguage
: "", // Next highest priority
1375 SupportedLanguages
, // Lowest priority
1378 if (BestLanguage
== NULL
) {
1383 // Retrieve the size of the string in the string package for the BestLanguage
1386 Status
= mPrivate
.HiiString
.GetString (
1387 &mPrivate
.HiiString
,
1396 // If GetString() returns EFI_SUCCESS for a zero size,
1397 // then there are no supported languages registered for HiiHandle. If GetString()
1398 // returns an error other than EFI_BUFFER_TOO_SMALL, then HiiHandle is not present
1399 // in the HII Database
1401 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
1406 // Allocate a buffer for the return string
1408 String
= AllocateZeroPool (StringSize
);
1409 if (String
== NULL
) {
1414 // Retrieve the string from the string package
1416 Status
= mPrivate
.HiiString
.GetString (
1417 &mPrivate
.HiiString
,
1425 if (EFI_ERROR (Status
)) {
1427 // Free the buffer and return NULL if the supported languages can not be retrieved.
1435 // Free allocated buffers
1437 if (SupportedLanguages
!= NULL
) {
1438 FreePool (SupportedLanguages
);
1440 if (PlatformLanguage
!= NULL
) {
1441 FreePool (PlatformLanguage
);
1443 if (BestLanguage
!= NULL
) {
1444 FreePool (BestLanguage
);
1448 // Return the Null-terminated Unicode string
1454 This function checks VarOffset and VarWidth is in the block range.
1456 @param RequestBlockArray The block array is to be checked.
1457 @param VarOffset Offset of var to the structure
1458 @param VarWidth Width of var.
1459 @param IsNameValueType Whether this varstore is name/value varstore or not.
1460 @param HiiHandle Hii handle for this hii package.
1462 @retval TRUE This Var is in the block range.
1463 @retval FALSE This Var is not in the block range.
1467 IN IFR_BLOCK_DATA
*RequestBlockArray
,
1468 IN UINT16 VarOffset
,
1470 IN BOOLEAN IsNameValueType
,
1471 IN EFI_HII_HANDLE HiiHandle
1475 IFR_BLOCK_DATA
*BlockData
;
1479 // No Request Block array, all vars are got.
1481 if (RequestBlockArray
== NULL
) {
1486 // Check the input var is in the request block range.
1488 for (Link
= RequestBlockArray
->Entry
.ForwardLink
; Link
!= &RequestBlockArray
->Entry
; Link
= Link
->ForwardLink
) {
1489 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
1491 if (IsNameValueType
) {
1492 Name
= InternalGetString (HiiHandle
, VarOffset
);
1493 ASSERT (Name
!= NULL
);
1495 if (StrnCmp (BlockData
->Name
, Name
, StrLen (Name
)) == 0) {
1501 if ((VarOffset
>= BlockData
->Offset
) && ((VarOffset
+ VarWidth
) <= (BlockData
->Offset
+ BlockData
->Width
))) {
1511 Get form package data from data base.
1513 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
1514 @param HiiFormPackage The buffer saves the package data.
1515 @param PackageSize The buffer size of the package data.
1519 GetFormPackageData (
1520 IN HII_DATABASE_RECORD
*DataBaseRecord
,
1521 IN OUT UINT8
**HiiFormPackage
,
1522 OUT UINTN
*PackageSize
1529 if (DataBaseRecord
== NULL
|| HiiFormPackage
== NULL
|| PackageSize
== NULL
) {
1530 return EFI_INVALID_PARAMETER
;
1536 // 0. Get Hii Form Package by HiiHandle
1538 Status
= ExportFormPackages (
1540 DataBaseRecord
->Handle
,
1541 DataBaseRecord
->PackageList
,
1547 if (EFI_ERROR (Status
)) {
1551 (*HiiFormPackage
) = AllocatePool (ResultSize
);
1552 if (*HiiFormPackage
== NULL
) {
1553 Status
= EFI_OUT_OF_RESOURCES
;
1558 // Get HiiFormPackage by HiiHandle
1562 Status
= ExportFormPackages (
1564 DataBaseRecord
->Handle
,
1565 DataBaseRecord
->PackageList
,
1571 if (EFI_ERROR (Status
)) {
1572 FreePool (*HiiFormPackage
);
1575 *PackageSize
= Size
;
1582 This function parses Form Package to get the efi varstore info according to the request ConfigHdr.
1584 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
1585 @param ConfigHdr Request string ConfigHdr. If it is NULL,
1586 the first found varstore will be as ConfigHdr.
1587 @param IsEfiVarstore Whether the request storage type is efi varstore type.
1588 @param EfiVarStore The efi varstore info which will return.
1592 IN HII_DATABASE_RECORD
*DataBaseRecord
,
1593 IN EFI_STRING ConfigHdr
,
1594 OUT BOOLEAN
*IsEfiVarstore
,
1595 OUT EFI_IFR_VARSTORE_EFI
**EfiVarStore
1600 UINTN PackageOffset
;
1601 EFI_IFR_OP_HEADER
*IfrOpHdr
;
1602 CHAR16
*VarStoreName
;
1607 UINT8
*HiiFormPackage
;
1609 EFI_IFR_VARSTORE_EFI
*IfrEfiVarStore
;
1610 EFI_HII_PACKAGE_HEADER
*PackageHeader
;
1612 HiiFormPackage
= NULL
;
1614 Status
= EFI_SUCCESS
;
1618 *IsEfiVarstore
= FALSE
;
1620 Status
= GetFormPackageData(DataBaseRecord
, &HiiFormPackage
, &PackageSize
);
1621 if (EFI_ERROR (Status
)) {
1625 IfrOffset
= sizeof (EFI_HII_PACKAGE_HEADER
);
1626 PackageOffset
= IfrOffset
;
1627 PackageHeader
= (EFI_HII_PACKAGE_HEADER
*) HiiFormPackage
;
1629 while (IfrOffset
< PackageSize
) {
1631 // More than one form packages exist.
1633 if (PackageOffset
>= PackageHeader
->Length
) {
1635 // Process the new form package.
1637 PackageOffset
= sizeof (EFI_HII_PACKAGE_HEADER
);
1638 IfrOffset
+= PackageOffset
;
1639 PackageHeader
= (EFI_HII_PACKAGE_HEADER
*) (HiiFormPackage
+ IfrOffset
);
1642 IfrOpHdr
= (EFI_IFR_OP_HEADER
*) (HiiFormPackage
+ IfrOffset
);
1643 IfrOffset
+= IfrOpHdr
->Length
;
1644 PackageOffset
+= IfrOpHdr
->Length
;
1646 if (IfrOpHdr
->OpCode
== EFI_IFR_VARSTORE_EFI_OP
) {
1647 IfrEfiVarStore
= (EFI_IFR_VARSTORE_EFI
*) IfrOpHdr
;
1649 // If the length is small than the structure, this is from old efi
1650 // varstore definition. Old efi varstore get config directly from
1651 // GetVariable function.
1653 if (IfrOpHdr
->Length
< sizeof (EFI_IFR_VARSTORE_EFI
)) {
1657 VarStoreName
= AllocateZeroPool (AsciiStrSize ((CHAR8
*)IfrEfiVarStore
->Name
) * sizeof (CHAR16
));
1658 if (VarStoreName
== NULL
) {
1659 Status
= EFI_OUT_OF_RESOURCES
;
1662 AsciiStrToUnicodeStr ((CHAR8
*) IfrEfiVarStore
->Name
, VarStoreName
);
1664 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*) &IfrEfiVarStore
->Guid
, 1, &GuidStr
);
1665 GenerateSubStr (L
"NAME=", StrLen (VarStoreName
) * sizeof (CHAR16
), (VOID
*) VarStoreName
, 2, &NameStr
);
1666 LengthString
= StrLen (GuidStr
);
1667 LengthString
= LengthString
+ StrLen (NameStr
) + 1;
1668 TempStr
= AllocateZeroPool (LengthString
* sizeof (CHAR16
));
1669 if (TempStr
== NULL
) {
1672 FreePool (VarStoreName
);
1673 Status
= EFI_OUT_OF_RESOURCES
;
1676 StrCpyS (TempStr
, LengthString
, GuidStr
);
1677 StrCatS (TempStr
, LengthString
, NameStr
);
1678 if (ConfigHdr
== NULL
|| StrnCmp (ConfigHdr
, TempStr
, StrLen (TempStr
)) == 0) {
1679 *EfiVarStore
= (EFI_IFR_VARSTORE_EFI
*) AllocateZeroPool (IfrOpHdr
->Length
);
1680 if (*EfiVarStore
== NULL
) {
1681 FreePool (VarStoreName
);
1685 Status
= EFI_OUT_OF_RESOURCES
;
1688 *IsEfiVarstore
= TRUE
;
1689 CopyMem (*EfiVarStore
, IfrEfiVarStore
, IfrOpHdr
->Length
);
1693 // Free alllocated temp string.
1695 FreePool (VarStoreName
);
1701 // Already found the varstore, break;
1703 if (*IsEfiVarstore
) {
1709 if (HiiFormPackage
!= NULL
) {
1710 FreePool (HiiFormPackage
);
1717 Check whether the ConfigRequest string has the request elements.
1718 For EFI_HII_VARSTORE_BUFFER type, the request has "&OFFSET=****&WIDTH=****..." format.
1719 For EFI_HII_VARSTORE_NAME_VALUE type, the request has "&NAME1**&NAME2..." format.
1721 @param ConfigRequest The input config request string.
1723 @retval TRUE The input include config request elements.
1724 @retval FALSE The input string not includes.
1728 GetElementsFromRequest (
1729 IN EFI_STRING ConfigRequest
1732 EFI_STRING TmpRequest
;
1734 TmpRequest
= StrStr (ConfigRequest
, L
"PATH=");
1735 ASSERT (TmpRequest
!= NULL
);
1737 if ((StrStr (TmpRequest
, L
"&OFFSET=") != NULL
) || (StrStr (TmpRequest
, L
"&") != NULL
)) {
1745 Check whether the this varstore is the request varstore.
1747 @param VarstoreGuid Varstore guid.
1748 @param Name Varstore name.
1749 @param ConfigHdr Current configRequest info.
1751 @retval TRUE This varstore is the requst one.
1752 @retval FALSE This varstore is not the requst one.
1757 IN EFI_GUID
*VarstoreGuid
,
1759 IN CHAR16
*ConfigHdr
1773 // If ConfigHdr has name field and varstore not has name, return FALSE.
1775 if (Name
== NULL
&& ConfigHdr
!= NULL
&& StrStr (ConfigHdr
, L
"NAME=&") == NULL
) {
1779 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*)VarstoreGuid
, 1, &GuidStr
);
1781 GenerateSubStr (L
"NAME=", StrLen (Name
) * sizeof (CHAR16
), (VOID
*) Name
, 2, &NameStr
);
1783 GenerateSubStr (L
"NAME=", 0, NULL
, 2, &NameStr
);
1785 LengthString
= StrLen (GuidStr
);
1786 LengthString
= LengthString
+ StrLen (NameStr
) + 1;
1787 TempStr
= AllocateZeroPool (LengthString
* sizeof (CHAR16
));
1788 if (TempStr
== NULL
) {
1792 StrCpyS (TempStr
, LengthString
, GuidStr
);
1793 StrCatS (TempStr
, LengthString
, NameStr
);
1795 if (ConfigHdr
== NULL
|| StrnCmp (ConfigHdr
, TempStr
, StrLen (TempStr
)) == 0) {
1800 if (GuidStr
!= NULL
) {
1804 if (NameStr
!= NULL
) {
1808 if (TempStr
!= NULL
) {
1816 This function parses Form Package to get the efi varstore info according to the request ConfigHdr.
1818 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
1819 @param ConfigHdr Request string ConfigHdr. If it is NULL,
1820 the first found varstore will be as ConfigHdr.
1821 @retval TRUE This hii package is the reqeust one.
1822 @retval FALSE This hii package is not the reqeust one.
1826 IN HII_DATABASE_RECORD
*DataBaseRecord
,
1827 IN EFI_STRING ConfigHdr
1832 UINTN PackageOffset
;
1833 EFI_IFR_OP_HEADER
*IfrOpHdr
;
1834 CHAR16
*VarStoreName
;
1835 UINT8
*HiiFormPackage
;
1837 EFI_IFR_VARSTORE_EFI
*IfrEfiVarStore
;
1838 EFI_HII_PACKAGE_HEADER
*PackageHeader
;
1839 EFI_IFR_VARSTORE
*IfrVarStore
;
1840 EFI_IFR_VARSTORE_NAME_VALUE
*IfrNameValueVarStore
;
1841 BOOLEAN FindVarstore
;
1843 HiiFormPackage
= NULL
;
1844 VarStoreName
= NULL
;
1845 Status
= EFI_SUCCESS
;
1846 FindVarstore
= FALSE
;
1848 Status
= GetFormPackageData(DataBaseRecord
, &HiiFormPackage
, &PackageSize
);
1849 if (EFI_ERROR (Status
)) {
1853 IfrOffset
= sizeof (EFI_HII_PACKAGE_HEADER
);
1854 PackageOffset
= IfrOffset
;
1855 PackageHeader
= (EFI_HII_PACKAGE_HEADER
*) HiiFormPackage
;
1857 while (IfrOffset
< PackageSize
) {
1859 // More than one form packages exist.
1861 if (PackageOffset
>= PackageHeader
->Length
) {
1863 // Process the new form package.
1865 PackageOffset
= sizeof (EFI_HII_PACKAGE_HEADER
);
1866 IfrOffset
+= PackageOffset
;
1867 PackageHeader
= (EFI_HII_PACKAGE_HEADER
*) (HiiFormPackage
+ IfrOffset
);
1870 IfrOpHdr
= (EFI_IFR_OP_HEADER
*) (HiiFormPackage
+ IfrOffset
);
1871 IfrOffset
+= IfrOpHdr
->Length
;
1872 PackageOffset
+= IfrOpHdr
->Length
;
1874 switch (IfrOpHdr
->OpCode
) {
1876 case EFI_IFR_VARSTORE_OP
:
1877 IfrVarStore
= (EFI_IFR_VARSTORE
*) IfrOpHdr
;
1879 VarStoreName
= AllocateZeroPool (AsciiStrSize ((CHAR8
*)IfrVarStore
->Name
) * sizeof (CHAR16
));
1880 if (VarStoreName
== NULL
) {
1883 AsciiStrToUnicodeStr ((CHAR8
*)IfrVarStore
->Name
, VarStoreName
);
1885 if (IsThisVarstore((VOID
*)&IfrVarStore
->Guid
, VarStoreName
, ConfigHdr
)) {
1886 FindVarstore
= TRUE
;
1891 case EFI_IFR_VARSTORE_EFI_OP
:
1892 IfrEfiVarStore
= (EFI_IFR_VARSTORE_EFI
*) IfrOpHdr
;
1893 VarStoreName
= AllocateZeroPool (AsciiStrSize ((CHAR8
*)IfrEfiVarStore
->Name
) * sizeof (CHAR16
));
1894 if (VarStoreName
== NULL
) {
1897 AsciiStrToUnicodeStr ((CHAR8
*)IfrEfiVarStore
->Name
, VarStoreName
);
1899 if (IsThisVarstore (&IfrEfiVarStore
->Guid
, VarStoreName
, ConfigHdr
)) {
1900 FindVarstore
= TRUE
;
1905 case EFI_IFR_VARSTORE_NAME_VALUE_OP
:
1906 IfrNameValueVarStore
= (EFI_IFR_VARSTORE_NAME_VALUE
*) IfrOpHdr
;
1908 if (IsThisVarstore (&IfrNameValueVarStore
->Guid
, NULL
, ConfigHdr
)) {
1909 FindVarstore
= TRUE
;
1914 case EFI_IFR_FORM_OP
:
1915 case EFI_IFR_FORM_MAP_OP
:
1917 // No matched varstore is found and directly return.
1926 if (HiiFormPackage
!= NULL
) {
1927 FreePool (HiiFormPackage
);
1930 if (VarStoreName
!= NULL
) {
1931 FreePool (VarStoreName
);
1934 return FindVarstore
;
1938 Check whether the this op code is required.
1940 @param RequestBlockArray The array includes all the request info or NULL.
1941 @param HiiHandle The hii handle for this form package.
1942 @param VarStorageData The varstore data strucure.
1943 @param IfrOpHdr Ifr opcode header for this opcode.
1944 @param VarWidth The buffer width for this opcode.
1945 @param ReturnData The data block added for this opcode.
1947 @retval EFI_SUCCESS This opcode is required.
1948 @retval EFI_NOT_FOUND This opcode is not required.
1949 @retval Others Contain some error.
1953 IsThisOpcodeRequired (
1954 IN IFR_BLOCK_DATA
*RequestBlockArray
,
1955 IN EFI_HII_HANDLE HiiHandle
,
1956 IN OUT IFR_VARSTORAGE_DATA
*VarStorageData
,
1957 IN EFI_IFR_OP_HEADER
*IfrOpHdr
,
1959 OUT IFR_BLOCK_DATA
**ReturnData
1962 IFR_BLOCK_DATA
*BlockData
;
1964 EFI_STRING_ID NameId
;
1965 EFI_IFR_QUESTION_HEADER
*IfrQuestionHdr
;
1969 IfrQuestionHdr
= (EFI_IFR_QUESTION_HEADER
*)((CHAR8
*) IfrOpHdr
+ sizeof (EFI_IFR_OP_HEADER
));
1971 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
1972 NameId
= IfrQuestionHdr
->VarStoreInfo
.VarName
;
1975 // Check whether this question is in requested block array.
1977 if (!BlockArrayCheck (RequestBlockArray
, NameId
, 0, TRUE
, HiiHandle
)) {
1979 // This question is not in the requested string. Skip it.
1981 return EFI_NOT_FOUND
;
1984 VarOffset
= IfrQuestionHdr
->VarStoreInfo
.VarOffset
;
1987 // Check whether this question is in requested block array.
1989 if (!BlockArrayCheck (RequestBlockArray
, VarOffset
, VarWidth
, FALSE
, HiiHandle
)) {
1991 // This question is not in the requested string. Skip it.
1993 return EFI_NOT_FOUND
;
1997 // Check this var question is in the var storage
1999 if (((VarOffset
+ VarWidth
) > VarStorageData
->Size
)) {
2000 return EFI_INVALID_PARAMETER
;
2004 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
2005 if (BlockData
== NULL
) {
2006 return EFI_OUT_OF_RESOURCES
;
2009 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2010 BlockData
->Name
= InternalGetString(HiiHandle
, NameId
);
2012 BlockData
->Offset
= VarOffset
;
2015 BlockData
->Width
= VarWidth
;
2016 BlockData
->QuestionId
= IfrQuestionHdr
->QuestionId
;
2017 BlockData
->OpCode
= IfrOpHdr
->OpCode
;
2018 BlockData
->Scope
= IfrOpHdr
->Scope
;
2019 InitializeListHead (&BlockData
->DefaultValueEntry
);
2021 // Add Block Data into VarStorageData BlockEntry
2023 InsertBlockData (&VarStorageData
->BlockEntry
, &BlockData
);
2024 *ReturnData
= BlockData
;
2030 This function parses Form Package to get the block array and the default
2031 value array according to the request ConfigHdr.
2033 @param HiiHandle Hii Handle for this hii package.
2034 @param Package Pointer to the form package data.
2035 @param PackageLength Length of the pacakge.
2036 @param ConfigHdr Request string ConfigHdr. If it is NULL,
2037 the first found varstore will be as ConfigHdr.
2038 @param RequestBlockArray The block array is retrieved from the request string.
2039 @param VarStorageData VarStorage structure contains the got block and default value.
2040 @param DefaultIdArray Point to the got default id and default name array.
2042 @retval EFI_SUCCESS The block array and the default value array are got.
2043 @retval EFI_INVALID_PARAMETER The varstore defintion in the differnt form pacakges
2045 @retval EFI_OUT_OF_RESOURCES No enough memory.
2050 IN EFI_HII_HANDLE HiiHandle
,
2052 IN UINT32 PackageLength
,
2053 IN EFI_STRING ConfigHdr
,
2054 IN IFR_BLOCK_DATA
*RequestBlockArray
,
2055 IN OUT IFR_VARSTORAGE_DATA
*VarStorageData
,
2056 OUT IFR_DEFAULT_DATA
*DefaultIdArray
2061 UINTN PackageOffset
;
2062 EFI_IFR_VARSTORE
*IfrVarStore
;
2063 EFI_IFR_VARSTORE_EFI
*IfrEfiVarStore
;
2064 EFI_IFR_OP_HEADER
*IfrOpHdr
;
2065 EFI_IFR_ONE_OF
*IfrOneOf
;
2066 EFI_IFR_REF4
*IfrRef
;
2067 EFI_IFR_ONE_OF_OPTION
*IfrOneOfOption
;
2068 EFI_IFR_DEFAULT
*IfrDefault
;
2069 EFI_IFR_ORDERED_LIST
*IfrOrderedList
;
2070 EFI_IFR_CHECKBOX
*IfrCheckBox
;
2071 EFI_IFR_PASSWORD
*IfrPassword
;
2072 EFI_IFR_STRING
*IfrString
;
2073 EFI_IFR_DATE
*IfrDate
;
2074 EFI_IFR_TIME
*IfrTime
;
2075 IFR_DEFAULT_DATA DefaultData
;
2076 IFR_DEFAULT_DATA
*DefaultDataPtr
;
2077 IFR_BLOCK_DATA
*BlockData
;
2078 CHAR16
*VarStoreName
;
2080 UINT16 VarDefaultId
;
2081 BOOLEAN FirstOneOfOption
;
2082 BOOLEAN FirstOrderedList
;
2083 LIST_ENTRY
*LinkData
;
2084 LIST_ENTRY
*LinkDefault
;
2085 EFI_IFR_VARSTORE_NAME_VALUE
*IfrNameValueVarStore
;
2086 EFI_HII_PACKAGE_HEADER
*PackageHeader
;
2087 EFI_VARSTORE_ID VarStoreId
;
2089 Status
= EFI_SUCCESS
;
2091 DefaultDataPtr
= NULL
;
2092 FirstOneOfOption
= FALSE
;
2094 FirstOrderedList
= FALSE
;
2095 ZeroMem (&DefaultData
, sizeof (IFR_DEFAULT_DATA
));
2098 // Go through the form package to parse OpCode one by one.
2100 PackageOffset
= sizeof (EFI_HII_PACKAGE_HEADER
);
2101 PackageHeader
= (EFI_HII_PACKAGE_HEADER
*) Package
;
2102 IfrOffset
= PackageOffset
;
2103 while (IfrOffset
< PackageLength
) {
2106 // More than one form package found.
2108 if (PackageOffset
>= PackageHeader
->Length
) {
2110 // Already found varstore for this request, break;
2112 if (VarStoreId
!= 0) {
2117 // Get next package header info.
2119 IfrOffset
+= sizeof (EFI_HII_PACKAGE_HEADER
);
2120 PackageOffset
= sizeof (EFI_HII_PACKAGE_HEADER
);
2121 PackageHeader
= (EFI_HII_PACKAGE_HEADER
*) (Package
+ IfrOffset
);
2124 IfrOpHdr
= (EFI_IFR_OP_HEADER
*) (Package
+ IfrOffset
);
2125 switch (IfrOpHdr
->OpCode
) {
2126 case EFI_IFR_VARSTORE_OP
:
2128 // VarStore is found. Don't need to search any more.
2130 if (VarStoreId
!= 0) {
2134 IfrVarStore
= (EFI_IFR_VARSTORE
*) IfrOpHdr
;
2136 VarStoreName
= AllocateZeroPool (AsciiStrSize ((CHAR8
*)IfrVarStore
->Name
) * sizeof (CHAR16
));
2137 if (VarStoreName
== NULL
) {
2138 Status
= EFI_OUT_OF_RESOURCES
;
2141 AsciiStrToUnicodeStr ((CHAR8
*)IfrVarStore
->Name
, VarStoreName
);
2143 if (IsThisVarstore((VOID
*)&IfrVarStore
->Guid
, VarStoreName
, ConfigHdr
)) {
2145 // Find the matched VarStore
2147 CopyGuid (&VarStorageData
->Guid
, (EFI_GUID
*) (VOID
*) &IfrVarStore
->Guid
);
2148 VarStorageData
->Size
= IfrVarStore
->Size
;
2149 VarStorageData
->Name
= VarStoreName
;
2150 VarStorageData
->Type
= EFI_HII_VARSTORE_BUFFER
;
2151 VarStoreId
= IfrVarStore
->VarStoreId
;
2155 case EFI_IFR_VARSTORE_EFI_OP
:
2157 // VarStore is found. Don't need to search any more.
2159 if (VarStoreId
!= 0) {
2163 IfrEfiVarStore
= (EFI_IFR_VARSTORE_EFI
*) IfrOpHdr
;
2166 // If the length is small than the structure, this is from old efi
2167 // varstore definition. Old efi varstore get config directly from
2168 // GetVariable function.
2170 if (IfrOpHdr
->Length
< sizeof (EFI_IFR_VARSTORE_EFI
)) {
2174 VarStoreName
= AllocateZeroPool (AsciiStrSize ((CHAR8
*)IfrEfiVarStore
->Name
) * sizeof (CHAR16
));
2175 if (VarStoreName
== NULL
) {
2176 Status
= EFI_OUT_OF_RESOURCES
;
2179 AsciiStrToUnicodeStr ((CHAR8
*)IfrEfiVarStore
->Name
, VarStoreName
);
2181 if (IsThisVarstore (&IfrEfiVarStore
->Guid
, VarStoreName
, ConfigHdr
)) {
2183 // Find the matched VarStore
2185 CopyGuid (&VarStorageData
->Guid
, (EFI_GUID
*) (VOID
*) &IfrEfiVarStore
->Guid
);
2186 VarStorageData
->Size
= IfrEfiVarStore
->Size
;
2187 VarStorageData
->Name
= VarStoreName
;
2188 VarStorageData
->Type
= EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
;
2189 VarStoreId
= IfrEfiVarStore
->VarStoreId
;
2193 case EFI_IFR_VARSTORE_NAME_VALUE_OP
:
2195 // VarStore is found. Don't need to search any more.
2197 if (VarStoreId
!= 0) {
2201 IfrNameValueVarStore
= (EFI_IFR_VARSTORE_NAME_VALUE
*) IfrOpHdr
;
2203 if (IsThisVarstore (&IfrNameValueVarStore
->Guid
, NULL
, ConfigHdr
)) {
2205 // Find the matched VarStore
2207 CopyGuid (&VarStorageData
->Guid
, (EFI_GUID
*) (VOID
*) &IfrNameValueVarStore
->Guid
);
2208 VarStorageData
->Type
= EFI_HII_VARSTORE_NAME_VALUE
;
2209 VarStoreId
= IfrNameValueVarStore
->VarStoreId
;
2213 case EFI_IFR_DEFAULTSTORE_OP
:
2215 // Add new the map between default id and default name.
2217 DefaultDataPtr
= (IFR_DEFAULT_DATA
*) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
2218 if (DefaultDataPtr
== NULL
) {
2219 Status
= EFI_OUT_OF_RESOURCES
;
2222 DefaultDataPtr
->DefaultId
= ((EFI_IFR_DEFAULTSTORE
*) IfrOpHdr
)->DefaultId
;
2223 InsertTailList (&DefaultIdArray
->Entry
, &DefaultDataPtr
->Entry
);
2224 DefaultDataPtr
= NULL
;
2227 case EFI_IFR_FORM_OP
:
2228 case EFI_IFR_FORM_MAP_OP
:
2230 // No matched varstore is found and directly return.
2232 if ( VarStoreId
== 0) {
2233 Status
= EFI_SUCCESS
;
2238 case EFI_IFR_REF_OP
:
2240 // Ref question is not in IFR Form. This IFR form is not valid.
2242 if ( VarStoreId
== 0) {
2243 Status
= EFI_INVALID_PARAMETER
;
2247 // Check whether this question is for the requested varstore.
2249 IfrRef
= (EFI_IFR_REF4
*) IfrOpHdr
;
2250 if (IfrRef
->Question
.VarStoreId
!= VarStoreId
) {
2253 VarWidth
= (UINT16
) (sizeof (EFI_HII_REF
));
2256 // The BlockData may allocate by other opcode,need to clean.
2258 if (BlockData
!= NULL
){
2262 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
2263 if (EFI_ERROR (Status
)) {
2264 if (Status
== EFI_NOT_FOUND
){
2266 //The opcode is not required,exit and parse other opcode.
2274 case EFI_IFR_ONE_OF_OP
:
2275 case EFI_IFR_NUMERIC_OP
:
2277 // Numeric and OneOf has the same opcode structure.
2281 // Numeric and OneOf question is not in IFR Form. This IFR form is not valid.
2283 if (VarStoreId
== 0) {
2284 Status
= EFI_INVALID_PARAMETER
;
2288 // Check whether this question is for the requested varstore.
2290 IfrOneOf
= (EFI_IFR_ONE_OF
*) IfrOpHdr
;
2291 if (IfrOneOf
->Question
.VarStoreId
!= VarStoreId
) {
2294 VarWidth
= (UINT16
) (1 << (IfrOneOf
->Flags
& EFI_IFR_NUMERIC_SIZE
));
2297 // The BlockData may allocate by other opcode,need to clean.
2299 if (BlockData
!= NULL
){
2303 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
2304 if (EFI_ERROR (Status
)) {
2305 if (Status
== EFI_NOT_FOUND
){
2307 //The opcode is not required,exit and parse other opcode.
2315 //when go to there,BlockData can't be NULLL.
2317 ASSERT (BlockData
!= NULL
);
2319 if (IfrOpHdr
->OpCode
== EFI_IFR_ONE_OF_OP
) {
2321 // Set this flag to TRUE for the first oneof option.
2323 FirstOneOfOption
= TRUE
;
2324 } else if (IfrOpHdr
->OpCode
== EFI_IFR_NUMERIC_OP
) {
2326 // Numeric minimum value will be used as default value when no default is specified.
2328 DefaultData
.Type
= DefaultValueFromDefault
;
2329 switch (IfrOneOf
->Flags
& EFI_IFR_NUMERIC_SIZE
) {
2330 case EFI_IFR_NUMERIC_SIZE_1
:
2331 DefaultData
.Value
.u8
= IfrOneOf
->data
.u8
.MinValue
;
2334 case EFI_IFR_NUMERIC_SIZE_2
:
2335 CopyMem (&DefaultData
.Value
.u16
, &IfrOneOf
->data
.u16
.MinValue
, sizeof (UINT16
));
2338 case EFI_IFR_NUMERIC_SIZE_4
:
2339 CopyMem (&DefaultData
.Value
.u32
, &IfrOneOf
->data
.u32
.MinValue
, sizeof (UINT32
));
2342 case EFI_IFR_NUMERIC_SIZE_8
:
2343 CopyMem (&DefaultData
.Value
.u64
, &IfrOneOf
->data
.u64
.MinValue
, sizeof (UINT64
));
2347 Status
= EFI_INVALID_PARAMETER
;
2351 // Set default value base on the DefaultId list get from IFR data.
2353 for (LinkData
= DefaultIdArray
->Entry
.ForwardLink
; LinkData
!= &DefaultIdArray
->Entry
; LinkData
= LinkData
->ForwardLink
) {
2354 DefaultDataPtr
= BASE_CR (LinkData
, IFR_DEFAULT_DATA
, Entry
);
2355 DefaultData
.DefaultId
= DefaultDataPtr
->DefaultId
;
2356 InsertDefaultValue (BlockData
, &DefaultData
);
2361 case EFI_IFR_ORDERED_LIST_OP
:
2363 // offset by question header
2364 // width by EFI_IFR_ORDERED_LIST MaxContainers * OneofOption Type
2367 FirstOrderedList
= TRUE
;
2369 // OrderedList question is not in IFR Form. This IFR form is not valid.
2371 if (VarStoreId
== 0) {
2372 Status
= EFI_INVALID_PARAMETER
;
2376 // Check whether this question is for the requested varstore.
2378 IfrOrderedList
= (EFI_IFR_ORDERED_LIST
*) IfrOpHdr
;
2379 if (IfrOrderedList
->Question
.VarStoreId
!= VarStoreId
) {
2383 VarWidth
= IfrOrderedList
->MaxContainers
;
2386 // The BlockData may allocate by other opcode,need to clean.
2388 if (BlockData
!= NULL
){
2392 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
2393 if (EFI_ERROR (Status
)) {
2394 if (Status
== EFI_NOT_FOUND
){
2396 //The opcode is not required,exit and parse other opcode.
2404 case EFI_IFR_CHECKBOX_OP
:
2406 // EFI_IFR_DEFAULT_OP
2407 // offset by question header
2408 // width is 1 sizeof (BOOLEAN)
2409 // default id by CheckBox Flags if CheckBox flags (Default or Mau) is set, the default value is 1 to be set.
2410 // value by DefaultOption
2411 // default id by DeaultOption DefaultId can override CheckBox Flags and Default value.
2415 // CheckBox question is not in IFR Form. This IFR form is not valid.
2417 if (VarStoreId
== 0) {
2418 Status
= EFI_INVALID_PARAMETER
;
2422 // Check whether this question is for the requested varstore.
2424 IfrCheckBox
= (EFI_IFR_CHECKBOX
*) IfrOpHdr
;
2425 if (IfrCheckBox
->Question
.VarStoreId
!= VarStoreId
) {
2428 VarWidth
= (UINT16
) sizeof (BOOLEAN
);
2431 // The BlockData may allocate by other opcode,need to clean.
2433 if (BlockData
!= NULL
){
2437 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
2438 if (EFI_ERROR (Status
)) {
2439 if (Status
== EFI_NOT_FOUND
){
2441 //The opcode is not required,exit and parse other opcode.
2449 //when go to there,BlockData can't be NULLL.
2451 ASSERT (BlockData
!= NULL
);
2454 // Add default value for standard ID by CheckBox Flag
2456 VarDefaultId
= EFI_HII_DEFAULT_CLASS_STANDARD
;
2458 // Prepare new DefaultValue
2460 DefaultData
.DefaultId
= VarDefaultId
;
2461 if ((IfrCheckBox
->Flags
& EFI_IFR_CHECKBOX_DEFAULT
) == EFI_IFR_CHECKBOX_DEFAULT
) {
2463 // When flag is set, defautl value is TRUE.
2465 DefaultData
.Type
= DefaultValueFromFlag
;
2466 DefaultData
.Value
.b
= TRUE
;
2469 // When flag is not set, defautl value is FASLE.
2471 DefaultData
.Type
= DefaultValueFromDefault
;
2472 DefaultData
.Value
.b
= FALSE
;
2475 // Add DefaultValue into current BlockData
2477 InsertDefaultValue (BlockData
, &DefaultData
);
2480 // Add default value for Manufacture ID by CheckBox Flag
2482 VarDefaultId
= EFI_HII_DEFAULT_CLASS_MANUFACTURING
;
2484 // Prepare new DefaultValue
2486 DefaultData
.DefaultId
= VarDefaultId
;
2487 if ((IfrCheckBox
->Flags
& EFI_IFR_CHECKBOX_DEFAULT_MFG
) == EFI_IFR_CHECKBOX_DEFAULT_MFG
) {
2489 // When flag is set, defautl value is TRUE.
2491 DefaultData
.Type
= DefaultValueFromFlag
;
2492 DefaultData
.Value
.b
= TRUE
;
2495 // When flag is not set, defautl value is FASLE.
2497 DefaultData
.Type
= DefaultValueFromDefault
;
2498 DefaultData
.Value
.b
= FALSE
;
2501 // Add DefaultValue into current BlockData
2503 InsertDefaultValue (BlockData
, &DefaultData
);
2506 case EFI_IFR_DATE_OP
:
2508 // offset by question header
2509 // width MaxSize * sizeof (CHAR16)
2510 // no default value, only block array
2514 // Date question is not in IFR Form. This IFR form is not valid.
2516 if (VarStoreId
== 0) {
2517 Status
= EFI_INVALID_PARAMETER
;
2521 // Check whether this question is for the requested varstore.
2523 IfrDate
= (EFI_IFR_DATE
*) IfrOpHdr
;
2524 if (IfrDate
->Question
.VarStoreId
!= VarStoreId
) {
2529 // The BlockData may allocate by other opcode,need to clean.
2531 if (BlockData
!= NULL
){
2535 VarWidth
= (UINT16
) sizeof (EFI_HII_DATE
);
2536 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
2537 if (EFI_ERROR (Status
)) {
2538 if (Status
== EFI_NOT_FOUND
){
2540 //The opcode is not required,exit and parse other opcode.
2548 case EFI_IFR_TIME_OP
:
2550 // offset by question header
2551 // width MaxSize * sizeof (CHAR16)
2552 // no default value, only block array
2556 // Time question is not in IFR Form. This IFR form is not valid.
2558 if (VarStoreId
== 0) {
2559 Status
= EFI_INVALID_PARAMETER
;
2563 // Check whether this question is for the requested varstore.
2565 IfrTime
= (EFI_IFR_TIME
*) IfrOpHdr
;
2566 if (IfrTime
->Question
.VarStoreId
!= VarStoreId
) {
2571 // The BlockData may allocate by other opcode,need to clean.
2573 if (BlockData
!= NULL
){
2577 VarWidth
= (UINT16
) sizeof (EFI_HII_TIME
);
2578 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
2579 if (EFI_ERROR (Status
)) {
2580 if (Status
== EFI_NOT_FOUND
){
2582 //The opcode is not required,exit and parse other opcode.
2590 case EFI_IFR_STRING_OP
:
2592 // offset by question header
2593 // width MaxSize * sizeof (CHAR16)
2594 // no default value, only block array
2598 // String question is not in IFR Form. This IFR form is not valid.
2600 if (VarStoreId
== 0) {
2601 Status
= EFI_INVALID_PARAMETER
;
2605 // Check whether this question is for the requested varstore.
2607 IfrString
= (EFI_IFR_STRING
*) IfrOpHdr
;
2608 if (IfrString
->Question
.VarStoreId
!= VarStoreId
) {
2613 // The BlockData may allocate by other opcode,need to clean.
2615 if (BlockData
!= NULL
){
2619 VarWidth
= (UINT16
) (IfrString
->MaxSize
* sizeof (UINT16
));
2620 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
2621 if (EFI_ERROR (Status
)) {
2622 if (Status
== EFI_NOT_FOUND
){
2624 //The opcode is not required,exit and parse other opcode.
2632 case EFI_IFR_PASSWORD_OP
:
2634 // offset by question header
2635 // width MaxSize * sizeof (CHAR16)
2636 // no default value, only block array
2640 // Password question is not in IFR Form. This IFR form is not valid.
2642 if (VarStoreId
== 0) {
2643 Status
= EFI_INVALID_PARAMETER
;
2647 // Check whether this question is for the requested varstore.
2649 IfrPassword
= (EFI_IFR_PASSWORD
*) IfrOpHdr
;
2650 if (IfrPassword
->Question
.VarStoreId
!= VarStoreId
) {
2655 // The BlockData may allocate by other opcode,need to clean.
2657 if (BlockData
!= NULL
){
2661 VarWidth
= (UINT16
) (IfrPassword
->MaxSize
* sizeof (UINT16
));
2662 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
2663 if (EFI_ERROR (Status
)) {
2664 if (Status
== EFI_NOT_FOUND
){
2666 //The opcode is not required,exit and parse other opcode.
2674 // No default value for string.
2679 case EFI_IFR_ONE_OF_OPTION_OP
:
2681 // No matched block data is ignored.
2683 if (BlockData
== NULL
|| BlockData
->Scope
== 0) {
2687 IfrOneOfOption
= (EFI_IFR_ONE_OF_OPTION
*) IfrOpHdr
;
2688 if (BlockData
->OpCode
== EFI_IFR_ORDERED_LIST_OP
) {
2690 if (!FirstOrderedList
){
2694 // Get ordered list option data type.
2696 if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_8
|| IfrOneOfOption
->Type
== EFI_IFR_TYPE_BOOLEAN
) {
2698 } else if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_16
) {
2700 } else if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_32
) {
2702 } else if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_64
) {
2706 // Invalid ordered list option data type.
2708 Status
= EFI_INVALID_PARAMETER
;
2709 if (BlockData
->Name
!= NULL
) {
2710 FreePool (BlockData
->Name
);
2712 FreePool (BlockData
);
2717 // Calculate Ordered list QuestionId width.
2719 BlockData
->Width
= (UINT16
) (BlockData
->Width
* VarWidth
);
2721 // Check whether this question is in requested block array.
2723 if (!BlockArrayCheck (RequestBlockArray
, BlockData
->Offset
, BlockData
->Width
, (BOOLEAN
)(BlockData
->Name
!= NULL
), HiiHandle
)) {
2725 // This question is not in the requested string. Skip it.
2727 if (BlockData
->Name
!= NULL
) {
2728 FreePool (BlockData
->Name
);
2730 FreePool (BlockData
);
2735 // Check this var question is in the var storage
2737 if ((BlockData
->Name
== NULL
) && ((BlockData
->Offset
+ BlockData
->Width
) > VarStorageData
->Size
)) {
2738 Status
= EFI_INVALID_PARAMETER
;
2739 if (BlockData
->Name
!= NULL
) {
2740 FreePool (BlockData
->Name
);
2742 FreePool (BlockData
);
2746 // Add Block Data into VarStorageData BlockEntry
2748 InsertBlockData (&VarStorageData
->BlockEntry
, &BlockData
);
2750 FirstOrderedList
= FALSE
;
2756 // 1. Set default value for OneOf option when flag field has default attribute.
2758 if (((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT
) == EFI_IFR_OPTION_DEFAULT
) ||
2759 ((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT_MFG
) == EFI_IFR_OPTION_DEFAULT_MFG
)) {
2761 // This flag is used to specify whether this option is the first. Set it to FALSE for the following options.
2762 // The first oneof option value will be used as default value when no default value is specified.
2764 FirstOneOfOption
= FALSE
;
2766 // Prepare new DefaultValue
2768 DefaultData
.Type
= DefaultValueFromFlag
;
2769 CopyMem (&DefaultData
.Value
, &IfrOneOfOption
->Value
, IfrOneOfOption
->Header
.Length
- OFFSET_OF (EFI_IFR_ONE_OF_OPTION
, Value
));
2770 if ((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT
) == EFI_IFR_OPTION_DEFAULT
) {
2771 DefaultData
.DefaultId
= EFI_HII_DEFAULT_CLASS_STANDARD
;
2772 InsertDefaultValue (BlockData
, &DefaultData
);
2774 if ((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT_MFG
) == EFI_IFR_OPTION_DEFAULT_MFG
) {
2775 DefaultData
.DefaultId
= EFI_HII_DEFAULT_CLASS_MANUFACTURING
;
2776 InsertDefaultValue (BlockData
, &DefaultData
);
2781 // 2. Set as the default value when this is the first option.
2782 // The first oneof option value will be used as default value when no default value is specified.
2784 if (FirstOneOfOption
) {
2785 // This flag is used to specify whether this option is the first. Set it to FALSE for the following options.
2786 FirstOneOfOption
= FALSE
;
2789 // Prepare new DefaultValue
2791 DefaultData
.Type
= DefaultValueFromDefault
;
2792 CopyMem (&DefaultData
.Value
, &IfrOneOfOption
->Value
, IfrOneOfOption
->Header
.Length
- OFFSET_OF (EFI_IFR_ONE_OF_OPTION
, Value
));
2793 for (LinkData
= DefaultIdArray
->Entry
.ForwardLink
; LinkData
!= &DefaultIdArray
->Entry
; LinkData
= LinkData
->ForwardLink
) {
2794 DefaultDataPtr
= BASE_CR (LinkData
, IFR_DEFAULT_DATA
, Entry
);
2795 DefaultData
.DefaultId
= DefaultDataPtr
->DefaultId
;
2796 InsertDefaultValue (BlockData
, &DefaultData
);
2801 case EFI_IFR_DEFAULT_OP
:
2803 // Update Current BlockData to the default value.
2805 if (BlockData
== NULL
|| BlockData
->Scope
== 0) {
2807 // No matched block data is ignored.
2813 // Get the DefaultId
2815 IfrDefault
= (EFI_IFR_DEFAULT
*) IfrOpHdr
;
2816 VarDefaultId
= IfrDefault
->DefaultId
;
2818 // Prepare new DefaultValue
2820 DefaultData
.Type
= DefaultValueFromOpcode
;
2821 DefaultData
.DefaultId
= VarDefaultId
;
2822 CopyMem (&DefaultData
.Value
, &IfrDefault
->Value
, IfrDefault
->Header
.Length
- OFFSET_OF (EFI_IFR_DEFAULT
, Value
));
2824 // If the value field is expression, set the cleaned flag.
2825 if (IfrDefault
->Type
== EFI_IFR_TYPE_OTHER
) {
2826 DefaultData
.Cleaned
= TRUE
;
2829 // Add DefaultValue into current BlockData
2831 InsertDefaultValue (BlockData
, &DefaultData
);
2834 // After insert the default value, reset the cleaned value for next
2835 // time used. If not set here, need to set the value before everytime
2838 DefaultData
.Cleaned
= FALSE
;
2841 case EFI_IFR_END_OP
:
2843 // End Opcode is for Var question.
2845 if (BlockData
!= NULL
) {
2846 if (BlockData
->Scope
> 0) {
2849 if (BlockData
->Scope
== 0) {
2857 if (BlockData
!= NULL
) {
2858 if (BlockData
->Scope
> 0) {
2859 BlockData
->Scope
= (UINT8
) (BlockData
->Scope
+ IfrOpHdr
->Scope
);
2862 if (BlockData
->Scope
== 0) {
2869 IfrOffset
+= IfrOpHdr
->Length
;
2870 PackageOffset
+= IfrOpHdr
->Length
;
2874 //if Status == EFI_NOT_FOUND, just means the opcode is not required,not contain any error,
2875 //so set the Status to EFI_SUCCESS.
2877 if (Status
== EFI_NOT_FOUND
){
2878 Status
= EFI_SUCCESS
;
2882 for (LinkData
= VarStorageData
->BlockEntry
.ForwardLink
; LinkData
!= &VarStorageData
->BlockEntry
; LinkData
= LinkData
->ForwardLink
) {
2883 BlockData
= BASE_CR (LinkData
, IFR_BLOCK_DATA
, Entry
);
2884 for (LinkDefault
= BlockData
->DefaultValueEntry
.ForwardLink
; LinkDefault
!= &BlockData
->DefaultValueEntry
; ) {
2885 DefaultDataPtr
= BASE_CR (LinkDefault
, IFR_DEFAULT_DATA
, Entry
);
2886 LinkDefault
= LinkDefault
->ForwardLink
;
2887 if (DefaultDataPtr
->Cleaned
== TRUE
) {
2888 RemoveEntryList (&DefaultDataPtr
->Entry
);
2889 FreePool (DefaultDataPtr
);
2898 parse the configrequest string, get the elements.
2900 @param ConfigRequest The input configrequest string.
2901 @param Progress Return the progress data.
2903 @retval Block data pointer.
2907 IN EFI_STRING ConfigRequest
,
2908 OUT EFI_STRING
*Progress
2911 EFI_STRING StringPtr
;
2912 IFR_BLOCK_DATA
*BlockData
;
2913 IFR_BLOCK_DATA
*RequestBlockArray
;
2919 IFR_BLOCK_DATA
*NextBlockData
;
2925 // Init RequestBlockArray
2927 RequestBlockArray
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
2928 if (RequestBlockArray
== NULL
) {
2931 InitializeListHead (&RequestBlockArray
->Entry
);
2934 // Get the request Block array from the request string
2939 // Parse each <RequestElement> if exists
2940 // Only <BlockName> format is supported by this help function.
2941 // <BlockName> ::= &'OFFSET='<Number>&'WIDTH='<Number>
2943 StringPtr
= ConfigRequest
;
2944 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) == 0) {
2946 // Skip the OFFSET string
2948 *Progress
= StringPtr
;
2949 StringPtr
+= StrLen (L
"&OFFSET=");
2953 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
2954 if (EFI_ERROR (Status
)) {
2961 (((Length
+ 1) / 2) < sizeof (UINT16
)) ? ((Length
+ 1) / 2) : sizeof (UINT16
)
2963 FreePool (TmpBuffer
);
2965 StringPtr
+= Length
;
2966 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
2969 StringPtr
+= StrLen (L
"&WIDTH=");
2974 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
2975 if (EFI_ERROR (Status
)) {
2982 (((Length
+ 1) / 2) < sizeof (UINT16
)) ? ((Length
+ 1) / 2) : sizeof (UINT16
)
2984 FreePool (TmpBuffer
);
2986 StringPtr
+= Length
;
2987 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
2994 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
2995 if (BlockData
== NULL
) {
2998 BlockData
->Offset
= Offset
;
2999 BlockData
->Width
= Width
;
3000 InsertBlockData (&RequestBlockArray
->Entry
, &BlockData
);
3003 // Skip &VALUE string if &VALUE does exists.
3005 if (StrnCmp (StringPtr
, L
"&VALUE=", StrLen (L
"&VALUE=")) == 0) {
3006 StringPtr
+= StrLen (L
"&VALUE=");
3011 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
3012 if (EFI_ERROR (Status
)) {
3016 StringPtr
+= Length
;
3017 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
3022 // If '\0', parsing is finished.
3024 if (*StringPtr
== 0) {
3030 // Merge the requested block data.
3032 Link
= RequestBlockArray
->Entry
.ForwardLink
;
3033 while ((Link
!= &RequestBlockArray
->Entry
) && (Link
->ForwardLink
!= &RequestBlockArray
->Entry
)) {
3034 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
3035 NextBlockData
= BASE_CR (Link
->ForwardLink
, IFR_BLOCK_DATA
, Entry
);
3036 if ((NextBlockData
->Offset
>= BlockData
->Offset
) && (NextBlockData
->Offset
<= (BlockData
->Offset
+ BlockData
->Width
))) {
3037 if ((NextBlockData
->Offset
+ NextBlockData
->Width
) > (BlockData
->Offset
+ BlockData
->Width
)) {
3038 BlockData
->Width
= (UINT16
) (NextBlockData
->Offset
+ NextBlockData
->Width
- BlockData
->Offset
);
3040 RemoveEntryList (Link
->ForwardLink
);
3041 FreePool (NextBlockData
);
3044 Link
= Link
->ForwardLink
;
3047 return RequestBlockArray
;
3050 if (RequestBlockArray
!= NULL
) {
3052 // Free Link Array RequestBlockArray
3054 while (!IsListEmpty (&RequestBlockArray
->Entry
)) {
3055 BlockData
= BASE_CR (RequestBlockArray
->Entry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
3056 RemoveEntryList (&BlockData
->Entry
);
3057 FreePool (BlockData
);
3060 FreePool (RequestBlockArray
);
3067 parse the configrequest string, get the elements.
3069 @param ConfigRequest The input config request string.
3070 @param Progress Return the progress data.
3072 @retval return data block array.
3076 IN EFI_STRING ConfigRequest
,
3077 OUT EFI_STRING
*Progress
3080 EFI_STRING StringPtr
;
3082 IFR_BLOCK_DATA
*BlockData
;
3083 IFR_BLOCK_DATA
*RequestBlockArray
;
3086 StringPtr
= ConfigRequest
;
3089 // Init RequestBlockArray
3091 RequestBlockArray
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
3092 if (RequestBlockArray
== NULL
) {
3095 InitializeListHead (&RequestBlockArray
->Entry
);
3098 // Get the request Block array from the request string
3102 // Parse each <RequestElement> if exists
3103 // Only <BlockName> format is supported by this help function.
3104 // <BlockName> ::= &'Name***=***
3106 while (StringPtr
!= NULL
&& *StringPtr
== L
'&') {
3108 *Progress
= StringPtr
;
3110 // Skip the L"&" string
3115 if ((NextTag
= StrStr (StringPtr
, L
"=")) != NULL
) {
3118 } else if ((NextTag
= StrStr (StringPtr
, L
"&")) != NULL
) {
3125 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
3126 if (BlockData
== NULL
) {
3133 BlockData
->Name
= AllocateCopyPool(StrSize (StringPtr
), StringPtr
);
3134 InsertBlockData (&RequestBlockArray
->Entry
, &BlockData
);
3138 // If has value, skip the value.
3140 StringPtr
= NextTag
+ 1;
3142 StringPtr
= StrStr (StringPtr
, L
"&");
3143 } else if (NextTag
!= NULL
) {
3145 // restore the '&' text.
3147 StringPtr
= NextTag
;
3152 return RequestBlockArray
;
3155 if (RequestBlockArray
!= NULL
) {
3157 // Free Link Array RequestBlockArray
3159 while (!IsListEmpty (&RequestBlockArray
->Entry
)) {
3160 BlockData
= BASE_CR (RequestBlockArray
->Entry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
3161 RemoveEntryList (&BlockData
->Entry
);
3162 if (BlockData
->Name
!= NULL
) {
3163 FreePool (BlockData
->Name
);
3165 FreePool (BlockData
);
3168 FreePool (RequestBlockArray
);
3175 Generate ConfigRequest string base on the varstore info.
3177 @param ConfigHdr The config header for this varstore.
3178 @param VarStorageData The varstore info.
3179 @param Status Return Status.
3180 @param ConfigRequest The ConfigRequest info may be return.
3182 @retval TRUE Need to continue
3183 @retval Others NO need to continue or error occur.
3186 GenerateConfigRequest (
3187 IN CHAR16
*ConfigHdr
,
3188 IN IFR_VARSTORAGE_DATA
*VarStorageData
,
3189 OUT EFI_STATUS
*Status
,
3190 IN OUT EFI_STRING
*ConfigRequest
3196 CHAR16
*FullConfigRequest
;
3198 IFR_BLOCK_DATA
*BlockData
;
3201 // Append VarStorageData BlockEntry into *Request string
3202 // Now support only one varstore in a form package.
3206 // Go through all VarStorageData Entry and get BlockEntry for each one for the multiple varstore in a single form package
3207 // Then construct them all to return MultiRequest string : ConfigHdr BlockConfig
3211 // Compute the length of the entire request starting with <ConfigHdr> and a
3215 Length
= StrLen (ConfigHdr
) + 1;
3217 for (Link
= VarStorageData
->BlockEntry
.ForwardLink
; Link
!= &VarStorageData
->BlockEntry
; Link
= Link
->ForwardLink
) {
3219 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
3220 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3222 // Add <BlockName> length for each Name
3224 // <BlockName> ::= &Name1&Name2&...
3225 // |1| StrLen(Name1)
3227 Length
= Length
+ (1 + StrLen (BlockData
->Name
));
3230 // Add <BlockName> length for each Offset/Width pair
3232 // <BlockName> ::= &OFFSET=1234&WIDTH=1234
3233 // | 8 | 4 | 7 | 4 |
3235 Length
= Length
+ (8 + 4 + 7 + 4);
3239 // No any request block data is found. The request string can't be constructed.
3242 *Status
= EFI_SUCCESS
;
3247 // Allocate buffer for the entire <ConfigRequest>
3249 FullConfigRequest
= AllocateZeroPool (Length
* sizeof (CHAR16
));
3250 if (FullConfigRequest
== NULL
) {
3251 *Status
= EFI_OUT_OF_RESOURCES
;
3254 StringPtr
= FullConfigRequest
;
3257 // Start with <ConfigHdr>
3259 StrCpyS (StringPtr
, Length
, ConfigHdr
);
3260 StringPtr
+= StrLen (StringPtr
);
3263 // Loop through all the Offset/Width pairs and append them to ConfigRequest
3265 for (Link
= VarStorageData
->BlockEntry
.ForwardLink
; Link
!= &VarStorageData
->BlockEntry
; Link
= Link
->ForwardLink
) {
3266 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
3267 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3273 (1 + StrLen (BlockData
->Name
) + 1) * sizeof (CHAR16
),
3279 // Append &OFFSET=XXXX&WIDTH=YYYY\0
3283 (8 + 4 + 7 + 4 + 1) * sizeof (CHAR16
),
3284 L
"&OFFSET=%04X&WIDTH=%04X",
3289 StringPtr
+= StrLen (StringPtr
);
3292 // Set to the got full request string.
3294 HiiToLower (FullConfigRequest
);
3296 if (*ConfigRequest
!= NULL
) {
3297 FreePool (*ConfigRequest
);
3299 *ConfigRequest
= FullConfigRequest
;
3305 Generate ConfigRequest Header base on the varstore info.
3307 @param VarStorageData The varstore info.
3308 @param DevicePath Device path for this varstore.
3309 @param ConfigHdr The config header for this varstore.
3311 @retval EFI_SUCCESS Generate the header success.
3312 @retval EFI_OUT_OF_RESOURCES Allocate buffer fail.
3316 IN IFR_VARSTORAGE_DATA
*VarStorageData
,
3317 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
3318 OUT EFI_STRING
*ConfigHdr
3327 Status
= EFI_SUCCESS
;
3333 // Construct <ConfigHdr> : "GUID=...&NAME=...&PATH=..." by VarStorageData Guid, Name and DriverHandle
3335 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*) &VarStorageData
->Guid
, 1, &GuidStr
);
3336 if (VarStorageData
->Name
!= NULL
) {
3337 GenerateSubStr (L
"NAME=", StrLen (VarStorageData
->Name
) * sizeof (CHAR16
), (VOID
*) VarStorageData
->Name
, 2, &NameStr
);
3339 GenerateSubStr (L
"NAME=", 0, NULL
, 2, &NameStr
);
3343 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) DevicePath
),
3344 (VOID
*) DevicePath
,
3348 Length
= StrLen (GuidStr
) + StrLen (NameStr
) + StrLen (PathStr
) + 1;
3349 if (VarStorageData
->Name
== NULL
) {
3353 *ConfigHdr
= AllocateZeroPool (Length
* sizeof (CHAR16
));
3354 if (*ConfigHdr
== NULL
) {
3355 Status
= EFI_OUT_OF_RESOURCES
;
3358 StrCpyS (*ConfigHdr
, Length
, GuidStr
);
3359 StrCatS (*ConfigHdr
, Length
, NameStr
);
3360 if (VarStorageData
->Name
== NULL
) {
3361 StrCatS (*ConfigHdr
, Length
, L
"&");
3363 StrCatS (*ConfigHdr
, Length
, PathStr
);
3366 // Remove the last character L'&'
3368 *(*ConfigHdr
+ StrLen (*ConfigHdr
) - 1) = L
'\0';
3371 if (GuidStr
!= NULL
) {
3375 if (NameStr
!= NULL
) {
3379 if (PathStr
!= NULL
) {
3387 Get Data buffer size based on data type.
3389 @param ValueType The input data type.
3391 @retval The data buffer size for the input type.
3398 UINT16 StorageWidth
;
3400 switch (ValueType
) {
3401 case EFI_IFR_NUMERIC_SIZE_1
:
3402 case EFI_IFR_TYPE_BOOLEAN
:
3403 StorageWidth
= (UINT16
) sizeof (UINT8
);
3406 case EFI_IFR_NUMERIC_SIZE_2
:
3407 StorageWidth
= (UINT16
) sizeof (UINT16
);
3410 case EFI_IFR_NUMERIC_SIZE_4
:
3411 StorageWidth
= (UINT16
) sizeof (UINT32
);
3414 case EFI_IFR_NUMERIC_SIZE_8
:
3415 StorageWidth
= (UINT16
) sizeof (UINT64
);
3418 case EFI_IFR_TYPE_TIME
:
3419 StorageWidth
= (UINT16
) sizeof (EFI_IFR_TIME
);
3422 case EFI_IFR_TYPE_DATE
:
3423 StorageWidth
= (UINT16
) sizeof (EFI_IFR_DATE
);
3431 return StorageWidth
;
3435 Generate ConfigAltResp string base on the varstore info.
3437 @param HiiHandle Hii Handle for this hii package.
3438 @param ConfigHdr The config header for this varstore.
3439 @param VarStorageData The varstore info.
3440 @param DefaultIdArray The Default id array.
3441 @param DefaultAltCfgResp The DefaultAltCfgResp info may be return.
3443 @retval TRUE Need to continue
3444 @retval Others NO need to continue or error occur.
3447 GenerateAltConfigResp (
3448 IN EFI_HII_HANDLE HiiHandle
,
3449 IN CHAR16
*ConfigHdr
,
3450 IN IFR_VARSTORAGE_DATA
*VarStorageData
,
3451 IN IFR_DEFAULT_DATA
*DefaultIdArray
,
3452 IN OUT EFI_STRING
*DefaultAltCfgResp
3458 LIST_ENTRY
*LinkData
;
3459 LIST_ENTRY
*LinkDefault
;
3460 LIST_ENTRY
*ListEntry
;
3462 IFR_BLOCK_DATA
*BlockData
;
3463 IFR_DEFAULT_DATA
*DefaultId
;
3464 IFR_DEFAULT_DATA
*DefaultValueData
;
3467 CHAR16
*DefaultString
;
3471 DefaultString
= NULL
;
3473 // Add length for <ConfigHdr> + '\0'
3475 Length
= StrLen (ConfigHdr
) + 1;
3477 for (Link
= DefaultIdArray
->Entry
.ForwardLink
; Link
!= &DefaultIdArray
->Entry
; Link
= Link
->ForwardLink
) {
3478 DefaultId
= BASE_CR (Link
, IFR_DEFAULT_DATA
, Entry
);
3480 // Add length for "&<ConfigHdr>&ALTCFG=XXXX"
3481 // |1| StrLen (ConfigHdr) | 8 | 4 |
3483 Length
+= (1 + StrLen (ConfigHdr
) + 8 + 4);
3485 for (LinkData
= VarStorageData
->BlockEntry
.ForwardLink
; LinkData
!= &VarStorageData
->BlockEntry
; LinkData
= LinkData
->ForwardLink
) {
3486 BlockData
= BASE_CR (LinkData
, IFR_BLOCK_DATA
, Entry
);
3487 ListEntry
= &BlockData
->DefaultValueEntry
;
3488 for (LinkDefault
= ListEntry
->ForwardLink
; LinkDefault
!= ListEntry
; LinkDefault
= LinkDefault
->ForwardLink
) {
3489 DefaultValueData
= BASE_CR (LinkDefault
, IFR_DEFAULT_DATA
, Entry
);
3490 if (DefaultValueData
->DefaultId
!= DefaultId
->DefaultId
) {
3493 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3495 // Add length for "&Name1=zzzzzzzzzzzz"
3498 Length
+= (1 + StrLen (BlockData
->Name
) + 1 + BlockData
->Width
* 2);
3501 // Add length for "&OFFSET=XXXX&WIDTH=YYYY&VALUE=zzzzzzzzzzzz"
3502 // | 8 | 4 | 7 | 4 | 7 | Width * 2 |
3504 Length
+= (8 + 4 + 7 + 4 + 7 + BlockData
->Width
* 2);
3512 // No default value is found. The default string doesn't exist.
3519 // Allocate buffer for the entire <DefaultAltCfgResp>
3521 *DefaultAltCfgResp
= AllocateZeroPool (Length
* sizeof (CHAR16
));
3522 if (*DefaultAltCfgResp
== NULL
) {
3523 return EFI_OUT_OF_RESOURCES
;
3525 StringPtr
= *DefaultAltCfgResp
;
3528 // Start with <ConfigHdr>
3530 StrCpyS (StringPtr
, Length
, ConfigHdr
);
3531 StringPtr
+= StrLen (StringPtr
);
3533 for (Link
= DefaultIdArray
->Entry
.ForwardLink
; Link
!= &DefaultIdArray
->Entry
; Link
= Link
->ForwardLink
) {
3534 DefaultId
= BASE_CR (Link
, IFR_DEFAULT_DATA
, Entry
);
3536 // Add <AltConfigHdr> of the form "&<ConfigHdr>&ALTCFG=XXXX\0"
3537 // |1| StrLen (ConfigHdr) | 8 | 4 |
3541 (1 + StrLen (ConfigHdr
) + 8 + 4 + 1) * sizeof (CHAR16
),
3544 DefaultId
->DefaultId
3546 StringPtr
+= StrLen (StringPtr
);
3548 for (LinkData
= VarStorageData
->BlockEntry
.ForwardLink
; LinkData
!= &VarStorageData
->BlockEntry
; LinkData
= LinkData
->ForwardLink
) {
3549 BlockData
= BASE_CR (LinkData
, IFR_BLOCK_DATA
, Entry
);
3550 ListEntry
= &BlockData
->DefaultValueEntry
;
3551 for (LinkDefault
= ListEntry
->ForwardLink
; LinkDefault
!= ListEntry
; LinkDefault
= LinkDefault
->ForwardLink
) {
3552 DefaultValueData
= BASE_CR (LinkDefault
, IFR_DEFAULT_DATA
, Entry
);
3553 if (DefaultValueData
->DefaultId
!= DefaultId
->DefaultId
) {
3556 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3559 (1 + StrLen (ConfigHdr
) + 1) * sizeof (CHAR16
),
3563 StringPtr
+= StrLen (StringPtr
);
3566 // Add <BlockConfig>
3567 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>
3571 (8 + 4 + 7 + 4 + 7 + 1) * sizeof (CHAR16
),
3572 L
"&OFFSET=%04X&WIDTH=%04X&VALUE=",
3576 StringPtr
+= StrLen (StringPtr
);
3578 Width
= BlockData
->Width
;
3580 // Convert Value to a hex string in "%x" format
3581 // NOTE: This is in the opposite byte that GUID and PATH use
3583 if (BlockData
->OpCode
== EFI_IFR_STRING_OP
){
3584 DefaultString
= InternalGetString(HiiHandle
, DefaultValueData
->Value
.string
);
3585 TmpBuffer
= (UINT8
*) DefaultString
;
3587 TmpBuffer
= (UINT8
*) &(DefaultValueData
->Value
);
3589 for (; Width
> 0 && (TmpBuffer
!= NULL
); Width
--) {
3590 StringPtr
+= UnicodeValueToString (StringPtr
, PREFIX_ZERO
| RADIX_HEX
, TmpBuffer
[Width
- 1], 2);
3592 if (DefaultString
!= NULL
){
3593 FreePool(DefaultString
);
3594 DefaultString
= NULL
;
3600 HiiToLower (*DefaultAltCfgResp
);
3606 This function gets the full request string and full default value string by
3607 parsing IFR data in HII form packages.
3609 When Request points to NULL string, the request string and default value string
3610 for each varstore in form package will return.
3612 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
3613 @param DevicePath Device Path which Hii Config Access Protocol is registered.
3614 @param Request Pointer to a null-terminated Unicode string in
3615 <ConfigRequest> format. When it doesn't contain
3616 any RequestElement, it will be updated to return
3617 the full RequestElement retrieved from IFR data.
3618 If it points to NULL, the request string for the first
3619 varstore in form package will be merged into a
3620 <MultiConfigRequest> format string and return.
3621 @param AltCfgResp Pointer to a null-terminated Unicode string in
3622 <ConfigAltResp> format. When the pointer is to NULL,
3623 the full default value string retrieved from IFR data
3624 will return. When the pinter is to a string, the
3625 full default value string retrieved from IFR data
3626 will be merged into the input string and return.
3627 When Request points to NULL, the default value string
3628 for each varstore in form package will be merged into
3629 a <MultiConfigAltResp> format string and return.
3630 @param PointerProgress Optional parameter, it can be be NULL.
3631 When it is not NULL, if Request is NULL, it returns NULL.
3632 On return, points to a character in the Request
3633 string. Points to the string's null terminator if
3634 request was successful. Points to the most recent
3635 & before the first failing name / value pair (or
3636 the beginning of the string if the failure is in
3637 the first name / value pair) if the request was
3639 @retval EFI_SUCCESS The Results string is set to the full request string.
3640 And AltCfgResp contains all default value string.
3641 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
3642 @retval EFI_NOT_FOUND The varstore (Guid and Name) in Request string
3643 can't be found in Form package.
3644 @retval EFI_NOT_FOUND HiiPackage can't be got on the input HiiHandle.
3645 @retval EFI_INVALID_PARAMETER Request points to NULL.
3650 GetFullStringFromHiiFormPackages (
3651 IN HII_DATABASE_RECORD
*DataBaseRecord
,
3652 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
3653 IN OUT EFI_STRING
*Request
,
3654 IN OUT EFI_STRING
*AltCfgResp
,
3655 OUT EFI_STRING
*PointerProgress OPTIONAL
3659 UINT8
*HiiFormPackage
;
3661 IFR_BLOCK_DATA
*RequestBlockArray
;
3662 IFR_BLOCK_DATA
*BlockData
;
3663 IFR_DEFAULT_DATA
*DefaultValueData
;
3664 IFR_DEFAULT_DATA
*DefaultId
;
3665 IFR_DEFAULT_DATA
*DefaultIdArray
;
3666 IFR_VARSTORAGE_DATA
*VarStorageData
;
3667 EFI_STRING DefaultAltCfgResp
;
3668 EFI_STRING ConfigHdr
;
3669 EFI_STRING StringPtr
;
3670 EFI_STRING Progress
;
3672 if (DataBaseRecord
== NULL
|| DevicePath
== NULL
|| Request
== NULL
|| AltCfgResp
== NULL
) {
3673 return EFI_INVALID_PARAMETER
;
3677 // Initialize the local variables.
3679 RequestBlockArray
= NULL
;
3680 DefaultIdArray
= NULL
;
3681 VarStorageData
= NULL
;
3682 DefaultAltCfgResp
= NULL
;
3684 HiiFormPackage
= NULL
;
3686 Progress
= *Request
;
3688 Status
= GetFormPackageData (DataBaseRecord
, &HiiFormPackage
, &PackageSize
);
3689 if (EFI_ERROR (Status
)) {
3694 // 1. Get the request block array by Request String when Request string containts the block array.
3697 if (*Request
!= NULL
) {
3698 StringPtr
= *Request
;
3702 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
3703 Status
= EFI_INVALID_PARAMETER
;
3706 StringPtr
+= StrLen (L
"GUID=");
3707 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&NAME=", StrLen (L
"&NAME=")) != 0) {
3710 if (*StringPtr
== L
'\0') {
3711 Status
= EFI_INVALID_PARAMETER
;
3714 StringPtr
+= StrLen (L
"&NAME=");
3715 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&PATH=", StrLen (L
"&PATH=")) != 0) {
3718 if (*StringPtr
== L
'\0') {
3719 Status
= EFI_INVALID_PARAMETER
;
3722 StringPtr
+= StrLen (L
"&PATH=");
3723 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
3727 if (*StringPtr
== L
'\0') {
3729 // No request block is found.
3736 // If StringPtr != NULL, get the request elements.
3738 if (StringPtr
!= NULL
) {
3739 if (StrStr (StringPtr
, L
"&OFFSET=") != NULL
) {
3740 RequestBlockArray
= GetBlockElement(StringPtr
, &Progress
);
3742 RequestBlockArray
= GetNameElement(StringPtr
, &Progress
);
3745 if (RequestBlockArray
== NULL
) {
3746 Status
= EFI_INVALID_PARAMETER
;
3752 // Initialize DefaultIdArray to store the map between DeaultId and DefaultName
3754 DefaultIdArray
= (IFR_DEFAULT_DATA
*) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
3755 if (DefaultIdArray
== NULL
) {
3756 Status
= EFI_OUT_OF_RESOURCES
;
3759 InitializeListHead (&DefaultIdArray
->Entry
);
3762 // Initialize VarStorageData to store the var store Block and Default value information.
3764 VarStorageData
= (IFR_VARSTORAGE_DATA
*) AllocateZeroPool (sizeof (IFR_VARSTORAGE_DATA
));
3765 if (VarStorageData
== NULL
) {
3766 Status
= EFI_OUT_OF_RESOURCES
;
3769 InitializeListHead (&VarStorageData
->Entry
);
3770 InitializeListHead (&VarStorageData
->BlockEntry
);
3773 // 2. Parse FormPackage to get BlockArray and DefaultId Array for the request BlockArray.
3777 // Parse the opcode in form pacakge to get the default setting.
3779 Status
= ParseIfrData (DataBaseRecord
->Handle
,
3781 (UINT32
) PackageSize
,
3786 if (EFI_ERROR (Status
)) {
3791 // No requested varstore in IFR data and directly return
3793 if (VarStorageData
->Type
== 0 && VarStorageData
->Name
== NULL
) {
3794 Status
= EFI_SUCCESS
;
3799 // 3. Construct Request Element (Block Name) for 2.1 and 2.2 case.
3801 Status
= GenerateHdr (VarStorageData
, DevicePath
, &ConfigHdr
);
3802 if (EFI_ERROR (Status
)) {
3806 if (RequestBlockArray
== NULL
) {
3807 if (!GenerateConfigRequest(ConfigHdr
, VarStorageData
, &Status
, Request
)) {
3813 // 4. Construct Default Value string in AltResp according to request element.
3814 // Go through all VarStorageData Entry and get the DefaultId array for each one
3815 // Then construct them all to : ConfigHdr AltConfigHdr ConfigBody AltConfigHdr ConfigBody
3817 Status
= GenerateAltConfigResp (DataBaseRecord
->Handle
,ConfigHdr
, VarStorageData
, DefaultIdArray
, &DefaultAltCfgResp
);
3818 if (EFI_ERROR (Status
)) {
3823 // 5. Merge string into the input AltCfgResp if the iput *AltCfgResp is not NULL.
3825 if (*AltCfgResp
!= NULL
&& DefaultAltCfgResp
!= NULL
) {
3826 Status
= MergeDefaultString (AltCfgResp
, DefaultAltCfgResp
);
3827 FreePool (DefaultAltCfgResp
);
3828 } else if (*AltCfgResp
== NULL
) {
3829 *AltCfgResp
= DefaultAltCfgResp
;
3833 if (RequestBlockArray
!= NULL
) {
3835 // Free Link Array RequestBlockArray
3837 while (!IsListEmpty (&RequestBlockArray
->Entry
)) {
3838 BlockData
= BASE_CR (RequestBlockArray
->Entry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
3839 RemoveEntryList (&BlockData
->Entry
);
3840 if (BlockData
->Name
!= NULL
) {
3841 FreePool (BlockData
->Name
);
3843 FreePool (BlockData
);
3846 FreePool (RequestBlockArray
);
3849 if (VarStorageData
!= NULL
) {
3851 // Free link array VarStorageData
3853 while (!IsListEmpty (&VarStorageData
->BlockEntry
)) {
3854 BlockData
= BASE_CR (VarStorageData
->BlockEntry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
3855 RemoveEntryList (&BlockData
->Entry
);
3856 if (BlockData
->Name
!= NULL
) {
3857 FreePool (BlockData
->Name
);
3860 // Free default value link array
3862 while (!IsListEmpty (&BlockData
->DefaultValueEntry
)) {
3863 DefaultValueData
= BASE_CR (BlockData
->DefaultValueEntry
.ForwardLink
, IFR_DEFAULT_DATA
, Entry
);
3864 RemoveEntryList (&DefaultValueData
->Entry
);
3865 FreePool (DefaultValueData
);
3867 FreePool (BlockData
);
3869 FreePool (VarStorageData
);
3872 if (DefaultIdArray
!= NULL
) {
3874 // Free DefaultId Array
3876 while (!IsListEmpty (&DefaultIdArray
->Entry
)) {
3877 DefaultId
= BASE_CR (DefaultIdArray
->Entry
.ForwardLink
, IFR_DEFAULT_DATA
, Entry
);
3878 RemoveEntryList (&DefaultId
->Entry
);
3879 FreePool (DefaultId
);
3881 FreePool (DefaultIdArray
);
3885 // Free the allocated string
3887 if (ConfigHdr
!= NULL
) {
3888 FreePool (ConfigHdr
);
3892 // Free Pacakge data
3894 if (HiiFormPackage
!= NULL
) {
3895 FreePool (HiiFormPackage
);
3898 if (PointerProgress
!= NULL
) {
3899 if (*Request
== NULL
) {
3900 *PointerProgress
= NULL
;
3901 } else if (EFI_ERROR (Status
)) {
3902 *PointerProgress
= *Request
;
3904 *PointerProgress
= *Request
+ StrLen (*Request
);
3912 This function gets the full request resp string by
3913 parsing IFR data in HII form packages.
3915 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
3917 @param EfiVarStoreInfo The efi varstore info which is save in the EFI
3918 varstore data structure.
3919 @param Request Pointer to a null-terminated Unicode string in
3920 <ConfigRequest> format.
3921 @param RequestResp Pointer to a null-terminated Unicode string in
3922 <ConfigResp> format.
3923 @param AccessProgress On return, points to a character in the Request
3924 string. Points to the string's null terminator if
3925 request was successful. Points to the most recent
3926 & before the first failing name / value pair (or
3927 the beginning of the string if the failure is in
3928 the first name / value pair) if the request was
3931 @retval EFI_SUCCESS The Results string is set to the full request string.
3932 And AltCfgResp contains all default value string.
3933 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
3934 @retval EFI_INVALID_PARAMETER Request points to NULL.
3938 GetConfigRespFromEfiVarStore (
3939 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
3940 IN EFI_IFR_VARSTORE_EFI
*EfiVarStoreInfo
,
3941 IN EFI_STRING Request
,
3942 OUT EFI_STRING
*RequestResp
,
3943 OUT EFI_STRING
*AccessProgress
3947 EFI_STRING VarStoreName
;
3951 Status
= EFI_SUCCESS
;
3954 VarStoreName
= NULL
;
3955 *AccessProgress
= Request
;
3957 VarStoreName
= AllocateZeroPool (AsciiStrSize ((CHAR8
*)EfiVarStoreInfo
->Name
) * sizeof (CHAR16
));
3958 if (VarStoreName
== NULL
) {
3959 Status
= EFI_OUT_OF_RESOURCES
;
3962 AsciiStrToUnicodeStr ((CHAR8
*) EfiVarStoreInfo
->Name
, VarStoreName
);
3965 Status
= gRT
->GetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, NULL
, &BufferSize
, NULL
);
3966 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
3970 VarStore
= AllocateZeroPool (BufferSize
);
3971 ASSERT (VarStore
!= NULL
);
3972 Status
= gRT
->GetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, NULL
, &BufferSize
, VarStore
);
3973 if (EFI_ERROR (Status
)) {
3977 Status
= HiiBlockToConfig(This
, Request
, VarStore
, BufferSize
, RequestResp
, AccessProgress
);
3978 if (EFI_ERROR (Status
)) {
3983 if (VarStoreName
!= NULL
) {
3984 FreePool (VarStoreName
);
3987 if (VarStore
!= NULL
) {
3988 FreePool (VarStore
);
3996 This function route the full request resp string for efi varstore.
3998 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
4000 @param EfiVarStoreInfo The efi varstore info which is save in the EFI
4001 varstore data structure.
4002 @param RequestResp Pointer to a null-terminated Unicode string in
4003 <ConfigResp> format.
4004 @param Result Pointer to a null-terminated Unicode string in
4005 <ConfigResp> format.
4007 @retval EFI_SUCCESS The Results string is set to the full request string.
4008 And AltCfgResp contains all default value string.
4009 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
4010 @retval EFI_INVALID_PARAMETER Request points to NULL.
4014 RouteConfigRespForEfiVarStore (
4015 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
4016 IN EFI_IFR_VARSTORE_EFI
*EfiVarStoreInfo
,
4017 IN EFI_STRING RequestResp
,
4018 OUT EFI_STRING
*Result
4022 EFI_STRING VarStoreName
;
4027 Status
= EFI_SUCCESS
;
4030 VarStoreName
= NULL
;
4032 VarStoreName
= AllocateZeroPool (AsciiStrSize ((CHAR8
*)EfiVarStoreInfo
->Name
) * sizeof (CHAR16
));
4033 if (VarStoreName
== NULL
) {
4034 Status
= EFI_OUT_OF_RESOURCES
;
4037 AsciiStrToUnicodeStr ((CHAR8
*) EfiVarStoreInfo
->Name
, VarStoreName
);
4039 Status
= gRT
->GetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, NULL
, &BufferSize
, NULL
);
4040 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
4044 BlockSize
= BufferSize
;
4045 VarStore
= AllocateZeroPool (BufferSize
);
4046 ASSERT (VarStore
!= NULL
);
4047 Status
= gRT
->GetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, NULL
, &BufferSize
, VarStore
);
4048 if (EFI_ERROR (Status
)) {
4052 Status
= HiiConfigToBlock(This
, RequestResp
, VarStore
, &BlockSize
, Result
);
4053 if (EFI_ERROR (Status
)) {
4057 Status
= gRT
->SetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, EfiVarStoreInfo
->Attributes
, BufferSize
, VarStore
);
4058 if (EFI_ERROR (Status
)) {
4063 if (VarStoreName
!= NULL
) {
4064 FreePool (VarStoreName
);
4067 if (VarStore
!= NULL
) {
4068 FreePool (VarStore
);
4075 Validate the config request elements.
4077 @param ConfigElements A null-terminated Unicode string in <ConfigRequest> format,
4078 without configHdr field.
4080 @retval CHAR16 * THE first Name/value pair not correct.
4081 @retval NULL Success parse the name/value pair
4084 OffsetWidthValidate (
4085 CHAR16
*ConfigElements
4091 StringPtr
= ConfigElements
;
4095 if (StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) != 0) {
4099 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
4102 if (*StringPtr
== L
'\0') {
4106 StringPtr
+= StrLen (L
"&WIDTH=");
4107 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) != 0) {
4111 if (*StringPtr
== L
'\0') {
4118 Validate the config request elements.
4120 @param ConfigElements A null-terminated Unicode string in <ConfigRequest> format,
4121 without configHdr field.
4123 @retval CHAR16 * THE first Name/value pair not correct.
4124 @retval NULL Success parse the name/value pair
4129 CHAR16
*ConfigElements
4135 StringPtr
= ConfigElements
;
4139 if (*StringPtr
!= L
'&') {
4144 StringPtr
= StrStr (StringPtr
, L
"&");
4146 if (StringPtr
== NULL
) {
4153 Validate the config request string.
4155 @param ConfigRequest A null-terminated Unicode string in <ConfigRequest> format.
4157 @retval CHAR16 * THE first element not correct.
4158 @retval NULL Success parse the name/value pair
4162 ConfigRequestValidate (
4163 CHAR16
*ConfigRequest
4166 BOOLEAN HasNameField
;
4169 HasNameField
= TRUE
;
4170 StringPtr
= ConfigRequest
;
4173 // Check <ConfigHdr>
4175 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
4176 return ConfigRequest
;
4178 StringPtr
+= StrLen (L
"GUID=");
4179 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&NAME=", StrLen (L
"&NAME=")) != 0) {
4182 if (*StringPtr
== L
'\0') {
4183 return ConfigRequest
;
4185 StringPtr
+= StrLen (L
"&NAME=");
4186 if (*StringPtr
== L
'&') {
4187 HasNameField
= FALSE
;
4189 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&PATH=", StrLen (L
"&PATH=")) != 0) {
4192 if (*StringPtr
== L
'\0') {
4193 return ConfigRequest
;
4195 StringPtr
+= StrLen (L
"&PATH=");
4196 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
4200 if (*StringPtr
== L
'\0') {
4206 // Should be Buffer varstore, config request should be "OFFSET/Width" pairs.
4208 return OffsetWidthValidate(StringPtr
);
4211 // Should be Name/Value varstore, config request should be "&name1&name2..." pairs.
4213 return NameValueValidate(StringPtr
);
4218 This function allows a caller to extract the current configuration
4219 for one or more named elements from one or more drivers.
4221 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
4223 @param Request A null-terminated Unicode string in
4224 <MultiConfigRequest> format.
4225 @param Progress On return, points to a character in the Request
4226 string. Points to the string's null terminator if
4227 request was successful. Points to the most recent
4228 & before the first failing name / value pair (or
4229 the beginning of the string if the failure is in
4230 the first name / value pair) if the request was
4232 @param Results Null-terminated Unicode string in
4233 <MultiConfigAltResp> format which has all values
4234 filled in for the names in the Request string.
4235 String to be allocated by the called function.
4237 @retval EFI_SUCCESS The Results string is filled with the values
4238 corresponding to all requested names.
4239 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
4240 results that must be stored awaiting possible
4242 @retval EFI_NOT_FOUND Routing data doesn't match any known driver.
4243 Progress set to the "G" in "GUID" of the routing
4244 header that doesn't match. Note: There is no
4245 requirement that all routing data be validated
4246 before any configuration extraction.
4247 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Request
4248 parameter would result in this type of error. The
4249 Progress parameter is set to NULL.
4250 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set to most recent &
4251 before the error or the beginning of the string.
4252 @retval EFI_INVALID_PARAMETER The ExtractConfig function of the underlying HII
4253 Configuration Access Protocol returned
4254 EFI_INVALID_PARAMETER. Progress set to most recent
4255 & before the error or the beginning of the string.
4260 HiiConfigRoutingExtractConfig (
4261 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
4262 IN CONST EFI_STRING Request
,
4263 OUT EFI_STRING
*Progress
,
4264 OUT EFI_STRING
*Results
4267 HII_DATABASE_PRIVATE_DATA
*Private
;
4268 EFI_STRING StringPtr
;
4269 EFI_STRING ConfigRequest
;
4271 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
4272 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
4275 HII_DATABASE_RECORD
*Database
;
4276 UINT8
*DevicePathPkg
;
4277 UINT8
*CurrentDevicePath
;
4278 EFI_HANDLE DriverHandle
;
4279 EFI_HII_HANDLE HiiHandle
;
4280 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
4281 EFI_STRING AccessProgress
;
4282 EFI_STRING AccessResults
;
4283 EFI_STRING AccessProgressBackup
;
4284 EFI_STRING AccessResultsBackup
;
4285 EFI_STRING DefaultResults
;
4286 BOOLEAN FirstElement
;
4287 BOOLEAN IfrDataParsedFlag
;
4288 BOOLEAN IsEfiVarStore
;
4289 EFI_IFR_VARSTORE_EFI
*EfiVarStoreInfo
;
4290 EFI_STRING ErrorPtr
;
4291 UINTN DevicePathSize
;
4292 UINTN ConigStringSize
;
4293 UINTN ConigStringSizeNewsize
;
4294 EFI_STRING ConfigStringPtr
;
4296 if (This
== NULL
|| Progress
== NULL
|| Results
== NULL
) {
4297 return EFI_INVALID_PARAMETER
;
4300 if (Request
== NULL
) {
4302 return EFI_INVALID_PARAMETER
;
4305 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
4306 StringPtr
= Request
;
4307 *Progress
= StringPtr
;
4308 DefaultResults
= NULL
;
4309 ConfigRequest
= NULL
;
4310 Status
= EFI_SUCCESS
;
4311 AccessResults
= NULL
;
4312 AccessProgress
= NULL
;
4313 AccessResultsBackup
= NULL
;
4314 AccessProgressBackup
= NULL
;
4316 IfrDataParsedFlag
= FALSE
;
4317 IsEfiVarStore
= FALSE
;
4318 EfiVarStoreInfo
= NULL
;
4321 // The first element of <MultiConfigRequest> should be
4322 // <GuidHdr>, which is in 'GUID='<Guid> syntax.
4324 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
4325 return EFI_INVALID_PARAMETER
;
4328 FirstElement
= TRUE
;
4331 // Allocate a fix length of memory to store Results. Reallocate memory for
4332 // Results if this fix length is insufficient.
4334 *Results
= (EFI_STRING
) AllocateZeroPool (MAX_STRING_LENGTH
);
4335 if (*Results
== NULL
) {
4336 return EFI_OUT_OF_RESOURCES
;
4339 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) == 0) {
4341 // If parsing error, set Progress to the beginning of the <MultiConfigRequest>
4342 // or most recent & before the error.
4344 if (StringPtr
== Request
) {
4345 *Progress
= StringPtr
;
4347 *Progress
= StringPtr
- 1;
4351 // Process each <ConfigRequest> of <MultiConfigRequest>
4353 Length
= CalculateConfigStringLen (StringPtr
);
4354 ConfigRequest
= AllocateCopyPool ((Length
+ 1) * sizeof (CHAR16
), StringPtr
);
4355 if (ConfigRequest
== NULL
) {
4356 Status
= EFI_OUT_OF_RESOURCES
;
4359 *(ConfigRequest
+ Length
) = 0;
4362 // Get the UEFI device path
4364 Status
= GetDevicePath (ConfigRequest
, (UINT8
**) &DevicePath
);
4365 if (EFI_ERROR (Status
)) {
4370 // Find driver which matches the routing data.
4372 DriverHandle
= NULL
;
4375 for (Link
= Private
->DatabaseList
.ForwardLink
;
4376 Link
!= &Private
->DatabaseList
;
4377 Link
= Link
->ForwardLink
4379 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
4380 if ((DevicePathPkg
= Database
->PackageList
->DevicePathPkg
) != NULL
) {
4381 CurrentDevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
4382 DevicePathSize
= GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) CurrentDevicePath
);
4383 if ((CompareMem (DevicePath
,CurrentDevicePath
,DevicePathSize
) == 0) && IsThisPackageList(Database
, ConfigRequest
)) {
4384 DriverHandle
= Database
->DriverHandle
;
4385 HiiHandle
= Database
->Handle
;
4392 // Try to find driver handle by device path.
4394 if (DriverHandle
== NULL
) {
4395 TempDevicePath
= DevicePath
;
4396 Status
= gBS
->LocateDevicePath (
4397 &gEfiDevicePathProtocolGuid
,
4401 if (EFI_ERROR (Status
) || (DriverHandle
== NULL
)) {
4403 // Routing data does not match any known driver.
4404 // Set Progress to the 'G' in "GUID" of the routing header.
4406 *Progress
= StringPtr
;
4407 Status
= EFI_NOT_FOUND
;
4413 // Validate ConfigRequest String.
4415 ErrorPtr
= ConfigRequestValidate(ConfigRequest
);
4416 if (ErrorPtr
!= NULL
) {
4417 *Progress
= StrStr (StringPtr
, ErrorPtr
);
4418 Status
= EFI_INVALID_PARAMETER
;
4423 // Check whether ConfigRequest contains request string.
4425 IfrDataParsedFlag
= FALSE
;
4426 if ((HiiHandle
!= NULL
) && !GetElementsFromRequest(ConfigRequest
)) {
4428 // Get the full request string from IFR when HiiPackage is registered to HiiHandle
4430 IfrDataParsedFlag
= TRUE
;
4431 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &ConfigRequest
, &DefaultResults
, &AccessProgress
);
4432 if (EFI_ERROR (Status
)) {
4434 // AccessProgress indicates the parsing progress on <ConfigRequest>.
4435 // Map it to the progress on <MultiConfigRequest> then return it.
4437 ASSERT (AccessProgress
!= NULL
);
4438 *Progress
= StrStr (StringPtr
, AccessProgress
);
4442 // Not any request block is found.
4444 if (!GetElementsFromRequest(ConfigRequest
)) {
4445 AccessResults
= AllocateCopyPool (StrSize (ConfigRequest
), ConfigRequest
);
4446 goto NextConfigString
;
4451 // Check whether this ConfigRequest is search from Efi varstore type storage.
4453 Status
= GetVarStoreType(Database
, ConfigRequest
, &IsEfiVarStore
, &EfiVarStoreInfo
);
4454 if (EFI_ERROR (Status
)) {
4458 if (IsEfiVarStore
) {
4460 // Call the GetVariable function to extract settings.
4462 Status
= GetConfigRespFromEfiVarStore(This
, EfiVarStoreInfo
, ConfigRequest
, &AccessResults
, &AccessProgress
);
4463 FreePool (EfiVarStoreInfo
);
4464 if (EFI_ERROR (Status
)) {
4466 // AccessProgress indicates the parsing progress on <ConfigRequest>.
4467 // Map it to the progress on <MultiConfigRequest> then return it.
4469 *Progress
= StrStr (StringPtr
, AccessProgress
);
4474 // For EfiVarstore, call corresponding ConfigAccess protocol to get the AltCfgResp from driver.
4476 Status
= gBS
->HandleProtocol (
4478 &gEfiHiiConfigAccessProtocolGuid
,
4479 (VOID
**) &ConfigAccess
4481 if (EFI_ERROR (Status
)) {
4483 // The driver has EfiVarStore, may not install ConfigAccess protocol.
4484 // So ignore the error status in this case.
4486 Status
= EFI_SUCCESS
;
4488 Status
= ConfigAccess
->ExtractConfig (
4491 &AccessProgressBackup
,
4492 &AccessResultsBackup
4494 if (!EFI_ERROR(Status
)) {
4496 //Merge the AltCfgResp in AccessResultsBackup to AccessResults
4498 if ((AccessResultsBackup
!= NULL
) && (StrStr (AccessResultsBackup
, L
"&ALTCFG=") != NULL
)) {
4499 ConigStringSize
= StrSize (AccessResults
);
4500 ConfigStringPtr
= StrStr (AccessResultsBackup
, L
"&GUID=");
4501 ConigStringSizeNewsize
= StrSize (ConfigStringPtr
) + ConigStringSize
+ sizeof (CHAR16
);
4502 AccessResults
= (EFI_STRING
) ReallocatePool (
4504 ConigStringSizeNewsize
,
4506 StrCatS (AccessResults
, ConigStringSizeNewsize
/ sizeof (CHAR16
), ConfigStringPtr
);
4510 // In the ExtractConfig function of some driver may not support EfiVarStore,
4511 // may return error status, just ignore the error status in this case.
4513 Status
= EFI_SUCCESS
;
4515 if (AccessResultsBackup
!= NULL
) {
4516 FreePool (AccessResultsBackup
);
4517 AccessResultsBackup
= NULL
;
4522 // Call corresponding ConfigAccess protocol to extract settings
4524 Status
= gBS
->HandleProtocol (
4526 &gEfiHiiConfigAccessProtocolGuid
,
4527 (VOID
**) &ConfigAccess
4529 if (EFI_ERROR (Status
)) {
4533 Status
= ConfigAccess
->ExtractConfig (
4540 if (EFI_ERROR (Status
)) {
4542 // AccessProgress indicates the parsing progress on <ConfigRequest>.
4543 // Map it to the progress on <MultiConfigRequest> then return it.
4545 *Progress
= StrStr (StringPtr
, AccessProgress
);
4550 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'
4551 // which seperates the first <ConfigAltResp> and the following ones.
4553 ASSERT (*AccessProgress
== 0);
4556 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
4558 if (!IfrDataParsedFlag
&& HiiHandle
!= NULL
) {
4559 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &ConfigRequest
, &DefaultResults
, NULL
);
4560 ASSERT_EFI_ERROR (Status
);
4563 FreePool (DevicePath
);
4566 if (DefaultResults
!= NULL
) {
4567 Status
= MergeDefaultString (&AccessResults
, DefaultResults
);
4568 ASSERT_EFI_ERROR (Status
);
4569 FreePool (DefaultResults
);
4570 DefaultResults
= NULL
;
4574 if (!FirstElement
) {
4575 Status
= AppendToMultiString (Results
, L
"&");
4576 ASSERT_EFI_ERROR (Status
);
4579 Status
= AppendToMultiString (Results
, AccessResults
);
4580 ASSERT_EFI_ERROR (Status
);
4582 FirstElement
= FALSE
;
4584 FreePool (AccessResults
);
4585 AccessResults
= NULL
;
4586 FreePool (ConfigRequest
);
4587 ConfigRequest
= NULL
;
4590 // Go to next <ConfigRequest> (skip '&').
4592 StringPtr
+= Length
;
4593 if (*StringPtr
== 0) {
4594 *Progress
= StringPtr
;
4602 if (EFI_ERROR (Status
)) {
4603 FreePool (*Results
);
4607 if (ConfigRequest
!= NULL
) {
4608 FreePool (ConfigRequest
);
4611 if (AccessResults
!= NULL
) {
4612 FreePool (AccessResults
);
4615 if (DefaultResults
!= NULL
) {
4616 FreePool (DefaultResults
);
4619 if (DevicePath
!= NULL
) {
4620 FreePool (DevicePath
);
4628 This function allows the caller to request the current configuration for the
4629 entirety of the current HII database and returns the data in a
4630 null-terminated Unicode string.
4632 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
4634 @param Results Null-terminated Unicode string in
4635 <MultiConfigAltResp> format which has all values
4636 filled in for the entirety of the current HII
4637 database. String to be allocated by the called
4638 function. De-allocation is up to the caller.
4640 @retval EFI_SUCCESS The Results string is filled with the values
4641 corresponding to all requested names.
4642 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
4643 results that must be stored awaiting possible
4645 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Results
4646 parameter would result in this type of error.
4651 HiiConfigRoutingExportConfig (
4652 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
4653 OUT EFI_STRING
*Results
4657 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
4658 EFI_STRING AccessResults
;
4659 EFI_STRING Progress
;
4660 EFI_STRING StringPtr
;
4661 EFI_STRING ConfigRequest
;
4663 EFI_HANDLE
*ConfigAccessHandles
;
4664 UINTN NumberConfigAccessHandles
;
4665 BOOLEAN FirstElement
;
4666 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
4667 EFI_HII_HANDLE HiiHandle
;
4668 EFI_STRING DefaultResults
;
4669 HII_DATABASE_PRIVATE_DATA
*Private
;
4671 HII_DATABASE_RECORD
*Database
;
4672 UINT8
*DevicePathPkg
;
4673 UINT8
*CurrentDevicePath
;
4674 BOOLEAN IfrDataParsedFlag
;
4676 if (This
== NULL
|| Results
== NULL
) {
4677 return EFI_INVALID_PARAMETER
;
4680 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
4683 // Allocate a fix length of memory to store Results. Reallocate memory for
4684 // Results if this fix length is insufficient.
4686 *Results
= (EFI_STRING
) AllocateZeroPool (MAX_STRING_LENGTH
);
4687 if (*Results
== NULL
) {
4688 return EFI_OUT_OF_RESOURCES
;
4691 NumberConfigAccessHandles
= 0;
4692 Status
= gBS
->LocateHandleBuffer (
4694 &gEfiHiiConfigAccessProtocolGuid
,
4696 &NumberConfigAccessHandles
,
4697 &ConfigAccessHandles
4699 if (EFI_ERROR (Status
)) {
4703 FirstElement
= TRUE
;
4705 for (Index
= 0; Index
< NumberConfigAccessHandles
; Index
++) {
4706 Status
= gBS
->HandleProtocol (
4707 ConfigAccessHandles
[Index
],
4708 &gEfiHiiConfigAccessProtocolGuid
,
4709 (VOID
**) &ConfigAccess
4711 if (EFI_ERROR (Status
)) {
4716 // Get DevicePath and HiiHandle for this ConfigAccess driver handle
4718 IfrDataParsedFlag
= FALSE
;
4721 DefaultResults
= NULL
;
4723 ConfigRequest
= NULL
;
4724 DevicePath
= DevicePathFromHandle (ConfigAccessHandles
[Index
]);
4725 if (DevicePath
!= NULL
) {
4726 for (Link
= Private
->DatabaseList
.ForwardLink
;
4727 Link
!= &Private
->DatabaseList
;
4728 Link
= Link
->ForwardLink
4730 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
4731 if ((DevicePathPkg
= Database
->PackageList
->DevicePathPkg
) != NULL
) {
4732 CurrentDevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
4736 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) CurrentDevicePath
)
4738 HiiHandle
= Database
->Handle
;
4745 Status
= ConfigAccess
->ExtractConfig (
4751 if (EFI_ERROR (Status
)) {
4753 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
4755 if (HiiHandle
!= NULL
&& DevicePath
!= NULL
) {
4756 IfrDataParsedFlag
= TRUE
;
4757 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &ConfigRequest
, &DefaultResults
, NULL
);
4759 // Get the full request string to get the Current setting again.
4761 if (!EFI_ERROR (Status
) && ConfigRequest
!= NULL
) {
4762 Status
= ConfigAccess
->ExtractConfig (
4768 FreePool (ConfigRequest
);
4770 Status
= EFI_NOT_FOUND
;
4775 if (!EFI_ERROR (Status
)) {
4777 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
4779 if (!IfrDataParsedFlag
&& HiiHandle
!= NULL
&& DevicePath
!= NULL
) {
4780 StringPtr
= StrStr (AccessResults
, L
"&GUID=");
4781 if (StringPtr
!= NULL
) {
4784 if (GetElementsFromRequest (AccessResults
)) {
4785 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &AccessResults
, &DefaultResults
, NULL
);
4786 ASSERT_EFI_ERROR (Status
);
4788 if (StringPtr
!= NULL
) {
4793 // Merge the default sting from IFR code into the got setting from driver.
4795 if (DefaultResults
!= NULL
) {
4796 Status
= MergeDefaultString (&AccessResults
, DefaultResults
);
4797 ASSERT_EFI_ERROR (Status
);
4798 FreePool (DefaultResults
);
4799 DefaultResults
= NULL
;
4803 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'
4804 // which seperates the first <ConfigAltResp> and the following ones.
4806 if (!FirstElement
) {
4807 Status
= AppendToMultiString (Results
, L
"&");
4808 ASSERT_EFI_ERROR (Status
);
4811 Status
= AppendToMultiString (Results
, AccessResults
);
4812 ASSERT_EFI_ERROR (Status
);
4814 FirstElement
= FALSE
;
4816 FreePool (AccessResults
);
4817 AccessResults
= NULL
;
4820 FreePool (ConfigAccessHandles
);
4827 This function processes the results of processing forms and routes it to the
4828 appropriate handlers or storage.
4830 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
4832 @param Configuration A null-terminated Unicode string in
4833 <MulltiConfigResp> format.
4834 @param Progress A pointer to a string filled in with the offset of
4835 the most recent & before the first failing name /
4836 value pair (or the beginning of the string if the
4837 failure is in the first name / value pair) or the
4838 terminating NULL if all was successful.
4840 @retval EFI_SUCCESS The results have been distributed or are awaiting
4842 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
4843 results that must be stored awaiting possible
4845 @retval EFI_INVALID_PARAMETER Passing in a NULL for the Configuration parameter
4846 would result in this type of error.
4847 @retval EFI_NOT_FOUND Target for the specified routing data was not
4853 HiiConfigRoutingRouteConfig (
4854 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
4855 IN CONST EFI_STRING Configuration
,
4856 OUT EFI_STRING
*Progress
4859 HII_DATABASE_PRIVATE_DATA
*Private
;
4860 EFI_STRING StringPtr
;
4861 EFI_STRING ConfigResp
;
4864 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
4865 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
4867 HII_DATABASE_RECORD
*Database
;
4868 UINT8
*DevicePathPkg
;
4869 UINT8
*CurrentDevicePath
;
4870 EFI_HANDLE DriverHandle
;
4871 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
4872 EFI_STRING AccessProgress
;
4873 EFI_IFR_VARSTORE_EFI
*EfiVarStoreInfo
;
4874 BOOLEAN IsEfiVarstore
;
4875 UINTN DevicePathSize
;
4877 if (This
== NULL
|| Progress
== NULL
) {
4878 return EFI_INVALID_PARAMETER
;
4881 if (Configuration
== NULL
) {
4883 return EFI_INVALID_PARAMETER
;
4886 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
4887 StringPtr
= Configuration
;
4888 *Progress
= StringPtr
;
4890 AccessProgress
= NULL
;
4891 EfiVarStoreInfo
= NULL
;
4892 IsEfiVarstore
= FALSE
;
4895 // The first element of <MultiConfigResp> should be
4896 // <GuidHdr>, which is in 'GUID='<Guid> syntax.
4898 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
4899 return EFI_INVALID_PARAMETER
;
4902 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) == 0) {
4904 // If parsing error, set Progress to the beginning of the <MultiConfigResp>
4905 // or most recent & before the error.
4907 if (StringPtr
== Configuration
) {
4908 *Progress
= StringPtr
;
4910 *Progress
= StringPtr
- 1;
4914 // Process each <ConfigResp> of <MultiConfigResp>
4916 Length
= CalculateConfigStringLen (StringPtr
);
4917 ConfigResp
= AllocateCopyPool ((Length
+ 1) * sizeof (CHAR16
), StringPtr
);
4918 if (ConfigResp
== NULL
) {
4919 return EFI_OUT_OF_RESOURCES
;
4922 // Append '\0' to the end of ConfigRequest
4924 *(ConfigResp
+ Length
) = 0;
4927 // Get the UEFI device path
4929 Status
= GetDevicePath (ConfigResp
, (UINT8
**) &DevicePath
);
4930 if (EFI_ERROR (Status
)) {
4931 FreePool (ConfigResp
);
4936 // Find driver which matches the routing data.
4938 DriverHandle
= NULL
;
4939 for (Link
= Private
->DatabaseList
.ForwardLink
;
4940 Link
!= &Private
->DatabaseList
;
4941 Link
= Link
->ForwardLink
4943 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
4945 if ((DevicePathPkg
= Database
->PackageList
->DevicePathPkg
) != NULL
) {
4946 CurrentDevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
4947 DevicePathSize
= GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) CurrentDevicePath
);
4948 if ((CompareMem (DevicePath
,CurrentDevicePath
,DevicePathSize
) == 0) && IsThisPackageList(Database
, ConfigResp
)) {
4949 DriverHandle
= Database
->DriverHandle
;
4956 // Try to find driver handle by device path.
4958 if (DriverHandle
== NULL
) {
4959 TempDevicePath
= DevicePath
;
4960 Status
= gBS
->LocateDevicePath (
4961 &gEfiDevicePathProtocolGuid
,
4965 if (EFI_ERROR (Status
) || (DriverHandle
== NULL
)) {
4967 // Routing data does not match any known driver.
4968 // Set Progress to the 'G' in "GUID" of the routing header.
4970 FreePool (DevicePath
);
4971 *Progress
= StringPtr
;
4972 FreePool (ConfigResp
);
4973 return EFI_NOT_FOUND
;
4977 FreePool (DevicePath
);
4980 // Check whether this ConfigRequest is search from Efi varstore type storage.
4982 Status
= GetVarStoreType(Database
, ConfigResp
, &IsEfiVarstore
, &EfiVarStoreInfo
);
4983 if (EFI_ERROR (Status
)) {
4987 if (IsEfiVarstore
) {
4989 // Call the SetVariable function to route settings.
4991 Status
= RouteConfigRespForEfiVarStore(This
, EfiVarStoreInfo
, ConfigResp
, &AccessProgress
);
4992 FreePool (EfiVarStoreInfo
);
4995 // Call corresponding ConfigAccess protocol to route settings
4997 Status
= gBS
->HandleProtocol (
4999 &gEfiHiiConfigAccessProtocolGuid
,
5000 (VOID
**) &ConfigAccess
5002 if (EFI_ERROR (Status
)) {
5003 *Progress
= StringPtr
;
5004 FreePool (ConfigResp
);
5005 return EFI_NOT_FOUND
;
5008 Status
= ConfigAccess
->RouteConfig (
5014 if (EFI_ERROR (Status
)) {
5015 ASSERT (AccessProgress
!= NULL
);
5017 // AccessProgress indicates the parsing progress on <ConfigResp>.
5018 // Map it to the progress on <MultiConfigResp> then return it.
5020 *Progress
= StrStr (StringPtr
, AccessProgress
);
5022 FreePool (ConfigResp
);
5026 FreePool (ConfigResp
);
5030 // Go to next <ConfigResp> (skip '&').
5032 StringPtr
+= Length
;
5033 if (*StringPtr
== 0) {
5034 *Progress
= StringPtr
;
5047 This helper function is to be called by drivers to map configuration data
5048 stored in byte array ("block") formats such as UEFI Variables into current
5049 configuration strings.
5051 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
5053 @param ConfigRequest A null-terminated Unicode string in
5054 <ConfigRequest> format.
5055 @param Block Array of bytes defining the block's configuration.
5056 @param BlockSize Length in bytes of Block.
5057 @param Config Filled-in configuration string. String allocated
5058 by the function. Returned only if call is
5059 successful. It is <ConfigResp> string format.
5060 @param Progress A pointer to a string filled in with the offset of
5061 the most recent & before the first failing
5062 name/value pair (or the beginning of the string if
5063 the failure is in the first name / value pair) or
5064 the terminating NULL if all was successful.
5066 @retval EFI_SUCCESS The request succeeded. Progress points to the null
5067 terminator at the end of the ConfigRequest
5069 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress
5070 points to the first character of ConfigRequest.
5071 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigRequest or
5072 Block parameter would result in this type of
5073 error. Progress points to the first character of
5075 @retval EFI_DEVICE_ERROR Block not large enough. Progress undefined.
5076 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted string.
5077 Block is left updated and Progress points at
5078 the "&" preceding the first non-<BlockName>.
5084 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
5085 IN CONST EFI_STRING ConfigRequest
,
5086 IN CONST UINT8
*Block
,
5087 IN CONST UINTN BlockSize
,
5088 OUT EFI_STRING
*Config
,
5089 OUT EFI_STRING
*Progress
5092 HII_DATABASE_PRIVATE_DATA
*Private
;
5093 EFI_STRING StringPtr
;
5101 EFI_STRING ValueStr
;
5102 EFI_STRING ConfigElement
;
5110 if (This
== NULL
|| Progress
== NULL
|| Config
== NULL
) {
5111 return EFI_INVALID_PARAMETER
;
5114 if (Block
== NULL
|| ConfigRequest
== NULL
) {
5115 *Progress
= ConfigRequest
;
5116 return EFI_INVALID_PARAMETER
;
5120 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
5121 ASSERT (Private
!= NULL
);
5123 StringPtr
= ConfigRequest
;
5126 ConfigElement
= NULL
;
5129 // Allocate a fix length of memory to store Results. Reallocate memory for
5130 // Results if this fix length is insufficient.
5132 *Config
= (EFI_STRING
) AllocateZeroPool (MAX_STRING_LENGTH
);
5133 if (*Config
== NULL
) {
5134 return EFI_OUT_OF_RESOURCES
;
5140 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
5141 *Progress
= StringPtr
;
5142 Status
= EFI_INVALID_PARAMETER
;
5145 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"PATH=", StrLen (L
"PATH=")) != 0) {
5148 if (*StringPtr
== 0) {
5149 *Progress
= StringPtr
- 1;
5150 Status
= EFI_INVALID_PARAMETER
;
5154 while (*StringPtr
!= L
'&' && *StringPtr
!= 0) {
5157 if (*StringPtr
== 0) {
5158 *Progress
= StringPtr
;
5160 AppendToMultiString(Config
, ConfigRequest
);
5161 HiiToLower (*Config
);
5171 // Copy <ConfigHdr> and an additional '&' to <ConfigResp>
5173 TemChar
= *StringPtr
;
5175 AppendToMultiString(Config
, ConfigRequest
);
5176 *StringPtr
= TemChar
;
5179 // Parse each <RequestElement> if exists
5180 // Only <BlockName> format is supported by this help function.
5181 // <BlockName> ::= 'OFFSET='<Number>&'WIDTH='<Number>
5183 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"OFFSET=", StrLen (L
"OFFSET=")) == 0) {
5185 // Back up the header of one <BlockName>
5189 StringPtr
+= StrLen (L
"OFFSET=");
5193 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
5194 if (EFI_ERROR (Status
)) {
5195 *Progress
= TmpPtr
- 1;
5202 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
5204 FreePool (TmpBuffer
);
5206 StringPtr
+= Length
;
5207 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
5208 *Progress
= TmpPtr
- 1;
5209 Status
= EFI_INVALID_PARAMETER
;
5212 StringPtr
+= StrLen (L
"&WIDTH=");
5217 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
5218 if (EFI_ERROR (Status
)) {
5219 *Progress
= TmpPtr
- 1;
5226 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
5228 FreePool (TmpBuffer
);
5230 StringPtr
+= Length
;
5231 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
5232 *Progress
= TmpPtr
- 1;
5233 Status
= EFI_INVALID_PARAMETER
;
5238 // Calculate Value and convert it to hex string.
5240 if (Offset
+ Width
> BlockSize
) {
5241 *Progress
= StringPtr
;
5242 Status
= EFI_DEVICE_ERROR
;
5246 Value
= (UINT8
*) AllocateZeroPool (Width
);
5247 if (Value
== NULL
) {
5248 *Progress
= ConfigRequest
;
5249 Status
= EFI_OUT_OF_RESOURCES
;
5253 CopyMem (Value
, (UINT8
*) Block
+ Offset
, Width
);
5255 Length
= Width
* 2 + 1;
5256 ValueStr
= (EFI_STRING
) AllocateZeroPool (Length
* sizeof (CHAR16
));
5257 if (ValueStr
== NULL
) {
5258 *Progress
= ConfigRequest
;
5259 Status
= EFI_OUT_OF_RESOURCES
;
5263 TemString
= ValueStr
;
5264 TemBuffer
= Value
+ Width
- 1;
5265 for (Index
= 0; Index
< Width
; Index
++, TemBuffer
--) {
5266 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
5273 // Build a ConfigElement
5275 Length
+= StringPtr
- TmpPtr
+ 1 + StrLen (L
"VALUE=");
5276 ConfigElement
= (EFI_STRING
) AllocateZeroPool (Length
* sizeof (CHAR16
));
5277 if (ConfigElement
== NULL
) {
5278 Status
= EFI_OUT_OF_RESOURCES
;
5281 CopyMem (ConfigElement
, TmpPtr
, (StringPtr
- TmpPtr
+ 1) * sizeof (CHAR16
));
5282 if (*StringPtr
== 0) {
5283 *(ConfigElement
+ (StringPtr
- TmpPtr
)) = L
'&';
5285 *(ConfigElement
+ (StringPtr
- TmpPtr
) + 1) = 0;
5286 StrCatS (ConfigElement
, Length
, L
"VALUE=");
5287 StrCatS (ConfigElement
, Length
, ValueStr
);
5289 AppendToMultiString (Config
, ConfigElement
);
5291 FreePool (ConfigElement
);
5292 FreePool (ValueStr
);
5293 ConfigElement
= NULL
;
5297 // If '\0', parsing is finished. Otherwise skip '&' to continue
5299 if (*StringPtr
== 0) {
5302 AppendToMultiString (Config
, L
"&");
5307 if (*StringPtr
!= 0) {
5308 *Progress
= StringPtr
- 1;
5309 Status
= EFI_INVALID_PARAMETER
;
5313 HiiToLower (*Config
);
5314 *Progress
= StringPtr
;
5318 if (*Config
!= NULL
) {
5322 if (ValueStr
!= NULL
) {
5323 FreePool (ValueStr
);
5325 if (Value
!= NULL
) {
5328 if (ConfigElement
!= NULL
) {
5329 FreePool (ConfigElement
);
5338 This helper function is to be called by drivers to map configuration strings
5339 to configurations stored in byte array ("block") formats such as UEFI Variables.
5341 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
5343 @param ConfigResp A null-terminated Unicode string in <ConfigResp>
5345 @param Block A possibly null array of bytes representing the
5346 current block. Only bytes referenced in the
5347 ConfigResp string in the block are modified. If
5348 this parameter is null or if the *BlockSize
5349 parameter is (on input) shorter than required by
5350 the Configuration string, only the BlockSize
5351 parameter is updated and an appropriate status
5352 (see below) is returned.
5353 @param BlockSize The length of the Block in units of UINT8. On
5354 input, this is the size of the Block. On output,
5355 if successful, contains the largest index of the
5356 modified byte in the Block, or the required buffer
5357 size if the Block is not large enough.
5358 @param Progress On return, points to an element of the ConfigResp
5359 string filled in with the offset of the most
5360 recent '&' before the first failing name / value
5361 pair (or the beginning of the string if the
5362 failure is in the first name / value pair) or the
5363 terminating NULL if all was successful.
5365 @retval EFI_SUCCESS The request succeeded. Progress points to the null
5366 terminator at the end of the ConfigResp string.
5367 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress
5368 points to the first character of ConfigResp.
5369 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigResp or
5370 Block parameter would result in this type of
5371 error. Progress points to the first character of
5373 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted name /
5374 value pair. Block is left updated and
5375 Progress points at the '&' preceding the first
5377 @retval EFI_BUFFER_TOO_SMALL Block not large enough. Progress undefined.
5378 BlockSize is updated with the required buffer size.
5379 @retval EFI_NOT_FOUND Target for the specified routing data was not found.
5380 Progress points to the "G" in "GUID" of the errant
5387 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
5388 IN CONST EFI_STRING ConfigResp
,
5389 IN OUT UINT8
*Block
,
5390 IN OUT UINTN
*BlockSize
,
5391 OUT EFI_STRING
*Progress
5394 HII_DATABASE_PRIVATE_DATA
*Private
;
5395 EFI_STRING StringPtr
;
5408 if (This
== NULL
|| BlockSize
== NULL
|| Progress
== NULL
) {
5409 return EFI_INVALID_PARAMETER
;
5412 *Progress
= ConfigResp
;
5413 if (ConfigResp
== NULL
) {
5414 return EFI_INVALID_PARAMETER
;
5417 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
5418 ASSERT (Private
!= NULL
);
5420 StringPtr
= ConfigResp
;
5421 BufferSize
= *BlockSize
;
5428 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
5429 *Progress
= StringPtr
;
5430 Status
= EFI_INVALID_PARAMETER
;
5433 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"PATH=", StrLen (L
"PATH=")) != 0) {
5436 if (*StringPtr
== 0) {
5437 *Progress
= StringPtr
;
5438 Status
= EFI_INVALID_PARAMETER
;
5442 while (*StringPtr
!= L
'&' && *StringPtr
!= 0) {
5445 if (*StringPtr
== 0) {
5446 *Progress
= StringPtr
;
5447 Status
= EFI_INVALID_PARAMETER
;
5452 // Parse each <ConfigElement> if exists
5453 // Only '&'<BlockConfig> format is supported by this help function.
5454 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE='<Number>
5456 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) == 0) {
5458 StringPtr
+= StrLen (L
"&OFFSET=");
5462 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
5463 if (EFI_ERROR (Status
)) {
5471 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
5473 FreePool (TmpBuffer
);
5475 StringPtr
+= Length
;
5476 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
5478 Status
= EFI_INVALID_PARAMETER
;
5481 StringPtr
+= StrLen (L
"&WIDTH=");
5486 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
5487 if (EFI_ERROR (Status
)) {
5495 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
5497 FreePool (TmpBuffer
);
5499 StringPtr
+= Length
;
5500 if (StrnCmp (StringPtr
, L
"&VALUE=", StrLen (L
"&VALUE=")) != 0) {
5502 Status
= EFI_INVALID_PARAMETER
;
5505 StringPtr
+= StrLen (L
"&VALUE=");
5510 Status
= GetValueOfNumber (StringPtr
, &Value
, &Length
);
5511 if (EFI_ERROR (Status
)) {
5516 StringPtr
+= Length
;
5517 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
5519 Status
= EFI_INVALID_PARAMETER
;
5524 // Update the Block with configuration info
5526 if ((Block
!= NULL
) && (Offset
+ Width
<= BufferSize
)) {
5527 CopyMem (Block
+ Offset
, Value
, Width
);
5529 if (Offset
+ Width
> MaxBlockSize
) {
5530 MaxBlockSize
= Offset
+ Width
;
5537 // If '\0', parsing is finished.
5539 if (*StringPtr
== 0) {
5545 // The input string is not ConfigResp format, return error.
5547 if (*StringPtr
!= 0) {
5548 *Progress
= StringPtr
;
5549 Status
= EFI_INVALID_PARAMETER
;
5553 *Progress
= StringPtr
+ StrLen (StringPtr
);
5554 *BlockSize
= MaxBlockSize
- 1;
5556 if (MaxBlockSize
> BufferSize
) {
5557 *BlockSize
= MaxBlockSize
;
5558 if (Block
!= NULL
) {
5559 return EFI_BUFFER_TOO_SMALL
;
5563 if (Block
== NULL
) {
5564 *Progress
= ConfigResp
;
5565 return EFI_INVALID_PARAMETER
;
5572 if (Value
!= NULL
) {
5580 This helper function is to be called by drivers to extract portions of
5581 a larger configuration string.
5583 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
5585 @param Configuration A null-terminated Unicode string in
5586 <MultiConfigAltResp> format.
5587 @param Guid A pointer to the GUID value to search for in the
5588 routing portion of the ConfigResp string when
5589 retrieving the requested data. If Guid is NULL,
5590 then all GUID values will be searched for.
5591 @param Name A pointer to the NAME value to search for in the
5592 routing portion of the ConfigResp string when
5593 retrieving the requested data. If Name is NULL,
5594 then all Name values will be searched for.
5595 @param DevicePath A pointer to the PATH value to search for in the
5596 routing portion of the ConfigResp string when
5597 retrieving the requested data. If DevicePath is
5598 NULL, then all DevicePath values will be searched
5600 @param AltCfgId A pointer to the ALTCFG value to search for in the
5601 routing portion of the ConfigResp string when
5602 retrieving the requested data. If this parameter
5603 is NULL, then the current setting will be
5605 @param AltCfgResp A pointer to a buffer which will be allocated by
5606 the function which contains the retrieved string
5607 as requested. This buffer is only allocated if
5608 the call was successful. It is <ConfigResp> format.
5610 @retval EFI_SUCCESS The request succeeded. The requested data was
5611 extracted and placed in the newly allocated
5613 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate AltCfgResp.
5614 @retval EFI_INVALID_PARAMETER Any parameter is invalid.
5615 @retval EFI_NOT_FOUND Target for the specified routing data was not
5622 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
5623 IN CONST EFI_STRING Configuration
,
5624 IN CONST EFI_GUID
*Guid
,
5625 IN CONST EFI_STRING Name
,
5626 IN CONST EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
5627 IN CONST UINT16
*AltCfgId
,
5628 OUT EFI_STRING
*AltCfgResp
5632 EFI_STRING StringPtr
;
5633 EFI_STRING HdrStart
;
5640 EFI_STRING AltIdStr
;
5657 if (This
== NULL
|| Configuration
== NULL
|| AltCfgResp
== NULL
) {
5658 return EFI_INVALID_PARAMETER
;
5661 StringPtr
= Configuration
;
5662 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
5663 return EFI_INVALID_PARAMETER
;
5667 // Generate the sub string for later matching.
5669 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*) Guid
, 1, &GuidStr
);
5672 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) DevicePath
),
5673 (VOID
*) DevicePath
,
5677 if (AltCfgId
!= NULL
) {
5678 GenerateSubStr (L
"ALTCFG=", sizeof (UINT16
), (VOID
*) AltCfgId
, 3, &AltIdStr
);
5681 GenerateSubStr (L
"NAME=", StrLen (Name
) * sizeof (CHAR16
), (VOID
*) Name
, 2, &NameStr
);
5683 GenerateSubStr (L
"NAME=", 0, NULL
, 2, &NameStr
);
5686 while (*StringPtr
!= 0) {
5688 // Try to match the GUID
5691 TmpPtr
= StrStr (StringPtr
, GuidStr
);
5692 if (TmpPtr
== NULL
) {
5693 Status
= EFI_NOT_FOUND
;
5699 // Jump to <NameHdr>
5702 StringPtr
= TmpPtr
+ StrLen (GuidStr
);
5704 StringPtr
= StrStr (TmpPtr
, L
"NAME=");
5705 if (StringPtr
== NULL
) {
5706 Status
= EFI_NOT_FOUND
;
5714 // Try to match the NAME
5716 if (GuidFlag
&& !NameFlag
) {
5717 if (StrnCmp (StringPtr
, NameStr
, StrLen (NameStr
)) != 0) {
5721 // Jump to <PathHdr>
5724 StringPtr
+= StrLen (NameStr
);
5726 StringPtr
= StrStr (StringPtr
, L
"PATH=");
5727 if (StringPtr
== NULL
) {
5728 Status
= EFI_NOT_FOUND
;
5737 // Try to match the DevicePath
5739 if (GuidFlag
&& NameFlag
&& !PathFlag
) {
5740 if (StrnCmp (StringPtr
, PathStr
, StrLen (PathStr
)) != 0) {
5745 // Jump to '&' before <DescHdr> or <ConfigBody>
5747 if (DevicePath
!= NULL
) {
5748 StringPtr
+= StrLen (PathStr
);
5750 StringPtr
= StrStr (StringPtr
, L
"&");
5751 if (StringPtr
== NULL
) {
5752 Status
= EFI_NOT_FOUND
;
5763 // Try to match the AltCfgId
5765 if (GuidFlag
&& NameFlag
&& PathFlag
) {
5766 if (AltCfgId
== NULL
) {
5768 // Return Current Setting when AltCfgId is NULL.
5770 Status
= OutputConfigBody (StringPtr
, &Result
);
5774 // Search the <ConfigAltResp> to get the <AltResp> with AltCfgId.
5776 if (StrnCmp (StringPtr
, AltIdStr
, StrLen (AltIdStr
)) != 0) {
5782 // Skip AltIdStr and &
5784 StringPtr
= StringPtr
+ StrLen (AltIdStr
);
5785 Status
= OutputConfigBody (StringPtr
, &Result
);
5791 Status
= EFI_NOT_FOUND
;
5795 if (!EFI_ERROR (Status
) && (Result
!= NULL
)) {
5797 // Copy the <ConfigHdr> and <ConfigBody>
5799 Length
= HdrEnd
- HdrStart
+ StrLen (Result
) + 1;
5800 *AltCfgResp
= AllocateZeroPool (Length
* sizeof (CHAR16
));
5801 if (*AltCfgResp
== NULL
) {
5802 Status
= EFI_OUT_OF_RESOURCES
;
5804 StrnCpyS (*AltCfgResp
, Length
, HdrStart
, HdrEnd
- HdrStart
);
5805 StrCatS (*AltCfgResp
, Length
, Result
);
5806 Status
= EFI_SUCCESS
;
5810 if (GuidStr
!= NULL
) {
5813 if (NameStr
!= NULL
) {
5816 if (PathStr
!= NULL
) {
5819 if (AltIdStr
!= NULL
) {
5820 FreePool (AltIdStr
);
5822 if (Result
!= NULL
) {