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
10 #include "HiiDatabase.h"
11 extern HII_DATABASE_PRIVATE_DATA mPrivate
;
14 Calculate the number of Unicode characters of the incoming Configuration string,
15 not including NULL terminator.
17 This is a internal function.
19 @param String String in <MultiConfigRequest> or
20 <MultiConfigResp> format.
22 @return The number of Unicode characters.
26 CalculateConfigStringLen (
33 // "GUID=" should be the first element of incoming string.
35 ASSERT (String
!= NULL
);
36 ASSERT (StrnCmp (String
, L
"GUID=", StrLen (L
"GUID=")) == 0);
39 // The beginning of next <ConfigRequest>/<ConfigResp> should be "&GUID=".
40 // Will meet '\0' if there is only one <ConfigRequest>/<ConfigResp>.
42 TmpPtr
= StrStr (String
, L
"&GUID=");
44 return StrLen (String
);
47 return (TmpPtr
- String
);
52 Convert the hex UNICODE %02x encoding of a UEFI device path to binary
53 from <PathHdr> of <ConfigHdr>.
55 This is a internal function.
57 @param String UEFI configuration string
58 @param DevicePathData Binary of a UEFI device path.
60 @retval EFI_NOT_FOUND The device path is not invalid.
61 @retval EFI_INVALID_PARAMETER Any incoming parameter is invalid.
62 @retval EFI_OUT_OF_RESOURCES Lake of resources to store necessary structures.
63 @retval EFI_SUCCESS The device path is retrieved and translated to
70 OUT UINT8
**DevicePathData
75 UINT8
*DevicePathBuffer
;
79 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
82 if (String
== NULL
|| DevicePathData
== NULL
) {
83 return EFI_INVALID_PARAMETER
;
87 // Find the 'PATH=' of <PathHdr> and skip it.
89 for (; (*String
!= 0 && StrnCmp (String
, L
"PATH=", StrLen (L
"PATH=")) != 0); String
++);
91 return EFI_INVALID_PARAMETER
;
94 // Check whether path data does exist.
96 String
+= StrLen (L
"PATH=");
98 return EFI_INVALID_PARAMETER
;
103 // The content between 'PATH=' of <ConfigHdr> and '&' of next element
104 // or '\0' (end of configuration string) is the UNICODE %02x bytes encoding
105 // of UEFI device path.
107 for (Length
= 0; *String
!= 0 && *String
!= L
'&'; String
++, Length
++);
109 // Check DevicePath Length
111 if (((Length
+ 1) / 2) < sizeof (EFI_DEVICE_PATH_PROTOCOL
)) {
112 return EFI_NOT_FOUND
;
116 // The data in <PathHdr> is encoded as hex UNICODE %02x bytes in the same order
117 // as the device path resides in RAM memory.
118 // Translate the data into binary.
120 DevicePathBuffer
= (UINT8
*) AllocateZeroPool ((Length
+ 1) / 2);
121 if (DevicePathBuffer
== NULL
) {
122 return EFI_OUT_OF_RESOURCES
;
126 // Convert DevicePath
128 ZeroMem (TemStr
, sizeof (TemStr
));
129 for (Index
= 0; Index
< Length
; Index
++) {
130 TemStr
[0] = PathHdr
[Index
];
131 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
132 if ((Index
& 1) == 0) {
133 DevicePathBuffer
[Index
/2] = DigitUint8
;
135 DevicePathBuffer
[Index
/2] = (UINT8
) ((DevicePathBuffer
[Index
/2] << 4) + DigitUint8
);
140 // Validate DevicePath
142 DevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) DevicePathBuffer
;
143 while (!IsDevicePathEnd (DevicePath
)) {
144 if ((DevicePath
->Type
== 0) || (DevicePath
->SubType
== 0) || (DevicePathNodeLength (DevicePath
) < sizeof (EFI_DEVICE_PATH_PROTOCOL
))) {
146 // Invalid device path
148 FreePool (DevicePathBuffer
);
149 return EFI_NOT_FOUND
;
151 DevicePath
= NextDevicePathNode (DevicePath
);
155 // return the device path
157 *DevicePathData
= DevicePathBuffer
;
162 Converts the unicode character of the string from uppercase to lowercase.
163 This is a internal function.
165 @param ConfigString String to be converted
171 IN EFI_STRING ConfigString
177 ASSERT (ConfigString
!= NULL
);
180 // Convert all hex digits in range [A-F] in the configuration header to [a-f]
182 for (String
= ConfigString
, Lower
= FALSE
; *String
!= L
'\0'; String
++) {
183 if (*String
== L
'=') {
185 } else if (*String
== L
'&') {
187 } else if (Lower
&& *String
>= L
'A' && *String
<= L
'F') {
188 *String
= (CHAR16
) (*String
- L
'A' + L
'a');
196 Generate a sub string then output it.
198 This is a internal function.
200 @param String A constant string which is the prefix of the to be
201 generated string, e.g. GUID=
203 @param BufferLen The length of the Buffer in bytes.
205 @param Buffer Points to a buffer which will be converted to be the
206 content of the generated string.
208 @param Flag If 1, the buffer contains data for the value of GUID or PATH stored in
209 UINT8 *; if 2, the buffer contains unicode string for the value of NAME;
210 if 3, the buffer contains other data.
212 @param SubStr Points to the output string. It's caller's
213 responsibility to free this buffer.
219 IN CONST EFI_STRING String
,
223 OUT EFI_STRING
*SubStr
228 EFI_STRING StringHeader
;
234 ASSERT (String
!= NULL
&& SubStr
!= NULL
);
236 if (Buffer
== NULL
) {
237 *SubStr
= AllocateCopyPool (StrSize (String
), String
);
238 ASSERT (*SubStr
!= NULL
);
243 // Header + Data + '&' + '\0'
245 Length
= StrLen (String
) + BufferLen
* 2 + 1 + 1;
246 Str
= AllocateZeroPool (Length
* sizeof (CHAR16
));
247 ASSERT (Str
!= NULL
);
249 StrCpyS (Str
, Length
, String
);
251 StringHeader
= Str
+ StrLen (String
);
252 TemString
= (CHAR16
*) StringHeader
;
257 // Convert Buffer to Hex String in reverse order
259 TemBuffer
= ((UINT8
*) Buffer
);
260 for (Index
= 0; Index
< BufferLen
; Index
++, TemBuffer
++) {
261 UnicodeValueToStringS (
263 sizeof (CHAR16
) * (Length
- StrnLenS (Str
, Length
)),
264 PREFIX_ZERO
| RADIX_HEX
,
268 TemString
+= StrnLenS (TemString
, Length
- StrnLenS (Str
, Length
));
273 // Check buffer is enough
275 TemName
= (CHAR16
*) Buffer
;
276 ASSERT ((BufferLen
* 2 + 1) >= (StrLen (TemName
) * 4 + 1));
278 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
280 for (; *TemName
!= L
'\0'; TemName
++) {
281 UnicodeValueToStringS (
283 sizeof (CHAR16
) * (Length
- StrnLenS (Str
, Length
)),
284 PREFIX_ZERO
| RADIX_HEX
,
288 TemString
+= StrnLenS (TemString
, Length
- StrnLenS (Str
, Length
));
293 // Convert Buffer to Hex String
295 TemBuffer
= ((UINT8
*) Buffer
) + BufferLen
- 1;
296 for (Index
= 0; Index
< BufferLen
; Index
++, TemBuffer
--) {
297 UnicodeValueToStringS (
299 sizeof (CHAR16
) * (Length
- StrnLenS (Str
, Length
)),
300 PREFIX_ZERO
| RADIX_HEX
,
304 TemString
+= StrnLenS (TemString
, Length
- StrnLenS (Str
, Length
));
312 // Convert the uppercase to lowercase since <HexAf> is defined in lowercase format.
314 StrCatS (Str
, Length
, L
"&");
322 Retrieve the <ConfigBody> from String then output it.
324 This is a internal function.
326 @param String A sub string of a configuration string in
327 <MultiConfigAltResp> format.
328 @param ConfigBody Points to the output string. It's caller's
329 responsibility to free this buffer.
331 @retval EFI_INVALID_PARAMETER There is no form package in current hii database.
332 @retval EFI_OUT_OF_RESOURCES Not enough memory to finish this operation.
333 @retval EFI_SUCCESS All existing storage is exported.
338 IN EFI_STRING String
,
339 OUT EFI_STRING
*ConfigBody
346 if (String
== NULL
|| ConfigBody
== NULL
) {
347 return EFI_INVALID_PARAMETER
;
351 // The setting information should start OFFSET, not ALTCFG.
353 if (StrnCmp (String
, L
"&ALTCFG=", StrLen (L
"&ALTCFG=")) == 0) {
354 return EFI_INVALID_PARAMETER
;
357 TmpPtr
= StrStr (String
, L
"GUID=");
358 if (TmpPtr
== NULL
) {
360 // It is the last <ConfigResp> of the incoming configuration string.
362 Result
= AllocateCopyPool (StrSize (String
), String
);
363 if (Result
== NULL
) {
364 return EFI_OUT_OF_RESOURCES
;
366 *ConfigBody
= Result
;
371 Length
= TmpPtr
- String
;
373 return EFI_NOT_FOUND
;
375 Result
= AllocateCopyPool (Length
* sizeof (CHAR16
), String
);
376 if (Result
== NULL
) {
377 return EFI_OUT_OF_RESOURCES
;
380 *(Result
+ Length
- 1) = 0;
381 *ConfigBody
= Result
;
386 Append a string to a multi-string format.
388 This is a internal function.
390 @param MultiString String in <MultiConfigRequest>,
391 <MultiConfigAltResp>, or <MultiConfigResp>. On
392 input, the buffer length of this string is
393 MAX_STRING_LENGTH. On output, the buffer length
395 @param AppendString NULL-terminated Unicode string.
397 @retval EFI_INVALID_PARAMETER Any incoming parameter is invalid.
398 @retval EFI_SUCCESS AppendString is append to the end of MultiString
402 AppendToMultiString (
403 IN OUT EFI_STRING
*MultiString
,
404 IN EFI_STRING AppendString
407 UINTN AppendStringSize
;
408 UINTN MultiStringSize
;
411 if (MultiString
== NULL
|| *MultiString
== NULL
|| AppendString
== NULL
) {
412 return EFI_INVALID_PARAMETER
;
415 AppendStringSize
= StrSize (AppendString
);
416 MultiStringSize
= StrSize (*MultiString
);
417 MaxLen
= MAX_STRING_LENGTH
/ sizeof (CHAR16
);
420 // Enlarge the buffer each time when length exceeds MAX_STRING_LENGTH.
422 if (MultiStringSize
+ AppendStringSize
> MAX_STRING_LENGTH
||
423 MultiStringSize
> MAX_STRING_LENGTH
) {
424 *MultiString
= (EFI_STRING
) ReallocatePool (
426 MultiStringSize
+ AppendStringSize
,
427 (VOID
*) (*MultiString
)
429 MaxLen
= (MultiStringSize
+ AppendStringSize
) / sizeof (CHAR16
);
430 ASSERT (*MultiString
!= NULL
);
433 // Append the incoming string
435 StrCatS (*MultiString
, MaxLen
, AppendString
);
442 Get the value of <Number> in <BlockConfig> format, i.e. the value of OFFSET
444 <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>
446 This is a internal function.
448 @param StringPtr String in <BlockConfig> format and points to the
449 first character of <Number>.
450 @param Number The output value. Caller takes the responsibility
452 @param Len Length of the <Number>, in characters.
454 @retval EFI_OUT_OF_RESOURCES Insufficient resources to store necessary
456 @retval EFI_SUCCESS Value of <Number> is outputted in Number
462 IN EFI_STRING StringPtr
,
476 if (StringPtr
== NULL
|| *StringPtr
== L
'\0' || Number
== NULL
|| Len
== NULL
) {
477 return EFI_INVALID_PARAMETER
;
483 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
486 *Len
= StringPtr
- TmpPtr
;
489 Str
= (EFI_STRING
) AllocateZeroPool (Length
* sizeof (CHAR16
));
491 Status
= EFI_OUT_OF_RESOURCES
;
494 CopyMem (Str
, TmpPtr
, *Len
* sizeof (CHAR16
));
495 *(Str
+ *Len
) = L
'\0';
497 Length
= (Length
+ 1) / 2;
498 Buf
= (UINT8
*) AllocateZeroPool (Length
);
500 Status
= EFI_OUT_OF_RESOURCES
;
505 ZeroMem (TemStr
, sizeof (TemStr
));
506 for (Index
= 0; Index
< Length
; Index
++) {
507 TemStr
[0] = Str
[Length
- Index
- 1];
508 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
509 if ((Index
& 1) == 0) {
510 Buf
[Index
/2] = DigitUint8
;
512 Buf
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Buf
[Index
/2]);
517 Status
= EFI_SUCCESS
;
528 To find the BlockName in the string with same value.
530 @param String Pointer to a Null-terminated Unicode string.
531 @param BlockName Pointer to a Null-terminated Unicode string to search for.
532 @param Buffer Pointer to the value correspond to the BlockName.
533 @param Found The Block whether has been found.
534 @param BufferLen The length of the buffer.
536 @retval EFI_OUT_OF_RESOURCES Insufficient resources to store necessary structures.
537 @retval EFI_SUCCESS The function finishes successfully.
541 FindSameBlockElement(
542 IN EFI_STRING String
,
543 IN EFI_STRING BlockName
,
556 BlockPtr
= StrStr (String
, BlockName
);
558 while (BlockPtr
!= NULL
) {
559 BlockPtr
+= StrLen (BlockName
);
560 Status
= GetValueOfNumber (BlockPtr
, &TempBuffer
, &Length
);
561 if (EFI_ERROR (Status
)) {
564 ASSERT (TempBuffer
!= NULL
);
565 if ((BufferLen
== Length
) && (0 == CompareMem (Buffer
, TempBuffer
, Length
))) {
567 FreePool (TempBuffer
);
571 FreePool (TempBuffer
);
573 BlockPtr
= StrStr (BlockPtr
+ 1, BlockName
);
580 Compare the <AltResp> in ConfigAltResp and DefaultAltCfgResp, if the <AltResp>
581 in DefaultAltCfgResp but not in ConfigAltResp,add it to the ConfigAltResp.
583 @param DefaultAltCfgResp Pointer to a null-terminated Unicode string in
584 <MultiConfigAltResp> format. The default value
585 string may contain more than one ConfigAltResp
586 string for the different varstore buffer.
587 @param ConfigAltResp Pointer to a null-terminated Unicode string in
588 <ConfigAltResp> format.
589 @param AltConfigHdr Pointer to a Unicode string in <AltConfigHdr> format.
590 @param ConfigAltRespChanged Whether the ConfigAltResp has been changed.
592 @retval EFI_OUT_OF_RESOURCES Insufficient resources to store necessary structures.
593 @retval EFI_SUCCESS The function finishes successfully.
597 CompareBlockElementDefault (
598 IN EFI_STRING DefaultAltCfgResp
,
599 IN OUT EFI_STRING
*ConfigAltResp
,
600 IN EFI_STRING AltConfigHdr
,
601 IN OUT BOOLEAN
*ConfigAltRespChanged
606 EFI_STRING BlockPtrStart
;
607 EFI_STRING StringPtr
;
608 EFI_STRING AppendString
;
609 EFI_STRING AltConfigHdrPtr
;
619 // Make BlockPtr point to the first <BlockConfig> with AltConfigHdr in DefaultAltCfgResp.
621 AltConfigHdrPtr
= StrStr (DefaultAltCfgResp
, AltConfigHdr
);
622 ASSERT (AltConfigHdrPtr
!= NULL
);
623 BlockPtr
= StrStr (AltConfigHdrPtr
, L
"&OFFSET=");
625 // Make StringPtr point to the AltConfigHdr in ConfigAltResp.
627 StringPtr
= StrStr (*ConfigAltResp
, AltConfigHdr
);
628 ASSERT (StringPtr
!= NULL
);
630 while (BlockPtr
!= NULL
) {
632 // Find the "&OFFSET=<Number>" block and get the value of the Number with AltConfigHdr in DefaultAltCfgResp.
634 BlockPtrStart
= BlockPtr
;
635 BlockPtr
+= StrLen (L
"&OFFSET=");
636 Status
= GetValueOfNumber (BlockPtr
, &TempBuffer
, &OffsetLength
);
637 if (EFI_ERROR (Status
)) {
638 Status
= EFI_OUT_OF_RESOURCES
;
642 // To find the same "&OFFSET=<Number>" block in ConfigAltResp.
644 Status
= FindSameBlockElement (StringPtr
, L
"&OFFSET=", TempBuffer
, &FoundOffset
, OffsetLength
);
645 if (TempBuffer
!= NULL
) {
646 FreePool (TempBuffer
);
649 if (EFI_ERROR (Status
)) {
650 Status
= EFI_OUT_OF_RESOURCES
;
655 // Don't find the same "&OFFSET=<Number>" block in ConfigAltResp.
656 // Calculate the size of <BlockConfig>.
657 // <BlockConfig>::='OFFSET='<Number>'&WIDTH='<Number>'&VALUE='<Number>.
659 BlockPtr
= StrStr (BlockPtr
+ 1, L
"&OFFSET=");
660 if (BlockPtr
!= NULL
) {
661 AppendSize
= (BlockPtr
- BlockPtrStart
) * sizeof (CHAR16
);
663 AppendSize
= StrSize (BlockPtrStart
);
666 // Copy the <BlockConfig> to AppendString.
668 if (AppendString
== NULL
) {
669 AppendString
= (EFI_STRING
) AllocateZeroPool (AppendSize
+ sizeof (CHAR16
));
670 StrnCatS (AppendString
, AppendSize
/ sizeof (CHAR16
) + 1, BlockPtrStart
, AppendSize
/ sizeof (CHAR16
));
672 TotalSize
= StrSize (AppendString
) + AppendSize
+ sizeof (CHAR16
);
673 AppendString
= (EFI_STRING
) ReallocatePool (
674 StrSize (AppendString
),
678 if (AppendString
== NULL
) {
679 Status
= EFI_OUT_OF_RESOURCES
;
682 StrnCatS (AppendString
, TotalSize
/ sizeof (CHAR16
), BlockPtrStart
, AppendSize
/ sizeof (CHAR16
));
686 // To find next "&OFFSET=<Number>" block with AltConfigHdr in DefaultAltCfgResp.
688 BlockPtr
= StrStr (BlockPtr
+ 1, L
"&OFFSET=");
692 if (AppendString
!= NULL
) {
694 // Reallocate ConfigAltResp to copy the AppendString.
696 TotalSize
= StrSize (*ConfigAltResp
) + StrSize (AppendString
) + sizeof (CHAR16
);
697 *ConfigAltResp
= (EFI_STRING
) ReallocatePool (
698 StrSize (*ConfigAltResp
),
702 if (*ConfigAltResp
== NULL
) {
703 Status
= EFI_OUT_OF_RESOURCES
;
706 StrCatS (*ConfigAltResp
, TotalSize
/ sizeof (CHAR16
), AppendString
);
707 *ConfigAltRespChanged
= TRUE
;
710 Status
= EFI_SUCCESS
;
713 if (AppendString
!= NULL
) {
714 FreePool (AppendString
);
721 Compare the <AltResp> in ConfigAltResp and DefaultAltCfgResp, if the <AltResp>
722 in DefaultAltCfgResp but not in ConfigAltResp,add it to the ConfigAltResp.
724 @param DefaultAltCfgResp Pointer to a null-terminated Unicode string in
725 <MultiConfigAltResp> format. The default value
726 string may contain more than one ConfigAltResp
727 string for the different varstore buffer.
728 @param ConfigAltResp Pointer to a null-terminated Unicode string in
729 <ConfigAltResp> format.
730 @param AltConfigHdr Pointer to a Unicode string in <AltConfigHdr> format.
731 @param ConfigAltRespChanged Whether the ConfigAltResp has been changed.
733 @retval EFI_OUT_OF_RESOURCES Insufficient resources to store necessary structures.
734 @retval EFI_SUCCESS The function finishes successfully.
738 CompareNameElementDefault (
739 IN EFI_STRING DefaultAltCfgResp
,
740 IN OUT EFI_STRING
*ConfigAltResp
,
741 IN EFI_STRING AltConfigHdr
,
742 IN OUT BOOLEAN
*ConfigAltRespChanged
746 EFI_STRING NvConfigPtr
;
747 EFI_STRING NvConfigStart
;
748 EFI_STRING NvConfigValuePtr
;
749 EFI_STRING StringPtr
;
750 EFI_STRING NvConfigExist
;
751 EFI_STRING AppendString
;
757 NvConfigExist
= NULL
;
759 // Make NvConfigPtr point to the first <NvConfig> with AltConfigHdr in DefaultAltCfgResp.
761 NvConfigPtr
= StrStr (DefaultAltCfgResp
, AltConfigHdr
);
762 ASSERT (NvConfigPtr
!= NULL
);
763 NvConfigPtr
= StrStr (NvConfigPtr
+ StrLen(AltConfigHdr
),L
"&");
765 // Make StringPtr point to the first <NvConfig> with AltConfigHdr in ConfigAltResp.
767 StringPtr
= StrStr (*ConfigAltResp
, AltConfigHdr
);
768 ASSERT (StringPtr
!= NULL
);
769 StringPtr
= StrStr (StringPtr
+ StrLen (AltConfigHdr
), L
"&");
770 ASSERT (StringPtr
!= NULL
);
772 while (NvConfigPtr
!= NULL
) {
774 // <NvConfig> ::= <Label>'='<String> | <Label>'='<Number>.
775 // Get the <Label> with AltConfigHdr in DefaultAltCfgResp.
777 NvConfigStart
= NvConfigPtr
;
778 NvConfigValuePtr
= StrStr (NvConfigPtr
+ 1, L
"=");
779 ASSERT (NvConfigValuePtr
!= NULL
);
780 TempChar
= *NvConfigValuePtr
;
781 *NvConfigValuePtr
= L
'\0';
783 // Get the <Label> with AltConfigHdr in ConfigAltResp.
785 NvConfigExist
= StrStr (StringPtr
, NvConfigPtr
);
786 if (NvConfigExist
== NULL
) {
788 // Don't find same <Label> in ConfigAltResp.
789 // Calculate the size of <NvConfig>.
791 *NvConfigValuePtr
= TempChar
;
792 NvConfigPtr
= StrStr (NvConfigPtr
+ 1, L
"&");
793 if (NvConfigPtr
!= NULL
) {
794 AppendSize
= (NvConfigPtr
- NvConfigStart
) * sizeof (CHAR16
);
796 AppendSize
= StrSize (NvConfigStart
);
799 // Copy the <NvConfig> to AppendString.
801 if (AppendString
== NULL
) {
802 AppendString
= (EFI_STRING
) AllocateZeroPool (AppendSize
+ sizeof (CHAR16
));
803 StrnCatS (AppendString
, AppendSize
/ sizeof (CHAR16
) + 1, NvConfigStart
, AppendSize
/ sizeof (CHAR16
));
805 TotalSize
= StrSize (AppendString
) + AppendSize
+ sizeof (CHAR16
);
806 AppendString
= (EFI_STRING
) ReallocatePool (
807 StrSize (AppendString
),
811 if (AppendString
== NULL
) {
812 Status
= EFI_OUT_OF_RESOURCES
;
815 StrnCatS (AppendString
, TotalSize
/ sizeof (CHAR16
), NvConfigStart
, AppendSize
/ sizeof (CHAR16
));
819 // To find next <Label> in DefaultAltCfgResp.
821 *NvConfigValuePtr
= TempChar
;
822 NvConfigPtr
= StrStr (NvConfigPtr
+ 1, L
"&");
825 if (AppendString
!= NULL
) {
827 // Reallocate ConfigAltResp to copy the AppendString.
829 TotalSize
= StrSize (*ConfigAltResp
) + StrSize (AppendString
) + sizeof (CHAR16
);
830 *ConfigAltResp
= (EFI_STRING
) ReallocatePool (
831 StrSize (*ConfigAltResp
),
832 StrSize (*ConfigAltResp
) + StrSize (AppendString
) + sizeof (CHAR16
),
835 if (*ConfigAltResp
== NULL
) {
836 Status
= EFI_OUT_OF_RESOURCES
;
839 StrCatS (*ConfigAltResp
, TotalSize
/ sizeof (CHAR16
), AppendString
);
840 *ConfigAltRespChanged
= TRUE
;
842 Status
= EFI_SUCCESS
;
845 if (AppendString
!= NULL
) {
846 FreePool (AppendString
);
852 Compare the <AltResp> in AltCfgResp and DefaultAltCfgResp, if the <AltResp>
853 in DefaultAltCfgResp but not in AltCfgResp,add it to the AltCfgResp.
855 @param AltCfgResp Pointer to a null-terminated Unicode string in
856 <ConfigAltResp> format.
857 @param DefaultAltCfgResp Pointer to a null-terminated Unicode string in
858 <MultiConfigAltResp> format. The default value
859 string may contain more than one ConfigAltResp
860 string for the different varstore buffer.
861 @param AltConfigHdr Pointer to a Unicode string in <AltConfigHdr> format.
863 @retval EFI_OUT_OF_RESOURCES Insufficient resources to store necessary
865 @retval EFI_SUCCESS The function finishes successfully.
869 CompareAndMergeDefaultString (
870 IN OUT EFI_STRING
*AltCfgResp
,
871 IN EFI_STRING DefaultAltCfgResp
,
872 IN EFI_STRING AltConfigHdr
876 EFI_STRING AltCfgRespBackup
;
877 EFI_STRING AltConfigHdrPtr
;
878 EFI_STRING AltConfigHdrPtrNext
;
879 EFI_STRING ConfigAltResp
;
880 EFI_STRING StringPtr
;
881 EFI_STRING StringPtrNext
;
883 UINTN ReallocateSize
;
886 BOOLEAN ConfigAltRespChanged
;
888 Status
= EFI_OUT_OF_RESOURCES
;
890 AltConfigHdrPtrNext
= NULL
;
891 StringPtrNext
= NULL
;
892 ConfigAltResp
= NULL
;
893 AltCfgRespBackup
= NULL
;
896 ConfigAltRespChanged
= FALSE
;
899 //To find the <AltResp> with AltConfigHdr in DefaultAltCfgResp, ignore other <AltResp> which follow it.
901 AltConfigHdrPtr
= StrStr (DefaultAltCfgResp
, AltConfigHdr
);
902 ASSERT (AltConfigHdrPtr
!= NULL
);
903 AltConfigHdrPtrNext
= StrStr (AltConfigHdrPtr
+ 1, L
"&GUID");
904 if (AltConfigHdrPtrNext
!= NULL
) {
905 TempChar
= *AltConfigHdrPtrNext
;
906 *AltConfigHdrPtrNext
= L
'\0';
909 // To find the <AltResp> with AltConfigHdr in AltCfgResp, ignore other <AltResp> which follow it.
911 StringPtr
= StrStr (*AltCfgResp
, AltConfigHdr
);
912 ASSERT (StringPtr
!= NULL
);
913 StringPtrNext
= StrStr (StringPtr
+ 1, L
"&GUID");
914 if (StringPtrNext
!= NULL
) {
915 TempCharA
= *StringPtrNext
;
916 *StringPtrNext
= L
'\0';
919 // Copy the content of <ConfigAltResp> which contain current AltConfigHdr in AltCfgResp.
921 ConfigAltResp
= AllocateCopyPool (StrSize (*AltCfgResp
), *AltCfgResp
);
922 if (ConfigAltResp
== NULL
) {
926 // To find the <ConfigBody> with AltConfigHdr in DefaultAltCfgResp.
928 BlockPtr
= StrStr (AltConfigHdrPtr
, L
"&OFFSET=");
929 if (BlockPtr
!= NULL
) {
931 // <BlockConfig>::='OFFSET='<Number>'&WIDTH='<Number>'&VALUE='<Number> style.
932 // Call function CompareBlockElementDefault to compare the <BlockConfig> in DefaultAltCfgResp and ConfigAltResp.
933 // The ConfigAltResp which may contain the new <BlockConfig> get from DefaultAltCfgResp.
935 Status
= CompareBlockElementDefault (DefaultAltCfgResp
, &ConfigAltResp
, AltConfigHdr
, &ConfigAltRespChanged
);
936 if (EFI_ERROR(Status
)) {
941 // <NvConfig> ::= <Label>'='<String> | <Label>'='<Number> style.
942 // Call function CompareNameElementDefault to compare the <NvConfig> in DefaultAltCfgResp and ConfigAltResp.
943 // The ConfigAltResp which may contain the new <NvConfig> get from DefaultAltCfgResp.
945 Status
= CompareNameElementDefault (DefaultAltCfgResp
, &ConfigAltResp
, AltConfigHdr
, &ConfigAltRespChanged
);
946 if (EFI_ERROR(Status
)) {
951 // Restore the AltCfgResp.
953 if (StringPtrNext
!= NULL
) {
954 *StringPtrNext
= TempCharA
;
958 // If the ConfigAltResp has no change,no need to update the content in AltCfgResp.
960 if (!ConfigAltRespChanged
) {
961 Status
= EFI_SUCCESS
;
965 // ConfigAltResp has been changed, need to update the content in AltCfgResp.
967 if (StringPtrNext
!= NULL
) {
968 ReallocateSize
= StrSize (ConfigAltResp
) + StrSize (StringPtrNext
) + sizeof (CHAR16
);
970 ReallocateSize
= StrSize (ConfigAltResp
) + sizeof (CHAR16
);
973 AltCfgRespBackup
= (EFI_STRING
) AllocateZeroPool (ReallocateSize
);
974 if (AltCfgRespBackup
== NULL
) {
978 StrCatS (AltCfgRespBackup
, ReallocateSize
/ sizeof (CHAR16
), ConfigAltResp
);
979 if (StringPtrNext
!= NULL
) {
980 StrCatS (AltCfgRespBackup
, ReallocateSize
/ sizeof (CHAR16
), StringPtrNext
);
983 FreePool (*AltCfgResp
);
984 *AltCfgResp
= AltCfgRespBackup
;
986 Status
= EFI_SUCCESS
;
989 if (ConfigAltResp
!= NULL
) {
990 FreePool(ConfigAltResp
);
993 // Restore the DefaultAltCfgResp.
995 if ( AltConfigHdrPtrNext
!= NULL
) {
996 *AltConfigHdrPtrNext
= TempChar
;
997 AltConfigHdrPtrNext
= NULL
;
1004 This function merges DefaultAltCfgResp string into AltCfgResp string for
1005 the missing AltCfgId in AltCfgResq.
1007 @param AltCfgResp Pointer to a null-terminated Unicode string in
1008 <ConfigAltResp> format. The default value string
1009 will be merged into it.
1010 @param DefaultAltCfgResp Pointer to a null-terminated Unicode string in
1011 <MultiConfigAltResp> format. The default value
1012 string may contain more than one ConfigAltResp
1013 string for the different varstore buffer.
1015 @retval EFI_SUCCESS The merged string returns.
1016 @retval EFI_INVALID_PARAMETER *AltCfgResp is to NULL.
1020 MergeDefaultString (
1021 IN OUT EFI_STRING
*AltCfgResp
,
1022 IN EFI_STRING DefaultAltCfgResp
1025 EFI_STRING StringPtrDefault
;
1026 EFI_STRING StringPtrEnd
;
1028 EFI_STRING StringPtr
;
1029 EFI_STRING AltConfigHdr
;
1031 UINTN SizeAltCfgResp
;
1035 if (*AltCfgResp
== NULL
) {
1036 return EFI_INVALID_PARAMETER
;
1040 // Get the request ConfigHdr
1043 StringPtr
= *AltCfgResp
;
1046 // Find <ConfigHdr> GUID=...&NAME=...&PATH=...
1048 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
1049 return EFI_INVALID_PARAMETER
;
1051 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&NAME=", StrLen (L
"&NAME=")) != 0) {
1054 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&PATH=", StrLen (L
"&PATH=")) != 0) {
1057 if (*StringPtr
== L
'\0') {
1058 return EFI_INVALID_PARAMETER
;
1060 StringPtr
+= StrLen (L
"&PATH=");
1061 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
1064 HeaderLength
= StringPtr
- *AltCfgResp
;
1067 // Construct AltConfigHdr string "&<ConfigHdr>&ALTCFG=XXXX\0"
1068 // |1| StrLen (ConfigHdr) | 8 | 4 | 1 |
1070 MaxLen
= 1 + HeaderLength
+ 8 + 4 + 1;
1071 AltConfigHdr
= AllocateZeroPool (MaxLen
* sizeof (CHAR16
));
1072 if (AltConfigHdr
== NULL
) {
1073 return EFI_OUT_OF_RESOURCES
;
1075 StrCpyS (AltConfigHdr
, MaxLen
, L
"&");
1076 StrnCatS (AltConfigHdr
, MaxLen
, *AltCfgResp
, HeaderLength
);
1077 StrCatS (AltConfigHdr
, MaxLen
, L
"&ALTCFG=");
1078 HeaderLength
= StrLen (AltConfigHdr
);
1080 StringPtrDefault
= StrStr (DefaultAltCfgResp
, AltConfigHdr
);
1081 while (StringPtrDefault
!= NULL
) {
1085 StrnCatS (AltConfigHdr
, MaxLen
, StringPtrDefault
+ HeaderLength
, 4);
1086 StringPtr
= StrStr (*AltCfgResp
, AltConfigHdr
);
1089 // Append the found default value string to the input AltCfgResp
1091 if (StringPtr
== NULL
) {
1092 StringPtrEnd
= StrStr (StringPtrDefault
+ 1, L
"&GUID");
1093 SizeAltCfgResp
= StrSize (*AltCfgResp
);
1094 if (StringPtrEnd
== NULL
) {
1096 // No more default string is found.
1098 TotalSize
= SizeAltCfgResp
+ StrSize (StringPtrDefault
);
1099 *AltCfgResp
= (EFI_STRING
) ReallocatePool (
1102 (VOID
*) (*AltCfgResp
)
1104 if (*AltCfgResp
== NULL
) {
1105 FreePool (AltConfigHdr
);
1106 return EFI_OUT_OF_RESOURCES
;
1108 StrCatS (*AltCfgResp
, TotalSize
/ sizeof (CHAR16
), StringPtrDefault
);
1111 TempChar
= *StringPtrEnd
;
1112 *StringPtrEnd
= L
'\0';
1113 TotalSize
= SizeAltCfgResp
+ StrSize (StringPtrDefault
);
1114 *AltCfgResp
= (EFI_STRING
) ReallocatePool (
1117 (VOID
*) (*AltCfgResp
)
1119 if (*AltCfgResp
== NULL
) {
1120 FreePool (AltConfigHdr
);
1121 return EFI_OUT_OF_RESOURCES
;
1123 StrCatS (*AltCfgResp
, TotalSize
/ sizeof (CHAR16
), StringPtrDefault
);
1124 *StringPtrEnd
= TempChar
;
1128 // The AltCfgResp contains <AltCfgResp>.
1129 // If the <ConfigElement> in <AltCfgResp> in the DefaultAltCfgResp but not in the
1130 // related <AltCfgResp> in AltCfgResp, merge it to AltCfgResp. else no need to merge.
1132 CompareAndMergeDefaultString (AltCfgResp
, DefaultAltCfgResp
, AltConfigHdr
);
1136 // Find next AltCfg String
1138 *(AltConfigHdr
+ HeaderLength
) = L
'\0';
1139 StringPtrDefault
= StrStr (StringPtrDefault
+ 1, AltConfigHdr
);
1142 FreePool (AltConfigHdr
);
1147 This function inserts new DefaultValueData into the BlockData DefaultValue array.
1149 @param BlockData The BlockData is updated to add new default value.
1150 @param DefaultValueData The DefaultValue is added.
1154 InsertDefaultValue (
1155 IN IFR_BLOCK_DATA
*BlockData
,
1156 IN IFR_DEFAULT_DATA
*DefaultValueData
1160 IFR_DEFAULT_DATA
*DefaultValueArray
;
1161 LIST_ENTRY
*DefaultLink
;
1163 DefaultLink
= &BlockData
->DefaultValueEntry
;
1165 for (Link
= DefaultLink
->ForwardLink
; Link
!= DefaultLink
; Link
= Link
->ForwardLink
) {
1166 DefaultValueArray
= BASE_CR (Link
, IFR_DEFAULT_DATA
, Entry
);
1167 if (DefaultValueArray
->DefaultId
== DefaultValueData
->DefaultId
) {
1169 // DEFAULT_VALUE_FROM_OPCODE has high priority, DEFAULT_VALUE_FROM_DEFAULT has low priority.
1170 // When default types are DEFAULT_VALUE_FROM_OTHER_DEFAULT, the default value can be overrode.
1172 if ((DefaultValueData
->Type
> DefaultValueArray
->Type
) || (DefaultValueData
->Type
== DefaultValueArray
->Type
&& DefaultValueData
->Type
== DefaultValueFromOtherDefault
)) {
1174 // Update the default value array in BlockData.
1176 CopyMem (&DefaultValueArray
->Value
, &DefaultValueData
->Value
, sizeof (EFI_IFR_TYPE_VALUE
));
1177 DefaultValueArray
->Type
= DefaultValueData
->Type
;
1178 DefaultValueArray
->Cleaned
= DefaultValueData
->Cleaned
;
1185 // Insert new default value data in tail.
1187 DefaultValueArray
= AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
1188 ASSERT (DefaultValueArray
!= NULL
);
1189 CopyMem (DefaultValueArray
, DefaultValueData
, sizeof (IFR_DEFAULT_DATA
));
1190 InsertTailList (Link
, &DefaultValueArray
->Entry
);
1194 This function inserts new BlockData into the block link
1196 @param BlockLink The list entry points to block array.
1197 @param BlockData The point to BlockData is added.
1202 IN LIST_ENTRY
*BlockLink
,
1203 IN IFR_BLOCK_DATA
**BlockData
1207 IFR_BLOCK_DATA
*BlockArray
;
1208 IFR_BLOCK_DATA
*BlockSingleData
;
1210 BlockSingleData
= *BlockData
;
1212 if (BlockSingleData
->Name
!= NULL
) {
1213 InsertTailList (BlockLink
, &BlockSingleData
->Entry
);
1218 // Insert block data in its Offset and Width order.
1220 for (Link
= BlockLink
->ForwardLink
; Link
!= BlockLink
; Link
= Link
->ForwardLink
) {
1221 BlockArray
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
1222 if (BlockArray
->Offset
== BlockSingleData
->Offset
) {
1223 if ((BlockArray
->Width
> BlockSingleData
->Width
) || (BlockSingleData
->IsBitVar
&& BlockArray
->Width
== BlockSingleData
->Width
)) {
1225 // Insert this block data in the front of block array
1227 InsertTailList (Link
, &BlockSingleData
->Entry
);
1231 if ((!BlockSingleData
->IsBitVar
) && BlockArray
->Width
== BlockSingleData
->Width
) {
1233 // The same block array has been added.
1235 if (BlockSingleData
!= BlockArray
) {
1236 FreePool (BlockSingleData
);
1237 *BlockData
= BlockArray
;
1241 } else if (BlockArray
->Offset
> BlockSingleData
->Offset
) {
1243 // Insert new block data in the front of block array
1245 InsertTailList (Link
, &BlockSingleData
->Entry
);
1251 // Add new block data into the tail.
1253 InsertTailList (Link
, &BlockSingleData
->Entry
);
1257 Retrieves a pointer to the a Null-terminated ASCII string containing the list
1258 of languages that an HII handle in the HII Database supports. The returned
1259 string is allocated using AllocatePool(). The caller is responsible for freeing
1260 the returned string using FreePool(). The format of the returned string follows
1261 the language format assumed the HII Database.
1263 If HiiHandle is NULL, then ASSERT().
1265 @param[in] HiiHandle A handle that was previously registered in the HII Database.
1267 @retval NULL HiiHandle is not registered in the HII database
1268 @retval NULL There are not enough resources available to retrieve the supported
1270 @retval NULL The list of supported languages could not be retrieved.
1271 @retval Other A pointer to the Null-terminated ASCII string of supported languages.
1275 GetSupportedLanguages (
1276 IN EFI_HII_HANDLE HiiHandle
1281 CHAR8 TempSupportedLanguages
;
1282 CHAR8
*SupportedLanguages
;
1284 ASSERT (HiiHandle
!= NULL
);
1287 // Retrieve the size required for the supported languages buffer.
1290 Status
= mPrivate
.HiiString
.GetLanguages (&mPrivate
.HiiString
, HiiHandle
, &TempSupportedLanguages
, &LanguageSize
);
1293 // If GetLanguages() returns EFI_SUCCESS for a zero size,
1294 // then there are no supported languages registered for HiiHandle. If GetLanguages()
1295 // returns an error other than EFI_BUFFER_TOO_SMALL, then HiiHandle is not present
1296 // in the HII Database
1298 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
1300 // Return NULL if the size can not be retrieved, or if HiiHandle is not in the HII Database
1306 // Allocate the supported languages buffer.
1308 SupportedLanguages
= AllocateZeroPool (LanguageSize
);
1309 if (SupportedLanguages
== NULL
) {
1311 // Return NULL if allocation fails.
1317 // Retrieve the supported languages string
1319 Status
= mPrivate
.HiiString
.GetLanguages (&mPrivate
.HiiString
, HiiHandle
, SupportedLanguages
, &LanguageSize
);
1320 if (EFI_ERROR (Status
)) {
1322 // Free the buffer and return NULL if the supported languages can not be retrieved.
1324 FreePool (SupportedLanguages
);
1329 // Return the Null-terminated ASCII string of supported languages
1331 return SupportedLanguages
;
1335 Retrieves a string from a string package.
1337 If HiiHandle is NULL, then ASSERT().
1338 If StringId is 0, then ASSET.
1340 @param[in] HiiHandle A handle that was previously registered in the HII Database.
1341 @param[in] StringId The identifier of the string to retrieved from the string
1342 package associated with HiiHandle.
1344 @retval NULL The string specified by StringId is not present in the string package.
1345 @retval Other The string was returned.
1350 IN EFI_HII_HANDLE HiiHandle
,
1351 IN EFI_STRING_ID StringId
1358 CHAR8
*SupportedLanguages
;
1359 CHAR8
*PlatformLanguage
;
1360 CHAR8
*BestLanguage
;
1363 ASSERT (HiiHandle
!= NULL
);
1364 ASSERT (StringId
!= 0);
1367 // Initialize all allocated buffers to NULL
1369 SupportedLanguages
= NULL
;
1370 PlatformLanguage
= NULL
;
1371 BestLanguage
= NULL
;
1376 // Get the languages that the package specified by HiiHandle supports
1378 SupportedLanguages
= GetSupportedLanguages (HiiHandle
);
1379 if (SupportedLanguages
== NULL
) {
1384 // Get the current platform language setting
1386 GetEfiGlobalVariable2 (L
"PlatformLang", (VOID
**)&PlatformLanguage
, NULL
);
1389 // Get the best matching language from SupportedLanguages
1391 BestLanguage
= GetBestLanguage (
1393 FALSE
, // RFC 4646 mode
1394 Language
, // Highest priority
1395 PlatformLanguage
!= NULL
? PlatformLanguage
: "", // Next highest priority
1396 SupportedLanguages
, // Lowest priority
1399 if (BestLanguage
== NULL
) {
1404 // Retrieve the size of the string in the string package for the BestLanguage
1407 Status
= mPrivate
.HiiString
.GetString (
1408 &mPrivate
.HiiString
,
1417 // If GetString() returns EFI_SUCCESS for a zero size,
1418 // then there are no supported languages registered for HiiHandle. If GetString()
1419 // returns an error other than EFI_BUFFER_TOO_SMALL, then HiiHandle is not present
1420 // in the HII Database
1422 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
1427 // Allocate a buffer for the return string
1429 String
= AllocateZeroPool (StringSize
);
1430 if (String
== NULL
) {
1435 // Retrieve the string from the string package
1437 Status
= mPrivate
.HiiString
.GetString (
1438 &mPrivate
.HiiString
,
1446 if (EFI_ERROR (Status
)) {
1448 // Free the buffer and return NULL if the supported languages can not be retrieved.
1456 // Free allocated buffers
1458 if (SupportedLanguages
!= NULL
) {
1459 FreePool (SupportedLanguages
);
1461 if (PlatformLanguage
!= NULL
) {
1462 FreePool (PlatformLanguage
);
1464 if (BestLanguage
!= NULL
) {
1465 FreePool (BestLanguage
);
1469 // Return the Null-terminated Unicode string
1475 This function checks VarOffset and VarWidth is in the block range.
1477 @param RequestBlockArray The block array is to be checked.
1478 @param VarOffset Offset of var to the structure
1479 @param VarWidth Width of var.
1480 @param IsNameValueType Whether this varstore is name/value varstore or not.
1481 @param HiiHandle Hii handle for this hii package.
1483 @retval TRUE This Var is in the block range.
1484 @retval FALSE This Var is not in the block range.
1488 IN IFR_BLOCK_DATA
*RequestBlockArray
,
1489 IN UINT16 VarOffset
,
1491 IN BOOLEAN IsNameValueType
,
1492 IN EFI_HII_HANDLE HiiHandle
1496 IFR_BLOCK_DATA
*BlockData
;
1500 // No Request Block array, all vars are got.
1502 if (RequestBlockArray
== NULL
) {
1507 // Check the input var is in the request block range.
1509 for (Link
= RequestBlockArray
->Entry
.ForwardLink
; Link
!= &RequestBlockArray
->Entry
; Link
= Link
->ForwardLink
) {
1510 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
1512 if (IsNameValueType
) {
1513 Name
= InternalGetString (HiiHandle
, VarOffset
);
1514 ASSERT (Name
!= NULL
);
1516 if (StrnCmp (BlockData
->Name
, Name
, StrLen (Name
)) == 0) {
1522 if ((VarOffset
>= BlockData
->Offset
) && ((VarOffset
+ VarWidth
) <= (BlockData
->Offset
+ BlockData
->Width
))) {
1532 Get form package data from data base.
1534 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
1535 @param HiiFormPackage The buffer saves the package data.
1536 @param PackageSize The buffer size of the package data.
1540 GetFormPackageData (
1541 IN HII_DATABASE_RECORD
*DataBaseRecord
,
1542 IN OUT UINT8
**HiiFormPackage
,
1543 OUT UINTN
*PackageSize
1550 if (DataBaseRecord
== NULL
|| HiiFormPackage
== NULL
|| PackageSize
== NULL
) {
1551 return EFI_INVALID_PARAMETER
;
1557 // 0. Get Hii Form Package by HiiHandle
1559 Status
= ExportFormPackages (
1561 DataBaseRecord
->Handle
,
1562 DataBaseRecord
->PackageList
,
1568 if (EFI_ERROR (Status
)) {
1572 (*HiiFormPackage
) = AllocatePool (ResultSize
);
1573 if (*HiiFormPackage
== NULL
) {
1574 Status
= EFI_OUT_OF_RESOURCES
;
1579 // Get HiiFormPackage by HiiHandle
1583 Status
= ExportFormPackages (
1585 DataBaseRecord
->Handle
,
1586 DataBaseRecord
->PackageList
,
1592 if (EFI_ERROR (Status
)) {
1593 FreePool (*HiiFormPackage
);
1596 *PackageSize
= Size
;
1603 This function parses Form Package to get the efi varstore info according to the request ConfigHdr.
1605 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
1606 @param ConfigHdr Request string ConfigHdr. If it is NULL,
1607 the first found varstore will be as ConfigHdr.
1608 @param IsEfiVarstore Whether the request storage type is efi varstore type.
1609 @param EfiVarStore The efi varstore info which will return.
1613 IN HII_DATABASE_RECORD
*DataBaseRecord
,
1614 IN EFI_STRING ConfigHdr
,
1615 OUT BOOLEAN
*IsEfiVarstore
,
1616 OUT EFI_IFR_VARSTORE_EFI
**EfiVarStore
1621 UINTN PackageOffset
;
1622 EFI_IFR_OP_HEADER
*IfrOpHdr
;
1623 CHAR16
*VarStoreName
;
1629 UINT8
*HiiFormPackage
;
1631 EFI_IFR_VARSTORE_EFI
*IfrEfiVarStore
;
1632 EFI_HII_PACKAGE_HEADER
*PackageHeader
;
1634 HiiFormPackage
= NULL
;
1636 Status
= EFI_SUCCESS
;
1640 *IsEfiVarstore
= FALSE
;
1642 Status
= GetFormPackageData(DataBaseRecord
, &HiiFormPackage
, &PackageSize
);
1643 if (EFI_ERROR (Status
)) {
1647 IfrOffset
= sizeof (EFI_HII_PACKAGE_HEADER
);
1648 PackageOffset
= IfrOffset
;
1649 PackageHeader
= (EFI_HII_PACKAGE_HEADER
*) HiiFormPackage
;
1651 while (IfrOffset
< PackageSize
) {
1653 // More than one form packages exist.
1655 if (PackageOffset
>= PackageHeader
->Length
) {
1657 // Process the new form package.
1659 PackageOffset
= sizeof (EFI_HII_PACKAGE_HEADER
);
1660 IfrOffset
+= PackageOffset
;
1661 PackageHeader
= (EFI_HII_PACKAGE_HEADER
*) (HiiFormPackage
+ IfrOffset
);
1664 IfrOpHdr
= (EFI_IFR_OP_HEADER
*) (HiiFormPackage
+ IfrOffset
);
1665 IfrOffset
+= IfrOpHdr
->Length
;
1666 PackageOffset
+= IfrOpHdr
->Length
;
1668 if (IfrOpHdr
->OpCode
== EFI_IFR_VARSTORE_EFI_OP
) {
1669 IfrEfiVarStore
= (EFI_IFR_VARSTORE_EFI
*) IfrOpHdr
;
1671 // If the length is small than the structure, this is from old efi
1672 // varstore definition. Old efi varstore get config directly from
1673 // GetVariable function.
1675 if (IfrOpHdr
->Length
< sizeof (EFI_IFR_VARSTORE_EFI
)) {
1679 NameSize
= AsciiStrSize ((CHAR8
*)IfrEfiVarStore
->Name
);
1680 VarStoreName
= AllocateZeroPool (NameSize
* sizeof (CHAR16
));
1681 if (VarStoreName
== NULL
) {
1682 Status
= EFI_OUT_OF_RESOURCES
;
1685 AsciiStrToUnicodeStrS ((CHAR8
*) IfrEfiVarStore
->Name
, VarStoreName
, NameSize
);
1687 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*) &IfrEfiVarStore
->Guid
, 1, &GuidStr
);
1688 GenerateSubStr (L
"NAME=", StrLen (VarStoreName
) * sizeof (CHAR16
), (VOID
*) VarStoreName
, 2, &NameStr
);
1689 LengthString
= StrLen (GuidStr
);
1690 LengthString
= LengthString
+ StrLen (NameStr
) + 1;
1691 TempStr
= AllocateZeroPool (LengthString
* sizeof (CHAR16
));
1692 if (TempStr
== NULL
) {
1695 FreePool (VarStoreName
);
1696 Status
= EFI_OUT_OF_RESOURCES
;
1699 StrCpyS (TempStr
, LengthString
, GuidStr
);
1700 StrCatS (TempStr
, LengthString
, NameStr
);
1701 if (ConfigHdr
== NULL
|| StrnCmp (ConfigHdr
, TempStr
, StrLen (TempStr
)) == 0) {
1702 *EfiVarStore
= (EFI_IFR_VARSTORE_EFI
*) AllocateZeroPool (IfrOpHdr
->Length
);
1703 if (*EfiVarStore
== NULL
) {
1704 FreePool (VarStoreName
);
1708 Status
= EFI_OUT_OF_RESOURCES
;
1711 *IsEfiVarstore
= TRUE
;
1712 CopyMem (*EfiVarStore
, IfrEfiVarStore
, IfrOpHdr
->Length
);
1716 // Free allocated temp string.
1718 FreePool (VarStoreName
);
1724 // Already found the varstore, break;
1726 if (*IsEfiVarstore
) {
1732 if (HiiFormPackage
!= NULL
) {
1733 FreePool (HiiFormPackage
);
1740 Check whether the ConfigRequest string has the request elements.
1741 For EFI_HII_VARSTORE_BUFFER type, the request has "&OFFSET=****&WIDTH=****..." format.
1742 For EFI_HII_VARSTORE_NAME_VALUE type, the request has "&NAME1**&NAME2..." format.
1744 @param ConfigRequest The input config request string.
1746 @retval TRUE The input include config request elements.
1747 @retval FALSE The input string not includes.
1751 GetElementsFromRequest (
1752 IN EFI_STRING ConfigRequest
1755 EFI_STRING TmpRequest
;
1757 TmpRequest
= StrStr (ConfigRequest
, L
"PATH=");
1758 ASSERT (TmpRequest
!= NULL
);
1760 if ((StrStr (TmpRequest
, L
"&OFFSET=") != NULL
) || (StrStr (TmpRequest
, L
"&") != NULL
)) {
1768 Check whether the this varstore is the request varstore.
1770 @param VarstoreGuid Varstore guid.
1771 @param Name Varstore name.
1772 @param ConfigHdr Current configRequest info.
1774 @retval TRUE This varstore is the request one.
1775 @retval FALSE This varstore is not the request one.
1780 IN EFI_GUID
*VarstoreGuid
,
1782 IN CHAR16
*ConfigHdr
1796 // If ConfigHdr has name field and varstore not has name, return FALSE.
1798 if (Name
== NULL
&& ConfigHdr
!= NULL
&& StrStr (ConfigHdr
, L
"NAME=&") == NULL
) {
1802 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*)VarstoreGuid
, 1, &GuidStr
);
1804 GenerateSubStr (L
"NAME=", StrLen (Name
) * sizeof (CHAR16
), (VOID
*) Name
, 2, &NameStr
);
1806 GenerateSubStr (L
"NAME=", 0, NULL
, 2, &NameStr
);
1808 LengthString
= StrLen (GuidStr
);
1809 LengthString
= LengthString
+ StrLen (NameStr
) + 1;
1810 TempStr
= AllocateZeroPool (LengthString
* sizeof (CHAR16
));
1811 if (TempStr
== NULL
) {
1815 StrCpyS (TempStr
, LengthString
, GuidStr
);
1816 StrCatS (TempStr
, LengthString
, NameStr
);
1818 if (ConfigHdr
== NULL
|| StrnCmp (ConfigHdr
, TempStr
, StrLen (TempStr
)) == 0) {
1823 if (GuidStr
!= NULL
) {
1827 if (NameStr
!= NULL
) {
1831 if (TempStr
!= NULL
) {
1839 This function parses Form Package to get the efi varstore info according to the request ConfigHdr.
1841 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
1842 @param ConfigHdr Request string ConfigHdr. If it is NULL,
1843 the first found varstore will be as ConfigHdr.
1844 @retval TRUE This hii package is the request one.
1845 @retval FALSE This hii package is not the request one.
1849 IN HII_DATABASE_RECORD
*DataBaseRecord
,
1850 IN EFI_STRING ConfigHdr
1855 UINTN PackageOffset
;
1856 EFI_IFR_OP_HEADER
*IfrOpHdr
;
1857 CHAR16
*VarStoreName
;
1859 UINT8
*HiiFormPackage
;
1861 EFI_IFR_VARSTORE_EFI
*IfrEfiVarStore
;
1862 EFI_HII_PACKAGE_HEADER
*PackageHeader
;
1863 EFI_IFR_VARSTORE
*IfrVarStore
;
1864 EFI_IFR_VARSTORE_NAME_VALUE
*IfrNameValueVarStore
;
1865 BOOLEAN FindVarstore
;
1867 HiiFormPackage
= NULL
;
1868 VarStoreName
= NULL
;
1869 Status
= EFI_SUCCESS
;
1870 FindVarstore
= FALSE
;
1872 Status
= GetFormPackageData(DataBaseRecord
, &HiiFormPackage
, &PackageSize
);
1873 if (EFI_ERROR (Status
)) {
1877 IfrOffset
= sizeof (EFI_HII_PACKAGE_HEADER
);
1878 PackageOffset
= IfrOffset
;
1879 PackageHeader
= (EFI_HII_PACKAGE_HEADER
*) HiiFormPackage
;
1881 while (IfrOffset
< PackageSize
) {
1883 // More than one form packages exist.
1885 if (PackageOffset
>= PackageHeader
->Length
) {
1887 // Process the new form package.
1889 PackageOffset
= sizeof (EFI_HII_PACKAGE_HEADER
);
1890 IfrOffset
+= PackageOffset
;
1891 PackageHeader
= (EFI_HII_PACKAGE_HEADER
*) (HiiFormPackage
+ IfrOffset
);
1894 IfrOpHdr
= (EFI_IFR_OP_HEADER
*) (HiiFormPackage
+ IfrOffset
);
1895 IfrOffset
+= IfrOpHdr
->Length
;
1896 PackageOffset
+= IfrOpHdr
->Length
;
1898 switch (IfrOpHdr
->OpCode
) {
1900 case EFI_IFR_VARSTORE_OP
:
1901 IfrVarStore
= (EFI_IFR_VARSTORE
*) IfrOpHdr
;
1903 NameSize
= AsciiStrSize ((CHAR8
*)IfrVarStore
->Name
);
1904 VarStoreName
= AllocateZeroPool (NameSize
* sizeof (CHAR16
));
1905 if (VarStoreName
== NULL
) {
1908 AsciiStrToUnicodeStrS ((CHAR8
*)IfrVarStore
->Name
, VarStoreName
, NameSize
);
1910 if (IsThisVarstore((VOID
*)&IfrVarStore
->Guid
, VarStoreName
, ConfigHdr
)) {
1911 FindVarstore
= TRUE
;
1914 FreePool (VarStoreName
);
1915 VarStoreName
= NULL
;
1919 case EFI_IFR_VARSTORE_EFI_OP
:
1920 IfrEfiVarStore
= (EFI_IFR_VARSTORE_EFI
*) IfrOpHdr
;
1921 NameSize
= AsciiStrSize ((CHAR8
*)IfrEfiVarStore
->Name
);
1922 VarStoreName
= AllocateZeroPool (NameSize
* sizeof (CHAR16
));
1923 if (VarStoreName
== NULL
) {
1926 AsciiStrToUnicodeStrS ((CHAR8
*)IfrEfiVarStore
->Name
, VarStoreName
, NameSize
);
1928 if (IsThisVarstore (&IfrEfiVarStore
->Guid
, VarStoreName
, ConfigHdr
)) {
1929 FindVarstore
= TRUE
;
1932 FreePool (VarStoreName
);
1933 VarStoreName
= NULL
;
1937 case EFI_IFR_VARSTORE_NAME_VALUE_OP
:
1938 IfrNameValueVarStore
= (EFI_IFR_VARSTORE_NAME_VALUE
*) IfrOpHdr
;
1940 if (IsThisVarstore (&IfrNameValueVarStore
->Guid
, NULL
, ConfigHdr
)) {
1941 FindVarstore
= TRUE
;
1946 case EFI_IFR_FORM_OP
:
1947 case EFI_IFR_FORM_MAP_OP
:
1949 // No matched varstore is found and directly return.
1958 if (HiiFormPackage
!= NULL
) {
1959 FreePool (HiiFormPackage
);
1962 if (VarStoreName
!= NULL
) {
1963 FreePool (VarStoreName
);
1966 return FindVarstore
;
1970 Check whether the this op code is required.
1972 @param RequestBlockArray The array includes all the request info or NULL.
1973 @param HiiHandle The hii handle for this form package.
1974 @param VarStorageData The varstore data structure.
1975 @param IfrOpHdr Ifr opcode header for this opcode.
1976 @param VarWidth The buffer width for this opcode.
1977 @param ReturnData The data block added for this opcode.
1978 @param IsBitVar Whether the the opcode refers to bit storage.
1980 @retval EFI_SUCCESS This opcode is required.
1981 @retval EFI_NOT_FOUND This opcode is not required.
1982 @retval Others Contain some error.
1986 IsThisOpcodeRequired (
1987 IN IFR_BLOCK_DATA
*RequestBlockArray
,
1988 IN EFI_HII_HANDLE HiiHandle
,
1989 IN OUT IFR_VARSTORAGE_DATA
*VarStorageData
,
1990 IN EFI_IFR_OP_HEADER
*IfrOpHdr
,
1992 OUT IFR_BLOCK_DATA
**ReturnData
,
1996 IFR_BLOCK_DATA
*BlockData
;
1998 EFI_STRING_ID NameId
;
1999 EFI_IFR_QUESTION_HEADER
*IfrQuestionHdr
;
2008 IfrQuestionHdr
= (EFI_IFR_QUESTION_HEADER
*)((CHAR8
*) IfrOpHdr
+ sizeof (EFI_IFR_OP_HEADER
));
2010 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2011 NameId
= IfrQuestionHdr
->VarStoreInfo
.VarName
;
2014 // Check whether this question is in requested block array.
2016 if (!BlockArrayCheck (RequestBlockArray
, NameId
, 0, TRUE
, HiiHandle
)) {
2018 // This question is not in the requested string. Skip it.
2020 return EFI_NOT_FOUND
;
2024 // Get the byte offset/with and bit offset/width
2027 BitOffset
= IfrQuestionHdr
->VarStoreInfo
.VarOffset
;
2028 BitWidth
= VarWidth
;
2029 VarOffset
= BitOffset
/ 8;
2031 // Use current bit width and the bit width before current bit (with same byte offset) to calculate the byte width.
2033 TotalBits
= BitOffset
% 8 + BitWidth
;
2034 VarWidth
= (TotalBits
% 8 == 0 ? TotalBits
/ 8: TotalBits
/ 8 + 1);
2036 VarOffset
= IfrQuestionHdr
->VarStoreInfo
.VarOffset
;
2037 BitWidth
= VarWidth
;
2038 BitOffset
= VarOffset
* 8;
2042 // Check whether this question is in requested block array.
2044 if (!BlockArrayCheck (RequestBlockArray
, VarOffset
, VarWidth
, FALSE
, HiiHandle
)) {
2046 // This question is not in the requested string. Skip it.
2048 return EFI_NOT_FOUND
;
2052 // Check this var question is in the var storage
2054 if (((VarOffset
+ VarWidth
) > VarStorageData
->Size
)) {
2055 return EFI_INVALID_PARAMETER
;
2059 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
2060 if (BlockData
== NULL
) {
2061 return EFI_OUT_OF_RESOURCES
;
2064 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2065 BlockData
->Name
= InternalGetString(HiiHandle
, NameId
);
2067 BlockData
->Offset
= VarOffset
;
2070 BlockData
->Width
= VarWidth
;
2071 BlockData
->QuestionId
= IfrQuestionHdr
->QuestionId
;
2072 BlockData
->OpCode
= IfrOpHdr
->OpCode
;
2073 BlockData
->Scope
= IfrOpHdr
->Scope
;
2074 BlockData
->IsBitVar
= IsBitVar
;
2075 BlockData
->BitOffset
= BitOffset
;
2076 BlockData
->BitWidth
= BitWidth
;
2077 InitializeListHead (&BlockData
->DefaultValueEntry
);
2079 // Add Block Data into VarStorageData BlockEntry
2081 InsertBlockData (&VarStorageData
->BlockEntry
, &BlockData
);
2082 *ReturnData
= BlockData
;
2088 This function parses Form Package to get the block array and the default
2089 value array according to the request ConfigHdr.
2091 @param HiiHandle Hii Handle for this hii package.
2092 @param Package Pointer to the form package data.
2093 @param PackageLength Length of the package.
2094 @param ConfigHdr Request string ConfigHdr. If it is NULL,
2095 the first found varstore will be as ConfigHdr.
2096 @param RequestBlockArray The block array is retrieved from the request string.
2097 @param VarStorageData VarStorage structure contains the got block and default value.
2098 @param DefaultIdArray Point to the got default id and default name array.
2100 @retval EFI_SUCCESS The block array and the default value array are got.
2101 @retval EFI_INVALID_PARAMETER The varstore definition in the different form packages
2103 @retval EFI_OUT_OF_RESOURCES No enough memory.
2108 IN EFI_HII_HANDLE HiiHandle
,
2110 IN UINT32 PackageLength
,
2111 IN EFI_STRING ConfigHdr
,
2112 IN IFR_BLOCK_DATA
*RequestBlockArray
,
2113 IN OUT IFR_VARSTORAGE_DATA
*VarStorageData
,
2114 OUT IFR_DEFAULT_DATA
*DefaultIdArray
2119 UINTN PackageOffset
;
2120 EFI_IFR_VARSTORE
*IfrVarStore
;
2121 EFI_IFR_VARSTORE_EFI
*IfrEfiVarStore
;
2122 EFI_IFR_OP_HEADER
*IfrOpHdr
;
2123 EFI_IFR_ONE_OF
*IfrOneOf
;
2124 EFI_IFR_REF4
*IfrRef
;
2125 EFI_IFR_ONE_OF_OPTION
*IfrOneOfOption
;
2126 EFI_IFR_DEFAULT
*IfrDefault
;
2127 EFI_IFR_ORDERED_LIST
*IfrOrderedList
;
2128 EFI_IFR_CHECKBOX
*IfrCheckBox
;
2129 EFI_IFR_PASSWORD
*IfrPassword
;
2130 EFI_IFR_STRING
*IfrString
;
2131 EFI_IFR_DATE
*IfrDate
;
2132 EFI_IFR_TIME
*IfrTime
;
2133 IFR_DEFAULT_DATA DefaultData
;
2134 IFR_DEFAULT_DATA
*DefaultDataPtr
;
2135 IFR_BLOCK_DATA
*BlockData
;
2136 CHAR16
*VarStoreName
;
2139 UINT16 VarDefaultId
;
2140 BOOLEAN FirstOneOfOption
;
2141 BOOLEAN FirstOrderedList
;
2142 LIST_ENTRY
*LinkData
;
2143 LIST_ENTRY
*LinkDefault
;
2144 EFI_IFR_VARSTORE_NAME_VALUE
*IfrNameValueVarStore
;
2145 EFI_HII_PACKAGE_HEADER
*PackageHeader
;
2146 EFI_VARSTORE_ID VarStoreId
;
2147 UINT16 SmallestDefaultId
;
2148 BOOLEAN SmallestIdFromFlag
;
2149 BOOLEAN FromOtherDefaultOpcode
;
2150 BOOLEAN QuestionReferBitField
;
2152 Status
= EFI_SUCCESS
;
2154 DefaultDataPtr
= NULL
;
2155 FirstOneOfOption
= FALSE
;
2157 FirstOrderedList
= FALSE
;
2158 VarStoreName
= NULL
;
2159 ZeroMem (&DefaultData
, sizeof (IFR_DEFAULT_DATA
));
2160 SmallestDefaultId
= 0xFFFF;
2161 FromOtherDefaultOpcode
= FALSE
;
2162 QuestionReferBitField
= FALSE
;
2165 // Go through the form package to parse OpCode one by one.
2167 PackageOffset
= sizeof (EFI_HII_PACKAGE_HEADER
);
2168 PackageHeader
= (EFI_HII_PACKAGE_HEADER
*) Package
;
2169 IfrOffset
= PackageOffset
;
2170 while (IfrOffset
< PackageLength
) {
2173 // More than one form package found.
2175 if (PackageOffset
>= PackageHeader
->Length
) {
2177 // Already found varstore for this request, break;
2179 if (VarStoreId
!= 0) {
2184 // Get next package header info.
2186 IfrOffset
+= sizeof (EFI_HII_PACKAGE_HEADER
);
2187 PackageOffset
= sizeof (EFI_HII_PACKAGE_HEADER
);
2188 PackageHeader
= (EFI_HII_PACKAGE_HEADER
*) (Package
+ IfrOffset
);
2191 IfrOpHdr
= (EFI_IFR_OP_HEADER
*) (Package
+ IfrOffset
);
2192 switch (IfrOpHdr
->OpCode
) {
2193 case EFI_IFR_VARSTORE_OP
:
2195 // VarStore is found. Don't need to search any more.
2197 if (VarStoreId
!= 0) {
2201 IfrVarStore
= (EFI_IFR_VARSTORE
*) IfrOpHdr
;
2203 NameSize
= AsciiStrSize ((CHAR8
*)IfrVarStore
->Name
);
2204 VarStoreName
= AllocateZeroPool (NameSize
* sizeof (CHAR16
));
2205 if (VarStoreName
== NULL
) {
2206 Status
= EFI_OUT_OF_RESOURCES
;
2209 AsciiStrToUnicodeStrS ((CHAR8
*)IfrVarStore
->Name
, VarStoreName
, NameSize
);
2211 if (IsThisVarstore((VOID
*)&IfrVarStore
->Guid
, VarStoreName
, ConfigHdr
)) {
2213 // Find the matched VarStore
2215 CopyGuid (&VarStorageData
->Guid
, (EFI_GUID
*) (VOID
*) &IfrVarStore
->Guid
);
2216 VarStorageData
->Size
= IfrVarStore
->Size
;
2217 VarStorageData
->Name
= VarStoreName
;
2218 VarStorageData
->Type
= EFI_HII_VARSTORE_BUFFER
;
2219 VarStoreId
= IfrVarStore
->VarStoreId
;
2221 FreePool (VarStoreName
);
2222 VarStoreName
= NULL
;
2226 case EFI_IFR_VARSTORE_EFI_OP
:
2228 // VarStore is found. Don't need to search any more.
2230 if (VarStoreId
!= 0) {
2234 IfrEfiVarStore
= (EFI_IFR_VARSTORE_EFI
*) IfrOpHdr
;
2237 // If the length is small than the structure, this is from old efi
2238 // varstore definition. Old efi varstore get config directly from
2239 // GetVariable function.
2241 if (IfrOpHdr
->Length
< sizeof (EFI_IFR_VARSTORE_EFI
)) {
2245 NameSize
= AsciiStrSize ((CHAR8
*)IfrEfiVarStore
->Name
);
2246 VarStoreName
= AllocateZeroPool (NameSize
* sizeof (CHAR16
));
2247 if (VarStoreName
== NULL
) {
2248 Status
= EFI_OUT_OF_RESOURCES
;
2251 AsciiStrToUnicodeStrS ((CHAR8
*)IfrEfiVarStore
->Name
, VarStoreName
, NameSize
);
2253 if (IsThisVarstore (&IfrEfiVarStore
->Guid
, VarStoreName
, ConfigHdr
)) {
2255 // Find the matched VarStore
2257 CopyGuid (&VarStorageData
->Guid
, (EFI_GUID
*) (VOID
*) &IfrEfiVarStore
->Guid
);
2258 VarStorageData
->Size
= IfrEfiVarStore
->Size
;
2259 VarStorageData
->Name
= VarStoreName
;
2260 VarStorageData
->Type
= EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
;
2261 VarStoreId
= IfrEfiVarStore
->VarStoreId
;
2263 FreePool (VarStoreName
);
2264 VarStoreName
= NULL
;
2268 case EFI_IFR_VARSTORE_NAME_VALUE_OP
:
2270 // VarStore is found. Don't need to search any more.
2272 if (VarStoreId
!= 0) {
2276 IfrNameValueVarStore
= (EFI_IFR_VARSTORE_NAME_VALUE
*) IfrOpHdr
;
2278 if (IsThisVarstore (&IfrNameValueVarStore
->Guid
, NULL
, ConfigHdr
)) {
2280 // Find the matched VarStore
2282 CopyGuid (&VarStorageData
->Guid
, (EFI_GUID
*) (VOID
*) &IfrNameValueVarStore
->Guid
);
2283 VarStorageData
->Type
= EFI_HII_VARSTORE_NAME_VALUE
;
2284 VarStoreId
= IfrNameValueVarStore
->VarStoreId
;
2288 case EFI_IFR_DEFAULTSTORE_OP
:
2290 // Add new the map between default id and default name.
2292 DefaultDataPtr
= (IFR_DEFAULT_DATA
*) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
2293 if (DefaultDataPtr
== NULL
) {
2294 Status
= EFI_OUT_OF_RESOURCES
;
2297 DefaultDataPtr
->DefaultId
= ((EFI_IFR_DEFAULTSTORE
*) IfrOpHdr
)->DefaultId
;
2298 InsertTailList (&DefaultIdArray
->Entry
, &DefaultDataPtr
->Entry
);
2299 DefaultDataPtr
= NULL
;
2302 case EFI_IFR_FORM_OP
:
2303 case EFI_IFR_FORM_MAP_OP
:
2305 // No matched varstore is found and directly return.
2307 if ( VarStoreId
== 0) {
2308 Status
= EFI_SUCCESS
;
2313 case EFI_IFR_REF_OP
:
2315 // Ref question is not in IFR Form. This IFR form is not valid.
2317 if ( VarStoreId
== 0) {
2318 Status
= EFI_INVALID_PARAMETER
;
2322 // Check whether this question is for the requested varstore.
2324 IfrRef
= (EFI_IFR_REF4
*) IfrOpHdr
;
2325 if (IfrRef
->Question
.VarStoreId
!= VarStoreId
) {
2328 VarWidth
= (UINT16
) (sizeof (EFI_HII_REF
));
2331 // The BlockData may allocate by other opcode,need to clean.
2333 if (BlockData
!= NULL
){
2337 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
, FALSE
);
2338 if (EFI_ERROR (Status
)) {
2339 if (Status
== EFI_NOT_FOUND
){
2341 //The opcode is not required,exit and parse other opcode.
2349 case EFI_IFR_ONE_OF_OP
:
2350 case EFI_IFR_NUMERIC_OP
:
2352 // Numeric and OneOf has the same opcode structure.
2356 // Numeric and OneOf question is not in IFR Form. This IFR form is not valid.
2358 if (VarStoreId
== 0) {
2359 Status
= EFI_INVALID_PARAMETER
;
2363 // Check whether this question is for the requested varstore.
2365 IfrOneOf
= (EFI_IFR_ONE_OF
*) IfrOpHdr
;
2366 if (IfrOneOf
->Question
.VarStoreId
!= VarStoreId
) {
2370 if (QuestionReferBitField
) {
2371 VarWidth
= IfrOneOf
->Flags
& EDKII_IFR_NUMERIC_SIZE_BIT
;
2373 VarWidth
= (UINT16
) (1 << (IfrOneOf
->Flags
& EFI_IFR_NUMERIC_SIZE
));
2377 // The BlockData may allocate by other opcode,need to clean.
2379 if (BlockData
!= NULL
){
2383 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
, QuestionReferBitField
);
2384 if (EFI_ERROR (Status
)) {
2385 if (Status
== EFI_NOT_FOUND
){
2387 //The opcode is not required,exit and parse other opcode.
2395 //when go to there,BlockData can't be NULLL.
2397 ASSERT (BlockData
!= NULL
);
2399 if (IfrOpHdr
->OpCode
== EFI_IFR_ONE_OF_OP
) {
2401 // Set this flag to TRUE for the first oneof option.
2403 FirstOneOfOption
= TRUE
;
2404 } else if (IfrOpHdr
->OpCode
== EFI_IFR_NUMERIC_OP
) {
2406 // Numeric minimum value will be used as default value when no default is specified.
2408 DefaultData
.Type
= DefaultValueFromDefault
;
2409 if (QuestionReferBitField
) {
2411 // Since default value in bit field was stored as UINT32 type.
2413 CopyMem (&DefaultData
.Value
.u32
, &IfrOneOf
->data
.u32
.MinValue
, sizeof (UINT32
));
2415 switch (IfrOneOf
->Flags
& EFI_IFR_NUMERIC_SIZE
) {
2416 case EFI_IFR_NUMERIC_SIZE_1
:
2417 DefaultData
.Value
.u8
= IfrOneOf
->data
.u8
.MinValue
;
2420 case EFI_IFR_NUMERIC_SIZE_2
:
2421 CopyMem (&DefaultData
.Value
.u16
, &IfrOneOf
->data
.u16
.MinValue
, sizeof (UINT16
));
2424 case EFI_IFR_NUMERIC_SIZE_4
:
2425 CopyMem (&DefaultData
.Value
.u32
, &IfrOneOf
->data
.u32
.MinValue
, sizeof (UINT32
));
2428 case EFI_IFR_NUMERIC_SIZE_8
:
2429 CopyMem (&DefaultData
.Value
.u64
, &IfrOneOf
->data
.u64
.MinValue
, sizeof (UINT64
));
2433 Status
= EFI_INVALID_PARAMETER
;
2438 // Set default value base on the DefaultId list get from IFR data.
2440 for (LinkData
= DefaultIdArray
->Entry
.ForwardLink
; LinkData
!= &DefaultIdArray
->Entry
; LinkData
= LinkData
->ForwardLink
) {
2441 DefaultDataPtr
= BASE_CR (LinkData
, IFR_DEFAULT_DATA
, Entry
);
2442 DefaultData
.DefaultId
= DefaultDataPtr
->DefaultId
;
2443 InsertDefaultValue (BlockData
, &DefaultData
);
2448 case EFI_IFR_ORDERED_LIST_OP
:
2450 // offset by question header
2451 // width by EFI_IFR_ORDERED_LIST MaxContainers * OneofOption Type
2454 FirstOrderedList
= TRUE
;
2456 // OrderedList question is not in IFR Form. This IFR form is not valid.
2458 if (VarStoreId
== 0) {
2459 Status
= EFI_INVALID_PARAMETER
;
2463 // Check whether this question is for the requested varstore.
2465 IfrOrderedList
= (EFI_IFR_ORDERED_LIST
*) IfrOpHdr
;
2466 if (IfrOrderedList
->Question
.VarStoreId
!= VarStoreId
) {
2470 VarWidth
= IfrOrderedList
->MaxContainers
;
2473 // The BlockData may allocate by other opcode,need to clean.
2475 if (BlockData
!= NULL
){
2479 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
, FALSE
);
2480 if (EFI_ERROR (Status
)) {
2481 if (Status
== EFI_NOT_FOUND
){
2483 //The opcode is not required,exit and parse other opcode.
2491 case EFI_IFR_CHECKBOX_OP
:
2493 // EFI_IFR_DEFAULT_OP
2494 // offset by question header
2495 // width is 1 sizeof (BOOLEAN)
2496 // default id by CheckBox Flags if CheckBox flags (Default or Mau) is set, the default value is 1 to be set.
2497 // value by DefaultOption
2498 // default id by DeaultOption DefaultId can override CheckBox Flags and Default value.
2502 // CheckBox question is not in IFR Form. This IFR form is not valid.
2504 if (VarStoreId
== 0) {
2505 Status
= EFI_INVALID_PARAMETER
;
2509 // Check whether this question is for the requested varstore.
2511 IfrCheckBox
= (EFI_IFR_CHECKBOX
*) IfrOpHdr
;
2512 if (IfrCheckBox
->Question
.VarStoreId
!= VarStoreId
) {
2515 VarWidth
= (UINT16
) sizeof (BOOLEAN
);
2518 // The BlockData may allocate by other opcode,need to clean.
2520 if (BlockData
!= NULL
){
2524 if (QuestionReferBitField
) {
2527 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
, QuestionReferBitField
);
2528 if (EFI_ERROR (Status
)) {
2529 if (Status
== EFI_NOT_FOUND
){
2531 //The opcode is not required,exit and parse other opcode.
2539 //when go to there,BlockData can't be NULLL.
2541 ASSERT (BlockData
!= NULL
);
2543 SmallestIdFromFlag
= FALSE
;
2546 // Add default value for standard ID by CheckBox Flag
2548 VarDefaultId
= EFI_HII_DEFAULT_CLASS_STANDARD
;
2550 // Prepare new DefaultValue
2552 DefaultData
.DefaultId
= VarDefaultId
;
2553 if ((IfrCheckBox
->Flags
& EFI_IFR_CHECKBOX_DEFAULT
) == EFI_IFR_CHECKBOX_DEFAULT
) {
2555 // When flag is set, default value is TRUE.
2557 DefaultData
.Type
= DefaultValueFromFlag
;
2558 if (QuestionReferBitField
) {
2559 DefaultData
.Value
.u32
= TRUE
;
2561 DefaultData
.Value
.b
= TRUE
;
2563 InsertDefaultValue (BlockData
, &DefaultData
);
2565 if (SmallestDefaultId
> EFI_HII_DEFAULT_CLASS_STANDARD
) {
2567 // Record the SmallestDefaultId and update the SmallestIdFromFlag.
2569 SmallestDefaultId
= EFI_HII_DEFAULT_CLASS_STANDARD
;
2570 SmallestIdFromFlag
= TRUE
;
2575 // Add default value for Manufacture ID by CheckBox Flag
2577 VarDefaultId
= EFI_HII_DEFAULT_CLASS_MANUFACTURING
;
2579 // Prepare new DefaultValue
2581 DefaultData
.DefaultId
= VarDefaultId
;
2582 if ((IfrCheckBox
->Flags
& EFI_IFR_CHECKBOX_DEFAULT_MFG
) == EFI_IFR_CHECKBOX_DEFAULT_MFG
) {
2584 // When flag is set, default value is TRUE.
2586 DefaultData
.Type
= DefaultValueFromFlag
;
2587 if (QuestionReferBitField
) {
2588 DefaultData
.Value
.u32
= TRUE
;
2590 DefaultData
.Value
.b
= TRUE
;
2592 InsertDefaultValue (BlockData
, &DefaultData
);
2594 if (SmallestDefaultId
> EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
2596 // Record the SmallestDefaultId and update the SmallestIdFromFlag.
2598 SmallestDefaultId
= EFI_HII_DEFAULT_CLASS_MANUFACTURING
;
2599 SmallestIdFromFlag
= TRUE
;
2602 if (SmallestIdFromFlag
) {
2604 // When smallest default Id is given by the flag of CheckBox, set default value with TRUE for other default Id in the DefaultId list.
2606 DefaultData
.Type
= DefaultValueFromOtherDefault
;
2607 if (QuestionReferBitField
) {
2608 DefaultData
.Value
.u32
= TRUE
;
2610 DefaultData
.Value
.b
= TRUE
;
2613 // Set default value for all the default id in the DefaultId list.
2615 for (LinkData
= DefaultIdArray
->Entry
.ForwardLink
; LinkData
!= &DefaultIdArray
->Entry
; LinkData
= LinkData
->ForwardLink
) {
2616 DefaultDataPtr
= BASE_CR (LinkData
, IFR_DEFAULT_DATA
, Entry
);
2617 DefaultData
.DefaultId
= DefaultDataPtr
->DefaultId
;
2618 InsertDefaultValue (BlockData
, &DefaultData
);
2622 // When flag is not set, default value is FASLE.
2624 DefaultData
.Type
= DefaultValueFromDefault
;
2625 if (QuestionReferBitField
) {
2626 DefaultData
.Value
.u32
= FALSE
;
2628 DefaultData
.Value
.b
= FALSE
;
2631 // Set default value for all the default id in the DefaultId list.
2633 for (LinkData
= DefaultIdArray
->Entry
.ForwardLink
; LinkData
!= &DefaultIdArray
->Entry
; LinkData
= LinkData
->ForwardLink
) {
2634 DefaultDataPtr
= BASE_CR (LinkData
, IFR_DEFAULT_DATA
, Entry
);
2635 DefaultData
.DefaultId
= DefaultDataPtr
->DefaultId
;
2636 InsertDefaultValue (BlockData
, &DefaultData
);
2641 case EFI_IFR_DATE_OP
:
2643 // offset by question header
2644 // width MaxSize * sizeof (CHAR16)
2645 // no default value, only block array
2649 // Date question is not in IFR Form. This IFR form is not valid.
2651 if (VarStoreId
== 0) {
2652 Status
= EFI_INVALID_PARAMETER
;
2656 // Check whether this question is for the requested varstore.
2658 IfrDate
= (EFI_IFR_DATE
*) IfrOpHdr
;
2659 if (IfrDate
->Question
.VarStoreId
!= VarStoreId
) {
2664 // The BlockData may allocate by other opcode,need to clean.
2666 if (BlockData
!= NULL
){
2670 VarWidth
= (UINT16
) sizeof (EFI_HII_DATE
);
2671 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
, FALSE
);
2672 if (EFI_ERROR (Status
)) {
2673 if (Status
== EFI_NOT_FOUND
){
2675 //The opcode is not required,exit and parse other opcode.
2683 case EFI_IFR_TIME_OP
:
2685 // offset by question header
2686 // width MaxSize * sizeof (CHAR16)
2687 // no default value, only block array
2691 // Time question is not in IFR Form. This IFR form is not valid.
2693 if (VarStoreId
== 0) {
2694 Status
= EFI_INVALID_PARAMETER
;
2698 // Check whether this question is for the requested varstore.
2700 IfrTime
= (EFI_IFR_TIME
*) IfrOpHdr
;
2701 if (IfrTime
->Question
.VarStoreId
!= VarStoreId
) {
2706 // The BlockData may allocate by other opcode,need to clean.
2708 if (BlockData
!= NULL
){
2712 VarWidth
= (UINT16
) sizeof (EFI_HII_TIME
);
2713 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
, FALSE
);
2714 if (EFI_ERROR (Status
)) {
2715 if (Status
== EFI_NOT_FOUND
){
2717 //The opcode is not required,exit and parse other opcode.
2725 case EFI_IFR_STRING_OP
:
2727 // offset by question header
2728 // width MaxSize * sizeof (CHAR16)
2729 // no default value, only block array
2733 // String question is not in IFR Form. This IFR form is not valid.
2735 if (VarStoreId
== 0) {
2736 Status
= EFI_INVALID_PARAMETER
;
2740 // Check whether this question is for the requested varstore.
2742 IfrString
= (EFI_IFR_STRING
*) IfrOpHdr
;
2743 if (IfrString
->Question
.VarStoreId
!= VarStoreId
) {
2748 // The BlockData may allocate by other opcode,need to clean.
2750 if (BlockData
!= NULL
){
2754 VarWidth
= (UINT16
) (IfrString
->MaxSize
* sizeof (UINT16
));
2755 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
, FALSE
);
2756 if (EFI_ERROR (Status
)) {
2757 if (Status
== EFI_NOT_FOUND
){
2759 //The opcode is not required,exit and parse other opcode.
2767 case EFI_IFR_PASSWORD_OP
:
2769 // offset by question header
2770 // width MaxSize * sizeof (CHAR16)
2771 // no default value, only block array
2775 // Password question is not in IFR Form. This IFR form is not valid.
2777 if (VarStoreId
== 0) {
2778 Status
= EFI_INVALID_PARAMETER
;
2782 // Check whether this question is for the requested varstore.
2784 IfrPassword
= (EFI_IFR_PASSWORD
*) IfrOpHdr
;
2785 if (IfrPassword
->Question
.VarStoreId
!= VarStoreId
) {
2790 // The BlockData may allocate by other opcode,need to clean.
2792 if (BlockData
!= NULL
){
2796 VarWidth
= (UINT16
) (IfrPassword
->MaxSize
* sizeof (UINT16
));
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.
2809 // No default value for string.
2814 case EFI_IFR_ONE_OF_OPTION_OP
:
2816 // No matched block data is ignored.
2818 if (BlockData
== NULL
|| BlockData
->Scope
== 0) {
2822 IfrOneOfOption
= (EFI_IFR_ONE_OF_OPTION
*) IfrOpHdr
;
2823 if (BlockData
->OpCode
== EFI_IFR_ORDERED_LIST_OP
) {
2825 if (!FirstOrderedList
){
2829 // Get ordered list option data type.
2831 if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_8
|| IfrOneOfOption
->Type
== EFI_IFR_TYPE_BOOLEAN
) {
2833 } else if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_16
) {
2835 } else if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_32
) {
2837 } else if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_64
) {
2841 // Invalid ordered list option data type.
2843 Status
= EFI_INVALID_PARAMETER
;
2844 if (BlockData
->Name
!= NULL
) {
2845 FreePool (BlockData
->Name
);
2847 FreePool (BlockData
);
2852 // Calculate Ordered list QuestionId width.
2854 BlockData
->Width
= (UINT16
) (BlockData
->Width
* VarWidth
);
2856 // Check whether this question is in requested block array.
2858 if (!BlockArrayCheck (RequestBlockArray
, BlockData
->Offset
, BlockData
->Width
, (BOOLEAN
)(BlockData
->Name
!= NULL
), HiiHandle
)) {
2860 // This question is not in the requested string. Skip it.
2862 if (BlockData
->Name
!= NULL
) {
2863 FreePool (BlockData
->Name
);
2865 FreePool (BlockData
);
2870 // Check this var question is in the var storage
2872 if ((BlockData
->Name
== NULL
) && ((BlockData
->Offset
+ BlockData
->Width
) > VarStorageData
->Size
)) {
2873 Status
= EFI_INVALID_PARAMETER
;
2874 FreePool (BlockData
);
2878 // Add Block Data into VarStorageData BlockEntry
2880 InsertBlockData (&VarStorageData
->BlockEntry
, &BlockData
);
2882 FirstOrderedList
= FALSE
;
2888 // 1. Set default value for OneOf option when flag field has default attribute.
2889 // And set the default value with the smallest default id for other default id in the DefaultId list.
2891 if (((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT
) == EFI_IFR_OPTION_DEFAULT
) ||
2892 ((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT_MFG
) == EFI_IFR_OPTION_DEFAULT_MFG
)) {
2894 // This flag is used to specify whether this option is the first. Set it to FALSE for the following options.
2895 // The first oneof option value will be used as default value when no default value is specified.
2897 FirstOneOfOption
= FALSE
;
2899 SmallestIdFromFlag
= FALSE
;
2901 // Prepare new DefaultValue
2903 DefaultData
.Type
= DefaultValueFromFlag
;
2904 CopyMem (&DefaultData
.Value
, &IfrOneOfOption
->Value
, IfrOneOfOption
->Header
.Length
- OFFSET_OF (EFI_IFR_ONE_OF_OPTION
, Value
));
2905 if ((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT
) == EFI_IFR_OPTION_DEFAULT
) {
2906 DefaultData
.DefaultId
= EFI_HII_DEFAULT_CLASS_STANDARD
;
2907 InsertDefaultValue (BlockData
, &DefaultData
);
2908 if (SmallestDefaultId
> EFI_HII_DEFAULT_CLASS_STANDARD
) {
2910 // Record the SmallestDefaultId and update the SmallestIdFromFlag.
2912 SmallestDefaultId
= EFI_HII_DEFAULT_CLASS_STANDARD
;
2913 SmallestIdFromFlag
= TRUE
;
2916 if ((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT_MFG
) == EFI_IFR_OPTION_DEFAULT_MFG
) {
2917 DefaultData
.DefaultId
= EFI_HII_DEFAULT_CLASS_MANUFACTURING
;
2918 InsertDefaultValue (BlockData
, &DefaultData
);
2919 if (SmallestDefaultId
> EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
2921 // Record the SmallestDefaultId and update the SmallestIdFromFlag.
2923 SmallestDefaultId
= EFI_HII_DEFAULT_CLASS_MANUFACTURING
;
2924 SmallestIdFromFlag
= TRUE
;
2928 if (SmallestIdFromFlag
) {
2930 // When smallest default Id is given by the flag of oneofOption, set this option value for other default Id in the DefaultId list.
2932 DefaultData
.Type
= DefaultValueFromOtherDefault
;
2934 // Set default value for other default id in the DefaultId list.
2936 for (LinkData
= DefaultIdArray
->Entry
.ForwardLink
; LinkData
!= &DefaultIdArray
->Entry
; LinkData
= LinkData
->ForwardLink
) {
2937 DefaultDataPtr
= BASE_CR (LinkData
, IFR_DEFAULT_DATA
, Entry
);
2938 DefaultData
.DefaultId
= DefaultDataPtr
->DefaultId
;
2939 InsertDefaultValue (BlockData
, &DefaultData
);
2945 // 2. Set as the default value when this is the first option.
2946 // The first oneof option value will be used as default value when no default value is specified.
2948 if (FirstOneOfOption
) {
2949 // This flag is used to specify whether this option is the first. Set it to FALSE for the following options.
2950 FirstOneOfOption
= FALSE
;
2953 // Prepare new DefaultValue
2955 DefaultData
.Type
= DefaultValueFromDefault
;
2956 CopyMem (&DefaultData
.Value
, &IfrOneOfOption
->Value
, IfrOneOfOption
->Header
.Length
- OFFSET_OF (EFI_IFR_ONE_OF_OPTION
, Value
));
2957 for (LinkData
= DefaultIdArray
->Entry
.ForwardLink
; LinkData
!= &DefaultIdArray
->Entry
; LinkData
= LinkData
->ForwardLink
) {
2958 DefaultDataPtr
= BASE_CR (LinkData
, IFR_DEFAULT_DATA
, Entry
);
2959 DefaultData
.DefaultId
= DefaultDataPtr
->DefaultId
;
2960 InsertDefaultValue (BlockData
, &DefaultData
);
2965 case EFI_IFR_DEFAULT_OP
:
2967 // Update Current BlockData to the default value.
2969 if (BlockData
== NULL
|| BlockData
->Scope
== 0) {
2971 // No matched block data is ignored.
2977 // Get the DefaultId
2979 IfrDefault
= (EFI_IFR_DEFAULT
*) IfrOpHdr
;
2980 VarDefaultId
= IfrDefault
->DefaultId
;
2982 // Prepare new DefaultValue
2984 DefaultData
.Type
= DefaultValueFromOpcode
;
2985 DefaultData
.DefaultId
= VarDefaultId
;
2986 if (QuestionReferBitField
) {
2987 CopyMem (&DefaultData
.Value
.u32
, &IfrDefault
->Value
.u32
, sizeof (UINT32
));
2989 CopyMem (&DefaultData
.Value
, &IfrDefault
->Value
, IfrDefault
->Header
.Length
- OFFSET_OF (EFI_IFR_DEFAULT
, Value
));
2992 // If the value field is expression, set the cleaned flag.
2993 if (IfrDefault
->Type
== EFI_IFR_TYPE_OTHER
) {
2994 DefaultData
.Cleaned
= TRUE
;
2997 // Add DefaultValue into current BlockData
2999 InsertDefaultValue (BlockData
, &DefaultData
);
3002 // Set default value for other default id in the DefaultId list.
3003 // when SmallestDefaultId == VarDefaultId means there are two defaults with same default Id.
3004 // If the two defaults are both from default opcode, use the first default as the default value of other default Id.
3005 // If one from flag and the other form default opcode, use the default opcode value as the default value of other default Id.
3007 if ((SmallestDefaultId
> VarDefaultId
) || (SmallestDefaultId
== VarDefaultId
&& !FromOtherDefaultOpcode
)) {
3008 FromOtherDefaultOpcode
= TRUE
;
3009 SmallestDefaultId
= VarDefaultId
;
3010 for (LinkData
= DefaultIdArray
->Entry
.ForwardLink
; LinkData
!= &DefaultIdArray
->Entry
; LinkData
= LinkData
->ForwardLink
) {
3011 DefaultDataPtr
= BASE_CR (LinkData
, IFR_DEFAULT_DATA
, Entry
);
3012 if (DefaultDataPtr
->DefaultId
!= DefaultData
.DefaultId
){
3013 DefaultData
.Type
= DefaultValueFromOtherDefault
;
3014 DefaultData
.DefaultId
= DefaultDataPtr
->DefaultId
;
3015 InsertDefaultValue (BlockData
, &DefaultData
);
3021 // After insert the default value, reset the cleaned value for next
3022 // time used. If not set here, need to set the value before every time.
3025 DefaultData
.Cleaned
= FALSE
;
3028 case EFI_IFR_END_OP
:
3030 // End Opcode is for Var question.
3032 QuestionReferBitField
= FALSE
;
3033 if (BlockData
!= NULL
) {
3034 if (BlockData
->Scope
> 0) {
3037 if (BlockData
->Scope
== 0) {
3040 // when finishing parsing a question, clean the SmallestDefaultId and GetDefaultFromDefaultOpcode.
3042 SmallestDefaultId
= 0xFFFF;
3043 FromOtherDefaultOpcode
= FALSE
;
3049 case EFI_IFR_GUID_OP
:
3050 if (CompareGuid ((EFI_GUID
*)((UINT8
*)IfrOpHdr
+ sizeof (EFI_IFR_OP_HEADER
)), &gEdkiiIfrBitVarstoreGuid
)) {
3051 QuestionReferBitField
= TRUE
;
3056 if (BlockData
!= NULL
) {
3057 if (BlockData
->Scope
> 0) {
3058 BlockData
->Scope
= (UINT8
) (BlockData
->Scope
+ IfrOpHdr
->Scope
);
3061 if (BlockData
->Scope
== 0) {
3068 IfrOffset
+= IfrOpHdr
->Length
;
3069 PackageOffset
+= IfrOpHdr
->Length
;
3073 //if Status == EFI_NOT_FOUND, just means the opcode is not required,not contain any error,
3074 //so set the Status to EFI_SUCCESS.
3076 if (Status
== EFI_NOT_FOUND
){
3077 Status
= EFI_SUCCESS
;
3081 for (LinkData
= VarStorageData
->BlockEntry
.ForwardLink
; LinkData
!= &VarStorageData
->BlockEntry
; LinkData
= LinkData
->ForwardLink
) {
3082 BlockData
= BASE_CR (LinkData
, IFR_BLOCK_DATA
, Entry
);
3083 for (LinkDefault
= BlockData
->DefaultValueEntry
.ForwardLink
; LinkDefault
!= &BlockData
->DefaultValueEntry
; ) {
3084 DefaultDataPtr
= BASE_CR (LinkDefault
, IFR_DEFAULT_DATA
, Entry
);
3085 LinkDefault
= LinkDefault
->ForwardLink
;
3086 if (DefaultDataPtr
->Cleaned
== TRUE
) {
3087 RemoveEntryList (&DefaultDataPtr
->Entry
);
3088 FreePool (DefaultDataPtr
);
3097 parse the configrequest string, get the elements.
3099 @param ConfigRequest The input configrequest string.
3100 @param Progress Return the progress data.
3102 @retval Block data pointer.
3106 IN EFI_STRING ConfigRequest
,
3107 OUT EFI_STRING
*Progress
3110 EFI_STRING StringPtr
;
3111 IFR_BLOCK_DATA
*BlockData
;
3112 IFR_BLOCK_DATA
*RequestBlockArray
;
3118 IFR_BLOCK_DATA
*NextBlockData
;
3124 // Init RequestBlockArray
3126 RequestBlockArray
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
3127 if (RequestBlockArray
== NULL
) {
3130 InitializeListHead (&RequestBlockArray
->Entry
);
3133 // Get the request Block array from the request string
3138 // Parse each <RequestElement> if exists
3139 // Only <BlockName> format is supported by this help function.
3140 // <BlockName> ::= &'OFFSET='<Number>&'WIDTH='<Number>
3142 StringPtr
= ConfigRequest
;
3143 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) == 0) {
3145 // Skip the OFFSET string
3147 *Progress
= StringPtr
;
3148 StringPtr
+= StrLen (L
"&OFFSET=");
3152 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
3153 if (EFI_ERROR (Status
)) {
3160 (((Length
+ 1) / 2) < sizeof (UINT16
)) ? ((Length
+ 1) / 2) : sizeof (UINT16
)
3162 FreePool (TmpBuffer
);
3164 StringPtr
+= Length
;
3165 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
3168 StringPtr
+= StrLen (L
"&WIDTH=");
3173 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
3174 if (EFI_ERROR (Status
)) {
3181 (((Length
+ 1) / 2) < sizeof (UINT16
)) ? ((Length
+ 1) / 2) : sizeof (UINT16
)
3183 FreePool (TmpBuffer
);
3185 StringPtr
+= Length
;
3186 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
3193 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
3194 if (BlockData
== NULL
) {
3197 BlockData
->Offset
= Offset
;
3198 BlockData
->Width
= Width
;
3199 InsertBlockData (&RequestBlockArray
->Entry
, &BlockData
);
3202 // Skip &VALUE string if &VALUE does exists.
3204 if (StrnCmp (StringPtr
, L
"&VALUE=", StrLen (L
"&VALUE=")) == 0) {
3205 StringPtr
+= StrLen (L
"&VALUE=");
3210 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
3211 if (EFI_ERROR (Status
)) {
3214 FreePool (TmpBuffer
);
3215 StringPtr
+= Length
;
3216 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
3221 // If '\0', parsing is finished.
3223 if (*StringPtr
== 0) {
3229 // Merge the requested block data.
3231 Link
= RequestBlockArray
->Entry
.ForwardLink
;
3232 while ((Link
!= &RequestBlockArray
->Entry
) && (Link
->ForwardLink
!= &RequestBlockArray
->Entry
)) {
3233 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
3234 NextBlockData
= BASE_CR (Link
->ForwardLink
, IFR_BLOCK_DATA
, Entry
);
3235 if ((NextBlockData
->Offset
>= BlockData
->Offset
) && (NextBlockData
->Offset
<= (BlockData
->Offset
+ BlockData
->Width
))) {
3236 if ((NextBlockData
->Offset
+ NextBlockData
->Width
) > (BlockData
->Offset
+ BlockData
->Width
)) {
3237 BlockData
->Width
= (UINT16
) (NextBlockData
->Offset
+ NextBlockData
->Width
- BlockData
->Offset
);
3239 RemoveEntryList (Link
->ForwardLink
);
3240 FreePool (NextBlockData
);
3243 Link
= Link
->ForwardLink
;
3246 return RequestBlockArray
;
3249 if (RequestBlockArray
!= NULL
) {
3251 // Free Link Array RequestBlockArray
3253 while (!IsListEmpty (&RequestBlockArray
->Entry
)) {
3254 BlockData
= BASE_CR (RequestBlockArray
->Entry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
3255 RemoveEntryList (&BlockData
->Entry
);
3256 FreePool (BlockData
);
3259 FreePool (RequestBlockArray
);
3266 parse the configrequest string, get the elements.
3268 @param ConfigRequest The input config request string.
3269 @param Progress Return the progress data.
3271 @retval return data block array.
3275 IN EFI_STRING ConfigRequest
,
3276 OUT EFI_STRING
*Progress
3279 EFI_STRING StringPtr
;
3281 IFR_BLOCK_DATA
*BlockData
;
3282 IFR_BLOCK_DATA
*RequestBlockArray
;
3285 StringPtr
= ConfigRequest
;
3288 // Init RequestBlockArray
3290 RequestBlockArray
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
3291 if (RequestBlockArray
== NULL
) {
3294 InitializeListHead (&RequestBlockArray
->Entry
);
3297 // Get the request Block array from the request string
3301 // Parse each <RequestElement> if exists
3302 // Only <BlockName> format is supported by this help function.
3303 // <BlockName> ::= &'Name***=***
3305 while (StringPtr
!= NULL
&& *StringPtr
== L
'&') {
3307 *Progress
= StringPtr
;
3309 // Skip the L"&" string
3314 if ((NextTag
= StrStr (StringPtr
, L
"=")) != NULL
) {
3317 } else if ((NextTag
= StrStr (StringPtr
, L
"&")) != NULL
) {
3324 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
3325 if (BlockData
== NULL
) {
3332 BlockData
->Name
= AllocateCopyPool(StrSize (StringPtr
), StringPtr
);
3333 InsertBlockData (&RequestBlockArray
->Entry
, &BlockData
);
3337 // If has value, skip the value.
3339 StringPtr
= NextTag
+ 1;
3341 StringPtr
= StrStr (StringPtr
, L
"&");
3342 } else if (NextTag
!= NULL
) {
3344 // restore the '&' text.
3346 StringPtr
= NextTag
;
3351 return RequestBlockArray
;
3354 if (RequestBlockArray
!= NULL
) {
3356 // Free Link Array RequestBlockArray
3358 while (!IsListEmpty (&RequestBlockArray
->Entry
)) {
3359 BlockData
= BASE_CR (RequestBlockArray
->Entry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
3360 RemoveEntryList (&BlockData
->Entry
);
3361 if (BlockData
->Name
!= NULL
) {
3362 FreePool (BlockData
->Name
);
3364 FreePool (BlockData
);
3367 FreePool (RequestBlockArray
);
3374 Generate ConfigRequest string base on the varstore info.
3376 @param ConfigHdr The config header for this varstore.
3377 @param VarStorageData The varstore info.
3378 @param Status Return Status.
3379 @param ConfigRequest The ConfigRequest info may be return.
3381 @retval TRUE Need to continue
3382 @retval Others NO need to continue or error occur.
3385 GenerateConfigRequest (
3386 IN CHAR16
*ConfigHdr
,
3387 IN IFR_VARSTORAGE_DATA
*VarStorageData
,
3388 OUT EFI_STATUS
*Status
,
3389 IN OUT EFI_STRING
*ConfigRequest
3395 CHAR16
*FullConfigRequest
;
3397 IFR_BLOCK_DATA
*BlockData
;
3400 // Append VarStorageData BlockEntry into *Request string
3401 // Now support only one varstore in a form package.
3405 // Go through all VarStorageData Entry and get BlockEntry for each one for the multiple varstore in a single form package
3406 // Then construct them all to return MultiRequest string : ConfigHdr BlockConfig
3410 // Compute the length of the entire request starting with <ConfigHdr> and a
3414 Length
= StrLen (ConfigHdr
) + 1;
3416 for (Link
= VarStorageData
->BlockEntry
.ForwardLink
; Link
!= &VarStorageData
->BlockEntry
; Link
= Link
->ForwardLink
) {
3418 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
3419 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3421 // Add <BlockName> length for each Name
3423 // <BlockName> ::= &Name1&Name2&...
3424 // |1| StrLen(Name1)
3426 Length
= Length
+ (1 + StrLen (BlockData
->Name
));
3429 // Add <BlockName> length for each Offset/Width pair
3431 // <BlockName> ::= &OFFSET=1234&WIDTH=1234
3432 // | 8 | 4 | 7 | 4 |
3434 Length
= Length
+ (8 + 4 + 7 + 4);
3438 // No any request block data is found. The request string can't be constructed.
3441 *Status
= EFI_SUCCESS
;
3446 // Allocate buffer for the entire <ConfigRequest>
3448 FullConfigRequest
= AllocateZeroPool (Length
* sizeof (CHAR16
));
3449 if (FullConfigRequest
== NULL
) {
3450 *Status
= EFI_OUT_OF_RESOURCES
;
3453 StringPtr
= FullConfigRequest
;
3456 // Start with <ConfigHdr>
3458 StrCpyS (StringPtr
, Length
, ConfigHdr
);
3459 StringPtr
+= StrLen (StringPtr
);
3462 // Loop through all the Offset/Width pairs and append them to ConfigRequest
3464 for (Link
= VarStorageData
->BlockEntry
.ForwardLink
; Link
!= &VarStorageData
->BlockEntry
; Link
= Link
->ForwardLink
) {
3465 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
3466 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3472 (1 + StrLen (BlockData
->Name
) + 1) * sizeof (CHAR16
),
3478 // Append &OFFSET=XXXX&WIDTH=YYYY\0
3482 (8 + 4 + 7 + 4 + 1) * sizeof (CHAR16
),
3483 L
"&OFFSET=%04X&WIDTH=%04X",
3488 StringPtr
+= StrLen (StringPtr
);
3491 // Set to the got full request string.
3493 HiiToLower (FullConfigRequest
);
3495 if (*ConfigRequest
!= NULL
) {
3496 FreePool (*ConfigRequest
);
3498 *ConfigRequest
= FullConfigRequest
;
3504 Generate ConfigRequest Header base on the varstore info.
3506 @param VarStorageData The varstore info.
3507 @param DevicePath Device path for this varstore.
3508 @param ConfigHdr The config header for this varstore.
3510 @retval EFI_SUCCESS Generate the header success.
3511 @retval EFI_OUT_OF_RESOURCES Allocate buffer fail.
3515 IN IFR_VARSTORAGE_DATA
*VarStorageData
,
3516 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
3517 OUT EFI_STRING
*ConfigHdr
3526 Status
= EFI_SUCCESS
;
3532 // Construct <ConfigHdr> : "GUID=...&NAME=...&PATH=..." by VarStorageData Guid, Name and DriverHandle
3534 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*) &VarStorageData
->Guid
, 1, &GuidStr
);
3535 if (VarStorageData
->Name
!= NULL
) {
3536 GenerateSubStr (L
"NAME=", StrLen (VarStorageData
->Name
) * sizeof (CHAR16
), (VOID
*) VarStorageData
->Name
, 2, &NameStr
);
3538 GenerateSubStr (L
"NAME=", 0, NULL
, 2, &NameStr
);
3542 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) DevicePath
),
3543 (VOID
*) DevicePath
,
3547 Length
= StrLen (GuidStr
) + StrLen (NameStr
) + StrLen (PathStr
) + 1;
3548 if (VarStorageData
->Name
== NULL
) {
3552 *ConfigHdr
= AllocateZeroPool (Length
* sizeof (CHAR16
));
3553 if (*ConfigHdr
== NULL
) {
3554 Status
= EFI_OUT_OF_RESOURCES
;
3557 StrCpyS (*ConfigHdr
, Length
, GuidStr
);
3558 StrCatS (*ConfigHdr
, Length
, NameStr
);
3559 if (VarStorageData
->Name
== NULL
) {
3560 StrCatS (*ConfigHdr
, Length
, L
"&");
3562 StrCatS (*ConfigHdr
, Length
, PathStr
);
3565 // Remove the last character L'&'
3567 *(*ConfigHdr
+ StrLen (*ConfigHdr
) - 1) = L
'\0';
3570 if (GuidStr
!= NULL
) {
3574 if (NameStr
!= NULL
) {
3578 if (PathStr
!= NULL
) {
3587 Update the default value in the block data which is used as bit var store.
3590 A question value saved in a bit fied: bitoffset = 1; bitwidth = 2;default value = 1.
3591 And corresponding block data info: offset==0; width==1;currently the default value
3592 is saved as 1.Actually the default value 1 need to be set to bit field 1, so the
3593 default value of this block data shuold be:2.
3597 UINT8 Bit2 : 2; // Question saved in Bit2,so originalBlock info: offset = 0; width = 1;(byte level) defaul = 1.
3598 // (default value record for the bit field)
3602 After function UpdateDefaultValue,the Block info is: offset = 0; width = 1;(byte level) default = 2.
3603 (default value record for the Block)
3605 UpdateDefaultValue function update default value of bit var block based on the bit field info in the block.
3607 @param BlockLink The Link of the block data.
3611 UpdateDefaultValue (
3612 IN LIST_ENTRY
*BlockLink
3616 LIST_ENTRY
*ListEntry
;
3617 LIST_ENTRY
*LinkDefault
;
3618 IFR_BLOCK_DATA
*BlockData
;
3619 IFR_DEFAULT_DATA
*DefaultValueData
;
3622 UINT32 BitFieldDefaultValue
;
3624 for ( Link
= BlockLink
->ForwardLink
; Link
!= BlockLink
; Link
= Link
->ForwardLink
) {
3625 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
3626 if (!BlockData
->IsBitVar
) {
3629 ListEntry
= &BlockData
->DefaultValueEntry
;
3631 // Update the default value in the block data with all existing default id.
3633 for (LinkDefault
= ListEntry
->ForwardLink
; LinkDefault
!= ListEntry
; LinkDefault
= LinkDefault
->ForwardLink
) {
3635 // Get the default data, and the value of the default data is for some field in the block.
3636 // Note: Default value for bit field question is stored as UINT32.
3638 DefaultValueData
= BASE_CR (LinkDefault
, IFR_DEFAULT_DATA
, Entry
);
3639 BitFieldDefaultValue
= DefaultValueData
->Value
.u32
;
3641 StartBit
= BlockData
->BitOffset
% 8;
3642 EndBit
= StartBit
+ BlockData
->BitWidth
- 1;
3645 // Set the bit field default value to related bit filed, then we will got the new default vaule for the block data.
3647 DefaultValueData
->Value
.u32
= BitFieldWrite32 (0, StartBit
, EndBit
, BitFieldDefaultValue
);
3653 Merge the default value in two block datas which have overlap region.
3655 For bit fields, their related block data may have overlap region, such as:
3658 UINT16 Bit1 : 6; // Question1 refer Bit1, Block1: offset = 0; width = 1;(byte level) default = 1
3659 UINT16 Bit2 : 5; // Question2 refer Bit2, Block2: offset = 0; width = 2;(byte level) default = 5
3660 // (default value record for the bit field)
3664 After function UpdateDefaultValue:
3665 Block1: offset = 0; width = 1;(byte level) default = 1
3666 Block2: offset = 0; width = 2;(byte level) default = 320 (5 * (2 << 6))
3667 (default value record for block)
3669 After function MergeBlockDefaultValue:
3670 Block1: offset = 0; width = 1;(byte level) default = 65
3671 Block2: offset = 0; width = 2;(byte level) default = 321
3672 (Block1 and Block2 has overlap region, merge the overlap value to Block1 and Blcok2)
3674 Block1 and Block2 have overlap byte region, but currntly the default value of Block1 only contains
3675 value of Bit1 (low 6 bits),the default value of Block2 only contains the value of Bit2 (middle 5 bits).
3677 This fuction merge the default value of these two blocks, and make the default value of block1
3678 also contain the value of lower 2 bits of the Bit2. And make the default value of Block2 also
3679 contain the default value of Bit1.
3681 We can get the total value of the whole block that just cover these two blocks(in this case is:
3682 block: offset =0; width =2;) then the value of block2 is same as block, the value of block1 is
3683 the first byte value of block.
3685 @param FirstBlock Point to the block date whose default value need to be merged.
3686 @param SecondBlock Point to the block date whose default value need to be merged.
3690 MergeBlockDefaultValue (
3691 IN OUT IFR_BLOCK_DATA
*FirstBlock
,
3692 IN OUT IFR_BLOCK_DATA
*SecondBlock
3695 LIST_ENTRY
*FirstListEntry
;
3696 LIST_ENTRY
*SecondListEntry
;
3697 LIST_ENTRY
*FirstDefaultLink
;
3698 LIST_ENTRY
*SecondDefaultLink
;
3699 IFR_DEFAULT_DATA
*FirstDefaultValueData
;
3700 IFR_DEFAULT_DATA
*SecondDefaultValueData
;
3701 UINT32
*FirstDefaultValue
;
3702 UINT32
*SecondDefaultValue
;
3704 UINT64 ShiftedValue
;
3707 FirstListEntry
= &FirstBlock
->DefaultValueEntry
;
3708 for (FirstDefaultLink
= FirstListEntry
->ForwardLink
; FirstDefaultLink
!= FirstListEntry
; FirstDefaultLink
= FirstDefaultLink
->ForwardLink
) {
3709 FirstDefaultValueData
= BASE_CR (FirstDefaultLink
, IFR_DEFAULT_DATA
, Entry
);
3710 SecondListEntry
= &SecondBlock
->DefaultValueEntry
;
3711 for (SecondDefaultLink
= SecondListEntry
->ForwardLink
; SecondDefaultLink
!= SecondListEntry
; SecondDefaultLink
= SecondDefaultLink
->ForwardLink
) {
3712 SecondDefaultValueData
= BASE_CR (SecondDefaultLink
, IFR_DEFAULT_DATA
, Entry
);
3713 if (FirstDefaultValueData
->DefaultId
!= SecondDefaultValueData
->DefaultId
) {
3717 // Find default value with same default id in the two blocks.
3718 // Note: Default value for bit field question is stored as UINT32 type.
3720 FirstDefaultValue
= &FirstDefaultValueData
->Value
.u32
;
3721 SecondDefaultValue
= &SecondDefaultValueData
->Value
.u32
;
3723 // 1. Get the default value of the whole blcok that can just cover FirstBlock and SecondBlock.
3724 // 2. Get the default value of FirstBlock and SecondBlock form the value of whole block based
3725 // on the offset and width of FirstBlock and SecondBlock.
3727 if (FirstBlock
->Offset
> SecondBlock
->Offset
) {
3728 OffsetShift
= FirstBlock
->Offset
- SecondBlock
->Offset
;
3729 ShiftedValue
= LShiftU64 ((UINT64
) (*FirstDefaultValue
), OffsetShift
* 8);
3730 TotalValue
= ShiftedValue
| (UINT64
) (*SecondDefaultValue
);
3731 *SecondDefaultValue
= (UINT32
) BitFieldRead64 (TotalValue
, 0, SecondBlock
->Width
* 8 -1);
3732 *FirstDefaultValue
= (UINT32
) BitFieldRead64 (TotalValue
, OffsetShift
* 8, OffsetShift
* 8 + FirstBlock
->Width
*8 -1);
3734 OffsetShift
= SecondBlock
->Offset
-FirstBlock
->Offset
;
3735 ShiftedValue
= LShiftU64 ((UINT64
) (*SecondDefaultValue
), OffsetShift
* 8);
3736 TotalValue
= ShiftedValue
| (UINT64
) (*FirstDefaultValue
);
3737 *FirstDefaultValue
= (UINT32
) BitFieldRead64 (TotalValue
, 0, FirstBlock
->Width
* 8 -1);
3738 *SecondDefaultValue
= (UINT32
) BitFieldRead64 (TotalValue
, OffsetShift
* 8, OffsetShift
* 8 + SecondBlock
->Width
*8 -1);
3746 Update the default value in the block data which used as Bit VarStore
3748 @param BlockLink The Link of the block data.
3752 UpdateBlockDataArray (
3753 IN LIST_ENTRY
*BlockLink
3757 LIST_ENTRY
*TempLink
;
3758 IFR_BLOCK_DATA
*BlockData
;
3759 IFR_BLOCK_DATA
*NextBlockData
;
3762 // 1. Update default value in BitVar block data.
3763 // Sine some block datas are used as BitVarStore, then the default value recored in the block
3764 // is for related bit field in the block. so we need to set the default value to the related bit
3765 // fields in the block data if the block data is used as bit varstore, then the default value of
3766 // the block will be updated.
3768 UpdateDefaultValue (BlockLink
);
3771 // 2.Update default value for overlap BitVar blcok datas.
3772 // For block datas have overlap region, we need to merge the default value in different blocks.
3774 for (Link
= BlockLink
->ForwardLink
; Link
!= BlockLink
; Link
= Link
->ForwardLink
) {
3775 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
3776 if (!BlockData
->IsBitVar
) {
3779 for (TempLink
= Link
->ForwardLink
; TempLink
!= BlockLink
; TempLink
= TempLink
->ForwardLink
) {
3780 NextBlockData
= BASE_CR (TempLink
, IFR_BLOCK_DATA
, Entry
);
3781 if (!NextBlockData
->IsBitVar
|| NextBlockData
->Offset
>= BlockData
->Offset
+ BlockData
->Width
|| BlockData
->Offset
>= NextBlockData
->Offset
+ NextBlockData
->Width
) {
3785 // Find two blocks are used as bit VarStore and have overlap region, so need to merge default value of these two blocks.
3787 MergeBlockDefaultValue (BlockData
, NextBlockData
);
3793 Generate ConfigAltResp string base on the varstore info.
3795 @param HiiHandle Hii Handle for this hii package.
3796 @param ConfigHdr The config header for this varstore.
3797 @param VarStorageData The varstore info.
3798 @param DefaultIdArray The Default id array.
3799 @param DefaultAltCfgResp The DefaultAltCfgResp info may be return.
3801 @retval TRUE Need to continue
3802 @retval Others NO need to continue or error occur.
3805 GenerateAltConfigResp (
3806 IN EFI_HII_HANDLE HiiHandle
,
3807 IN CHAR16
*ConfigHdr
,
3808 IN IFR_VARSTORAGE_DATA
*VarStorageData
,
3809 IN IFR_DEFAULT_DATA
*DefaultIdArray
,
3810 IN OUT EFI_STRING
*DefaultAltCfgResp
3816 LIST_ENTRY
*LinkData
;
3817 LIST_ENTRY
*LinkDefault
;
3818 LIST_ENTRY
*ListEntry
;
3820 IFR_BLOCK_DATA
*BlockData
;
3821 IFR_DEFAULT_DATA
*DefaultId
;
3822 IFR_DEFAULT_DATA
*DefaultValueData
;
3825 CHAR16
*DefaultString
;
3830 DefaultString
= NULL
;
3832 // Add length for <ConfigHdr> + '\0'
3834 Length
= StrLen (ConfigHdr
) + 1;
3836 UpdateBlockDataArray (&VarStorageData
->BlockEntry
);
3838 for (Link
= DefaultIdArray
->Entry
.ForwardLink
; Link
!= &DefaultIdArray
->Entry
; Link
= Link
->ForwardLink
) {
3839 DefaultId
= BASE_CR (Link
, IFR_DEFAULT_DATA
, Entry
);
3841 // Add length for "&<ConfigHdr>&ALTCFG=XXXX"
3842 // |1| StrLen (ConfigHdr) | 8 | 4 |
3844 Length
+= (1 + StrLen (ConfigHdr
) + 8 + 4);
3846 for (LinkData
= VarStorageData
->BlockEntry
.ForwardLink
; LinkData
!= &VarStorageData
->BlockEntry
; LinkData
= LinkData
->ForwardLink
) {
3847 BlockData
= BASE_CR (LinkData
, IFR_BLOCK_DATA
, Entry
);
3848 ListEntry
= &BlockData
->DefaultValueEntry
;
3849 for (LinkDefault
= ListEntry
->ForwardLink
; LinkDefault
!= ListEntry
; LinkDefault
= LinkDefault
->ForwardLink
) {
3850 DefaultValueData
= BASE_CR (LinkDefault
, IFR_DEFAULT_DATA
, Entry
);
3851 if (DefaultValueData
->DefaultId
!= DefaultId
->DefaultId
) {
3854 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3856 // Add length for "&Name1=zzzzzzzzzzzz"
3859 Length
+= (1 + StrLen (BlockData
->Name
) + 1 + BlockData
->Width
* 2);
3862 // Add length for "&OFFSET=XXXX&WIDTH=YYYY&VALUE=zzzzzzzzzzzz"
3863 // | 8 | 4 | 7 | 4 | 7 | Width * 2 |
3865 Length
+= (8 + 4 + 7 + 4 + 7 + BlockData
->Width
* 2);
3873 // No default value is found. The default string doesn't exist.
3880 // Allocate buffer for the entire <DefaultAltCfgResp>
3882 *DefaultAltCfgResp
= AllocateZeroPool (Length
* sizeof (CHAR16
));
3883 if (*DefaultAltCfgResp
== NULL
) {
3884 return EFI_OUT_OF_RESOURCES
;
3886 StringPtr
= *DefaultAltCfgResp
;
3889 // Start with <ConfigHdr>
3891 StrCpyS (StringPtr
, Length
, ConfigHdr
);
3892 StringPtr
+= StrLen (StringPtr
);
3894 for (Link
= DefaultIdArray
->Entry
.ForwardLink
; Link
!= &DefaultIdArray
->Entry
; Link
= Link
->ForwardLink
) {
3895 DefaultId
= BASE_CR (Link
, IFR_DEFAULT_DATA
, Entry
);
3897 // Add <AltConfigHdr> of the form "&<ConfigHdr>&ALTCFG=XXXX\0"
3898 // |1| StrLen (ConfigHdr) | 8 | 4 |
3902 (1 + StrLen (ConfigHdr
) + 8 + 4 + 1) * sizeof (CHAR16
),
3905 DefaultId
->DefaultId
3907 StringPtr
+= StrLen (StringPtr
);
3909 for (LinkData
= VarStorageData
->BlockEntry
.ForwardLink
; LinkData
!= &VarStorageData
->BlockEntry
; LinkData
= LinkData
->ForwardLink
) {
3910 BlockData
= BASE_CR (LinkData
, IFR_BLOCK_DATA
, Entry
);
3911 ListEntry
= &BlockData
->DefaultValueEntry
;
3912 for (LinkDefault
= ListEntry
->ForwardLink
; LinkDefault
!= ListEntry
; LinkDefault
= LinkDefault
->ForwardLink
) {
3913 DefaultValueData
= BASE_CR (LinkDefault
, IFR_DEFAULT_DATA
, Entry
);
3914 if (DefaultValueData
->DefaultId
!= DefaultId
->DefaultId
) {
3917 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3920 (1 + StrLen (ConfigHdr
) + 1) * sizeof (CHAR16
),
3924 StringPtr
+= StrLen (StringPtr
);
3927 // Add <BlockConfig>
3928 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>
3932 (8 + 4 + 7 + 4 + 7 + 1) * sizeof (CHAR16
),
3933 L
"&OFFSET=%04X&WIDTH=%04X&VALUE=",
3937 StringPtr
+= StrLen (StringPtr
);
3939 Width
= BlockData
->Width
;
3941 // Convert Value to a hex string in "%x" format
3942 // NOTE: This is in the opposite byte that GUID and PATH use
3944 if (BlockData
->OpCode
== EFI_IFR_STRING_OP
){
3945 DefaultString
= InternalGetString(HiiHandle
, DefaultValueData
->Value
.string
);
3946 TmpBuffer
= AllocateZeroPool (Width
);
3947 ASSERT (TmpBuffer
!= NULL
);
3948 if (DefaultString
!= NULL
) {
3949 StrSize
= StrLen(DefaultString
)* sizeof (CHAR16
);
3950 if (StrSize
> Width
) {
3953 CopyMem (TmpBuffer
, (UINT8
*) DefaultString
, StrSize
);
3956 TmpBuffer
= (UINT8
*) &(DefaultValueData
->Value
);
3958 for (; Width
> 0 && (TmpBuffer
!= NULL
); Width
--) {
3959 UnicodeValueToStringS (
3961 Length
* sizeof (CHAR16
) - ((UINTN
)StringPtr
- (UINTN
)*DefaultAltCfgResp
),
3962 PREFIX_ZERO
| RADIX_HEX
,
3963 TmpBuffer
[Width
- 1],
3966 StringPtr
+= StrnLenS (StringPtr
, Length
- ((UINTN
)StringPtr
- (UINTN
)*DefaultAltCfgResp
) / sizeof (CHAR16
));
3968 if (DefaultString
!= NULL
){
3969 FreePool(DefaultString
);
3970 DefaultString
= NULL
;
3972 if (BlockData
->OpCode
== EFI_IFR_STRING_OP
&& TmpBuffer
!= NULL
) {
3973 FreePool(TmpBuffer
);
3980 HiiToLower (*DefaultAltCfgResp
);
3986 This function gets the full request string and full default value string by
3987 parsing IFR data in HII form packages.
3989 When Request points to NULL string, the request string and default value string
3990 for each varstore in form package will return.
3992 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
3993 @param DevicePath Device Path which Hii Config Access Protocol is registered.
3994 @param Request Pointer to a null-terminated Unicode string in
3995 <ConfigRequest> format. When it doesn't contain
3996 any RequestElement, it will be updated to return
3997 the full RequestElement retrieved from IFR data.
3998 If it points to NULL, the request string for the first
3999 varstore in form package will be merged into a
4000 <MultiConfigRequest> format string and return.
4001 @param AltCfgResp Pointer to a null-terminated Unicode string in
4002 <ConfigAltResp> format. When the pointer is to NULL,
4003 the full default value string retrieved from IFR data
4004 will return. When the pinter is to a string, the
4005 full default value string retrieved from IFR data
4006 will be merged into the input string and return.
4007 When Request points to NULL, the default value string
4008 for each varstore in form package will be merged into
4009 a <MultiConfigAltResp> format string and return.
4010 @param PointerProgress Optional parameter, it can be NULL.
4011 When it is not NULL, if Request is NULL, it returns NULL.
4012 On return, points to a character in the Request
4013 string. Points to the string's null terminator if
4014 request was successful. Points to the most recent
4015 & before the first failing name / value pair (or
4016 the beginning of the string if the failure is in
4017 the first name / value pair) if the request was
4019 @retval EFI_SUCCESS The Results string is set to the full request string.
4020 And AltCfgResp contains all default value string.
4021 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
4022 @retval EFI_NOT_FOUND The varstore (Guid and Name) in Request string
4023 can't be found in Form package.
4024 @retval EFI_NOT_FOUND HiiPackage can't be got on the input HiiHandle.
4025 @retval EFI_INVALID_PARAMETER Request points to NULL.
4030 GetFullStringFromHiiFormPackages (
4031 IN HII_DATABASE_RECORD
*DataBaseRecord
,
4032 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
4033 IN OUT EFI_STRING
*Request
,
4034 IN OUT EFI_STRING
*AltCfgResp
,
4035 OUT EFI_STRING
*PointerProgress OPTIONAL
4039 UINT8
*HiiFormPackage
;
4041 IFR_BLOCK_DATA
*RequestBlockArray
;
4042 IFR_BLOCK_DATA
*BlockData
;
4043 IFR_DEFAULT_DATA
*DefaultValueData
;
4044 IFR_DEFAULT_DATA
*DefaultId
;
4045 IFR_DEFAULT_DATA
*DefaultIdArray
;
4046 IFR_VARSTORAGE_DATA
*VarStorageData
;
4047 EFI_STRING DefaultAltCfgResp
;
4048 EFI_STRING ConfigHdr
;
4049 EFI_STRING StringPtr
;
4050 EFI_STRING Progress
;
4052 if (DataBaseRecord
== NULL
|| DevicePath
== NULL
|| Request
== NULL
|| AltCfgResp
== NULL
) {
4053 return EFI_INVALID_PARAMETER
;
4057 // Initialize the local variables.
4059 RequestBlockArray
= NULL
;
4060 DefaultIdArray
= NULL
;
4061 VarStorageData
= NULL
;
4062 DefaultAltCfgResp
= NULL
;
4064 HiiFormPackage
= NULL
;
4066 Progress
= *Request
;
4068 Status
= GetFormPackageData (DataBaseRecord
, &HiiFormPackage
, &PackageSize
);
4069 if (EFI_ERROR (Status
)) {
4074 // 1. Get the request block array by Request String when Request string contains the block array.
4077 if (*Request
!= NULL
) {
4078 StringPtr
= *Request
;
4082 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
4083 Status
= EFI_INVALID_PARAMETER
;
4086 StringPtr
+= StrLen (L
"GUID=");
4087 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&NAME=", StrLen (L
"&NAME=")) != 0) {
4090 if (*StringPtr
== L
'\0') {
4091 Status
= EFI_INVALID_PARAMETER
;
4094 StringPtr
+= StrLen (L
"&NAME=");
4095 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&PATH=", StrLen (L
"&PATH=")) != 0) {
4098 if (*StringPtr
== L
'\0') {
4099 Status
= EFI_INVALID_PARAMETER
;
4102 StringPtr
+= StrLen (L
"&PATH=");
4103 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
4107 if (*StringPtr
== L
'\0') {
4109 // No request block is found.
4116 // If StringPtr != NULL, get the request elements.
4118 if (StringPtr
!= NULL
) {
4119 if (StrStr (StringPtr
, L
"&OFFSET=") != NULL
) {
4120 RequestBlockArray
= GetBlockElement(StringPtr
, &Progress
);
4122 RequestBlockArray
= GetNameElement(StringPtr
, &Progress
);
4125 if (RequestBlockArray
== NULL
) {
4126 Status
= EFI_INVALID_PARAMETER
;
4132 // Initialize DefaultIdArray to store the map between DeaultId and DefaultName
4134 DefaultIdArray
= (IFR_DEFAULT_DATA
*) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
4135 if (DefaultIdArray
== NULL
) {
4136 Status
= EFI_OUT_OF_RESOURCES
;
4139 InitializeListHead (&DefaultIdArray
->Entry
);
4142 // Initialize VarStorageData to store the var store Block and Default value information.
4144 VarStorageData
= (IFR_VARSTORAGE_DATA
*) AllocateZeroPool (sizeof (IFR_VARSTORAGE_DATA
));
4145 if (VarStorageData
== NULL
) {
4146 Status
= EFI_OUT_OF_RESOURCES
;
4149 InitializeListHead (&VarStorageData
->Entry
);
4150 InitializeListHead (&VarStorageData
->BlockEntry
);
4153 // 2. Parse FormPackage to get BlockArray and DefaultId Array for the request BlockArray.
4157 // Parse the opcode in form package to get the default setting.
4159 Status
= ParseIfrData (DataBaseRecord
->Handle
,
4161 (UINT32
) PackageSize
,
4166 if (EFI_ERROR (Status
)) {
4171 // No requested varstore in IFR data and directly return
4173 if (VarStorageData
->Type
== 0 && VarStorageData
->Name
== NULL
) {
4174 Status
= EFI_SUCCESS
;
4179 // 3. Construct Request Element (Block Name) for 2.1 and 2.2 case.
4181 Status
= GenerateHdr (VarStorageData
, DevicePath
, &ConfigHdr
);
4182 if (EFI_ERROR (Status
)) {
4186 if (RequestBlockArray
== NULL
) {
4187 if (!GenerateConfigRequest(ConfigHdr
, VarStorageData
, &Status
, Request
)) {
4193 // 4. Construct Default Value string in AltResp according to request element.
4194 // Go through all VarStorageData Entry and get the DefaultId array for each one
4195 // Then construct them all to : ConfigHdr AltConfigHdr ConfigBody AltConfigHdr ConfigBody
4197 Status
= GenerateAltConfigResp (DataBaseRecord
->Handle
,ConfigHdr
, VarStorageData
, DefaultIdArray
, &DefaultAltCfgResp
);
4198 if (EFI_ERROR (Status
)) {
4203 // 5. Merge string into the input AltCfgResp if the input *AltCfgResp is not NULL.
4205 if (*AltCfgResp
!= NULL
&& DefaultAltCfgResp
!= NULL
) {
4206 Status
= MergeDefaultString (AltCfgResp
, DefaultAltCfgResp
);
4207 FreePool (DefaultAltCfgResp
);
4208 } else if (*AltCfgResp
== NULL
) {
4209 *AltCfgResp
= DefaultAltCfgResp
;
4213 if (RequestBlockArray
!= NULL
) {
4215 // Free Link Array RequestBlockArray
4217 while (!IsListEmpty (&RequestBlockArray
->Entry
)) {
4218 BlockData
= BASE_CR (RequestBlockArray
->Entry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
4219 RemoveEntryList (&BlockData
->Entry
);
4220 if (BlockData
->Name
!= NULL
) {
4221 FreePool (BlockData
->Name
);
4223 FreePool (BlockData
);
4226 FreePool (RequestBlockArray
);
4229 if (VarStorageData
!= NULL
) {
4231 // Free link array VarStorageData
4233 while (!IsListEmpty (&VarStorageData
->BlockEntry
)) {
4234 BlockData
= BASE_CR (VarStorageData
->BlockEntry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
4235 RemoveEntryList (&BlockData
->Entry
);
4236 if (BlockData
->Name
!= NULL
) {
4237 FreePool (BlockData
->Name
);
4240 // Free default value link array
4242 while (!IsListEmpty (&BlockData
->DefaultValueEntry
)) {
4243 DefaultValueData
= BASE_CR (BlockData
->DefaultValueEntry
.ForwardLink
, IFR_DEFAULT_DATA
, Entry
);
4244 RemoveEntryList (&DefaultValueData
->Entry
);
4245 FreePool (DefaultValueData
);
4247 FreePool (BlockData
);
4249 if (VarStorageData
->Name
!= NULL
) {
4250 FreePool (VarStorageData
->Name
);
4251 VarStorageData
->Name
= NULL
;
4253 FreePool (VarStorageData
);
4256 if (DefaultIdArray
!= NULL
) {
4258 // Free DefaultId Array
4260 while (!IsListEmpty (&DefaultIdArray
->Entry
)) {
4261 DefaultId
= BASE_CR (DefaultIdArray
->Entry
.ForwardLink
, IFR_DEFAULT_DATA
, Entry
);
4262 RemoveEntryList (&DefaultId
->Entry
);
4263 FreePool (DefaultId
);
4265 FreePool (DefaultIdArray
);
4269 // Free the allocated string
4271 if (ConfigHdr
!= NULL
) {
4272 FreePool (ConfigHdr
);
4276 // Free Package data
4278 if (HiiFormPackage
!= NULL
) {
4279 FreePool (HiiFormPackage
);
4282 if (PointerProgress
!= NULL
) {
4283 if (*Request
== NULL
) {
4284 *PointerProgress
= NULL
;
4285 } else if (EFI_ERROR (Status
)) {
4286 *PointerProgress
= *Request
;
4288 *PointerProgress
= *Request
+ StrLen (*Request
);
4296 This function gets the full request resp string by
4297 parsing IFR data in HII form packages.
4299 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
4301 @param EfiVarStoreInfo The efi varstore info which is save in the EFI
4302 varstore data structure.
4303 @param Request Pointer to a null-terminated Unicode string in
4304 <ConfigRequest> format.
4305 @param RequestResp Pointer to a null-terminated Unicode string in
4306 <ConfigResp> format.
4307 @param AccessProgress On return, points to a character in the Request
4308 string. Points to the string's null terminator if
4309 request was successful. Points to the most recent
4310 & before the first failing name / value pair (or
4311 the beginning of the string if the failure is in
4312 the first name / value pair) if the request was
4315 @retval EFI_SUCCESS The Results string is set to the full request string.
4316 And AltCfgResp contains all default value string.
4317 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
4318 @retval EFI_INVALID_PARAMETER Request points to NULL.
4322 GetConfigRespFromEfiVarStore (
4323 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
4324 IN EFI_IFR_VARSTORE_EFI
*EfiVarStoreInfo
,
4325 IN EFI_STRING Request
,
4326 OUT EFI_STRING
*RequestResp
,
4327 OUT EFI_STRING
*AccessProgress
4331 EFI_STRING VarStoreName
;
4336 Status
= EFI_SUCCESS
;
4339 VarStoreName
= NULL
;
4340 *AccessProgress
= Request
;
4342 NameSize
= AsciiStrSize ((CHAR8
*)EfiVarStoreInfo
->Name
);
4343 VarStoreName
= AllocateZeroPool (NameSize
* sizeof (CHAR16
));
4344 if (VarStoreName
== NULL
) {
4345 Status
= EFI_OUT_OF_RESOURCES
;
4348 AsciiStrToUnicodeStrS ((CHAR8
*) EfiVarStoreInfo
->Name
, VarStoreName
, NameSize
);
4351 Status
= gRT
->GetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, NULL
, &BufferSize
, NULL
);
4352 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
4356 VarStore
= AllocateZeroPool (BufferSize
);
4357 ASSERT (VarStore
!= NULL
);
4358 Status
= gRT
->GetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, NULL
, &BufferSize
, VarStore
);
4359 if (EFI_ERROR (Status
)) {
4363 Status
= HiiBlockToConfig(This
, Request
, VarStore
, BufferSize
, RequestResp
, AccessProgress
);
4364 if (EFI_ERROR (Status
)) {
4369 if (VarStoreName
!= NULL
) {
4370 FreePool (VarStoreName
);
4373 if (VarStore
!= NULL
) {
4374 FreePool (VarStore
);
4382 This function route the full request resp string for efi varstore.
4384 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
4386 @param EfiVarStoreInfo The efi varstore info which is save in the EFI
4387 varstore data structure.
4388 @param RequestResp Pointer to a null-terminated Unicode string in
4389 <ConfigResp> format.
4390 @param Result Pointer to a null-terminated Unicode string in
4391 <ConfigResp> format.
4393 @retval EFI_SUCCESS The Results string is set to the full request string.
4394 And AltCfgResp contains all default value string.
4395 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
4396 @retval EFI_INVALID_PARAMETER Request points to NULL.
4400 RouteConfigRespForEfiVarStore (
4401 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
4402 IN EFI_IFR_VARSTORE_EFI
*EfiVarStoreInfo
,
4403 IN EFI_STRING RequestResp
,
4404 OUT EFI_STRING
*Result
4408 EFI_STRING VarStoreName
;
4414 Status
= EFI_SUCCESS
;
4417 VarStoreName
= NULL
;
4418 *Result
= RequestResp
;
4420 NameSize
= AsciiStrSize ((CHAR8
*)EfiVarStoreInfo
->Name
);
4421 VarStoreName
= AllocateZeroPool (NameSize
* sizeof (CHAR16
));
4422 if (VarStoreName
== NULL
) {
4423 Status
= EFI_OUT_OF_RESOURCES
;
4426 AsciiStrToUnicodeStrS ((CHAR8
*) EfiVarStoreInfo
->Name
, VarStoreName
, NameSize
);
4428 Status
= gRT
->GetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, NULL
, &BufferSize
, NULL
);
4429 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
4430 DEBUG ((DEBUG_ERROR
, "The variable does not exist!"));
4434 BlockSize
= BufferSize
;
4435 VarStore
= AllocateZeroPool (BufferSize
);
4436 ASSERT (VarStore
!= NULL
);
4437 Status
= gRT
->GetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, NULL
, &BufferSize
, VarStore
);
4438 if (EFI_ERROR (Status
)) {
4442 Status
= HiiConfigToBlock(This
, RequestResp
, VarStore
, &BlockSize
, Result
);
4443 if (EFI_ERROR (Status
)) {
4447 Status
= gRT
->SetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, EfiVarStoreInfo
->Attributes
, BufferSize
, VarStore
);
4448 if (EFI_ERROR (Status
)) {
4449 *Result
= RequestResp
;
4454 if (VarStoreName
!= NULL
) {
4455 FreePool (VarStoreName
);
4458 if (VarStore
!= NULL
) {
4459 FreePool (VarStore
);
4466 Validate the config request elements.
4468 @param ConfigElements A null-terminated Unicode string in <ConfigRequest> format,
4469 without configHdr field.
4471 @retval CHAR16 * THE first Name/value pair not correct.
4472 @retval NULL Success parse the name/value pair
4475 OffsetWidthValidate (
4476 CHAR16
*ConfigElements
4482 StringPtr
= ConfigElements
;
4486 if (StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) != 0) {
4490 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
4493 if (*StringPtr
== L
'\0') {
4497 StringPtr
+= StrLen (L
"&WIDTH=");
4498 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) != 0) {
4502 if (*StringPtr
== L
'\0') {
4509 Validate the config request elements.
4511 @param ConfigElements A null-terminated Unicode string in <ConfigRequest> format,
4512 without configHdr field.
4514 @retval CHAR16 * THE first Name/value pair not correct.
4515 @retval NULL Success parse the name/value pair
4520 CHAR16
*ConfigElements
4526 StringPtr
= ConfigElements
;
4530 if (*StringPtr
!= L
'&') {
4535 StringPtr
= StrStr (StringPtr
, L
"&");
4537 if (StringPtr
== NULL
) {
4544 Validate the config request string.
4546 @param ConfigRequest A null-terminated Unicode string in <ConfigRequest> format.
4548 @retval CHAR16 * THE first element not correct.
4549 @retval NULL Success parse the name/value pair
4553 ConfigRequestValidate (
4554 CHAR16
*ConfigRequest
4557 BOOLEAN HasNameField
;
4560 HasNameField
= TRUE
;
4561 StringPtr
= ConfigRequest
;
4564 // Check <ConfigHdr>
4566 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
4567 return ConfigRequest
;
4569 StringPtr
+= StrLen (L
"GUID=");
4570 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&NAME=", StrLen (L
"&NAME=")) != 0) {
4573 if (*StringPtr
== L
'\0') {
4574 return ConfigRequest
;
4576 StringPtr
+= StrLen (L
"&NAME=");
4577 if (*StringPtr
== L
'&') {
4578 HasNameField
= FALSE
;
4580 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&PATH=", StrLen (L
"&PATH=")) != 0) {
4583 if (*StringPtr
== L
'\0') {
4584 return ConfigRequest
;
4586 StringPtr
+= StrLen (L
"&PATH=");
4587 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
4591 if (*StringPtr
== L
'\0') {
4597 // Should be Buffer varstore, config request should be "OFFSET/Width" pairs.
4599 return OffsetWidthValidate(StringPtr
);
4602 // Should be Name/Value varstore, config request should be "&name1&name2..." pairs.
4604 return NameValueValidate(StringPtr
);
4609 This function allows a caller to extract the current configuration
4610 for one or more named elements from one or more drivers.
4612 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
4614 @param Request A null-terminated Unicode string in
4615 <MultiConfigRequest> format.
4616 @param Progress On return, points to a character in the Request
4617 string. Points to the string's null terminator if
4618 request was successful. Points to the most recent
4619 & before the first failing name / value pair (or
4620 the beginning of the string if the failure is in
4621 the first name / value pair) if the request was
4623 @param Results Null-terminated Unicode string in
4624 <MultiConfigAltResp> format which has all values
4625 filled in for the names in the Request string.
4626 String to be allocated by the called function.
4628 @retval EFI_SUCCESS The Results string is filled with the values
4629 corresponding to all requested names.
4630 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
4631 results that must be stored awaiting possible
4633 @retval EFI_NOT_FOUND Routing data doesn't match any known driver.
4634 Progress set to the "G" in "GUID" of the routing
4635 header that doesn't match. Note: There is no
4636 requirement that all routing data be validated
4637 before any configuration extraction.
4638 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Request
4639 parameter would result in this type of error. The
4640 Progress parameter is set to NULL.
4641 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set to most recent &
4642 before the error or the beginning of the string.
4643 @retval EFI_INVALID_PARAMETER The ExtractConfig function of the underlying HII
4644 Configuration Access Protocol returned
4645 EFI_INVALID_PARAMETER. Progress set to most recent
4646 & before the error or the beginning of the string.
4651 HiiConfigRoutingExtractConfig (
4652 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
4653 IN CONST EFI_STRING Request
,
4654 OUT EFI_STRING
*Progress
,
4655 OUT EFI_STRING
*Results
4658 HII_DATABASE_PRIVATE_DATA
*Private
;
4659 EFI_STRING StringPtr
;
4660 EFI_STRING ConfigRequest
;
4662 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
4663 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
4666 HII_DATABASE_RECORD
*Database
;
4667 UINT8
*DevicePathPkg
;
4668 UINT8
*CurrentDevicePath
;
4669 EFI_HANDLE DriverHandle
;
4670 EFI_HII_HANDLE HiiHandle
;
4671 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
4672 EFI_STRING AccessProgress
;
4673 EFI_STRING AccessResults
;
4674 EFI_STRING AccessProgressBackup
;
4675 EFI_STRING AccessResultsBackup
;
4676 EFI_STRING DefaultResults
;
4677 BOOLEAN FirstElement
;
4678 BOOLEAN IfrDataParsedFlag
;
4679 BOOLEAN IsEfiVarStore
;
4680 EFI_IFR_VARSTORE_EFI
*EfiVarStoreInfo
;
4681 EFI_STRING ErrorPtr
;
4682 UINTN DevicePathSize
;
4683 UINTN ConigStringSize
;
4684 UINTN ConigStringSizeNewsize
;
4685 EFI_STRING ConfigStringPtr
;
4687 if (This
== NULL
|| Progress
== NULL
|| Results
== NULL
) {
4688 return EFI_INVALID_PARAMETER
;
4691 if (Request
== NULL
) {
4693 return EFI_INVALID_PARAMETER
;
4696 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
4697 StringPtr
= Request
;
4698 *Progress
= StringPtr
;
4699 DefaultResults
= NULL
;
4700 ConfigRequest
= NULL
;
4701 Status
= EFI_SUCCESS
;
4702 AccessResults
= NULL
;
4703 AccessProgress
= NULL
;
4704 AccessResultsBackup
= NULL
;
4705 AccessProgressBackup
= NULL
;
4707 IfrDataParsedFlag
= FALSE
;
4708 IsEfiVarStore
= FALSE
;
4709 EfiVarStoreInfo
= NULL
;
4712 // The first element of <MultiConfigRequest> should be
4713 // <GuidHdr>, which is in 'GUID='<Guid> syntax.
4715 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
4716 return EFI_INVALID_PARAMETER
;
4719 FirstElement
= TRUE
;
4722 // Allocate a fix length of memory to store Results. Reallocate memory for
4723 // Results if this fix length is insufficient.
4725 *Results
= (EFI_STRING
) AllocateZeroPool (MAX_STRING_LENGTH
);
4726 if (*Results
== NULL
) {
4727 return EFI_OUT_OF_RESOURCES
;
4730 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) == 0) {
4732 // If parsing error, set Progress to the beginning of the <MultiConfigRequest>
4733 // or most recent & before the error.
4735 if (StringPtr
== Request
) {
4736 *Progress
= StringPtr
;
4738 *Progress
= StringPtr
- 1;
4742 // Process each <ConfigRequest> of <MultiConfigRequest>
4744 Length
= CalculateConfigStringLen (StringPtr
);
4745 ConfigRequest
= AllocateCopyPool ((Length
+ 1) * sizeof (CHAR16
), StringPtr
);
4746 if (ConfigRequest
== NULL
) {
4747 Status
= EFI_OUT_OF_RESOURCES
;
4750 *(ConfigRequest
+ Length
) = 0;
4753 // Get the UEFI device path
4755 Status
= GetDevicePath (ConfigRequest
, (UINT8
**) &DevicePath
);
4756 if (EFI_ERROR (Status
)) {
4761 // Find driver which matches the routing data.
4763 DriverHandle
= NULL
;
4766 for (Link
= Private
->DatabaseList
.ForwardLink
;
4767 Link
!= &Private
->DatabaseList
;
4768 Link
= Link
->ForwardLink
4770 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
4771 if ((DevicePathPkg
= Database
->PackageList
->DevicePathPkg
) != NULL
) {
4772 CurrentDevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
4773 DevicePathSize
= GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) CurrentDevicePath
);
4774 if ((CompareMem (DevicePath
,CurrentDevicePath
,DevicePathSize
) == 0) && IsThisPackageList(Database
, ConfigRequest
)) {
4775 DriverHandle
= Database
->DriverHandle
;
4776 HiiHandle
= Database
->Handle
;
4783 // Try to find driver handle by device path.
4785 if (DriverHandle
== NULL
) {
4786 TempDevicePath
= DevicePath
;
4787 Status
= gBS
->LocateDevicePath (
4788 &gEfiDevicePathProtocolGuid
,
4792 if (EFI_ERROR (Status
) || (DriverHandle
== NULL
)) {
4794 // Routing data does not match any known driver.
4795 // Set Progress to the 'G' in "GUID" of the routing header.
4797 *Progress
= StringPtr
;
4798 Status
= EFI_NOT_FOUND
;
4804 // Validate ConfigRequest String.
4806 ErrorPtr
= ConfigRequestValidate(ConfigRequest
);
4807 if (ErrorPtr
!= NULL
) {
4808 *Progress
= StrStr (StringPtr
, ErrorPtr
);
4809 Status
= EFI_INVALID_PARAMETER
;
4814 // Check whether ConfigRequest contains request string.
4816 IfrDataParsedFlag
= FALSE
;
4817 if ((HiiHandle
!= NULL
) && !GetElementsFromRequest(ConfigRequest
)) {
4819 // Get the full request string from IFR when HiiPackage is registered to HiiHandle
4821 IfrDataParsedFlag
= TRUE
;
4822 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &ConfigRequest
, &DefaultResults
, &AccessProgress
);
4823 if (EFI_ERROR (Status
)) {
4825 // AccessProgress indicates the parsing progress on <ConfigRequest>.
4826 // Map it to the progress on <MultiConfigRequest> then return it.
4828 ASSERT (AccessProgress
!= NULL
);
4829 *Progress
= StrStr (StringPtr
, AccessProgress
);
4833 // Not any request block is found.
4835 if (!GetElementsFromRequest(ConfigRequest
)) {
4836 AccessResults
= AllocateCopyPool (StrSize (ConfigRequest
), ConfigRequest
);
4837 goto NextConfigString
;
4842 // Check whether this ConfigRequest is search from Efi varstore type storage.
4844 Status
= GetVarStoreType(Database
, ConfigRequest
, &IsEfiVarStore
, &EfiVarStoreInfo
);
4845 if (EFI_ERROR (Status
)) {
4849 if (IsEfiVarStore
) {
4851 // Call the GetVariable function to extract settings.
4853 Status
= GetConfigRespFromEfiVarStore(This
, EfiVarStoreInfo
, ConfigRequest
, &AccessResults
, &AccessProgress
);
4854 FreePool (EfiVarStoreInfo
);
4855 if (EFI_ERROR (Status
)) {
4857 // AccessProgress indicates the parsing progress on <ConfigRequest>.
4858 // Map it to the progress on <MultiConfigRequest> then return it.
4860 *Progress
= StrStr (StringPtr
, AccessProgress
);
4865 // For EfiVarstore, call corresponding ConfigAccess protocol to get the AltCfgResp from driver.
4867 Status
= gBS
->HandleProtocol (
4869 &gEfiHiiConfigAccessProtocolGuid
,
4870 (VOID
**) &ConfigAccess
4872 if (EFI_ERROR (Status
)) {
4874 // The driver has EfiVarStore, may not install ConfigAccess protocol.
4875 // So ignore the error status in this case.
4877 Status
= EFI_SUCCESS
;
4879 Status
= ConfigAccess
->ExtractConfig (
4882 &AccessProgressBackup
,
4883 &AccessResultsBackup
4885 if (!EFI_ERROR(Status
)) {
4887 //Merge the AltCfgResp in AccessResultsBackup to AccessResults
4889 if ((AccessResultsBackup
!= NULL
) && (StrStr (AccessResultsBackup
, L
"&ALTCFG=") != NULL
)) {
4890 ConigStringSize
= StrSize (AccessResults
);
4891 ConfigStringPtr
= StrStr (AccessResultsBackup
, L
"&GUID=");
4892 ConigStringSizeNewsize
= StrSize (ConfigStringPtr
) + ConigStringSize
+ sizeof (CHAR16
);
4893 AccessResults
= (EFI_STRING
) ReallocatePool (
4895 ConigStringSizeNewsize
,
4897 StrCatS (AccessResults
, ConigStringSizeNewsize
/ sizeof (CHAR16
), ConfigStringPtr
);
4901 // In the ExtractConfig function of some driver may not support EfiVarStore,
4902 // may return error status, just ignore the error status in this case.
4904 Status
= EFI_SUCCESS
;
4906 if (AccessResultsBackup
!= NULL
) {
4907 FreePool (AccessResultsBackup
);
4908 AccessResultsBackup
= NULL
;
4913 // Call corresponding ConfigAccess protocol to extract settings
4915 Status
= gBS
->HandleProtocol (
4917 &gEfiHiiConfigAccessProtocolGuid
,
4918 (VOID
**) &ConfigAccess
4920 if (EFI_ERROR (Status
)) {
4924 Status
= ConfigAccess
->ExtractConfig (
4931 if (EFI_ERROR (Status
)) {
4933 // AccessProgress indicates the parsing progress on <ConfigRequest>.
4934 // Map it to the progress on <MultiConfigRequest> then return it.
4936 *Progress
= StrStr (StringPtr
, AccessProgress
);
4941 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'
4942 // which separates the first <ConfigAltResp> and the following ones.
4944 ASSERT (*AccessProgress
== 0);
4947 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
4949 if (!IfrDataParsedFlag
&& HiiHandle
!= NULL
) {
4950 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &ConfigRequest
, &DefaultResults
, NULL
);
4951 ASSERT_EFI_ERROR (Status
);
4954 FreePool (DevicePath
);
4957 if (DefaultResults
!= NULL
) {
4958 Status
= MergeDefaultString (&AccessResults
, DefaultResults
);
4959 ASSERT_EFI_ERROR (Status
);
4960 FreePool (DefaultResults
);
4961 DefaultResults
= NULL
;
4965 if (!FirstElement
) {
4966 Status
= AppendToMultiString (Results
, L
"&");
4967 ASSERT_EFI_ERROR (Status
);
4970 Status
= AppendToMultiString (Results
, AccessResults
);
4971 ASSERT_EFI_ERROR (Status
);
4973 FirstElement
= FALSE
;
4975 FreePool (AccessResults
);
4976 AccessResults
= NULL
;
4977 FreePool (ConfigRequest
);
4978 ConfigRequest
= NULL
;
4981 // Go to next <ConfigRequest> (skip '&').
4983 StringPtr
+= Length
;
4984 if (*StringPtr
== 0) {
4985 *Progress
= StringPtr
;
4993 if (EFI_ERROR (Status
)) {
4994 FreePool (*Results
);
4998 if (ConfigRequest
!= NULL
) {
4999 FreePool (ConfigRequest
);
5002 if (AccessResults
!= NULL
) {
5003 FreePool (AccessResults
);
5006 if (DefaultResults
!= NULL
) {
5007 FreePool (DefaultResults
);
5010 if (DevicePath
!= NULL
) {
5011 FreePool (DevicePath
);
5019 This function allows the caller to request the current configuration for the
5020 entirety of the current HII database and returns the data in a
5021 null-terminated Unicode string.
5023 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
5025 @param Results Null-terminated Unicode string in
5026 <MultiConfigAltResp> format which has all values
5027 filled in for the entirety of the current HII
5028 database. String to be allocated by the called
5029 function. De-allocation is up to the caller.
5031 @retval EFI_SUCCESS The Results string is filled with the values
5032 corresponding to all requested names.
5033 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
5034 results that must be stored awaiting possible
5036 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Results
5037 parameter would result in this type of error.
5042 HiiConfigRoutingExportConfig (
5043 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
5044 OUT EFI_STRING
*Results
5048 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
5049 EFI_STRING AccessResults
;
5050 EFI_STRING Progress
;
5051 EFI_STRING StringPtr
;
5052 EFI_STRING ConfigRequest
;
5054 EFI_HANDLE
*ConfigAccessHandles
;
5055 UINTN NumberConfigAccessHandles
;
5056 BOOLEAN FirstElement
;
5057 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
5058 EFI_HII_HANDLE HiiHandle
;
5059 EFI_STRING DefaultResults
;
5060 HII_DATABASE_PRIVATE_DATA
*Private
;
5062 HII_DATABASE_RECORD
*Database
;
5063 UINT8
*DevicePathPkg
;
5064 UINT8
*CurrentDevicePath
;
5065 BOOLEAN IfrDataParsedFlag
;
5067 if (This
== NULL
|| Results
== NULL
) {
5068 return EFI_INVALID_PARAMETER
;
5071 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
5074 // Allocate a fix length of memory to store Results. Reallocate memory for
5075 // Results if this fix length is insufficient.
5077 *Results
= (EFI_STRING
) AllocateZeroPool (MAX_STRING_LENGTH
);
5078 if (*Results
== NULL
) {
5079 return EFI_OUT_OF_RESOURCES
;
5082 NumberConfigAccessHandles
= 0;
5083 Status
= gBS
->LocateHandleBuffer (
5085 &gEfiHiiConfigAccessProtocolGuid
,
5087 &NumberConfigAccessHandles
,
5088 &ConfigAccessHandles
5090 if (EFI_ERROR (Status
)) {
5094 FirstElement
= TRUE
;
5096 for (Index
= 0; Index
< NumberConfigAccessHandles
; Index
++) {
5097 Status
= gBS
->HandleProtocol (
5098 ConfigAccessHandles
[Index
],
5099 &gEfiHiiConfigAccessProtocolGuid
,
5100 (VOID
**) &ConfigAccess
5102 if (EFI_ERROR (Status
)) {
5107 // Get DevicePath and HiiHandle for this ConfigAccess driver handle
5109 IfrDataParsedFlag
= FALSE
;
5112 DefaultResults
= NULL
;
5114 ConfigRequest
= NULL
;
5115 DevicePath
= DevicePathFromHandle (ConfigAccessHandles
[Index
]);
5116 if (DevicePath
!= NULL
) {
5117 for (Link
= Private
->DatabaseList
.ForwardLink
;
5118 Link
!= &Private
->DatabaseList
;
5119 Link
= Link
->ForwardLink
5121 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
5122 if ((DevicePathPkg
= Database
->PackageList
->DevicePathPkg
) != NULL
) {
5123 CurrentDevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
5127 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) CurrentDevicePath
)
5129 HiiHandle
= Database
->Handle
;
5136 Status
= ConfigAccess
->ExtractConfig (
5142 if (EFI_ERROR (Status
)) {
5144 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
5146 if (HiiHandle
!= NULL
&& DevicePath
!= NULL
) {
5147 IfrDataParsedFlag
= TRUE
;
5148 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &ConfigRequest
, &DefaultResults
, NULL
);
5150 // Get the full request string to get the Current setting again.
5152 if (!EFI_ERROR (Status
) && ConfigRequest
!= NULL
) {
5153 Status
= ConfigAccess
->ExtractConfig (
5159 FreePool (ConfigRequest
);
5161 Status
= EFI_NOT_FOUND
;
5166 if (!EFI_ERROR (Status
)) {
5168 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
5170 if (!IfrDataParsedFlag
&& HiiHandle
!= NULL
&& DevicePath
!= NULL
) {
5171 StringPtr
= StrStr (AccessResults
, L
"&GUID=");
5172 if (StringPtr
!= NULL
) {
5175 if (GetElementsFromRequest (AccessResults
)) {
5176 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &AccessResults
, &DefaultResults
, NULL
);
5177 ASSERT_EFI_ERROR (Status
);
5179 if (StringPtr
!= NULL
) {
5184 // Merge the default sting from IFR code into the got setting from driver.
5186 if (DefaultResults
!= NULL
) {
5187 Status
= MergeDefaultString (&AccessResults
, DefaultResults
);
5188 ASSERT_EFI_ERROR (Status
);
5189 FreePool (DefaultResults
);
5190 DefaultResults
= NULL
;
5194 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'
5195 // which separates the first <ConfigAltResp> and the following ones.
5197 if (!FirstElement
) {
5198 Status
= AppendToMultiString (Results
, L
"&");
5199 ASSERT_EFI_ERROR (Status
);
5202 Status
= AppendToMultiString (Results
, AccessResults
);
5203 ASSERT_EFI_ERROR (Status
);
5205 FirstElement
= FALSE
;
5207 FreePool (AccessResults
);
5208 AccessResults
= NULL
;
5211 FreePool (ConfigAccessHandles
);
5218 This function processes the results of processing forms and routes it to the
5219 appropriate handlers or storage.
5221 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
5223 @param Configuration A null-terminated Unicode string in
5224 <MulltiConfigResp> format.
5225 @param Progress A pointer to a string filled in with the offset of
5226 the most recent & before the first failing name /
5227 value pair (or the beginning of the string if the
5228 failure is in the first name / value pair) or the
5229 terminating NULL if all was successful.
5231 @retval EFI_SUCCESS The results have been distributed or are awaiting
5233 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
5234 results that must be stored awaiting possible
5236 @retval EFI_INVALID_PARAMETER Passing in a NULL for the Configuration parameter
5237 would result in this type of error.
5238 @retval EFI_NOT_FOUND Target for the specified routing data was not
5244 HiiConfigRoutingRouteConfig (
5245 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
5246 IN CONST EFI_STRING Configuration
,
5247 OUT EFI_STRING
*Progress
5250 HII_DATABASE_PRIVATE_DATA
*Private
;
5251 EFI_STRING StringPtr
;
5252 EFI_STRING ConfigResp
;
5255 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
5256 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
5258 HII_DATABASE_RECORD
*Database
;
5259 UINT8
*DevicePathPkg
;
5260 UINT8
*CurrentDevicePath
;
5261 EFI_HANDLE DriverHandle
;
5262 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
5263 EFI_STRING AccessProgress
;
5264 EFI_IFR_VARSTORE_EFI
*EfiVarStoreInfo
;
5265 BOOLEAN IsEfiVarstore
;
5266 UINTN DevicePathSize
;
5268 if (This
== NULL
|| Progress
== NULL
) {
5269 return EFI_INVALID_PARAMETER
;
5272 if (Configuration
== NULL
) {
5274 return EFI_INVALID_PARAMETER
;
5277 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
5278 StringPtr
= Configuration
;
5279 *Progress
= StringPtr
;
5281 AccessProgress
= NULL
;
5282 EfiVarStoreInfo
= NULL
;
5283 IsEfiVarstore
= FALSE
;
5286 // The first element of <MultiConfigResp> should be
5287 // <GuidHdr>, which is in 'GUID='<Guid> syntax.
5289 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
5290 return EFI_INVALID_PARAMETER
;
5293 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) == 0) {
5295 // If parsing error, set Progress to the beginning of the <MultiConfigResp>
5296 // or most recent & before the error.
5298 if (StringPtr
== Configuration
) {
5299 *Progress
= StringPtr
;
5301 *Progress
= StringPtr
- 1;
5305 // Process each <ConfigResp> of <MultiConfigResp>
5307 Length
= CalculateConfigStringLen (StringPtr
);
5308 ConfigResp
= AllocateCopyPool ((Length
+ 1) * sizeof (CHAR16
), StringPtr
);
5309 if (ConfigResp
== NULL
) {
5310 return EFI_OUT_OF_RESOURCES
;
5313 // Append '\0' to the end of ConfigRequest
5315 *(ConfigResp
+ Length
) = 0;
5318 // Get the UEFI device path
5320 Status
= GetDevicePath (ConfigResp
, (UINT8
**) &DevicePath
);
5321 if (EFI_ERROR (Status
)) {
5322 FreePool (ConfigResp
);
5327 // Find driver which matches the routing data.
5329 DriverHandle
= NULL
;
5330 for (Link
= Private
->DatabaseList
.ForwardLink
;
5331 Link
!= &Private
->DatabaseList
;
5332 Link
= Link
->ForwardLink
5334 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
5336 if ((DevicePathPkg
= Database
->PackageList
->DevicePathPkg
) != NULL
) {
5337 CurrentDevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
5338 DevicePathSize
= GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) CurrentDevicePath
);
5339 if ((CompareMem (DevicePath
,CurrentDevicePath
,DevicePathSize
) == 0) && IsThisPackageList(Database
, ConfigResp
)) {
5340 DriverHandle
= Database
->DriverHandle
;
5347 // Try to find driver handle by device path.
5349 if (DriverHandle
== NULL
) {
5350 TempDevicePath
= DevicePath
;
5351 Status
= gBS
->LocateDevicePath (
5352 &gEfiDevicePathProtocolGuid
,
5356 if (EFI_ERROR (Status
) || (DriverHandle
== NULL
)) {
5358 // Routing data does not match any known driver.
5359 // Set Progress to the 'G' in "GUID" of the routing header.
5361 FreePool (DevicePath
);
5362 *Progress
= StringPtr
;
5363 FreePool (ConfigResp
);
5364 return EFI_NOT_FOUND
;
5368 FreePool (DevicePath
);
5371 // Check whether this ConfigRequest is search from Efi varstore type storage.
5373 Status
= GetVarStoreType(Database
, ConfigResp
, &IsEfiVarstore
, &EfiVarStoreInfo
);
5374 if (EFI_ERROR (Status
)) {
5378 if (IsEfiVarstore
) {
5380 // Call the SetVariable function to route settings.
5382 Status
= RouteConfigRespForEfiVarStore(This
, EfiVarStoreInfo
, ConfigResp
, &AccessProgress
);
5383 FreePool (EfiVarStoreInfo
);
5386 // Call corresponding ConfigAccess protocol to route settings
5388 Status
= gBS
->HandleProtocol (
5390 &gEfiHiiConfigAccessProtocolGuid
,
5391 (VOID
**) &ConfigAccess
5393 if (EFI_ERROR (Status
)) {
5394 *Progress
= StringPtr
;
5395 FreePool (ConfigResp
);
5396 return EFI_NOT_FOUND
;
5399 Status
= ConfigAccess
->RouteConfig (
5405 if (EFI_ERROR (Status
)) {
5406 ASSERT (AccessProgress
!= NULL
);
5408 // AccessProgress indicates the parsing progress on <ConfigResp>.
5409 // Map it to the progress on <MultiConfigResp> then return it.
5411 *Progress
= StrStr (StringPtr
, AccessProgress
);
5413 FreePool (ConfigResp
);
5417 FreePool (ConfigResp
);
5421 // Go to next <ConfigResp> (skip '&').
5423 StringPtr
+= Length
;
5424 if (*StringPtr
== 0) {
5425 *Progress
= StringPtr
;
5438 This helper function is to be called by drivers to map configuration data
5439 stored in byte array ("block") formats such as UEFI Variables into current
5440 configuration strings.
5442 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
5444 @param ConfigRequest A null-terminated Unicode string in
5445 <ConfigRequest> format.
5446 @param Block Array of bytes defining the block's configuration.
5447 @param BlockSize Length in bytes of Block.
5448 @param Config Filled-in configuration string. String allocated
5449 by the function. Returned only if call is
5450 successful. It is <ConfigResp> string format.
5451 @param Progress A pointer to a string filled in with the offset of
5452 the most recent & before the first failing
5453 name/value pair (or the beginning of the string if
5454 the failure is in the first name / value pair) or
5455 the terminating NULL if all was successful.
5457 @retval EFI_SUCCESS The request succeeded. Progress points to the null
5458 terminator at the end of the ConfigRequest
5460 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress
5461 points to the first character of ConfigRequest.
5462 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigRequest or
5463 Block parameter would result in this type of
5464 error. Progress points to the first character of
5466 @retval EFI_DEVICE_ERROR Block not large enough. Progress undefined.
5467 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted string.
5468 Block is left updated and Progress points at
5469 the "&" preceding the first non-<BlockName>.
5475 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
5476 IN CONST EFI_STRING ConfigRequest
,
5477 IN CONST UINT8
*Block
,
5478 IN CONST UINTN BlockSize
,
5479 OUT EFI_STRING
*Config
,
5480 OUT EFI_STRING
*Progress
5483 HII_DATABASE_PRIVATE_DATA
*Private
;
5484 EFI_STRING StringPtr
;
5492 EFI_STRING ValueStr
;
5493 EFI_STRING ConfigElement
;
5500 if (This
== NULL
|| Progress
== NULL
|| Config
== NULL
) {
5501 return EFI_INVALID_PARAMETER
;
5504 if (Block
== NULL
|| ConfigRequest
== NULL
) {
5505 *Progress
= ConfigRequest
;
5506 return EFI_INVALID_PARAMETER
;
5510 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
5511 ASSERT (Private
!= NULL
);
5513 StringPtr
= ConfigRequest
;
5516 ConfigElement
= NULL
;
5519 // Allocate a fix length of memory to store Results. Reallocate memory for
5520 // Results if this fix length is insufficient.
5522 *Config
= (EFI_STRING
) AllocateZeroPool (MAX_STRING_LENGTH
);
5523 if (*Config
== NULL
) {
5524 return EFI_OUT_OF_RESOURCES
;
5530 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
5531 *Progress
= StringPtr
;
5532 Status
= EFI_INVALID_PARAMETER
;
5535 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"PATH=", StrLen (L
"PATH=")) != 0) {
5538 if (*StringPtr
== 0) {
5539 *Progress
= StringPtr
- 1;
5540 Status
= EFI_INVALID_PARAMETER
;
5544 while (*StringPtr
!= L
'&' && *StringPtr
!= 0) {
5547 if (*StringPtr
== 0) {
5548 *Progress
= StringPtr
;
5550 AppendToMultiString(Config
, ConfigRequest
);
5551 HiiToLower (*Config
);
5561 // Copy <ConfigHdr> and an additional '&' to <ConfigResp>
5563 TemString
= AllocateCopyPool (sizeof (CHAR16
) * (StringPtr
- ConfigRequest
+ 1), ConfigRequest
);
5564 if (TemString
== NULL
) {
5565 return EFI_OUT_OF_RESOURCES
;
5567 TemString
[StringPtr
- ConfigRequest
] = '\0';
5568 AppendToMultiString(Config
, TemString
);
5569 FreePool (TemString
);
5572 // Parse each <RequestElement> if exists
5573 // Only <BlockName> format is supported by this help function.
5574 // <BlockName> ::= 'OFFSET='<Number>&'WIDTH='<Number>
5576 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"OFFSET=", StrLen (L
"OFFSET=")) == 0) {
5578 // Back up the header of one <BlockName>
5582 StringPtr
+= StrLen (L
"OFFSET=");
5586 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
5587 if (EFI_ERROR (Status
)) {
5588 *Progress
= TmpPtr
- 1;
5595 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
5597 FreePool (TmpBuffer
);
5599 StringPtr
+= Length
;
5600 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
5601 *Progress
= TmpPtr
- 1;
5602 Status
= EFI_INVALID_PARAMETER
;
5605 StringPtr
+= StrLen (L
"&WIDTH=");
5610 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
5611 if (EFI_ERROR (Status
)) {
5612 *Progress
= TmpPtr
- 1;
5619 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
5621 FreePool (TmpBuffer
);
5623 StringPtr
+= Length
;
5624 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
5625 *Progress
= TmpPtr
- 1;
5626 Status
= EFI_INVALID_PARAMETER
;
5631 // Calculate Value and convert it to hex string.
5633 if (Offset
+ Width
> BlockSize
) {
5634 *Progress
= StringPtr
;
5635 Status
= EFI_DEVICE_ERROR
;
5639 Value
= (UINT8
*) AllocateZeroPool (Width
);
5640 if (Value
== NULL
) {
5641 *Progress
= ConfigRequest
;
5642 Status
= EFI_OUT_OF_RESOURCES
;
5646 CopyMem (Value
, (UINT8
*) Block
+ Offset
, Width
);
5648 Length
= Width
* 2 + 1;
5649 ValueStr
= (EFI_STRING
) AllocateZeroPool (Length
* sizeof (CHAR16
));
5650 if (ValueStr
== NULL
) {
5651 *Progress
= ConfigRequest
;
5652 Status
= EFI_OUT_OF_RESOURCES
;
5656 TemString
= ValueStr
;
5657 TemBuffer
= Value
+ Width
- 1;
5658 for (Index
= 0; Index
< Width
; Index
++, TemBuffer
--) {
5659 UnicodeValueToStringS (
5661 Length
* sizeof (CHAR16
) - ((UINTN
)TemString
- (UINTN
)ValueStr
),
5662 PREFIX_ZERO
| RADIX_HEX
,
5666 TemString
+= StrnLenS (TemString
, Length
- ((UINTN
)TemString
- (UINTN
)ValueStr
) / sizeof (CHAR16
));
5673 // Build a ConfigElement
5675 Length
+= StringPtr
- TmpPtr
+ 1 + StrLen (L
"VALUE=");
5676 ConfigElement
= (EFI_STRING
) AllocateZeroPool (Length
* sizeof (CHAR16
));
5677 if (ConfigElement
== NULL
) {
5678 Status
= EFI_OUT_OF_RESOURCES
;
5681 CopyMem (ConfigElement
, TmpPtr
, (StringPtr
- TmpPtr
+ 1) * sizeof (CHAR16
));
5682 if (*StringPtr
== 0) {
5683 *(ConfigElement
+ (StringPtr
- TmpPtr
)) = L
'&';
5685 *(ConfigElement
+ (StringPtr
- TmpPtr
) + 1) = 0;
5686 StrCatS (ConfigElement
, Length
, L
"VALUE=");
5687 StrCatS (ConfigElement
, Length
, ValueStr
);
5689 AppendToMultiString (Config
, ConfigElement
);
5691 FreePool (ConfigElement
);
5692 FreePool (ValueStr
);
5693 ConfigElement
= NULL
;
5697 // If '\0', parsing is finished. Otherwise skip '&' to continue
5699 if (*StringPtr
== 0) {
5702 AppendToMultiString (Config
, L
"&");
5707 if (*StringPtr
!= 0) {
5708 *Progress
= StringPtr
- 1;
5709 Status
= EFI_INVALID_PARAMETER
;
5713 HiiToLower (*Config
);
5714 *Progress
= StringPtr
;
5718 if (*Config
!= NULL
) {
5722 if (ValueStr
!= NULL
) {
5723 FreePool (ValueStr
);
5725 if (Value
!= NULL
) {
5728 if (ConfigElement
!= NULL
) {
5729 FreePool (ConfigElement
);
5738 This helper function is to be called by drivers to map configuration strings
5739 to configurations stored in byte array ("block") formats such as UEFI Variables.
5741 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
5743 @param ConfigResp A null-terminated Unicode string in <ConfigResp>
5745 @param Block A possibly null array of bytes representing the
5746 current block. Only bytes referenced in the
5747 ConfigResp string in the block are modified. If
5748 this parameter is null or if the *BlockSize
5749 parameter is (on input) shorter than required by
5750 the Configuration string, only the BlockSize
5751 parameter is updated and an appropriate status
5752 (see below) is returned.
5753 @param BlockSize The length of the Block in units of UINT8. On
5754 input, this is the size of the Block. On output,
5755 if successful, contains the largest index of the
5756 modified byte in the Block, or the required buffer
5757 size if the Block is not large enough.
5758 @param Progress On return, points to an element of the ConfigResp
5759 string filled in with the offset of the most
5760 recent '&' before the first failing name / value
5761 pair (or the beginning of the string if the
5762 failure is in the first name / value pair) or the
5763 terminating NULL if all was successful.
5765 @retval EFI_SUCCESS The request succeeded. Progress points to the null
5766 terminator at the end of the ConfigResp string.
5767 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress
5768 points to the first character of ConfigResp.
5769 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigResp or
5770 Block parameter would result in this type of
5771 error. Progress points to the first character of
5773 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted name /
5774 value pair. Block is left updated and
5775 Progress points at the '&' preceding the first
5777 @retval EFI_BUFFER_TOO_SMALL Block not large enough. Progress undefined.
5778 BlockSize is updated with the required buffer size.
5779 @retval EFI_NOT_FOUND Target for the specified routing data was not found.
5780 Progress points to the "G" in "GUID" of the errant
5787 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
5788 IN CONST EFI_STRING ConfigResp
,
5789 IN OUT UINT8
*Block
,
5790 IN OUT UINTN
*BlockSize
,
5791 OUT EFI_STRING
*Progress
5794 HII_DATABASE_PRIVATE_DATA
*Private
;
5795 EFI_STRING StringPtr
;
5808 if (This
== NULL
|| BlockSize
== NULL
|| Progress
== NULL
) {
5809 return EFI_INVALID_PARAMETER
;
5812 *Progress
= ConfigResp
;
5813 if (ConfigResp
== NULL
) {
5814 return EFI_INVALID_PARAMETER
;
5817 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
5818 ASSERT (Private
!= NULL
);
5820 StringPtr
= ConfigResp
;
5821 BufferSize
= *BlockSize
;
5828 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
5829 *Progress
= StringPtr
;
5830 Status
= EFI_INVALID_PARAMETER
;
5833 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"PATH=", StrLen (L
"PATH=")) != 0) {
5836 if (*StringPtr
== 0) {
5837 *Progress
= StringPtr
;
5838 Status
= EFI_INVALID_PARAMETER
;
5842 while (*StringPtr
!= L
'&' && *StringPtr
!= 0) {
5845 if (*StringPtr
== 0) {
5846 *Progress
= StringPtr
;
5847 Status
= EFI_INVALID_PARAMETER
;
5852 // Parse each <ConfigElement> if exists
5853 // Only '&'<BlockConfig> format is supported by this help function.
5854 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE='<Number>
5856 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) == 0) {
5858 StringPtr
+= StrLen (L
"&OFFSET=");
5862 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
5863 if (EFI_ERROR (Status
)) {
5871 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
5873 FreePool (TmpBuffer
);
5875 StringPtr
+= Length
;
5876 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
5878 Status
= EFI_INVALID_PARAMETER
;
5881 StringPtr
+= StrLen (L
"&WIDTH=");
5886 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
5887 if (EFI_ERROR (Status
)) {
5895 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
5897 FreePool (TmpBuffer
);
5899 StringPtr
+= Length
;
5900 if (StrnCmp (StringPtr
, L
"&VALUE=", StrLen (L
"&VALUE=")) != 0) {
5902 Status
= EFI_INVALID_PARAMETER
;
5905 StringPtr
+= StrLen (L
"&VALUE=");
5910 Status
= GetValueOfNumber (StringPtr
, &Value
, &Length
);
5911 if (EFI_ERROR (Status
)) {
5916 StringPtr
+= Length
;
5917 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
5919 Status
= EFI_INVALID_PARAMETER
;
5924 // Update the Block with configuration info
5926 if ((Block
!= NULL
) && (Offset
+ Width
<= BufferSize
)) {
5927 CopyMem (Block
+ Offset
, Value
, Width
);
5929 if (Offset
+ Width
> MaxBlockSize
) {
5930 MaxBlockSize
= Offset
+ Width
;
5937 // If '\0', parsing is finished.
5939 if (*StringPtr
== 0) {
5945 // The input string is not ConfigResp format, return error.
5947 if (*StringPtr
!= 0) {
5948 *Progress
= StringPtr
;
5949 Status
= EFI_INVALID_PARAMETER
;
5953 *Progress
= StringPtr
+ StrLen (StringPtr
);
5954 *BlockSize
= MaxBlockSize
- 1;
5956 if (MaxBlockSize
> BufferSize
) {
5957 *BlockSize
= MaxBlockSize
;
5958 if (Block
!= NULL
) {
5959 return EFI_BUFFER_TOO_SMALL
;
5963 if (Block
== NULL
) {
5964 *Progress
= ConfigResp
;
5965 return EFI_INVALID_PARAMETER
;
5972 if (Value
!= NULL
) {
5980 This helper function is to be called by drivers to extract portions of
5981 a larger configuration string.
5983 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
5985 @param Configuration A null-terminated Unicode string in
5986 <MultiConfigAltResp> format.
5987 @param Guid A pointer to the GUID value to search for in the
5988 routing portion of the ConfigResp string when
5989 retrieving the requested data. If Guid is NULL,
5990 then all GUID values will be searched for.
5991 @param Name A pointer to the NAME value to search for in the
5992 routing portion of the ConfigResp string when
5993 retrieving the requested data. If Name is NULL,
5994 then all Name values will be searched for.
5995 @param DevicePath A pointer to the PATH value to search for in the
5996 routing portion of the ConfigResp string when
5997 retrieving the requested data. If DevicePath is
5998 NULL, then all DevicePath values will be searched
6000 @param AltCfgId A pointer to the ALTCFG value to search for in the
6001 routing portion of the ConfigResp string when
6002 retrieving the requested data. If this parameter
6003 is NULL, then the current setting will be
6005 @param AltCfgResp A pointer to a buffer which will be allocated by
6006 the function which contains the retrieved string
6007 as requested. This buffer is only allocated if
6008 the call was successful. It is <ConfigResp> format.
6010 @retval EFI_SUCCESS The request succeeded. The requested data was
6011 extracted and placed in the newly allocated
6013 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate AltCfgResp.
6014 @retval EFI_INVALID_PARAMETER Any parameter is invalid.
6015 @retval EFI_NOT_FOUND Target for the specified routing data was not
6022 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
6023 IN CONST EFI_STRING Configuration
,
6024 IN CONST EFI_GUID
*Guid
,
6025 IN CONST EFI_STRING Name
,
6026 IN CONST EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
6027 IN CONST UINT16
*AltCfgId
,
6028 OUT EFI_STRING
*AltCfgResp
6032 EFI_STRING StringPtr
;
6033 EFI_STRING HdrStart
;
6040 EFI_STRING AltIdStr
;
6057 if (This
== NULL
|| Configuration
== NULL
|| AltCfgResp
== NULL
) {
6058 return EFI_INVALID_PARAMETER
;
6061 StringPtr
= Configuration
;
6062 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
6063 return EFI_INVALID_PARAMETER
;
6067 // Generate the sub string for later matching.
6069 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*) Guid
, 1, &GuidStr
);
6072 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) DevicePath
),
6073 (VOID
*) DevicePath
,
6077 if (AltCfgId
!= NULL
) {
6078 GenerateSubStr (L
"ALTCFG=", sizeof (UINT16
), (VOID
*) AltCfgId
, 3, &AltIdStr
);
6081 GenerateSubStr (L
"NAME=", StrLen (Name
) * sizeof (CHAR16
), (VOID
*) Name
, 2, &NameStr
);
6083 GenerateSubStr (L
"NAME=", 0, NULL
, 2, &NameStr
);
6086 while (*StringPtr
!= 0) {
6088 // Try to match the GUID
6091 TmpPtr
= StrStr (StringPtr
, GuidStr
);
6092 if (TmpPtr
== NULL
) {
6093 Status
= EFI_NOT_FOUND
;
6099 // Jump to <NameHdr>
6102 StringPtr
= TmpPtr
+ StrLen (GuidStr
);
6104 StringPtr
= StrStr (TmpPtr
, L
"NAME=");
6105 if (StringPtr
== NULL
) {
6106 Status
= EFI_NOT_FOUND
;
6114 // Try to match the NAME
6116 if (GuidFlag
&& !NameFlag
) {
6117 if (StrnCmp (StringPtr
, NameStr
, StrLen (NameStr
)) != 0) {
6121 // Jump to <PathHdr>
6124 StringPtr
+= StrLen (NameStr
);
6126 StringPtr
= StrStr (StringPtr
, L
"PATH=");
6127 if (StringPtr
== NULL
) {
6128 Status
= EFI_NOT_FOUND
;
6137 // Try to match the DevicePath
6139 if (GuidFlag
&& NameFlag
&& !PathFlag
) {
6140 if (StrnCmp (StringPtr
, PathStr
, StrLen (PathStr
)) != 0) {
6145 // Jump to '&' before <DescHdr> or <ConfigBody>
6147 if (DevicePath
!= NULL
) {
6148 StringPtr
+= StrLen (PathStr
);
6150 StringPtr
= StrStr (StringPtr
, L
"&");
6151 if (StringPtr
== NULL
) {
6152 Status
= EFI_NOT_FOUND
;
6163 // Try to match the AltCfgId
6165 if (GuidFlag
&& NameFlag
&& PathFlag
) {
6166 if (AltCfgId
== NULL
) {
6168 // Return Current Setting when AltCfgId is NULL.
6170 Status
= OutputConfigBody (StringPtr
, &Result
);
6174 // Search the <ConfigAltResp> to get the <AltResp> with AltCfgId.
6176 if (StrnCmp (StringPtr
, AltIdStr
, StrLen (AltIdStr
)) != 0) {
6182 // Skip AltIdStr and &
6184 StringPtr
= StringPtr
+ StrLen (AltIdStr
);
6185 Status
= OutputConfigBody (StringPtr
, &Result
);
6191 Status
= EFI_NOT_FOUND
;
6195 if (!EFI_ERROR (Status
) && (Result
!= NULL
)) {
6197 // Copy the <ConfigHdr> and <ConfigBody>
6199 Length
= HdrEnd
- HdrStart
+ StrLen (Result
) + 1;
6200 *AltCfgResp
= AllocateZeroPool (Length
* sizeof (CHAR16
));
6201 if (*AltCfgResp
== NULL
) {
6202 Status
= EFI_OUT_OF_RESOURCES
;
6204 StrnCpyS (*AltCfgResp
, Length
, HdrStart
, HdrEnd
- HdrStart
);
6205 StrCatS (*AltCfgResp
, Length
, Result
);
6206 Status
= EFI_SUCCESS
;
6210 if (GuidStr
!= NULL
) {
6213 if (NameStr
!= NULL
) {
6216 if (PathStr
!= NULL
) {
6219 if (AltIdStr
!= NULL
) {
6220 FreePool (AltIdStr
);
6222 if (Result
!= NULL
) {