2 Implementation of interfaces function for EFI_HII_CONFIG_ROUTING_PROTOCOL.
4 Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
9 #include "HiiDatabase.h"
10 extern HII_DATABASE_PRIVATE_DATA mPrivate
;
13 Calculate the number of Unicode characters of the incoming Configuration string,
14 not including NULL terminator.
16 This is a internal function.
18 @param String String in <MultiConfigRequest> or
19 <MultiConfigResp> format.
21 @return The number of Unicode characters.
25 CalculateConfigStringLen (
32 // "GUID=" should be the first element of incoming string.
34 ASSERT (String
!= NULL
);
35 ASSERT (StrnCmp (String
, L
"GUID=", StrLen (L
"GUID=")) == 0);
38 // The beginning of next <ConfigRequest>/<ConfigResp> should be "&GUID=".
39 // Will meet '\0' if there is only one <ConfigRequest>/<ConfigResp>.
41 TmpPtr
= StrStr (String
, L
"&GUID=");
43 return StrLen (String
);
46 return (TmpPtr
- String
);
50 Convert the hex UNICODE %02x encoding of a UEFI device path to binary
51 from <PathHdr> of <ConfigHdr>.
53 This is a internal function.
55 @param String UEFI configuration string
56 @param DevicePathData Binary of a UEFI device path.
58 @retval EFI_NOT_FOUND The device path is not invalid.
59 @retval EFI_INVALID_PARAMETER Any incoming parameter is invalid.
60 @retval EFI_OUT_OF_RESOURCES Lake of resources to store necessary structures.
61 @retval EFI_SUCCESS The device path is retrieved and translated to
68 OUT UINT8
**DevicePathData
73 UINT8
*DevicePathBuffer
;
77 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
79 if ((String
== NULL
) || (DevicePathData
== NULL
)) {
80 return EFI_INVALID_PARAMETER
;
84 // Find the 'PATH=' of <PathHdr> and skip it.
86 for ( ; (*String
!= 0 && StrnCmp (String
, L
"PATH=", StrLen (L
"PATH=")) != 0); String
++) {
90 return EFI_INVALID_PARAMETER
;
94 // Check whether path data does exist.
96 String
+= StrLen (L
"PATH=");
98 return EFI_INVALID_PARAMETER
;
104 // The content between 'PATH=' of <ConfigHdr> and '&' of next element
105 // or '\0' (end of configuration string) is the UNICODE %02x bytes encoding
106 // of UEFI device path.
108 for (Length
= 0; *String
!= 0 && *String
!= L
'&'; String
++, Length
++) {
112 // Check DevicePath Length
114 if (((Length
+ 1) / 2) < sizeof (EFI_DEVICE_PATH_PROTOCOL
)) {
115 return EFI_NOT_FOUND
;
119 // The data in <PathHdr> is encoded as hex UNICODE %02x bytes in the same order
120 // as the device path resides in RAM memory.
121 // Translate the data into binary.
123 DevicePathBuffer
= (UINT8
*)AllocateZeroPool ((Length
+ 1) / 2);
124 if (DevicePathBuffer
== NULL
) {
125 return EFI_OUT_OF_RESOURCES
;
129 // Convert DevicePath
131 ZeroMem (TemStr
, sizeof (TemStr
));
132 for (Index
= 0; Index
< Length
; Index
++) {
133 TemStr
[0] = PathHdr
[Index
];
134 DigitUint8
= (UINT8
)StrHexToUint64 (TemStr
);
135 if ((Index
& 1) == 0) {
136 DevicePathBuffer
[Index
/2] = DigitUint8
;
138 DevicePathBuffer
[Index
/2] = (UINT8
)((DevicePathBuffer
[Index
/2] << 4) + DigitUint8
);
143 // Validate DevicePath
145 DevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*)DevicePathBuffer
;
146 while (!IsDevicePathEnd (DevicePath
)) {
147 if ((DevicePath
->Type
== 0) || (DevicePath
->SubType
== 0) || (DevicePathNodeLength (DevicePath
) < sizeof (EFI_DEVICE_PATH_PROTOCOL
))) {
149 // Invalid device path
151 FreePool (DevicePathBuffer
);
152 return EFI_NOT_FOUND
;
155 DevicePath
= NextDevicePathNode (DevicePath
);
159 // return the device path
161 *DevicePathData
= DevicePathBuffer
;
166 Converts the unicode character of the string from uppercase to lowercase.
167 This is a internal function.
169 @param ConfigString String to be converted
175 IN EFI_STRING ConfigString
181 ASSERT (ConfigString
!= NULL
);
184 // Convert all hex digits in range [A-F] in the configuration header to [a-f]
186 for (String
= ConfigString
, Lower
= FALSE
; *String
!= L
'\0'; String
++) {
187 if (*String
== L
'=') {
189 } else if (*String
== L
'&') {
191 } else if (Lower
&& (*String
>= L
'A') && (*String
<= L
'F')) {
192 *String
= (CHAR16
)(*String
- L
'A' + L
'a');
200 Generate a sub string then output it.
202 This is a internal function.
204 @param String A constant string which is the prefix of the to be
205 generated string, e.g. GUID=
207 @param BufferLen The length of the Buffer in bytes.
209 @param Buffer Points to a buffer which will be converted to be the
210 content of the generated string.
212 @param Flag If 1, the buffer contains data for the value of GUID or PATH stored in
213 UINT8 *; if 2, the buffer contains unicode string for the value of NAME;
214 if 3, the buffer contains other data.
216 @param SubStr Points to the output string. It's caller's
217 responsibility to free this buffer.
223 IN CONST EFI_STRING String
,
227 OUT EFI_STRING
*SubStr
232 EFI_STRING StringHeader
;
238 ASSERT (String
!= NULL
&& SubStr
!= NULL
);
240 if (Buffer
== NULL
) {
241 *SubStr
= AllocateCopyPool (StrSize (String
), String
);
242 ASSERT (*SubStr
!= NULL
);
247 // Header + Data + '&' + '\0'
249 Length
= StrLen (String
) + BufferLen
* 2 + 1 + 1;
250 Str
= AllocateZeroPool (Length
* sizeof (CHAR16
));
251 ASSERT (Str
!= NULL
);
253 StrCpyS (Str
, Length
, String
);
255 StringHeader
= Str
+ StrLen (String
);
256 TemString
= (CHAR16
*)StringHeader
;
261 // Convert Buffer to Hex String in reverse order
263 TemBuffer
= ((UINT8
*)Buffer
);
264 for (Index
= 0; Index
< BufferLen
; Index
++, TemBuffer
++) {
265 UnicodeValueToStringS (
267 sizeof (CHAR16
) * (Length
- StrnLenS (Str
, Length
)),
268 PREFIX_ZERO
| RADIX_HEX
,
272 TemString
+= StrnLenS (TemString
, Length
- StrnLenS (Str
, Length
));
278 // Check buffer is enough
280 TemName
= (CHAR16
*)Buffer
;
281 ASSERT ((BufferLen
* 2 + 1) >= (StrLen (TemName
) * 4 + 1));
283 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
285 for ( ; *TemName
!= L
'\0'; TemName
++) {
286 UnicodeValueToStringS (
288 sizeof (CHAR16
) * (Length
- StrnLenS (Str
, Length
)),
289 PREFIX_ZERO
| RADIX_HEX
,
293 TemString
+= StrnLenS (TemString
, Length
- StrnLenS (Str
, Length
));
299 // Convert Buffer to Hex String
301 TemBuffer
= ((UINT8
*)Buffer
) + BufferLen
- 1;
302 for (Index
= 0; Index
< BufferLen
; Index
++, TemBuffer
--) {
303 UnicodeValueToStringS (
305 sizeof (CHAR16
) * (Length
- StrnLenS (Str
, Length
)),
306 PREFIX_ZERO
| RADIX_HEX
,
310 TemString
+= StrnLenS (TemString
, Length
- StrnLenS (Str
, Length
));
319 // Convert the uppercase to lowercase since <HexAf> is defined in lowercase format.
321 StrCatS (Str
, Length
, L
"&");
328 Retrieve the <ConfigBody> from String then output it.
330 This is a internal function.
332 @param String A sub string of a configuration string in
333 <MultiConfigAltResp> format.
334 @param ConfigBody Points to the output string. It's caller's
335 responsibility to free this buffer.
337 @retval EFI_INVALID_PARAMETER There is no form package in current hii database.
338 @retval EFI_OUT_OF_RESOURCES Not enough memory to finish this operation.
339 @retval EFI_SUCCESS All existing storage is exported.
344 IN EFI_STRING String
,
345 OUT EFI_STRING
*ConfigBody
352 if ((String
== NULL
) || (ConfigBody
== NULL
)) {
353 return EFI_INVALID_PARAMETER
;
357 // The setting information should start OFFSET, not ALTCFG.
359 if (StrnCmp (String
, L
"&ALTCFG=", StrLen (L
"&ALTCFG=")) == 0) {
360 return EFI_INVALID_PARAMETER
;
363 TmpPtr
= StrStr (String
, L
"GUID=");
364 if (TmpPtr
== NULL
) {
366 // It is the last <ConfigResp> of the incoming configuration string.
368 Result
= AllocateCopyPool (StrSize (String
), String
);
369 if (Result
== NULL
) {
370 return EFI_OUT_OF_RESOURCES
;
372 *ConfigBody
= Result
;
377 Length
= TmpPtr
- String
;
379 return EFI_NOT_FOUND
;
382 Result
= AllocateCopyPool (Length
* sizeof (CHAR16
), String
);
383 if (Result
== NULL
) {
384 return EFI_OUT_OF_RESOURCES
;
387 *(Result
+ Length
- 1) = 0;
388 *ConfigBody
= Result
;
393 Append a string to a multi-string format.
395 This is a internal function.
397 @param MultiString String in <MultiConfigRequest>,
398 <MultiConfigAltResp>, or <MultiConfigResp>. On
399 input, the buffer length of this string is
400 MAX_STRING_LENGTH. On output, the buffer length
402 @param AppendString NULL-terminated Unicode string.
404 @retval EFI_INVALID_PARAMETER Any incoming parameter is invalid.
405 @retval EFI_SUCCESS AppendString is append to the end of MultiString
409 AppendToMultiString (
410 IN OUT EFI_STRING
*MultiString
,
411 IN EFI_STRING AppendString
414 UINTN AppendStringSize
;
415 UINTN MultiStringSize
;
418 if ((MultiString
== NULL
) || (*MultiString
== NULL
) || (AppendString
== NULL
)) {
419 return EFI_INVALID_PARAMETER
;
422 AppendStringSize
= StrSize (AppendString
);
423 MultiStringSize
= StrSize (*MultiString
);
424 MaxLen
= MAX_STRING_LENGTH
/ sizeof (CHAR16
);
427 // Enlarge the buffer each time when length exceeds MAX_STRING_LENGTH.
429 if ((MultiStringSize
+ AppendStringSize
> MAX_STRING_LENGTH
) ||
430 (MultiStringSize
> MAX_STRING_LENGTH
))
432 *MultiString
= (EFI_STRING
)ReallocatePool (
434 MultiStringSize
+ AppendStringSize
,
435 (VOID
*)(*MultiString
)
437 MaxLen
= (MultiStringSize
+ AppendStringSize
) / sizeof (CHAR16
);
438 ASSERT (*MultiString
!= NULL
);
442 // Append the incoming string
444 StrCatS (*MultiString
, MaxLen
, AppendString
);
450 Get the value of <Number> in <BlockConfig> format, i.e. the value of OFFSET
452 <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>
454 This is a internal function.
456 @param StringPtr String in <BlockConfig> format and points to the
457 first character of <Number>.
458 @param Number The output value. Caller takes the responsibility
460 @param Len Length of the <Number>, in characters.
462 @retval EFI_OUT_OF_RESOURCES Insufficient resources to store necessary
464 @retval EFI_SUCCESS Value of <Number> is outputted in Number
470 IN EFI_STRING StringPtr
,
484 if ((StringPtr
== NULL
) || (*StringPtr
== L
'\0') || (Number
== NULL
) || (Len
== NULL
)) {
485 return EFI_INVALID_PARAMETER
;
491 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
495 *Len
= StringPtr
- TmpPtr
;
498 Str
= (EFI_STRING
)AllocateZeroPool (Length
* sizeof (CHAR16
));
500 Status
= EFI_OUT_OF_RESOURCES
;
504 CopyMem (Str
, TmpPtr
, *Len
* sizeof (CHAR16
));
505 *(Str
+ *Len
) = L
'\0';
507 Length
= (Length
+ 1) / 2;
508 Buf
= (UINT8
*)AllocateZeroPool (Length
);
510 Status
= EFI_OUT_OF_RESOURCES
;
515 ZeroMem (TemStr
, sizeof (TemStr
));
516 for (Index
= 0; Index
< Length
; Index
++) {
517 TemStr
[0] = Str
[Length
- Index
- 1];
518 DigitUint8
= (UINT8
)StrHexToUint64 (TemStr
);
519 if ((Index
& 1) == 0) {
520 Buf
[Index
/2] = DigitUint8
;
522 Buf
[Index
/2] = (UINT8
)((DigitUint8
<< 4) + Buf
[Index
/2]);
527 Status
= EFI_SUCCESS
;
538 To find the BlockName in the string with same value.
540 @param String Pointer to a Null-terminated Unicode string.
541 @param BlockName Pointer to a Null-terminated Unicode string to search for.
542 @param Buffer Pointer to the value correspond to the BlockName.
543 @param Found The Block whether has been found.
544 @param BufferLen The length of the buffer.
546 @retval EFI_OUT_OF_RESOURCES Insufficient resources to store necessary structures.
547 @retval EFI_SUCCESS The function finishes successfully.
551 FindSameBlockElement (
552 IN EFI_STRING String
,
553 IN EFI_STRING BlockName
,
566 BlockPtr
= StrStr (String
, BlockName
);
568 while (BlockPtr
!= NULL
) {
569 BlockPtr
+= StrLen (BlockName
);
570 Status
= GetValueOfNumber (BlockPtr
, &TempBuffer
, &Length
);
571 if (EFI_ERROR (Status
)) {
575 ASSERT (TempBuffer
!= NULL
);
576 if ((BufferLen
== Length
) && (0 == CompareMem (Buffer
, TempBuffer
, Length
))) {
578 FreePool (TempBuffer
);
582 FreePool (TempBuffer
);
584 BlockPtr
= StrStr (BlockPtr
+ 1, BlockName
);
592 Compare the <AltResp> in ConfigAltResp and DefaultAltCfgResp, if the <AltResp>
593 in DefaultAltCfgResp but not in ConfigAltResp,add it to the ConfigAltResp.
595 @param DefaultAltCfgResp Pointer to a null-terminated Unicode string in
596 <MultiConfigAltResp> format. The default value
597 string may contain more than one ConfigAltResp
598 string for the different varstore buffer.
599 @param ConfigAltResp Pointer to a null-terminated Unicode string in
600 <ConfigAltResp> format.
601 @param AltConfigHdr Pointer to a Unicode string in <AltConfigHdr> format.
602 @param ConfigAltRespChanged Whether the ConfigAltResp has been changed.
604 @retval EFI_OUT_OF_RESOURCES Insufficient resources to store necessary structures.
605 @retval EFI_SUCCESS The function finishes successfully.
609 CompareBlockElementDefault (
610 IN EFI_STRING DefaultAltCfgResp
,
611 IN OUT EFI_STRING
*ConfigAltResp
,
612 IN EFI_STRING AltConfigHdr
,
613 IN OUT BOOLEAN
*ConfigAltRespChanged
618 EFI_STRING BlockPtrStart
;
619 EFI_STRING StringPtr
;
620 EFI_STRING AppendString
;
621 EFI_STRING AltConfigHdrPtr
;
631 // Make BlockPtr point to the first <BlockConfig> with AltConfigHdr in DefaultAltCfgResp.
633 AltConfigHdrPtr
= StrStr (DefaultAltCfgResp
, AltConfigHdr
);
634 ASSERT (AltConfigHdrPtr
!= NULL
);
635 BlockPtr
= StrStr (AltConfigHdrPtr
, L
"&OFFSET=");
637 // Make StringPtr point to the AltConfigHdr in ConfigAltResp.
639 StringPtr
= StrStr (*ConfigAltResp
, AltConfigHdr
);
640 ASSERT (StringPtr
!= NULL
);
642 while (BlockPtr
!= NULL
) {
644 // Find the "&OFFSET=<Number>" block and get the value of the Number with AltConfigHdr in DefaultAltCfgResp.
646 BlockPtrStart
= BlockPtr
;
647 BlockPtr
+= StrLen (L
"&OFFSET=");
648 Status
= GetValueOfNumber (BlockPtr
, &TempBuffer
, &OffsetLength
);
649 if (EFI_ERROR (Status
)) {
650 Status
= EFI_OUT_OF_RESOURCES
;
655 // To find the same "&OFFSET=<Number>" block in ConfigAltResp.
657 Status
= FindSameBlockElement (StringPtr
, L
"&OFFSET=", TempBuffer
, &FoundOffset
, OffsetLength
);
658 if (TempBuffer
!= NULL
) {
659 FreePool (TempBuffer
);
663 if (EFI_ERROR (Status
)) {
664 Status
= EFI_OUT_OF_RESOURCES
;
670 // Don't find the same "&OFFSET=<Number>" block in ConfigAltResp.
671 // Calculate the size of <BlockConfig>.
672 // <BlockConfig>::='OFFSET='<Number>'&WIDTH='<Number>'&VALUE='<Number>.
674 BlockPtr
= StrStr (BlockPtr
+ 1, L
"&OFFSET=");
675 if (BlockPtr
!= NULL
) {
676 AppendSize
= (BlockPtr
- BlockPtrStart
) * sizeof (CHAR16
);
678 AppendSize
= StrSize (BlockPtrStart
);
682 // Copy the <BlockConfig> to AppendString.
684 if (AppendString
== NULL
) {
685 AppendString
= (EFI_STRING
)AllocateZeroPool (AppendSize
+ sizeof (CHAR16
));
686 StrnCatS (AppendString
, AppendSize
/ sizeof (CHAR16
) + 1, BlockPtrStart
, AppendSize
/ sizeof (CHAR16
));
688 TotalSize
= StrSize (AppendString
) + AppendSize
+ sizeof (CHAR16
);
689 AppendString
= (EFI_STRING
)ReallocatePool (
690 StrSize (AppendString
),
694 if (AppendString
== NULL
) {
695 Status
= EFI_OUT_OF_RESOURCES
;
699 StrnCatS (AppendString
, TotalSize
/ sizeof (CHAR16
), BlockPtrStart
, AppendSize
/ sizeof (CHAR16
));
703 // To find next "&OFFSET=<Number>" block with AltConfigHdr in DefaultAltCfgResp.
705 BlockPtr
= StrStr (BlockPtr
+ 1, L
"&OFFSET=");
709 if (AppendString
!= NULL
) {
711 // Reallocate ConfigAltResp to copy the AppendString.
713 TotalSize
= StrSize (*ConfigAltResp
) + StrSize (AppendString
) + sizeof (CHAR16
);
714 *ConfigAltResp
= (EFI_STRING
)ReallocatePool (
715 StrSize (*ConfigAltResp
),
719 if (*ConfigAltResp
== NULL
) {
720 Status
= EFI_OUT_OF_RESOURCES
;
724 StrCatS (*ConfigAltResp
, TotalSize
/ sizeof (CHAR16
), AppendString
);
725 *ConfigAltRespChanged
= TRUE
;
728 Status
= EFI_SUCCESS
;
731 if (AppendString
!= NULL
) {
732 FreePool (AppendString
);
739 Compare the <AltResp> in ConfigAltResp and DefaultAltCfgResp, if the <AltResp>
740 in DefaultAltCfgResp but not in ConfigAltResp,add it to the ConfigAltResp.
742 @param DefaultAltCfgResp Pointer to a null-terminated Unicode string in
743 <MultiConfigAltResp> format. The default value
744 string may contain more than one ConfigAltResp
745 string for the different varstore buffer.
746 @param ConfigAltResp Pointer to a null-terminated Unicode string in
747 <ConfigAltResp> format.
748 @param AltConfigHdr Pointer to a Unicode string in <AltConfigHdr> format.
749 @param ConfigAltRespChanged Whether the ConfigAltResp has been changed.
751 @retval EFI_OUT_OF_RESOURCES Insufficient resources to store necessary structures.
752 @retval EFI_SUCCESS The function finishes successfully.
756 CompareNameElementDefault (
757 IN EFI_STRING DefaultAltCfgResp
,
758 IN OUT EFI_STRING
*ConfigAltResp
,
759 IN EFI_STRING AltConfigHdr
,
760 IN OUT BOOLEAN
*ConfigAltRespChanged
764 EFI_STRING NvConfigPtr
;
765 EFI_STRING NvConfigStart
;
766 EFI_STRING NvConfigValuePtr
;
767 EFI_STRING StringPtr
;
768 EFI_STRING NvConfigExist
;
769 EFI_STRING AppendString
;
775 NvConfigExist
= NULL
;
777 // Make NvConfigPtr point to the first <NvConfig> with AltConfigHdr in DefaultAltCfgResp.
779 NvConfigPtr
= StrStr (DefaultAltCfgResp
, AltConfigHdr
);
780 ASSERT (NvConfigPtr
!= NULL
);
781 NvConfigPtr
= StrStr (NvConfigPtr
+ StrLen (AltConfigHdr
), L
"&");
783 // Make StringPtr point to the first <NvConfig> with AltConfigHdr in ConfigAltResp.
785 StringPtr
= StrStr (*ConfigAltResp
, AltConfigHdr
);
786 ASSERT (StringPtr
!= NULL
);
787 StringPtr
= StrStr (StringPtr
+ StrLen (AltConfigHdr
), L
"&");
788 ASSERT (StringPtr
!= NULL
);
790 while (NvConfigPtr
!= NULL
) {
792 // <NvConfig> ::= <Label>'='<String> | <Label>'='<Number>.
793 // Get the <Label> with AltConfigHdr in DefaultAltCfgResp.
795 NvConfigStart
= NvConfigPtr
;
796 NvConfigValuePtr
= StrStr (NvConfigPtr
+ 1, L
"=");
797 ASSERT (NvConfigValuePtr
!= NULL
);
798 TempChar
= *NvConfigValuePtr
;
799 *NvConfigValuePtr
= L
'\0';
801 // Get the <Label> with AltConfigHdr in ConfigAltResp.
803 NvConfigExist
= StrStr (StringPtr
, NvConfigPtr
);
804 if (NvConfigExist
== NULL
) {
806 // Don't find same <Label> in ConfigAltResp.
807 // Calculate the size of <NvConfig>.
809 *NvConfigValuePtr
= TempChar
;
810 NvConfigPtr
= StrStr (NvConfigPtr
+ 1, L
"&");
811 if (NvConfigPtr
!= NULL
) {
812 AppendSize
= (NvConfigPtr
- NvConfigStart
) * sizeof (CHAR16
);
814 AppendSize
= StrSize (NvConfigStart
);
818 // Copy the <NvConfig> to AppendString.
820 if (AppendString
== NULL
) {
821 AppendString
= (EFI_STRING
)AllocateZeroPool (AppendSize
+ sizeof (CHAR16
));
822 StrnCatS (AppendString
, AppendSize
/ sizeof (CHAR16
) + 1, NvConfigStart
, AppendSize
/ sizeof (CHAR16
));
824 TotalSize
= StrSize (AppendString
) + AppendSize
+ sizeof (CHAR16
);
825 AppendString
= (EFI_STRING
)ReallocatePool (
826 StrSize (AppendString
),
830 if (AppendString
== NULL
) {
831 Status
= EFI_OUT_OF_RESOURCES
;
835 StrnCatS (AppendString
, TotalSize
/ sizeof (CHAR16
), NvConfigStart
, AppendSize
/ sizeof (CHAR16
));
839 // To find next <Label> in DefaultAltCfgResp.
841 *NvConfigValuePtr
= TempChar
;
842 NvConfigPtr
= StrStr (NvConfigPtr
+ 1, L
"&");
846 if (AppendString
!= NULL
) {
848 // Reallocate ConfigAltResp to copy the AppendString.
850 TotalSize
= StrSize (*ConfigAltResp
) + StrSize (AppendString
) + sizeof (CHAR16
);
851 *ConfigAltResp
= (EFI_STRING
)ReallocatePool (
852 StrSize (*ConfigAltResp
),
853 StrSize (*ConfigAltResp
) + StrSize (AppendString
) + sizeof (CHAR16
),
856 if (*ConfigAltResp
== NULL
) {
857 Status
= EFI_OUT_OF_RESOURCES
;
861 StrCatS (*ConfigAltResp
, TotalSize
/ sizeof (CHAR16
), AppendString
);
862 *ConfigAltRespChanged
= TRUE
;
865 Status
= EFI_SUCCESS
;
868 if (AppendString
!= NULL
) {
869 FreePool (AppendString
);
876 Compare the <AltResp> in AltCfgResp and DefaultAltCfgResp, if the <AltResp>
877 in DefaultAltCfgResp but not in AltCfgResp,add it to the AltCfgResp.
879 @param AltCfgResp Pointer to a null-terminated Unicode string in
880 <ConfigAltResp> format.
881 @param DefaultAltCfgResp Pointer to a null-terminated Unicode string in
882 <MultiConfigAltResp> format. The default value
883 string may contain more than one ConfigAltResp
884 string for the different varstore buffer.
885 @param AltConfigHdr Pointer to a Unicode string in <AltConfigHdr> format.
887 @retval EFI_OUT_OF_RESOURCES Insufficient resources to store necessary
889 @retval EFI_SUCCESS The function finishes successfully.
893 CompareAndMergeDefaultString (
894 IN OUT EFI_STRING
*AltCfgResp
,
895 IN EFI_STRING DefaultAltCfgResp
,
896 IN EFI_STRING AltConfigHdr
900 EFI_STRING AltCfgRespBackup
;
901 EFI_STRING AltConfigHdrPtr
;
902 EFI_STRING AltConfigHdrPtrNext
;
903 EFI_STRING ConfigAltResp
;
904 EFI_STRING StringPtr
;
905 EFI_STRING StringPtrNext
;
907 UINTN ReallocateSize
;
910 BOOLEAN ConfigAltRespChanged
;
912 Status
= EFI_OUT_OF_RESOURCES
;
914 AltConfigHdrPtrNext
= NULL
;
915 StringPtrNext
= NULL
;
916 ConfigAltResp
= NULL
;
917 AltCfgRespBackup
= NULL
;
920 ConfigAltRespChanged
= FALSE
;
923 // To find the <AltResp> with AltConfigHdr in DefaultAltCfgResp, ignore other <AltResp> which follow it.
925 AltConfigHdrPtr
= StrStr (DefaultAltCfgResp
, AltConfigHdr
);
926 ASSERT (AltConfigHdrPtr
!= NULL
);
927 AltConfigHdrPtrNext
= StrStr (AltConfigHdrPtr
+ 1, L
"&GUID");
928 if (AltConfigHdrPtrNext
!= NULL
) {
929 TempChar
= *AltConfigHdrPtrNext
;
930 *AltConfigHdrPtrNext
= L
'\0';
934 // To find the <AltResp> with AltConfigHdr in AltCfgResp, ignore other <AltResp> which follow it.
936 StringPtr
= StrStr (*AltCfgResp
, AltConfigHdr
);
937 ASSERT (StringPtr
!= NULL
);
938 StringPtrNext
= StrStr (StringPtr
+ 1, L
"&GUID");
939 if (StringPtrNext
!= NULL
) {
940 TempCharA
= *StringPtrNext
;
941 *StringPtrNext
= L
'\0';
945 // Copy the content of <ConfigAltResp> which contain current AltConfigHdr in AltCfgResp.
947 ConfigAltResp
= AllocateCopyPool (StrSize (*AltCfgResp
), *AltCfgResp
);
948 if (ConfigAltResp
== NULL
) {
953 // To find the <ConfigBody> with AltConfigHdr in DefaultAltCfgResp.
955 BlockPtr
= StrStr (AltConfigHdrPtr
, L
"&OFFSET=");
956 if (BlockPtr
!= NULL
) {
958 // <BlockConfig>::='OFFSET='<Number>'&WIDTH='<Number>'&VALUE='<Number> style.
959 // Call function CompareBlockElementDefault to compare the <BlockConfig> in DefaultAltCfgResp and ConfigAltResp.
960 // The ConfigAltResp which may contain the new <BlockConfig> get from DefaultAltCfgResp.
962 Status
= CompareBlockElementDefault (DefaultAltCfgResp
, &ConfigAltResp
, AltConfigHdr
, &ConfigAltRespChanged
);
963 if (EFI_ERROR (Status
)) {
968 // <NvConfig> ::= <Label>'='<String> | <Label>'='<Number> style.
969 // Call function CompareNameElementDefault to compare the <NvConfig> in DefaultAltCfgResp and ConfigAltResp.
970 // The ConfigAltResp which may contain the new <NvConfig> get from DefaultAltCfgResp.
972 Status
= CompareNameElementDefault (DefaultAltCfgResp
, &ConfigAltResp
, AltConfigHdr
, &ConfigAltRespChanged
);
973 if (EFI_ERROR (Status
)) {
979 // Restore the AltCfgResp.
981 if (StringPtrNext
!= NULL
) {
982 *StringPtrNext
= TempCharA
;
986 // If the ConfigAltResp has no change,no need to update the content in AltCfgResp.
988 if (!ConfigAltRespChanged
) {
989 Status
= EFI_SUCCESS
;
994 // ConfigAltResp has been changed, need to update the content in AltCfgResp.
996 if (StringPtrNext
!= NULL
) {
997 ReallocateSize
= StrSize (ConfigAltResp
) + StrSize (StringPtrNext
) + sizeof (CHAR16
);
999 ReallocateSize
= StrSize (ConfigAltResp
) + sizeof (CHAR16
);
1002 AltCfgRespBackup
= (EFI_STRING
)AllocateZeroPool (ReallocateSize
);
1003 if (AltCfgRespBackup
== NULL
) {
1007 StrCatS (AltCfgRespBackup
, ReallocateSize
/ sizeof (CHAR16
), ConfigAltResp
);
1008 if (StringPtrNext
!= NULL
) {
1009 StrCatS (AltCfgRespBackup
, ReallocateSize
/ sizeof (CHAR16
), StringPtrNext
);
1012 FreePool (*AltCfgResp
);
1013 *AltCfgResp
= AltCfgRespBackup
;
1015 Status
= EFI_SUCCESS
;
1018 if (ConfigAltResp
!= NULL
) {
1019 FreePool (ConfigAltResp
);
1023 // Restore the DefaultAltCfgResp.
1025 if ( AltConfigHdrPtrNext
!= NULL
) {
1026 *AltConfigHdrPtrNext
= TempChar
;
1027 AltConfigHdrPtrNext
= NULL
;
1034 This function merges DefaultAltCfgResp string into AltCfgResp string for
1035 the missing AltCfgId in AltCfgResq.
1037 @param AltCfgResp Pointer to a null-terminated Unicode string in
1038 <ConfigAltResp> format. The default value string
1039 will be merged into it.
1040 @param DefaultAltCfgResp Pointer to a null-terminated Unicode string in
1041 <MultiConfigAltResp> format. The default value
1042 string may contain more than one ConfigAltResp
1043 string for the different varstore buffer.
1045 @retval EFI_SUCCESS The merged string returns.
1046 @retval EFI_INVALID_PARAMETER *AltCfgResp is to NULL.
1050 MergeDefaultString (
1051 IN OUT EFI_STRING
*AltCfgResp
,
1052 IN EFI_STRING DefaultAltCfgResp
1055 EFI_STRING StringPtrDefault
;
1056 EFI_STRING StringPtrEnd
;
1058 EFI_STRING StringPtr
;
1059 EFI_STRING AltConfigHdr
;
1061 UINTN SizeAltCfgResp
;
1065 if (*AltCfgResp
== NULL
) {
1066 return EFI_INVALID_PARAMETER
;
1070 // Get the request ConfigHdr
1073 StringPtr
= *AltCfgResp
;
1076 // Find <ConfigHdr> GUID=...&NAME=...&PATH=...
1078 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
1079 return EFI_INVALID_PARAMETER
;
1082 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&NAME=", StrLen (L
"&NAME=")) != 0) {
1086 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&PATH=", StrLen (L
"&PATH=")) != 0) {
1090 if (*StringPtr
== L
'\0') {
1091 return EFI_INVALID_PARAMETER
;
1094 StringPtr
+= StrLen (L
"&PATH=");
1095 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
1099 HeaderLength
= StringPtr
- *AltCfgResp
;
1102 // Construct AltConfigHdr string "&<ConfigHdr>&ALTCFG=XXXX\0"
1103 // |1| StrLen (ConfigHdr) | 8 | 4 | 1 |
1105 MaxLen
= 1 + HeaderLength
+ 8 + 4 + 1;
1106 AltConfigHdr
= AllocateZeroPool (MaxLen
* sizeof (CHAR16
));
1107 if (AltConfigHdr
== NULL
) {
1108 return EFI_OUT_OF_RESOURCES
;
1111 StrCpyS (AltConfigHdr
, MaxLen
, L
"&");
1112 StrnCatS (AltConfigHdr
, MaxLen
, *AltCfgResp
, HeaderLength
);
1113 StrCatS (AltConfigHdr
, MaxLen
, L
"&ALTCFG=");
1114 HeaderLength
= StrLen (AltConfigHdr
);
1116 StringPtrDefault
= StrStr (DefaultAltCfgResp
, AltConfigHdr
);
1117 while (StringPtrDefault
!= NULL
) {
1121 StrnCatS (AltConfigHdr
, MaxLen
, StringPtrDefault
+ HeaderLength
, 4);
1122 StringPtr
= StrStr (*AltCfgResp
, AltConfigHdr
);
1125 // Append the found default value string to the input AltCfgResp
1127 if (StringPtr
== NULL
) {
1128 StringPtrEnd
= StrStr (StringPtrDefault
+ 1, L
"&GUID");
1129 SizeAltCfgResp
= StrSize (*AltCfgResp
);
1130 if (StringPtrEnd
== NULL
) {
1132 // No more default string is found.
1134 TotalSize
= SizeAltCfgResp
+ StrSize (StringPtrDefault
);
1135 *AltCfgResp
= (EFI_STRING
)ReallocatePool (
1138 (VOID
*)(*AltCfgResp
)
1140 if (*AltCfgResp
== NULL
) {
1141 FreePool (AltConfigHdr
);
1142 return EFI_OUT_OF_RESOURCES
;
1145 StrCatS (*AltCfgResp
, TotalSize
/ sizeof (CHAR16
), StringPtrDefault
);
1148 TempChar
= *StringPtrEnd
;
1149 *StringPtrEnd
= L
'\0';
1150 TotalSize
= SizeAltCfgResp
+ StrSize (StringPtrDefault
);
1151 *AltCfgResp
= (EFI_STRING
)ReallocatePool (
1154 (VOID
*)(*AltCfgResp
)
1156 if (*AltCfgResp
== NULL
) {
1157 FreePool (AltConfigHdr
);
1158 return EFI_OUT_OF_RESOURCES
;
1161 StrCatS (*AltCfgResp
, TotalSize
/ sizeof (CHAR16
), StringPtrDefault
);
1162 *StringPtrEnd
= TempChar
;
1166 // The AltCfgResp contains <AltCfgResp>.
1167 // If the <ConfigElement> in <AltCfgResp> in the DefaultAltCfgResp but not in the
1168 // related <AltCfgResp> in AltCfgResp, merge it to AltCfgResp. else no need to merge.
1170 CompareAndMergeDefaultString (AltCfgResp
, DefaultAltCfgResp
, AltConfigHdr
);
1174 // Find next AltCfg String
1176 *(AltConfigHdr
+ HeaderLength
) = L
'\0';
1177 StringPtrDefault
= StrStr (StringPtrDefault
+ 1, AltConfigHdr
);
1180 FreePool (AltConfigHdr
);
1185 This function inserts new DefaultValueData into the BlockData DefaultValue array.
1187 @param BlockData The BlockData is updated to add new default value.
1188 @param DefaultValueData The DefaultValue is added.
1192 InsertDefaultValue (
1193 IN IFR_BLOCK_DATA
*BlockData
,
1194 IN IFR_DEFAULT_DATA
*DefaultValueData
1198 IFR_DEFAULT_DATA
*DefaultValueArray
;
1199 LIST_ENTRY
*DefaultLink
;
1201 DefaultLink
= &BlockData
->DefaultValueEntry
;
1203 for (Link
= DefaultLink
->ForwardLink
; Link
!= DefaultLink
; Link
= Link
->ForwardLink
) {
1204 DefaultValueArray
= BASE_CR (Link
, IFR_DEFAULT_DATA
, Entry
);
1205 if (DefaultValueArray
->DefaultId
== DefaultValueData
->DefaultId
) {
1207 // DEFAULT_VALUE_FROM_OPCODE has high priority, DEFAULT_VALUE_FROM_DEFAULT has low priority.
1208 // When default types are DEFAULT_VALUE_FROM_OTHER_DEFAULT, the default value can be overrode.
1210 if ((DefaultValueData
->Type
> DefaultValueArray
->Type
) || ((DefaultValueData
->Type
== DefaultValueArray
->Type
) && (DefaultValueData
->Type
== DefaultValueFromOtherDefault
))) {
1212 // Update the default value array in BlockData.
1214 CopyMem (&DefaultValueArray
->Value
, &DefaultValueData
->Value
, sizeof (EFI_IFR_TYPE_VALUE
));
1215 DefaultValueArray
->Type
= DefaultValueData
->Type
;
1216 DefaultValueArray
->Cleaned
= DefaultValueData
->Cleaned
;
1224 // Insert new default value data in tail.
1226 DefaultValueArray
= AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
1227 ASSERT (DefaultValueArray
!= NULL
);
1228 CopyMem (DefaultValueArray
, DefaultValueData
, sizeof (IFR_DEFAULT_DATA
));
1229 InsertTailList (Link
, &DefaultValueArray
->Entry
);
1233 This function inserts new BlockData into the block link
1235 @param BlockLink The list entry points to block array.
1236 @param BlockData The point to BlockData is added.
1241 IN LIST_ENTRY
*BlockLink
,
1242 IN IFR_BLOCK_DATA
**BlockData
1246 IFR_BLOCK_DATA
*BlockArray
;
1247 IFR_BLOCK_DATA
*BlockSingleData
;
1249 BlockSingleData
= *BlockData
;
1251 if (BlockSingleData
->Name
!= NULL
) {
1252 InsertTailList (BlockLink
, &BlockSingleData
->Entry
);
1257 // Insert block data in its Offset and Width order.
1259 for (Link
= BlockLink
->ForwardLink
; Link
!= BlockLink
; Link
= Link
->ForwardLink
) {
1260 BlockArray
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
1261 if (BlockArray
->Offset
== BlockSingleData
->Offset
) {
1262 if ((BlockArray
->Width
> BlockSingleData
->Width
) || (BlockSingleData
->IsBitVar
&& (BlockArray
->Width
== BlockSingleData
->Width
))) {
1264 // Insert this block data in the front of block array
1266 InsertTailList (Link
, &BlockSingleData
->Entry
);
1270 if ((!BlockSingleData
->IsBitVar
) && (BlockArray
->Width
== BlockSingleData
->Width
)) {
1272 // The same block array has been added.
1274 if (BlockSingleData
!= BlockArray
) {
1275 FreePool (BlockSingleData
);
1276 *BlockData
= BlockArray
;
1281 } else if (BlockArray
->Offset
> BlockSingleData
->Offset
) {
1283 // Insert new block data in the front of block array
1285 InsertTailList (Link
, &BlockSingleData
->Entry
);
1291 // Add new block data into the tail.
1293 InsertTailList (Link
, &BlockSingleData
->Entry
);
1297 Retrieves a pointer to the a Null-terminated ASCII string containing the list
1298 of languages that an HII handle in the HII Database supports. The returned
1299 string is allocated using AllocatePool(). The caller is responsible for freeing
1300 the returned string using FreePool(). The format of the returned string follows
1301 the language format assumed the HII Database.
1303 If HiiHandle is NULL, then ASSERT().
1305 @param[in] HiiHandle A handle that was previously registered in the HII Database.
1307 @retval NULL HiiHandle is not registered in the HII database
1308 @retval NULL There are not enough resources available to retrieve the supported
1310 @retval NULL The list of supported languages could not be retrieved.
1311 @retval Other A pointer to the Null-terminated ASCII string of supported languages.
1315 GetSupportedLanguages (
1316 IN EFI_HII_HANDLE HiiHandle
1321 CHAR8 TempSupportedLanguages
;
1322 CHAR8
*SupportedLanguages
;
1324 ASSERT (HiiHandle
!= NULL
);
1327 // Retrieve the size required for the supported languages buffer.
1330 Status
= mPrivate
.HiiString
.GetLanguages (&mPrivate
.HiiString
, HiiHandle
, &TempSupportedLanguages
, &LanguageSize
);
1333 // If GetLanguages() returns EFI_SUCCESS for a zero size,
1334 // then there are no supported languages registered for HiiHandle. If GetLanguages()
1335 // returns an error other than EFI_BUFFER_TOO_SMALL, then HiiHandle is not present
1336 // in the HII Database
1338 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
1340 // Return NULL if the size can not be retrieved, or if HiiHandle is not in the HII Database
1346 // Allocate the supported languages buffer.
1348 SupportedLanguages
= AllocateZeroPool (LanguageSize
);
1349 if (SupportedLanguages
== NULL
) {
1351 // Return NULL if allocation fails.
1357 // Retrieve the supported languages string
1359 Status
= mPrivate
.HiiString
.GetLanguages (&mPrivate
.HiiString
, HiiHandle
, SupportedLanguages
, &LanguageSize
);
1360 if (EFI_ERROR (Status
)) {
1362 // Free the buffer and return NULL if the supported languages can not be retrieved.
1364 FreePool (SupportedLanguages
);
1369 // Return the Null-terminated ASCII string of supported languages
1371 return SupportedLanguages
;
1375 Retrieves a string from a string package.
1377 If HiiHandle is NULL, then ASSERT().
1378 If StringId is 0, then ASSET.
1380 @param[in] HiiHandle A handle that was previously registered in the HII Database.
1381 @param[in] StringId The identifier of the string to retrieved from the string
1382 package associated with HiiHandle.
1384 @retval NULL The string specified by StringId is not present in the string package.
1385 @retval Other The string was returned.
1390 IN EFI_HII_HANDLE HiiHandle
,
1391 IN EFI_STRING_ID StringId
1398 CHAR8
*SupportedLanguages
;
1399 CHAR8
*PlatformLanguage
;
1400 CHAR8
*BestLanguage
;
1403 ASSERT (HiiHandle
!= NULL
);
1404 ASSERT (StringId
!= 0);
1407 // Initialize all allocated buffers to NULL
1409 SupportedLanguages
= NULL
;
1410 PlatformLanguage
= NULL
;
1411 BestLanguage
= NULL
;
1416 // Get the languages that the package specified by HiiHandle supports
1418 SupportedLanguages
= GetSupportedLanguages (HiiHandle
);
1419 if (SupportedLanguages
== NULL
) {
1424 // Get the current platform language setting
1426 GetEfiGlobalVariable2 (L
"PlatformLang", (VOID
**)&PlatformLanguage
, NULL
);
1429 // Get the best matching language from SupportedLanguages
1431 BestLanguage
= GetBestLanguage (
1433 FALSE
, // RFC 4646 mode
1434 Language
, // Highest priority
1435 PlatformLanguage
!= NULL
? PlatformLanguage
: "", // Next highest priority
1436 SupportedLanguages
, // Lowest priority
1439 if (BestLanguage
== NULL
) {
1444 // Retrieve the size of the string in the string package for the BestLanguage
1447 Status
= mPrivate
.HiiString
.GetString (
1448 &mPrivate
.HiiString
,
1457 // If GetString() returns EFI_SUCCESS for a zero size,
1458 // then there are no supported languages registered for HiiHandle. If GetString()
1459 // returns an error other than EFI_BUFFER_TOO_SMALL, then HiiHandle is not present
1460 // in the HII Database
1462 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
1467 // Allocate a buffer for the return string
1469 String
= AllocateZeroPool (StringSize
);
1470 if (String
== NULL
) {
1475 // Retrieve the string from the string package
1477 Status
= mPrivate
.HiiString
.GetString (
1478 &mPrivate
.HiiString
,
1486 if (EFI_ERROR (Status
)) {
1488 // Free the buffer and return NULL if the supported languages can not be retrieved.
1496 // Free allocated buffers
1498 if (SupportedLanguages
!= NULL
) {
1499 FreePool (SupportedLanguages
);
1502 if (PlatformLanguage
!= NULL
) {
1503 FreePool (PlatformLanguage
);
1506 if (BestLanguage
!= NULL
) {
1507 FreePool (BestLanguage
);
1511 // Return the Null-terminated Unicode string
1517 This function checks VarOffset and VarWidth is in the block range.
1519 @param RequestBlockArray The block array is to be checked.
1520 @param VarOffset Offset of var to the structure
1521 @param VarWidth Width of var.
1522 @param IsNameValueType Whether this varstore is name/value varstore or not.
1523 @param HiiHandle Hii handle for this hii package.
1525 @retval TRUE This Var is in the block range.
1526 @retval FALSE This Var is not in the block range.
1530 IN IFR_BLOCK_DATA
*RequestBlockArray
,
1531 IN UINT16 VarOffset
,
1533 IN BOOLEAN IsNameValueType
,
1534 IN EFI_HII_HANDLE HiiHandle
1538 IFR_BLOCK_DATA
*BlockData
;
1542 // No Request Block array, all vars are got.
1544 if (RequestBlockArray
== NULL
) {
1549 // Check the input var is in the request block range.
1551 for (Link
= RequestBlockArray
->Entry
.ForwardLink
; Link
!= &RequestBlockArray
->Entry
; Link
= Link
->ForwardLink
) {
1552 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
1554 if (IsNameValueType
) {
1555 Name
= InternalGetString (HiiHandle
, VarOffset
);
1556 ASSERT (Name
!= NULL
);
1558 if (StrnCmp (BlockData
->Name
, Name
, StrLen (Name
)) == 0) {
1565 if ((VarOffset
>= BlockData
->Offset
) && ((VarOffset
+ VarWidth
) <= (BlockData
->Offset
+ BlockData
->Width
))) {
1575 Get form package data from data base.
1577 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
1578 @param HiiFormPackage The buffer saves the package data.
1579 @param PackageSize The buffer size of the package data.
1583 GetFormPackageData (
1584 IN HII_DATABASE_RECORD
*DataBaseRecord
,
1585 IN OUT UINT8
**HiiFormPackage
,
1586 OUT UINTN
*PackageSize
1593 if ((DataBaseRecord
== NULL
) || (HiiFormPackage
== NULL
) || (PackageSize
== NULL
)) {
1594 return EFI_INVALID_PARAMETER
;
1600 // 0. Get Hii Form Package by HiiHandle
1602 Status
= ExportFormPackages (
1604 DataBaseRecord
->Handle
,
1605 DataBaseRecord
->PackageList
,
1611 if (EFI_ERROR (Status
)) {
1615 (*HiiFormPackage
) = AllocatePool (ResultSize
);
1616 if (*HiiFormPackage
== NULL
) {
1617 Status
= EFI_OUT_OF_RESOURCES
;
1622 // Get HiiFormPackage by HiiHandle
1626 Status
= ExportFormPackages (
1628 DataBaseRecord
->Handle
,
1629 DataBaseRecord
->PackageList
,
1635 if (EFI_ERROR (Status
)) {
1636 FreePool (*HiiFormPackage
);
1639 *PackageSize
= Size
;
1645 This function parses Form Package to get the efi varstore info according to the request ConfigHdr.
1647 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
1648 @param ConfigHdr Request string ConfigHdr. If it is NULL,
1649 the first found varstore will be as ConfigHdr.
1650 @param IsEfiVarstore Whether the request storage type is efi varstore type.
1651 @param EfiVarStore The efi varstore info which will return.
1655 IN HII_DATABASE_RECORD
*DataBaseRecord
,
1656 IN EFI_STRING ConfigHdr
,
1657 OUT BOOLEAN
*IsEfiVarstore
,
1658 OUT EFI_IFR_VARSTORE_EFI
**EfiVarStore
1663 UINTN PackageOffset
;
1664 EFI_IFR_OP_HEADER
*IfrOpHdr
;
1665 CHAR16
*VarStoreName
;
1671 UINT8
*HiiFormPackage
;
1673 EFI_IFR_VARSTORE_EFI
*IfrEfiVarStore
;
1674 EFI_HII_PACKAGE_HEADER
*PackageHeader
;
1676 HiiFormPackage
= NULL
;
1678 Status
= EFI_SUCCESS
;
1682 *IsEfiVarstore
= FALSE
;
1684 Status
= GetFormPackageData (DataBaseRecord
, &HiiFormPackage
, &PackageSize
);
1685 if (EFI_ERROR (Status
)) {
1689 IfrOffset
= sizeof (EFI_HII_PACKAGE_HEADER
);
1690 PackageOffset
= IfrOffset
;
1691 PackageHeader
= (EFI_HII_PACKAGE_HEADER
*)HiiFormPackage
;
1693 while (IfrOffset
< PackageSize
) {
1695 // More than one form packages exist.
1697 if (PackageOffset
>= PackageHeader
->Length
) {
1699 // Process the new form package.
1701 PackageOffset
= sizeof (EFI_HII_PACKAGE_HEADER
);
1702 IfrOffset
+= PackageOffset
;
1703 PackageHeader
= (EFI_HII_PACKAGE_HEADER
*)(HiiFormPackage
+ IfrOffset
);
1706 IfrOpHdr
= (EFI_IFR_OP_HEADER
*)(HiiFormPackage
+ IfrOffset
);
1707 IfrOffset
+= IfrOpHdr
->Length
;
1708 PackageOffset
+= IfrOpHdr
->Length
;
1710 if (IfrOpHdr
->OpCode
== EFI_IFR_VARSTORE_EFI_OP
) {
1711 IfrEfiVarStore
= (EFI_IFR_VARSTORE_EFI
*)IfrOpHdr
;
1713 // If the length is small than the structure, this is from old efi
1714 // varstore definition. Old efi varstore get config directly from
1715 // GetVariable function.
1717 if (IfrOpHdr
->Length
< sizeof (EFI_IFR_VARSTORE_EFI
)) {
1721 NameSize
= AsciiStrSize ((CHAR8
*)IfrEfiVarStore
->Name
);
1722 VarStoreName
= AllocateZeroPool (NameSize
* sizeof (CHAR16
));
1723 if (VarStoreName
== NULL
) {
1724 Status
= EFI_OUT_OF_RESOURCES
;
1728 AsciiStrToUnicodeStrS ((CHAR8
*)IfrEfiVarStore
->Name
, VarStoreName
, NameSize
);
1730 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*)&IfrEfiVarStore
->Guid
, 1, &GuidStr
);
1731 GenerateSubStr (L
"NAME=", StrLen (VarStoreName
) * sizeof (CHAR16
), (VOID
*)VarStoreName
, 2, &NameStr
);
1732 LengthString
= StrLen (GuidStr
);
1733 LengthString
= LengthString
+ StrLen (NameStr
) + 1;
1734 TempStr
= AllocateZeroPool (LengthString
* sizeof (CHAR16
));
1735 if (TempStr
== NULL
) {
1738 FreePool (VarStoreName
);
1739 Status
= EFI_OUT_OF_RESOURCES
;
1743 StrCpyS (TempStr
, LengthString
, GuidStr
);
1744 StrCatS (TempStr
, LengthString
, NameStr
);
1745 if ((ConfigHdr
== NULL
) || (StrnCmp (ConfigHdr
, TempStr
, StrLen (TempStr
)) == 0)) {
1746 *EfiVarStore
= (EFI_IFR_VARSTORE_EFI
*)AllocateZeroPool (IfrOpHdr
->Length
);
1747 if (*EfiVarStore
== NULL
) {
1748 FreePool (VarStoreName
);
1752 Status
= EFI_OUT_OF_RESOURCES
;
1756 *IsEfiVarstore
= TRUE
;
1757 CopyMem (*EfiVarStore
, IfrEfiVarStore
, IfrOpHdr
->Length
);
1761 // Free allocated temp string.
1763 FreePool (VarStoreName
);
1769 // Already found the varstore, break;
1771 if (*IsEfiVarstore
) {
1778 if (HiiFormPackage
!= NULL
) {
1779 FreePool (HiiFormPackage
);
1786 Check whether the ConfigRequest string has the request elements.
1787 For EFI_HII_VARSTORE_BUFFER type, the request has "&OFFSET=****&WIDTH=****..." format.
1788 For EFI_HII_VARSTORE_NAME_VALUE type, the request has "&NAME1**&NAME2..." format.
1790 @param ConfigRequest The input config request string.
1792 @retval TRUE The input include config request elements.
1793 @retval FALSE The input string not includes.
1797 GetElementsFromRequest (
1798 IN EFI_STRING ConfigRequest
1801 EFI_STRING TmpRequest
;
1803 TmpRequest
= StrStr (ConfigRequest
, L
"PATH=");
1804 ASSERT (TmpRequest
!= NULL
);
1806 if ((StrStr (TmpRequest
, L
"&OFFSET=") != NULL
) || (StrStr (TmpRequest
, L
"&") != NULL
)) {
1814 Check whether the this varstore is the request varstore.
1816 @param VarstoreGuid Varstore guid.
1817 @param Name Varstore name.
1818 @param ConfigHdr Current configRequest info.
1820 @retval TRUE This varstore is the request one.
1821 @retval FALSE This varstore is not the request one.
1826 IN EFI_GUID
*VarstoreGuid
,
1828 IN CHAR16
*ConfigHdr
1842 // If ConfigHdr has name field and varstore not has name, return FALSE.
1844 if ((Name
== NULL
) && (ConfigHdr
!= NULL
) && (StrStr (ConfigHdr
, L
"NAME=&") == NULL
)) {
1848 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*)VarstoreGuid
, 1, &GuidStr
);
1850 GenerateSubStr (L
"NAME=", StrLen (Name
) * sizeof (CHAR16
), (VOID
*)Name
, 2, &NameStr
);
1852 GenerateSubStr (L
"NAME=", 0, NULL
, 2, &NameStr
);
1855 LengthString
= StrLen (GuidStr
);
1856 LengthString
= LengthString
+ StrLen (NameStr
) + 1;
1857 TempStr
= AllocateZeroPool (LengthString
* sizeof (CHAR16
));
1858 if (TempStr
== NULL
) {
1862 StrCpyS (TempStr
, LengthString
, GuidStr
);
1863 StrCatS (TempStr
, LengthString
, NameStr
);
1865 if ((ConfigHdr
== NULL
) || (StrnCmp (ConfigHdr
, TempStr
, StrLen (TempStr
)) == 0)) {
1870 if (GuidStr
!= NULL
) {
1874 if (NameStr
!= NULL
) {
1878 if (TempStr
!= NULL
) {
1886 This function parses Form Package to get the efi varstore info according to the request ConfigHdr.
1888 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
1889 @param ConfigHdr Request string ConfigHdr. If it is NULL,
1890 the first found varstore will be as ConfigHdr.
1891 @retval TRUE This hii package is the request one.
1892 @retval FALSE This hii package is not the request one.
1896 IN HII_DATABASE_RECORD
*DataBaseRecord
,
1897 IN EFI_STRING ConfigHdr
1902 UINTN PackageOffset
;
1903 EFI_IFR_OP_HEADER
*IfrOpHdr
;
1904 CHAR16
*VarStoreName
;
1906 UINT8
*HiiFormPackage
;
1908 EFI_IFR_VARSTORE_EFI
*IfrEfiVarStore
;
1909 EFI_HII_PACKAGE_HEADER
*PackageHeader
;
1910 EFI_IFR_VARSTORE
*IfrVarStore
;
1911 EFI_IFR_VARSTORE_NAME_VALUE
*IfrNameValueVarStore
;
1912 BOOLEAN FindVarstore
;
1914 HiiFormPackage
= NULL
;
1915 VarStoreName
= NULL
;
1916 Status
= EFI_SUCCESS
;
1917 FindVarstore
= FALSE
;
1919 Status
= GetFormPackageData (DataBaseRecord
, &HiiFormPackage
, &PackageSize
);
1920 if (EFI_ERROR (Status
)) {
1924 IfrOffset
= sizeof (EFI_HII_PACKAGE_HEADER
);
1925 PackageOffset
= IfrOffset
;
1926 PackageHeader
= (EFI_HII_PACKAGE_HEADER
*)HiiFormPackage
;
1928 while (IfrOffset
< PackageSize
) {
1930 // More than one form packages exist.
1932 if (PackageOffset
>= PackageHeader
->Length
) {
1934 // Process the new form package.
1936 PackageOffset
= sizeof (EFI_HII_PACKAGE_HEADER
);
1937 IfrOffset
+= PackageOffset
;
1938 PackageHeader
= (EFI_HII_PACKAGE_HEADER
*)(HiiFormPackage
+ IfrOffset
);
1941 IfrOpHdr
= (EFI_IFR_OP_HEADER
*)(HiiFormPackage
+ IfrOffset
);
1942 IfrOffset
+= IfrOpHdr
->Length
;
1943 PackageOffset
+= IfrOpHdr
->Length
;
1945 switch (IfrOpHdr
->OpCode
) {
1946 case EFI_IFR_VARSTORE_OP
:
1947 IfrVarStore
= (EFI_IFR_VARSTORE
*)IfrOpHdr
;
1949 NameSize
= AsciiStrSize ((CHAR8
*)IfrVarStore
->Name
);
1950 VarStoreName
= AllocateZeroPool (NameSize
* sizeof (CHAR16
));
1951 if (VarStoreName
== NULL
) {
1955 AsciiStrToUnicodeStrS ((CHAR8
*)IfrVarStore
->Name
, VarStoreName
, NameSize
);
1957 if (IsThisVarstore ((VOID
*)&IfrVarStore
->Guid
, VarStoreName
, ConfigHdr
)) {
1958 FindVarstore
= TRUE
;
1961 FreePool (VarStoreName
);
1962 VarStoreName
= NULL
;
1967 case EFI_IFR_VARSTORE_EFI_OP
:
1968 IfrEfiVarStore
= (EFI_IFR_VARSTORE_EFI
*)IfrOpHdr
;
1969 NameSize
= AsciiStrSize ((CHAR8
*)IfrEfiVarStore
->Name
);
1970 VarStoreName
= AllocateZeroPool (NameSize
* sizeof (CHAR16
));
1971 if (VarStoreName
== NULL
) {
1975 AsciiStrToUnicodeStrS ((CHAR8
*)IfrEfiVarStore
->Name
, VarStoreName
, NameSize
);
1977 if (IsThisVarstore (&IfrEfiVarStore
->Guid
, VarStoreName
, ConfigHdr
)) {
1978 FindVarstore
= TRUE
;
1981 FreePool (VarStoreName
);
1982 VarStoreName
= NULL
;
1987 case EFI_IFR_VARSTORE_NAME_VALUE_OP
:
1988 IfrNameValueVarStore
= (EFI_IFR_VARSTORE_NAME_VALUE
*)IfrOpHdr
;
1990 if (IsThisVarstore (&IfrNameValueVarStore
->Guid
, NULL
, ConfigHdr
)) {
1991 FindVarstore
= TRUE
;
1997 case EFI_IFR_FORM_OP
:
1998 case EFI_IFR_FORM_MAP_OP
:
2000 // No matched varstore is found and directly return.
2010 if (HiiFormPackage
!= NULL
) {
2011 FreePool (HiiFormPackage
);
2014 if (VarStoreName
!= NULL
) {
2015 FreePool (VarStoreName
);
2018 return FindVarstore
;
2022 Check whether the this op code is required.
2024 @param RequestBlockArray The array includes all the request info or NULL.
2025 @param HiiHandle The hii handle for this form package.
2026 @param VarStorageData The varstore data structure.
2027 @param IfrOpHdr Ifr opcode header for this opcode.
2028 @param VarWidth The buffer width for this opcode.
2029 @param ReturnData The data block added for this opcode.
2030 @param IsBitVar Whether the the opcode refers to bit storage.
2032 @retval EFI_SUCCESS This opcode is required.
2033 @retval EFI_NOT_FOUND This opcode is not required.
2034 @retval Others Contain some error.
2038 IsThisOpcodeRequired (
2039 IN IFR_BLOCK_DATA
*RequestBlockArray
,
2040 IN EFI_HII_HANDLE HiiHandle
,
2041 IN OUT IFR_VARSTORAGE_DATA
*VarStorageData
,
2042 IN EFI_IFR_OP_HEADER
*IfrOpHdr
,
2044 OUT IFR_BLOCK_DATA
**ReturnData
,
2048 IFR_BLOCK_DATA
*BlockData
;
2050 EFI_STRING_ID NameId
;
2051 EFI_IFR_QUESTION_HEADER
*IfrQuestionHdr
;
2060 IfrQuestionHdr
= (EFI_IFR_QUESTION_HEADER
*)((CHAR8
*)IfrOpHdr
+ sizeof (EFI_IFR_OP_HEADER
));
2062 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2063 NameId
= IfrQuestionHdr
->VarStoreInfo
.VarName
;
2066 // Check whether this question is in requested block array.
2068 if (!BlockArrayCheck (RequestBlockArray
, NameId
, 0, TRUE
, HiiHandle
)) {
2070 // This question is not in the requested string. Skip it.
2072 return EFI_NOT_FOUND
;
2076 // Get the byte offset/with and bit offset/width
2079 BitOffset
= IfrQuestionHdr
->VarStoreInfo
.VarOffset
;
2080 BitWidth
= VarWidth
;
2081 VarOffset
= BitOffset
/ 8;
2083 // Use current bit width and the bit width before current bit (with same byte offset) to calculate the byte width.
2085 TotalBits
= BitOffset
% 8 + BitWidth
;
2086 VarWidth
= (TotalBits
% 8 == 0 ? TotalBits
/ 8 : TotalBits
/ 8 + 1);
2088 VarOffset
= IfrQuestionHdr
->VarStoreInfo
.VarOffset
;
2089 BitWidth
= VarWidth
;
2090 BitOffset
= VarOffset
* 8;
2094 // Check whether this question is in requested block array.
2096 if (!BlockArrayCheck (RequestBlockArray
, VarOffset
, VarWidth
, FALSE
, HiiHandle
)) {
2098 // This question is not in the requested string. Skip it.
2100 return EFI_NOT_FOUND
;
2104 // Check this var question is in the var storage
2106 if (((VarOffset
+ VarWidth
) > VarStorageData
->Size
)) {
2107 return EFI_INVALID_PARAMETER
;
2111 BlockData
= (IFR_BLOCK_DATA
*)AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
2112 if (BlockData
== NULL
) {
2113 return EFI_OUT_OF_RESOURCES
;
2116 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2117 BlockData
->Name
= InternalGetString (HiiHandle
, NameId
);
2119 BlockData
->Offset
= VarOffset
;
2122 BlockData
->Width
= VarWidth
;
2123 BlockData
->QuestionId
= IfrQuestionHdr
->QuestionId
;
2124 BlockData
->OpCode
= IfrOpHdr
->OpCode
;
2125 BlockData
->Scope
= IfrOpHdr
->Scope
;
2126 BlockData
->IsBitVar
= IsBitVar
;
2127 BlockData
->BitOffset
= BitOffset
;
2128 BlockData
->BitWidth
= BitWidth
;
2129 InitializeListHead (&BlockData
->DefaultValueEntry
);
2131 // Add Block Data into VarStorageData BlockEntry
2133 InsertBlockData (&VarStorageData
->BlockEntry
, &BlockData
);
2134 *ReturnData
= BlockData
;
2140 This function parses Form Package to get the block array and the default
2141 value array according to the request ConfigHdr.
2143 @param HiiHandle Hii Handle for this hii package.
2144 @param Package Pointer to the form package data.
2145 @param PackageLength Length of the package.
2146 @param ConfigHdr Request string ConfigHdr. If it is NULL,
2147 the first found varstore will be as ConfigHdr.
2148 @param RequestBlockArray The block array is retrieved from the request string.
2149 @param VarStorageData VarStorage structure contains the got block and default value.
2150 @param DefaultIdArray Point to the got default id and default name array.
2152 @retval EFI_SUCCESS The block array and the default value array are got.
2153 @retval EFI_INVALID_PARAMETER The varstore definition in the different form packages
2155 @retval EFI_OUT_OF_RESOURCES No enough memory.
2160 IN EFI_HII_HANDLE HiiHandle
,
2162 IN UINT32 PackageLength
,
2163 IN EFI_STRING ConfigHdr
,
2164 IN IFR_BLOCK_DATA
*RequestBlockArray
,
2165 IN OUT IFR_VARSTORAGE_DATA
*VarStorageData
,
2166 OUT IFR_DEFAULT_DATA
*DefaultIdArray
2171 UINTN PackageOffset
;
2172 EFI_IFR_VARSTORE
*IfrVarStore
;
2173 EFI_IFR_VARSTORE_EFI
*IfrEfiVarStore
;
2174 EFI_IFR_VARSTORE_EFI
*IfrEfiVarStoreTmp
;
2175 EFI_IFR_OP_HEADER
*IfrOpHdr
;
2176 EFI_IFR_ONE_OF
*IfrOneOf
;
2177 EFI_IFR_REF4
*IfrRef
;
2178 EFI_IFR_ONE_OF_OPTION
*IfrOneOfOption
;
2179 EFI_IFR_DEFAULT
*IfrDefault
;
2180 EFI_IFR_ORDERED_LIST
*IfrOrderedList
;
2181 EFI_IFR_CHECKBOX
*IfrCheckBox
;
2182 EFI_IFR_PASSWORD
*IfrPassword
;
2183 EFI_IFR_STRING
*IfrString
;
2184 EFI_IFR_DATE
*IfrDate
;
2185 EFI_IFR_TIME
*IfrTime
;
2186 IFR_DEFAULT_DATA DefaultData
;
2187 IFR_DEFAULT_DATA
*DefaultDataPtr
;
2188 IFR_BLOCK_DATA
*BlockData
;
2189 CHAR16
*VarStoreName
;
2191 UINTN NvDefaultStoreSize
;
2193 UINT16 VarDefaultId
;
2194 BOOLEAN FirstOneOfOption
;
2195 BOOLEAN FirstOrderedList
;
2196 LIST_ENTRY
*LinkData
;
2197 LIST_ENTRY
*LinkDefault
;
2198 EFI_IFR_VARSTORE_NAME_VALUE
*IfrNameValueVarStore
;
2199 EFI_HII_PACKAGE_HEADER
*PackageHeader
;
2200 EFI_VARSTORE_ID VarStoreId
;
2201 UINT16 SmallestDefaultId
;
2202 BOOLEAN SmallestIdFromFlag
;
2203 BOOLEAN FromOtherDefaultOpcode
;
2204 BOOLEAN QuestionReferBitField
;
2206 Status
= EFI_SUCCESS
;
2208 DefaultDataPtr
= NULL
;
2209 FirstOneOfOption
= FALSE
;
2211 FirstOrderedList
= FALSE
;
2212 VarStoreName
= NULL
;
2213 ZeroMem (&DefaultData
, sizeof (IFR_DEFAULT_DATA
));
2214 SmallestDefaultId
= 0xFFFF;
2215 FromOtherDefaultOpcode
= FALSE
;
2216 QuestionReferBitField
= FALSE
;
2217 IfrEfiVarStoreTmp
= NULL
;
2220 // Go through the form package to parse OpCode one by one.
2222 PackageOffset
= sizeof (EFI_HII_PACKAGE_HEADER
);
2223 PackageHeader
= (EFI_HII_PACKAGE_HEADER
*)Package
;
2224 IfrOffset
= PackageOffset
;
2225 while (IfrOffset
< PackageLength
) {
2227 // More than one form package found.
2229 if (PackageOffset
>= PackageHeader
->Length
) {
2231 // Already found varstore for this request, break;
2233 if (VarStoreId
!= 0) {
2238 // Get next package header info.
2240 IfrOffset
+= sizeof (EFI_HII_PACKAGE_HEADER
);
2241 PackageOffset
= sizeof (EFI_HII_PACKAGE_HEADER
);
2242 PackageHeader
= (EFI_HII_PACKAGE_HEADER
*)(Package
+ IfrOffset
);
2245 IfrOpHdr
= (EFI_IFR_OP_HEADER
*)(Package
+ IfrOffset
);
2246 switch (IfrOpHdr
->OpCode
) {
2247 case EFI_IFR_VARSTORE_OP
:
2249 // VarStore is found. Don't need to search any more.
2251 if (VarStoreId
!= 0) {
2255 IfrVarStore
= (EFI_IFR_VARSTORE
*)IfrOpHdr
;
2257 NameSize
= AsciiStrSize ((CHAR8
*)IfrVarStore
->Name
);
2258 VarStoreName
= AllocateZeroPool (NameSize
* sizeof (CHAR16
));
2259 if (VarStoreName
== NULL
) {
2260 Status
= EFI_OUT_OF_RESOURCES
;
2264 AsciiStrToUnicodeStrS ((CHAR8
*)IfrVarStore
->Name
, VarStoreName
, NameSize
);
2266 if (IsThisVarstore ((VOID
*)&IfrVarStore
->Guid
, VarStoreName
, ConfigHdr
)) {
2268 // Find the matched VarStore
2270 CopyGuid (&VarStorageData
->Guid
, (EFI_GUID
*)(VOID
*)&IfrVarStore
->Guid
);
2271 VarStorageData
->Size
= IfrVarStore
->Size
;
2272 VarStorageData
->Name
= VarStoreName
;
2273 VarStorageData
->Type
= EFI_HII_VARSTORE_BUFFER
;
2274 VarStoreId
= IfrVarStore
->VarStoreId
;
2276 FreePool (VarStoreName
);
2277 VarStoreName
= NULL
;
2282 case EFI_IFR_VARSTORE_EFI_OP
:
2284 // VarStore is found. Don't need to search any more.
2286 if (VarStoreId
!= 0) {
2290 IfrEfiVarStore
= (EFI_IFR_VARSTORE_EFI
*)IfrOpHdr
;
2293 // If the length is small than the structure, this is from old efi
2294 // varstore definition. Old efi varstore get config directly from
2295 // GetVariable function.
2297 if (IfrOpHdr
->Length
< sizeof (EFI_IFR_VARSTORE_EFI
)) {
2301 NameSize
= AsciiStrSize ((CHAR8
*)IfrEfiVarStore
->Name
);
2302 VarStoreName
= AllocateZeroPool (NameSize
* sizeof (CHAR16
));
2303 if (VarStoreName
== NULL
) {
2304 Status
= EFI_OUT_OF_RESOURCES
;
2308 AsciiStrToUnicodeStrS ((CHAR8
*)IfrEfiVarStore
->Name
, VarStoreName
, NameSize
);
2309 if (IfrEfiVarStoreTmp
!= NULL
) {
2310 FreePool (IfrEfiVarStoreTmp
);
2313 IfrEfiVarStoreTmp
= AllocatePool (IfrEfiVarStore
->Header
.Length
+ AsciiStrSize ((CHAR8
*)IfrEfiVarStore
->Name
));
2314 if (IfrEfiVarStoreTmp
== NULL
) {
2315 Status
= EFI_OUT_OF_RESOURCES
;
2319 CopyMem (IfrEfiVarStoreTmp
, IfrEfiVarStore
, IfrEfiVarStore
->Header
.Length
);
2320 AsciiStrToUnicodeStrS ((CHAR8
*)IfrEfiVarStore
->Name
, (CHAR16
*)&(IfrEfiVarStoreTmp
->Name
[0]), AsciiStrSize ((CHAR8
*)IfrEfiVarStore
->Name
) * sizeof (CHAR16
));
2322 if (IsThisVarstore (&IfrEfiVarStore
->Guid
, VarStoreName
, ConfigHdr
)) {
2324 // Find the matched VarStore
2326 CopyGuid (&VarStorageData
->Guid
, (EFI_GUID
*)(VOID
*)&IfrEfiVarStore
->Guid
);
2327 VarStorageData
->Size
= IfrEfiVarStore
->Size
;
2328 VarStorageData
->Name
= VarStoreName
;
2329 VarStorageData
->Type
= EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
;
2330 VarStoreId
= IfrEfiVarStore
->VarStoreId
;
2332 FreePool (VarStoreName
);
2333 VarStoreName
= NULL
;
2338 case EFI_IFR_VARSTORE_NAME_VALUE_OP
:
2340 // VarStore is found. Don't need to search any more.
2342 if (VarStoreId
!= 0) {
2346 IfrNameValueVarStore
= (EFI_IFR_VARSTORE_NAME_VALUE
*)IfrOpHdr
;
2348 if (IsThisVarstore (&IfrNameValueVarStore
->Guid
, NULL
, ConfigHdr
)) {
2350 // Find the matched VarStore
2352 CopyGuid (&VarStorageData
->Guid
, (EFI_GUID
*)(VOID
*)&IfrNameValueVarStore
->Guid
);
2353 VarStorageData
->Type
= EFI_HII_VARSTORE_NAME_VALUE
;
2354 VarStoreId
= IfrNameValueVarStore
->VarStoreId
;
2359 case EFI_IFR_DEFAULTSTORE_OP
:
2361 // Add new the map between default id and default name.
2363 DefaultDataPtr
= (IFR_DEFAULT_DATA
*)AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
2364 if (DefaultDataPtr
== NULL
) {
2365 Status
= EFI_OUT_OF_RESOURCES
;
2369 DefaultDataPtr
->DefaultId
= ((EFI_IFR_DEFAULTSTORE
*)IfrOpHdr
)->DefaultId
;
2370 InsertTailList (&DefaultIdArray
->Entry
, &DefaultDataPtr
->Entry
);
2371 DefaultDataPtr
= NULL
;
2374 case EFI_IFR_FORM_OP
:
2375 case EFI_IFR_FORM_MAP_OP
:
2377 // No matched varstore is found and directly return.
2379 if ( VarStoreId
== 0) {
2380 Status
= EFI_SUCCESS
;
2386 case EFI_IFR_REF_OP
:
2388 // Ref question is not in IFR Form. This IFR form is not valid.
2390 if ( VarStoreId
== 0) {
2391 Status
= EFI_INVALID_PARAMETER
;
2396 // Check whether this question is for the requested varstore.
2398 IfrRef
= (EFI_IFR_REF4
*)IfrOpHdr
;
2399 if (IfrRef
->Question
.VarStoreId
!= VarStoreId
) {
2403 VarWidth
= (UINT16
)(sizeof (EFI_HII_REF
));
2406 // The BlockData may allocate by other opcode,need to clean.
2408 if (BlockData
!= NULL
) {
2412 Status
= IsThisOpcodeRequired (RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
, FALSE
);
2413 if (EFI_ERROR (Status
)) {
2414 if (Status
== EFI_NOT_FOUND
) {
2416 // The opcode is not required,exit and parse other opcode.
2426 case EFI_IFR_ONE_OF_OP
:
2427 case EFI_IFR_NUMERIC_OP
:
2429 // Numeric and OneOf has the same opcode structure.
2433 // Numeric and OneOf question is not in IFR Form. This IFR form is not valid.
2435 if (VarStoreId
== 0) {
2436 Status
= EFI_INVALID_PARAMETER
;
2441 // Check whether this question is for the requested varstore.
2443 IfrOneOf
= (EFI_IFR_ONE_OF
*)IfrOpHdr
;
2444 if (IfrOneOf
->Question
.VarStoreId
!= VarStoreId
) {
2448 if (QuestionReferBitField
) {
2449 VarWidth
= IfrOneOf
->Flags
& EDKII_IFR_NUMERIC_SIZE_BIT
;
2451 VarWidth
= (UINT16
)(1 << (IfrOneOf
->Flags
& EFI_IFR_NUMERIC_SIZE
));
2455 // The BlockData may allocate by other opcode,need to clean.
2457 if (BlockData
!= NULL
) {
2461 Status
= IsThisOpcodeRequired (RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
, QuestionReferBitField
);
2462 if (EFI_ERROR (Status
)) {
2463 if (Status
== EFI_NOT_FOUND
) {
2465 // The opcode is not required,exit and parse other opcode.
2474 // when go to there,BlockData can't be NULLL.
2476 ASSERT (BlockData
!= NULL
);
2478 if (IfrOpHdr
->OpCode
== EFI_IFR_ONE_OF_OP
) {
2480 // Set this flag to TRUE for the first oneof option.
2482 FirstOneOfOption
= TRUE
;
2483 } else if (IfrOpHdr
->OpCode
== EFI_IFR_NUMERIC_OP
) {
2485 // Numeric minimum value will be used as default value when no default is specified.
2487 DefaultData
.Type
= DefaultValueFromDefault
;
2488 if (QuestionReferBitField
) {
2490 // Since default value in bit field was stored as UINT32 type.
2492 CopyMem (&DefaultData
.Value
.u32
, &IfrOneOf
->data
.u32
.MinValue
, sizeof (UINT32
));
2494 switch (IfrOneOf
->Flags
& EFI_IFR_NUMERIC_SIZE
) {
2495 case EFI_IFR_NUMERIC_SIZE_1
:
2496 DefaultData
.Value
.u8
= IfrOneOf
->data
.u8
.MinValue
;
2499 case EFI_IFR_NUMERIC_SIZE_2
:
2500 CopyMem (&DefaultData
.Value
.u16
, &IfrOneOf
->data
.u16
.MinValue
, sizeof (UINT16
));
2503 case EFI_IFR_NUMERIC_SIZE_4
:
2504 CopyMem (&DefaultData
.Value
.u32
, &IfrOneOf
->data
.u32
.MinValue
, sizeof (UINT32
));
2507 case EFI_IFR_NUMERIC_SIZE_8
:
2508 CopyMem (&DefaultData
.Value
.u64
, &IfrOneOf
->data
.u64
.MinValue
, sizeof (UINT64
));
2512 Status
= EFI_INVALID_PARAMETER
;
2518 // Set default value base on the DefaultId list get from IFR data.
2520 NvDefaultStoreSize
= PcdGetSize (PcdNvStoreDefaultValueBuffer
);
2521 for (LinkData
= DefaultIdArray
->Entry
.ForwardLink
; LinkData
!= &DefaultIdArray
->Entry
; LinkData
= LinkData
->ForwardLink
) {
2522 DefaultDataPtr
= BASE_CR (LinkData
, IFR_DEFAULT_DATA
, Entry
);
2523 DefaultData
.DefaultId
= DefaultDataPtr
->DefaultId
;
2524 if (NvDefaultStoreSize
> sizeof (PCD_NV_STORE_DEFAULT_BUFFER_HEADER
)) {
2525 FindQuestionDefaultSetting (DefaultData
.DefaultId
, IfrEfiVarStoreTmp
, &(IfrOneOf
->Question
), &DefaultData
.Value
, VarWidth
, QuestionReferBitField
);
2528 InsertDefaultValue (BlockData
, &DefaultData
);
2534 case EFI_IFR_ORDERED_LIST_OP
:
2536 // offset by question header
2537 // width by EFI_IFR_ORDERED_LIST MaxContainers * OneofOption Type
2540 FirstOrderedList
= TRUE
;
2542 // OrderedList question is not in IFR Form. This IFR form is not valid.
2544 if (VarStoreId
== 0) {
2545 Status
= EFI_INVALID_PARAMETER
;
2550 // Check whether this question is for the requested varstore.
2552 IfrOrderedList
= (EFI_IFR_ORDERED_LIST
*)IfrOpHdr
;
2553 if (IfrOrderedList
->Question
.VarStoreId
!= VarStoreId
) {
2558 VarWidth
= IfrOrderedList
->MaxContainers
;
2561 // The BlockData may allocate by other opcode,need to clean.
2563 if (BlockData
!= NULL
) {
2567 Status
= IsThisOpcodeRequired (RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
, FALSE
);
2568 if (EFI_ERROR (Status
)) {
2569 if (Status
== EFI_NOT_FOUND
) {
2571 // The opcode is not required,exit and parse other opcode.
2581 case EFI_IFR_CHECKBOX_OP
:
2583 // EFI_IFR_DEFAULT_OP
2584 // offset by question header
2585 // width is 1 sizeof (BOOLEAN)
2586 // default id by CheckBox Flags if CheckBox flags (Default or Mau) is set, the default value is 1 to be set.
2587 // value by DefaultOption
2588 // default id by DeaultOption DefaultId can override CheckBox Flags and Default value.
2592 // CheckBox question is not in IFR Form. This IFR form is not valid.
2594 if (VarStoreId
== 0) {
2595 Status
= EFI_INVALID_PARAMETER
;
2600 // Check whether this question is for the requested varstore.
2602 IfrCheckBox
= (EFI_IFR_CHECKBOX
*)IfrOpHdr
;
2603 if (IfrCheckBox
->Question
.VarStoreId
!= VarStoreId
) {
2607 VarWidth
= (UINT16
)sizeof (BOOLEAN
);
2610 // The BlockData may allocate by other opcode,need to clean.
2612 if (BlockData
!= NULL
) {
2616 if (QuestionReferBitField
) {
2620 Status
= IsThisOpcodeRequired (RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
, QuestionReferBitField
);
2621 if (EFI_ERROR (Status
)) {
2622 if (Status
== EFI_NOT_FOUND
) {
2624 // The opcode is not required,exit and parse other opcode.
2633 // when go to there,BlockData can't be NULLL.
2635 ASSERT (BlockData
!= NULL
);
2637 SmallestIdFromFlag
= FALSE
;
2640 // Add default value for standard ID by CheckBox Flag
2642 VarDefaultId
= EFI_HII_DEFAULT_CLASS_STANDARD
;
2644 // Prepare new DefaultValue
2646 DefaultData
.DefaultId
= VarDefaultId
;
2647 if ((IfrCheckBox
->Flags
& EFI_IFR_CHECKBOX_DEFAULT
) == EFI_IFR_CHECKBOX_DEFAULT
) {
2649 // When flag is set, default value is TRUE.
2651 DefaultData
.Type
= DefaultValueFromFlag
;
2652 if (QuestionReferBitField
) {
2653 DefaultData
.Value
.u32
= TRUE
;
2655 DefaultData
.Value
.b
= TRUE
;
2658 InsertDefaultValue (BlockData
, &DefaultData
);
2660 if (SmallestDefaultId
> EFI_HII_DEFAULT_CLASS_STANDARD
) {
2662 // Record the SmallestDefaultId and update the SmallestIdFromFlag.
2664 SmallestDefaultId
= EFI_HII_DEFAULT_CLASS_STANDARD
;
2665 SmallestIdFromFlag
= TRUE
;
2670 // Add default value for Manufacture ID by CheckBox Flag
2672 VarDefaultId
= EFI_HII_DEFAULT_CLASS_MANUFACTURING
;
2674 // Prepare new DefaultValue
2676 DefaultData
.DefaultId
= VarDefaultId
;
2677 if ((IfrCheckBox
->Flags
& EFI_IFR_CHECKBOX_DEFAULT_MFG
) == EFI_IFR_CHECKBOX_DEFAULT_MFG
) {
2679 // When flag is set, default value is TRUE.
2681 DefaultData
.Type
= DefaultValueFromFlag
;
2682 if (QuestionReferBitField
) {
2683 DefaultData
.Value
.u32
= TRUE
;
2685 DefaultData
.Value
.b
= TRUE
;
2688 InsertDefaultValue (BlockData
, &DefaultData
);
2690 if (SmallestDefaultId
> EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
2692 // Record the SmallestDefaultId and update the SmallestIdFromFlag.
2694 SmallestDefaultId
= EFI_HII_DEFAULT_CLASS_MANUFACTURING
;
2695 SmallestIdFromFlag
= TRUE
;
2699 if (SmallestIdFromFlag
) {
2701 // When smallest default Id is given by the flag of CheckBox, set default value with TRUE for other default Id in the DefaultId list.
2703 DefaultData
.Type
= DefaultValueFromOtherDefault
;
2704 if (QuestionReferBitField
) {
2705 DefaultData
.Value
.u32
= TRUE
;
2707 DefaultData
.Value
.b
= TRUE
;
2711 // Set default value for all the default id in the DefaultId list.
2713 for (LinkData
= DefaultIdArray
->Entry
.ForwardLink
; LinkData
!= &DefaultIdArray
->Entry
; LinkData
= LinkData
->ForwardLink
) {
2714 DefaultDataPtr
= BASE_CR (LinkData
, IFR_DEFAULT_DATA
, Entry
);
2715 DefaultData
.DefaultId
= DefaultDataPtr
->DefaultId
;
2716 InsertDefaultValue (BlockData
, &DefaultData
);
2720 // When flag is not set, default value is FASLE.
2722 DefaultData
.Type
= DefaultValueFromDefault
;
2723 if (QuestionReferBitField
) {
2724 DefaultData
.Value
.u32
= FALSE
;
2726 DefaultData
.Value
.b
= FALSE
;
2730 // Set default value for all the default id in the DefaultId list.
2732 for (LinkData
= DefaultIdArray
->Entry
.ForwardLink
; LinkData
!= &DefaultIdArray
->Entry
; LinkData
= LinkData
->ForwardLink
) {
2733 DefaultDataPtr
= BASE_CR (LinkData
, IFR_DEFAULT_DATA
, Entry
);
2734 DefaultData
.DefaultId
= DefaultDataPtr
->DefaultId
;
2735 InsertDefaultValue (BlockData
, &DefaultData
);
2741 case EFI_IFR_DATE_OP
:
2743 // offset by question header
2744 // width MaxSize * sizeof (CHAR16)
2745 // no default value, only block array
2749 // Date question is not in IFR Form. This IFR form is not valid.
2751 if (VarStoreId
== 0) {
2752 Status
= EFI_INVALID_PARAMETER
;
2757 // Check whether this question is for the requested varstore.
2759 IfrDate
= (EFI_IFR_DATE
*)IfrOpHdr
;
2760 if (IfrDate
->Question
.VarStoreId
!= VarStoreId
) {
2765 // The BlockData may allocate by other opcode,need to clean.
2767 if (BlockData
!= NULL
) {
2771 VarWidth
= (UINT16
)sizeof (EFI_HII_DATE
);
2772 Status
= IsThisOpcodeRequired (RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
, FALSE
);
2773 if (EFI_ERROR (Status
)) {
2774 if (Status
== EFI_NOT_FOUND
) {
2776 // The opcode is not required,exit and parse other opcode.
2786 case EFI_IFR_TIME_OP
:
2788 // offset by question header
2789 // width MaxSize * sizeof (CHAR16)
2790 // no default value, only block array
2794 // Time question is not in IFR Form. This IFR form is not valid.
2796 if (VarStoreId
== 0) {
2797 Status
= EFI_INVALID_PARAMETER
;
2802 // Check whether this question is for the requested varstore.
2804 IfrTime
= (EFI_IFR_TIME
*)IfrOpHdr
;
2805 if (IfrTime
->Question
.VarStoreId
!= VarStoreId
) {
2810 // The BlockData may allocate by other opcode,need to clean.
2812 if (BlockData
!= NULL
) {
2816 VarWidth
= (UINT16
)sizeof (EFI_HII_TIME
);
2817 Status
= IsThisOpcodeRequired (RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
, FALSE
);
2818 if (EFI_ERROR (Status
)) {
2819 if (Status
== EFI_NOT_FOUND
) {
2821 // The opcode is not required,exit and parse other opcode.
2831 case EFI_IFR_STRING_OP
:
2833 // offset by question header
2834 // width MaxSize * sizeof (CHAR16)
2835 // no default value, only block array
2839 // String question is not in IFR Form. This IFR form is not valid.
2841 if (VarStoreId
== 0) {
2842 Status
= EFI_INVALID_PARAMETER
;
2847 // Check whether this question is for the requested varstore.
2849 IfrString
= (EFI_IFR_STRING
*)IfrOpHdr
;
2850 if (IfrString
->Question
.VarStoreId
!= VarStoreId
) {
2855 // The BlockData may allocate by other opcode,need to clean.
2857 if (BlockData
!= NULL
) {
2861 VarWidth
= (UINT16
)(IfrString
->MaxSize
* sizeof (UINT16
));
2862 Status
= IsThisOpcodeRequired (RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
, FALSE
);
2863 if (EFI_ERROR (Status
)) {
2864 if (Status
== EFI_NOT_FOUND
) {
2866 // The opcode is not required,exit and parse other opcode.
2876 case EFI_IFR_PASSWORD_OP
:
2878 // offset by question header
2879 // width MaxSize * sizeof (CHAR16)
2880 // no default value, only block array
2884 // Password question is not in IFR Form. This IFR form is not valid.
2886 if (VarStoreId
== 0) {
2887 Status
= EFI_INVALID_PARAMETER
;
2892 // Check whether this question is for the requested varstore.
2894 IfrPassword
= (EFI_IFR_PASSWORD
*)IfrOpHdr
;
2895 if (IfrPassword
->Question
.VarStoreId
!= VarStoreId
) {
2900 // The BlockData may allocate by other opcode,need to clean.
2902 if (BlockData
!= NULL
) {
2906 VarWidth
= (UINT16
)(IfrPassword
->MaxSize
* sizeof (UINT16
));
2907 Status
= IsThisOpcodeRequired (RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
, FALSE
);
2908 if (EFI_ERROR (Status
)) {
2909 if (Status
== EFI_NOT_FOUND
) {
2911 // The opcode is not required,exit and parse other opcode.
2920 // No default value for string.
2925 case EFI_IFR_ONE_OF_OPTION_OP
:
2927 // No matched block data is ignored.
2929 if ((BlockData
== NULL
) || (BlockData
->Scope
== 0)) {
2933 IfrOneOfOption
= (EFI_IFR_ONE_OF_OPTION
*)IfrOpHdr
;
2934 if (BlockData
->OpCode
== EFI_IFR_ORDERED_LIST_OP
) {
2935 if (!FirstOrderedList
) {
2940 // Get ordered list option data type.
2942 if ((IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_8
) || (IfrOneOfOption
->Type
== EFI_IFR_TYPE_BOOLEAN
)) {
2944 } else if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_16
) {
2946 } else if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_32
) {
2948 } else if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_64
) {
2952 // Invalid ordered list option data type.
2954 Status
= EFI_INVALID_PARAMETER
;
2955 if (BlockData
->Name
!= NULL
) {
2956 FreePool (BlockData
->Name
);
2959 FreePool (BlockData
);
2964 // Calculate Ordered list QuestionId width.
2966 BlockData
->Width
= (UINT16
)(BlockData
->Width
* VarWidth
);
2968 // Check whether this question is in requested block array.
2970 if (!BlockArrayCheck (RequestBlockArray
, BlockData
->Offset
, BlockData
->Width
, (BOOLEAN
)(BlockData
->Name
!= NULL
), HiiHandle
)) {
2972 // This question is not in the requested string. Skip it.
2974 if (BlockData
->Name
!= NULL
) {
2975 FreePool (BlockData
->Name
);
2978 FreePool (BlockData
);
2984 // Check this var question is in the var storage
2986 if ((BlockData
->Name
== NULL
) && ((BlockData
->Offset
+ BlockData
->Width
) > VarStorageData
->Size
)) {
2987 Status
= EFI_INVALID_PARAMETER
;
2988 FreePool (BlockData
);
2993 // Add Block Data into VarStorageData BlockEntry
2995 InsertBlockData (&VarStorageData
->BlockEntry
, &BlockData
);
2997 FirstOrderedList
= FALSE
;
3003 // 1. Set default value for OneOf option when flag field has default attribute.
3004 // And set the default value with the smallest default id for other default id in the DefaultId list.
3006 if (((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT
) == EFI_IFR_OPTION_DEFAULT
) ||
3007 ((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT_MFG
) == EFI_IFR_OPTION_DEFAULT_MFG
))
3010 // This flag is used to specify whether this option is the first. Set it to FALSE for the following options.
3011 // The first oneof option value will be used as default value when no default value is specified.
3013 FirstOneOfOption
= FALSE
;
3015 SmallestIdFromFlag
= FALSE
;
3017 // Prepare new DefaultValue
3019 DefaultData
.Type
= DefaultValueFromFlag
;
3020 CopyMem (&DefaultData
.Value
, &IfrOneOfOption
->Value
, IfrOneOfOption
->Header
.Length
- OFFSET_OF (EFI_IFR_ONE_OF_OPTION
, Value
));
3021 if ((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT
) == EFI_IFR_OPTION_DEFAULT
) {
3022 DefaultData
.DefaultId
= EFI_HII_DEFAULT_CLASS_STANDARD
;
3023 InsertDefaultValue (BlockData
, &DefaultData
);
3024 if (SmallestDefaultId
> EFI_HII_DEFAULT_CLASS_STANDARD
) {
3026 // Record the SmallestDefaultId and update the SmallestIdFromFlag.
3028 SmallestDefaultId
= EFI_HII_DEFAULT_CLASS_STANDARD
;
3029 SmallestIdFromFlag
= TRUE
;
3033 if ((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT_MFG
) == EFI_IFR_OPTION_DEFAULT_MFG
) {
3034 DefaultData
.DefaultId
= EFI_HII_DEFAULT_CLASS_MANUFACTURING
;
3035 InsertDefaultValue (BlockData
, &DefaultData
);
3036 if (SmallestDefaultId
> EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
3038 // Record the SmallestDefaultId and update the SmallestIdFromFlag.
3040 SmallestDefaultId
= EFI_HII_DEFAULT_CLASS_MANUFACTURING
;
3041 SmallestIdFromFlag
= TRUE
;
3045 if (SmallestIdFromFlag
) {
3047 // When smallest default Id is given by the flag of oneofOption, set this option value for other default Id in the DefaultId list.
3049 DefaultData
.Type
= DefaultValueFromOtherDefault
;
3051 // Set default value for other default id in the DefaultId list.
3053 for (LinkData
= DefaultIdArray
->Entry
.ForwardLink
; LinkData
!= &DefaultIdArray
->Entry
; LinkData
= LinkData
->ForwardLink
) {
3054 DefaultDataPtr
= BASE_CR (LinkData
, IFR_DEFAULT_DATA
, Entry
);
3055 DefaultData
.DefaultId
= DefaultDataPtr
->DefaultId
;
3056 InsertDefaultValue (BlockData
, &DefaultData
);
3062 // 2. Set as the default value when this is the first option.
3063 // The first oneof option value will be used as default value when no default value is specified.
3065 if (FirstOneOfOption
) {
3066 // This flag is used to specify whether this option is the first. Set it to FALSE for the following options.
3067 FirstOneOfOption
= FALSE
;
3070 // Prepare new DefaultValue
3072 DefaultData
.Type
= DefaultValueFromDefault
;
3073 CopyMem (&DefaultData
.Value
, &IfrOneOfOption
->Value
, IfrOneOfOption
->Header
.Length
- OFFSET_OF (EFI_IFR_ONE_OF_OPTION
, Value
));
3074 for (LinkData
= DefaultIdArray
->Entry
.ForwardLink
; LinkData
!= &DefaultIdArray
->Entry
; LinkData
= LinkData
->ForwardLink
) {
3075 DefaultDataPtr
= BASE_CR (LinkData
, IFR_DEFAULT_DATA
, Entry
);
3076 DefaultData
.DefaultId
= DefaultDataPtr
->DefaultId
;
3077 InsertDefaultValue (BlockData
, &DefaultData
);
3083 case EFI_IFR_DEFAULT_OP
:
3085 // Update Current BlockData to the default value.
3087 if ((BlockData
== NULL
) || (BlockData
->Scope
== 0)) {
3089 // No matched block data is ignored.
3095 // Get the DefaultId
3097 IfrDefault
= (EFI_IFR_DEFAULT
*)IfrOpHdr
;
3098 VarDefaultId
= IfrDefault
->DefaultId
;
3100 // Prepare new DefaultValue
3102 DefaultData
.Type
= DefaultValueFromOpcode
;
3103 DefaultData
.DefaultId
= VarDefaultId
;
3104 if (QuestionReferBitField
) {
3105 CopyMem (&DefaultData
.Value
.u32
, &IfrDefault
->Value
.u32
, sizeof (UINT32
));
3107 CopyMem (&DefaultData
.Value
, &IfrDefault
->Value
, IfrDefault
->Header
.Length
- OFFSET_OF (EFI_IFR_DEFAULT
, Value
));
3110 // If the value field is expression, set the cleaned flag.
3111 if (IfrDefault
->Type
== EFI_IFR_TYPE_OTHER
) {
3112 DefaultData
.Cleaned
= TRUE
;
3116 // Add DefaultValue into current BlockData
3118 InsertDefaultValue (BlockData
, &DefaultData
);
3121 // Set default value for other default id in the DefaultId list.
3122 // when SmallestDefaultId == VarDefaultId means there are two defaults with same default Id.
3123 // If the two defaults are both from default opcode, use the first default as the default value of other default Id.
3124 // If one from flag and the other form default opcode, use the default opcode value as the default value of other default Id.
3126 if ((SmallestDefaultId
> VarDefaultId
) || ((SmallestDefaultId
== VarDefaultId
) && !FromOtherDefaultOpcode
)) {
3127 FromOtherDefaultOpcode
= TRUE
;
3128 SmallestDefaultId
= VarDefaultId
;
3129 for (LinkData
= DefaultIdArray
->Entry
.ForwardLink
; LinkData
!= &DefaultIdArray
->Entry
; LinkData
= LinkData
->ForwardLink
) {
3130 DefaultDataPtr
= BASE_CR (LinkData
, IFR_DEFAULT_DATA
, Entry
);
3131 if (DefaultDataPtr
->DefaultId
!= DefaultData
.DefaultId
) {
3132 DefaultData
.Type
= DefaultValueFromOtherDefault
;
3133 DefaultData
.DefaultId
= DefaultDataPtr
->DefaultId
;
3134 InsertDefaultValue (BlockData
, &DefaultData
);
3140 // After insert the default value, reset the cleaned value for next
3141 // time used. If not set here, need to set the value before every time.
3144 DefaultData
.Cleaned
= FALSE
;
3147 case EFI_IFR_END_OP
:
3149 // End Opcode is for Var question.
3151 QuestionReferBitField
= FALSE
;
3152 if (BlockData
!= NULL
) {
3153 if (BlockData
->Scope
> 0) {
3157 if (BlockData
->Scope
== 0) {
3160 // when finishing parsing a question, clean the SmallestDefaultId and GetDefaultFromDefaultOpcode.
3162 SmallestDefaultId
= 0xFFFF;
3163 FromOtherDefaultOpcode
= FALSE
;
3169 case EFI_IFR_GUID_OP
:
3170 if (CompareGuid ((EFI_GUID
*)((UINT8
*)IfrOpHdr
+ sizeof (EFI_IFR_OP_HEADER
)), &gEdkiiIfrBitVarstoreGuid
)) {
3171 QuestionReferBitField
= TRUE
;
3177 if (BlockData
!= NULL
) {
3178 if (BlockData
->Scope
> 0) {
3179 BlockData
->Scope
= (UINT8
)(BlockData
->Scope
+ IfrOpHdr
->Scope
);
3182 if (BlockData
->Scope
== 0) {
3190 IfrOffset
+= IfrOpHdr
->Length
;
3191 PackageOffset
+= IfrOpHdr
->Length
;
3195 // if Status == EFI_NOT_FOUND, just means the opcode is not required,not contain any error,
3196 // so set the Status to EFI_SUCCESS.
3198 if (Status
== EFI_NOT_FOUND
) {
3199 Status
= EFI_SUCCESS
;
3203 for (LinkData
= VarStorageData
->BlockEntry
.ForwardLink
; LinkData
!= &VarStorageData
->BlockEntry
; LinkData
= LinkData
->ForwardLink
) {
3204 BlockData
= BASE_CR (LinkData
, IFR_BLOCK_DATA
, Entry
);
3205 for (LinkDefault
= BlockData
->DefaultValueEntry
.ForwardLink
; LinkDefault
!= &BlockData
->DefaultValueEntry
; ) {
3206 DefaultDataPtr
= BASE_CR (LinkDefault
, IFR_DEFAULT_DATA
, Entry
);
3207 LinkDefault
= LinkDefault
->ForwardLink
;
3208 if (DefaultDataPtr
->Cleaned
== TRUE
) {
3209 RemoveEntryList (&DefaultDataPtr
->Entry
);
3210 FreePool (DefaultDataPtr
);
3215 if (IfrEfiVarStoreTmp
!= NULL
) {
3216 FreePool (IfrEfiVarStoreTmp
);
3223 parse the configrequest string, get the elements.
3225 @param ConfigRequest The input configrequest string.
3226 @param Progress Return the progress data.
3228 @retval Block data pointer.
3232 IN EFI_STRING ConfigRequest
,
3233 OUT EFI_STRING
*Progress
3236 EFI_STRING StringPtr
;
3237 IFR_BLOCK_DATA
*BlockData
;
3238 IFR_BLOCK_DATA
*RequestBlockArray
;
3244 IFR_BLOCK_DATA
*NextBlockData
;
3250 // Init RequestBlockArray
3252 RequestBlockArray
= (IFR_BLOCK_DATA
*)AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
3253 if (RequestBlockArray
== NULL
) {
3257 InitializeListHead (&RequestBlockArray
->Entry
);
3260 // Get the request Block array from the request string
3265 // Parse each <RequestElement> if exists
3266 // Only <BlockName> format is supported by this help function.
3267 // <BlockName> ::= &'OFFSET='<Number>&'WIDTH='<Number>
3269 StringPtr
= ConfigRequest
;
3270 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) == 0) {
3272 // Skip the OFFSET string
3274 *Progress
= StringPtr
;
3275 StringPtr
+= StrLen (L
"&OFFSET=");
3279 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
3280 if (EFI_ERROR (Status
)) {
3288 (((Length
+ 1) / 2) < sizeof (UINT16
)) ? ((Length
+ 1) / 2) : sizeof (UINT16
)
3290 FreePool (TmpBuffer
);
3292 StringPtr
+= Length
;
3293 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
3297 StringPtr
+= StrLen (L
"&WIDTH=");
3302 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
3303 if (EFI_ERROR (Status
)) {
3311 (((Length
+ 1) / 2) < sizeof (UINT16
)) ? ((Length
+ 1) / 2) : sizeof (UINT16
)
3313 FreePool (TmpBuffer
);
3315 StringPtr
+= Length
;
3316 if ((*StringPtr
!= 0) && (*StringPtr
!= L
'&')) {
3323 BlockData
= (IFR_BLOCK_DATA
*)AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
3324 if (BlockData
== NULL
) {
3328 BlockData
->Offset
= Offset
;
3329 BlockData
->Width
= Width
;
3330 InsertBlockData (&RequestBlockArray
->Entry
, &BlockData
);
3333 // Skip &VALUE string if &VALUE does exists.
3335 if (StrnCmp (StringPtr
, L
"&VALUE=", StrLen (L
"&VALUE=")) == 0) {
3336 StringPtr
+= StrLen (L
"&VALUE=");
3341 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
3342 if (EFI_ERROR (Status
)) {
3346 FreePool (TmpBuffer
);
3347 StringPtr
+= Length
;
3348 if ((*StringPtr
!= 0) && (*StringPtr
!= L
'&')) {
3354 // If '\0', parsing is finished.
3356 if (*StringPtr
== 0) {
3362 // Merge the requested block data.
3364 Link
= RequestBlockArray
->Entry
.ForwardLink
;
3365 while ((Link
!= &RequestBlockArray
->Entry
) && (Link
->ForwardLink
!= &RequestBlockArray
->Entry
)) {
3366 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
3367 NextBlockData
= BASE_CR (Link
->ForwardLink
, IFR_BLOCK_DATA
, Entry
);
3368 if ((NextBlockData
->Offset
>= BlockData
->Offset
) && (NextBlockData
->Offset
<= (BlockData
->Offset
+ BlockData
->Width
))) {
3369 if ((NextBlockData
->Offset
+ NextBlockData
->Width
) > (BlockData
->Offset
+ BlockData
->Width
)) {
3370 BlockData
->Width
= (UINT16
)(NextBlockData
->Offset
+ NextBlockData
->Width
- BlockData
->Offset
);
3373 RemoveEntryList (Link
->ForwardLink
);
3374 FreePool (NextBlockData
);
3378 Link
= Link
->ForwardLink
;
3381 return RequestBlockArray
;
3384 if (RequestBlockArray
!= NULL
) {
3386 // Free Link Array RequestBlockArray
3388 while (!IsListEmpty (&RequestBlockArray
->Entry
)) {
3389 BlockData
= BASE_CR (RequestBlockArray
->Entry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
3390 RemoveEntryList (&BlockData
->Entry
);
3391 FreePool (BlockData
);
3394 FreePool (RequestBlockArray
);
3401 parse the configrequest string, get the elements.
3403 @param ConfigRequest The input config request string.
3404 @param Progress Return the progress data.
3406 @retval return data block array.
3410 IN EFI_STRING ConfigRequest
,
3411 OUT EFI_STRING
*Progress
3414 EFI_STRING StringPtr
;
3416 IFR_BLOCK_DATA
*BlockData
;
3417 IFR_BLOCK_DATA
*RequestBlockArray
;
3420 StringPtr
= ConfigRequest
;
3423 // Init RequestBlockArray
3425 RequestBlockArray
= (IFR_BLOCK_DATA
*)AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
3426 if (RequestBlockArray
== NULL
) {
3430 InitializeListHead (&RequestBlockArray
->Entry
);
3433 // Get the request Block array from the request string
3437 // Parse each <RequestElement> if exists
3438 // Only <BlockName> format is supported by this help function.
3439 // <BlockName> ::= &'Name***=***
3441 while (StringPtr
!= NULL
&& *StringPtr
== L
'&') {
3442 *Progress
= StringPtr
;
3444 // Skip the L"&" string
3449 if ((NextTag
= StrStr (StringPtr
, L
"=")) != NULL
) {
3452 } else if ((NextTag
= StrStr (StringPtr
, L
"&")) != NULL
) {
3459 BlockData
= (IFR_BLOCK_DATA
*)AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
3460 if (BlockData
== NULL
) {
3467 BlockData
->Name
= AllocateCopyPool (StrSize (StringPtr
), StringPtr
);
3468 InsertBlockData (&RequestBlockArray
->Entry
, &BlockData
);
3472 // If has value, skip the value.
3474 StringPtr
= NextTag
+ 1;
3476 StringPtr
= StrStr (StringPtr
, L
"&");
3477 } else if (NextTag
!= NULL
) {
3479 // restore the '&' text.
3481 StringPtr
= NextTag
;
3486 return RequestBlockArray
;
3489 if (RequestBlockArray
!= NULL
) {
3491 // Free Link Array RequestBlockArray
3493 while (!IsListEmpty (&RequestBlockArray
->Entry
)) {
3494 BlockData
= BASE_CR (RequestBlockArray
->Entry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
3495 RemoveEntryList (&BlockData
->Entry
);
3496 if (BlockData
->Name
!= NULL
) {
3497 FreePool (BlockData
->Name
);
3500 FreePool (BlockData
);
3503 FreePool (RequestBlockArray
);
3510 Generate ConfigRequest string base on the varstore info.
3512 @param ConfigHdr The config header for this varstore.
3513 @param VarStorageData The varstore info.
3514 @param Status Return Status.
3515 @param ConfigRequest The ConfigRequest info may be return.
3517 @retval TRUE Need to continue
3518 @retval Others NO need to continue or error occur.
3521 GenerateConfigRequest (
3522 IN CHAR16
*ConfigHdr
,
3523 IN IFR_VARSTORAGE_DATA
*VarStorageData
,
3524 OUT EFI_STATUS
*Status
,
3525 IN OUT EFI_STRING
*ConfigRequest
3531 CHAR16
*FullConfigRequest
;
3533 IFR_BLOCK_DATA
*BlockData
;
3536 // Append VarStorageData BlockEntry into *Request string
3537 // Now support only one varstore in a form package.
3541 // Go through all VarStorageData Entry and get BlockEntry for each one for the multiple varstore in a single form package
3542 // Then construct them all to return MultiRequest string : ConfigHdr BlockConfig
3546 // Compute the length of the entire request starting with <ConfigHdr> and a
3550 Length
= StrLen (ConfigHdr
) + 1;
3552 for (Link
= VarStorageData
->BlockEntry
.ForwardLink
; Link
!= &VarStorageData
->BlockEntry
; Link
= Link
->ForwardLink
) {
3554 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
3555 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3557 // Add <BlockName> length for each Name
3559 // <BlockName> ::= &Name1&Name2&...
3560 // |1| StrLen(Name1)
3562 Length
= Length
+ (1 + StrLen (BlockData
->Name
));
3565 // Add <BlockName> length for each Offset/Width pair
3567 // <BlockName> ::= &OFFSET=1234&WIDTH=1234
3568 // | 8 | 4 | 7 | 4 |
3570 Length
= Length
+ (8 + 4 + 7 + 4);
3575 // No any request block data is found. The request string can't be constructed.
3578 *Status
= EFI_SUCCESS
;
3583 // Allocate buffer for the entire <ConfigRequest>
3585 FullConfigRequest
= AllocateZeroPool (Length
* sizeof (CHAR16
));
3586 if (FullConfigRequest
== NULL
) {
3587 *Status
= EFI_OUT_OF_RESOURCES
;
3591 StringPtr
= FullConfigRequest
;
3594 // Start with <ConfigHdr>
3596 StrCpyS (StringPtr
, Length
, ConfigHdr
);
3597 StringPtr
+= StrLen (StringPtr
);
3600 // Loop through all the Offset/Width pairs and append them to ConfigRequest
3602 for (Link
= VarStorageData
->BlockEntry
.ForwardLink
; Link
!= &VarStorageData
->BlockEntry
; Link
= Link
->ForwardLink
) {
3603 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
3604 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3610 (1 + StrLen (BlockData
->Name
) + 1) * sizeof (CHAR16
),
3616 // Append &OFFSET=XXXX&WIDTH=YYYY\0
3620 (8 + 4 + 7 + 4 + 1) * sizeof (CHAR16
),
3621 L
"&OFFSET=%04X&WIDTH=%04X",
3627 StringPtr
+= StrLen (StringPtr
);
3631 // Set to the got full request string.
3633 HiiToLower (FullConfigRequest
);
3635 if (*ConfigRequest
!= NULL
) {
3636 FreePool (*ConfigRequest
);
3639 *ConfigRequest
= FullConfigRequest
;
3645 Generate ConfigRequest Header base on the varstore info.
3647 @param VarStorageData The varstore info.
3648 @param DevicePath Device path for this varstore.
3649 @param ConfigHdr The config header for this varstore.
3651 @retval EFI_SUCCESS Generate the header success.
3652 @retval EFI_OUT_OF_RESOURCES Allocate buffer fail.
3656 IN IFR_VARSTORAGE_DATA
*VarStorageData
,
3657 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
3658 OUT EFI_STRING
*ConfigHdr
3667 Status
= EFI_SUCCESS
;
3673 // Construct <ConfigHdr> : "GUID=...&NAME=...&PATH=..." by VarStorageData Guid, Name and DriverHandle
3675 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*)&VarStorageData
->Guid
, 1, &GuidStr
);
3676 if (VarStorageData
->Name
!= NULL
) {
3677 GenerateSubStr (L
"NAME=", StrLen (VarStorageData
->Name
) * sizeof (CHAR16
), (VOID
*)VarStorageData
->Name
, 2, &NameStr
);
3679 GenerateSubStr (L
"NAME=", 0, NULL
, 2, &NameStr
);
3684 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*)DevicePath
),
3689 Length
= StrLen (GuidStr
) + StrLen (NameStr
) + StrLen (PathStr
) + 1;
3690 if (VarStorageData
->Name
== NULL
) {
3694 *ConfigHdr
= AllocateZeroPool (Length
* sizeof (CHAR16
));
3695 if (*ConfigHdr
== NULL
) {
3696 Status
= EFI_OUT_OF_RESOURCES
;
3700 StrCpyS (*ConfigHdr
, Length
, GuidStr
);
3701 StrCatS (*ConfigHdr
, Length
, NameStr
);
3702 if (VarStorageData
->Name
== NULL
) {
3703 StrCatS (*ConfigHdr
, Length
, L
"&");
3706 StrCatS (*ConfigHdr
, Length
, PathStr
);
3709 // Remove the last character L'&'
3711 *(*ConfigHdr
+ StrLen (*ConfigHdr
) - 1) = L
'\0';
3714 if (GuidStr
!= NULL
) {
3718 if (NameStr
!= NULL
) {
3722 if (PathStr
!= NULL
) {
3730 Update the default value in the block data which is used as bit var store.
3733 A question value saved in a bit fied: bitoffset = 1; bitwidth = 2;default value = 1.
3734 And corresponding block data info: offset==0; width==1;currently the default value
3735 is saved as 1.Actually the default value 1 need to be set to bit field 1, so the
3736 default value of this block data shuold be:2.
3740 UINT8 Bit2 : 2; // Question saved in Bit2,so originalBlock info: offset = 0; width = 1;(byte level) defaul = 1.
3741 // (default value record for the bit field)
3745 After function UpdateDefaultValue,the Block info is: offset = 0; width = 1;(byte level) default = 2.
3746 (default value record for the Block)
3748 UpdateDefaultValue function update default value of bit var block based on the bit field info in the block.
3750 @param BlockLink The Link of the block data.
3754 UpdateDefaultValue (
3755 IN LIST_ENTRY
*BlockLink
3759 LIST_ENTRY
*ListEntry
;
3760 LIST_ENTRY
*LinkDefault
;
3761 IFR_BLOCK_DATA
*BlockData
;
3762 IFR_DEFAULT_DATA
*DefaultValueData
;
3765 UINT32 BitFieldDefaultValue
;
3767 for ( Link
= BlockLink
->ForwardLink
; Link
!= BlockLink
; Link
= Link
->ForwardLink
) {
3768 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
3769 if (!BlockData
->IsBitVar
) {
3773 ListEntry
= &BlockData
->DefaultValueEntry
;
3775 // Update the default value in the block data with all existing default id.
3777 for (LinkDefault
= ListEntry
->ForwardLink
; LinkDefault
!= ListEntry
; LinkDefault
= LinkDefault
->ForwardLink
) {
3779 // Get the default data, and the value of the default data is for some field in the block.
3780 // Note: Default value for bit field question is stored as UINT32.
3782 DefaultValueData
= BASE_CR (LinkDefault
, IFR_DEFAULT_DATA
, Entry
);
3783 BitFieldDefaultValue
= DefaultValueData
->Value
.u32
;
3785 StartBit
= BlockData
->BitOffset
% 8;
3786 EndBit
= StartBit
+ BlockData
->BitWidth
- 1;
3789 // Set the bit field default value to related bit filed, then we will got the new default vaule for the block data.
3791 DefaultValueData
->Value
.u32
= BitFieldWrite32 (0, StartBit
, EndBit
, BitFieldDefaultValue
);
3797 Merge the default value in two block datas which have overlap region.
3799 For bit fields, their related block data may have overlap region, such as:
3802 UINT16 Bit1 : 6; // Question1 refer Bit1, Block1: offset = 0; width = 1;(byte level) default = 1
3803 UINT16 Bit2 : 5; // Question2 refer Bit2, Block2: offset = 0; width = 2;(byte level) default = 5
3804 // (default value record for the bit field)
3808 After function UpdateDefaultValue:
3809 Block1: offset = 0; width = 1;(byte level) default = 1
3810 Block2: offset = 0; width = 2;(byte level) default = 320 (5 * (2 << 6))
3811 (default value record for block)
3813 After function MergeBlockDefaultValue:
3814 Block1: offset = 0; width = 1;(byte level) default = 65
3815 Block2: offset = 0; width = 2;(byte level) default = 321
3816 (Block1 and Block2 has overlap region, merge the overlap value to Block1 and Blcok2)
3818 Block1 and Block2 have overlap byte region, but currntly the default value of Block1 only contains
3819 value of Bit1 (low 6 bits),the default value of Block2 only contains the value of Bit2 (middle 5 bits).
3821 This fuction merge the default value of these two blocks, and make the default value of block1
3822 also contain the value of lower 2 bits of the Bit2. And make the default value of Block2 also
3823 contain the default value of Bit1.
3825 We can get the total value of the whole block that just cover these two blocks(in this case is:
3826 block: offset =0; width =2;) then the value of block2 is same as block, the value of block1 is
3827 the first byte value of block.
3829 @param FirstBlock Point to the block date whose default value need to be merged.
3830 @param SecondBlock Point to the block date whose default value need to be merged.
3834 MergeBlockDefaultValue (
3835 IN OUT IFR_BLOCK_DATA
*FirstBlock
,
3836 IN OUT IFR_BLOCK_DATA
*SecondBlock
3839 LIST_ENTRY
*FirstListEntry
;
3840 LIST_ENTRY
*SecondListEntry
;
3841 LIST_ENTRY
*FirstDefaultLink
;
3842 LIST_ENTRY
*SecondDefaultLink
;
3843 IFR_DEFAULT_DATA
*FirstDefaultValueData
;
3844 IFR_DEFAULT_DATA
*SecondDefaultValueData
;
3845 UINT32
*FirstDefaultValue
;
3846 UINT32
*SecondDefaultValue
;
3848 UINT64 ShiftedValue
;
3851 FirstListEntry
= &FirstBlock
->DefaultValueEntry
;
3852 for (FirstDefaultLink
= FirstListEntry
->ForwardLink
; FirstDefaultLink
!= FirstListEntry
; FirstDefaultLink
= FirstDefaultLink
->ForwardLink
) {
3853 FirstDefaultValueData
= BASE_CR (FirstDefaultLink
, IFR_DEFAULT_DATA
, Entry
);
3854 SecondListEntry
= &SecondBlock
->DefaultValueEntry
;
3855 for (SecondDefaultLink
= SecondListEntry
->ForwardLink
; SecondDefaultLink
!= SecondListEntry
; SecondDefaultLink
= SecondDefaultLink
->ForwardLink
) {
3856 SecondDefaultValueData
= BASE_CR (SecondDefaultLink
, IFR_DEFAULT_DATA
, Entry
);
3857 if (FirstDefaultValueData
->DefaultId
!= SecondDefaultValueData
->DefaultId
) {
3862 // Find default value with same default id in the two blocks.
3863 // Note: Default value for bit field question is stored as UINT32 type.
3865 FirstDefaultValue
= &FirstDefaultValueData
->Value
.u32
;
3866 SecondDefaultValue
= &SecondDefaultValueData
->Value
.u32
;
3868 // 1. Get the default value of the whole blcok that can just cover FirstBlock and SecondBlock.
3869 // 2. Get the default value of FirstBlock and SecondBlock form the value of whole block based
3870 // on the offset and width of FirstBlock and SecondBlock.
3872 if (FirstBlock
->Offset
> SecondBlock
->Offset
) {
3873 OffsetShift
= FirstBlock
->Offset
- SecondBlock
->Offset
;
3874 ShiftedValue
= LShiftU64 ((UINT64
)(*FirstDefaultValue
), OffsetShift
* 8);
3875 TotalValue
= ShiftedValue
| (UINT64
)(*SecondDefaultValue
);
3876 *SecondDefaultValue
= (UINT32
)BitFieldRead64 (TotalValue
, 0, SecondBlock
->Width
* 8 -1);
3877 *FirstDefaultValue
= (UINT32
)BitFieldRead64 (TotalValue
, OffsetShift
* 8, OffsetShift
* 8 + FirstBlock
->Width
*8 -1);
3879 OffsetShift
= SecondBlock
->Offset
-FirstBlock
->Offset
;
3880 ShiftedValue
= LShiftU64 ((UINT64
)(*SecondDefaultValue
), OffsetShift
* 8);
3881 TotalValue
= ShiftedValue
| (UINT64
)(*FirstDefaultValue
);
3882 *FirstDefaultValue
= (UINT32
)BitFieldRead64 (TotalValue
, 0, FirstBlock
->Width
* 8 -1);
3883 *SecondDefaultValue
= (UINT32
)BitFieldRead64 (TotalValue
, OffsetShift
* 8, OffsetShift
* 8 + SecondBlock
->Width
*8 -1);
3891 Update the default value in the block data which used as Bit VarStore
3893 @param BlockLink The Link of the block data.
3897 UpdateBlockDataArray (
3898 IN LIST_ENTRY
*BlockLink
3902 LIST_ENTRY
*TempLink
;
3903 IFR_BLOCK_DATA
*BlockData
;
3904 IFR_BLOCK_DATA
*NextBlockData
;
3907 // 1. Update default value in BitVar block data.
3908 // Sine some block datas are used as BitVarStore, then the default value recored in the block
3909 // is for related bit field in the block. so we need to set the default value to the related bit
3910 // fields in the block data if the block data is used as bit varstore, then the default value of
3911 // the block will be updated.
3913 UpdateDefaultValue (BlockLink
);
3916 // 2.Update default value for overlap BitVar blcok datas.
3917 // For block datas have overlap region, we need to merge the default value in different blocks.
3919 for (Link
= BlockLink
->ForwardLink
; Link
!= BlockLink
; Link
= Link
->ForwardLink
) {
3920 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
3921 if (!BlockData
->IsBitVar
) {
3925 for (TempLink
= Link
->ForwardLink
; TempLink
!= BlockLink
; TempLink
= TempLink
->ForwardLink
) {
3926 NextBlockData
= BASE_CR (TempLink
, IFR_BLOCK_DATA
, Entry
);
3927 if (!NextBlockData
->IsBitVar
|| (NextBlockData
->Offset
>= BlockData
->Offset
+ BlockData
->Width
) || (BlockData
->Offset
>= NextBlockData
->Offset
+ NextBlockData
->Width
)) {
3932 // Find two blocks are used as bit VarStore and have overlap region, so need to merge default value of these two blocks.
3934 MergeBlockDefaultValue (BlockData
, NextBlockData
);
3940 Generate ConfigAltResp string base on the varstore info.
3942 @param HiiHandle Hii Handle for this hii package.
3943 @param ConfigHdr The config header for this varstore.
3944 @param VarStorageData The varstore info.
3945 @param DefaultIdArray The Default id array.
3946 @param DefaultAltCfgResp The DefaultAltCfgResp info may be return.
3948 @retval TRUE Need to continue
3949 @retval Others NO need to continue or error occur.
3952 GenerateAltConfigResp (
3953 IN EFI_HII_HANDLE HiiHandle
,
3954 IN CHAR16
*ConfigHdr
,
3955 IN IFR_VARSTORAGE_DATA
*VarStorageData
,
3956 IN IFR_DEFAULT_DATA
*DefaultIdArray
,
3957 IN OUT EFI_STRING
*DefaultAltCfgResp
3963 LIST_ENTRY
*LinkData
;
3964 LIST_ENTRY
*LinkDefault
;
3965 LIST_ENTRY
*ListEntry
;
3967 IFR_BLOCK_DATA
*BlockData
;
3968 IFR_DEFAULT_DATA
*DefaultId
;
3969 IFR_DEFAULT_DATA
*DefaultValueData
;
3972 CHAR16
*DefaultString
;
3977 DefaultString
= NULL
;
3979 // Add length for <ConfigHdr> + '\0'
3981 Length
= StrLen (ConfigHdr
) + 1;
3983 UpdateBlockDataArray (&VarStorageData
->BlockEntry
);
3985 for (Link
= DefaultIdArray
->Entry
.ForwardLink
; Link
!= &DefaultIdArray
->Entry
; Link
= Link
->ForwardLink
) {
3986 DefaultId
= BASE_CR (Link
, IFR_DEFAULT_DATA
, Entry
);
3988 // Add length for "&<ConfigHdr>&ALTCFG=XXXX"
3989 // |1| StrLen (ConfigHdr) | 8 | 4 |
3991 Length
+= (1 + StrLen (ConfigHdr
) + 8 + 4);
3993 for (LinkData
= VarStorageData
->BlockEntry
.ForwardLink
; LinkData
!= &VarStorageData
->BlockEntry
; LinkData
= LinkData
->ForwardLink
) {
3994 BlockData
= BASE_CR (LinkData
, IFR_BLOCK_DATA
, Entry
);
3995 ListEntry
= &BlockData
->DefaultValueEntry
;
3996 for (LinkDefault
= ListEntry
->ForwardLink
; LinkDefault
!= ListEntry
; LinkDefault
= LinkDefault
->ForwardLink
) {
3997 DefaultValueData
= BASE_CR (LinkDefault
, IFR_DEFAULT_DATA
, Entry
);
3998 if (DefaultValueData
->DefaultId
!= DefaultId
->DefaultId
) {
4002 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
4004 // Add length for "&Name1=zzzzzzzzzzzz"
4007 Length
+= (1 + StrLen (BlockData
->Name
) + 1 + BlockData
->Width
* 2);
4010 // Add length for "&OFFSET=XXXX&WIDTH=YYYY&VALUE=zzzzzzzzzzzz"
4011 // | 8 | 4 | 7 | 4 | 7 | Width * 2 |
4013 Length
+= (8 + 4 + 7 + 4 + 7 + BlockData
->Width
* 2);
4022 // No default value is found. The default string doesn't exist.
4029 // Allocate buffer for the entire <DefaultAltCfgResp>
4031 *DefaultAltCfgResp
= AllocateZeroPool (Length
* sizeof (CHAR16
));
4032 if (*DefaultAltCfgResp
== NULL
) {
4033 return EFI_OUT_OF_RESOURCES
;
4036 StringPtr
= *DefaultAltCfgResp
;
4039 // Start with <ConfigHdr>
4041 StrCpyS (StringPtr
, Length
, ConfigHdr
);
4042 StringPtr
+= StrLen (StringPtr
);
4044 for (Link
= DefaultIdArray
->Entry
.ForwardLink
; Link
!= &DefaultIdArray
->Entry
; Link
= Link
->ForwardLink
) {
4045 DefaultId
= BASE_CR (Link
, IFR_DEFAULT_DATA
, Entry
);
4047 // Add <AltConfigHdr> of the form "&<ConfigHdr>&ALTCFG=XXXX\0"
4048 // |1| StrLen (ConfigHdr) | 8 | 4 |
4052 (1 + StrLen (ConfigHdr
) + 8 + 4 + 1) * sizeof (CHAR16
),
4055 DefaultId
->DefaultId
4057 StringPtr
+= StrLen (StringPtr
);
4059 for (LinkData
= VarStorageData
->BlockEntry
.ForwardLink
; LinkData
!= &VarStorageData
->BlockEntry
; LinkData
= LinkData
->ForwardLink
) {
4060 BlockData
= BASE_CR (LinkData
, IFR_BLOCK_DATA
, Entry
);
4061 ListEntry
= &BlockData
->DefaultValueEntry
;
4062 for (LinkDefault
= ListEntry
->ForwardLink
; LinkDefault
!= ListEntry
; LinkDefault
= LinkDefault
->ForwardLink
) {
4063 DefaultValueData
= BASE_CR (LinkDefault
, IFR_DEFAULT_DATA
, Entry
);
4064 if (DefaultValueData
->DefaultId
!= DefaultId
->DefaultId
) {
4068 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
4071 (1 + StrLen (ConfigHdr
) + 1) * sizeof (CHAR16
),
4075 StringPtr
+= StrLen (StringPtr
);
4078 // Add <BlockConfig>
4079 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>
4083 (8 + 4 + 7 + 4 + 7 + 1) * sizeof (CHAR16
),
4084 L
"&OFFSET=%04X&WIDTH=%04X&VALUE=",
4088 StringPtr
+= StrLen (StringPtr
);
4091 Width
= BlockData
->Width
;
4093 // Convert Value to a hex string in "%x" format
4094 // NOTE: This is in the opposite byte that GUID and PATH use
4096 if (BlockData
->OpCode
== EFI_IFR_STRING_OP
) {
4097 DefaultString
= InternalGetString (HiiHandle
, DefaultValueData
->Value
.string
);
4098 TmpBuffer
= AllocateZeroPool (Width
);
4099 ASSERT (TmpBuffer
!= NULL
);
4100 if (DefaultString
!= NULL
) {
4101 StrSize
= StrLen (DefaultString
)* sizeof (CHAR16
);
4102 if (StrSize
> Width
) {
4106 CopyMem (TmpBuffer
, (UINT8
*)DefaultString
, StrSize
);
4109 TmpBuffer
= (UINT8
*)&(DefaultValueData
->Value
);
4112 for ( ; Width
> 0 && (TmpBuffer
!= NULL
); Width
--) {
4113 UnicodeValueToStringS (
4115 Length
* sizeof (CHAR16
) - ((UINTN
)StringPtr
- (UINTN
)*DefaultAltCfgResp
),
4116 PREFIX_ZERO
| RADIX_HEX
,
4117 TmpBuffer
[Width
- 1],
4120 StringPtr
+= StrnLenS (StringPtr
, Length
- ((UINTN
)StringPtr
- (UINTN
)*DefaultAltCfgResp
) / sizeof (CHAR16
));
4123 if (DefaultString
!= NULL
) {
4124 FreePool (DefaultString
);
4125 DefaultString
= NULL
;
4128 if ((BlockData
->OpCode
== EFI_IFR_STRING_OP
) && (TmpBuffer
!= NULL
)) {
4129 FreePool (TmpBuffer
);
4136 HiiToLower (*DefaultAltCfgResp
);
4142 This function gets the full request string and full default value string by
4143 parsing IFR data in HII form packages.
4145 When Request points to NULL string, the request string and default value string
4146 for each varstore in form package will return.
4148 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
4149 @param DevicePath Device Path which Hii Config Access Protocol is registered.
4150 @param Request Pointer to a null-terminated Unicode string in
4151 <ConfigRequest> format. When it doesn't contain
4152 any RequestElement, it will be updated to return
4153 the full RequestElement retrieved from IFR data.
4154 If it points to NULL, the request string for the first
4155 varstore in form package will be merged into a
4156 <MultiConfigRequest> format string and return.
4157 @param AltCfgResp Pointer to a null-terminated Unicode string in
4158 <ConfigAltResp> format. When the pointer is to NULL,
4159 the full default value string retrieved from IFR data
4160 will return. When the pinter is to a string, the
4161 full default value string retrieved from IFR data
4162 will be merged into the input string and return.
4163 When Request points to NULL, the default value string
4164 for each varstore in form package will be merged into
4165 a <MultiConfigAltResp> format string and return.
4166 @param PointerProgress Optional parameter, it can be NULL.
4167 When it is not NULL, if Request is NULL, it returns NULL.
4168 On return, points to a character in the Request
4169 string. Points to the string's null terminator if
4170 request was successful. Points to the most recent
4171 & before the first failing name / value pair (or
4172 the beginning of the string if the failure is in
4173 the first name / value pair) if the request was
4175 @retval EFI_SUCCESS The Results string is set to the full request string.
4176 And AltCfgResp contains all default value string.
4177 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
4178 @retval EFI_NOT_FOUND The varstore (Guid and Name) in Request string
4179 can't be found in Form package.
4180 @retval EFI_NOT_FOUND HiiPackage can't be got on the input HiiHandle.
4181 @retval EFI_INVALID_PARAMETER Request points to NULL.
4186 GetFullStringFromHiiFormPackages (
4187 IN HII_DATABASE_RECORD
*DataBaseRecord
,
4188 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
4189 IN OUT EFI_STRING
*Request
,
4190 IN OUT EFI_STRING
*AltCfgResp
,
4191 OUT EFI_STRING
*PointerProgress OPTIONAL
4195 UINT8
*HiiFormPackage
;
4197 IFR_BLOCK_DATA
*RequestBlockArray
;
4198 IFR_BLOCK_DATA
*BlockData
;
4199 IFR_DEFAULT_DATA
*DefaultValueData
;
4200 IFR_DEFAULT_DATA
*DefaultId
;
4201 IFR_DEFAULT_DATA
*DefaultIdArray
;
4202 IFR_VARSTORAGE_DATA
*VarStorageData
;
4203 EFI_STRING DefaultAltCfgResp
;
4204 EFI_STRING ConfigHdr
;
4205 EFI_STRING StringPtr
;
4206 EFI_STRING Progress
;
4208 if ((DataBaseRecord
== NULL
) || (DevicePath
== NULL
) || (Request
== NULL
) || (AltCfgResp
== NULL
)) {
4209 return EFI_INVALID_PARAMETER
;
4213 // Initialize the local variables.
4215 RequestBlockArray
= NULL
;
4216 DefaultIdArray
= NULL
;
4217 VarStorageData
= NULL
;
4218 DefaultAltCfgResp
= NULL
;
4220 HiiFormPackage
= NULL
;
4222 Progress
= *Request
;
4224 Status
= GetFormPackageData (DataBaseRecord
, &HiiFormPackage
, &PackageSize
);
4225 if (EFI_ERROR (Status
)) {
4230 // 1. Get the request block array by Request String when Request string contains the block array.
4233 if (*Request
!= NULL
) {
4234 StringPtr
= *Request
;
4238 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
4239 Status
= EFI_INVALID_PARAMETER
;
4243 StringPtr
+= StrLen (L
"GUID=");
4244 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&NAME=", StrLen (L
"&NAME=")) != 0) {
4248 if (*StringPtr
== L
'\0') {
4249 Status
= EFI_INVALID_PARAMETER
;
4253 StringPtr
+= StrLen (L
"&NAME=");
4254 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&PATH=", StrLen (L
"&PATH=")) != 0) {
4258 if (*StringPtr
== L
'\0') {
4259 Status
= EFI_INVALID_PARAMETER
;
4263 StringPtr
+= StrLen (L
"&PATH=");
4264 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
4268 if (*StringPtr
== L
'\0') {
4270 // No request block is found.
4277 // If StringPtr != NULL, get the request elements.
4279 if (StringPtr
!= NULL
) {
4280 if (StrStr (StringPtr
, L
"&OFFSET=") != NULL
) {
4281 RequestBlockArray
= GetBlockElement (StringPtr
, &Progress
);
4283 RequestBlockArray
= GetNameElement (StringPtr
, &Progress
);
4286 if (RequestBlockArray
== NULL
) {
4287 Status
= EFI_INVALID_PARAMETER
;
4293 // Initialize DefaultIdArray to store the map between DeaultId and DefaultName
4295 DefaultIdArray
= (IFR_DEFAULT_DATA
*)AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
4296 if (DefaultIdArray
== NULL
) {
4297 Status
= EFI_OUT_OF_RESOURCES
;
4301 InitializeListHead (&DefaultIdArray
->Entry
);
4304 // Initialize VarStorageData to store the var store Block and Default value information.
4306 VarStorageData
= (IFR_VARSTORAGE_DATA
*)AllocateZeroPool (sizeof (IFR_VARSTORAGE_DATA
));
4307 if (VarStorageData
== NULL
) {
4308 Status
= EFI_OUT_OF_RESOURCES
;
4312 InitializeListHead (&VarStorageData
->Entry
);
4313 InitializeListHead (&VarStorageData
->BlockEntry
);
4316 // 2. Parse FormPackage to get BlockArray and DefaultId Array for the request BlockArray.
4320 // Parse the opcode in form package to get the default setting.
4322 Status
= ParseIfrData (
4323 DataBaseRecord
->Handle
,
4325 (UINT32
)PackageSize
,
4331 if (EFI_ERROR (Status
)) {
4336 // No requested varstore in IFR data and directly return
4338 if ((VarStorageData
->Type
== 0) && (VarStorageData
->Name
== NULL
)) {
4339 Status
= EFI_SUCCESS
;
4344 // 3. Construct Request Element (Block Name) for 2.1 and 2.2 case.
4346 Status
= GenerateHdr (VarStorageData
, DevicePath
, &ConfigHdr
);
4347 if (EFI_ERROR (Status
)) {
4351 if (RequestBlockArray
== NULL
) {
4352 if (!GenerateConfigRequest (ConfigHdr
, VarStorageData
, &Status
, Request
)) {
4358 // 4. Construct Default Value string in AltResp according to request element.
4359 // Go through all VarStorageData Entry and get the DefaultId array for each one
4360 // Then construct them all to : ConfigHdr AltConfigHdr ConfigBody AltConfigHdr ConfigBody
4362 Status
= GenerateAltConfigResp (DataBaseRecord
->Handle
, ConfigHdr
, VarStorageData
, DefaultIdArray
, &DefaultAltCfgResp
);
4363 if (EFI_ERROR (Status
)) {
4368 // 5. Merge string into the input AltCfgResp if the input *AltCfgResp is not NULL.
4370 if ((*AltCfgResp
!= NULL
) && (DefaultAltCfgResp
!= NULL
)) {
4371 Status
= MergeDefaultString (AltCfgResp
, DefaultAltCfgResp
);
4372 FreePool (DefaultAltCfgResp
);
4373 } else if (*AltCfgResp
== NULL
) {
4374 *AltCfgResp
= DefaultAltCfgResp
;
4378 if (RequestBlockArray
!= NULL
) {
4380 // Free Link Array RequestBlockArray
4382 while (!IsListEmpty (&RequestBlockArray
->Entry
)) {
4383 BlockData
= BASE_CR (RequestBlockArray
->Entry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
4384 RemoveEntryList (&BlockData
->Entry
);
4385 if (BlockData
->Name
!= NULL
) {
4386 FreePool (BlockData
->Name
);
4389 FreePool (BlockData
);
4392 FreePool (RequestBlockArray
);
4395 if (VarStorageData
!= NULL
) {
4397 // Free link array VarStorageData
4399 while (!IsListEmpty (&VarStorageData
->BlockEntry
)) {
4400 BlockData
= BASE_CR (VarStorageData
->BlockEntry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
4401 RemoveEntryList (&BlockData
->Entry
);
4402 if (BlockData
->Name
!= NULL
) {
4403 FreePool (BlockData
->Name
);
4407 // Free default value link array
4409 while (!IsListEmpty (&BlockData
->DefaultValueEntry
)) {
4410 DefaultValueData
= BASE_CR (BlockData
->DefaultValueEntry
.ForwardLink
, IFR_DEFAULT_DATA
, Entry
);
4411 RemoveEntryList (&DefaultValueData
->Entry
);
4412 FreePool (DefaultValueData
);
4415 FreePool (BlockData
);
4418 if (VarStorageData
->Name
!= NULL
) {
4419 FreePool (VarStorageData
->Name
);
4420 VarStorageData
->Name
= NULL
;
4423 FreePool (VarStorageData
);
4426 if (DefaultIdArray
!= NULL
) {
4428 // Free DefaultId Array
4430 while (!IsListEmpty (&DefaultIdArray
->Entry
)) {
4431 DefaultId
= BASE_CR (DefaultIdArray
->Entry
.ForwardLink
, IFR_DEFAULT_DATA
, Entry
);
4432 RemoveEntryList (&DefaultId
->Entry
);
4433 FreePool (DefaultId
);
4436 FreePool (DefaultIdArray
);
4440 // Free the allocated string
4442 if (ConfigHdr
!= NULL
) {
4443 FreePool (ConfigHdr
);
4447 // Free Package data
4449 if (HiiFormPackage
!= NULL
) {
4450 FreePool (HiiFormPackage
);
4453 if (PointerProgress
!= NULL
) {
4454 if (*Request
== NULL
) {
4455 *PointerProgress
= NULL
;
4456 } else if (EFI_ERROR (Status
)) {
4457 *PointerProgress
= *Request
;
4459 *PointerProgress
= *Request
+ StrLen (*Request
);
4467 This function gets the full request resp string by
4468 parsing IFR data in HII form packages.
4470 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
4472 @param EfiVarStoreInfo The efi varstore info which is save in the EFI
4473 varstore data structure.
4474 @param Request Pointer to a null-terminated Unicode string in
4475 <ConfigRequest> format.
4476 @param RequestResp Pointer to a null-terminated Unicode string in
4477 <ConfigResp> format.
4478 @param AccessProgress On return, points to a character in the Request
4479 string. Points to the string's null terminator if
4480 request was successful. Points to the most recent
4481 & before the first failing name / value pair (or
4482 the beginning of the string if the failure is in
4483 the first name / value pair) if the request was
4486 @retval EFI_SUCCESS The Results string is set to the full request string.
4487 And AltCfgResp contains all default value string.
4488 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
4489 @retval EFI_INVALID_PARAMETER Request points to NULL.
4493 GetConfigRespFromEfiVarStore (
4494 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
4495 IN EFI_IFR_VARSTORE_EFI
*EfiVarStoreInfo
,
4496 IN EFI_STRING Request
,
4497 OUT EFI_STRING
*RequestResp
,
4498 OUT EFI_STRING
*AccessProgress
4502 EFI_STRING VarStoreName
;
4507 Status
= EFI_SUCCESS
;
4510 VarStoreName
= NULL
;
4511 *AccessProgress
= Request
;
4513 NameSize
= AsciiStrSize ((CHAR8
*)EfiVarStoreInfo
->Name
);
4514 VarStoreName
= AllocateZeroPool (NameSize
* sizeof (CHAR16
));
4515 if (VarStoreName
== NULL
) {
4516 Status
= EFI_OUT_OF_RESOURCES
;
4520 AsciiStrToUnicodeStrS ((CHAR8
*)EfiVarStoreInfo
->Name
, VarStoreName
, NameSize
);
4522 Status
= gRT
->GetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, NULL
, &BufferSize
, NULL
);
4523 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
4527 VarStore
= AllocateZeroPool (BufferSize
);
4528 ASSERT (VarStore
!= NULL
);
4529 Status
= gRT
->GetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, NULL
, &BufferSize
, VarStore
);
4530 if (EFI_ERROR (Status
)) {
4534 Status
= HiiBlockToConfig (This
, Request
, VarStore
, BufferSize
, RequestResp
, AccessProgress
);
4535 if (EFI_ERROR (Status
)) {
4540 if (VarStoreName
!= NULL
) {
4541 FreePool (VarStoreName
);
4544 if (VarStore
!= NULL
) {
4545 FreePool (VarStore
);
4552 This function route the full request resp string for efi varstore.
4554 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
4556 @param EfiVarStoreInfo The efi varstore info which is save in the EFI
4557 varstore data structure.
4558 @param RequestResp Pointer to a null-terminated Unicode string in
4559 <ConfigResp> format.
4560 @param Result Pointer to a null-terminated Unicode string in
4561 <ConfigResp> format.
4563 @retval EFI_SUCCESS The Results string is set to the full request string.
4564 And AltCfgResp contains all default value string.
4565 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
4566 @retval EFI_INVALID_PARAMETER Request points to NULL.
4570 RouteConfigRespForEfiVarStore (
4571 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
4572 IN EFI_IFR_VARSTORE_EFI
*EfiVarStoreInfo
,
4573 IN EFI_STRING RequestResp
,
4574 OUT EFI_STRING
*Result
4578 EFI_STRING VarStoreName
;
4584 Status
= EFI_SUCCESS
;
4587 VarStoreName
= NULL
;
4588 *Result
= RequestResp
;
4590 NameSize
= AsciiStrSize ((CHAR8
*)EfiVarStoreInfo
->Name
);
4591 VarStoreName
= AllocateZeroPool (NameSize
* sizeof (CHAR16
));
4592 if (VarStoreName
== NULL
) {
4593 Status
= EFI_OUT_OF_RESOURCES
;
4597 AsciiStrToUnicodeStrS ((CHAR8
*)EfiVarStoreInfo
->Name
, VarStoreName
, NameSize
);
4599 Status
= gRT
->GetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, NULL
, &BufferSize
, NULL
);
4600 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
4601 DEBUG ((DEBUG_ERROR
, "The variable does not exist!"));
4605 BlockSize
= BufferSize
;
4606 VarStore
= AllocateZeroPool (BufferSize
);
4607 ASSERT (VarStore
!= NULL
);
4608 Status
= gRT
->GetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, NULL
, &BufferSize
, VarStore
);
4609 if (EFI_ERROR (Status
)) {
4613 Status
= HiiConfigToBlock (This
, RequestResp
, VarStore
, &BlockSize
, Result
);
4614 if (EFI_ERROR (Status
)) {
4618 Status
= gRT
->SetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, EfiVarStoreInfo
->Attributes
, BufferSize
, VarStore
);
4619 if (EFI_ERROR (Status
)) {
4620 *Result
= RequestResp
;
4625 if (VarStoreName
!= NULL
) {
4626 FreePool (VarStoreName
);
4629 if (VarStore
!= NULL
) {
4630 FreePool (VarStore
);
4637 Validate the config request elements.
4639 @param ConfigElements A null-terminated Unicode string in <ConfigRequest> format,
4640 without configHdr field.
4642 @retval CHAR16 * THE first Name/value pair not correct.
4643 @retval NULL Success parse the name/value pair
4646 OffsetWidthValidate (
4647 CHAR16
*ConfigElements
4653 StringPtr
= ConfigElements
;
4657 if (StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) != 0) {
4661 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
4665 if (*StringPtr
== L
'\0') {
4669 StringPtr
+= StrLen (L
"&WIDTH=");
4670 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) != 0) {
4674 if (*StringPtr
== L
'\0') {
4681 Validate the config request elements.
4683 @param ConfigElements A null-terminated Unicode string in <ConfigRequest> format,
4684 without configHdr field.
4686 @retval CHAR16 * THE first Name/value pair not correct.
4687 @retval NULL Success parse the name/value pair
4692 CHAR16
*ConfigElements
4698 StringPtr
= ConfigElements
;
4702 if (*StringPtr
!= L
'&') {
4708 StringPtr
= StrStr (StringPtr
, L
"&");
4710 if (StringPtr
== NULL
) {
4717 Validate the config request string.
4719 @param ConfigRequest A null-terminated Unicode string in <ConfigRequest> format.
4721 @retval CHAR16 * THE first element not correct.
4722 @retval NULL Success parse the name/value pair
4726 ConfigRequestValidate (
4727 CHAR16
*ConfigRequest
4730 BOOLEAN HasNameField
;
4733 HasNameField
= TRUE
;
4734 StringPtr
= ConfigRequest
;
4737 // Check <ConfigHdr>
4739 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
4740 return ConfigRequest
;
4743 StringPtr
+= StrLen (L
"GUID=");
4744 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&NAME=", StrLen (L
"&NAME=")) != 0) {
4748 if (*StringPtr
== L
'\0') {
4749 return ConfigRequest
;
4752 StringPtr
+= StrLen (L
"&NAME=");
4753 if (*StringPtr
== L
'&') {
4754 HasNameField
= FALSE
;
4757 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&PATH=", StrLen (L
"&PATH=")) != 0) {
4761 if (*StringPtr
== L
'\0') {
4762 return ConfigRequest
;
4765 StringPtr
+= StrLen (L
"&PATH=");
4766 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
4770 if (*StringPtr
== L
'\0') {
4776 // Should be Buffer varstore, config request should be "OFFSET/Width" pairs.
4778 return OffsetWidthValidate (StringPtr
);
4781 // Should be Name/Value varstore, config request should be "&name1&name2..." pairs.
4783 return NameValueValidate (StringPtr
);
4788 This function allows a caller to extract the current configuration
4789 for one or more named elements from one or more drivers.
4791 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
4793 @param Request A null-terminated Unicode string in
4794 <MultiConfigRequest> format.
4795 @param Progress On return, points to a character in the Request
4796 string. Points to the string's null terminator if
4797 request was successful. Points to the most recent
4798 & before the first failing name / value pair (or
4799 the beginning of the string if the failure is in
4800 the first name / value pair) if the request was
4802 @param Results Null-terminated Unicode string in
4803 <MultiConfigAltResp> format which has all values
4804 filled in for the names in the Request string.
4805 String to be allocated by the called function.
4807 @retval EFI_SUCCESS The Results string is filled with the values
4808 corresponding to all requested names.
4809 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
4810 results that must be stored awaiting possible
4812 @retval EFI_NOT_FOUND Routing data doesn't match any known driver.
4813 Progress set to the "G" in "GUID" of the routing
4814 header that doesn't match. Note: There is no
4815 requirement that all routing data be validated
4816 before any configuration extraction.
4817 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Request
4818 parameter would result in this type of error. The
4819 Progress parameter is set to NULL.
4820 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set to most recent &
4821 before the error or the beginning of the string.
4822 @retval EFI_INVALID_PARAMETER The ExtractConfig function of the underlying HII
4823 Configuration Access Protocol returned
4824 EFI_INVALID_PARAMETER. Progress set to most recent
4825 & before the error or the beginning of the string.
4830 HiiConfigRoutingExtractConfig (
4831 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
4832 IN CONST EFI_STRING Request
,
4833 OUT EFI_STRING
*Progress
,
4834 OUT EFI_STRING
*Results
4837 HII_DATABASE_PRIVATE_DATA
*Private
;
4838 EFI_STRING StringPtr
;
4839 EFI_STRING ConfigRequest
;
4841 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
4842 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
4845 HII_DATABASE_RECORD
*Database
;
4846 UINT8
*DevicePathPkg
;
4847 UINT8
*CurrentDevicePath
;
4848 EFI_HANDLE DriverHandle
;
4849 EFI_HII_HANDLE HiiHandle
;
4850 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
4851 EFI_STRING AccessProgress
;
4852 EFI_STRING AccessResults
;
4853 EFI_STRING AccessProgressBackup
;
4854 EFI_STRING AccessResultsBackup
;
4855 EFI_STRING DefaultResults
;
4856 BOOLEAN FirstElement
;
4857 BOOLEAN IfrDataParsedFlag
;
4858 BOOLEAN IsEfiVarStore
;
4859 EFI_IFR_VARSTORE_EFI
*EfiVarStoreInfo
;
4860 EFI_STRING ErrorPtr
;
4861 UINTN DevicePathSize
;
4862 UINTN ConigStringSize
;
4863 UINTN ConigStringSizeNewsize
;
4864 EFI_STRING ConfigStringPtr
;
4866 if ((This
== NULL
) || (Progress
== NULL
) || (Results
== NULL
)) {
4867 return EFI_INVALID_PARAMETER
;
4870 if (Request
== NULL
) {
4872 return EFI_INVALID_PARAMETER
;
4875 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
4876 StringPtr
= Request
;
4877 *Progress
= StringPtr
;
4878 DefaultResults
= NULL
;
4879 ConfigRequest
= NULL
;
4880 Status
= EFI_SUCCESS
;
4881 AccessResults
= NULL
;
4882 AccessProgress
= NULL
;
4883 AccessResultsBackup
= NULL
;
4884 AccessProgressBackup
= NULL
;
4886 IfrDataParsedFlag
= FALSE
;
4887 IsEfiVarStore
= FALSE
;
4888 EfiVarStoreInfo
= NULL
;
4891 // The first element of <MultiConfigRequest> should be
4892 // <GuidHdr>, which is in 'GUID='<Guid> syntax.
4894 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
4895 return EFI_INVALID_PARAMETER
;
4898 FirstElement
= TRUE
;
4901 // Allocate a fix length of memory to store Results. Reallocate memory for
4902 // Results if this fix length is insufficient.
4904 *Results
= (EFI_STRING
)AllocateZeroPool (MAX_STRING_LENGTH
);
4905 if (*Results
== NULL
) {
4906 return EFI_OUT_OF_RESOURCES
;
4909 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) == 0) {
4911 // If parsing error, set Progress to the beginning of the <MultiConfigRequest>
4912 // or most recent & before the error.
4914 if (StringPtr
== Request
) {
4915 *Progress
= StringPtr
;
4917 *Progress
= StringPtr
- 1;
4921 // Process each <ConfigRequest> of <MultiConfigRequest>
4923 Length
= CalculateConfigStringLen (StringPtr
);
4924 ConfigRequest
= AllocateCopyPool ((Length
+ 1) * sizeof (CHAR16
), StringPtr
);
4925 if (ConfigRequest
== NULL
) {
4926 Status
= EFI_OUT_OF_RESOURCES
;
4930 *(ConfigRequest
+ Length
) = 0;
4933 // Get the UEFI device path
4935 Status
= GetDevicePath (ConfigRequest
, (UINT8
**)&DevicePath
);
4936 if (EFI_ERROR (Status
)) {
4941 // Find driver which matches the routing data.
4943 DriverHandle
= NULL
;
4946 for (Link
= Private
->DatabaseList
.ForwardLink
;
4947 Link
!= &Private
->DatabaseList
;
4948 Link
= Link
->ForwardLink
4951 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
4952 if ((DevicePathPkg
= Database
->PackageList
->DevicePathPkg
) != NULL
) {
4953 CurrentDevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
4954 DevicePathSize
= GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*)CurrentDevicePath
);
4955 if ((CompareMem (DevicePath
, CurrentDevicePath
, DevicePathSize
) == 0) && IsThisPackageList (Database
, ConfigRequest
)) {
4956 DriverHandle
= Database
->DriverHandle
;
4957 HiiHandle
= Database
->Handle
;
4964 // Try to find driver handle by device path.
4966 if (DriverHandle
== NULL
) {
4967 TempDevicePath
= DevicePath
;
4968 Status
= gBS
->LocateDevicePath (
4969 &gEfiDevicePathProtocolGuid
,
4973 if (EFI_ERROR (Status
) || (DriverHandle
== NULL
)) {
4975 // Routing data does not match any known driver.
4976 // Set Progress to the 'G' in "GUID" of the routing header.
4978 *Progress
= StringPtr
;
4979 Status
= EFI_NOT_FOUND
;
4985 // Validate ConfigRequest String.
4987 ErrorPtr
= ConfigRequestValidate (ConfigRequest
);
4988 if (ErrorPtr
!= NULL
) {
4989 *Progress
= StrStr (StringPtr
, ErrorPtr
);
4990 Status
= EFI_INVALID_PARAMETER
;
4995 // Check whether ConfigRequest contains request string.
4997 IfrDataParsedFlag
= FALSE
;
4998 if ((HiiHandle
!= NULL
) && !GetElementsFromRequest (ConfigRequest
)) {
5000 // Get the full request string from IFR when HiiPackage is registered to HiiHandle
5002 IfrDataParsedFlag
= TRUE
;
5003 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &ConfigRequest
, &DefaultResults
, &AccessProgress
);
5004 if (EFI_ERROR (Status
)) {
5006 // AccessProgress indicates the parsing progress on <ConfigRequest>.
5007 // Map it to the progress on <MultiConfigRequest> then return it.
5009 ASSERT (AccessProgress
!= NULL
);
5010 *Progress
= StrStr (StringPtr
, AccessProgress
);
5015 // Not any request block is found.
5017 if (!GetElementsFromRequest (ConfigRequest
)) {
5018 AccessResults
= AllocateCopyPool (StrSize (ConfigRequest
), ConfigRequest
);
5019 goto NextConfigString
;
5024 // Check whether this ConfigRequest is search from Efi varstore type storage.
5026 Status
= GetVarStoreType (Database
, ConfigRequest
, &IsEfiVarStore
, &EfiVarStoreInfo
);
5027 if (EFI_ERROR (Status
)) {
5031 if (IsEfiVarStore
) {
5033 // Call the GetVariable function to extract settings.
5035 Status
= GetConfigRespFromEfiVarStore (This
, EfiVarStoreInfo
, ConfigRequest
, &AccessResults
, &AccessProgress
);
5036 FreePool (EfiVarStoreInfo
);
5037 if (EFI_ERROR (Status
)) {
5039 // AccessProgress indicates the parsing progress on <ConfigRequest>.
5040 // Map it to the progress on <MultiConfigRequest> then return it.
5042 *Progress
= StrStr (StringPtr
, AccessProgress
);
5047 // For EfiVarstore, call corresponding ConfigAccess protocol to get the AltCfgResp from driver.
5049 Status
= gBS
->HandleProtocol (
5051 &gEfiHiiConfigAccessProtocolGuid
,
5052 (VOID
**)&ConfigAccess
5054 if (EFI_ERROR (Status
)) {
5056 // The driver has EfiVarStore, may not install ConfigAccess protocol.
5057 // So ignore the error status in this case.
5059 Status
= EFI_SUCCESS
;
5061 Status
= ConfigAccess
->ExtractConfig (
5064 &AccessProgressBackup
,
5065 &AccessResultsBackup
5067 if (!EFI_ERROR (Status
)) {
5069 // Merge the AltCfgResp in AccessResultsBackup to AccessResults
5071 if ((AccessResultsBackup
!= NULL
) && (StrStr (AccessResultsBackup
, L
"&ALTCFG=") != NULL
)) {
5072 ConigStringSize
= StrSize (AccessResults
);
5073 ConfigStringPtr
= StrStr (AccessResultsBackup
, L
"&GUID=");
5074 ConigStringSizeNewsize
= StrSize (ConfigStringPtr
) + ConigStringSize
+ sizeof (CHAR16
);
5075 AccessResults
= (EFI_STRING
)ReallocatePool (
5077 ConigStringSizeNewsize
,
5080 StrCatS (AccessResults
, ConigStringSizeNewsize
/ sizeof (CHAR16
), ConfigStringPtr
);
5084 // In the ExtractConfig function of some driver may not support EfiVarStore,
5085 // may return error status, just ignore the error status in this case.
5087 Status
= EFI_SUCCESS
;
5090 if (AccessResultsBackup
!= NULL
) {
5091 FreePool (AccessResultsBackup
);
5092 AccessResultsBackup
= NULL
;
5097 // Call corresponding ConfigAccess protocol to extract settings
5099 Status
= gBS
->HandleProtocol (
5101 &gEfiHiiConfigAccessProtocolGuid
,
5102 (VOID
**)&ConfigAccess
5104 if (EFI_ERROR (Status
)) {
5108 Status
= ConfigAccess
->ExtractConfig (
5116 if (EFI_ERROR (Status
)) {
5118 // AccessProgress indicates the parsing progress on <ConfigRequest>.
5119 // Map it to the progress on <MultiConfigRequest> then return it.
5121 *Progress
= StrStr (StringPtr
, AccessProgress
);
5126 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'
5127 // which separates the first <ConfigAltResp> and the following ones.
5129 ASSERT (*AccessProgress
== 0);
5132 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
5134 if (!IfrDataParsedFlag
&& (HiiHandle
!= NULL
)) {
5135 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &ConfigRequest
, &DefaultResults
, NULL
);
5136 ASSERT_EFI_ERROR (Status
);
5139 FreePool (DevicePath
);
5142 if (DefaultResults
!= NULL
) {
5143 Status
= MergeDefaultString (&AccessResults
, DefaultResults
);
5144 ASSERT_EFI_ERROR (Status
);
5145 FreePool (DefaultResults
);
5146 DefaultResults
= NULL
;
5150 if (!FirstElement
) {
5151 Status
= AppendToMultiString (Results
, L
"&");
5152 ASSERT_EFI_ERROR (Status
);
5155 Status
= AppendToMultiString (Results
, AccessResults
);
5156 ASSERT_EFI_ERROR (Status
);
5158 FirstElement
= FALSE
;
5160 FreePool (AccessResults
);
5161 AccessResults
= NULL
;
5162 FreePool (ConfigRequest
);
5163 ConfigRequest
= NULL
;
5166 // Go to next <ConfigRequest> (skip '&').
5168 StringPtr
+= Length
;
5169 if (*StringPtr
== 0) {
5170 *Progress
= StringPtr
;
5178 if (EFI_ERROR (Status
)) {
5179 FreePool (*Results
);
5183 if (ConfigRequest
!= NULL
) {
5184 FreePool (ConfigRequest
);
5187 if (AccessResults
!= NULL
) {
5188 FreePool (AccessResults
);
5191 if (DefaultResults
!= NULL
) {
5192 FreePool (DefaultResults
);
5195 if (DevicePath
!= NULL
) {
5196 FreePool (DevicePath
);
5203 This function allows the caller to request the current configuration for the
5204 entirety of the current HII database and returns the data in a
5205 null-terminated Unicode string.
5207 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
5209 @param Results Null-terminated Unicode string in
5210 <MultiConfigAltResp> format which has all values
5211 filled in for the entirety of the current HII
5212 database. String to be allocated by the called
5213 function. De-allocation is up to the caller.
5215 @retval EFI_SUCCESS The Results string is filled with the values
5216 corresponding to all requested names.
5217 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
5218 results that must be stored awaiting possible
5220 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Results
5221 parameter would result in this type of error.
5226 HiiConfigRoutingExportConfig (
5227 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
5228 OUT EFI_STRING
*Results
5232 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
5233 EFI_STRING AccessResults
;
5234 EFI_STRING Progress
;
5235 EFI_STRING StringPtr
;
5236 EFI_STRING ConfigRequest
;
5238 EFI_HANDLE
*ConfigAccessHandles
;
5239 UINTN NumberConfigAccessHandles
;
5240 BOOLEAN FirstElement
;
5241 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
5242 EFI_HII_HANDLE HiiHandle
;
5243 EFI_STRING DefaultResults
;
5244 HII_DATABASE_PRIVATE_DATA
*Private
;
5246 HII_DATABASE_RECORD
*Database
;
5247 UINT8
*DevicePathPkg
;
5248 UINT8
*CurrentDevicePath
;
5249 BOOLEAN IfrDataParsedFlag
;
5251 if ((This
== NULL
) || (Results
== NULL
)) {
5252 return EFI_INVALID_PARAMETER
;
5255 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
5258 // Allocate a fix length of memory to store Results. Reallocate memory for
5259 // Results if this fix length is insufficient.
5261 *Results
= (EFI_STRING
)AllocateZeroPool (MAX_STRING_LENGTH
);
5262 if (*Results
== NULL
) {
5263 return EFI_OUT_OF_RESOURCES
;
5266 NumberConfigAccessHandles
= 0;
5267 Status
= gBS
->LocateHandleBuffer (
5269 &gEfiHiiConfigAccessProtocolGuid
,
5271 &NumberConfigAccessHandles
,
5272 &ConfigAccessHandles
5274 if (EFI_ERROR (Status
)) {
5278 FirstElement
= TRUE
;
5280 for (Index
= 0; Index
< NumberConfigAccessHandles
; Index
++) {
5281 Status
= gBS
->HandleProtocol (
5282 ConfigAccessHandles
[Index
],
5283 &gEfiHiiConfigAccessProtocolGuid
,
5284 (VOID
**)&ConfigAccess
5286 if (EFI_ERROR (Status
)) {
5291 // Get DevicePath and HiiHandle for this ConfigAccess driver handle
5293 IfrDataParsedFlag
= FALSE
;
5296 DefaultResults
= NULL
;
5298 ConfigRequest
= NULL
;
5299 DevicePath
= DevicePathFromHandle (ConfigAccessHandles
[Index
]);
5300 if (DevicePath
!= NULL
) {
5301 for (Link
= Private
->DatabaseList
.ForwardLink
;
5302 Link
!= &Private
->DatabaseList
;
5303 Link
= Link
->ForwardLink
5306 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
5307 if ((DevicePathPkg
= Database
->PackageList
->DevicePathPkg
) != NULL
) {
5308 CurrentDevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
5312 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*)CurrentDevicePath
)
5315 HiiHandle
= Database
->Handle
;
5322 Status
= ConfigAccess
->ExtractConfig (
5328 if (EFI_ERROR (Status
)) {
5330 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
5332 if ((HiiHandle
!= NULL
) && (DevicePath
!= NULL
)) {
5333 IfrDataParsedFlag
= TRUE
;
5334 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &ConfigRequest
, &DefaultResults
, NULL
);
5336 // Get the full request string to get the Current setting again.
5338 if (!EFI_ERROR (Status
) && (ConfigRequest
!= NULL
)) {
5339 Status
= ConfigAccess
->ExtractConfig (
5345 FreePool (ConfigRequest
);
5347 Status
= EFI_NOT_FOUND
;
5352 if (!EFI_ERROR (Status
)) {
5354 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
5356 if (!IfrDataParsedFlag
&& (HiiHandle
!= NULL
) && (DevicePath
!= NULL
)) {
5357 StringPtr
= StrStr (AccessResults
, L
"&GUID=");
5358 if (StringPtr
!= NULL
) {
5362 if (GetElementsFromRequest (AccessResults
)) {
5363 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &AccessResults
, &DefaultResults
, NULL
);
5364 ASSERT_EFI_ERROR (Status
);
5367 if (StringPtr
!= NULL
) {
5373 // Merge the default sting from IFR code into the got setting from driver.
5375 if (DefaultResults
!= NULL
) {
5376 Status
= MergeDefaultString (&AccessResults
, DefaultResults
);
5377 ASSERT_EFI_ERROR (Status
);
5378 FreePool (DefaultResults
);
5379 DefaultResults
= NULL
;
5383 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'
5384 // which separates the first <ConfigAltResp> and the following ones.
5386 if (!FirstElement
) {
5387 Status
= AppendToMultiString (Results
, L
"&");
5388 ASSERT_EFI_ERROR (Status
);
5391 Status
= AppendToMultiString (Results
, AccessResults
);
5392 ASSERT_EFI_ERROR (Status
);
5394 FirstElement
= FALSE
;
5396 FreePool (AccessResults
);
5397 AccessResults
= NULL
;
5401 FreePool (ConfigAccessHandles
);
5407 This function processes the results of processing forms and routes it to the
5408 appropriate handlers or storage.
5410 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
5412 @param Configuration A null-terminated Unicode string in
5413 <MulltiConfigResp> format.
5414 @param Progress A pointer to a string filled in with the offset of
5415 the most recent & before the first failing name /
5416 value pair (or the beginning of the string if the
5417 failure is in the first name / value pair) or the
5418 terminating NULL if all was successful.
5420 @retval EFI_SUCCESS The results have been distributed or are awaiting
5422 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
5423 results that must be stored awaiting possible
5425 @retval EFI_INVALID_PARAMETER Passing in a NULL for the Configuration parameter
5426 would result in this type of error.
5427 @retval EFI_NOT_FOUND Target for the specified routing data was not
5433 HiiConfigRoutingRouteConfig (
5434 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
5435 IN CONST EFI_STRING Configuration
,
5436 OUT EFI_STRING
*Progress
5439 HII_DATABASE_PRIVATE_DATA
*Private
;
5440 EFI_STRING StringPtr
;
5441 EFI_STRING ConfigResp
;
5444 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
5445 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
5447 HII_DATABASE_RECORD
*Database
;
5448 UINT8
*DevicePathPkg
;
5449 UINT8
*CurrentDevicePath
;
5450 EFI_HANDLE DriverHandle
;
5451 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
5452 EFI_STRING AccessProgress
;
5453 EFI_IFR_VARSTORE_EFI
*EfiVarStoreInfo
;
5454 BOOLEAN IsEfiVarstore
;
5455 UINTN DevicePathSize
;
5457 if ((This
== NULL
) || (Progress
== NULL
)) {
5458 return EFI_INVALID_PARAMETER
;
5461 if (Configuration
== NULL
) {
5463 return EFI_INVALID_PARAMETER
;
5466 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
5467 StringPtr
= Configuration
;
5468 *Progress
= StringPtr
;
5470 AccessProgress
= NULL
;
5471 EfiVarStoreInfo
= NULL
;
5472 IsEfiVarstore
= FALSE
;
5475 // The first element of <MultiConfigResp> should be
5476 // <GuidHdr>, which is in 'GUID='<Guid> syntax.
5478 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
5479 return EFI_INVALID_PARAMETER
;
5482 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) == 0) {
5484 // If parsing error, set Progress to the beginning of the <MultiConfigResp>
5485 // or most recent & before the error.
5487 if (StringPtr
== Configuration
) {
5488 *Progress
= StringPtr
;
5490 *Progress
= StringPtr
- 1;
5494 // Process each <ConfigResp> of <MultiConfigResp>
5496 Length
= CalculateConfigStringLen (StringPtr
);
5497 ConfigResp
= AllocateCopyPool ((Length
+ 1) * sizeof (CHAR16
), StringPtr
);
5498 if (ConfigResp
== NULL
) {
5499 return EFI_OUT_OF_RESOURCES
;
5503 // Append '\0' to the end of ConfigRequest
5505 *(ConfigResp
+ Length
) = 0;
5508 // Get the UEFI device path
5510 Status
= GetDevicePath (ConfigResp
, (UINT8
**)&DevicePath
);
5511 if (EFI_ERROR (Status
)) {
5512 FreePool (ConfigResp
);
5517 // Find driver which matches the routing data.
5519 DriverHandle
= NULL
;
5520 for (Link
= Private
->DatabaseList
.ForwardLink
;
5521 Link
!= &Private
->DatabaseList
;
5522 Link
= Link
->ForwardLink
5525 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
5527 if ((DevicePathPkg
= Database
->PackageList
->DevicePathPkg
) != NULL
) {
5528 CurrentDevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
5529 DevicePathSize
= GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*)CurrentDevicePath
);
5530 if ((CompareMem (DevicePath
, CurrentDevicePath
, DevicePathSize
) == 0) && IsThisPackageList (Database
, ConfigResp
)) {
5531 DriverHandle
= Database
->DriverHandle
;
5538 // Try to find driver handle by device path.
5540 if (DriverHandle
== NULL
) {
5541 TempDevicePath
= DevicePath
;
5542 Status
= gBS
->LocateDevicePath (
5543 &gEfiDevicePathProtocolGuid
,
5547 if (EFI_ERROR (Status
) || (DriverHandle
== NULL
)) {
5549 // Routing data does not match any known driver.
5550 // Set Progress to the 'G' in "GUID" of the routing header.
5552 FreePool (DevicePath
);
5553 *Progress
= StringPtr
;
5554 FreePool (ConfigResp
);
5555 return EFI_NOT_FOUND
;
5559 FreePool (DevicePath
);
5562 // Check whether this ConfigRequest is search from Efi varstore type storage.
5564 Status
= GetVarStoreType (Database
, ConfigResp
, &IsEfiVarstore
, &EfiVarStoreInfo
);
5565 if (EFI_ERROR (Status
)) {
5569 if (IsEfiVarstore
) {
5571 // Call the SetVariable function to route settings.
5573 Status
= RouteConfigRespForEfiVarStore (This
, EfiVarStoreInfo
, ConfigResp
, &AccessProgress
);
5574 FreePool (EfiVarStoreInfo
);
5577 // Call corresponding ConfigAccess protocol to route settings
5579 Status
= gBS
->HandleProtocol (
5581 &gEfiHiiConfigAccessProtocolGuid
,
5582 (VOID
**)&ConfigAccess
5584 if (EFI_ERROR (Status
)) {
5585 *Progress
= StringPtr
;
5586 FreePool (ConfigResp
);
5587 return EFI_NOT_FOUND
;
5590 Status
= ConfigAccess
->RouteConfig (
5597 if (EFI_ERROR (Status
)) {
5598 ASSERT (AccessProgress
!= NULL
);
5600 // AccessProgress indicates the parsing progress on <ConfigResp>.
5601 // Map it to the progress on <MultiConfigResp> then return it.
5603 *Progress
= StrStr (StringPtr
, AccessProgress
);
5605 FreePool (ConfigResp
);
5609 FreePool (ConfigResp
);
5613 // Go to next <ConfigResp> (skip '&').
5615 StringPtr
+= Length
;
5616 if (*StringPtr
== 0) {
5617 *Progress
= StringPtr
;
5628 This helper function is to be called by drivers to map configuration data
5629 stored in byte array ("block") formats such as UEFI Variables into current
5630 configuration strings.
5632 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
5634 @param ConfigRequest A null-terminated Unicode string in
5635 <ConfigRequest> format.
5636 @param Block Array of bytes defining the block's configuration.
5637 @param BlockSize Length in bytes of Block.
5638 @param Config Filled-in configuration string. String allocated
5639 by the function. Returned only if call is
5640 successful. It is <ConfigResp> string format.
5641 @param Progress A pointer to a string filled in with the offset of
5642 the most recent & before the first failing
5643 name/value pair (or the beginning of the string if
5644 the failure is in the first name / value pair) or
5645 the terminating NULL if all was successful.
5647 @retval EFI_SUCCESS The request succeeded. Progress points to the null
5648 terminator at the end of the ConfigRequest
5650 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress
5651 points to the first character of ConfigRequest.
5652 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigRequest or
5653 Block parameter would result in this type of
5654 error. Progress points to the first character of
5656 @retval EFI_DEVICE_ERROR Block not large enough. Progress undefined.
5657 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted string.
5658 Block is left updated and Progress points at
5659 the "&" preceding the first non-<BlockName>.
5665 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
5666 IN CONST EFI_STRING ConfigRequest
,
5667 IN CONST UINT8
*Block
,
5668 IN CONST UINTN BlockSize
,
5669 OUT EFI_STRING
*Config
,
5670 OUT EFI_STRING
*Progress
5673 HII_DATABASE_PRIVATE_DATA
*Private
;
5674 EFI_STRING StringPtr
;
5682 EFI_STRING ValueStr
;
5683 EFI_STRING ConfigElement
;
5690 if ((This
== NULL
) || (Progress
== NULL
) || (Config
== NULL
)) {
5691 return EFI_INVALID_PARAMETER
;
5694 if ((Block
== NULL
) || (ConfigRequest
== NULL
)) {
5695 *Progress
= ConfigRequest
;
5696 return EFI_INVALID_PARAMETER
;
5699 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
5700 ASSERT (Private
!= NULL
);
5702 StringPtr
= ConfigRequest
;
5705 ConfigElement
= NULL
;
5708 // Allocate a fix length of memory to store Results. Reallocate memory for
5709 // Results if this fix length is insufficient.
5711 *Config
= (EFI_STRING
)AllocateZeroPool (MAX_STRING_LENGTH
);
5712 if (*Config
== NULL
) {
5713 return EFI_OUT_OF_RESOURCES
;
5719 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
5720 *Progress
= StringPtr
;
5721 Status
= EFI_INVALID_PARAMETER
;
5725 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"PATH=", StrLen (L
"PATH=")) != 0) {
5729 if (*StringPtr
== 0) {
5730 *Progress
= StringPtr
- 1;
5731 Status
= EFI_INVALID_PARAMETER
;
5735 while (*StringPtr
!= L
'&' && *StringPtr
!= 0) {
5739 if (*StringPtr
== 0) {
5740 *Progress
= StringPtr
;
5742 AppendToMultiString (Config
, ConfigRequest
);
5743 HiiToLower (*Config
);
5754 // Copy <ConfigHdr> and an additional '&' to <ConfigResp>
5756 TemString
= AllocateCopyPool (sizeof (CHAR16
) * (StringPtr
- ConfigRequest
+ 1), ConfigRequest
);
5757 if (TemString
== NULL
) {
5758 return EFI_OUT_OF_RESOURCES
;
5761 TemString
[StringPtr
- ConfigRequest
] = '\0';
5762 AppendToMultiString (Config
, TemString
);
5763 FreePool (TemString
);
5766 // Parse each <RequestElement> if exists
5767 // Only <BlockName> format is supported by this help function.
5768 // <BlockName> ::= 'OFFSET='<Number>&'WIDTH='<Number>
5770 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"OFFSET=", StrLen (L
"OFFSET=")) == 0) {
5772 // Back up the header of one <BlockName>
5776 StringPtr
+= StrLen (L
"OFFSET=");
5780 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
5781 if (EFI_ERROR (Status
)) {
5782 *Progress
= TmpPtr
- 1;
5790 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
5792 FreePool (TmpBuffer
);
5794 StringPtr
+= Length
;
5795 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
5796 *Progress
= TmpPtr
- 1;
5797 Status
= EFI_INVALID_PARAMETER
;
5801 StringPtr
+= StrLen (L
"&WIDTH=");
5806 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
5807 if (EFI_ERROR (Status
)) {
5808 *Progress
= TmpPtr
- 1;
5816 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
5818 FreePool (TmpBuffer
);
5820 StringPtr
+= Length
;
5821 if ((*StringPtr
!= 0) && (*StringPtr
!= L
'&')) {
5822 *Progress
= TmpPtr
- 1;
5823 Status
= EFI_INVALID_PARAMETER
;
5828 // Calculate Value and convert it to hex string.
5830 if (Offset
+ Width
> BlockSize
) {
5831 *Progress
= StringPtr
;
5832 Status
= EFI_DEVICE_ERROR
;
5836 Value
= (UINT8
*)AllocateZeroPool (Width
);
5837 if (Value
== NULL
) {
5838 *Progress
= ConfigRequest
;
5839 Status
= EFI_OUT_OF_RESOURCES
;
5843 CopyMem (Value
, (UINT8
*)Block
+ Offset
, Width
);
5845 Length
= Width
* 2 + 1;
5846 ValueStr
= (EFI_STRING
)AllocateZeroPool (Length
* sizeof (CHAR16
));
5847 if (ValueStr
== NULL
) {
5848 *Progress
= ConfigRequest
;
5849 Status
= EFI_OUT_OF_RESOURCES
;
5853 TemString
= ValueStr
;
5854 TemBuffer
= Value
+ Width
- 1;
5855 for (Index
= 0; Index
< Width
; Index
++, TemBuffer
--) {
5856 UnicodeValueToStringS (
5858 Length
* sizeof (CHAR16
) - ((UINTN
)TemString
- (UINTN
)ValueStr
),
5859 PREFIX_ZERO
| RADIX_HEX
,
5863 TemString
+= StrnLenS (TemString
, Length
- ((UINTN
)TemString
- (UINTN
)ValueStr
) / sizeof (CHAR16
));
5870 // Build a ConfigElement
5872 Length
+= StringPtr
- TmpPtr
+ 1 + StrLen (L
"VALUE=");
5873 ConfigElement
= (EFI_STRING
)AllocateZeroPool (Length
* sizeof (CHAR16
));
5874 if (ConfigElement
== NULL
) {
5875 Status
= EFI_OUT_OF_RESOURCES
;
5879 CopyMem (ConfigElement
, TmpPtr
, (StringPtr
- TmpPtr
+ 1) * sizeof (CHAR16
));
5880 if (*StringPtr
== 0) {
5881 *(ConfigElement
+ (StringPtr
- TmpPtr
)) = L
'&';
5884 *(ConfigElement
+ (StringPtr
- TmpPtr
) + 1) = 0;
5885 StrCatS (ConfigElement
, Length
, L
"VALUE=");
5886 StrCatS (ConfigElement
, Length
, ValueStr
);
5888 AppendToMultiString (Config
, ConfigElement
);
5890 FreePool (ConfigElement
);
5891 FreePool (ValueStr
);
5892 ConfigElement
= NULL
;
5896 // If '\0', parsing is finished. Otherwise skip '&' to continue
5898 if (*StringPtr
== 0) {
5902 AppendToMultiString (Config
, L
"&");
5906 if (*StringPtr
!= 0) {
5907 *Progress
= StringPtr
- 1;
5908 Status
= EFI_INVALID_PARAMETER
;
5912 HiiToLower (*Config
);
5913 *Progress
= StringPtr
;
5917 if (*Config
!= NULL
) {
5922 if (ValueStr
!= NULL
) {
5923 FreePool (ValueStr
);
5926 if (Value
!= NULL
) {
5930 if (ConfigElement
!= NULL
) {
5931 FreePool (ConfigElement
);
5938 This helper function is to be called by drivers to map configuration strings
5939 to configurations stored in byte array ("block") formats such as UEFI Variables.
5941 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
5943 @param ConfigResp A null-terminated Unicode string in <ConfigResp>
5945 @param Block A possibly null array of bytes representing the
5946 current block. Only bytes referenced in the
5947 ConfigResp string in the block are modified. If
5948 this parameter is null or if the *BlockSize
5949 parameter is (on input) shorter than required by
5950 the Configuration string, only the BlockSize
5951 parameter is updated and an appropriate status
5952 (see below) is returned.
5953 @param BlockSize The length of the Block in units of UINT8. On
5954 input, this is the size of the Block. On output,
5955 if successful, contains the largest index of the
5956 modified byte in the Block, or the required buffer
5957 size if the Block is not large enough.
5958 @param Progress On return, points to an element of the ConfigResp
5959 string filled in with the offset of the most
5960 recent '&' before the first failing name / value
5961 pair (or the beginning of the string if the
5962 failure is in the first name / value pair) or the
5963 terminating NULL if all was successful.
5965 @retval EFI_SUCCESS The request succeeded. Progress points to the null
5966 terminator at the end of the ConfigResp string.
5967 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress
5968 points to the first character of ConfigResp.
5969 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigResp or
5970 Block parameter would result in this type of
5971 error. Progress points to the first character of
5973 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted name /
5974 value pair. Block is left updated and
5975 Progress points at the '&' preceding the first
5977 @retval EFI_BUFFER_TOO_SMALL Block not large enough. Progress undefined.
5978 BlockSize is updated with the required buffer size.
5979 @retval EFI_NOT_FOUND Target for the specified routing data was not found.
5980 Progress points to the "G" in "GUID" of the errant
5987 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
5988 IN CONST EFI_STRING ConfigResp
,
5989 IN OUT UINT8
*Block
,
5990 IN OUT UINTN
*BlockSize
,
5991 OUT EFI_STRING
*Progress
5994 HII_DATABASE_PRIVATE_DATA
*Private
;
5995 EFI_STRING StringPtr
;
6008 if ((This
== NULL
) || (BlockSize
== NULL
) || (Progress
== NULL
)) {
6009 return EFI_INVALID_PARAMETER
;
6012 *Progress
= ConfigResp
;
6013 if (ConfigResp
== NULL
) {
6014 return EFI_INVALID_PARAMETER
;
6017 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
6018 ASSERT (Private
!= NULL
);
6020 StringPtr
= ConfigResp
;
6021 BufferSize
= *BlockSize
;
6028 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
6029 *Progress
= StringPtr
;
6030 Status
= EFI_INVALID_PARAMETER
;
6034 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"PATH=", StrLen (L
"PATH=")) != 0) {
6038 if (*StringPtr
== 0) {
6039 *Progress
= StringPtr
;
6040 Status
= EFI_INVALID_PARAMETER
;
6044 while (*StringPtr
!= L
'&' && *StringPtr
!= 0) {
6048 if (*StringPtr
== 0) {
6049 *Progress
= StringPtr
;
6050 Status
= EFI_INVALID_PARAMETER
;
6055 // Parse each <ConfigElement> if exists
6056 // Only '&'<BlockConfig> format is supported by this help function.
6057 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE='<Number>
6059 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) == 0) {
6061 StringPtr
+= StrLen (L
"&OFFSET=");
6065 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
6066 if (EFI_ERROR (Status
)) {
6075 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
6077 FreePool (TmpBuffer
);
6079 StringPtr
+= Length
;
6080 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
6082 Status
= EFI_INVALID_PARAMETER
;
6086 StringPtr
+= StrLen (L
"&WIDTH=");
6091 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
6092 if (EFI_ERROR (Status
)) {
6101 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
6103 FreePool (TmpBuffer
);
6105 StringPtr
+= Length
;
6106 if (StrnCmp (StringPtr
, L
"&VALUE=", StrLen (L
"&VALUE=")) != 0) {
6108 Status
= EFI_INVALID_PARAMETER
;
6112 StringPtr
+= StrLen (L
"&VALUE=");
6117 Status
= GetValueOfNumber (StringPtr
, &Value
, &Length
);
6118 if (EFI_ERROR (Status
)) {
6123 StringPtr
+= Length
;
6124 if ((*StringPtr
!= 0) && (*StringPtr
!= L
'&')) {
6126 Status
= EFI_INVALID_PARAMETER
;
6131 // Update the Block with configuration info
6133 if ((Block
!= NULL
) && (Offset
+ Width
<= BufferSize
)) {
6134 CopyMem (Block
+ Offset
, Value
, Width
);
6137 if (Offset
+ Width
> MaxBlockSize
) {
6138 MaxBlockSize
= Offset
+ Width
;
6145 // If '\0', parsing is finished.
6147 if (*StringPtr
== 0) {
6153 // The input string is not ConfigResp format, return error.
6155 if (*StringPtr
!= 0) {
6156 *Progress
= StringPtr
;
6157 Status
= EFI_INVALID_PARAMETER
;
6161 *Progress
= StringPtr
+ StrLen (StringPtr
);
6162 *BlockSize
= MaxBlockSize
- 1;
6164 if (MaxBlockSize
> BufferSize
) {
6165 *BlockSize
= MaxBlockSize
;
6166 if (Block
!= NULL
) {
6167 return EFI_BUFFER_TOO_SMALL
;
6171 if (Block
== NULL
) {
6172 *Progress
= ConfigResp
;
6173 return EFI_INVALID_PARAMETER
;
6180 if (Value
!= NULL
) {
6188 This helper function is to be called by drivers to extract portions of
6189 a larger configuration string.
6191 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
6193 @param Configuration A null-terminated Unicode string in
6194 <MultiConfigAltResp> format.
6195 @param Guid A pointer to the GUID value to search for in the
6196 routing portion of the ConfigResp string when
6197 retrieving the requested data. If Guid is NULL,
6198 then all GUID values will be searched for.
6199 @param Name A pointer to the NAME value to search for in the
6200 routing portion of the ConfigResp string when
6201 retrieving the requested data. If Name is NULL,
6202 then all Name values will be searched for.
6203 @param DevicePath A pointer to the PATH value to search for in the
6204 routing portion of the ConfigResp string when
6205 retrieving the requested data. If DevicePath is
6206 NULL, then all DevicePath values will be searched
6208 @param AltCfgId A pointer to the ALTCFG value to search for in the
6209 routing portion of the ConfigResp string when
6210 retrieving the requested data. If this parameter
6211 is NULL, then the current setting will be
6213 @param AltCfgResp A pointer to a buffer which will be allocated by
6214 the function which contains the retrieved string
6215 as requested. This buffer is only allocated if
6216 the call was successful. It is <ConfigResp> format.
6218 @retval EFI_SUCCESS The request succeeded. The requested data was
6219 extracted and placed in the newly allocated
6221 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate AltCfgResp.
6222 @retval EFI_INVALID_PARAMETER Any parameter is invalid.
6223 @retval EFI_NOT_FOUND Target for the specified routing data was not
6230 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
6231 IN CONST EFI_STRING Configuration
,
6232 IN CONST EFI_GUID
*Guid
,
6233 IN CONST EFI_STRING Name
,
6234 IN CONST EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
6235 IN CONST UINT16
*AltCfgId
,
6236 OUT EFI_STRING
*AltCfgResp
6240 EFI_STRING StringPtr
;
6241 EFI_STRING HdrStart
;
6248 EFI_STRING AltIdStr
;
6265 if ((This
== NULL
) || (Configuration
== NULL
) || (AltCfgResp
== NULL
)) {
6266 return EFI_INVALID_PARAMETER
;
6269 StringPtr
= Configuration
;
6270 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
6271 return EFI_INVALID_PARAMETER
;
6275 // Generate the sub string for later matching.
6277 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*)Guid
, 1, &GuidStr
);
6280 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*)DevicePath
),
6285 if (AltCfgId
!= NULL
) {
6286 GenerateSubStr (L
"ALTCFG=", sizeof (UINT16
), (VOID
*)AltCfgId
, 3, &AltIdStr
);
6290 GenerateSubStr (L
"NAME=", StrLen (Name
) * sizeof (CHAR16
), (VOID
*)Name
, 2, &NameStr
);
6292 GenerateSubStr (L
"NAME=", 0, NULL
, 2, &NameStr
);
6295 while (*StringPtr
!= 0) {
6297 // Try to match the GUID
6300 TmpPtr
= StrStr (StringPtr
, GuidStr
);
6301 if (TmpPtr
== NULL
) {
6302 Status
= EFI_NOT_FOUND
;
6309 // Jump to <NameHdr>
6312 StringPtr
= TmpPtr
+ StrLen (GuidStr
);
6314 StringPtr
= StrStr (TmpPtr
, L
"NAME=");
6315 if (StringPtr
== NULL
) {
6316 Status
= EFI_NOT_FOUND
;
6325 // Try to match the NAME
6327 if (GuidFlag
&& !NameFlag
) {
6328 if (StrnCmp (StringPtr
, NameStr
, StrLen (NameStr
)) != 0) {
6332 // Jump to <PathHdr>
6335 StringPtr
+= StrLen (NameStr
);
6337 StringPtr
= StrStr (StringPtr
, L
"PATH=");
6338 if (StringPtr
== NULL
) {
6339 Status
= EFI_NOT_FOUND
;
6349 // Try to match the DevicePath
6351 if (GuidFlag
&& NameFlag
&& !PathFlag
) {
6352 if (StrnCmp (StringPtr
, PathStr
, StrLen (PathStr
)) != 0) {
6357 // Jump to '&' before <DescHdr> or <ConfigBody>
6359 if (DevicePath
!= NULL
) {
6360 StringPtr
+= StrLen (PathStr
);
6362 StringPtr
= StrStr (StringPtr
, L
"&");
6363 if (StringPtr
== NULL
) {
6364 Status
= EFI_NOT_FOUND
;
6377 // Try to match the AltCfgId
6379 if (GuidFlag
&& NameFlag
&& PathFlag
) {
6380 if (AltCfgId
== NULL
) {
6382 // Return Current Setting when AltCfgId is NULL.
6384 Status
= OutputConfigBody (StringPtr
, &Result
);
6389 // Search the <ConfigAltResp> to get the <AltResp> with AltCfgId.
6391 if (StrnCmp (StringPtr
, AltIdStr
, StrLen (AltIdStr
)) != 0) {
6397 // Skip AltIdStr and &
6399 StringPtr
= StringPtr
+ StrLen (AltIdStr
);
6400 Status
= OutputConfigBody (StringPtr
, &Result
);
6406 Status
= EFI_NOT_FOUND
;
6410 if (!EFI_ERROR (Status
) && (Result
!= NULL
)) {
6412 // Copy the <ConfigHdr> and <ConfigBody>
6414 Length
= HdrEnd
- HdrStart
+ StrLen (Result
) + 1;
6415 *AltCfgResp
= AllocateZeroPool (Length
* sizeof (CHAR16
));
6416 if (*AltCfgResp
== NULL
) {
6417 Status
= EFI_OUT_OF_RESOURCES
;
6419 StrnCpyS (*AltCfgResp
, Length
, HdrStart
, HdrEnd
- HdrStart
);
6420 StrCatS (*AltCfgResp
, Length
, Result
);
6421 Status
= EFI_SUCCESS
;
6425 if (GuidStr
!= NULL
) {
6429 if (NameStr
!= NULL
) {
6433 if (PathStr
!= NULL
) {
6437 if (AltIdStr
!= NULL
) {
6438 FreePool (AltIdStr
);
6441 if (Result
!= NULL
) {