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_OP_HEADER
*IfrOpHdr
;
2175 EFI_IFR_ONE_OF
*IfrOneOf
;
2176 EFI_IFR_REF4
*IfrRef
;
2177 EFI_IFR_ONE_OF_OPTION
*IfrOneOfOption
;
2178 EFI_IFR_DEFAULT
*IfrDefault
;
2179 EFI_IFR_ORDERED_LIST
*IfrOrderedList
;
2180 EFI_IFR_CHECKBOX
*IfrCheckBox
;
2181 EFI_IFR_PASSWORD
*IfrPassword
;
2182 EFI_IFR_STRING
*IfrString
;
2183 EFI_IFR_DATE
*IfrDate
;
2184 EFI_IFR_TIME
*IfrTime
;
2185 IFR_DEFAULT_DATA DefaultData
;
2186 IFR_DEFAULT_DATA
*DefaultDataPtr
;
2187 IFR_BLOCK_DATA
*BlockData
;
2188 CHAR16
*VarStoreName
;
2191 UINT16 VarDefaultId
;
2192 BOOLEAN FirstOneOfOption
;
2193 BOOLEAN FirstOrderedList
;
2194 LIST_ENTRY
*LinkData
;
2195 LIST_ENTRY
*LinkDefault
;
2196 EFI_IFR_VARSTORE_NAME_VALUE
*IfrNameValueVarStore
;
2197 EFI_HII_PACKAGE_HEADER
*PackageHeader
;
2198 EFI_VARSTORE_ID VarStoreId
;
2199 UINT16 SmallestDefaultId
;
2200 BOOLEAN SmallestIdFromFlag
;
2201 BOOLEAN FromOtherDefaultOpcode
;
2202 BOOLEAN QuestionReferBitField
;
2204 Status
= EFI_SUCCESS
;
2206 DefaultDataPtr
= NULL
;
2207 FirstOneOfOption
= FALSE
;
2209 FirstOrderedList
= FALSE
;
2210 VarStoreName
= NULL
;
2211 ZeroMem (&DefaultData
, sizeof (IFR_DEFAULT_DATA
));
2212 SmallestDefaultId
= 0xFFFF;
2213 FromOtherDefaultOpcode
= FALSE
;
2214 QuestionReferBitField
= FALSE
;
2217 // Go through the form package to parse OpCode one by one.
2219 PackageOffset
= sizeof (EFI_HII_PACKAGE_HEADER
);
2220 PackageHeader
= (EFI_HII_PACKAGE_HEADER
*)Package
;
2221 IfrOffset
= PackageOffset
;
2222 while (IfrOffset
< PackageLength
) {
2224 // More than one form package found.
2226 if (PackageOffset
>= PackageHeader
->Length
) {
2228 // Already found varstore for this request, break;
2230 if (VarStoreId
!= 0) {
2235 // Get next package header info.
2237 IfrOffset
+= sizeof (EFI_HII_PACKAGE_HEADER
);
2238 PackageOffset
= sizeof (EFI_HII_PACKAGE_HEADER
);
2239 PackageHeader
= (EFI_HII_PACKAGE_HEADER
*)(Package
+ IfrOffset
);
2242 IfrOpHdr
= (EFI_IFR_OP_HEADER
*)(Package
+ IfrOffset
);
2243 switch (IfrOpHdr
->OpCode
) {
2244 case EFI_IFR_VARSTORE_OP
:
2246 // VarStore is found. Don't need to search any more.
2248 if (VarStoreId
!= 0) {
2252 IfrVarStore
= (EFI_IFR_VARSTORE
*)IfrOpHdr
;
2254 NameSize
= AsciiStrSize ((CHAR8
*)IfrVarStore
->Name
);
2255 VarStoreName
= AllocateZeroPool (NameSize
* sizeof (CHAR16
));
2256 if (VarStoreName
== NULL
) {
2257 Status
= EFI_OUT_OF_RESOURCES
;
2261 AsciiStrToUnicodeStrS ((CHAR8
*)IfrVarStore
->Name
, VarStoreName
, NameSize
);
2263 if (IsThisVarstore ((VOID
*)&IfrVarStore
->Guid
, VarStoreName
, ConfigHdr
)) {
2265 // Find the matched VarStore
2267 CopyGuid (&VarStorageData
->Guid
, (EFI_GUID
*)(VOID
*)&IfrVarStore
->Guid
);
2268 VarStorageData
->Size
= IfrVarStore
->Size
;
2269 VarStorageData
->Name
= VarStoreName
;
2270 VarStorageData
->Type
= EFI_HII_VARSTORE_BUFFER
;
2271 VarStoreId
= IfrVarStore
->VarStoreId
;
2273 FreePool (VarStoreName
);
2274 VarStoreName
= NULL
;
2279 case EFI_IFR_VARSTORE_EFI_OP
:
2281 // VarStore is found. Don't need to search any more.
2283 if (VarStoreId
!= 0) {
2287 IfrEfiVarStore
= (EFI_IFR_VARSTORE_EFI
*)IfrOpHdr
;
2290 // If the length is small than the structure, this is from old efi
2291 // varstore definition. Old efi varstore get config directly from
2292 // GetVariable function.
2294 if (IfrOpHdr
->Length
< sizeof (EFI_IFR_VARSTORE_EFI
)) {
2298 NameSize
= AsciiStrSize ((CHAR8
*)IfrEfiVarStore
->Name
);
2299 VarStoreName
= AllocateZeroPool (NameSize
* sizeof (CHAR16
));
2300 if (VarStoreName
== NULL
) {
2301 Status
= EFI_OUT_OF_RESOURCES
;
2305 AsciiStrToUnicodeStrS ((CHAR8
*)IfrEfiVarStore
->Name
, VarStoreName
, NameSize
);
2307 if (IsThisVarstore (&IfrEfiVarStore
->Guid
, VarStoreName
, ConfigHdr
)) {
2309 // Find the matched VarStore
2311 CopyGuid (&VarStorageData
->Guid
, (EFI_GUID
*)(VOID
*)&IfrEfiVarStore
->Guid
);
2312 VarStorageData
->Size
= IfrEfiVarStore
->Size
;
2313 VarStorageData
->Name
= VarStoreName
;
2314 VarStorageData
->Type
= EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
;
2315 VarStoreId
= IfrEfiVarStore
->VarStoreId
;
2317 FreePool (VarStoreName
);
2318 VarStoreName
= NULL
;
2323 case EFI_IFR_VARSTORE_NAME_VALUE_OP
:
2325 // VarStore is found. Don't need to search any more.
2327 if (VarStoreId
!= 0) {
2331 IfrNameValueVarStore
= (EFI_IFR_VARSTORE_NAME_VALUE
*)IfrOpHdr
;
2333 if (IsThisVarstore (&IfrNameValueVarStore
->Guid
, NULL
, ConfigHdr
)) {
2335 // Find the matched VarStore
2337 CopyGuid (&VarStorageData
->Guid
, (EFI_GUID
*)(VOID
*)&IfrNameValueVarStore
->Guid
);
2338 VarStorageData
->Type
= EFI_HII_VARSTORE_NAME_VALUE
;
2339 VarStoreId
= IfrNameValueVarStore
->VarStoreId
;
2344 case EFI_IFR_DEFAULTSTORE_OP
:
2346 // Add new the map between default id and default name.
2348 DefaultDataPtr
= (IFR_DEFAULT_DATA
*)AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
2349 if (DefaultDataPtr
== NULL
) {
2350 Status
= EFI_OUT_OF_RESOURCES
;
2354 DefaultDataPtr
->DefaultId
= ((EFI_IFR_DEFAULTSTORE
*)IfrOpHdr
)->DefaultId
;
2355 InsertTailList (&DefaultIdArray
->Entry
, &DefaultDataPtr
->Entry
);
2356 DefaultDataPtr
= NULL
;
2359 case EFI_IFR_FORM_OP
:
2360 case EFI_IFR_FORM_MAP_OP
:
2362 // No matched varstore is found and directly return.
2364 if ( VarStoreId
== 0) {
2365 Status
= EFI_SUCCESS
;
2371 case EFI_IFR_REF_OP
:
2373 // Ref question is not in IFR Form. This IFR form is not valid.
2375 if ( VarStoreId
== 0) {
2376 Status
= EFI_INVALID_PARAMETER
;
2381 // Check whether this question is for the requested varstore.
2383 IfrRef
= (EFI_IFR_REF4
*)IfrOpHdr
;
2384 if (IfrRef
->Question
.VarStoreId
!= VarStoreId
) {
2388 VarWidth
= (UINT16
)(sizeof (EFI_HII_REF
));
2391 // The BlockData may allocate by other opcode,need to clean.
2393 if (BlockData
!= NULL
) {
2397 Status
= IsThisOpcodeRequired (RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
, FALSE
);
2398 if (EFI_ERROR (Status
)) {
2399 if (Status
== EFI_NOT_FOUND
) {
2401 // The opcode is not required,exit and parse other opcode.
2411 case EFI_IFR_ONE_OF_OP
:
2412 case EFI_IFR_NUMERIC_OP
:
2414 // Numeric and OneOf has the same opcode structure.
2418 // Numeric and OneOf question is not in IFR Form. This IFR form is not valid.
2420 if (VarStoreId
== 0) {
2421 Status
= EFI_INVALID_PARAMETER
;
2426 // Check whether this question is for the requested varstore.
2428 IfrOneOf
= (EFI_IFR_ONE_OF
*)IfrOpHdr
;
2429 if (IfrOneOf
->Question
.VarStoreId
!= VarStoreId
) {
2433 if (QuestionReferBitField
) {
2434 VarWidth
= IfrOneOf
->Flags
& EDKII_IFR_NUMERIC_SIZE_BIT
;
2436 VarWidth
= (UINT16
)(1 << (IfrOneOf
->Flags
& EFI_IFR_NUMERIC_SIZE
));
2440 // The BlockData may allocate by other opcode,need to clean.
2442 if (BlockData
!= NULL
) {
2446 Status
= IsThisOpcodeRequired (RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
, QuestionReferBitField
);
2447 if (EFI_ERROR (Status
)) {
2448 if (Status
== EFI_NOT_FOUND
) {
2450 // The opcode is not required,exit and parse other opcode.
2459 // when go to there,BlockData can't be NULLL.
2461 ASSERT (BlockData
!= NULL
);
2463 if (IfrOpHdr
->OpCode
== EFI_IFR_ONE_OF_OP
) {
2465 // Set this flag to TRUE for the first oneof option.
2467 FirstOneOfOption
= TRUE
;
2468 } else if (IfrOpHdr
->OpCode
== EFI_IFR_NUMERIC_OP
) {
2470 // Numeric minimum value will be used as default value when no default is specified.
2472 DefaultData
.Type
= DefaultValueFromDefault
;
2473 if (QuestionReferBitField
) {
2475 // Since default value in bit field was stored as UINT32 type.
2477 CopyMem (&DefaultData
.Value
.u32
, &IfrOneOf
->data
.u32
.MinValue
, sizeof (UINT32
));
2479 switch (IfrOneOf
->Flags
& EFI_IFR_NUMERIC_SIZE
) {
2480 case EFI_IFR_NUMERIC_SIZE_1
:
2481 DefaultData
.Value
.u8
= IfrOneOf
->data
.u8
.MinValue
;
2484 case EFI_IFR_NUMERIC_SIZE_2
:
2485 CopyMem (&DefaultData
.Value
.u16
, &IfrOneOf
->data
.u16
.MinValue
, sizeof (UINT16
));
2488 case EFI_IFR_NUMERIC_SIZE_4
:
2489 CopyMem (&DefaultData
.Value
.u32
, &IfrOneOf
->data
.u32
.MinValue
, sizeof (UINT32
));
2492 case EFI_IFR_NUMERIC_SIZE_8
:
2493 CopyMem (&DefaultData
.Value
.u64
, &IfrOneOf
->data
.u64
.MinValue
, sizeof (UINT64
));
2497 Status
= EFI_INVALID_PARAMETER
;
2503 // Set default value base on the DefaultId list get from IFR data.
2505 for (LinkData
= DefaultIdArray
->Entry
.ForwardLink
; LinkData
!= &DefaultIdArray
->Entry
; LinkData
= LinkData
->ForwardLink
) {
2506 DefaultDataPtr
= BASE_CR (LinkData
, IFR_DEFAULT_DATA
, Entry
);
2507 DefaultData
.DefaultId
= DefaultDataPtr
->DefaultId
;
2508 InsertDefaultValue (BlockData
, &DefaultData
);
2514 case EFI_IFR_ORDERED_LIST_OP
:
2516 // offset by question header
2517 // width by EFI_IFR_ORDERED_LIST MaxContainers * OneofOption Type
2520 FirstOrderedList
= TRUE
;
2522 // OrderedList question is not in IFR Form. This IFR form is not valid.
2524 if (VarStoreId
== 0) {
2525 Status
= EFI_INVALID_PARAMETER
;
2530 // Check whether this question is for the requested varstore.
2532 IfrOrderedList
= (EFI_IFR_ORDERED_LIST
*)IfrOpHdr
;
2533 if (IfrOrderedList
->Question
.VarStoreId
!= VarStoreId
) {
2538 VarWidth
= IfrOrderedList
->MaxContainers
;
2541 // The BlockData may allocate by other opcode,need to clean.
2543 if (BlockData
!= NULL
) {
2547 Status
= IsThisOpcodeRequired (RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
, FALSE
);
2548 if (EFI_ERROR (Status
)) {
2549 if (Status
== EFI_NOT_FOUND
) {
2551 // The opcode is not required,exit and parse other opcode.
2561 case EFI_IFR_CHECKBOX_OP
:
2563 // EFI_IFR_DEFAULT_OP
2564 // offset by question header
2565 // width is 1 sizeof (BOOLEAN)
2566 // default id by CheckBox Flags if CheckBox flags (Default or Mau) is set, the default value is 1 to be set.
2567 // value by DefaultOption
2568 // default id by DeaultOption DefaultId can override CheckBox Flags and Default value.
2572 // CheckBox question is not in IFR Form. This IFR form is not valid.
2574 if (VarStoreId
== 0) {
2575 Status
= EFI_INVALID_PARAMETER
;
2580 // Check whether this question is for the requested varstore.
2582 IfrCheckBox
= (EFI_IFR_CHECKBOX
*)IfrOpHdr
;
2583 if (IfrCheckBox
->Question
.VarStoreId
!= VarStoreId
) {
2587 VarWidth
= (UINT16
)sizeof (BOOLEAN
);
2590 // The BlockData may allocate by other opcode,need to clean.
2592 if (BlockData
!= NULL
) {
2596 if (QuestionReferBitField
) {
2600 Status
= IsThisOpcodeRequired (RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
, QuestionReferBitField
);
2601 if (EFI_ERROR (Status
)) {
2602 if (Status
== EFI_NOT_FOUND
) {
2604 // The opcode is not required,exit and parse other opcode.
2613 // when go to there,BlockData can't be NULLL.
2615 ASSERT (BlockData
!= NULL
);
2617 SmallestIdFromFlag
= FALSE
;
2620 // Add default value for standard ID by CheckBox Flag
2622 VarDefaultId
= EFI_HII_DEFAULT_CLASS_STANDARD
;
2624 // Prepare new DefaultValue
2626 DefaultData
.DefaultId
= VarDefaultId
;
2627 if ((IfrCheckBox
->Flags
& EFI_IFR_CHECKBOX_DEFAULT
) == EFI_IFR_CHECKBOX_DEFAULT
) {
2629 // When flag is set, default value is TRUE.
2631 DefaultData
.Type
= DefaultValueFromFlag
;
2632 if (QuestionReferBitField
) {
2633 DefaultData
.Value
.u32
= TRUE
;
2635 DefaultData
.Value
.b
= TRUE
;
2638 InsertDefaultValue (BlockData
, &DefaultData
);
2640 if (SmallestDefaultId
> EFI_HII_DEFAULT_CLASS_STANDARD
) {
2642 // Record the SmallestDefaultId and update the SmallestIdFromFlag.
2644 SmallestDefaultId
= EFI_HII_DEFAULT_CLASS_STANDARD
;
2645 SmallestIdFromFlag
= TRUE
;
2650 // Add default value for Manufacture ID by CheckBox Flag
2652 VarDefaultId
= EFI_HII_DEFAULT_CLASS_MANUFACTURING
;
2654 // Prepare new DefaultValue
2656 DefaultData
.DefaultId
= VarDefaultId
;
2657 if ((IfrCheckBox
->Flags
& EFI_IFR_CHECKBOX_DEFAULT_MFG
) == EFI_IFR_CHECKBOX_DEFAULT_MFG
) {
2659 // When flag is set, default value is TRUE.
2661 DefaultData
.Type
= DefaultValueFromFlag
;
2662 if (QuestionReferBitField
) {
2663 DefaultData
.Value
.u32
= TRUE
;
2665 DefaultData
.Value
.b
= TRUE
;
2668 InsertDefaultValue (BlockData
, &DefaultData
);
2670 if (SmallestDefaultId
> EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
2672 // Record the SmallestDefaultId and update the SmallestIdFromFlag.
2674 SmallestDefaultId
= EFI_HII_DEFAULT_CLASS_MANUFACTURING
;
2675 SmallestIdFromFlag
= TRUE
;
2679 if (SmallestIdFromFlag
) {
2681 // When smallest default Id is given by the flag of CheckBox, set default value with TRUE for other default Id in the DefaultId list.
2683 DefaultData
.Type
= DefaultValueFromOtherDefault
;
2684 if (QuestionReferBitField
) {
2685 DefaultData
.Value
.u32
= TRUE
;
2687 DefaultData
.Value
.b
= TRUE
;
2691 // Set default value for all the default id in the DefaultId list.
2693 for (LinkData
= DefaultIdArray
->Entry
.ForwardLink
; LinkData
!= &DefaultIdArray
->Entry
; LinkData
= LinkData
->ForwardLink
) {
2694 DefaultDataPtr
= BASE_CR (LinkData
, IFR_DEFAULT_DATA
, Entry
);
2695 DefaultData
.DefaultId
= DefaultDataPtr
->DefaultId
;
2696 InsertDefaultValue (BlockData
, &DefaultData
);
2700 // When flag is not set, default value is FASLE.
2702 DefaultData
.Type
= DefaultValueFromDefault
;
2703 if (QuestionReferBitField
) {
2704 DefaultData
.Value
.u32
= FALSE
;
2706 DefaultData
.Value
.b
= FALSE
;
2710 // Set default value for all the default id in the DefaultId list.
2712 for (LinkData
= DefaultIdArray
->Entry
.ForwardLink
; LinkData
!= &DefaultIdArray
->Entry
; LinkData
= LinkData
->ForwardLink
) {
2713 DefaultDataPtr
= BASE_CR (LinkData
, IFR_DEFAULT_DATA
, Entry
);
2714 DefaultData
.DefaultId
= DefaultDataPtr
->DefaultId
;
2715 InsertDefaultValue (BlockData
, &DefaultData
);
2721 case EFI_IFR_DATE_OP
:
2723 // offset by question header
2724 // width MaxSize * sizeof (CHAR16)
2725 // no default value, only block array
2729 // Date question is not in IFR Form. This IFR form is not valid.
2731 if (VarStoreId
== 0) {
2732 Status
= EFI_INVALID_PARAMETER
;
2737 // Check whether this question is for the requested varstore.
2739 IfrDate
= (EFI_IFR_DATE
*)IfrOpHdr
;
2740 if (IfrDate
->Question
.VarStoreId
!= VarStoreId
) {
2745 // The BlockData may allocate by other opcode,need to clean.
2747 if (BlockData
!= NULL
) {
2751 VarWidth
= (UINT16
)sizeof (EFI_HII_DATE
);
2752 Status
= IsThisOpcodeRequired (RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
, FALSE
);
2753 if (EFI_ERROR (Status
)) {
2754 if (Status
== EFI_NOT_FOUND
) {
2756 // The opcode is not required,exit and parse other opcode.
2766 case EFI_IFR_TIME_OP
:
2768 // offset by question header
2769 // width MaxSize * sizeof (CHAR16)
2770 // no default value, only block array
2774 // Time question is not in IFR Form. This IFR form is not valid.
2776 if (VarStoreId
== 0) {
2777 Status
= EFI_INVALID_PARAMETER
;
2782 // Check whether this question is for the requested varstore.
2784 IfrTime
= (EFI_IFR_TIME
*)IfrOpHdr
;
2785 if (IfrTime
->Question
.VarStoreId
!= VarStoreId
) {
2790 // The BlockData may allocate by other opcode,need to clean.
2792 if (BlockData
!= NULL
) {
2796 VarWidth
= (UINT16
)sizeof (EFI_HII_TIME
);
2797 Status
= IsThisOpcodeRequired (RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
, FALSE
);
2798 if (EFI_ERROR (Status
)) {
2799 if (Status
== EFI_NOT_FOUND
) {
2801 // The opcode is not required,exit and parse other opcode.
2811 case EFI_IFR_STRING_OP
:
2813 // offset by question header
2814 // width MaxSize * sizeof (CHAR16)
2815 // no default value, only block array
2819 // String question is not in IFR Form. This IFR form is not valid.
2821 if (VarStoreId
== 0) {
2822 Status
= EFI_INVALID_PARAMETER
;
2827 // Check whether this question is for the requested varstore.
2829 IfrString
= (EFI_IFR_STRING
*)IfrOpHdr
;
2830 if (IfrString
->Question
.VarStoreId
!= VarStoreId
) {
2835 // The BlockData may allocate by other opcode,need to clean.
2837 if (BlockData
!= NULL
) {
2841 VarWidth
= (UINT16
)(IfrString
->MaxSize
* sizeof (UINT16
));
2842 Status
= IsThisOpcodeRequired (RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
, FALSE
);
2843 if (EFI_ERROR (Status
)) {
2844 if (Status
== EFI_NOT_FOUND
) {
2846 // The opcode is not required,exit and parse other opcode.
2856 case EFI_IFR_PASSWORD_OP
:
2858 // offset by question header
2859 // width MaxSize * sizeof (CHAR16)
2860 // no default value, only block array
2864 // Password question is not in IFR Form. This IFR form is not valid.
2866 if (VarStoreId
== 0) {
2867 Status
= EFI_INVALID_PARAMETER
;
2872 // Check whether this question is for the requested varstore.
2874 IfrPassword
= (EFI_IFR_PASSWORD
*)IfrOpHdr
;
2875 if (IfrPassword
->Question
.VarStoreId
!= VarStoreId
) {
2880 // The BlockData may allocate by other opcode,need to clean.
2882 if (BlockData
!= NULL
) {
2886 VarWidth
= (UINT16
)(IfrPassword
->MaxSize
* sizeof (UINT16
));
2887 Status
= IsThisOpcodeRequired (RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
, FALSE
);
2888 if (EFI_ERROR (Status
)) {
2889 if (Status
== EFI_NOT_FOUND
) {
2891 // The opcode is not required,exit and parse other opcode.
2900 // No default value for string.
2905 case EFI_IFR_ONE_OF_OPTION_OP
:
2907 // No matched block data is ignored.
2909 if ((BlockData
== NULL
) || (BlockData
->Scope
== 0)) {
2913 IfrOneOfOption
= (EFI_IFR_ONE_OF_OPTION
*)IfrOpHdr
;
2914 if (BlockData
->OpCode
== EFI_IFR_ORDERED_LIST_OP
) {
2915 if (!FirstOrderedList
) {
2920 // Get ordered list option data type.
2922 if ((IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_8
) || (IfrOneOfOption
->Type
== EFI_IFR_TYPE_BOOLEAN
)) {
2924 } else if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_16
) {
2926 } else if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_32
) {
2928 } else if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_64
) {
2932 // Invalid ordered list option data type.
2934 Status
= EFI_INVALID_PARAMETER
;
2935 if (BlockData
->Name
!= NULL
) {
2936 FreePool (BlockData
->Name
);
2939 FreePool (BlockData
);
2944 // Calculate Ordered list QuestionId width.
2946 BlockData
->Width
= (UINT16
)(BlockData
->Width
* VarWidth
);
2948 // Check whether this question is in requested block array.
2950 if (!BlockArrayCheck (RequestBlockArray
, BlockData
->Offset
, BlockData
->Width
, (BOOLEAN
)(BlockData
->Name
!= NULL
), HiiHandle
)) {
2952 // This question is not in the requested string. Skip it.
2954 if (BlockData
->Name
!= NULL
) {
2955 FreePool (BlockData
->Name
);
2958 FreePool (BlockData
);
2964 // Check this var question is in the var storage
2966 if ((BlockData
->Name
== NULL
) && ((BlockData
->Offset
+ BlockData
->Width
) > VarStorageData
->Size
)) {
2967 Status
= EFI_INVALID_PARAMETER
;
2968 FreePool (BlockData
);
2973 // Add Block Data into VarStorageData BlockEntry
2975 InsertBlockData (&VarStorageData
->BlockEntry
, &BlockData
);
2977 FirstOrderedList
= FALSE
;
2983 // 1. Set default value for OneOf option when flag field has default attribute.
2984 // And set the default value with the smallest default id for other default id in the DefaultId list.
2986 if (((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT
) == EFI_IFR_OPTION_DEFAULT
) ||
2987 ((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT_MFG
) == EFI_IFR_OPTION_DEFAULT_MFG
))
2990 // This flag is used to specify whether this option is the first. Set it to FALSE for the following options.
2991 // The first oneof option value will be used as default value when no default value is specified.
2993 FirstOneOfOption
= FALSE
;
2995 SmallestIdFromFlag
= FALSE
;
2997 // Prepare new DefaultValue
2999 DefaultData
.Type
= DefaultValueFromFlag
;
3000 CopyMem (&DefaultData
.Value
, &IfrOneOfOption
->Value
, IfrOneOfOption
->Header
.Length
- OFFSET_OF (EFI_IFR_ONE_OF_OPTION
, Value
));
3001 if ((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT
) == EFI_IFR_OPTION_DEFAULT
) {
3002 DefaultData
.DefaultId
= EFI_HII_DEFAULT_CLASS_STANDARD
;
3003 InsertDefaultValue (BlockData
, &DefaultData
);
3004 if (SmallestDefaultId
> EFI_HII_DEFAULT_CLASS_STANDARD
) {
3006 // Record the SmallestDefaultId and update the SmallestIdFromFlag.
3008 SmallestDefaultId
= EFI_HII_DEFAULT_CLASS_STANDARD
;
3009 SmallestIdFromFlag
= TRUE
;
3013 if ((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT_MFG
) == EFI_IFR_OPTION_DEFAULT_MFG
) {
3014 DefaultData
.DefaultId
= EFI_HII_DEFAULT_CLASS_MANUFACTURING
;
3015 InsertDefaultValue (BlockData
, &DefaultData
);
3016 if (SmallestDefaultId
> EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
3018 // Record the SmallestDefaultId and update the SmallestIdFromFlag.
3020 SmallestDefaultId
= EFI_HII_DEFAULT_CLASS_MANUFACTURING
;
3021 SmallestIdFromFlag
= TRUE
;
3025 if (SmallestIdFromFlag
) {
3027 // When smallest default Id is given by the flag of oneofOption, set this option value for other default Id in the DefaultId list.
3029 DefaultData
.Type
= DefaultValueFromOtherDefault
;
3031 // Set default value for other default id in the DefaultId list.
3033 for (LinkData
= DefaultIdArray
->Entry
.ForwardLink
; LinkData
!= &DefaultIdArray
->Entry
; LinkData
= LinkData
->ForwardLink
) {
3034 DefaultDataPtr
= BASE_CR (LinkData
, IFR_DEFAULT_DATA
, Entry
);
3035 DefaultData
.DefaultId
= DefaultDataPtr
->DefaultId
;
3036 InsertDefaultValue (BlockData
, &DefaultData
);
3042 // 2. Set as the default value when this is the first option.
3043 // The first oneof option value will be used as default value when no default value is specified.
3045 if (FirstOneOfOption
) {
3046 // This flag is used to specify whether this option is the first. Set it to FALSE for the following options.
3047 FirstOneOfOption
= FALSE
;
3050 // Prepare new DefaultValue
3052 DefaultData
.Type
= DefaultValueFromDefault
;
3053 CopyMem (&DefaultData
.Value
, &IfrOneOfOption
->Value
, IfrOneOfOption
->Header
.Length
- OFFSET_OF (EFI_IFR_ONE_OF_OPTION
, Value
));
3054 for (LinkData
= DefaultIdArray
->Entry
.ForwardLink
; LinkData
!= &DefaultIdArray
->Entry
; LinkData
= LinkData
->ForwardLink
) {
3055 DefaultDataPtr
= BASE_CR (LinkData
, IFR_DEFAULT_DATA
, Entry
);
3056 DefaultData
.DefaultId
= DefaultDataPtr
->DefaultId
;
3057 InsertDefaultValue (BlockData
, &DefaultData
);
3063 case EFI_IFR_DEFAULT_OP
:
3065 // Update Current BlockData to the default value.
3067 if ((BlockData
== NULL
) || (BlockData
->Scope
== 0)) {
3069 // No matched block data is ignored.
3075 // Get the DefaultId
3077 IfrDefault
= (EFI_IFR_DEFAULT
*)IfrOpHdr
;
3078 VarDefaultId
= IfrDefault
->DefaultId
;
3080 // Prepare new DefaultValue
3082 DefaultData
.Type
= DefaultValueFromOpcode
;
3083 DefaultData
.DefaultId
= VarDefaultId
;
3084 if (QuestionReferBitField
) {
3085 CopyMem (&DefaultData
.Value
.u32
, &IfrDefault
->Value
.u32
, sizeof (UINT32
));
3087 CopyMem (&DefaultData
.Value
, &IfrDefault
->Value
, IfrDefault
->Header
.Length
- OFFSET_OF (EFI_IFR_DEFAULT
, Value
));
3090 // If the value field is expression, set the cleaned flag.
3091 if (IfrDefault
->Type
== EFI_IFR_TYPE_OTHER
) {
3092 DefaultData
.Cleaned
= TRUE
;
3096 // Add DefaultValue into current BlockData
3098 InsertDefaultValue (BlockData
, &DefaultData
);
3101 // Set default value for other default id in the DefaultId list.
3102 // when SmallestDefaultId == VarDefaultId means there are two defaults with same default Id.
3103 // If the two defaults are both from default opcode, use the first default as the default value of other default Id.
3104 // If one from flag and the other form default opcode, use the default opcode value as the default value of other default Id.
3106 if ((SmallestDefaultId
> VarDefaultId
) || ((SmallestDefaultId
== VarDefaultId
) && !FromOtherDefaultOpcode
)) {
3107 FromOtherDefaultOpcode
= TRUE
;
3108 SmallestDefaultId
= VarDefaultId
;
3109 for (LinkData
= DefaultIdArray
->Entry
.ForwardLink
; LinkData
!= &DefaultIdArray
->Entry
; LinkData
= LinkData
->ForwardLink
) {
3110 DefaultDataPtr
= BASE_CR (LinkData
, IFR_DEFAULT_DATA
, Entry
);
3111 if (DefaultDataPtr
->DefaultId
!= DefaultData
.DefaultId
) {
3112 DefaultData
.Type
= DefaultValueFromOtherDefault
;
3113 DefaultData
.DefaultId
= DefaultDataPtr
->DefaultId
;
3114 InsertDefaultValue (BlockData
, &DefaultData
);
3120 // After insert the default value, reset the cleaned value for next
3121 // time used. If not set here, need to set the value before every time.
3124 DefaultData
.Cleaned
= FALSE
;
3127 case EFI_IFR_END_OP
:
3129 // End Opcode is for Var question.
3131 QuestionReferBitField
= FALSE
;
3132 if (BlockData
!= NULL
) {
3133 if (BlockData
->Scope
> 0) {
3137 if (BlockData
->Scope
== 0) {
3140 // when finishing parsing a question, clean the SmallestDefaultId and GetDefaultFromDefaultOpcode.
3142 SmallestDefaultId
= 0xFFFF;
3143 FromOtherDefaultOpcode
= FALSE
;
3149 case EFI_IFR_GUID_OP
:
3150 if (CompareGuid ((EFI_GUID
*)((UINT8
*)IfrOpHdr
+ sizeof (EFI_IFR_OP_HEADER
)), &gEdkiiIfrBitVarstoreGuid
)) {
3151 QuestionReferBitField
= TRUE
;
3157 if (BlockData
!= NULL
) {
3158 if (BlockData
->Scope
> 0) {
3159 BlockData
->Scope
= (UINT8
)(BlockData
->Scope
+ IfrOpHdr
->Scope
);
3162 if (BlockData
->Scope
== 0) {
3170 IfrOffset
+= IfrOpHdr
->Length
;
3171 PackageOffset
+= IfrOpHdr
->Length
;
3175 // if Status == EFI_NOT_FOUND, just means the opcode is not required,not contain any error,
3176 // so set the Status to EFI_SUCCESS.
3178 if (Status
== EFI_NOT_FOUND
) {
3179 Status
= EFI_SUCCESS
;
3183 for (LinkData
= VarStorageData
->BlockEntry
.ForwardLink
; LinkData
!= &VarStorageData
->BlockEntry
; LinkData
= LinkData
->ForwardLink
) {
3184 BlockData
= BASE_CR (LinkData
, IFR_BLOCK_DATA
, Entry
);
3185 for (LinkDefault
= BlockData
->DefaultValueEntry
.ForwardLink
; LinkDefault
!= &BlockData
->DefaultValueEntry
; ) {
3186 DefaultDataPtr
= BASE_CR (LinkDefault
, IFR_DEFAULT_DATA
, Entry
);
3187 LinkDefault
= LinkDefault
->ForwardLink
;
3188 if (DefaultDataPtr
->Cleaned
== TRUE
) {
3189 RemoveEntryList (&DefaultDataPtr
->Entry
);
3190 FreePool (DefaultDataPtr
);
3199 parse the configrequest string, get the elements.
3201 @param ConfigRequest The input configrequest string.
3202 @param Progress Return the progress data.
3204 @retval Block data pointer.
3208 IN EFI_STRING ConfigRequest
,
3209 OUT EFI_STRING
*Progress
3212 EFI_STRING StringPtr
;
3213 IFR_BLOCK_DATA
*BlockData
;
3214 IFR_BLOCK_DATA
*RequestBlockArray
;
3220 IFR_BLOCK_DATA
*NextBlockData
;
3226 // Init RequestBlockArray
3228 RequestBlockArray
= (IFR_BLOCK_DATA
*)AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
3229 if (RequestBlockArray
== NULL
) {
3233 InitializeListHead (&RequestBlockArray
->Entry
);
3236 // Get the request Block array from the request string
3241 // Parse each <RequestElement> if exists
3242 // Only <BlockName> format is supported by this help function.
3243 // <BlockName> ::= &'OFFSET='<Number>&'WIDTH='<Number>
3245 StringPtr
= ConfigRequest
;
3246 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) == 0) {
3248 // Skip the OFFSET string
3250 *Progress
= StringPtr
;
3251 StringPtr
+= StrLen (L
"&OFFSET=");
3255 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
3256 if (EFI_ERROR (Status
)) {
3264 (((Length
+ 1) / 2) < sizeof (UINT16
)) ? ((Length
+ 1) / 2) : sizeof (UINT16
)
3266 FreePool (TmpBuffer
);
3268 StringPtr
+= Length
;
3269 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
3273 StringPtr
+= StrLen (L
"&WIDTH=");
3278 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
3279 if (EFI_ERROR (Status
)) {
3287 (((Length
+ 1) / 2) < sizeof (UINT16
)) ? ((Length
+ 1) / 2) : sizeof (UINT16
)
3289 FreePool (TmpBuffer
);
3291 StringPtr
+= Length
;
3292 if ((*StringPtr
!= 0) && (*StringPtr
!= L
'&')) {
3299 BlockData
= (IFR_BLOCK_DATA
*)AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
3300 if (BlockData
== NULL
) {
3304 BlockData
->Offset
= Offset
;
3305 BlockData
->Width
= Width
;
3306 InsertBlockData (&RequestBlockArray
->Entry
, &BlockData
);
3309 // Skip &VALUE string if &VALUE does exists.
3311 if (StrnCmp (StringPtr
, L
"&VALUE=", StrLen (L
"&VALUE=")) == 0) {
3312 StringPtr
+= StrLen (L
"&VALUE=");
3317 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
3318 if (EFI_ERROR (Status
)) {
3322 FreePool (TmpBuffer
);
3323 StringPtr
+= Length
;
3324 if ((*StringPtr
!= 0) && (*StringPtr
!= L
'&')) {
3330 // If '\0', parsing is finished.
3332 if (*StringPtr
== 0) {
3338 // Merge the requested block data.
3340 Link
= RequestBlockArray
->Entry
.ForwardLink
;
3341 while ((Link
!= &RequestBlockArray
->Entry
) && (Link
->ForwardLink
!= &RequestBlockArray
->Entry
)) {
3342 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
3343 NextBlockData
= BASE_CR (Link
->ForwardLink
, IFR_BLOCK_DATA
, Entry
);
3344 if ((NextBlockData
->Offset
>= BlockData
->Offset
) && (NextBlockData
->Offset
<= (BlockData
->Offset
+ BlockData
->Width
))) {
3345 if ((NextBlockData
->Offset
+ NextBlockData
->Width
) > (BlockData
->Offset
+ BlockData
->Width
)) {
3346 BlockData
->Width
= (UINT16
)(NextBlockData
->Offset
+ NextBlockData
->Width
- BlockData
->Offset
);
3349 RemoveEntryList (Link
->ForwardLink
);
3350 FreePool (NextBlockData
);
3354 Link
= Link
->ForwardLink
;
3357 return RequestBlockArray
;
3360 if (RequestBlockArray
!= NULL
) {
3362 // Free Link Array RequestBlockArray
3364 while (!IsListEmpty (&RequestBlockArray
->Entry
)) {
3365 BlockData
= BASE_CR (RequestBlockArray
->Entry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
3366 RemoveEntryList (&BlockData
->Entry
);
3367 FreePool (BlockData
);
3370 FreePool (RequestBlockArray
);
3377 parse the configrequest string, get the elements.
3379 @param ConfigRequest The input config request string.
3380 @param Progress Return the progress data.
3382 @retval return data block array.
3386 IN EFI_STRING ConfigRequest
,
3387 OUT EFI_STRING
*Progress
3390 EFI_STRING StringPtr
;
3392 IFR_BLOCK_DATA
*BlockData
;
3393 IFR_BLOCK_DATA
*RequestBlockArray
;
3396 StringPtr
= ConfigRequest
;
3399 // Init RequestBlockArray
3401 RequestBlockArray
= (IFR_BLOCK_DATA
*)AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
3402 if (RequestBlockArray
== NULL
) {
3406 InitializeListHead (&RequestBlockArray
->Entry
);
3409 // Get the request Block array from the request string
3413 // Parse each <RequestElement> if exists
3414 // Only <BlockName> format is supported by this help function.
3415 // <BlockName> ::= &'Name***=***
3417 while (StringPtr
!= NULL
&& *StringPtr
== L
'&') {
3418 *Progress
= StringPtr
;
3420 // Skip the L"&" string
3425 if ((NextTag
= StrStr (StringPtr
, L
"=")) != NULL
) {
3428 } else if ((NextTag
= StrStr (StringPtr
, L
"&")) != NULL
) {
3435 BlockData
= (IFR_BLOCK_DATA
*)AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
3436 if (BlockData
== NULL
) {
3443 BlockData
->Name
= AllocateCopyPool (StrSize (StringPtr
), StringPtr
);
3444 InsertBlockData (&RequestBlockArray
->Entry
, &BlockData
);
3448 // If has value, skip the value.
3450 StringPtr
= NextTag
+ 1;
3452 StringPtr
= StrStr (StringPtr
, L
"&");
3453 } else if (NextTag
!= NULL
) {
3455 // restore the '&' text.
3457 StringPtr
= NextTag
;
3462 return RequestBlockArray
;
3465 if (RequestBlockArray
!= NULL
) {
3467 // Free Link Array RequestBlockArray
3469 while (!IsListEmpty (&RequestBlockArray
->Entry
)) {
3470 BlockData
= BASE_CR (RequestBlockArray
->Entry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
3471 RemoveEntryList (&BlockData
->Entry
);
3472 if (BlockData
->Name
!= NULL
) {
3473 FreePool (BlockData
->Name
);
3476 FreePool (BlockData
);
3479 FreePool (RequestBlockArray
);
3486 Generate ConfigRequest string base on the varstore info.
3488 @param ConfigHdr The config header for this varstore.
3489 @param VarStorageData The varstore info.
3490 @param Status Return Status.
3491 @param ConfigRequest The ConfigRequest info may be return.
3493 @retval TRUE Need to continue
3494 @retval Others NO need to continue or error occur.
3497 GenerateConfigRequest (
3498 IN CHAR16
*ConfigHdr
,
3499 IN IFR_VARSTORAGE_DATA
*VarStorageData
,
3500 OUT EFI_STATUS
*Status
,
3501 IN OUT EFI_STRING
*ConfigRequest
3507 CHAR16
*FullConfigRequest
;
3509 IFR_BLOCK_DATA
*BlockData
;
3512 // Append VarStorageData BlockEntry into *Request string
3513 // Now support only one varstore in a form package.
3517 // Go through all VarStorageData Entry and get BlockEntry for each one for the multiple varstore in a single form package
3518 // Then construct them all to return MultiRequest string : ConfigHdr BlockConfig
3522 // Compute the length of the entire request starting with <ConfigHdr> and a
3526 Length
= StrLen (ConfigHdr
) + 1;
3528 for (Link
= VarStorageData
->BlockEntry
.ForwardLink
; Link
!= &VarStorageData
->BlockEntry
; Link
= Link
->ForwardLink
) {
3530 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
3531 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3533 // Add <BlockName> length for each Name
3535 // <BlockName> ::= &Name1&Name2&...
3536 // |1| StrLen(Name1)
3538 Length
= Length
+ (1 + StrLen (BlockData
->Name
));
3541 // Add <BlockName> length for each Offset/Width pair
3543 // <BlockName> ::= &OFFSET=1234&WIDTH=1234
3544 // | 8 | 4 | 7 | 4 |
3546 Length
= Length
+ (8 + 4 + 7 + 4);
3551 // No any request block data is found. The request string can't be constructed.
3554 *Status
= EFI_SUCCESS
;
3559 // Allocate buffer for the entire <ConfigRequest>
3561 FullConfigRequest
= AllocateZeroPool (Length
* sizeof (CHAR16
));
3562 if (FullConfigRequest
== NULL
) {
3563 *Status
= EFI_OUT_OF_RESOURCES
;
3567 StringPtr
= FullConfigRequest
;
3570 // Start with <ConfigHdr>
3572 StrCpyS (StringPtr
, Length
, ConfigHdr
);
3573 StringPtr
+= StrLen (StringPtr
);
3576 // Loop through all the Offset/Width pairs and append them to ConfigRequest
3578 for (Link
= VarStorageData
->BlockEntry
.ForwardLink
; Link
!= &VarStorageData
->BlockEntry
; Link
= Link
->ForwardLink
) {
3579 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
3580 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3586 (1 + StrLen (BlockData
->Name
) + 1) * sizeof (CHAR16
),
3592 // Append &OFFSET=XXXX&WIDTH=YYYY\0
3596 (8 + 4 + 7 + 4 + 1) * sizeof (CHAR16
),
3597 L
"&OFFSET=%04X&WIDTH=%04X",
3603 StringPtr
+= StrLen (StringPtr
);
3607 // Set to the got full request string.
3609 HiiToLower (FullConfigRequest
);
3611 if (*ConfigRequest
!= NULL
) {
3612 FreePool (*ConfigRequest
);
3615 *ConfigRequest
= FullConfigRequest
;
3621 Generate ConfigRequest Header base on the varstore info.
3623 @param VarStorageData The varstore info.
3624 @param DevicePath Device path for this varstore.
3625 @param ConfigHdr The config header for this varstore.
3627 @retval EFI_SUCCESS Generate the header success.
3628 @retval EFI_OUT_OF_RESOURCES Allocate buffer fail.
3632 IN IFR_VARSTORAGE_DATA
*VarStorageData
,
3633 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
3634 OUT EFI_STRING
*ConfigHdr
3643 Status
= EFI_SUCCESS
;
3649 // Construct <ConfigHdr> : "GUID=...&NAME=...&PATH=..." by VarStorageData Guid, Name and DriverHandle
3651 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*)&VarStorageData
->Guid
, 1, &GuidStr
);
3652 if (VarStorageData
->Name
!= NULL
) {
3653 GenerateSubStr (L
"NAME=", StrLen (VarStorageData
->Name
) * sizeof (CHAR16
), (VOID
*)VarStorageData
->Name
, 2, &NameStr
);
3655 GenerateSubStr (L
"NAME=", 0, NULL
, 2, &NameStr
);
3660 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*)DevicePath
),
3665 Length
= StrLen (GuidStr
) + StrLen (NameStr
) + StrLen (PathStr
) + 1;
3666 if (VarStorageData
->Name
== NULL
) {
3670 *ConfigHdr
= AllocateZeroPool (Length
* sizeof (CHAR16
));
3671 if (*ConfigHdr
== NULL
) {
3672 Status
= EFI_OUT_OF_RESOURCES
;
3676 StrCpyS (*ConfigHdr
, Length
, GuidStr
);
3677 StrCatS (*ConfigHdr
, Length
, NameStr
);
3678 if (VarStorageData
->Name
== NULL
) {
3679 StrCatS (*ConfigHdr
, Length
, L
"&");
3682 StrCatS (*ConfigHdr
, Length
, PathStr
);
3685 // Remove the last character L'&'
3687 *(*ConfigHdr
+ StrLen (*ConfigHdr
) - 1) = L
'\0';
3690 if (GuidStr
!= NULL
) {
3694 if (NameStr
!= NULL
) {
3698 if (PathStr
!= NULL
) {
3706 Update the default value in the block data which is used as bit var store.
3709 A question value saved in a bit fied: bitoffset = 1; bitwidth = 2;default value = 1.
3710 And corresponding block data info: offset==0; width==1;currently the default value
3711 is saved as 1.Actually the default value 1 need to be set to bit field 1, so the
3712 default value of this block data shuold be:2.
3716 UINT8 Bit2 : 2; // Question saved in Bit2,so originalBlock info: offset = 0; width = 1;(byte level) defaul = 1.
3717 // (default value record for the bit field)
3721 After function UpdateDefaultValue,the Block info is: offset = 0; width = 1;(byte level) default = 2.
3722 (default value record for the Block)
3724 UpdateDefaultValue function update default value of bit var block based on the bit field info in the block.
3726 @param BlockLink The Link of the block data.
3730 UpdateDefaultValue (
3731 IN LIST_ENTRY
*BlockLink
3735 LIST_ENTRY
*ListEntry
;
3736 LIST_ENTRY
*LinkDefault
;
3737 IFR_BLOCK_DATA
*BlockData
;
3738 IFR_DEFAULT_DATA
*DefaultValueData
;
3741 UINT32 BitFieldDefaultValue
;
3743 for ( Link
= BlockLink
->ForwardLink
; Link
!= BlockLink
; Link
= Link
->ForwardLink
) {
3744 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
3745 if (!BlockData
->IsBitVar
) {
3749 ListEntry
= &BlockData
->DefaultValueEntry
;
3751 // Update the default value in the block data with all existing default id.
3753 for (LinkDefault
= ListEntry
->ForwardLink
; LinkDefault
!= ListEntry
; LinkDefault
= LinkDefault
->ForwardLink
) {
3755 // Get the default data, and the value of the default data is for some field in the block.
3756 // Note: Default value for bit field question is stored as UINT32.
3758 DefaultValueData
= BASE_CR (LinkDefault
, IFR_DEFAULT_DATA
, Entry
);
3759 BitFieldDefaultValue
= DefaultValueData
->Value
.u32
;
3761 StartBit
= BlockData
->BitOffset
% 8;
3762 EndBit
= StartBit
+ BlockData
->BitWidth
- 1;
3765 // Set the bit field default value to related bit filed, then we will got the new default vaule for the block data.
3767 DefaultValueData
->Value
.u32
= BitFieldWrite32 (0, StartBit
, EndBit
, BitFieldDefaultValue
);
3773 Merge the default value in two block datas which have overlap region.
3775 For bit fields, their related block data may have overlap region, such as:
3778 UINT16 Bit1 : 6; // Question1 refer Bit1, Block1: offset = 0; width = 1;(byte level) default = 1
3779 UINT16 Bit2 : 5; // Question2 refer Bit2, Block2: offset = 0; width = 2;(byte level) default = 5
3780 // (default value record for the bit field)
3784 After function UpdateDefaultValue:
3785 Block1: offset = 0; width = 1;(byte level) default = 1
3786 Block2: offset = 0; width = 2;(byte level) default = 320 (5 * (2 << 6))
3787 (default value record for block)
3789 After function MergeBlockDefaultValue:
3790 Block1: offset = 0; width = 1;(byte level) default = 65
3791 Block2: offset = 0; width = 2;(byte level) default = 321
3792 (Block1 and Block2 has overlap region, merge the overlap value to Block1 and Blcok2)
3794 Block1 and Block2 have overlap byte region, but currntly the default value of Block1 only contains
3795 value of Bit1 (low 6 bits),the default value of Block2 only contains the value of Bit2 (middle 5 bits).
3797 This fuction merge the default value of these two blocks, and make the default value of block1
3798 also contain the value of lower 2 bits of the Bit2. And make the default value of Block2 also
3799 contain the default value of Bit1.
3801 We can get the total value of the whole block that just cover these two blocks(in this case is:
3802 block: offset =0; width =2;) then the value of block2 is same as block, the value of block1 is
3803 the first byte value of block.
3805 @param FirstBlock Point to the block date whose default value need to be merged.
3806 @param SecondBlock Point to the block date whose default value need to be merged.
3810 MergeBlockDefaultValue (
3811 IN OUT IFR_BLOCK_DATA
*FirstBlock
,
3812 IN OUT IFR_BLOCK_DATA
*SecondBlock
3815 LIST_ENTRY
*FirstListEntry
;
3816 LIST_ENTRY
*SecondListEntry
;
3817 LIST_ENTRY
*FirstDefaultLink
;
3818 LIST_ENTRY
*SecondDefaultLink
;
3819 IFR_DEFAULT_DATA
*FirstDefaultValueData
;
3820 IFR_DEFAULT_DATA
*SecondDefaultValueData
;
3821 UINT32
*FirstDefaultValue
;
3822 UINT32
*SecondDefaultValue
;
3824 UINT64 ShiftedValue
;
3827 FirstListEntry
= &FirstBlock
->DefaultValueEntry
;
3828 for (FirstDefaultLink
= FirstListEntry
->ForwardLink
; FirstDefaultLink
!= FirstListEntry
; FirstDefaultLink
= FirstDefaultLink
->ForwardLink
) {
3829 FirstDefaultValueData
= BASE_CR (FirstDefaultLink
, IFR_DEFAULT_DATA
, Entry
);
3830 SecondListEntry
= &SecondBlock
->DefaultValueEntry
;
3831 for (SecondDefaultLink
= SecondListEntry
->ForwardLink
; SecondDefaultLink
!= SecondListEntry
; SecondDefaultLink
= SecondDefaultLink
->ForwardLink
) {
3832 SecondDefaultValueData
= BASE_CR (SecondDefaultLink
, IFR_DEFAULT_DATA
, Entry
);
3833 if (FirstDefaultValueData
->DefaultId
!= SecondDefaultValueData
->DefaultId
) {
3838 // Find default value with same default id in the two blocks.
3839 // Note: Default value for bit field question is stored as UINT32 type.
3841 FirstDefaultValue
= &FirstDefaultValueData
->Value
.u32
;
3842 SecondDefaultValue
= &SecondDefaultValueData
->Value
.u32
;
3844 // 1. Get the default value of the whole blcok that can just cover FirstBlock and SecondBlock.
3845 // 2. Get the default value of FirstBlock and SecondBlock form the value of whole block based
3846 // on the offset and width of FirstBlock and SecondBlock.
3848 if (FirstBlock
->Offset
> SecondBlock
->Offset
) {
3849 OffsetShift
= FirstBlock
->Offset
- SecondBlock
->Offset
;
3850 ShiftedValue
= LShiftU64 ((UINT64
)(*FirstDefaultValue
), OffsetShift
* 8);
3851 TotalValue
= ShiftedValue
| (UINT64
)(*SecondDefaultValue
);
3852 *SecondDefaultValue
= (UINT32
)BitFieldRead64 (TotalValue
, 0, SecondBlock
->Width
* 8 -1);
3853 *FirstDefaultValue
= (UINT32
)BitFieldRead64 (TotalValue
, OffsetShift
* 8, OffsetShift
* 8 + FirstBlock
->Width
*8 -1);
3855 OffsetShift
= SecondBlock
->Offset
-FirstBlock
->Offset
;
3856 ShiftedValue
= LShiftU64 ((UINT64
)(*SecondDefaultValue
), OffsetShift
* 8);
3857 TotalValue
= ShiftedValue
| (UINT64
)(*FirstDefaultValue
);
3858 *FirstDefaultValue
= (UINT32
)BitFieldRead64 (TotalValue
, 0, FirstBlock
->Width
* 8 -1);
3859 *SecondDefaultValue
= (UINT32
)BitFieldRead64 (TotalValue
, OffsetShift
* 8, OffsetShift
* 8 + SecondBlock
->Width
*8 -1);
3867 Update the default value in the block data which used as Bit VarStore
3869 @param BlockLink The Link of the block data.
3873 UpdateBlockDataArray (
3874 IN LIST_ENTRY
*BlockLink
3878 LIST_ENTRY
*TempLink
;
3879 IFR_BLOCK_DATA
*BlockData
;
3880 IFR_BLOCK_DATA
*NextBlockData
;
3883 // 1. Update default value in BitVar block data.
3884 // Sine some block datas are used as BitVarStore, then the default value recored in the block
3885 // is for related bit field in the block. so we need to set the default value to the related bit
3886 // fields in the block data if the block data is used as bit varstore, then the default value of
3887 // the block will be updated.
3889 UpdateDefaultValue (BlockLink
);
3892 // 2.Update default value for overlap BitVar blcok datas.
3893 // For block datas have overlap region, we need to merge the default value in different blocks.
3895 for (Link
= BlockLink
->ForwardLink
; Link
!= BlockLink
; Link
= Link
->ForwardLink
) {
3896 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
3897 if (!BlockData
->IsBitVar
) {
3901 for (TempLink
= Link
->ForwardLink
; TempLink
!= BlockLink
; TempLink
= TempLink
->ForwardLink
) {
3902 NextBlockData
= BASE_CR (TempLink
, IFR_BLOCK_DATA
, Entry
);
3903 if (!NextBlockData
->IsBitVar
|| (NextBlockData
->Offset
>= BlockData
->Offset
+ BlockData
->Width
) || (BlockData
->Offset
>= NextBlockData
->Offset
+ NextBlockData
->Width
)) {
3908 // Find two blocks are used as bit VarStore and have overlap region, so need to merge default value of these two blocks.
3910 MergeBlockDefaultValue (BlockData
, NextBlockData
);
3916 Generate ConfigAltResp string base on the varstore info.
3918 @param HiiHandle Hii Handle for this hii package.
3919 @param ConfigHdr The config header for this varstore.
3920 @param VarStorageData The varstore info.
3921 @param DefaultIdArray The Default id array.
3922 @param DefaultAltCfgResp The DefaultAltCfgResp info may be return.
3924 @retval TRUE Need to continue
3925 @retval Others NO need to continue or error occur.
3928 GenerateAltConfigResp (
3929 IN EFI_HII_HANDLE HiiHandle
,
3930 IN CHAR16
*ConfigHdr
,
3931 IN IFR_VARSTORAGE_DATA
*VarStorageData
,
3932 IN IFR_DEFAULT_DATA
*DefaultIdArray
,
3933 IN OUT EFI_STRING
*DefaultAltCfgResp
3939 LIST_ENTRY
*LinkData
;
3940 LIST_ENTRY
*LinkDefault
;
3941 LIST_ENTRY
*ListEntry
;
3943 IFR_BLOCK_DATA
*BlockData
;
3944 IFR_DEFAULT_DATA
*DefaultId
;
3945 IFR_DEFAULT_DATA
*DefaultValueData
;
3948 CHAR16
*DefaultString
;
3953 DefaultString
= NULL
;
3955 // Add length for <ConfigHdr> + '\0'
3957 Length
= StrLen (ConfigHdr
) + 1;
3959 UpdateBlockDataArray (&VarStorageData
->BlockEntry
);
3961 for (Link
= DefaultIdArray
->Entry
.ForwardLink
; Link
!= &DefaultIdArray
->Entry
; Link
= Link
->ForwardLink
) {
3962 DefaultId
= BASE_CR (Link
, IFR_DEFAULT_DATA
, Entry
);
3964 // Add length for "&<ConfigHdr>&ALTCFG=XXXX"
3965 // |1| StrLen (ConfigHdr) | 8 | 4 |
3967 Length
+= (1 + StrLen (ConfigHdr
) + 8 + 4);
3969 for (LinkData
= VarStorageData
->BlockEntry
.ForwardLink
; LinkData
!= &VarStorageData
->BlockEntry
; LinkData
= LinkData
->ForwardLink
) {
3970 BlockData
= BASE_CR (LinkData
, IFR_BLOCK_DATA
, Entry
);
3971 ListEntry
= &BlockData
->DefaultValueEntry
;
3972 for (LinkDefault
= ListEntry
->ForwardLink
; LinkDefault
!= ListEntry
; LinkDefault
= LinkDefault
->ForwardLink
) {
3973 DefaultValueData
= BASE_CR (LinkDefault
, IFR_DEFAULT_DATA
, Entry
);
3974 if (DefaultValueData
->DefaultId
!= DefaultId
->DefaultId
) {
3978 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3980 // Add length for "&Name1=zzzzzzzzzzzz"
3983 Length
+= (1 + StrLen (BlockData
->Name
) + 1 + BlockData
->Width
* 2);
3986 // Add length for "&OFFSET=XXXX&WIDTH=YYYY&VALUE=zzzzzzzzzzzz"
3987 // | 8 | 4 | 7 | 4 | 7 | Width * 2 |
3989 Length
+= (8 + 4 + 7 + 4 + 7 + BlockData
->Width
* 2);
3998 // No default value is found. The default string doesn't exist.
4005 // Allocate buffer for the entire <DefaultAltCfgResp>
4007 *DefaultAltCfgResp
= AllocateZeroPool (Length
* sizeof (CHAR16
));
4008 if (*DefaultAltCfgResp
== NULL
) {
4009 return EFI_OUT_OF_RESOURCES
;
4012 StringPtr
= *DefaultAltCfgResp
;
4015 // Start with <ConfigHdr>
4017 StrCpyS (StringPtr
, Length
, ConfigHdr
);
4018 StringPtr
+= StrLen (StringPtr
);
4020 for (Link
= DefaultIdArray
->Entry
.ForwardLink
; Link
!= &DefaultIdArray
->Entry
; Link
= Link
->ForwardLink
) {
4021 DefaultId
= BASE_CR (Link
, IFR_DEFAULT_DATA
, Entry
);
4023 // Add <AltConfigHdr> of the form "&<ConfigHdr>&ALTCFG=XXXX\0"
4024 // |1| StrLen (ConfigHdr) | 8 | 4 |
4028 (1 + StrLen (ConfigHdr
) + 8 + 4 + 1) * sizeof (CHAR16
),
4031 DefaultId
->DefaultId
4033 StringPtr
+= StrLen (StringPtr
);
4035 for (LinkData
= VarStorageData
->BlockEntry
.ForwardLink
; LinkData
!= &VarStorageData
->BlockEntry
; LinkData
= LinkData
->ForwardLink
) {
4036 BlockData
= BASE_CR (LinkData
, IFR_BLOCK_DATA
, Entry
);
4037 ListEntry
= &BlockData
->DefaultValueEntry
;
4038 for (LinkDefault
= ListEntry
->ForwardLink
; LinkDefault
!= ListEntry
; LinkDefault
= LinkDefault
->ForwardLink
) {
4039 DefaultValueData
= BASE_CR (LinkDefault
, IFR_DEFAULT_DATA
, Entry
);
4040 if (DefaultValueData
->DefaultId
!= DefaultId
->DefaultId
) {
4044 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
4047 (1 + StrLen (ConfigHdr
) + 1) * sizeof (CHAR16
),
4051 StringPtr
+= StrLen (StringPtr
);
4054 // Add <BlockConfig>
4055 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>
4059 (8 + 4 + 7 + 4 + 7 + 1) * sizeof (CHAR16
),
4060 L
"&OFFSET=%04X&WIDTH=%04X&VALUE=",
4064 StringPtr
+= StrLen (StringPtr
);
4067 Width
= BlockData
->Width
;
4069 // Convert Value to a hex string in "%x" format
4070 // NOTE: This is in the opposite byte that GUID and PATH use
4072 if (BlockData
->OpCode
== EFI_IFR_STRING_OP
) {
4073 DefaultString
= InternalGetString (HiiHandle
, DefaultValueData
->Value
.string
);
4074 TmpBuffer
= AllocateZeroPool (Width
);
4075 ASSERT (TmpBuffer
!= NULL
);
4076 if (DefaultString
!= NULL
) {
4077 StrSize
= StrLen (DefaultString
)* sizeof (CHAR16
);
4078 if (StrSize
> Width
) {
4082 CopyMem (TmpBuffer
, (UINT8
*)DefaultString
, StrSize
);
4085 TmpBuffer
= (UINT8
*)&(DefaultValueData
->Value
);
4088 for ( ; Width
> 0 && (TmpBuffer
!= NULL
); Width
--) {
4089 UnicodeValueToStringS (
4091 Length
* sizeof (CHAR16
) - ((UINTN
)StringPtr
- (UINTN
)*DefaultAltCfgResp
),
4092 PREFIX_ZERO
| RADIX_HEX
,
4093 TmpBuffer
[Width
- 1],
4096 StringPtr
+= StrnLenS (StringPtr
, Length
- ((UINTN
)StringPtr
- (UINTN
)*DefaultAltCfgResp
) / sizeof (CHAR16
));
4099 if (DefaultString
!= NULL
) {
4100 FreePool (DefaultString
);
4101 DefaultString
= NULL
;
4104 if ((BlockData
->OpCode
== EFI_IFR_STRING_OP
) && (TmpBuffer
!= NULL
)) {
4105 FreePool (TmpBuffer
);
4112 HiiToLower (*DefaultAltCfgResp
);
4118 This function gets the full request string and full default value string by
4119 parsing IFR data in HII form packages.
4121 When Request points to NULL string, the request string and default value string
4122 for each varstore in form package will return.
4124 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
4125 @param DevicePath Device Path which Hii Config Access Protocol is registered.
4126 @param Request Pointer to a null-terminated Unicode string in
4127 <ConfigRequest> format. When it doesn't contain
4128 any RequestElement, it will be updated to return
4129 the full RequestElement retrieved from IFR data.
4130 If it points to NULL, the request string for the first
4131 varstore in form package will be merged into a
4132 <MultiConfigRequest> format string and return.
4133 @param AltCfgResp Pointer to a null-terminated Unicode string in
4134 <ConfigAltResp> format. When the pointer is to NULL,
4135 the full default value string retrieved from IFR data
4136 will return. When the pinter is to a string, the
4137 full default value string retrieved from IFR data
4138 will be merged into the input string and return.
4139 When Request points to NULL, the default value string
4140 for each varstore in form package will be merged into
4141 a <MultiConfigAltResp> format string and return.
4142 @param PointerProgress Optional parameter, it can be NULL.
4143 When it is not NULL, if Request is NULL, it returns NULL.
4144 On return, points to a character in the Request
4145 string. Points to the string's null terminator if
4146 request was successful. Points to the most recent
4147 & before the first failing name / value pair (or
4148 the beginning of the string if the failure is in
4149 the first name / value pair) if the request was
4151 @retval EFI_SUCCESS The Results string is set to the full request string.
4152 And AltCfgResp contains all default value string.
4153 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
4154 @retval EFI_NOT_FOUND The varstore (Guid and Name) in Request string
4155 can't be found in Form package.
4156 @retval EFI_NOT_FOUND HiiPackage can't be got on the input HiiHandle.
4157 @retval EFI_INVALID_PARAMETER Request points to NULL.
4162 GetFullStringFromHiiFormPackages (
4163 IN HII_DATABASE_RECORD
*DataBaseRecord
,
4164 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
4165 IN OUT EFI_STRING
*Request
,
4166 IN OUT EFI_STRING
*AltCfgResp
,
4167 OUT EFI_STRING
*PointerProgress OPTIONAL
4171 UINT8
*HiiFormPackage
;
4173 IFR_BLOCK_DATA
*RequestBlockArray
;
4174 IFR_BLOCK_DATA
*BlockData
;
4175 IFR_DEFAULT_DATA
*DefaultValueData
;
4176 IFR_DEFAULT_DATA
*DefaultId
;
4177 IFR_DEFAULT_DATA
*DefaultIdArray
;
4178 IFR_VARSTORAGE_DATA
*VarStorageData
;
4179 EFI_STRING DefaultAltCfgResp
;
4180 EFI_STRING ConfigHdr
;
4181 EFI_STRING StringPtr
;
4182 EFI_STRING Progress
;
4184 if ((DataBaseRecord
== NULL
) || (DevicePath
== NULL
) || (Request
== NULL
) || (AltCfgResp
== NULL
)) {
4185 return EFI_INVALID_PARAMETER
;
4189 // Initialize the local variables.
4191 RequestBlockArray
= NULL
;
4192 DefaultIdArray
= NULL
;
4193 VarStorageData
= NULL
;
4194 DefaultAltCfgResp
= NULL
;
4196 HiiFormPackage
= NULL
;
4198 Progress
= *Request
;
4200 Status
= GetFormPackageData (DataBaseRecord
, &HiiFormPackage
, &PackageSize
);
4201 if (EFI_ERROR (Status
)) {
4206 // 1. Get the request block array by Request String when Request string contains the block array.
4209 if (*Request
!= NULL
) {
4210 StringPtr
= *Request
;
4214 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
4215 Status
= EFI_INVALID_PARAMETER
;
4219 StringPtr
+= StrLen (L
"GUID=");
4220 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&NAME=", StrLen (L
"&NAME=")) != 0) {
4224 if (*StringPtr
== L
'\0') {
4225 Status
= EFI_INVALID_PARAMETER
;
4229 StringPtr
+= StrLen (L
"&NAME=");
4230 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&PATH=", StrLen (L
"&PATH=")) != 0) {
4234 if (*StringPtr
== L
'\0') {
4235 Status
= EFI_INVALID_PARAMETER
;
4239 StringPtr
+= StrLen (L
"&PATH=");
4240 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
4244 if (*StringPtr
== L
'\0') {
4246 // No request block is found.
4253 // If StringPtr != NULL, get the request elements.
4255 if (StringPtr
!= NULL
) {
4256 if (StrStr (StringPtr
, L
"&OFFSET=") != NULL
) {
4257 RequestBlockArray
= GetBlockElement (StringPtr
, &Progress
);
4259 RequestBlockArray
= GetNameElement (StringPtr
, &Progress
);
4262 if (RequestBlockArray
== NULL
) {
4263 Status
= EFI_INVALID_PARAMETER
;
4269 // Initialize DefaultIdArray to store the map between DeaultId and DefaultName
4271 DefaultIdArray
= (IFR_DEFAULT_DATA
*)AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
4272 if (DefaultIdArray
== NULL
) {
4273 Status
= EFI_OUT_OF_RESOURCES
;
4277 InitializeListHead (&DefaultIdArray
->Entry
);
4280 // Initialize VarStorageData to store the var store Block and Default value information.
4282 VarStorageData
= (IFR_VARSTORAGE_DATA
*)AllocateZeroPool (sizeof (IFR_VARSTORAGE_DATA
));
4283 if (VarStorageData
== NULL
) {
4284 Status
= EFI_OUT_OF_RESOURCES
;
4288 InitializeListHead (&VarStorageData
->Entry
);
4289 InitializeListHead (&VarStorageData
->BlockEntry
);
4292 // 2. Parse FormPackage to get BlockArray and DefaultId Array for the request BlockArray.
4296 // Parse the opcode in form package to get the default setting.
4298 Status
= ParseIfrData (
4299 DataBaseRecord
->Handle
,
4301 (UINT32
)PackageSize
,
4307 if (EFI_ERROR (Status
)) {
4312 // No requested varstore in IFR data and directly return
4314 if ((VarStorageData
->Type
== 0) && (VarStorageData
->Name
== NULL
)) {
4315 Status
= EFI_SUCCESS
;
4320 // 3. Construct Request Element (Block Name) for 2.1 and 2.2 case.
4322 Status
= GenerateHdr (VarStorageData
, DevicePath
, &ConfigHdr
);
4323 if (EFI_ERROR (Status
)) {
4327 if (RequestBlockArray
== NULL
) {
4328 if (!GenerateConfigRequest (ConfigHdr
, VarStorageData
, &Status
, Request
)) {
4334 // 4. Construct Default Value string in AltResp according to request element.
4335 // Go through all VarStorageData Entry and get the DefaultId array for each one
4336 // Then construct them all to : ConfigHdr AltConfigHdr ConfigBody AltConfigHdr ConfigBody
4338 Status
= GenerateAltConfigResp (DataBaseRecord
->Handle
, ConfigHdr
, VarStorageData
, DefaultIdArray
, &DefaultAltCfgResp
);
4339 if (EFI_ERROR (Status
)) {
4344 // 5. Merge string into the input AltCfgResp if the input *AltCfgResp is not NULL.
4346 if ((*AltCfgResp
!= NULL
) && (DefaultAltCfgResp
!= NULL
)) {
4347 Status
= MergeDefaultString (AltCfgResp
, DefaultAltCfgResp
);
4348 FreePool (DefaultAltCfgResp
);
4349 } else if (*AltCfgResp
== NULL
) {
4350 *AltCfgResp
= DefaultAltCfgResp
;
4354 if (RequestBlockArray
!= NULL
) {
4356 // Free Link Array RequestBlockArray
4358 while (!IsListEmpty (&RequestBlockArray
->Entry
)) {
4359 BlockData
= BASE_CR (RequestBlockArray
->Entry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
4360 RemoveEntryList (&BlockData
->Entry
);
4361 if (BlockData
->Name
!= NULL
) {
4362 FreePool (BlockData
->Name
);
4365 FreePool (BlockData
);
4368 FreePool (RequestBlockArray
);
4371 if (VarStorageData
!= NULL
) {
4373 // Free link array VarStorageData
4375 while (!IsListEmpty (&VarStorageData
->BlockEntry
)) {
4376 BlockData
= BASE_CR (VarStorageData
->BlockEntry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
4377 RemoveEntryList (&BlockData
->Entry
);
4378 if (BlockData
->Name
!= NULL
) {
4379 FreePool (BlockData
->Name
);
4383 // Free default value link array
4385 while (!IsListEmpty (&BlockData
->DefaultValueEntry
)) {
4386 DefaultValueData
= BASE_CR (BlockData
->DefaultValueEntry
.ForwardLink
, IFR_DEFAULT_DATA
, Entry
);
4387 RemoveEntryList (&DefaultValueData
->Entry
);
4388 FreePool (DefaultValueData
);
4391 FreePool (BlockData
);
4394 if (VarStorageData
->Name
!= NULL
) {
4395 FreePool (VarStorageData
->Name
);
4396 VarStorageData
->Name
= NULL
;
4399 FreePool (VarStorageData
);
4402 if (DefaultIdArray
!= NULL
) {
4404 // Free DefaultId Array
4406 while (!IsListEmpty (&DefaultIdArray
->Entry
)) {
4407 DefaultId
= BASE_CR (DefaultIdArray
->Entry
.ForwardLink
, IFR_DEFAULT_DATA
, Entry
);
4408 RemoveEntryList (&DefaultId
->Entry
);
4409 FreePool (DefaultId
);
4412 FreePool (DefaultIdArray
);
4416 // Free the allocated string
4418 if (ConfigHdr
!= NULL
) {
4419 FreePool (ConfigHdr
);
4423 // Free Package data
4425 if (HiiFormPackage
!= NULL
) {
4426 FreePool (HiiFormPackage
);
4429 if (PointerProgress
!= NULL
) {
4430 if (*Request
== NULL
) {
4431 *PointerProgress
= NULL
;
4432 } else if (EFI_ERROR (Status
)) {
4433 *PointerProgress
= *Request
;
4435 *PointerProgress
= *Request
+ StrLen (*Request
);
4443 This function gets the full request resp string by
4444 parsing IFR data in HII form packages.
4446 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
4448 @param EfiVarStoreInfo The efi varstore info which is save in the EFI
4449 varstore data structure.
4450 @param Request Pointer to a null-terminated Unicode string in
4451 <ConfigRequest> format.
4452 @param RequestResp Pointer to a null-terminated Unicode string in
4453 <ConfigResp> format.
4454 @param AccessProgress On return, points to a character in the Request
4455 string. Points to the string's null terminator if
4456 request was successful. Points to the most recent
4457 & before the first failing name / value pair (or
4458 the beginning of the string if the failure is in
4459 the first name / value pair) if the request was
4462 @retval EFI_SUCCESS The Results string is set to the full request string.
4463 And AltCfgResp contains all default value string.
4464 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
4465 @retval EFI_INVALID_PARAMETER Request points to NULL.
4469 GetConfigRespFromEfiVarStore (
4470 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
4471 IN EFI_IFR_VARSTORE_EFI
*EfiVarStoreInfo
,
4472 IN EFI_STRING Request
,
4473 OUT EFI_STRING
*RequestResp
,
4474 OUT EFI_STRING
*AccessProgress
4478 EFI_STRING VarStoreName
;
4483 Status
= EFI_SUCCESS
;
4486 VarStoreName
= NULL
;
4487 *AccessProgress
= Request
;
4489 NameSize
= AsciiStrSize ((CHAR8
*)EfiVarStoreInfo
->Name
);
4490 VarStoreName
= AllocateZeroPool (NameSize
* sizeof (CHAR16
));
4491 if (VarStoreName
== NULL
) {
4492 Status
= EFI_OUT_OF_RESOURCES
;
4496 AsciiStrToUnicodeStrS ((CHAR8
*)EfiVarStoreInfo
->Name
, VarStoreName
, NameSize
);
4498 Status
= gRT
->GetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, NULL
, &BufferSize
, NULL
);
4499 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
4503 VarStore
= AllocateZeroPool (BufferSize
);
4504 ASSERT (VarStore
!= NULL
);
4505 Status
= gRT
->GetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, NULL
, &BufferSize
, VarStore
);
4506 if (EFI_ERROR (Status
)) {
4510 Status
= HiiBlockToConfig (This
, Request
, VarStore
, BufferSize
, RequestResp
, AccessProgress
);
4511 if (EFI_ERROR (Status
)) {
4516 if (VarStoreName
!= NULL
) {
4517 FreePool (VarStoreName
);
4520 if (VarStore
!= NULL
) {
4521 FreePool (VarStore
);
4528 This function route the full request resp string for efi varstore.
4530 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
4532 @param EfiVarStoreInfo The efi varstore info which is save in the EFI
4533 varstore data structure.
4534 @param RequestResp Pointer to a null-terminated Unicode string in
4535 <ConfigResp> format.
4536 @param Result Pointer to a null-terminated Unicode string in
4537 <ConfigResp> format.
4539 @retval EFI_SUCCESS The Results string is set to the full request string.
4540 And AltCfgResp contains all default value string.
4541 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
4542 @retval EFI_INVALID_PARAMETER Request points to NULL.
4546 RouteConfigRespForEfiVarStore (
4547 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
4548 IN EFI_IFR_VARSTORE_EFI
*EfiVarStoreInfo
,
4549 IN EFI_STRING RequestResp
,
4550 OUT EFI_STRING
*Result
4554 EFI_STRING VarStoreName
;
4560 Status
= EFI_SUCCESS
;
4563 VarStoreName
= NULL
;
4564 *Result
= RequestResp
;
4566 NameSize
= AsciiStrSize ((CHAR8
*)EfiVarStoreInfo
->Name
);
4567 VarStoreName
= AllocateZeroPool (NameSize
* sizeof (CHAR16
));
4568 if (VarStoreName
== NULL
) {
4569 Status
= EFI_OUT_OF_RESOURCES
;
4573 AsciiStrToUnicodeStrS ((CHAR8
*)EfiVarStoreInfo
->Name
, VarStoreName
, NameSize
);
4575 Status
= gRT
->GetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, NULL
, &BufferSize
, NULL
);
4576 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
4577 DEBUG ((DEBUG_ERROR
, "The variable does not exist!"));
4581 BlockSize
= BufferSize
;
4582 VarStore
= AllocateZeroPool (BufferSize
);
4583 ASSERT (VarStore
!= NULL
);
4584 Status
= gRT
->GetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, NULL
, &BufferSize
, VarStore
);
4585 if (EFI_ERROR (Status
)) {
4589 Status
= HiiConfigToBlock (This
, RequestResp
, VarStore
, &BlockSize
, Result
);
4590 if (EFI_ERROR (Status
)) {
4594 Status
= gRT
->SetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, EfiVarStoreInfo
->Attributes
, BufferSize
, VarStore
);
4595 if (EFI_ERROR (Status
)) {
4596 *Result
= RequestResp
;
4601 if (VarStoreName
!= NULL
) {
4602 FreePool (VarStoreName
);
4605 if (VarStore
!= NULL
) {
4606 FreePool (VarStore
);
4613 Validate the config request elements.
4615 @param ConfigElements A null-terminated Unicode string in <ConfigRequest> format,
4616 without configHdr field.
4618 @retval CHAR16 * THE first Name/value pair not correct.
4619 @retval NULL Success parse the name/value pair
4622 OffsetWidthValidate (
4623 CHAR16
*ConfigElements
4629 StringPtr
= ConfigElements
;
4633 if (StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) != 0) {
4637 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
4641 if (*StringPtr
== L
'\0') {
4645 StringPtr
+= StrLen (L
"&WIDTH=");
4646 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) != 0) {
4650 if (*StringPtr
== L
'\0') {
4657 Validate the config request elements.
4659 @param ConfigElements A null-terminated Unicode string in <ConfigRequest> format,
4660 without configHdr field.
4662 @retval CHAR16 * THE first Name/value pair not correct.
4663 @retval NULL Success parse the name/value pair
4668 CHAR16
*ConfigElements
4674 StringPtr
= ConfigElements
;
4678 if (*StringPtr
!= L
'&') {
4684 StringPtr
= StrStr (StringPtr
, L
"&");
4686 if (StringPtr
== NULL
) {
4693 Validate the config request string.
4695 @param ConfigRequest A null-terminated Unicode string in <ConfigRequest> format.
4697 @retval CHAR16 * THE first element not correct.
4698 @retval NULL Success parse the name/value pair
4702 ConfigRequestValidate (
4703 CHAR16
*ConfigRequest
4706 BOOLEAN HasNameField
;
4709 HasNameField
= TRUE
;
4710 StringPtr
= ConfigRequest
;
4713 // Check <ConfigHdr>
4715 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
4716 return ConfigRequest
;
4719 StringPtr
+= StrLen (L
"GUID=");
4720 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&NAME=", StrLen (L
"&NAME=")) != 0) {
4724 if (*StringPtr
== L
'\0') {
4725 return ConfigRequest
;
4728 StringPtr
+= StrLen (L
"&NAME=");
4729 if (*StringPtr
== L
'&') {
4730 HasNameField
= FALSE
;
4733 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&PATH=", StrLen (L
"&PATH=")) != 0) {
4737 if (*StringPtr
== L
'\0') {
4738 return ConfigRequest
;
4741 StringPtr
+= StrLen (L
"&PATH=");
4742 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
4746 if (*StringPtr
== L
'\0') {
4752 // Should be Buffer varstore, config request should be "OFFSET/Width" pairs.
4754 return OffsetWidthValidate (StringPtr
);
4757 // Should be Name/Value varstore, config request should be "&name1&name2..." pairs.
4759 return NameValueValidate (StringPtr
);
4764 This function allows a caller to extract the current configuration
4765 for one or more named elements from one or more drivers.
4767 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
4769 @param Request A null-terminated Unicode string in
4770 <MultiConfigRequest> format.
4771 @param Progress On return, points to a character in the Request
4772 string. Points to the string's null terminator if
4773 request was successful. Points to the most recent
4774 & before the first failing name / value pair (or
4775 the beginning of the string if the failure is in
4776 the first name / value pair) if the request was
4778 @param Results Null-terminated Unicode string in
4779 <MultiConfigAltResp> format which has all values
4780 filled in for the names in the Request string.
4781 String to be allocated by the called function.
4783 @retval EFI_SUCCESS The Results string is filled with the values
4784 corresponding to all requested names.
4785 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
4786 results that must be stored awaiting possible
4788 @retval EFI_NOT_FOUND Routing data doesn't match any known driver.
4789 Progress set to the "G" in "GUID" of the routing
4790 header that doesn't match. Note: There is no
4791 requirement that all routing data be validated
4792 before any configuration extraction.
4793 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Request
4794 parameter would result in this type of error. The
4795 Progress parameter is set to NULL.
4796 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set to most recent &
4797 before the error or the beginning of the string.
4798 @retval EFI_INVALID_PARAMETER The ExtractConfig function of the underlying HII
4799 Configuration Access Protocol returned
4800 EFI_INVALID_PARAMETER. Progress set to most recent
4801 & before the error or the beginning of the string.
4806 HiiConfigRoutingExtractConfig (
4807 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
4808 IN CONST EFI_STRING Request
,
4809 OUT EFI_STRING
*Progress
,
4810 OUT EFI_STRING
*Results
4813 HII_DATABASE_PRIVATE_DATA
*Private
;
4814 EFI_STRING StringPtr
;
4815 EFI_STRING ConfigRequest
;
4817 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
4818 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
4821 HII_DATABASE_RECORD
*Database
;
4822 UINT8
*DevicePathPkg
;
4823 UINT8
*CurrentDevicePath
;
4824 EFI_HANDLE DriverHandle
;
4825 EFI_HII_HANDLE HiiHandle
;
4826 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
4827 EFI_STRING AccessProgress
;
4828 EFI_STRING AccessResults
;
4829 EFI_STRING AccessProgressBackup
;
4830 EFI_STRING AccessResultsBackup
;
4831 EFI_STRING DefaultResults
;
4832 BOOLEAN FirstElement
;
4833 BOOLEAN IfrDataParsedFlag
;
4834 BOOLEAN IsEfiVarStore
;
4835 EFI_IFR_VARSTORE_EFI
*EfiVarStoreInfo
;
4836 EFI_STRING ErrorPtr
;
4837 UINTN DevicePathSize
;
4838 UINTN ConigStringSize
;
4839 UINTN ConigStringSizeNewsize
;
4840 EFI_STRING ConfigStringPtr
;
4842 if ((This
== NULL
) || (Progress
== NULL
) || (Results
== NULL
)) {
4843 return EFI_INVALID_PARAMETER
;
4846 if (Request
== NULL
) {
4848 return EFI_INVALID_PARAMETER
;
4851 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
4852 StringPtr
= Request
;
4853 *Progress
= StringPtr
;
4854 DefaultResults
= NULL
;
4855 ConfigRequest
= NULL
;
4856 Status
= EFI_SUCCESS
;
4857 AccessResults
= NULL
;
4858 AccessProgress
= NULL
;
4859 AccessResultsBackup
= NULL
;
4860 AccessProgressBackup
= NULL
;
4862 IfrDataParsedFlag
= FALSE
;
4863 IsEfiVarStore
= FALSE
;
4864 EfiVarStoreInfo
= NULL
;
4867 // The first element of <MultiConfigRequest> should be
4868 // <GuidHdr>, which is in 'GUID='<Guid> syntax.
4870 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
4871 return EFI_INVALID_PARAMETER
;
4874 FirstElement
= TRUE
;
4877 // Allocate a fix length of memory to store Results. Reallocate memory for
4878 // Results if this fix length is insufficient.
4880 *Results
= (EFI_STRING
)AllocateZeroPool (MAX_STRING_LENGTH
);
4881 if (*Results
== NULL
) {
4882 return EFI_OUT_OF_RESOURCES
;
4885 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) == 0) {
4887 // If parsing error, set Progress to the beginning of the <MultiConfigRequest>
4888 // or most recent & before the error.
4890 if (StringPtr
== Request
) {
4891 *Progress
= StringPtr
;
4893 *Progress
= StringPtr
- 1;
4897 // Process each <ConfigRequest> of <MultiConfigRequest>
4899 Length
= CalculateConfigStringLen (StringPtr
);
4900 ConfigRequest
= AllocateCopyPool ((Length
+ 1) * sizeof (CHAR16
), StringPtr
);
4901 if (ConfigRequest
== NULL
) {
4902 Status
= EFI_OUT_OF_RESOURCES
;
4906 *(ConfigRequest
+ Length
) = 0;
4909 // Get the UEFI device path
4911 Status
= GetDevicePath (ConfigRequest
, (UINT8
**)&DevicePath
);
4912 if (EFI_ERROR (Status
)) {
4917 // Find driver which matches the routing data.
4919 DriverHandle
= NULL
;
4922 for (Link
= Private
->DatabaseList
.ForwardLink
;
4923 Link
!= &Private
->DatabaseList
;
4924 Link
= Link
->ForwardLink
4927 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
4928 if ((DevicePathPkg
= Database
->PackageList
->DevicePathPkg
) != NULL
) {
4929 CurrentDevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
4930 DevicePathSize
= GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*)CurrentDevicePath
);
4931 if ((CompareMem (DevicePath
, CurrentDevicePath
, DevicePathSize
) == 0) && IsThisPackageList (Database
, ConfigRequest
)) {
4932 DriverHandle
= Database
->DriverHandle
;
4933 HiiHandle
= Database
->Handle
;
4940 // Try to find driver handle by device path.
4942 if (DriverHandle
== NULL
) {
4943 TempDevicePath
= DevicePath
;
4944 Status
= gBS
->LocateDevicePath (
4945 &gEfiDevicePathProtocolGuid
,
4949 if (EFI_ERROR (Status
) || (DriverHandle
== NULL
)) {
4951 // Routing data does not match any known driver.
4952 // Set Progress to the 'G' in "GUID" of the routing header.
4954 *Progress
= StringPtr
;
4955 Status
= EFI_NOT_FOUND
;
4961 // Validate ConfigRequest String.
4963 ErrorPtr
= ConfigRequestValidate (ConfigRequest
);
4964 if (ErrorPtr
!= NULL
) {
4965 *Progress
= StrStr (StringPtr
, ErrorPtr
);
4966 Status
= EFI_INVALID_PARAMETER
;
4971 // Check whether ConfigRequest contains request string.
4973 IfrDataParsedFlag
= FALSE
;
4974 if ((HiiHandle
!= NULL
) && !GetElementsFromRequest (ConfigRequest
)) {
4976 // Get the full request string from IFR when HiiPackage is registered to HiiHandle
4978 IfrDataParsedFlag
= TRUE
;
4979 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &ConfigRequest
, &DefaultResults
, &AccessProgress
);
4980 if (EFI_ERROR (Status
)) {
4982 // AccessProgress indicates the parsing progress on <ConfigRequest>.
4983 // Map it to the progress on <MultiConfigRequest> then return it.
4985 ASSERT (AccessProgress
!= NULL
);
4986 *Progress
= StrStr (StringPtr
, AccessProgress
);
4991 // Not any request block is found.
4993 if (!GetElementsFromRequest (ConfigRequest
)) {
4994 AccessResults
= AllocateCopyPool (StrSize (ConfigRequest
), ConfigRequest
);
4995 goto NextConfigString
;
5000 // Check whether this ConfigRequest is search from Efi varstore type storage.
5002 Status
= GetVarStoreType (Database
, ConfigRequest
, &IsEfiVarStore
, &EfiVarStoreInfo
);
5003 if (EFI_ERROR (Status
)) {
5007 if (IsEfiVarStore
) {
5009 // Call the GetVariable function to extract settings.
5011 Status
= GetConfigRespFromEfiVarStore (This
, EfiVarStoreInfo
, ConfigRequest
, &AccessResults
, &AccessProgress
);
5012 FreePool (EfiVarStoreInfo
);
5013 if (EFI_ERROR (Status
)) {
5015 // AccessProgress indicates the parsing progress on <ConfigRequest>.
5016 // Map it to the progress on <MultiConfigRequest> then return it.
5018 *Progress
= StrStr (StringPtr
, AccessProgress
);
5023 // For EfiVarstore, call corresponding ConfigAccess protocol to get the AltCfgResp from driver.
5025 Status
= gBS
->HandleProtocol (
5027 &gEfiHiiConfigAccessProtocolGuid
,
5028 (VOID
**)&ConfigAccess
5030 if (EFI_ERROR (Status
)) {
5032 // The driver has EfiVarStore, may not install ConfigAccess protocol.
5033 // So ignore the error status in this case.
5035 Status
= EFI_SUCCESS
;
5037 Status
= ConfigAccess
->ExtractConfig (
5040 &AccessProgressBackup
,
5041 &AccessResultsBackup
5043 if (!EFI_ERROR (Status
)) {
5045 // Merge the AltCfgResp in AccessResultsBackup to AccessResults
5047 if ((AccessResultsBackup
!= NULL
) && (StrStr (AccessResultsBackup
, L
"&ALTCFG=") != NULL
)) {
5048 ConigStringSize
= StrSize (AccessResults
);
5049 ConfigStringPtr
= StrStr (AccessResultsBackup
, L
"&GUID=");
5050 ConigStringSizeNewsize
= StrSize (ConfigStringPtr
) + ConigStringSize
+ sizeof (CHAR16
);
5051 AccessResults
= (EFI_STRING
)ReallocatePool (
5053 ConigStringSizeNewsize
,
5056 StrCatS (AccessResults
, ConigStringSizeNewsize
/ sizeof (CHAR16
), ConfigStringPtr
);
5060 // In the ExtractConfig function of some driver may not support EfiVarStore,
5061 // may return error status, just ignore the error status in this case.
5063 Status
= EFI_SUCCESS
;
5066 if (AccessResultsBackup
!= NULL
) {
5067 FreePool (AccessResultsBackup
);
5068 AccessResultsBackup
= NULL
;
5073 // Call corresponding ConfigAccess protocol to extract settings
5075 Status
= gBS
->HandleProtocol (
5077 &gEfiHiiConfigAccessProtocolGuid
,
5078 (VOID
**)&ConfigAccess
5080 if (EFI_ERROR (Status
)) {
5084 Status
= ConfigAccess
->ExtractConfig (
5092 if (EFI_ERROR (Status
)) {
5094 // AccessProgress indicates the parsing progress on <ConfigRequest>.
5095 // Map it to the progress on <MultiConfigRequest> then return it.
5097 *Progress
= StrStr (StringPtr
, AccessProgress
);
5102 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'
5103 // which separates the first <ConfigAltResp> and the following ones.
5105 ASSERT (*AccessProgress
== 0);
5108 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
5110 if (!IfrDataParsedFlag
&& (HiiHandle
!= NULL
)) {
5111 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &ConfigRequest
, &DefaultResults
, NULL
);
5112 ASSERT_EFI_ERROR (Status
);
5115 FreePool (DevicePath
);
5118 if (DefaultResults
!= NULL
) {
5119 Status
= MergeDefaultString (&AccessResults
, DefaultResults
);
5120 ASSERT_EFI_ERROR (Status
);
5121 FreePool (DefaultResults
);
5122 DefaultResults
= NULL
;
5126 if (!FirstElement
) {
5127 Status
= AppendToMultiString (Results
, L
"&");
5128 ASSERT_EFI_ERROR (Status
);
5131 Status
= AppendToMultiString (Results
, AccessResults
);
5132 ASSERT_EFI_ERROR (Status
);
5134 FirstElement
= FALSE
;
5136 FreePool (AccessResults
);
5137 AccessResults
= NULL
;
5138 FreePool (ConfigRequest
);
5139 ConfigRequest
= NULL
;
5142 // Go to next <ConfigRequest> (skip '&').
5144 StringPtr
+= Length
;
5145 if (*StringPtr
== 0) {
5146 *Progress
= StringPtr
;
5154 if (EFI_ERROR (Status
)) {
5155 FreePool (*Results
);
5159 if (ConfigRequest
!= NULL
) {
5160 FreePool (ConfigRequest
);
5163 if (AccessResults
!= NULL
) {
5164 FreePool (AccessResults
);
5167 if (DefaultResults
!= NULL
) {
5168 FreePool (DefaultResults
);
5171 if (DevicePath
!= NULL
) {
5172 FreePool (DevicePath
);
5179 This function allows the caller to request the current configuration for the
5180 entirety of the current HII database and returns the data in a
5181 null-terminated Unicode string.
5183 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
5185 @param Results Null-terminated Unicode string in
5186 <MultiConfigAltResp> format which has all values
5187 filled in for the entirety of the current HII
5188 database. String to be allocated by the called
5189 function. De-allocation is up to the caller.
5191 @retval EFI_SUCCESS The Results string is filled with the values
5192 corresponding to all requested names.
5193 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
5194 results that must be stored awaiting possible
5196 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Results
5197 parameter would result in this type of error.
5202 HiiConfigRoutingExportConfig (
5203 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
5204 OUT EFI_STRING
*Results
5208 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
5209 EFI_STRING AccessResults
;
5210 EFI_STRING Progress
;
5211 EFI_STRING StringPtr
;
5212 EFI_STRING ConfigRequest
;
5214 EFI_HANDLE
*ConfigAccessHandles
;
5215 UINTN NumberConfigAccessHandles
;
5216 BOOLEAN FirstElement
;
5217 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
5218 EFI_HII_HANDLE HiiHandle
;
5219 EFI_STRING DefaultResults
;
5220 HII_DATABASE_PRIVATE_DATA
*Private
;
5222 HII_DATABASE_RECORD
*Database
;
5223 UINT8
*DevicePathPkg
;
5224 UINT8
*CurrentDevicePath
;
5225 BOOLEAN IfrDataParsedFlag
;
5227 if ((This
== NULL
) || (Results
== NULL
)) {
5228 return EFI_INVALID_PARAMETER
;
5231 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
5234 // Allocate a fix length of memory to store Results. Reallocate memory for
5235 // Results if this fix length is insufficient.
5237 *Results
= (EFI_STRING
)AllocateZeroPool (MAX_STRING_LENGTH
);
5238 if (*Results
== NULL
) {
5239 return EFI_OUT_OF_RESOURCES
;
5242 NumberConfigAccessHandles
= 0;
5243 Status
= gBS
->LocateHandleBuffer (
5245 &gEfiHiiConfigAccessProtocolGuid
,
5247 &NumberConfigAccessHandles
,
5248 &ConfigAccessHandles
5250 if (EFI_ERROR (Status
)) {
5254 FirstElement
= TRUE
;
5256 for (Index
= 0; Index
< NumberConfigAccessHandles
; Index
++) {
5257 Status
= gBS
->HandleProtocol (
5258 ConfigAccessHandles
[Index
],
5259 &gEfiHiiConfigAccessProtocolGuid
,
5260 (VOID
**)&ConfigAccess
5262 if (EFI_ERROR (Status
)) {
5267 // Get DevicePath and HiiHandle for this ConfigAccess driver handle
5269 IfrDataParsedFlag
= FALSE
;
5272 DefaultResults
= NULL
;
5274 ConfigRequest
= NULL
;
5275 DevicePath
= DevicePathFromHandle (ConfigAccessHandles
[Index
]);
5276 if (DevicePath
!= NULL
) {
5277 for (Link
= Private
->DatabaseList
.ForwardLink
;
5278 Link
!= &Private
->DatabaseList
;
5279 Link
= Link
->ForwardLink
5282 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
5283 if ((DevicePathPkg
= Database
->PackageList
->DevicePathPkg
) != NULL
) {
5284 CurrentDevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
5288 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*)CurrentDevicePath
)
5291 HiiHandle
= Database
->Handle
;
5298 Status
= ConfigAccess
->ExtractConfig (
5304 if (EFI_ERROR (Status
)) {
5306 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
5308 if ((HiiHandle
!= NULL
) && (DevicePath
!= NULL
)) {
5309 IfrDataParsedFlag
= TRUE
;
5310 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &ConfigRequest
, &DefaultResults
, NULL
);
5312 // Get the full request string to get the Current setting again.
5314 if (!EFI_ERROR (Status
) && (ConfigRequest
!= NULL
)) {
5315 Status
= ConfigAccess
->ExtractConfig (
5321 FreePool (ConfigRequest
);
5323 Status
= EFI_NOT_FOUND
;
5328 if (!EFI_ERROR (Status
)) {
5330 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
5332 if (!IfrDataParsedFlag
&& (HiiHandle
!= NULL
) && (DevicePath
!= NULL
)) {
5333 StringPtr
= StrStr (AccessResults
, L
"&GUID=");
5334 if (StringPtr
!= NULL
) {
5338 if (GetElementsFromRequest (AccessResults
)) {
5339 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &AccessResults
, &DefaultResults
, NULL
);
5340 ASSERT_EFI_ERROR (Status
);
5343 if (StringPtr
!= NULL
) {
5349 // Merge the default sting from IFR code into the got setting from driver.
5351 if (DefaultResults
!= NULL
) {
5352 Status
= MergeDefaultString (&AccessResults
, DefaultResults
);
5353 ASSERT_EFI_ERROR (Status
);
5354 FreePool (DefaultResults
);
5355 DefaultResults
= NULL
;
5359 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'
5360 // which separates the first <ConfigAltResp> and the following ones.
5362 if (!FirstElement
) {
5363 Status
= AppendToMultiString (Results
, L
"&");
5364 ASSERT_EFI_ERROR (Status
);
5367 Status
= AppendToMultiString (Results
, AccessResults
);
5368 ASSERT_EFI_ERROR (Status
);
5370 FirstElement
= FALSE
;
5372 FreePool (AccessResults
);
5373 AccessResults
= NULL
;
5377 FreePool (ConfigAccessHandles
);
5383 This function processes the results of processing forms and routes it to the
5384 appropriate handlers or storage.
5386 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
5388 @param Configuration A null-terminated Unicode string in
5389 <MulltiConfigResp> format.
5390 @param Progress A pointer to a string filled in with the offset of
5391 the most recent & before the first failing name /
5392 value pair (or the beginning of the string if the
5393 failure is in the first name / value pair) or the
5394 terminating NULL if all was successful.
5396 @retval EFI_SUCCESS The results have been distributed or are awaiting
5398 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
5399 results that must be stored awaiting possible
5401 @retval EFI_INVALID_PARAMETER Passing in a NULL for the Configuration parameter
5402 would result in this type of error.
5403 @retval EFI_NOT_FOUND Target for the specified routing data was not
5409 HiiConfigRoutingRouteConfig (
5410 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
5411 IN CONST EFI_STRING Configuration
,
5412 OUT EFI_STRING
*Progress
5415 HII_DATABASE_PRIVATE_DATA
*Private
;
5416 EFI_STRING StringPtr
;
5417 EFI_STRING ConfigResp
;
5420 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
5421 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
5423 HII_DATABASE_RECORD
*Database
;
5424 UINT8
*DevicePathPkg
;
5425 UINT8
*CurrentDevicePath
;
5426 EFI_HANDLE DriverHandle
;
5427 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
5428 EFI_STRING AccessProgress
;
5429 EFI_IFR_VARSTORE_EFI
*EfiVarStoreInfo
;
5430 BOOLEAN IsEfiVarstore
;
5431 UINTN DevicePathSize
;
5433 if ((This
== NULL
) || (Progress
== NULL
)) {
5434 return EFI_INVALID_PARAMETER
;
5437 if (Configuration
== NULL
) {
5439 return EFI_INVALID_PARAMETER
;
5442 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
5443 StringPtr
= Configuration
;
5444 *Progress
= StringPtr
;
5446 AccessProgress
= NULL
;
5447 EfiVarStoreInfo
= NULL
;
5448 IsEfiVarstore
= FALSE
;
5451 // The first element of <MultiConfigResp> should be
5452 // <GuidHdr>, which is in 'GUID='<Guid> syntax.
5454 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
5455 return EFI_INVALID_PARAMETER
;
5458 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) == 0) {
5460 // If parsing error, set Progress to the beginning of the <MultiConfigResp>
5461 // or most recent & before the error.
5463 if (StringPtr
== Configuration
) {
5464 *Progress
= StringPtr
;
5466 *Progress
= StringPtr
- 1;
5470 // Process each <ConfigResp> of <MultiConfigResp>
5472 Length
= CalculateConfigStringLen (StringPtr
);
5473 ConfigResp
= AllocateCopyPool ((Length
+ 1) * sizeof (CHAR16
), StringPtr
);
5474 if (ConfigResp
== NULL
) {
5475 return EFI_OUT_OF_RESOURCES
;
5479 // Append '\0' to the end of ConfigRequest
5481 *(ConfigResp
+ Length
) = 0;
5484 // Get the UEFI device path
5486 Status
= GetDevicePath (ConfigResp
, (UINT8
**)&DevicePath
);
5487 if (EFI_ERROR (Status
)) {
5488 FreePool (ConfigResp
);
5493 // Find driver which matches the routing data.
5495 DriverHandle
= NULL
;
5496 for (Link
= Private
->DatabaseList
.ForwardLink
;
5497 Link
!= &Private
->DatabaseList
;
5498 Link
= Link
->ForwardLink
5501 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
5503 if ((DevicePathPkg
= Database
->PackageList
->DevicePathPkg
) != NULL
) {
5504 CurrentDevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
5505 DevicePathSize
= GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*)CurrentDevicePath
);
5506 if ((CompareMem (DevicePath
, CurrentDevicePath
, DevicePathSize
) == 0) && IsThisPackageList (Database
, ConfigResp
)) {
5507 DriverHandle
= Database
->DriverHandle
;
5514 // Try to find driver handle by device path.
5516 if (DriverHandle
== NULL
) {
5517 TempDevicePath
= DevicePath
;
5518 Status
= gBS
->LocateDevicePath (
5519 &gEfiDevicePathProtocolGuid
,
5523 if (EFI_ERROR (Status
) || (DriverHandle
== NULL
)) {
5525 // Routing data does not match any known driver.
5526 // Set Progress to the 'G' in "GUID" of the routing header.
5528 FreePool (DevicePath
);
5529 *Progress
= StringPtr
;
5530 FreePool (ConfigResp
);
5531 return EFI_NOT_FOUND
;
5535 FreePool (DevicePath
);
5538 // Check whether this ConfigRequest is search from Efi varstore type storage.
5540 Status
= GetVarStoreType (Database
, ConfigResp
, &IsEfiVarstore
, &EfiVarStoreInfo
);
5541 if (EFI_ERROR (Status
)) {
5545 if (IsEfiVarstore
) {
5547 // Call the SetVariable function to route settings.
5549 Status
= RouteConfigRespForEfiVarStore (This
, EfiVarStoreInfo
, ConfigResp
, &AccessProgress
);
5550 FreePool (EfiVarStoreInfo
);
5553 // Call corresponding ConfigAccess protocol to route settings
5555 Status
= gBS
->HandleProtocol (
5557 &gEfiHiiConfigAccessProtocolGuid
,
5558 (VOID
**)&ConfigAccess
5560 if (EFI_ERROR (Status
)) {
5561 *Progress
= StringPtr
;
5562 FreePool (ConfigResp
);
5563 return EFI_NOT_FOUND
;
5566 Status
= ConfigAccess
->RouteConfig (
5573 if (EFI_ERROR (Status
)) {
5574 ASSERT (AccessProgress
!= NULL
);
5576 // AccessProgress indicates the parsing progress on <ConfigResp>.
5577 // Map it to the progress on <MultiConfigResp> then return it.
5579 *Progress
= StrStr (StringPtr
, AccessProgress
);
5581 FreePool (ConfigResp
);
5585 FreePool (ConfigResp
);
5589 // Go to next <ConfigResp> (skip '&').
5591 StringPtr
+= Length
;
5592 if (*StringPtr
== 0) {
5593 *Progress
= StringPtr
;
5604 This helper function is to be called by drivers to map configuration data
5605 stored in byte array ("block") formats such as UEFI Variables into current
5606 configuration strings.
5608 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
5610 @param ConfigRequest A null-terminated Unicode string in
5611 <ConfigRequest> format.
5612 @param Block Array of bytes defining the block's configuration.
5613 @param BlockSize Length in bytes of Block.
5614 @param Config Filled-in configuration string. String allocated
5615 by the function. Returned only if call is
5616 successful. It is <ConfigResp> string format.
5617 @param Progress A pointer to a string filled in with the offset of
5618 the most recent & before the first failing
5619 name/value pair (or the beginning of the string if
5620 the failure is in the first name / value pair) or
5621 the terminating NULL if all was successful.
5623 @retval EFI_SUCCESS The request succeeded. Progress points to the null
5624 terminator at the end of the ConfigRequest
5626 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress
5627 points to the first character of ConfigRequest.
5628 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigRequest or
5629 Block parameter would result in this type of
5630 error. Progress points to the first character of
5632 @retval EFI_DEVICE_ERROR Block not large enough. Progress undefined.
5633 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted string.
5634 Block is left updated and Progress points at
5635 the "&" preceding the first non-<BlockName>.
5641 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
5642 IN CONST EFI_STRING ConfigRequest
,
5643 IN CONST UINT8
*Block
,
5644 IN CONST UINTN BlockSize
,
5645 OUT EFI_STRING
*Config
,
5646 OUT EFI_STRING
*Progress
5649 HII_DATABASE_PRIVATE_DATA
*Private
;
5650 EFI_STRING StringPtr
;
5658 EFI_STRING ValueStr
;
5659 EFI_STRING ConfigElement
;
5666 if ((This
== NULL
) || (Progress
== NULL
) || (Config
== NULL
)) {
5667 return EFI_INVALID_PARAMETER
;
5670 if ((Block
== NULL
) || (ConfigRequest
== NULL
)) {
5671 *Progress
= ConfigRequest
;
5672 return EFI_INVALID_PARAMETER
;
5675 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
5676 ASSERT (Private
!= NULL
);
5678 StringPtr
= ConfigRequest
;
5681 ConfigElement
= NULL
;
5684 // Allocate a fix length of memory to store Results. Reallocate memory for
5685 // Results if this fix length is insufficient.
5687 *Config
= (EFI_STRING
)AllocateZeroPool (MAX_STRING_LENGTH
);
5688 if (*Config
== NULL
) {
5689 return EFI_OUT_OF_RESOURCES
;
5695 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
5696 *Progress
= StringPtr
;
5697 Status
= EFI_INVALID_PARAMETER
;
5701 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"PATH=", StrLen (L
"PATH=")) != 0) {
5705 if (*StringPtr
== 0) {
5706 *Progress
= StringPtr
- 1;
5707 Status
= EFI_INVALID_PARAMETER
;
5711 while (*StringPtr
!= L
'&' && *StringPtr
!= 0) {
5715 if (*StringPtr
== 0) {
5716 *Progress
= StringPtr
;
5718 AppendToMultiString (Config
, ConfigRequest
);
5719 HiiToLower (*Config
);
5730 // Copy <ConfigHdr> and an additional '&' to <ConfigResp>
5732 TemString
= AllocateCopyPool (sizeof (CHAR16
) * (StringPtr
- ConfigRequest
+ 1), ConfigRequest
);
5733 if (TemString
== NULL
) {
5734 return EFI_OUT_OF_RESOURCES
;
5737 TemString
[StringPtr
- ConfigRequest
] = '\0';
5738 AppendToMultiString (Config
, TemString
);
5739 FreePool (TemString
);
5742 // Parse each <RequestElement> if exists
5743 // Only <BlockName> format is supported by this help function.
5744 // <BlockName> ::= 'OFFSET='<Number>&'WIDTH='<Number>
5746 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"OFFSET=", StrLen (L
"OFFSET=")) == 0) {
5748 // Back up the header of one <BlockName>
5752 StringPtr
+= StrLen (L
"OFFSET=");
5756 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
5757 if (EFI_ERROR (Status
)) {
5758 *Progress
= TmpPtr
- 1;
5766 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
5768 FreePool (TmpBuffer
);
5770 StringPtr
+= Length
;
5771 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
5772 *Progress
= TmpPtr
- 1;
5773 Status
= EFI_INVALID_PARAMETER
;
5777 StringPtr
+= StrLen (L
"&WIDTH=");
5782 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
5783 if (EFI_ERROR (Status
)) {
5784 *Progress
= TmpPtr
- 1;
5792 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
5794 FreePool (TmpBuffer
);
5796 StringPtr
+= Length
;
5797 if ((*StringPtr
!= 0) && (*StringPtr
!= L
'&')) {
5798 *Progress
= TmpPtr
- 1;
5799 Status
= EFI_INVALID_PARAMETER
;
5804 // Calculate Value and convert it to hex string.
5806 if (Offset
+ Width
> BlockSize
) {
5807 *Progress
= StringPtr
;
5808 Status
= EFI_DEVICE_ERROR
;
5812 Value
= (UINT8
*)AllocateZeroPool (Width
);
5813 if (Value
== NULL
) {
5814 *Progress
= ConfigRequest
;
5815 Status
= EFI_OUT_OF_RESOURCES
;
5819 CopyMem (Value
, (UINT8
*)Block
+ Offset
, Width
);
5821 Length
= Width
* 2 + 1;
5822 ValueStr
= (EFI_STRING
)AllocateZeroPool (Length
* sizeof (CHAR16
));
5823 if (ValueStr
== NULL
) {
5824 *Progress
= ConfigRequest
;
5825 Status
= EFI_OUT_OF_RESOURCES
;
5829 TemString
= ValueStr
;
5830 TemBuffer
= Value
+ Width
- 1;
5831 for (Index
= 0; Index
< Width
; Index
++, TemBuffer
--) {
5832 UnicodeValueToStringS (
5834 Length
* sizeof (CHAR16
) - ((UINTN
)TemString
- (UINTN
)ValueStr
),
5835 PREFIX_ZERO
| RADIX_HEX
,
5839 TemString
+= StrnLenS (TemString
, Length
- ((UINTN
)TemString
- (UINTN
)ValueStr
) / sizeof (CHAR16
));
5846 // Build a ConfigElement
5848 Length
+= StringPtr
- TmpPtr
+ 1 + StrLen (L
"VALUE=");
5849 ConfigElement
= (EFI_STRING
)AllocateZeroPool (Length
* sizeof (CHAR16
));
5850 if (ConfigElement
== NULL
) {
5851 Status
= EFI_OUT_OF_RESOURCES
;
5855 CopyMem (ConfigElement
, TmpPtr
, (StringPtr
- TmpPtr
+ 1) * sizeof (CHAR16
));
5856 if (*StringPtr
== 0) {
5857 *(ConfigElement
+ (StringPtr
- TmpPtr
)) = L
'&';
5860 *(ConfigElement
+ (StringPtr
- TmpPtr
) + 1) = 0;
5861 StrCatS (ConfigElement
, Length
, L
"VALUE=");
5862 StrCatS (ConfigElement
, Length
, ValueStr
);
5864 AppendToMultiString (Config
, ConfigElement
);
5866 FreePool (ConfigElement
);
5867 FreePool (ValueStr
);
5868 ConfigElement
= NULL
;
5872 // If '\0', parsing is finished. Otherwise skip '&' to continue
5874 if (*StringPtr
== 0) {
5878 AppendToMultiString (Config
, L
"&");
5882 if (*StringPtr
!= 0) {
5883 *Progress
= StringPtr
- 1;
5884 Status
= EFI_INVALID_PARAMETER
;
5888 HiiToLower (*Config
);
5889 *Progress
= StringPtr
;
5893 if (*Config
!= NULL
) {
5898 if (ValueStr
!= NULL
) {
5899 FreePool (ValueStr
);
5902 if (Value
!= NULL
) {
5906 if (ConfigElement
!= NULL
) {
5907 FreePool (ConfigElement
);
5914 This helper function is to be called by drivers to map configuration strings
5915 to configurations stored in byte array ("block") formats such as UEFI Variables.
5917 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
5919 @param ConfigResp A null-terminated Unicode string in <ConfigResp>
5921 @param Block A possibly null array of bytes representing the
5922 current block. Only bytes referenced in the
5923 ConfigResp string in the block are modified. If
5924 this parameter is null or if the *BlockSize
5925 parameter is (on input) shorter than required by
5926 the Configuration string, only the BlockSize
5927 parameter is updated and an appropriate status
5928 (see below) is returned.
5929 @param BlockSize The length of the Block in units of UINT8. On
5930 input, this is the size of the Block. On output,
5931 if successful, contains the largest index of the
5932 modified byte in the Block, or the required buffer
5933 size if the Block is not large enough.
5934 @param Progress On return, points to an element of the ConfigResp
5935 string filled in with the offset of the most
5936 recent '&' before the first failing name / value
5937 pair (or the beginning of the string if the
5938 failure is in the first name / value pair) or the
5939 terminating NULL if all was successful.
5941 @retval EFI_SUCCESS The request succeeded. Progress points to the null
5942 terminator at the end of the ConfigResp string.
5943 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress
5944 points to the first character of ConfigResp.
5945 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigResp or
5946 Block parameter would result in this type of
5947 error. Progress points to the first character of
5949 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted name /
5950 value pair. Block is left updated and
5951 Progress points at the '&' preceding the first
5953 @retval EFI_BUFFER_TOO_SMALL Block not large enough. Progress undefined.
5954 BlockSize is updated with the required buffer size.
5955 @retval EFI_NOT_FOUND Target for the specified routing data was not found.
5956 Progress points to the "G" in "GUID" of the errant
5963 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
5964 IN CONST EFI_STRING ConfigResp
,
5965 IN OUT UINT8
*Block
,
5966 IN OUT UINTN
*BlockSize
,
5967 OUT EFI_STRING
*Progress
5970 HII_DATABASE_PRIVATE_DATA
*Private
;
5971 EFI_STRING StringPtr
;
5984 if ((This
== NULL
) || (BlockSize
== NULL
) || (Progress
== NULL
)) {
5985 return EFI_INVALID_PARAMETER
;
5988 *Progress
= ConfigResp
;
5989 if (ConfigResp
== NULL
) {
5990 return EFI_INVALID_PARAMETER
;
5993 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
5994 ASSERT (Private
!= NULL
);
5996 StringPtr
= ConfigResp
;
5997 BufferSize
= *BlockSize
;
6004 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
6005 *Progress
= StringPtr
;
6006 Status
= EFI_INVALID_PARAMETER
;
6010 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"PATH=", StrLen (L
"PATH=")) != 0) {
6014 if (*StringPtr
== 0) {
6015 *Progress
= StringPtr
;
6016 Status
= EFI_INVALID_PARAMETER
;
6020 while (*StringPtr
!= L
'&' && *StringPtr
!= 0) {
6024 if (*StringPtr
== 0) {
6025 *Progress
= StringPtr
;
6026 Status
= EFI_INVALID_PARAMETER
;
6031 // Parse each <ConfigElement> if exists
6032 // Only '&'<BlockConfig> format is supported by this help function.
6033 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE='<Number>
6035 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) == 0) {
6037 StringPtr
+= StrLen (L
"&OFFSET=");
6041 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
6042 if (EFI_ERROR (Status
)) {
6051 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
6053 FreePool (TmpBuffer
);
6055 StringPtr
+= Length
;
6056 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
6058 Status
= EFI_INVALID_PARAMETER
;
6062 StringPtr
+= StrLen (L
"&WIDTH=");
6067 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
6068 if (EFI_ERROR (Status
)) {
6077 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
6079 FreePool (TmpBuffer
);
6081 StringPtr
+= Length
;
6082 if (StrnCmp (StringPtr
, L
"&VALUE=", StrLen (L
"&VALUE=")) != 0) {
6084 Status
= EFI_INVALID_PARAMETER
;
6088 StringPtr
+= StrLen (L
"&VALUE=");
6093 Status
= GetValueOfNumber (StringPtr
, &Value
, &Length
);
6094 if (EFI_ERROR (Status
)) {
6099 StringPtr
+= Length
;
6100 if ((*StringPtr
!= 0) && (*StringPtr
!= L
'&')) {
6102 Status
= EFI_INVALID_PARAMETER
;
6107 // Update the Block with configuration info
6109 if ((Block
!= NULL
) && (Offset
+ Width
<= BufferSize
)) {
6110 CopyMem (Block
+ Offset
, Value
, Width
);
6113 if (Offset
+ Width
> MaxBlockSize
) {
6114 MaxBlockSize
= Offset
+ Width
;
6121 // If '\0', parsing is finished.
6123 if (*StringPtr
== 0) {
6129 // The input string is not ConfigResp format, return error.
6131 if (*StringPtr
!= 0) {
6132 *Progress
= StringPtr
;
6133 Status
= EFI_INVALID_PARAMETER
;
6137 *Progress
= StringPtr
+ StrLen (StringPtr
);
6138 *BlockSize
= MaxBlockSize
- 1;
6140 if (MaxBlockSize
> BufferSize
) {
6141 *BlockSize
= MaxBlockSize
;
6142 if (Block
!= NULL
) {
6143 return EFI_BUFFER_TOO_SMALL
;
6147 if (Block
== NULL
) {
6148 *Progress
= ConfigResp
;
6149 return EFI_INVALID_PARAMETER
;
6156 if (Value
!= NULL
) {
6164 This helper function is to be called by drivers to extract portions of
6165 a larger configuration string.
6167 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
6169 @param Configuration A null-terminated Unicode string in
6170 <MultiConfigAltResp> format.
6171 @param Guid A pointer to the GUID value to search for in the
6172 routing portion of the ConfigResp string when
6173 retrieving the requested data. If Guid is NULL,
6174 then all GUID values will be searched for.
6175 @param Name A pointer to the NAME value to search for in the
6176 routing portion of the ConfigResp string when
6177 retrieving the requested data. If Name is NULL,
6178 then all Name values will be searched for.
6179 @param DevicePath A pointer to the PATH value to search for in the
6180 routing portion of the ConfigResp string when
6181 retrieving the requested data. If DevicePath is
6182 NULL, then all DevicePath values will be searched
6184 @param AltCfgId A pointer to the ALTCFG value to search for in the
6185 routing portion of the ConfigResp string when
6186 retrieving the requested data. If this parameter
6187 is NULL, then the current setting will be
6189 @param AltCfgResp A pointer to a buffer which will be allocated by
6190 the function which contains the retrieved string
6191 as requested. This buffer is only allocated if
6192 the call was successful. It is <ConfigResp> format.
6194 @retval EFI_SUCCESS The request succeeded. The requested data was
6195 extracted and placed in the newly allocated
6197 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate AltCfgResp.
6198 @retval EFI_INVALID_PARAMETER Any parameter is invalid.
6199 @retval EFI_NOT_FOUND Target for the specified routing data was not
6206 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
6207 IN CONST EFI_STRING Configuration
,
6208 IN CONST EFI_GUID
*Guid
,
6209 IN CONST EFI_STRING Name
,
6210 IN CONST EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
6211 IN CONST UINT16
*AltCfgId
,
6212 OUT EFI_STRING
*AltCfgResp
6216 EFI_STRING StringPtr
;
6217 EFI_STRING HdrStart
;
6224 EFI_STRING AltIdStr
;
6241 if ((This
== NULL
) || (Configuration
== NULL
) || (AltCfgResp
== NULL
)) {
6242 return EFI_INVALID_PARAMETER
;
6245 StringPtr
= Configuration
;
6246 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
6247 return EFI_INVALID_PARAMETER
;
6251 // Generate the sub string for later matching.
6253 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*)Guid
, 1, &GuidStr
);
6256 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*)DevicePath
),
6261 if (AltCfgId
!= NULL
) {
6262 GenerateSubStr (L
"ALTCFG=", sizeof (UINT16
), (VOID
*)AltCfgId
, 3, &AltIdStr
);
6266 GenerateSubStr (L
"NAME=", StrLen (Name
) * sizeof (CHAR16
), (VOID
*)Name
, 2, &NameStr
);
6268 GenerateSubStr (L
"NAME=", 0, NULL
, 2, &NameStr
);
6271 while (*StringPtr
!= 0) {
6273 // Try to match the GUID
6276 TmpPtr
= StrStr (StringPtr
, GuidStr
);
6277 if (TmpPtr
== NULL
) {
6278 Status
= EFI_NOT_FOUND
;
6285 // Jump to <NameHdr>
6288 StringPtr
= TmpPtr
+ StrLen (GuidStr
);
6290 StringPtr
= StrStr (TmpPtr
, L
"NAME=");
6291 if (StringPtr
== NULL
) {
6292 Status
= EFI_NOT_FOUND
;
6301 // Try to match the NAME
6303 if (GuidFlag
&& !NameFlag
) {
6304 if (StrnCmp (StringPtr
, NameStr
, StrLen (NameStr
)) != 0) {
6308 // Jump to <PathHdr>
6311 StringPtr
+= StrLen (NameStr
);
6313 StringPtr
= StrStr (StringPtr
, L
"PATH=");
6314 if (StringPtr
== NULL
) {
6315 Status
= EFI_NOT_FOUND
;
6325 // Try to match the DevicePath
6327 if (GuidFlag
&& NameFlag
&& !PathFlag
) {
6328 if (StrnCmp (StringPtr
, PathStr
, StrLen (PathStr
)) != 0) {
6333 // Jump to '&' before <DescHdr> or <ConfigBody>
6335 if (DevicePath
!= NULL
) {
6336 StringPtr
+= StrLen (PathStr
);
6338 StringPtr
= StrStr (StringPtr
, L
"&");
6339 if (StringPtr
== NULL
) {
6340 Status
= EFI_NOT_FOUND
;
6353 // Try to match the AltCfgId
6355 if (GuidFlag
&& NameFlag
&& PathFlag
) {
6356 if (AltCfgId
== NULL
) {
6358 // Return Current Setting when AltCfgId is NULL.
6360 Status
= OutputConfigBody (StringPtr
, &Result
);
6365 // Search the <ConfigAltResp> to get the <AltResp> with AltCfgId.
6367 if (StrnCmp (StringPtr
, AltIdStr
, StrLen (AltIdStr
)) != 0) {
6373 // Skip AltIdStr and &
6375 StringPtr
= StringPtr
+ StrLen (AltIdStr
);
6376 Status
= OutputConfigBody (StringPtr
, &Result
);
6382 Status
= EFI_NOT_FOUND
;
6386 if (!EFI_ERROR (Status
) && (Result
!= NULL
)) {
6388 // Copy the <ConfigHdr> and <ConfigBody>
6390 Length
= HdrEnd
- HdrStart
+ StrLen (Result
) + 1;
6391 *AltCfgResp
= AllocateZeroPool (Length
* sizeof (CHAR16
));
6392 if (*AltCfgResp
== NULL
) {
6393 Status
= EFI_OUT_OF_RESOURCES
;
6395 StrnCpyS (*AltCfgResp
, Length
, HdrStart
, HdrEnd
- HdrStart
);
6396 StrCatS (*AltCfgResp
, Length
, Result
);
6397 Status
= EFI_SUCCESS
;
6401 if (GuidStr
!= NULL
) {
6405 if (NameStr
!= NULL
) {
6409 if (PathStr
!= NULL
) {
6413 if (AltIdStr
!= NULL
) {
6414 FreePool (AltIdStr
);
6417 if (Result
!= NULL
) {