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 if (BlockData
->Name
!= NULL
) {
2875 FreePool (BlockData
->Name
);
2877 FreePool (BlockData
);
2881 // Add Block Data into VarStorageData BlockEntry
2883 InsertBlockData (&VarStorageData
->BlockEntry
, &BlockData
);
2885 FirstOrderedList
= FALSE
;
2891 // 1. Set default value for OneOf option when flag field has default attribute.
2892 // And set the default value with the smallest default id for other default id in the DefaultId list.
2894 if (((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT
) == EFI_IFR_OPTION_DEFAULT
) ||
2895 ((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT_MFG
) == EFI_IFR_OPTION_DEFAULT_MFG
)) {
2897 // This flag is used to specify whether this option is the first. Set it to FALSE for the following options.
2898 // The first oneof option value will be used as default value when no default value is specified.
2900 FirstOneOfOption
= FALSE
;
2902 SmallestIdFromFlag
= FALSE
;
2904 // Prepare new DefaultValue
2906 DefaultData
.Type
= DefaultValueFromFlag
;
2907 CopyMem (&DefaultData
.Value
, &IfrOneOfOption
->Value
, IfrOneOfOption
->Header
.Length
- OFFSET_OF (EFI_IFR_ONE_OF_OPTION
, Value
));
2908 if ((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT
) == EFI_IFR_OPTION_DEFAULT
) {
2909 DefaultData
.DefaultId
= EFI_HII_DEFAULT_CLASS_STANDARD
;
2910 InsertDefaultValue (BlockData
, &DefaultData
);
2911 if (SmallestDefaultId
> EFI_HII_DEFAULT_CLASS_STANDARD
) {
2913 // Record the SmallestDefaultId and update the SmallestIdFromFlag.
2915 SmallestDefaultId
= EFI_HII_DEFAULT_CLASS_STANDARD
;
2916 SmallestIdFromFlag
= TRUE
;
2919 if ((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT_MFG
) == EFI_IFR_OPTION_DEFAULT_MFG
) {
2920 DefaultData
.DefaultId
= EFI_HII_DEFAULT_CLASS_MANUFACTURING
;
2921 InsertDefaultValue (BlockData
, &DefaultData
);
2922 if (SmallestDefaultId
> EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
2924 // Record the SmallestDefaultId and update the SmallestIdFromFlag.
2926 SmallestDefaultId
= EFI_HII_DEFAULT_CLASS_MANUFACTURING
;
2927 SmallestIdFromFlag
= TRUE
;
2931 if (SmallestIdFromFlag
) {
2933 // When smallest default Id is given by the flag of oneofOption, set this option value for other default Id in the DefaultId list.
2935 DefaultData
.Type
= DefaultValueFromOtherDefault
;
2937 // Set default value for other default id in the DefaultId list.
2939 for (LinkData
= DefaultIdArray
->Entry
.ForwardLink
; LinkData
!= &DefaultIdArray
->Entry
; LinkData
= LinkData
->ForwardLink
) {
2940 DefaultDataPtr
= BASE_CR (LinkData
, IFR_DEFAULT_DATA
, Entry
);
2941 DefaultData
.DefaultId
= DefaultDataPtr
->DefaultId
;
2942 InsertDefaultValue (BlockData
, &DefaultData
);
2948 // 2. Set as the default value when this is the first option.
2949 // The first oneof option value will be used as default value when no default value is specified.
2951 if (FirstOneOfOption
) {
2952 // This flag is used to specify whether this option is the first. Set it to FALSE for the following options.
2953 FirstOneOfOption
= FALSE
;
2956 // Prepare new DefaultValue
2958 DefaultData
.Type
= DefaultValueFromDefault
;
2959 CopyMem (&DefaultData
.Value
, &IfrOneOfOption
->Value
, IfrOneOfOption
->Header
.Length
- OFFSET_OF (EFI_IFR_ONE_OF_OPTION
, Value
));
2960 for (LinkData
= DefaultIdArray
->Entry
.ForwardLink
; LinkData
!= &DefaultIdArray
->Entry
; LinkData
= LinkData
->ForwardLink
) {
2961 DefaultDataPtr
= BASE_CR (LinkData
, IFR_DEFAULT_DATA
, Entry
);
2962 DefaultData
.DefaultId
= DefaultDataPtr
->DefaultId
;
2963 InsertDefaultValue (BlockData
, &DefaultData
);
2968 case EFI_IFR_DEFAULT_OP
:
2970 // Update Current BlockData to the default value.
2972 if (BlockData
== NULL
|| BlockData
->Scope
== 0) {
2974 // No matched block data is ignored.
2980 // Get the DefaultId
2982 IfrDefault
= (EFI_IFR_DEFAULT
*) IfrOpHdr
;
2983 VarDefaultId
= IfrDefault
->DefaultId
;
2985 // Prepare new DefaultValue
2987 DefaultData
.Type
= DefaultValueFromOpcode
;
2988 DefaultData
.DefaultId
= VarDefaultId
;
2989 if (QuestionReferBitField
) {
2990 CopyMem (&DefaultData
.Value
.u32
, &IfrDefault
->Value
.u32
, sizeof (UINT32
));
2992 CopyMem (&DefaultData
.Value
, &IfrDefault
->Value
, IfrDefault
->Header
.Length
- OFFSET_OF (EFI_IFR_DEFAULT
, Value
));
2995 // If the value field is expression, set the cleaned flag.
2996 if (IfrDefault
->Type
== EFI_IFR_TYPE_OTHER
) {
2997 DefaultData
.Cleaned
= TRUE
;
3000 // Add DefaultValue into current BlockData
3002 InsertDefaultValue (BlockData
, &DefaultData
);
3005 // Set default value for other default id in the DefaultId list.
3006 // when SmallestDefaultId == VarDefaultId means there are two defaults with same default Id.
3007 // If the two defaults are both from default opcode, use the first default as the default value of other default Id.
3008 // If one from flag and the other form default opcode, use the default opcode value as the default value of other default Id.
3010 if ((SmallestDefaultId
> VarDefaultId
) || (SmallestDefaultId
== VarDefaultId
&& !FromOtherDefaultOpcode
)) {
3011 FromOtherDefaultOpcode
= TRUE
;
3012 SmallestDefaultId
= VarDefaultId
;
3013 for (LinkData
= DefaultIdArray
->Entry
.ForwardLink
; LinkData
!= &DefaultIdArray
->Entry
; LinkData
= LinkData
->ForwardLink
) {
3014 DefaultDataPtr
= BASE_CR (LinkData
, IFR_DEFAULT_DATA
, Entry
);
3015 if (DefaultDataPtr
->DefaultId
!= DefaultData
.DefaultId
){
3016 DefaultData
.Type
= DefaultValueFromOtherDefault
;
3017 DefaultData
.DefaultId
= DefaultDataPtr
->DefaultId
;
3018 InsertDefaultValue (BlockData
, &DefaultData
);
3024 // After insert the default value, reset the cleaned value for next
3025 // time used. If not set here, need to set the value before every time.
3028 DefaultData
.Cleaned
= FALSE
;
3031 case EFI_IFR_END_OP
:
3033 // End Opcode is for Var question.
3035 QuestionReferBitField
= FALSE
;
3036 if (BlockData
!= NULL
) {
3037 if (BlockData
->Scope
> 0) {
3040 if (BlockData
->Scope
== 0) {
3043 // when finishing parsing a question, clean the SmallestDefaultId and GetDefaultFromDefaultOpcode.
3045 SmallestDefaultId
= 0xFFFF;
3046 FromOtherDefaultOpcode
= FALSE
;
3052 case EFI_IFR_GUID_OP
:
3053 if (CompareGuid ((EFI_GUID
*)((UINT8
*)IfrOpHdr
+ sizeof (EFI_IFR_OP_HEADER
)), &gEdkiiIfrBitVarstoreGuid
)) {
3054 QuestionReferBitField
= TRUE
;
3059 if (BlockData
!= NULL
) {
3060 if (BlockData
->Scope
> 0) {
3061 BlockData
->Scope
= (UINT8
) (BlockData
->Scope
+ IfrOpHdr
->Scope
);
3064 if (BlockData
->Scope
== 0) {
3071 IfrOffset
+= IfrOpHdr
->Length
;
3072 PackageOffset
+= IfrOpHdr
->Length
;
3076 //if Status == EFI_NOT_FOUND, just means the opcode is not required,not contain any error,
3077 //so set the Status to EFI_SUCCESS.
3079 if (Status
== EFI_NOT_FOUND
){
3080 Status
= EFI_SUCCESS
;
3084 for (LinkData
= VarStorageData
->BlockEntry
.ForwardLink
; LinkData
!= &VarStorageData
->BlockEntry
; LinkData
= LinkData
->ForwardLink
) {
3085 BlockData
= BASE_CR (LinkData
, IFR_BLOCK_DATA
, Entry
);
3086 for (LinkDefault
= BlockData
->DefaultValueEntry
.ForwardLink
; LinkDefault
!= &BlockData
->DefaultValueEntry
; ) {
3087 DefaultDataPtr
= BASE_CR (LinkDefault
, IFR_DEFAULT_DATA
, Entry
);
3088 LinkDefault
= LinkDefault
->ForwardLink
;
3089 if (DefaultDataPtr
->Cleaned
== TRUE
) {
3090 RemoveEntryList (&DefaultDataPtr
->Entry
);
3091 FreePool (DefaultDataPtr
);
3100 parse the configrequest string, get the elements.
3102 @param ConfigRequest The input configrequest string.
3103 @param Progress Return the progress data.
3105 @retval Block data pointer.
3109 IN EFI_STRING ConfigRequest
,
3110 OUT EFI_STRING
*Progress
3113 EFI_STRING StringPtr
;
3114 IFR_BLOCK_DATA
*BlockData
;
3115 IFR_BLOCK_DATA
*RequestBlockArray
;
3121 IFR_BLOCK_DATA
*NextBlockData
;
3127 // Init RequestBlockArray
3129 RequestBlockArray
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
3130 if (RequestBlockArray
== NULL
) {
3133 InitializeListHead (&RequestBlockArray
->Entry
);
3136 // Get the request Block array from the request string
3141 // Parse each <RequestElement> if exists
3142 // Only <BlockName> format is supported by this help function.
3143 // <BlockName> ::= &'OFFSET='<Number>&'WIDTH='<Number>
3145 StringPtr
= ConfigRequest
;
3146 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) == 0) {
3148 // Skip the OFFSET string
3150 *Progress
= StringPtr
;
3151 StringPtr
+= StrLen (L
"&OFFSET=");
3155 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
3156 if (EFI_ERROR (Status
)) {
3163 (((Length
+ 1) / 2) < sizeof (UINT16
)) ? ((Length
+ 1) / 2) : sizeof (UINT16
)
3165 FreePool (TmpBuffer
);
3167 StringPtr
+= Length
;
3168 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
3171 StringPtr
+= StrLen (L
"&WIDTH=");
3176 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
3177 if (EFI_ERROR (Status
)) {
3184 (((Length
+ 1) / 2) < sizeof (UINT16
)) ? ((Length
+ 1) / 2) : sizeof (UINT16
)
3186 FreePool (TmpBuffer
);
3188 StringPtr
+= Length
;
3189 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
3196 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
3197 if (BlockData
== NULL
) {
3200 BlockData
->Offset
= Offset
;
3201 BlockData
->Width
= Width
;
3202 InsertBlockData (&RequestBlockArray
->Entry
, &BlockData
);
3205 // Skip &VALUE string if &VALUE does exists.
3207 if (StrnCmp (StringPtr
, L
"&VALUE=", StrLen (L
"&VALUE=")) == 0) {
3208 StringPtr
+= StrLen (L
"&VALUE=");
3213 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
3214 if (EFI_ERROR (Status
)) {
3217 FreePool (TmpBuffer
);
3218 StringPtr
+= Length
;
3219 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
3224 // If '\0', parsing is finished.
3226 if (*StringPtr
== 0) {
3232 // Merge the requested block data.
3234 Link
= RequestBlockArray
->Entry
.ForwardLink
;
3235 while ((Link
!= &RequestBlockArray
->Entry
) && (Link
->ForwardLink
!= &RequestBlockArray
->Entry
)) {
3236 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
3237 NextBlockData
= BASE_CR (Link
->ForwardLink
, IFR_BLOCK_DATA
, Entry
);
3238 if ((NextBlockData
->Offset
>= BlockData
->Offset
) && (NextBlockData
->Offset
<= (BlockData
->Offset
+ BlockData
->Width
))) {
3239 if ((NextBlockData
->Offset
+ NextBlockData
->Width
) > (BlockData
->Offset
+ BlockData
->Width
)) {
3240 BlockData
->Width
= (UINT16
) (NextBlockData
->Offset
+ NextBlockData
->Width
- BlockData
->Offset
);
3242 RemoveEntryList (Link
->ForwardLink
);
3243 FreePool (NextBlockData
);
3246 Link
= Link
->ForwardLink
;
3249 return RequestBlockArray
;
3252 if (RequestBlockArray
!= NULL
) {
3254 // Free Link Array RequestBlockArray
3256 while (!IsListEmpty (&RequestBlockArray
->Entry
)) {
3257 BlockData
= BASE_CR (RequestBlockArray
->Entry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
3258 RemoveEntryList (&BlockData
->Entry
);
3259 FreePool (BlockData
);
3262 FreePool (RequestBlockArray
);
3269 parse the configrequest string, get the elements.
3271 @param ConfigRequest The input config request string.
3272 @param Progress Return the progress data.
3274 @retval return data block array.
3278 IN EFI_STRING ConfigRequest
,
3279 OUT EFI_STRING
*Progress
3282 EFI_STRING StringPtr
;
3284 IFR_BLOCK_DATA
*BlockData
;
3285 IFR_BLOCK_DATA
*RequestBlockArray
;
3288 StringPtr
= ConfigRequest
;
3291 // Init RequestBlockArray
3293 RequestBlockArray
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
3294 if (RequestBlockArray
== NULL
) {
3297 InitializeListHead (&RequestBlockArray
->Entry
);
3300 // Get the request Block array from the request string
3304 // Parse each <RequestElement> if exists
3305 // Only <BlockName> format is supported by this help function.
3306 // <BlockName> ::= &'Name***=***
3308 while (StringPtr
!= NULL
&& *StringPtr
== L
'&') {
3310 *Progress
= StringPtr
;
3312 // Skip the L"&" string
3317 if ((NextTag
= StrStr (StringPtr
, L
"=")) != NULL
) {
3320 } else if ((NextTag
= StrStr (StringPtr
, L
"&")) != NULL
) {
3327 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
3328 if (BlockData
== NULL
) {
3335 BlockData
->Name
= AllocateCopyPool(StrSize (StringPtr
), StringPtr
);
3336 InsertBlockData (&RequestBlockArray
->Entry
, &BlockData
);
3340 // If has value, skip the value.
3342 StringPtr
= NextTag
+ 1;
3344 StringPtr
= StrStr (StringPtr
, L
"&");
3345 } else if (NextTag
!= NULL
) {
3347 // restore the '&' text.
3349 StringPtr
= NextTag
;
3354 return RequestBlockArray
;
3357 if (RequestBlockArray
!= NULL
) {
3359 // Free Link Array RequestBlockArray
3361 while (!IsListEmpty (&RequestBlockArray
->Entry
)) {
3362 BlockData
= BASE_CR (RequestBlockArray
->Entry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
3363 RemoveEntryList (&BlockData
->Entry
);
3364 if (BlockData
->Name
!= NULL
) {
3365 FreePool (BlockData
->Name
);
3367 FreePool (BlockData
);
3370 FreePool (RequestBlockArray
);
3377 Generate ConfigRequest string base on the varstore info.
3379 @param ConfigHdr The config header for this varstore.
3380 @param VarStorageData The varstore info.
3381 @param Status Return Status.
3382 @param ConfigRequest The ConfigRequest info may be return.
3384 @retval TRUE Need to continue
3385 @retval Others NO need to continue or error occur.
3388 GenerateConfigRequest (
3389 IN CHAR16
*ConfigHdr
,
3390 IN IFR_VARSTORAGE_DATA
*VarStorageData
,
3391 OUT EFI_STATUS
*Status
,
3392 IN OUT EFI_STRING
*ConfigRequest
3398 CHAR16
*FullConfigRequest
;
3400 IFR_BLOCK_DATA
*BlockData
;
3403 // Append VarStorageData BlockEntry into *Request string
3404 // Now support only one varstore in a form package.
3408 // Go through all VarStorageData Entry and get BlockEntry for each one for the multiple varstore in a single form package
3409 // Then construct them all to return MultiRequest string : ConfigHdr BlockConfig
3413 // Compute the length of the entire request starting with <ConfigHdr> and a
3417 Length
= StrLen (ConfigHdr
) + 1;
3419 for (Link
= VarStorageData
->BlockEntry
.ForwardLink
; Link
!= &VarStorageData
->BlockEntry
; Link
= Link
->ForwardLink
) {
3421 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
3422 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3424 // Add <BlockName> length for each Name
3426 // <BlockName> ::= &Name1&Name2&...
3427 // |1| StrLen(Name1)
3429 Length
= Length
+ (1 + StrLen (BlockData
->Name
));
3432 // Add <BlockName> length for each Offset/Width pair
3434 // <BlockName> ::= &OFFSET=1234&WIDTH=1234
3435 // | 8 | 4 | 7 | 4 |
3437 Length
= Length
+ (8 + 4 + 7 + 4);
3441 // No any request block data is found. The request string can't be constructed.
3444 *Status
= EFI_SUCCESS
;
3449 // Allocate buffer for the entire <ConfigRequest>
3451 FullConfigRequest
= AllocateZeroPool (Length
* sizeof (CHAR16
));
3452 if (FullConfigRequest
== NULL
) {
3453 *Status
= EFI_OUT_OF_RESOURCES
;
3456 StringPtr
= FullConfigRequest
;
3459 // Start with <ConfigHdr>
3461 StrCpyS (StringPtr
, Length
, ConfigHdr
);
3462 StringPtr
+= StrLen (StringPtr
);
3465 // Loop through all the Offset/Width pairs and append them to ConfigRequest
3467 for (Link
= VarStorageData
->BlockEntry
.ForwardLink
; Link
!= &VarStorageData
->BlockEntry
; Link
= Link
->ForwardLink
) {
3468 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
3469 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3475 (1 + StrLen (BlockData
->Name
) + 1) * sizeof (CHAR16
),
3481 // Append &OFFSET=XXXX&WIDTH=YYYY\0
3485 (8 + 4 + 7 + 4 + 1) * sizeof (CHAR16
),
3486 L
"&OFFSET=%04X&WIDTH=%04X",
3491 StringPtr
+= StrLen (StringPtr
);
3494 // Set to the got full request string.
3496 HiiToLower (FullConfigRequest
);
3498 if (*ConfigRequest
!= NULL
) {
3499 FreePool (*ConfigRequest
);
3501 *ConfigRequest
= FullConfigRequest
;
3507 Generate ConfigRequest Header base on the varstore info.
3509 @param VarStorageData The varstore info.
3510 @param DevicePath Device path for this varstore.
3511 @param ConfigHdr The config header for this varstore.
3513 @retval EFI_SUCCESS Generate the header success.
3514 @retval EFI_OUT_OF_RESOURCES Allocate buffer fail.
3518 IN IFR_VARSTORAGE_DATA
*VarStorageData
,
3519 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
3520 OUT EFI_STRING
*ConfigHdr
3529 Status
= EFI_SUCCESS
;
3535 // Construct <ConfigHdr> : "GUID=...&NAME=...&PATH=..." by VarStorageData Guid, Name and DriverHandle
3537 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*) &VarStorageData
->Guid
, 1, &GuidStr
);
3538 if (VarStorageData
->Name
!= NULL
) {
3539 GenerateSubStr (L
"NAME=", StrLen (VarStorageData
->Name
) * sizeof (CHAR16
), (VOID
*) VarStorageData
->Name
, 2, &NameStr
);
3541 GenerateSubStr (L
"NAME=", 0, NULL
, 2, &NameStr
);
3545 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) DevicePath
),
3546 (VOID
*) DevicePath
,
3550 Length
= StrLen (GuidStr
) + StrLen (NameStr
) + StrLen (PathStr
) + 1;
3551 if (VarStorageData
->Name
== NULL
) {
3555 *ConfigHdr
= AllocateZeroPool (Length
* sizeof (CHAR16
));
3556 if (*ConfigHdr
== NULL
) {
3557 Status
= EFI_OUT_OF_RESOURCES
;
3560 StrCpyS (*ConfigHdr
, Length
, GuidStr
);
3561 StrCatS (*ConfigHdr
, Length
, NameStr
);
3562 if (VarStorageData
->Name
== NULL
) {
3563 StrCatS (*ConfigHdr
, Length
, L
"&");
3565 StrCatS (*ConfigHdr
, Length
, PathStr
);
3568 // Remove the last character L'&'
3570 *(*ConfigHdr
+ StrLen (*ConfigHdr
) - 1) = L
'\0';
3573 if (GuidStr
!= NULL
) {
3577 if (NameStr
!= NULL
) {
3581 if (PathStr
!= NULL
) {
3590 Update the default value in the block data which is used as bit var store.
3593 A question value saved in a bit fied: bitoffset = 1; bitwidth = 2;default value = 1.
3594 And corresponding block data info: offset==0; width==1;currently the default value
3595 is saved as 1.Actually the default value 1 need to be set to bit field 1, so the
3596 default value of this block data shuold be:2.
3600 UINT8 Bit2 : 2; // Question saved in Bit2,so originalBlock info: offset = 0; width = 1;(byte level) defaul = 1.
3601 // (default value record for the bit field)
3605 After function UpdateDefaultValue,the Block info is: offset = 0; width = 1;(byte level) default = 2.
3606 (default value record for the Block)
3608 UpdateDefaultValue function update default value of bit var block based on the bit field info in the block.
3610 @param BlockLink The Link of the block data.
3614 UpdateDefaultValue (
3615 IN LIST_ENTRY
*BlockLink
3619 LIST_ENTRY
*ListEntry
;
3620 LIST_ENTRY
*LinkDefault
;
3621 IFR_BLOCK_DATA
*BlockData
;
3622 IFR_DEFAULT_DATA
*DefaultValueData
;
3625 UINT32 BitFieldDefaultValue
;
3627 for ( Link
= BlockLink
->ForwardLink
; Link
!= BlockLink
; Link
= Link
->ForwardLink
) {
3628 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
3629 if (!BlockData
->IsBitVar
) {
3632 ListEntry
= &BlockData
->DefaultValueEntry
;
3634 // Update the default value in the block data with all existing default id.
3636 for (LinkDefault
= ListEntry
->ForwardLink
; LinkDefault
!= ListEntry
; LinkDefault
= LinkDefault
->ForwardLink
) {
3638 // Get the default data, and the value of the default data is for some field in the block.
3639 // Note: Default value for bit field question is stored as UINT32.
3641 DefaultValueData
= BASE_CR (LinkDefault
, IFR_DEFAULT_DATA
, Entry
);
3642 BitFieldDefaultValue
= DefaultValueData
->Value
.u32
;
3644 StartBit
= BlockData
->BitOffset
% 8;
3645 EndBit
= StartBit
+ BlockData
->BitWidth
- 1;
3648 // Set the bit field default value to related bit filed, then we will got the new default vaule for the block data.
3650 DefaultValueData
->Value
.u32
= BitFieldWrite32 (0, StartBit
, EndBit
, BitFieldDefaultValue
);
3656 Merge the default value in two block datas which have overlap region.
3658 For bit fields, their related block data may have overlap region, such as:
3661 UINT16 Bit1 : 6; // Question1 refer Bit1, Block1: offset = 0; width = 1;(byte level) default = 1
3662 UINT16 Bit2 : 5; // Question2 refer Bit2, Block2: offset = 0; width = 2;(byte level) default = 5
3663 // (default value record for the bit field)
3667 After function UpdateDefaultValue:
3668 Block1: offset = 0; width = 1;(byte level) default = 1
3669 Block2: offset = 0; width = 2;(byte level) default = 320 (5 * (2 << 6))
3670 (default value record for block)
3672 After function MergeBlockDefaultValue:
3673 Block1: offset = 0; width = 1;(byte level) default = 65
3674 Block2: offset = 0; width = 2;(byte level) default = 321
3675 (Block1 and Block2 has overlap region, merge the overlap value to Block1 and Blcok2)
3677 Block1 and Block2 have overlap byte region, but currntly the default value of Block1 only contains
3678 value of Bit1 (low 6 bits),the default value of Block2 only contains the value of Bit2 (middle 5 bits).
3680 This fuction merge the default value of these two blocks, and make the default value of block1
3681 also contain the value of lower 2 bits of the Bit2. And make the default value of Block2 also
3682 contain the default value of Bit1.
3684 We can get the total value of the whole block that just cover these two blocks(in this case is:
3685 block: offset =0; width =2;) then the value of block2 is same as block, the value of block1 is
3686 the first byte value of block.
3688 @param FirstBlock Point to the block date whose default value need to be merged.
3689 @param SecondBlock Point to the block date whose default value need to be merged.
3693 MergeBlockDefaultValue (
3694 IN OUT IFR_BLOCK_DATA
*FirstBlock
,
3695 IN OUT IFR_BLOCK_DATA
*SecondBlock
3698 LIST_ENTRY
*FirstListEntry
;
3699 LIST_ENTRY
*SecondListEntry
;
3700 LIST_ENTRY
*FirstDefaultLink
;
3701 LIST_ENTRY
*SecondDefaultLink
;
3702 IFR_DEFAULT_DATA
*FirstDefaultValueData
;
3703 IFR_DEFAULT_DATA
*SecondDefaultValueData
;
3704 UINT32
*FirstDefaultValue
;
3705 UINT32
*SecondDefaultValue
;
3707 UINT64 ShiftedValue
;
3710 FirstListEntry
= &FirstBlock
->DefaultValueEntry
;
3711 for (FirstDefaultLink
= FirstListEntry
->ForwardLink
; FirstDefaultLink
!= FirstListEntry
; FirstDefaultLink
= FirstDefaultLink
->ForwardLink
) {
3712 FirstDefaultValueData
= BASE_CR (FirstDefaultLink
, IFR_DEFAULT_DATA
, Entry
);
3713 SecondListEntry
= &SecondBlock
->DefaultValueEntry
;
3714 for (SecondDefaultLink
= SecondListEntry
->ForwardLink
; SecondDefaultLink
!= SecondListEntry
; SecondDefaultLink
= SecondDefaultLink
->ForwardLink
) {
3715 SecondDefaultValueData
= BASE_CR (SecondDefaultLink
, IFR_DEFAULT_DATA
, Entry
);
3716 if (FirstDefaultValueData
->DefaultId
!= SecondDefaultValueData
->DefaultId
) {
3720 // Find default value with same default id in the two blocks.
3721 // Note: Default value for bit field question is stored as UINT32 type.
3723 FirstDefaultValue
= &FirstDefaultValueData
->Value
.u32
;
3724 SecondDefaultValue
= &SecondDefaultValueData
->Value
.u32
;
3726 // 1. Get the default value of the whole blcok that can just cover FirstBlock and SecondBlock.
3727 // 2. Get the default value of FirstBlock and SecondBlock form the value of whole block based
3728 // on the offset and width of FirstBlock and SecondBlock.
3730 if (FirstBlock
->Offset
> SecondBlock
->Offset
) {
3731 OffsetShift
= FirstBlock
->Offset
- SecondBlock
->Offset
;
3732 ShiftedValue
= LShiftU64 ((UINT64
) (*FirstDefaultValue
), OffsetShift
* 8);
3733 TotalValue
= ShiftedValue
| (UINT64
) (*SecondDefaultValue
);
3734 *SecondDefaultValue
= (UINT32
) BitFieldRead64 (TotalValue
, 0, SecondBlock
->Width
* 8 -1);
3735 *FirstDefaultValue
= (UINT32
) BitFieldRead64 (TotalValue
, OffsetShift
* 8, OffsetShift
* 8 + FirstBlock
->Width
*8 -1);
3737 OffsetShift
= SecondBlock
->Offset
-FirstBlock
->Offset
;
3738 ShiftedValue
= LShiftU64 ((UINT64
) (*SecondDefaultValue
), OffsetShift
* 8);
3739 TotalValue
= ShiftedValue
| (UINT64
) (*FirstDefaultValue
);
3740 *FirstDefaultValue
= (UINT32
) BitFieldRead64 (TotalValue
, 0, FirstBlock
->Width
* 8 -1);
3741 *SecondDefaultValue
= (UINT32
) BitFieldRead64 (TotalValue
, OffsetShift
* 8, OffsetShift
* 8 + SecondBlock
->Width
*8 -1);
3749 Update the default value in the block data which used as Bit VarStore
3751 @param BlockLink The Link of the block data.
3755 UpdateBlockDataArray (
3756 IN LIST_ENTRY
*BlockLink
3760 LIST_ENTRY
*TempLink
;
3761 IFR_BLOCK_DATA
*BlockData
;
3762 IFR_BLOCK_DATA
*NextBlockData
;
3765 // 1. Update default value in BitVar block data.
3766 // Sine some block datas are used as BitVarStore, then the default value recored in the block
3767 // is for related bit field in the block. so we need to set the default value to the related bit
3768 // fields in the block data if the block data is used as bit varstore, then the default value of
3769 // the block will be updated.
3771 UpdateDefaultValue (BlockLink
);
3774 // 2.Update default value for overlap BitVar blcok datas.
3775 // For block datas have overlap region, we need to merge the default value in different blocks.
3777 for (Link
= BlockLink
->ForwardLink
; Link
!= BlockLink
; Link
= Link
->ForwardLink
) {
3778 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
3779 if (!BlockData
->IsBitVar
) {
3782 for (TempLink
= Link
->ForwardLink
; TempLink
!= BlockLink
; TempLink
= TempLink
->ForwardLink
) {
3783 NextBlockData
= BASE_CR (TempLink
, IFR_BLOCK_DATA
, Entry
);
3784 if (!NextBlockData
->IsBitVar
|| NextBlockData
->Offset
>= BlockData
->Offset
+ BlockData
->Width
|| BlockData
->Offset
>= NextBlockData
->Offset
+ NextBlockData
->Width
) {
3788 // Find two blocks are used as bit VarStore and have overlap region, so need to merge default value of these two blocks.
3790 MergeBlockDefaultValue (BlockData
, NextBlockData
);
3796 Generate ConfigAltResp string base on the varstore info.
3798 @param HiiHandle Hii Handle for this hii package.
3799 @param ConfigHdr The config header for this varstore.
3800 @param VarStorageData The varstore info.
3801 @param DefaultIdArray The Default id array.
3802 @param DefaultAltCfgResp The DefaultAltCfgResp info may be return.
3804 @retval TRUE Need to continue
3805 @retval Others NO need to continue or error occur.
3808 GenerateAltConfigResp (
3809 IN EFI_HII_HANDLE HiiHandle
,
3810 IN CHAR16
*ConfigHdr
,
3811 IN IFR_VARSTORAGE_DATA
*VarStorageData
,
3812 IN IFR_DEFAULT_DATA
*DefaultIdArray
,
3813 IN OUT EFI_STRING
*DefaultAltCfgResp
3819 LIST_ENTRY
*LinkData
;
3820 LIST_ENTRY
*LinkDefault
;
3821 LIST_ENTRY
*ListEntry
;
3823 IFR_BLOCK_DATA
*BlockData
;
3824 IFR_DEFAULT_DATA
*DefaultId
;
3825 IFR_DEFAULT_DATA
*DefaultValueData
;
3828 CHAR16
*DefaultString
;
3833 DefaultString
= NULL
;
3835 // Add length for <ConfigHdr> + '\0'
3837 Length
= StrLen (ConfigHdr
) + 1;
3839 UpdateBlockDataArray (&VarStorageData
->BlockEntry
);
3841 for (Link
= DefaultIdArray
->Entry
.ForwardLink
; Link
!= &DefaultIdArray
->Entry
; Link
= Link
->ForwardLink
) {
3842 DefaultId
= BASE_CR (Link
, IFR_DEFAULT_DATA
, Entry
);
3844 // Add length for "&<ConfigHdr>&ALTCFG=XXXX"
3845 // |1| StrLen (ConfigHdr) | 8 | 4 |
3847 Length
+= (1 + StrLen (ConfigHdr
) + 8 + 4);
3849 for (LinkData
= VarStorageData
->BlockEntry
.ForwardLink
; LinkData
!= &VarStorageData
->BlockEntry
; LinkData
= LinkData
->ForwardLink
) {
3850 BlockData
= BASE_CR (LinkData
, IFR_BLOCK_DATA
, Entry
);
3851 ListEntry
= &BlockData
->DefaultValueEntry
;
3852 for (LinkDefault
= ListEntry
->ForwardLink
; LinkDefault
!= ListEntry
; LinkDefault
= LinkDefault
->ForwardLink
) {
3853 DefaultValueData
= BASE_CR (LinkDefault
, IFR_DEFAULT_DATA
, Entry
);
3854 if (DefaultValueData
->DefaultId
!= DefaultId
->DefaultId
) {
3857 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3859 // Add length for "&Name1=zzzzzzzzzzzz"
3862 Length
+= (1 + StrLen (BlockData
->Name
) + 1 + BlockData
->Width
* 2);
3865 // Add length for "&OFFSET=XXXX&WIDTH=YYYY&VALUE=zzzzzzzzzzzz"
3866 // | 8 | 4 | 7 | 4 | 7 | Width * 2 |
3868 Length
+= (8 + 4 + 7 + 4 + 7 + BlockData
->Width
* 2);
3876 // No default value is found. The default string doesn't exist.
3883 // Allocate buffer for the entire <DefaultAltCfgResp>
3885 *DefaultAltCfgResp
= AllocateZeroPool (Length
* sizeof (CHAR16
));
3886 if (*DefaultAltCfgResp
== NULL
) {
3887 return EFI_OUT_OF_RESOURCES
;
3889 StringPtr
= *DefaultAltCfgResp
;
3892 // Start with <ConfigHdr>
3894 StrCpyS (StringPtr
, Length
, ConfigHdr
);
3895 StringPtr
+= StrLen (StringPtr
);
3897 for (Link
= DefaultIdArray
->Entry
.ForwardLink
; Link
!= &DefaultIdArray
->Entry
; Link
= Link
->ForwardLink
) {
3898 DefaultId
= BASE_CR (Link
, IFR_DEFAULT_DATA
, Entry
);
3900 // Add <AltConfigHdr> of the form "&<ConfigHdr>&ALTCFG=XXXX\0"
3901 // |1| StrLen (ConfigHdr) | 8 | 4 |
3905 (1 + StrLen (ConfigHdr
) + 8 + 4 + 1) * sizeof (CHAR16
),
3908 DefaultId
->DefaultId
3910 StringPtr
+= StrLen (StringPtr
);
3912 for (LinkData
= VarStorageData
->BlockEntry
.ForwardLink
; LinkData
!= &VarStorageData
->BlockEntry
; LinkData
= LinkData
->ForwardLink
) {
3913 BlockData
= BASE_CR (LinkData
, IFR_BLOCK_DATA
, Entry
);
3914 ListEntry
= &BlockData
->DefaultValueEntry
;
3915 for (LinkDefault
= ListEntry
->ForwardLink
; LinkDefault
!= ListEntry
; LinkDefault
= LinkDefault
->ForwardLink
) {
3916 DefaultValueData
= BASE_CR (LinkDefault
, IFR_DEFAULT_DATA
, Entry
);
3917 if (DefaultValueData
->DefaultId
!= DefaultId
->DefaultId
) {
3920 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3923 (1 + StrLen (ConfigHdr
) + 1) * sizeof (CHAR16
),
3927 StringPtr
+= StrLen (StringPtr
);
3930 // Add <BlockConfig>
3931 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>
3935 (8 + 4 + 7 + 4 + 7 + 1) * sizeof (CHAR16
),
3936 L
"&OFFSET=%04X&WIDTH=%04X&VALUE=",
3940 StringPtr
+= StrLen (StringPtr
);
3942 Width
= BlockData
->Width
;
3944 // Convert Value to a hex string in "%x" format
3945 // NOTE: This is in the opposite byte that GUID and PATH use
3947 if (BlockData
->OpCode
== EFI_IFR_STRING_OP
){
3948 DefaultString
= InternalGetString(HiiHandle
, DefaultValueData
->Value
.string
);
3949 TmpBuffer
= AllocateZeroPool (Width
);
3950 ASSERT (TmpBuffer
!= NULL
);
3951 if (DefaultString
!= NULL
) {
3952 StrSize
= StrLen(DefaultString
)* sizeof (CHAR16
);
3953 if (StrSize
> Width
) {
3956 CopyMem (TmpBuffer
, (UINT8
*) DefaultString
, StrSize
);
3959 TmpBuffer
= (UINT8
*) &(DefaultValueData
->Value
);
3961 for (; Width
> 0 && (TmpBuffer
!= NULL
); Width
--) {
3962 UnicodeValueToStringS (
3964 Length
* sizeof (CHAR16
) - ((UINTN
)StringPtr
- (UINTN
)*DefaultAltCfgResp
),
3965 PREFIX_ZERO
| RADIX_HEX
,
3966 TmpBuffer
[Width
- 1],
3969 StringPtr
+= StrnLenS (StringPtr
, Length
- ((UINTN
)StringPtr
- (UINTN
)*DefaultAltCfgResp
) / sizeof (CHAR16
));
3971 if (DefaultString
!= NULL
){
3972 FreePool(DefaultString
);
3973 DefaultString
= NULL
;
3975 if (BlockData
->OpCode
== EFI_IFR_STRING_OP
&& TmpBuffer
!= NULL
) {
3976 FreePool(TmpBuffer
);
3983 HiiToLower (*DefaultAltCfgResp
);
3989 This function gets the full request string and full default value string by
3990 parsing IFR data in HII form packages.
3992 When Request points to NULL string, the request string and default value string
3993 for each varstore in form package will return.
3995 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
3996 @param DevicePath Device Path which Hii Config Access Protocol is registered.
3997 @param Request Pointer to a null-terminated Unicode string in
3998 <ConfigRequest> format. When it doesn't contain
3999 any RequestElement, it will be updated to return
4000 the full RequestElement retrieved from IFR data.
4001 If it points to NULL, the request string for the first
4002 varstore in form package will be merged into a
4003 <MultiConfigRequest> format string and return.
4004 @param AltCfgResp Pointer to a null-terminated Unicode string in
4005 <ConfigAltResp> format. When the pointer is to NULL,
4006 the full default value string retrieved from IFR data
4007 will return. When the pinter is to a string, the
4008 full default value string retrieved from IFR data
4009 will be merged into the input string and return.
4010 When Request points to NULL, the default value string
4011 for each varstore in form package will be merged into
4012 a <MultiConfigAltResp> format string and return.
4013 @param PointerProgress Optional parameter, it can be NULL.
4014 When it is not NULL, if Request is NULL, it returns NULL.
4015 On return, points to a character in the Request
4016 string. Points to the string's null terminator if
4017 request was successful. Points to the most recent
4018 & before the first failing name / value pair (or
4019 the beginning of the string if the failure is in
4020 the first name / value pair) if the request was
4022 @retval EFI_SUCCESS The Results string is set to the full request string.
4023 And AltCfgResp contains all default value string.
4024 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
4025 @retval EFI_NOT_FOUND The varstore (Guid and Name) in Request string
4026 can't be found in Form package.
4027 @retval EFI_NOT_FOUND HiiPackage can't be got on the input HiiHandle.
4028 @retval EFI_INVALID_PARAMETER Request points to NULL.
4033 GetFullStringFromHiiFormPackages (
4034 IN HII_DATABASE_RECORD
*DataBaseRecord
,
4035 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
4036 IN OUT EFI_STRING
*Request
,
4037 IN OUT EFI_STRING
*AltCfgResp
,
4038 OUT EFI_STRING
*PointerProgress OPTIONAL
4042 UINT8
*HiiFormPackage
;
4044 IFR_BLOCK_DATA
*RequestBlockArray
;
4045 IFR_BLOCK_DATA
*BlockData
;
4046 IFR_DEFAULT_DATA
*DefaultValueData
;
4047 IFR_DEFAULT_DATA
*DefaultId
;
4048 IFR_DEFAULT_DATA
*DefaultIdArray
;
4049 IFR_VARSTORAGE_DATA
*VarStorageData
;
4050 EFI_STRING DefaultAltCfgResp
;
4051 EFI_STRING ConfigHdr
;
4052 EFI_STRING StringPtr
;
4053 EFI_STRING Progress
;
4055 if (DataBaseRecord
== NULL
|| DevicePath
== NULL
|| Request
== NULL
|| AltCfgResp
== NULL
) {
4056 return EFI_INVALID_PARAMETER
;
4060 // Initialize the local variables.
4062 RequestBlockArray
= NULL
;
4063 DefaultIdArray
= NULL
;
4064 VarStorageData
= NULL
;
4065 DefaultAltCfgResp
= NULL
;
4067 HiiFormPackage
= NULL
;
4069 Progress
= *Request
;
4071 Status
= GetFormPackageData (DataBaseRecord
, &HiiFormPackage
, &PackageSize
);
4072 if (EFI_ERROR (Status
)) {
4077 // 1. Get the request block array by Request String when Request string contains the block array.
4080 if (*Request
!= NULL
) {
4081 StringPtr
= *Request
;
4085 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
4086 Status
= EFI_INVALID_PARAMETER
;
4089 StringPtr
+= StrLen (L
"GUID=");
4090 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&NAME=", StrLen (L
"&NAME=")) != 0) {
4093 if (*StringPtr
== L
'\0') {
4094 Status
= EFI_INVALID_PARAMETER
;
4097 StringPtr
+= StrLen (L
"&NAME=");
4098 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&PATH=", StrLen (L
"&PATH=")) != 0) {
4101 if (*StringPtr
== L
'\0') {
4102 Status
= EFI_INVALID_PARAMETER
;
4105 StringPtr
+= StrLen (L
"&PATH=");
4106 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
4110 if (*StringPtr
== L
'\0') {
4112 // No request block is found.
4119 // If StringPtr != NULL, get the request elements.
4121 if (StringPtr
!= NULL
) {
4122 if (StrStr (StringPtr
, L
"&OFFSET=") != NULL
) {
4123 RequestBlockArray
= GetBlockElement(StringPtr
, &Progress
);
4125 RequestBlockArray
= GetNameElement(StringPtr
, &Progress
);
4128 if (RequestBlockArray
== NULL
) {
4129 Status
= EFI_INVALID_PARAMETER
;
4135 // Initialize DefaultIdArray to store the map between DeaultId and DefaultName
4137 DefaultIdArray
= (IFR_DEFAULT_DATA
*) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
4138 if (DefaultIdArray
== NULL
) {
4139 Status
= EFI_OUT_OF_RESOURCES
;
4142 InitializeListHead (&DefaultIdArray
->Entry
);
4145 // Initialize VarStorageData to store the var store Block and Default value information.
4147 VarStorageData
= (IFR_VARSTORAGE_DATA
*) AllocateZeroPool (sizeof (IFR_VARSTORAGE_DATA
));
4148 if (VarStorageData
== NULL
) {
4149 Status
= EFI_OUT_OF_RESOURCES
;
4152 InitializeListHead (&VarStorageData
->Entry
);
4153 InitializeListHead (&VarStorageData
->BlockEntry
);
4156 // 2. Parse FormPackage to get BlockArray and DefaultId Array for the request BlockArray.
4160 // Parse the opcode in form package to get the default setting.
4162 Status
= ParseIfrData (DataBaseRecord
->Handle
,
4164 (UINT32
) PackageSize
,
4169 if (EFI_ERROR (Status
)) {
4174 // No requested varstore in IFR data and directly return
4176 if (VarStorageData
->Type
== 0 && VarStorageData
->Name
== NULL
) {
4177 Status
= EFI_SUCCESS
;
4182 // 3. Construct Request Element (Block Name) for 2.1 and 2.2 case.
4184 Status
= GenerateHdr (VarStorageData
, DevicePath
, &ConfigHdr
);
4185 if (EFI_ERROR (Status
)) {
4189 if (RequestBlockArray
== NULL
) {
4190 if (!GenerateConfigRequest(ConfigHdr
, VarStorageData
, &Status
, Request
)) {
4196 // 4. Construct Default Value string in AltResp according to request element.
4197 // Go through all VarStorageData Entry and get the DefaultId array for each one
4198 // Then construct them all to : ConfigHdr AltConfigHdr ConfigBody AltConfigHdr ConfigBody
4200 Status
= GenerateAltConfigResp (DataBaseRecord
->Handle
,ConfigHdr
, VarStorageData
, DefaultIdArray
, &DefaultAltCfgResp
);
4201 if (EFI_ERROR (Status
)) {
4206 // 5. Merge string into the input AltCfgResp if the input *AltCfgResp is not NULL.
4208 if (*AltCfgResp
!= NULL
&& DefaultAltCfgResp
!= NULL
) {
4209 Status
= MergeDefaultString (AltCfgResp
, DefaultAltCfgResp
);
4210 FreePool (DefaultAltCfgResp
);
4211 } else if (*AltCfgResp
== NULL
) {
4212 *AltCfgResp
= DefaultAltCfgResp
;
4216 if (RequestBlockArray
!= NULL
) {
4218 // Free Link Array RequestBlockArray
4220 while (!IsListEmpty (&RequestBlockArray
->Entry
)) {
4221 BlockData
= BASE_CR (RequestBlockArray
->Entry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
4222 RemoveEntryList (&BlockData
->Entry
);
4223 if (BlockData
->Name
!= NULL
) {
4224 FreePool (BlockData
->Name
);
4226 FreePool (BlockData
);
4229 FreePool (RequestBlockArray
);
4232 if (VarStorageData
!= NULL
) {
4234 // Free link array VarStorageData
4236 while (!IsListEmpty (&VarStorageData
->BlockEntry
)) {
4237 BlockData
= BASE_CR (VarStorageData
->BlockEntry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
4238 RemoveEntryList (&BlockData
->Entry
);
4239 if (BlockData
->Name
!= NULL
) {
4240 FreePool (BlockData
->Name
);
4243 // Free default value link array
4245 while (!IsListEmpty (&BlockData
->DefaultValueEntry
)) {
4246 DefaultValueData
= BASE_CR (BlockData
->DefaultValueEntry
.ForwardLink
, IFR_DEFAULT_DATA
, Entry
);
4247 RemoveEntryList (&DefaultValueData
->Entry
);
4248 FreePool (DefaultValueData
);
4250 FreePool (BlockData
);
4252 if (VarStorageData
->Name
!= NULL
) {
4253 FreePool (VarStorageData
->Name
);
4254 VarStorageData
->Name
= NULL
;
4256 FreePool (VarStorageData
);
4259 if (DefaultIdArray
!= NULL
) {
4261 // Free DefaultId Array
4263 while (!IsListEmpty (&DefaultIdArray
->Entry
)) {
4264 DefaultId
= BASE_CR (DefaultIdArray
->Entry
.ForwardLink
, IFR_DEFAULT_DATA
, Entry
);
4265 RemoveEntryList (&DefaultId
->Entry
);
4266 FreePool (DefaultId
);
4268 FreePool (DefaultIdArray
);
4272 // Free the allocated string
4274 if (ConfigHdr
!= NULL
) {
4275 FreePool (ConfigHdr
);
4279 // Free Package data
4281 if (HiiFormPackage
!= NULL
) {
4282 FreePool (HiiFormPackage
);
4285 if (PointerProgress
!= NULL
) {
4286 if (*Request
== NULL
) {
4287 *PointerProgress
= NULL
;
4288 } else if (EFI_ERROR (Status
)) {
4289 *PointerProgress
= *Request
;
4291 *PointerProgress
= *Request
+ StrLen (*Request
);
4299 This function gets the full request resp string by
4300 parsing IFR data in HII form packages.
4302 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
4304 @param EfiVarStoreInfo The efi varstore info which is save in the EFI
4305 varstore data structure.
4306 @param Request Pointer to a null-terminated Unicode string in
4307 <ConfigRequest> format.
4308 @param RequestResp Pointer to a null-terminated Unicode string in
4309 <ConfigResp> format.
4310 @param AccessProgress On return, points to a character in the Request
4311 string. Points to the string's null terminator if
4312 request was successful. Points to the most recent
4313 & before the first failing name / value pair (or
4314 the beginning of the string if the failure is in
4315 the first name / value pair) if the request was
4318 @retval EFI_SUCCESS The Results string is set to the full request string.
4319 And AltCfgResp contains all default value string.
4320 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
4321 @retval EFI_INVALID_PARAMETER Request points to NULL.
4325 GetConfigRespFromEfiVarStore (
4326 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
4327 IN EFI_IFR_VARSTORE_EFI
*EfiVarStoreInfo
,
4328 IN EFI_STRING Request
,
4329 OUT EFI_STRING
*RequestResp
,
4330 OUT EFI_STRING
*AccessProgress
4334 EFI_STRING VarStoreName
;
4339 Status
= EFI_SUCCESS
;
4342 VarStoreName
= NULL
;
4343 *AccessProgress
= Request
;
4345 NameSize
= AsciiStrSize ((CHAR8
*)EfiVarStoreInfo
->Name
);
4346 VarStoreName
= AllocateZeroPool (NameSize
* sizeof (CHAR16
));
4347 if (VarStoreName
== NULL
) {
4348 Status
= EFI_OUT_OF_RESOURCES
;
4351 AsciiStrToUnicodeStrS ((CHAR8
*) EfiVarStoreInfo
->Name
, VarStoreName
, NameSize
);
4354 Status
= gRT
->GetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, NULL
, &BufferSize
, NULL
);
4355 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
4359 VarStore
= AllocateZeroPool (BufferSize
);
4360 ASSERT (VarStore
!= NULL
);
4361 Status
= gRT
->GetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, NULL
, &BufferSize
, VarStore
);
4362 if (EFI_ERROR (Status
)) {
4366 Status
= HiiBlockToConfig(This
, Request
, VarStore
, BufferSize
, RequestResp
, AccessProgress
);
4367 if (EFI_ERROR (Status
)) {
4372 if (VarStoreName
!= NULL
) {
4373 FreePool (VarStoreName
);
4376 if (VarStore
!= NULL
) {
4377 FreePool (VarStore
);
4385 This function route the full request resp string for efi varstore.
4387 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
4389 @param EfiVarStoreInfo The efi varstore info which is save in the EFI
4390 varstore data structure.
4391 @param RequestResp Pointer to a null-terminated Unicode string in
4392 <ConfigResp> format.
4393 @param Result Pointer to a null-terminated Unicode string in
4394 <ConfigResp> format.
4396 @retval EFI_SUCCESS The Results string is set to the full request string.
4397 And AltCfgResp contains all default value string.
4398 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
4399 @retval EFI_INVALID_PARAMETER Request points to NULL.
4403 RouteConfigRespForEfiVarStore (
4404 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
4405 IN EFI_IFR_VARSTORE_EFI
*EfiVarStoreInfo
,
4406 IN EFI_STRING RequestResp
,
4407 OUT EFI_STRING
*Result
4411 EFI_STRING VarStoreName
;
4417 Status
= EFI_SUCCESS
;
4420 VarStoreName
= NULL
;
4421 *Result
= RequestResp
;
4423 NameSize
= AsciiStrSize ((CHAR8
*)EfiVarStoreInfo
->Name
);
4424 VarStoreName
= AllocateZeroPool (NameSize
* sizeof (CHAR16
));
4425 if (VarStoreName
== NULL
) {
4426 Status
= EFI_OUT_OF_RESOURCES
;
4429 AsciiStrToUnicodeStrS ((CHAR8
*) EfiVarStoreInfo
->Name
, VarStoreName
, NameSize
);
4431 Status
= gRT
->GetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, NULL
, &BufferSize
, NULL
);
4432 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
4433 DEBUG ((DEBUG_ERROR
, "The variable does not exist!"));
4437 BlockSize
= BufferSize
;
4438 VarStore
= AllocateZeroPool (BufferSize
);
4439 ASSERT (VarStore
!= NULL
);
4440 Status
= gRT
->GetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, NULL
, &BufferSize
, VarStore
);
4441 if (EFI_ERROR (Status
)) {
4445 Status
= HiiConfigToBlock(This
, RequestResp
, VarStore
, &BlockSize
, Result
);
4446 if (EFI_ERROR (Status
)) {
4450 Status
= gRT
->SetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, EfiVarStoreInfo
->Attributes
, BufferSize
, VarStore
);
4451 if (EFI_ERROR (Status
)) {
4452 *Result
= RequestResp
;
4457 if (VarStoreName
!= NULL
) {
4458 FreePool (VarStoreName
);
4461 if (VarStore
!= NULL
) {
4462 FreePool (VarStore
);
4469 Validate the config request elements.
4471 @param ConfigElements A null-terminated Unicode string in <ConfigRequest> format,
4472 without configHdr field.
4474 @retval CHAR16 * THE first Name/value pair not correct.
4475 @retval NULL Success parse the name/value pair
4478 OffsetWidthValidate (
4479 CHAR16
*ConfigElements
4485 StringPtr
= ConfigElements
;
4489 if (StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) != 0) {
4493 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
4496 if (*StringPtr
== L
'\0') {
4500 StringPtr
+= StrLen (L
"&WIDTH=");
4501 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) != 0) {
4505 if (*StringPtr
== L
'\0') {
4512 Validate the config request elements.
4514 @param ConfigElements A null-terminated Unicode string in <ConfigRequest> format,
4515 without configHdr field.
4517 @retval CHAR16 * THE first Name/value pair not correct.
4518 @retval NULL Success parse the name/value pair
4523 CHAR16
*ConfigElements
4529 StringPtr
= ConfigElements
;
4533 if (*StringPtr
!= L
'&') {
4538 StringPtr
= StrStr (StringPtr
, L
"&");
4540 if (StringPtr
== NULL
) {
4547 Validate the config request string.
4549 @param ConfigRequest A null-terminated Unicode string in <ConfigRequest> format.
4551 @retval CHAR16 * THE first element not correct.
4552 @retval NULL Success parse the name/value pair
4556 ConfigRequestValidate (
4557 CHAR16
*ConfigRequest
4560 BOOLEAN HasNameField
;
4563 HasNameField
= TRUE
;
4564 StringPtr
= ConfigRequest
;
4567 // Check <ConfigHdr>
4569 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
4570 return ConfigRequest
;
4572 StringPtr
+= StrLen (L
"GUID=");
4573 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&NAME=", StrLen (L
"&NAME=")) != 0) {
4576 if (*StringPtr
== L
'\0') {
4577 return ConfigRequest
;
4579 StringPtr
+= StrLen (L
"&NAME=");
4580 if (*StringPtr
== L
'&') {
4581 HasNameField
= FALSE
;
4583 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&PATH=", StrLen (L
"&PATH=")) != 0) {
4586 if (*StringPtr
== L
'\0') {
4587 return ConfigRequest
;
4589 StringPtr
+= StrLen (L
"&PATH=");
4590 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
4594 if (*StringPtr
== L
'\0') {
4600 // Should be Buffer varstore, config request should be "OFFSET/Width" pairs.
4602 return OffsetWidthValidate(StringPtr
);
4605 // Should be Name/Value varstore, config request should be "&name1&name2..." pairs.
4607 return NameValueValidate(StringPtr
);
4612 This function allows a caller to extract the current configuration
4613 for one or more named elements from one or more drivers.
4615 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
4617 @param Request A null-terminated Unicode string in
4618 <MultiConfigRequest> format.
4619 @param Progress On return, points to a character in the Request
4620 string. Points to the string's null terminator if
4621 request was successful. Points to the most recent
4622 & before the first failing name / value pair (or
4623 the beginning of the string if the failure is in
4624 the first name / value pair) if the request was
4626 @param Results Null-terminated Unicode string in
4627 <MultiConfigAltResp> format which has all values
4628 filled in for the names in the Request string.
4629 String to be allocated by the called function.
4631 @retval EFI_SUCCESS The Results string is filled with the values
4632 corresponding to all requested names.
4633 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
4634 results that must be stored awaiting possible
4636 @retval EFI_NOT_FOUND Routing data doesn't match any known driver.
4637 Progress set to the "G" in "GUID" of the routing
4638 header that doesn't match. Note: There is no
4639 requirement that all routing data be validated
4640 before any configuration extraction.
4641 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Request
4642 parameter would result in this type of error. The
4643 Progress parameter is set to NULL.
4644 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set to most recent &
4645 before the error or the beginning of the string.
4646 @retval EFI_INVALID_PARAMETER The ExtractConfig function of the underlying HII
4647 Configuration Access Protocol returned
4648 EFI_INVALID_PARAMETER. Progress set to most recent
4649 & before the error or the beginning of the string.
4654 HiiConfigRoutingExtractConfig (
4655 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
4656 IN CONST EFI_STRING Request
,
4657 OUT EFI_STRING
*Progress
,
4658 OUT EFI_STRING
*Results
4661 HII_DATABASE_PRIVATE_DATA
*Private
;
4662 EFI_STRING StringPtr
;
4663 EFI_STRING ConfigRequest
;
4665 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
4666 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
4669 HII_DATABASE_RECORD
*Database
;
4670 UINT8
*DevicePathPkg
;
4671 UINT8
*CurrentDevicePath
;
4672 EFI_HANDLE DriverHandle
;
4673 EFI_HII_HANDLE HiiHandle
;
4674 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
4675 EFI_STRING AccessProgress
;
4676 EFI_STRING AccessResults
;
4677 EFI_STRING AccessProgressBackup
;
4678 EFI_STRING AccessResultsBackup
;
4679 EFI_STRING DefaultResults
;
4680 BOOLEAN FirstElement
;
4681 BOOLEAN IfrDataParsedFlag
;
4682 BOOLEAN IsEfiVarStore
;
4683 EFI_IFR_VARSTORE_EFI
*EfiVarStoreInfo
;
4684 EFI_STRING ErrorPtr
;
4685 UINTN DevicePathSize
;
4686 UINTN ConigStringSize
;
4687 UINTN ConigStringSizeNewsize
;
4688 EFI_STRING ConfigStringPtr
;
4690 if (This
== NULL
|| Progress
== NULL
|| Results
== NULL
) {
4691 return EFI_INVALID_PARAMETER
;
4694 if (Request
== NULL
) {
4696 return EFI_INVALID_PARAMETER
;
4699 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
4700 StringPtr
= Request
;
4701 *Progress
= StringPtr
;
4702 DefaultResults
= NULL
;
4703 ConfigRequest
= NULL
;
4704 Status
= EFI_SUCCESS
;
4705 AccessResults
= NULL
;
4706 AccessProgress
= NULL
;
4707 AccessResultsBackup
= NULL
;
4708 AccessProgressBackup
= NULL
;
4710 IfrDataParsedFlag
= FALSE
;
4711 IsEfiVarStore
= FALSE
;
4712 EfiVarStoreInfo
= NULL
;
4715 // The first element of <MultiConfigRequest> should be
4716 // <GuidHdr>, which is in 'GUID='<Guid> syntax.
4718 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
4719 return EFI_INVALID_PARAMETER
;
4722 FirstElement
= TRUE
;
4725 // Allocate a fix length of memory to store Results. Reallocate memory for
4726 // Results if this fix length is insufficient.
4728 *Results
= (EFI_STRING
) AllocateZeroPool (MAX_STRING_LENGTH
);
4729 if (*Results
== NULL
) {
4730 return EFI_OUT_OF_RESOURCES
;
4733 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) == 0) {
4735 // If parsing error, set Progress to the beginning of the <MultiConfigRequest>
4736 // or most recent & before the error.
4738 if (StringPtr
== Request
) {
4739 *Progress
= StringPtr
;
4741 *Progress
= StringPtr
- 1;
4745 // Process each <ConfigRequest> of <MultiConfigRequest>
4747 Length
= CalculateConfigStringLen (StringPtr
);
4748 ConfigRequest
= AllocateCopyPool ((Length
+ 1) * sizeof (CHAR16
), StringPtr
);
4749 if (ConfigRequest
== NULL
) {
4750 Status
= EFI_OUT_OF_RESOURCES
;
4753 *(ConfigRequest
+ Length
) = 0;
4756 // Get the UEFI device path
4758 Status
= GetDevicePath (ConfigRequest
, (UINT8
**) &DevicePath
);
4759 if (EFI_ERROR (Status
)) {
4764 // Find driver which matches the routing data.
4766 DriverHandle
= NULL
;
4769 for (Link
= Private
->DatabaseList
.ForwardLink
;
4770 Link
!= &Private
->DatabaseList
;
4771 Link
= Link
->ForwardLink
4773 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
4774 if ((DevicePathPkg
= Database
->PackageList
->DevicePathPkg
) != NULL
) {
4775 CurrentDevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
4776 DevicePathSize
= GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) CurrentDevicePath
);
4777 if ((CompareMem (DevicePath
,CurrentDevicePath
,DevicePathSize
) == 0) && IsThisPackageList(Database
, ConfigRequest
)) {
4778 DriverHandle
= Database
->DriverHandle
;
4779 HiiHandle
= Database
->Handle
;
4786 // Try to find driver handle by device path.
4788 if (DriverHandle
== NULL
) {
4789 TempDevicePath
= DevicePath
;
4790 Status
= gBS
->LocateDevicePath (
4791 &gEfiDevicePathProtocolGuid
,
4795 if (EFI_ERROR (Status
) || (DriverHandle
== NULL
)) {
4797 // Routing data does not match any known driver.
4798 // Set Progress to the 'G' in "GUID" of the routing header.
4800 *Progress
= StringPtr
;
4801 Status
= EFI_NOT_FOUND
;
4807 // Validate ConfigRequest String.
4809 ErrorPtr
= ConfigRequestValidate(ConfigRequest
);
4810 if (ErrorPtr
!= NULL
) {
4811 *Progress
= StrStr (StringPtr
, ErrorPtr
);
4812 Status
= EFI_INVALID_PARAMETER
;
4817 // Check whether ConfigRequest contains request string.
4819 IfrDataParsedFlag
= FALSE
;
4820 if ((HiiHandle
!= NULL
) && !GetElementsFromRequest(ConfigRequest
)) {
4822 // Get the full request string from IFR when HiiPackage is registered to HiiHandle
4824 IfrDataParsedFlag
= TRUE
;
4825 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &ConfigRequest
, &DefaultResults
, &AccessProgress
);
4826 if (EFI_ERROR (Status
)) {
4828 // AccessProgress indicates the parsing progress on <ConfigRequest>.
4829 // Map it to the progress on <MultiConfigRequest> then return it.
4831 ASSERT (AccessProgress
!= NULL
);
4832 *Progress
= StrStr (StringPtr
, AccessProgress
);
4836 // Not any request block is found.
4838 if (!GetElementsFromRequest(ConfigRequest
)) {
4839 AccessResults
= AllocateCopyPool (StrSize (ConfigRequest
), ConfigRequest
);
4840 goto NextConfigString
;
4845 // Check whether this ConfigRequest is search from Efi varstore type storage.
4847 Status
= GetVarStoreType(Database
, ConfigRequest
, &IsEfiVarStore
, &EfiVarStoreInfo
);
4848 if (EFI_ERROR (Status
)) {
4852 if (IsEfiVarStore
) {
4854 // Call the GetVariable function to extract settings.
4856 Status
= GetConfigRespFromEfiVarStore(This
, EfiVarStoreInfo
, ConfigRequest
, &AccessResults
, &AccessProgress
);
4857 FreePool (EfiVarStoreInfo
);
4858 if (EFI_ERROR (Status
)) {
4860 // AccessProgress indicates the parsing progress on <ConfigRequest>.
4861 // Map it to the progress on <MultiConfigRequest> then return it.
4863 *Progress
= StrStr (StringPtr
, AccessProgress
);
4868 // For EfiVarstore, call corresponding ConfigAccess protocol to get the AltCfgResp from driver.
4870 Status
= gBS
->HandleProtocol (
4872 &gEfiHiiConfigAccessProtocolGuid
,
4873 (VOID
**) &ConfigAccess
4875 if (EFI_ERROR (Status
)) {
4877 // The driver has EfiVarStore, may not install ConfigAccess protocol.
4878 // So ignore the error status in this case.
4880 Status
= EFI_SUCCESS
;
4882 Status
= ConfigAccess
->ExtractConfig (
4885 &AccessProgressBackup
,
4886 &AccessResultsBackup
4888 if (!EFI_ERROR(Status
)) {
4890 //Merge the AltCfgResp in AccessResultsBackup to AccessResults
4892 if ((AccessResultsBackup
!= NULL
) && (StrStr (AccessResultsBackup
, L
"&ALTCFG=") != NULL
)) {
4893 ConigStringSize
= StrSize (AccessResults
);
4894 ConfigStringPtr
= StrStr (AccessResultsBackup
, L
"&GUID=");
4895 ConigStringSizeNewsize
= StrSize (ConfigStringPtr
) + ConigStringSize
+ sizeof (CHAR16
);
4896 AccessResults
= (EFI_STRING
) ReallocatePool (
4898 ConigStringSizeNewsize
,
4900 StrCatS (AccessResults
, ConigStringSizeNewsize
/ sizeof (CHAR16
), ConfigStringPtr
);
4904 // In the ExtractConfig function of some driver may not support EfiVarStore,
4905 // may return error status, just ignore the error status in this case.
4907 Status
= EFI_SUCCESS
;
4909 if (AccessResultsBackup
!= NULL
) {
4910 FreePool (AccessResultsBackup
);
4911 AccessResultsBackup
= NULL
;
4916 // Call corresponding ConfigAccess protocol to extract settings
4918 Status
= gBS
->HandleProtocol (
4920 &gEfiHiiConfigAccessProtocolGuid
,
4921 (VOID
**) &ConfigAccess
4923 if (EFI_ERROR (Status
)) {
4927 Status
= ConfigAccess
->ExtractConfig (
4934 if (EFI_ERROR (Status
)) {
4936 // AccessProgress indicates the parsing progress on <ConfigRequest>.
4937 // Map it to the progress on <MultiConfigRequest> then return it.
4939 *Progress
= StrStr (StringPtr
, AccessProgress
);
4944 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'
4945 // which separates the first <ConfigAltResp> and the following ones.
4947 ASSERT (*AccessProgress
== 0);
4950 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
4952 if (!IfrDataParsedFlag
&& HiiHandle
!= NULL
) {
4953 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &ConfigRequest
, &DefaultResults
, NULL
);
4954 ASSERT_EFI_ERROR (Status
);
4957 FreePool (DevicePath
);
4960 if (DefaultResults
!= NULL
) {
4961 Status
= MergeDefaultString (&AccessResults
, DefaultResults
);
4962 ASSERT_EFI_ERROR (Status
);
4963 FreePool (DefaultResults
);
4964 DefaultResults
= NULL
;
4968 if (!FirstElement
) {
4969 Status
= AppendToMultiString (Results
, L
"&");
4970 ASSERT_EFI_ERROR (Status
);
4973 Status
= AppendToMultiString (Results
, AccessResults
);
4974 ASSERT_EFI_ERROR (Status
);
4976 FirstElement
= FALSE
;
4978 FreePool (AccessResults
);
4979 AccessResults
= NULL
;
4980 FreePool (ConfigRequest
);
4981 ConfigRequest
= NULL
;
4984 // Go to next <ConfigRequest> (skip '&').
4986 StringPtr
+= Length
;
4987 if (*StringPtr
== 0) {
4988 *Progress
= StringPtr
;
4996 if (EFI_ERROR (Status
)) {
4997 FreePool (*Results
);
5001 if (ConfigRequest
!= NULL
) {
5002 FreePool (ConfigRequest
);
5005 if (AccessResults
!= NULL
) {
5006 FreePool (AccessResults
);
5009 if (DefaultResults
!= NULL
) {
5010 FreePool (DefaultResults
);
5013 if (DevicePath
!= NULL
) {
5014 FreePool (DevicePath
);
5022 This function allows the caller to request the current configuration for the
5023 entirety of the current HII database and returns the data in a
5024 null-terminated Unicode string.
5026 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
5028 @param Results Null-terminated Unicode string in
5029 <MultiConfigAltResp> format which has all values
5030 filled in for the entirety of the current HII
5031 database. String to be allocated by the called
5032 function. De-allocation is up to the caller.
5034 @retval EFI_SUCCESS The Results string is filled with the values
5035 corresponding to all requested names.
5036 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
5037 results that must be stored awaiting possible
5039 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Results
5040 parameter would result in this type of error.
5045 HiiConfigRoutingExportConfig (
5046 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
5047 OUT EFI_STRING
*Results
5051 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
5052 EFI_STRING AccessResults
;
5053 EFI_STRING Progress
;
5054 EFI_STRING StringPtr
;
5055 EFI_STRING ConfigRequest
;
5057 EFI_HANDLE
*ConfigAccessHandles
;
5058 UINTN NumberConfigAccessHandles
;
5059 BOOLEAN FirstElement
;
5060 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
5061 EFI_HII_HANDLE HiiHandle
;
5062 EFI_STRING DefaultResults
;
5063 HII_DATABASE_PRIVATE_DATA
*Private
;
5065 HII_DATABASE_RECORD
*Database
;
5066 UINT8
*DevicePathPkg
;
5067 UINT8
*CurrentDevicePath
;
5068 BOOLEAN IfrDataParsedFlag
;
5070 if (This
== NULL
|| Results
== NULL
) {
5071 return EFI_INVALID_PARAMETER
;
5074 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
5077 // Allocate a fix length of memory to store Results. Reallocate memory for
5078 // Results if this fix length is insufficient.
5080 *Results
= (EFI_STRING
) AllocateZeroPool (MAX_STRING_LENGTH
);
5081 if (*Results
== NULL
) {
5082 return EFI_OUT_OF_RESOURCES
;
5085 NumberConfigAccessHandles
= 0;
5086 Status
= gBS
->LocateHandleBuffer (
5088 &gEfiHiiConfigAccessProtocolGuid
,
5090 &NumberConfigAccessHandles
,
5091 &ConfigAccessHandles
5093 if (EFI_ERROR (Status
)) {
5097 FirstElement
= TRUE
;
5099 for (Index
= 0; Index
< NumberConfigAccessHandles
; Index
++) {
5100 Status
= gBS
->HandleProtocol (
5101 ConfigAccessHandles
[Index
],
5102 &gEfiHiiConfigAccessProtocolGuid
,
5103 (VOID
**) &ConfigAccess
5105 if (EFI_ERROR (Status
)) {
5110 // Get DevicePath and HiiHandle for this ConfigAccess driver handle
5112 IfrDataParsedFlag
= FALSE
;
5115 DefaultResults
= NULL
;
5117 ConfigRequest
= NULL
;
5118 DevicePath
= DevicePathFromHandle (ConfigAccessHandles
[Index
]);
5119 if (DevicePath
!= NULL
) {
5120 for (Link
= Private
->DatabaseList
.ForwardLink
;
5121 Link
!= &Private
->DatabaseList
;
5122 Link
= Link
->ForwardLink
5124 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
5125 if ((DevicePathPkg
= Database
->PackageList
->DevicePathPkg
) != NULL
) {
5126 CurrentDevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
5130 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) CurrentDevicePath
)
5132 HiiHandle
= Database
->Handle
;
5139 Status
= ConfigAccess
->ExtractConfig (
5145 if (EFI_ERROR (Status
)) {
5147 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
5149 if (HiiHandle
!= NULL
&& DevicePath
!= NULL
) {
5150 IfrDataParsedFlag
= TRUE
;
5151 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &ConfigRequest
, &DefaultResults
, NULL
);
5153 // Get the full request string to get the Current setting again.
5155 if (!EFI_ERROR (Status
) && ConfigRequest
!= NULL
) {
5156 Status
= ConfigAccess
->ExtractConfig (
5162 FreePool (ConfigRequest
);
5164 Status
= EFI_NOT_FOUND
;
5169 if (!EFI_ERROR (Status
)) {
5171 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
5173 if (!IfrDataParsedFlag
&& HiiHandle
!= NULL
&& DevicePath
!= NULL
) {
5174 StringPtr
= StrStr (AccessResults
, L
"&GUID=");
5175 if (StringPtr
!= NULL
) {
5178 if (GetElementsFromRequest (AccessResults
)) {
5179 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &AccessResults
, &DefaultResults
, NULL
);
5180 ASSERT_EFI_ERROR (Status
);
5182 if (StringPtr
!= NULL
) {
5187 // Merge the default sting from IFR code into the got setting from driver.
5189 if (DefaultResults
!= NULL
) {
5190 Status
= MergeDefaultString (&AccessResults
, DefaultResults
);
5191 ASSERT_EFI_ERROR (Status
);
5192 FreePool (DefaultResults
);
5193 DefaultResults
= NULL
;
5197 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'
5198 // which separates the first <ConfigAltResp> and the following ones.
5200 if (!FirstElement
) {
5201 Status
= AppendToMultiString (Results
, L
"&");
5202 ASSERT_EFI_ERROR (Status
);
5205 Status
= AppendToMultiString (Results
, AccessResults
);
5206 ASSERT_EFI_ERROR (Status
);
5208 FirstElement
= FALSE
;
5210 FreePool (AccessResults
);
5211 AccessResults
= NULL
;
5214 FreePool (ConfigAccessHandles
);
5221 This function processes the results of processing forms and routes it to the
5222 appropriate handlers or storage.
5224 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
5226 @param Configuration A null-terminated Unicode string in
5227 <MulltiConfigResp> format.
5228 @param Progress A pointer to a string filled in with the offset of
5229 the most recent & before the first failing name /
5230 value pair (or the beginning of the string if the
5231 failure is in the first name / value pair) or the
5232 terminating NULL if all was successful.
5234 @retval EFI_SUCCESS The results have been distributed or are awaiting
5236 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
5237 results that must be stored awaiting possible
5239 @retval EFI_INVALID_PARAMETER Passing in a NULL for the Configuration parameter
5240 would result in this type of error.
5241 @retval EFI_NOT_FOUND Target for the specified routing data was not
5247 HiiConfigRoutingRouteConfig (
5248 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
5249 IN CONST EFI_STRING Configuration
,
5250 OUT EFI_STRING
*Progress
5253 HII_DATABASE_PRIVATE_DATA
*Private
;
5254 EFI_STRING StringPtr
;
5255 EFI_STRING ConfigResp
;
5258 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
5259 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
5261 HII_DATABASE_RECORD
*Database
;
5262 UINT8
*DevicePathPkg
;
5263 UINT8
*CurrentDevicePath
;
5264 EFI_HANDLE DriverHandle
;
5265 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
5266 EFI_STRING AccessProgress
;
5267 EFI_IFR_VARSTORE_EFI
*EfiVarStoreInfo
;
5268 BOOLEAN IsEfiVarstore
;
5269 UINTN DevicePathSize
;
5271 if (This
== NULL
|| Progress
== NULL
) {
5272 return EFI_INVALID_PARAMETER
;
5275 if (Configuration
== NULL
) {
5277 return EFI_INVALID_PARAMETER
;
5280 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
5281 StringPtr
= Configuration
;
5282 *Progress
= StringPtr
;
5284 AccessProgress
= NULL
;
5285 EfiVarStoreInfo
= NULL
;
5286 IsEfiVarstore
= FALSE
;
5289 // The first element of <MultiConfigResp> should be
5290 // <GuidHdr>, which is in 'GUID='<Guid> syntax.
5292 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
5293 return EFI_INVALID_PARAMETER
;
5296 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) == 0) {
5298 // If parsing error, set Progress to the beginning of the <MultiConfigResp>
5299 // or most recent & before the error.
5301 if (StringPtr
== Configuration
) {
5302 *Progress
= StringPtr
;
5304 *Progress
= StringPtr
- 1;
5308 // Process each <ConfigResp> of <MultiConfigResp>
5310 Length
= CalculateConfigStringLen (StringPtr
);
5311 ConfigResp
= AllocateCopyPool ((Length
+ 1) * sizeof (CHAR16
), StringPtr
);
5312 if (ConfigResp
== NULL
) {
5313 return EFI_OUT_OF_RESOURCES
;
5316 // Append '\0' to the end of ConfigRequest
5318 *(ConfigResp
+ Length
) = 0;
5321 // Get the UEFI device path
5323 Status
= GetDevicePath (ConfigResp
, (UINT8
**) &DevicePath
);
5324 if (EFI_ERROR (Status
)) {
5325 FreePool (ConfigResp
);
5330 // Find driver which matches the routing data.
5332 DriverHandle
= NULL
;
5333 for (Link
= Private
->DatabaseList
.ForwardLink
;
5334 Link
!= &Private
->DatabaseList
;
5335 Link
= Link
->ForwardLink
5337 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
5339 if ((DevicePathPkg
= Database
->PackageList
->DevicePathPkg
) != NULL
) {
5340 CurrentDevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
5341 DevicePathSize
= GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) CurrentDevicePath
);
5342 if ((CompareMem (DevicePath
,CurrentDevicePath
,DevicePathSize
) == 0) && IsThisPackageList(Database
, ConfigResp
)) {
5343 DriverHandle
= Database
->DriverHandle
;
5350 // Try to find driver handle by device path.
5352 if (DriverHandle
== NULL
) {
5353 TempDevicePath
= DevicePath
;
5354 Status
= gBS
->LocateDevicePath (
5355 &gEfiDevicePathProtocolGuid
,
5359 if (EFI_ERROR (Status
) || (DriverHandle
== NULL
)) {
5361 // Routing data does not match any known driver.
5362 // Set Progress to the 'G' in "GUID" of the routing header.
5364 FreePool (DevicePath
);
5365 *Progress
= StringPtr
;
5366 FreePool (ConfigResp
);
5367 return EFI_NOT_FOUND
;
5371 FreePool (DevicePath
);
5374 // Check whether this ConfigRequest is search from Efi varstore type storage.
5376 Status
= GetVarStoreType(Database
, ConfigResp
, &IsEfiVarstore
, &EfiVarStoreInfo
);
5377 if (EFI_ERROR (Status
)) {
5381 if (IsEfiVarstore
) {
5383 // Call the SetVariable function to route settings.
5385 Status
= RouteConfigRespForEfiVarStore(This
, EfiVarStoreInfo
, ConfigResp
, &AccessProgress
);
5386 FreePool (EfiVarStoreInfo
);
5389 // Call corresponding ConfigAccess protocol to route settings
5391 Status
= gBS
->HandleProtocol (
5393 &gEfiHiiConfigAccessProtocolGuid
,
5394 (VOID
**) &ConfigAccess
5396 if (EFI_ERROR (Status
)) {
5397 *Progress
= StringPtr
;
5398 FreePool (ConfigResp
);
5399 return EFI_NOT_FOUND
;
5402 Status
= ConfigAccess
->RouteConfig (
5408 if (EFI_ERROR (Status
)) {
5409 ASSERT (AccessProgress
!= NULL
);
5411 // AccessProgress indicates the parsing progress on <ConfigResp>.
5412 // Map it to the progress on <MultiConfigResp> then return it.
5414 *Progress
= StrStr (StringPtr
, AccessProgress
);
5416 FreePool (ConfigResp
);
5420 FreePool (ConfigResp
);
5424 // Go to next <ConfigResp> (skip '&').
5426 StringPtr
+= Length
;
5427 if (*StringPtr
== 0) {
5428 *Progress
= StringPtr
;
5441 This helper function is to be called by drivers to map configuration data
5442 stored in byte array ("block") formats such as UEFI Variables into current
5443 configuration strings.
5445 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
5447 @param ConfigRequest A null-terminated Unicode string in
5448 <ConfigRequest> format.
5449 @param Block Array of bytes defining the block's configuration.
5450 @param BlockSize Length in bytes of Block.
5451 @param Config Filled-in configuration string. String allocated
5452 by the function. Returned only if call is
5453 successful. It is <ConfigResp> string format.
5454 @param Progress A pointer to a string filled in with the offset of
5455 the most recent & before the first failing
5456 name/value pair (or the beginning of the string if
5457 the failure is in the first name / value pair) or
5458 the terminating NULL if all was successful.
5460 @retval EFI_SUCCESS The request succeeded. Progress points to the null
5461 terminator at the end of the ConfigRequest
5463 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress
5464 points to the first character of ConfigRequest.
5465 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigRequest or
5466 Block parameter would result in this type of
5467 error. Progress points to the first character of
5469 @retval EFI_DEVICE_ERROR Block not large enough. Progress undefined.
5470 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted string.
5471 Block is left updated and Progress points at
5472 the "&" preceding the first non-<BlockName>.
5478 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
5479 IN CONST EFI_STRING ConfigRequest
,
5480 IN CONST UINT8
*Block
,
5481 IN CONST UINTN BlockSize
,
5482 OUT EFI_STRING
*Config
,
5483 OUT EFI_STRING
*Progress
5486 HII_DATABASE_PRIVATE_DATA
*Private
;
5487 EFI_STRING StringPtr
;
5495 EFI_STRING ValueStr
;
5496 EFI_STRING ConfigElement
;
5503 if (This
== NULL
|| Progress
== NULL
|| Config
== NULL
) {
5504 return EFI_INVALID_PARAMETER
;
5507 if (Block
== NULL
|| ConfigRequest
== NULL
) {
5508 *Progress
= ConfigRequest
;
5509 return EFI_INVALID_PARAMETER
;
5513 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
5514 ASSERT (Private
!= NULL
);
5516 StringPtr
= ConfigRequest
;
5519 ConfigElement
= NULL
;
5522 // Allocate a fix length of memory to store Results. Reallocate memory for
5523 // Results if this fix length is insufficient.
5525 *Config
= (EFI_STRING
) AllocateZeroPool (MAX_STRING_LENGTH
);
5526 if (*Config
== NULL
) {
5527 return EFI_OUT_OF_RESOURCES
;
5533 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
5534 *Progress
= StringPtr
;
5535 Status
= EFI_INVALID_PARAMETER
;
5538 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"PATH=", StrLen (L
"PATH=")) != 0) {
5541 if (*StringPtr
== 0) {
5542 *Progress
= StringPtr
- 1;
5543 Status
= EFI_INVALID_PARAMETER
;
5547 while (*StringPtr
!= L
'&' && *StringPtr
!= 0) {
5550 if (*StringPtr
== 0) {
5551 *Progress
= StringPtr
;
5553 AppendToMultiString(Config
, ConfigRequest
);
5554 HiiToLower (*Config
);
5564 // Copy <ConfigHdr> and an additional '&' to <ConfigResp>
5566 TemString
= AllocateCopyPool (sizeof (CHAR16
) * (StringPtr
- ConfigRequest
+ 1), ConfigRequest
);
5567 if (TemString
== NULL
) {
5568 return EFI_OUT_OF_RESOURCES
;
5570 TemString
[StringPtr
- ConfigRequest
] = '\0';
5571 AppendToMultiString(Config
, TemString
);
5572 FreePool (TemString
);
5575 // Parse each <RequestElement> if exists
5576 // Only <BlockName> format is supported by this help function.
5577 // <BlockName> ::= 'OFFSET='<Number>&'WIDTH='<Number>
5579 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"OFFSET=", StrLen (L
"OFFSET=")) == 0) {
5581 // Back up the header of one <BlockName>
5585 StringPtr
+= StrLen (L
"OFFSET=");
5589 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
5590 if (EFI_ERROR (Status
)) {
5591 *Progress
= TmpPtr
- 1;
5598 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
5600 FreePool (TmpBuffer
);
5602 StringPtr
+= Length
;
5603 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
5604 *Progress
= TmpPtr
- 1;
5605 Status
= EFI_INVALID_PARAMETER
;
5608 StringPtr
+= StrLen (L
"&WIDTH=");
5613 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
5614 if (EFI_ERROR (Status
)) {
5615 *Progress
= TmpPtr
- 1;
5622 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
5624 FreePool (TmpBuffer
);
5626 StringPtr
+= Length
;
5627 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
5628 *Progress
= TmpPtr
- 1;
5629 Status
= EFI_INVALID_PARAMETER
;
5634 // Calculate Value and convert it to hex string.
5636 if (Offset
+ Width
> BlockSize
) {
5637 *Progress
= StringPtr
;
5638 Status
= EFI_DEVICE_ERROR
;
5642 Value
= (UINT8
*) AllocateZeroPool (Width
);
5643 if (Value
== NULL
) {
5644 *Progress
= ConfigRequest
;
5645 Status
= EFI_OUT_OF_RESOURCES
;
5649 CopyMem (Value
, (UINT8
*) Block
+ Offset
, Width
);
5651 Length
= Width
* 2 + 1;
5652 ValueStr
= (EFI_STRING
) AllocateZeroPool (Length
* sizeof (CHAR16
));
5653 if (ValueStr
== NULL
) {
5654 *Progress
= ConfigRequest
;
5655 Status
= EFI_OUT_OF_RESOURCES
;
5659 TemString
= ValueStr
;
5660 TemBuffer
= Value
+ Width
- 1;
5661 for (Index
= 0; Index
< Width
; Index
++, TemBuffer
--) {
5662 UnicodeValueToStringS (
5664 Length
* sizeof (CHAR16
) - ((UINTN
)TemString
- (UINTN
)ValueStr
),
5665 PREFIX_ZERO
| RADIX_HEX
,
5669 TemString
+= StrnLenS (TemString
, Length
- ((UINTN
)TemString
- (UINTN
)ValueStr
) / sizeof (CHAR16
));
5676 // Build a ConfigElement
5678 Length
+= StringPtr
- TmpPtr
+ 1 + StrLen (L
"VALUE=");
5679 ConfigElement
= (EFI_STRING
) AllocateZeroPool (Length
* sizeof (CHAR16
));
5680 if (ConfigElement
== NULL
) {
5681 Status
= EFI_OUT_OF_RESOURCES
;
5684 CopyMem (ConfigElement
, TmpPtr
, (StringPtr
- TmpPtr
+ 1) * sizeof (CHAR16
));
5685 if (*StringPtr
== 0) {
5686 *(ConfigElement
+ (StringPtr
- TmpPtr
)) = L
'&';
5688 *(ConfigElement
+ (StringPtr
- TmpPtr
) + 1) = 0;
5689 StrCatS (ConfigElement
, Length
, L
"VALUE=");
5690 StrCatS (ConfigElement
, Length
, ValueStr
);
5692 AppendToMultiString (Config
, ConfigElement
);
5694 FreePool (ConfigElement
);
5695 FreePool (ValueStr
);
5696 ConfigElement
= NULL
;
5700 // If '\0', parsing is finished. Otherwise skip '&' to continue
5702 if (*StringPtr
== 0) {
5705 AppendToMultiString (Config
, L
"&");
5710 if (*StringPtr
!= 0) {
5711 *Progress
= StringPtr
- 1;
5712 Status
= EFI_INVALID_PARAMETER
;
5716 HiiToLower (*Config
);
5717 *Progress
= StringPtr
;
5721 if (*Config
!= NULL
) {
5725 if (ValueStr
!= NULL
) {
5726 FreePool (ValueStr
);
5728 if (Value
!= NULL
) {
5731 if (ConfigElement
!= NULL
) {
5732 FreePool (ConfigElement
);
5741 This helper function is to be called by drivers to map configuration strings
5742 to configurations stored in byte array ("block") formats such as UEFI Variables.
5744 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
5746 @param ConfigResp A null-terminated Unicode string in <ConfigResp>
5748 @param Block A possibly null array of bytes representing the
5749 current block. Only bytes referenced in the
5750 ConfigResp string in the block are modified. If
5751 this parameter is null or if the *BlockSize
5752 parameter is (on input) shorter than required by
5753 the Configuration string, only the BlockSize
5754 parameter is updated and an appropriate status
5755 (see below) is returned.
5756 @param BlockSize The length of the Block in units of UINT8. On
5757 input, this is the size of the Block. On output,
5758 if successful, contains the largest index of the
5759 modified byte in the Block, or the required buffer
5760 size if the Block is not large enough.
5761 @param Progress On return, points to an element of the ConfigResp
5762 string filled in with the offset of the most
5763 recent '&' before the first failing name / value
5764 pair (or the beginning of the string if the
5765 failure is in the first name / value pair) or the
5766 terminating NULL if all was successful.
5768 @retval EFI_SUCCESS The request succeeded. Progress points to the null
5769 terminator at the end of the ConfigResp string.
5770 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress
5771 points to the first character of ConfigResp.
5772 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigResp or
5773 Block parameter would result in this type of
5774 error. Progress points to the first character of
5776 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted name /
5777 value pair. Block is left updated and
5778 Progress points at the '&' preceding the first
5780 @retval EFI_BUFFER_TOO_SMALL Block not large enough. Progress undefined.
5781 BlockSize is updated with the required buffer size.
5782 @retval EFI_NOT_FOUND Target for the specified routing data was not found.
5783 Progress points to the "G" in "GUID" of the errant
5790 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
5791 IN CONST EFI_STRING ConfigResp
,
5792 IN OUT UINT8
*Block
,
5793 IN OUT UINTN
*BlockSize
,
5794 OUT EFI_STRING
*Progress
5797 HII_DATABASE_PRIVATE_DATA
*Private
;
5798 EFI_STRING StringPtr
;
5811 if (This
== NULL
|| BlockSize
== NULL
|| Progress
== NULL
) {
5812 return EFI_INVALID_PARAMETER
;
5815 *Progress
= ConfigResp
;
5816 if (ConfigResp
== NULL
) {
5817 return EFI_INVALID_PARAMETER
;
5820 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
5821 ASSERT (Private
!= NULL
);
5823 StringPtr
= ConfigResp
;
5824 BufferSize
= *BlockSize
;
5831 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
5832 *Progress
= StringPtr
;
5833 Status
= EFI_INVALID_PARAMETER
;
5836 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"PATH=", StrLen (L
"PATH=")) != 0) {
5839 if (*StringPtr
== 0) {
5840 *Progress
= StringPtr
;
5841 Status
= EFI_INVALID_PARAMETER
;
5845 while (*StringPtr
!= L
'&' && *StringPtr
!= 0) {
5848 if (*StringPtr
== 0) {
5849 *Progress
= StringPtr
;
5850 Status
= EFI_INVALID_PARAMETER
;
5855 // Parse each <ConfigElement> if exists
5856 // Only '&'<BlockConfig> format is supported by this help function.
5857 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE='<Number>
5859 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) == 0) {
5861 StringPtr
+= StrLen (L
"&OFFSET=");
5865 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
5866 if (EFI_ERROR (Status
)) {
5874 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
5876 FreePool (TmpBuffer
);
5878 StringPtr
+= Length
;
5879 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
5881 Status
= EFI_INVALID_PARAMETER
;
5884 StringPtr
+= StrLen (L
"&WIDTH=");
5889 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
5890 if (EFI_ERROR (Status
)) {
5898 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
5900 FreePool (TmpBuffer
);
5902 StringPtr
+= Length
;
5903 if (StrnCmp (StringPtr
, L
"&VALUE=", StrLen (L
"&VALUE=")) != 0) {
5905 Status
= EFI_INVALID_PARAMETER
;
5908 StringPtr
+= StrLen (L
"&VALUE=");
5913 Status
= GetValueOfNumber (StringPtr
, &Value
, &Length
);
5914 if (EFI_ERROR (Status
)) {
5919 StringPtr
+= Length
;
5920 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
5922 Status
= EFI_INVALID_PARAMETER
;
5927 // Update the Block with configuration info
5929 if ((Block
!= NULL
) && (Offset
+ Width
<= BufferSize
)) {
5930 CopyMem (Block
+ Offset
, Value
, Width
);
5932 if (Offset
+ Width
> MaxBlockSize
) {
5933 MaxBlockSize
= Offset
+ Width
;
5940 // If '\0', parsing is finished.
5942 if (*StringPtr
== 0) {
5948 // The input string is not ConfigResp format, return error.
5950 if (*StringPtr
!= 0) {
5951 *Progress
= StringPtr
;
5952 Status
= EFI_INVALID_PARAMETER
;
5956 *Progress
= StringPtr
+ StrLen (StringPtr
);
5957 *BlockSize
= MaxBlockSize
- 1;
5959 if (MaxBlockSize
> BufferSize
) {
5960 *BlockSize
= MaxBlockSize
;
5961 if (Block
!= NULL
) {
5962 return EFI_BUFFER_TOO_SMALL
;
5966 if (Block
== NULL
) {
5967 *Progress
= ConfigResp
;
5968 return EFI_INVALID_PARAMETER
;
5975 if (Value
!= NULL
) {
5983 This helper function is to be called by drivers to extract portions of
5984 a larger configuration string.
5986 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
5988 @param Configuration A null-terminated Unicode string in
5989 <MultiConfigAltResp> format.
5990 @param Guid A pointer to the GUID value to search for in the
5991 routing portion of the ConfigResp string when
5992 retrieving the requested data. If Guid is NULL,
5993 then all GUID values will be searched for.
5994 @param Name A pointer to the NAME value to search for in the
5995 routing portion of the ConfigResp string when
5996 retrieving the requested data. If Name is NULL,
5997 then all Name values will be searched for.
5998 @param DevicePath A pointer to the PATH value to search for in the
5999 routing portion of the ConfigResp string when
6000 retrieving the requested data. If DevicePath is
6001 NULL, then all DevicePath values will be searched
6003 @param AltCfgId A pointer to the ALTCFG value to search for in the
6004 routing portion of the ConfigResp string when
6005 retrieving the requested data. If this parameter
6006 is NULL, then the current setting will be
6008 @param AltCfgResp A pointer to a buffer which will be allocated by
6009 the function which contains the retrieved string
6010 as requested. This buffer is only allocated if
6011 the call was successful. It is <ConfigResp> format.
6013 @retval EFI_SUCCESS The request succeeded. The requested data was
6014 extracted and placed in the newly allocated
6016 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate AltCfgResp.
6017 @retval EFI_INVALID_PARAMETER Any parameter is invalid.
6018 @retval EFI_NOT_FOUND Target for the specified routing data was not
6025 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
6026 IN CONST EFI_STRING Configuration
,
6027 IN CONST EFI_GUID
*Guid
,
6028 IN CONST EFI_STRING Name
,
6029 IN CONST EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
6030 IN CONST UINT16
*AltCfgId
,
6031 OUT EFI_STRING
*AltCfgResp
6035 EFI_STRING StringPtr
;
6036 EFI_STRING HdrStart
;
6043 EFI_STRING AltIdStr
;
6060 if (This
== NULL
|| Configuration
== NULL
|| AltCfgResp
== NULL
) {
6061 return EFI_INVALID_PARAMETER
;
6064 StringPtr
= Configuration
;
6065 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
6066 return EFI_INVALID_PARAMETER
;
6070 // Generate the sub string for later matching.
6072 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*) Guid
, 1, &GuidStr
);
6075 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) DevicePath
),
6076 (VOID
*) DevicePath
,
6080 if (AltCfgId
!= NULL
) {
6081 GenerateSubStr (L
"ALTCFG=", sizeof (UINT16
), (VOID
*) AltCfgId
, 3, &AltIdStr
);
6084 GenerateSubStr (L
"NAME=", StrLen (Name
) * sizeof (CHAR16
), (VOID
*) Name
, 2, &NameStr
);
6086 GenerateSubStr (L
"NAME=", 0, NULL
, 2, &NameStr
);
6089 while (*StringPtr
!= 0) {
6091 // Try to match the GUID
6094 TmpPtr
= StrStr (StringPtr
, GuidStr
);
6095 if (TmpPtr
== NULL
) {
6096 Status
= EFI_NOT_FOUND
;
6102 // Jump to <NameHdr>
6105 StringPtr
= TmpPtr
+ StrLen (GuidStr
);
6107 StringPtr
= StrStr (TmpPtr
, L
"NAME=");
6108 if (StringPtr
== NULL
) {
6109 Status
= EFI_NOT_FOUND
;
6117 // Try to match the NAME
6119 if (GuidFlag
&& !NameFlag
) {
6120 if (StrnCmp (StringPtr
, NameStr
, StrLen (NameStr
)) != 0) {
6124 // Jump to <PathHdr>
6127 StringPtr
+= StrLen (NameStr
);
6129 StringPtr
= StrStr (StringPtr
, L
"PATH=");
6130 if (StringPtr
== NULL
) {
6131 Status
= EFI_NOT_FOUND
;
6140 // Try to match the DevicePath
6142 if (GuidFlag
&& NameFlag
&& !PathFlag
) {
6143 if (StrnCmp (StringPtr
, PathStr
, StrLen (PathStr
)) != 0) {
6148 // Jump to '&' before <DescHdr> or <ConfigBody>
6150 if (DevicePath
!= NULL
) {
6151 StringPtr
+= StrLen (PathStr
);
6153 StringPtr
= StrStr (StringPtr
, L
"&");
6154 if (StringPtr
== NULL
) {
6155 Status
= EFI_NOT_FOUND
;
6166 // Try to match the AltCfgId
6168 if (GuidFlag
&& NameFlag
&& PathFlag
) {
6169 if (AltCfgId
== NULL
) {
6171 // Return Current Setting when AltCfgId is NULL.
6173 Status
= OutputConfigBody (StringPtr
, &Result
);
6177 // Search the <ConfigAltResp> to get the <AltResp> with AltCfgId.
6179 if (StrnCmp (StringPtr
, AltIdStr
, StrLen (AltIdStr
)) != 0) {
6185 // Skip AltIdStr and &
6187 StringPtr
= StringPtr
+ StrLen (AltIdStr
);
6188 Status
= OutputConfigBody (StringPtr
, &Result
);
6194 Status
= EFI_NOT_FOUND
;
6198 if (!EFI_ERROR (Status
) && (Result
!= NULL
)) {
6200 // Copy the <ConfigHdr> and <ConfigBody>
6202 Length
= HdrEnd
- HdrStart
+ StrLen (Result
) + 1;
6203 *AltCfgResp
= AllocateZeroPool (Length
* sizeof (CHAR16
));
6204 if (*AltCfgResp
== NULL
) {
6205 Status
= EFI_OUT_OF_RESOURCES
;
6207 StrnCpyS (*AltCfgResp
, Length
, HdrStart
, HdrEnd
- HdrStart
);
6208 StrCatS (*AltCfgResp
, Length
, Result
);
6209 Status
= EFI_SUCCESS
;
6213 if (GuidStr
!= NULL
) {
6216 if (NameStr
!= NULL
) {
6219 if (PathStr
!= NULL
) {
6222 if (AltIdStr
!= NULL
) {
6223 FreePool (AltIdStr
);
6225 if (Result
!= NULL
) {