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 StringPtrNext
= StrStr (StringPtr
+ 1, L
"&GUID");
913 if (StringPtrNext
!= NULL
) {
914 TempCharA
= *StringPtrNext
;
915 *StringPtrNext
= L
'\0';
918 // Copy the content of <ConfigAltResp> which contain current AltConfigHdr in AltCfgResp.
920 ConfigAltResp
= AllocateCopyPool (StrSize (*AltCfgResp
), *AltCfgResp
);
921 if (ConfigAltResp
== NULL
) {
925 // To find the <ConfigBody> with AltConfigHdr in DefaultAltCfgResp.
927 BlockPtr
= StrStr (AltConfigHdrPtr
, L
"&OFFSET=");
928 if (BlockPtr
!= NULL
) {
930 // <BlockConfig>::='OFFSET='<Number>'&WIDTH='<Number>'&VALUE='<Number> style.
931 // Call function CompareBlockElementDefault to compare the <BlockConfig> in DefaultAltCfgResp and ConfigAltResp.
932 // The ConfigAltResp which may contain the new <BlockConfig> get from DefaultAltCfgResp.
934 Status
= CompareBlockElementDefault (DefaultAltCfgResp
, &ConfigAltResp
, AltConfigHdr
, &ConfigAltRespChanged
);
935 if (EFI_ERROR(Status
)) {
940 // <NvConfig> ::= <Label>'='<String> | <Label>'='<Number> style.
941 // Call function CompareNameElementDefault to compare the <NvConfig> in DefaultAltCfgResp and ConfigAltResp.
942 // The ConfigAltResp which may contain the new <NvConfig> get from DefaultAltCfgResp.
944 Status
= CompareNameElementDefault (DefaultAltCfgResp
, &ConfigAltResp
, AltConfigHdr
, &ConfigAltRespChanged
);
945 if (EFI_ERROR(Status
)) {
950 // Restore the AltCfgResp.
952 if (StringPtrNext
!= NULL
) {
953 *StringPtrNext
= TempCharA
;
957 // If the ConfigAltResp has no change,no need to update the content in AltCfgResp.
959 if (!ConfigAltRespChanged
) {
960 Status
= EFI_SUCCESS
;
964 // ConfigAltResp has been changed, need to update the content in AltCfgResp.
966 if (StringPtrNext
!= NULL
) {
967 ReallocateSize
= StrSize (ConfigAltResp
) + StrSize (StringPtrNext
) + sizeof (CHAR16
);
969 ReallocateSize
= StrSize (ConfigAltResp
) + sizeof (CHAR16
);
972 AltCfgRespBackup
= (EFI_STRING
) AllocateZeroPool (ReallocateSize
);
973 if (AltCfgRespBackup
== NULL
) {
977 StrCatS (AltCfgRespBackup
, ReallocateSize
/ sizeof (CHAR16
), ConfigAltResp
);
978 if (StringPtrNext
!= NULL
) {
979 StrCatS (AltCfgRespBackup
, ReallocateSize
/ sizeof (CHAR16
), StringPtrNext
);
982 FreePool (*AltCfgResp
);
983 *AltCfgResp
= AltCfgRespBackup
;
985 Status
= EFI_SUCCESS
;
988 if (ConfigAltResp
!= NULL
) {
989 FreePool(ConfigAltResp
);
992 // Restore the DefaultAltCfgResp.
994 if ( AltConfigHdrPtrNext
!= NULL
) {
995 *AltConfigHdrPtrNext
= TempChar
;
996 AltConfigHdrPtrNext
= NULL
;
1003 This function merges DefaultAltCfgResp string into AltCfgResp string for
1004 the missing AltCfgId in AltCfgResq.
1006 @param AltCfgResp Pointer to a null-terminated Unicode string in
1007 <ConfigAltResp> format. The default value string
1008 will be merged into it.
1009 @param DefaultAltCfgResp Pointer to a null-terminated Unicode string in
1010 <MultiConfigAltResp> format. The default value
1011 string may contain more than one ConfigAltResp
1012 string for the different varstore buffer.
1014 @retval EFI_SUCCESS The merged string returns.
1015 @retval EFI_INVALID_PARAMETER *AltCfgResp is to NULL.
1019 MergeDefaultString (
1020 IN OUT EFI_STRING
*AltCfgResp
,
1021 IN EFI_STRING DefaultAltCfgResp
1024 EFI_STRING StringPtrDefault
;
1025 EFI_STRING StringPtrEnd
;
1027 EFI_STRING StringPtr
;
1028 EFI_STRING AltConfigHdr
;
1030 UINTN SizeAltCfgResp
;
1034 if (*AltCfgResp
== NULL
) {
1035 return EFI_INVALID_PARAMETER
;
1039 // Get the request ConfigHdr
1042 StringPtr
= *AltCfgResp
;
1045 // Find <ConfigHdr> GUID=...&NAME=...&PATH=...
1047 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
1048 return EFI_INVALID_PARAMETER
;
1050 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&NAME=", StrLen (L
"&NAME=")) != 0) {
1053 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&PATH=", StrLen (L
"&PATH=")) != 0) {
1056 if (*StringPtr
== L
'\0') {
1057 return EFI_INVALID_PARAMETER
;
1059 StringPtr
+= StrLen (L
"&PATH=");
1060 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
1063 HeaderLength
= StringPtr
- *AltCfgResp
;
1066 // Construct AltConfigHdr string "&<ConfigHdr>&ALTCFG=XXXX\0"
1067 // |1| StrLen (ConfigHdr) | 8 | 4 | 1 |
1069 MaxLen
= 1 + HeaderLength
+ 8 + 4 + 1;
1070 AltConfigHdr
= AllocateZeroPool (MaxLen
* sizeof (CHAR16
));
1071 if (AltConfigHdr
== NULL
) {
1072 return EFI_OUT_OF_RESOURCES
;
1074 StrCpyS (AltConfigHdr
, MaxLen
, L
"&");
1075 StrnCatS (AltConfigHdr
, MaxLen
, *AltCfgResp
, HeaderLength
);
1076 StrCatS (AltConfigHdr
, MaxLen
, L
"&ALTCFG=");
1077 HeaderLength
= StrLen (AltConfigHdr
);
1079 StringPtrDefault
= StrStr (DefaultAltCfgResp
, AltConfigHdr
);
1080 while (StringPtrDefault
!= NULL
) {
1084 StrnCatS (AltConfigHdr
, MaxLen
, StringPtrDefault
+ HeaderLength
, 4);
1085 StringPtr
= StrStr (*AltCfgResp
, AltConfigHdr
);
1088 // Append the found default value string to the input AltCfgResp
1090 if (StringPtr
== NULL
) {
1091 StringPtrEnd
= StrStr (StringPtrDefault
+ 1, L
"&GUID");
1092 SizeAltCfgResp
= StrSize (*AltCfgResp
);
1093 if (StringPtrEnd
== NULL
) {
1095 // No more default string is found.
1097 TotalSize
= SizeAltCfgResp
+ StrSize (StringPtrDefault
);
1098 *AltCfgResp
= (EFI_STRING
) ReallocatePool (
1101 (VOID
*) (*AltCfgResp
)
1103 if (*AltCfgResp
== NULL
) {
1104 FreePool (AltConfigHdr
);
1105 return EFI_OUT_OF_RESOURCES
;
1107 StrCatS (*AltCfgResp
, TotalSize
/ sizeof (CHAR16
), StringPtrDefault
);
1110 TempChar
= *StringPtrEnd
;
1111 *StringPtrEnd
= L
'\0';
1112 TotalSize
= SizeAltCfgResp
+ StrSize (StringPtrDefault
);
1113 *AltCfgResp
= (EFI_STRING
) ReallocatePool (
1116 (VOID
*) (*AltCfgResp
)
1118 if (*AltCfgResp
== NULL
) {
1119 FreePool (AltConfigHdr
);
1120 return EFI_OUT_OF_RESOURCES
;
1122 StrCatS (*AltCfgResp
, TotalSize
/ sizeof (CHAR16
), StringPtrDefault
);
1123 *StringPtrEnd
= TempChar
;
1127 // The AltCfgResp contains <AltCfgResp>.
1128 // If the <ConfigElement> in <AltCfgResp> in the DefaultAltCfgResp but not in the
1129 // related <AltCfgResp> in AltCfgResp, merge it to AltCfgResp. else no need to merge.
1131 CompareAndMergeDefaultString (AltCfgResp
, DefaultAltCfgResp
, AltConfigHdr
);
1135 // Find next AltCfg String
1137 *(AltConfigHdr
+ HeaderLength
) = L
'\0';
1138 StringPtrDefault
= StrStr (StringPtrDefault
+ 1, AltConfigHdr
);
1141 FreePool (AltConfigHdr
);
1146 This function inserts new DefaultValueData into the BlockData DefaultValue array.
1148 @param BlockData The BlockData is updated to add new default value.
1149 @param DefaultValueData The DefaultValue is added.
1153 InsertDefaultValue (
1154 IN IFR_BLOCK_DATA
*BlockData
,
1155 IN IFR_DEFAULT_DATA
*DefaultValueData
1159 IFR_DEFAULT_DATA
*DefaultValueArray
;
1160 LIST_ENTRY
*DefaultLink
;
1162 DefaultLink
= &BlockData
->DefaultValueEntry
;
1164 for (Link
= DefaultLink
->ForwardLink
; Link
!= DefaultLink
; Link
= Link
->ForwardLink
) {
1165 DefaultValueArray
= BASE_CR (Link
, IFR_DEFAULT_DATA
, Entry
);
1166 if (DefaultValueArray
->DefaultId
== DefaultValueData
->DefaultId
) {
1168 // DEFAULT_VALUE_FROM_OPCODE has high priority, DEFAULT_VALUE_FROM_DEFAULT has low priority.
1169 // When default types are DEFAULT_VALUE_FROM_OTHER_DEFAULT, the default value can be overrode.
1171 if ((DefaultValueData
->Type
> DefaultValueArray
->Type
) || (DefaultValueData
->Type
== DefaultValueArray
->Type
&& DefaultValueData
->Type
== DefaultValueFromOtherDefault
)) {
1173 // Update the default value array in BlockData.
1175 CopyMem (&DefaultValueArray
->Value
, &DefaultValueData
->Value
, sizeof (EFI_IFR_TYPE_VALUE
));
1176 DefaultValueArray
->Type
= DefaultValueData
->Type
;
1177 DefaultValueArray
->Cleaned
= DefaultValueData
->Cleaned
;
1184 // Insert new default value data in tail.
1186 DefaultValueArray
= AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
1187 ASSERT (DefaultValueArray
!= NULL
);
1188 CopyMem (DefaultValueArray
, DefaultValueData
, sizeof (IFR_DEFAULT_DATA
));
1189 InsertTailList (Link
, &DefaultValueArray
->Entry
);
1193 This function inserts new BlockData into the block link
1195 @param BlockLink The list entry points to block array.
1196 @param BlockData The point to BlockData is added.
1201 IN LIST_ENTRY
*BlockLink
,
1202 IN IFR_BLOCK_DATA
**BlockData
1206 IFR_BLOCK_DATA
*BlockArray
;
1207 IFR_BLOCK_DATA
*BlockSingleData
;
1209 BlockSingleData
= *BlockData
;
1211 if (BlockSingleData
->Name
!= NULL
) {
1212 InsertTailList (BlockLink
, &BlockSingleData
->Entry
);
1217 // Insert block data in its Offset and Width order.
1219 for (Link
= BlockLink
->ForwardLink
; Link
!= BlockLink
; Link
= Link
->ForwardLink
) {
1220 BlockArray
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
1221 if (BlockArray
->Offset
== BlockSingleData
->Offset
) {
1222 if ((BlockArray
->Width
> BlockSingleData
->Width
) || (BlockSingleData
->IsBitVar
&& BlockArray
->Width
== BlockSingleData
->Width
)) {
1224 // Insert this block data in the front of block array
1226 InsertTailList (Link
, &BlockSingleData
->Entry
);
1230 if ((!BlockSingleData
->IsBitVar
) && BlockArray
->Width
== BlockSingleData
->Width
) {
1232 // The same block array has been added.
1234 if (BlockSingleData
!= BlockArray
) {
1235 FreePool (BlockSingleData
);
1236 *BlockData
= BlockArray
;
1240 } else if (BlockArray
->Offset
> BlockSingleData
->Offset
) {
1242 // Insert new block data in the front of block array
1244 InsertTailList (Link
, &BlockSingleData
->Entry
);
1250 // Add new block data into the tail.
1252 InsertTailList (Link
, &BlockSingleData
->Entry
);
1256 Retrieves a pointer to the a Null-terminated ASCII string containing the list
1257 of languages that an HII handle in the HII Database supports. The returned
1258 string is allocated using AllocatePool(). The caller is responsible for freeing
1259 the returned string using FreePool(). The format of the returned string follows
1260 the language format assumed the HII Database.
1262 If HiiHandle is NULL, then ASSERT().
1264 @param[in] HiiHandle A handle that was previously registered in the HII Database.
1266 @retval NULL HiiHandle is not registered in the HII database
1267 @retval NULL There are not enough resources available to retrieve the supported
1269 @retval NULL The list of supported languages could not be retrieved.
1270 @retval Other A pointer to the Null-terminated ASCII string of supported languages.
1274 GetSupportedLanguages (
1275 IN EFI_HII_HANDLE HiiHandle
1280 CHAR8 TempSupportedLanguages
;
1281 CHAR8
*SupportedLanguages
;
1283 ASSERT (HiiHandle
!= NULL
);
1286 // Retrieve the size required for the supported languages buffer.
1289 Status
= mPrivate
.HiiString
.GetLanguages (&mPrivate
.HiiString
, HiiHandle
, &TempSupportedLanguages
, &LanguageSize
);
1292 // If GetLanguages() returns EFI_SUCCESS for a zero size,
1293 // then there are no supported languages registered for HiiHandle. If GetLanguages()
1294 // returns an error other than EFI_BUFFER_TOO_SMALL, then HiiHandle is not present
1295 // in the HII Database
1297 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
1299 // Return NULL if the size can not be retrieved, or if HiiHandle is not in the HII Database
1305 // Allocate the supported languages buffer.
1307 SupportedLanguages
= AllocateZeroPool (LanguageSize
);
1308 if (SupportedLanguages
== NULL
) {
1310 // Return NULL if allocation fails.
1316 // Retrieve the supported languages string
1318 Status
= mPrivate
.HiiString
.GetLanguages (&mPrivate
.HiiString
, HiiHandle
, SupportedLanguages
, &LanguageSize
);
1319 if (EFI_ERROR (Status
)) {
1321 // Free the buffer and return NULL if the supported languages can not be retrieved.
1323 FreePool (SupportedLanguages
);
1328 // Return the Null-terminated ASCII string of supported languages
1330 return SupportedLanguages
;
1334 Retrieves a string from a string package.
1336 If HiiHandle is NULL, then ASSERT().
1337 If StringId is 0, then ASSET.
1339 @param[in] HiiHandle A handle that was previously registered in the HII Database.
1340 @param[in] StringId The identifier of the string to retrieved from the string
1341 package associated with HiiHandle.
1343 @retval NULL The string specified by StringId is not present in the string package.
1344 @retval Other The string was returned.
1349 IN EFI_HII_HANDLE HiiHandle
,
1350 IN EFI_STRING_ID StringId
1357 CHAR8
*SupportedLanguages
;
1358 CHAR8
*PlatformLanguage
;
1359 CHAR8
*BestLanguage
;
1362 ASSERT (HiiHandle
!= NULL
);
1363 ASSERT (StringId
!= 0);
1366 // Initialize all allocated buffers to NULL
1368 SupportedLanguages
= NULL
;
1369 PlatformLanguage
= NULL
;
1370 BestLanguage
= NULL
;
1375 // Get the languages that the package specified by HiiHandle supports
1377 SupportedLanguages
= GetSupportedLanguages (HiiHandle
);
1378 if (SupportedLanguages
== NULL
) {
1383 // Get the current platform language setting
1385 GetEfiGlobalVariable2 (L
"PlatformLang", (VOID
**)&PlatformLanguage
, NULL
);
1388 // Get the best matching language from SupportedLanguages
1390 BestLanguage
= GetBestLanguage (
1392 FALSE
, // RFC 4646 mode
1393 Language
, // Highest priority
1394 PlatformLanguage
!= NULL
? PlatformLanguage
: "", // Next highest priority
1395 SupportedLanguages
, // Lowest priority
1398 if (BestLanguage
== NULL
) {
1403 // Retrieve the size of the string in the string package for the BestLanguage
1406 Status
= mPrivate
.HiiString
.GetString (
1407 &mPrivate
.HiiString
,
1416 // If GetString() returns EFI_SUCCESS for a zero size,
1417 // then there are no supported languages registered for HiiHandle. If GetString()
1418 // returns an error other than EFI_BUFFER_TOO_SMALL, then HiiHandle is not present
1419 // in the HII Database
1421 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
1426 // Allocate a buffer for the return string
1428 String
= AllocateZeroPool (StringSize
);
1429 if (String
== NULL
) {
1434 // Retrieve the string from the string package
1436 Status
= mPrivate
.HiiString
.GetString (
1437 &mPrivate
.HiiString
,
1445 if (EFI_ERROR (Status
)) {
1447 // Free the buffer and return NULL if the supported languages can not be retrieved.
1455 // Free allocated buffers
1457 if (SupportedLanguages
!= NULL
) {
1458 FreePool (SupportedLanguages
);
1460 if (PlatformLanguage
!= NULL
) {
1461 FreePool (PlatformLanguage
);
1463 if (BestLanguage
!= NULL
) {
1464 FreePool (BestLanguage
);
1468 // Return the Null-terminated Unicode string
1474 This function checks VarOffset and VarWidth is in the block range.
1476 @param RequestBlockArray The block array is to be checked.
1477 @param VarOffset Offset of var to the structure
1478 @param VarWidth Width of var.
1479 @param IsNameValueType Whether this varstore is name/value varstore or not.
1480 @param HiiHandle Hii handle for this hii package.
1482 @retval TRUE This Var is in the block range.
1483 @retval FALSE This Var is not in the block range.
1487 IN IFR_BLOCK_DATA
*RequestBlockArray
,
1488 IN UINT16 VarOffset
,
1490 IN BOOLEAN IsNameValueType
,
1491 IN EFI_HII_HANDLE HiiHandle
1495 IFR_BLOCK_DATA
*BlockData
;
1499 // No Request Block array, all vars are got.
1501 if (RequestBlockArray
== NULL
) {
1506 // Check the input var is in the request block range.
1508 for (Link
= RequestBlockArray
->Entry
.ForwardLink
; Link
!= &RequestBlockArray
->Entry
; Link
= Link
->ForwardLink
) {
1509 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
1511 if (IsNameValueType
) {
1512 Name
= InternalGetString (HiiHandle
, VarOffset
);
1513 ASSERT (Name
!= NULL
);
1515 if (StrnCmp (BlockData
->Name
, Name
, StrLen (Name
)) == 0) {
1521 if ((VarOffset
>= BlockData
->Offset
) && ((VarOffset
+ VarWidth
) <= (BlockData
->Offset
+ BlockData
->Width
))) {
1531 Get form package data from data base.
1533 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
1534 @param HiiFormPackage The buffer saves the package data.
1535 @param PackageSize The buffer size of the package data.
1539 GetFormPackageData (
1540 IN HII_DATABASE_RECORD
*DataBaseRecord
,
1541 IN OUT UINT8
**HiiFormPackage
,
1542 OUT UINTN
*PackageSize
1549 if (DataBaseRecord
== NULL
|| HiiFormPackage
== NULL
|| PackageSize
== NULL
) {
1550 return EFI_INVALID_PARAMETER
;
1556 // 0. Get Hii Form Package by HiiHandle
1558 Status
= ExportFormPackages (
1560 DataBaseRecord
->Handle
,
1561 DataBaseRecord
->PackageList
,
1567 if (EFI_ERROR (Status
)) {
1571 (*HiiFormPackage
) = AllocatePool (ResultSize
);
1572 if (*HiiFormPackage
== NULL
) {
1573 Status
= EFI_OUT_OF_RESOURCES
;
1578 // Get HiiFormPackage by HiiHandle
1582 Status
= ExportFormPackages (
1584 DataBaseRecord
->Handle
,
1585 DataBaseRecord
->PackageList
,
1591 if (EFI_ERROR (Status
)) {
1592 FreePool (*HiiFormPackage
);
1595 *PackageSize
= Size
;
1602 This function parses Form Package to get the efi varstore info according to the request ConfigHdr.
1604 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
1605 @param ConfigHdr Request string ConfigHdr. If it is NULL,
1606 the first found varstore will be as ConfigHdr.
1607 @param IsEfiVarstore Whether the request storage type is efi varstore type.
1608 @param EfiVarStore The efi varstore info which will return.
1612 IN HII_DATABASE_RECORD
*DataBaseRecord
,
1613 IN EFI_STRING ConfigHdr
,
1614 OUT BOOLEAN
*IsEfiVarstore
,
1615 OUT EFI_IFR_VARSTORE_EFI
**EfiVarStore
1620 UINTN PackageOffset
;
1621 EFI_IFR_OP_HEADER
*IfrOpHdr
;
1622 CHAR16
*VarStoreName
;
1628 UINT8
*HiiFormPackage
;
1630 EFI_IFR_VARSTORE_EFI
*IfrEfiVarStore
;
1631 EFI_HII_PACKAGE_HEADER
*PackageHeader
;
1633 HiiFormPackage
= NULL
;
1635 Status
= EFI_SUCCESS
;
1639 *IsEfiVarstore
= FALSE
;
1641 Status
= GetFormPackageData(DataBaseRecord
, &HiiFormPackage
, &PackageSize
);
1642 if (EFI_ERROR (Status
)) {
1646 IfrOffset
= sizeof (EFI_HII_PACKAGE_HEADER
);
1647 PackageOffset
= IfrOffset
;
1648 PackageHeader
= (EFI_HII_PACKAGE_HEADER
*) HiiFormPackage
;
1650 while (IfrOffset
< PackageSize
) {
1652 // More than one form packages exist.
1654 if (PackageOffset
>= PackageHeader
->Length
) {
1656 // Process the new form package.
1658 PackageOffset
= sizeof (EFI_HII_PACKAGE_HEADER
);
1659 IfrOffset
+= PackageOffset
;
1660 PackageHeader
= (EFI_HII_PACKAGE_HEADER
*) (HiiFormPackage
+ IfrOffset
);
1663 IfrOpHdr
= (EFI_IFR_OP_HEADER
*) (HiiFormPackage
+ IfrOffset
);
1664 IfrOffset
+= IfrOpHdr
->Length
;
1665 PackageOffset
+= IfrOpHdr
->Length
;
1667 if (IfrOpHdr
->OpCode
== EFI_IFR_VARSTORE_EFI_OP
) {
1668 IfrEfiVarStore
= (EFI_IFR_VARSTORE_EFI
*) IfrOpHdr
;
1670 // If the length is small than the structure, this is from old efi
1671 // varstore definition. Old efi varstore get config directly from
1672 // GetVariable function.
1674 if (IfrOpHdr
->Length
< sizeof (EFI_IFR_VARSTORE_EFI
)) {
1678 NameSize
= AsciiStrSize ((CHAR8
*)IfrEfiVarStore
->Name
);
1679 VarStoreName
= AllocateZeroPool (NameSize
* sizeof (CHAR16
));
1680 if (VarStoreName
== NULL
) {
1681 Status
= EFI_OUT_OF_RESOURCES
;
1684 AsciiStrToUnicodeStrS ((CHAR8
*) IfrEfiVarStore
->Name
, VarStoreName
, NameSize
);
1686 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*) &IfrEfiVarStore
->Guid
, 1, &GuidStr
);
1687 GenerateSubStr (L
"NAME=", StrLen (VarStoreName
) * sizeof (CHAR16
), (VOID
*) VarStoreName
, 2, &NameStr
);
1688 LengthString
= StrLen (GuidStr
);
1689 LengthString
= LengthString
+ StrLen (NameStr
) + 1;
1690 TempStr
= AllocateZeroPool (LengthString
* sizeof (CHAR16
));
1691 if (TempStr
== NULL
) {
1694 FreePool (VarStoreName
);
1695 Status
= EFI_OUT_OF_RESOURCES
;
1698 StrCpyS (TempStr
, LengthString
, GuidStr
);
1699 StrCatS (TempStr
, LengthString
, NameStr
);
1700 if (ConfigHdr
== NULL
|| StrnCmp (ConfigHdr
, TempStr
, StrLen (TempStr
)) == 0) {
1701 *EfiVarStore
= (EFI_IFR_VARSTORE_EFI
*) AllocateZeroPool (IfrOpHdr
->Length
);
1702 if (*EfiVarStore
== NULL
) {
1703 FreePool (VarStoreName
);
1707 Status
= EFI_OUT_OF_RESOURCES
;
1710 *IsEfiVarstore
= TRUE
;
1711 CopyMem (*EfiVarStore
, IfrEfiVarStore
, IfrOpHdr
->Length
);
1715 // Free allocated temp string.
1717 FreePool (VarStoreName
);
1723 // Already found the varstore, break;
1725 if (*IsEfiVarstore
) {
1731 if (HiiFormPackage
!= NULL
) {
1732 FreePool (HiiFormPackage
);
1739 Check whether the ConfigRequest string has the request elements.
1740 For EFI_HII_VARSTORE_BUFFER type, the request has "&OFFSET=****&WIDTH=****..." format.
1741 For EFI_HII_VARSTORE_NAME_VALUE type, the request has "&NAME1**&NAME2..." format.
1743 @param ConfigRequest The input config request string.
1745 @retval TRUE The input include config request elements.
1746 @retval FALSE The input string not includes.
1750 GetElementsFromRequest (
1751 IN EFI_STRING ConfigRequest
1754 EFI_STRING TmpRequest
;
1756 TmpRequest
= StrStr (ConfigRequest
, L
"PATH=");
1757 ASSERT (TmpRequest
!= NULL
);
1759 if ((StrStr (TmpRequest
, L
"&OFFSET=") != NULL
) || (StrStr (TmpRequest
, L
"&") != NULL
)) {
1767 Check whether the this varstore is the request varstore.
1769 @param VarstoreGuid Varstore guid.
1770 @param Name Varstore name.
1771 @param ConfigHdr Current configRequest info.
1773 @retval TRUE This varstore is the request one.
1774 @retval FALSE This varstore is not the request one.
1779 IN EFI_GUID
*VarstoreGuid
,
1781 IN CHAR16
*ConfigHdr
1795 // If ConfigHdr has name field and varstore not has name, return FALSE.
1797 if (Name
== NULL
&& ConfigHdr
!= NULL
&& StrStr (ConfigHdr
, L
"NAME=&") == NULL
) {
1801 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*)VarstoreGuid
, 1, &GuidStr
);
1803 GenerateSubStr (L
"NAME=", StrLen (Name
) * sizeof (CHAR16
), (VOID
*) Name
, 2, &NameStr
);
1805 GenerateSubStr (L
"NAME=", 0, NULL
, 2, &NameStr
);
1807 LengthString
= StrLen (GuidStr
);
1808 LengthString
= LengthString
+ StrLen (NameStr
) + 1;
1809 TempStr
= AllocateZeroPool (LengthString
* sizeof (CHAR16
));
1810 if (TempStr
== NULL
) {
1814 StrCpyS (TempStr
, LengthString
, GuidStr
);
1815 StrCatS (TempStr
, LengthString
, NameStr
);
1817 if (ConfigHdr
== NULL
|| StrnCmp (ConfigHdr
, TempStr
, StrLen (TempStr
)) == 0) {
1822 if (GuidStr
!= NULL
) {
1826 if (NameStr
!= NULL
) {
1830 if (TempStr
!= NULL
) {
1838 This function parses Form Package to get the efi varstore info according to the request ConfigHdr.
1840 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
1841 @param ConfigHdr Request string ConfigHdr. If it is NULL,
1842 the first found varstore will be as ConfigHdr.
1843 @retval TRUE This hii package is the request one.
1844 @retval FALSE This hii package is not the request one.
1848 IN HII_DATABASE_RECORD
*DataBaseRecord
,
1849 IN EFI_STRING ConfigHdr
1854 UINTN PackageOffset
;
1855 EFI_IFR_OP_HEADER
*IfrOpHdr
;
1856 CHAR16
*VarStoreName
;
1858 UINT8
*HiiFormPackage
;
1860 EFI_IFR_VARSTORE_EFI
*IfrEfiVarStore
;
1861 EFI_HII_PACKAGE_HEADER
*PackageHeader
;
1862 EFI_IFR_VARSTORE
*IfrVarStore
;
1863 EFI_IFR_VARSTORE_NAME_VALUE
*IfrNameValueVarStore
;
1864 BOOLEAN FindVarstore
;
1866 HiiFormPackage
= NULL
;
1867 VarStoreName
= NULL
;
1868 Status
= EFI_SUCCESS
;
1869 FindVarstore
= FALSE
;
1871 Status
= GetFormPackageData(DataBaseRecord
, &HiiFormPackage
, &PackageSize
);
1872 if (EFI_ERROR (Status
)) {
1876 IfrOffset
= sizeof (EFI_HII_PACKAGE_HEADER
);
1877 PackageOffset
= IfrOffset
;
1878 PackageHeader
= (EFI_HII_PACKAGE_HEADER
*) HiiFormPackage
;
1880 while (IfrOffset
< PackageSize
) {
1882 // More than one form packages exist.
1884 if (PackageOffset
>= PackageHeader
->Length
) {
1886 // Process the new form package.
1888 PackageOffset
= sizeof (EFI_HII_PACKAGE_HEADER
);
1889 IfrOffset
+= PackageOffset
;
1890 PackageHeader
= (EFI_HII_PACKAGE_HEADER
*) (HiiFormPackage
+ IfrOffset
);
1893 IfrOpHdr
= (EFI_IFR_OP_HEADER
*) (HiiFormPackage
+ IfrOffset
);
1894 IfrOffset
+= IfrOpHdr
->Length
;
1895 PackageOffset
+= IfrOpHdr
->Length
;
1897 switch (IfrOpHdr
->OpCode
) {
1899 case EFI_IFR_VARSTORE_OP
:
1900 IfrVarStore
= (EFI_IFR_VARSTORE
*) IfrOpHdr
;
1902 NameSize
= AsciiStrSize ((CHAR8
*)IfrVarStore
->Name
);
1903 VarStoreName
= AllocateZeroPool (NameSize
* sizeof (CHAR16
));
1904 if (VarStoreName
== NULL
) {
1907 AsciiStrToUnicodeStrS ((CHAR8
*)IfrVarStore
->Name
, VarStoreName
, NameSize
);
1909 if (IsThisVarstore((VOID
*)&IfrVarStore
->Guid
, VarStoreName
, ConfigHdr
)) {
1910 FindVarstore
= TRUE
;
1913 FreePool (VarStoreName
);
1914 VarStoreName
= NULL
;
1918 case EFI_IFR_VARSTORE_EFI_OP
:
1919 IfrEfiVarStore
= (EFI_IFR_VARSTORE_EFI
*) IfrOpHdr
;
1920 NameSize
= AsciiStrSize ((CHAR8
*)IfrEfiVarStore
->Name
);
1921 VarStoreName
= AllocateZeroPool (NameSize
* sizeof (CHAR16
));
1922 if (VarStoreName
== NULL
) {
1925 AsciiStrToUnicodeStrS ((CHAR8
*)IfrEfiVarStore
->Name
, VarStoreName
, NameSize
);
1927 if (IsThisVarstore (&IfrEfiVarStore
->Guid
, VarStoreName
, ConfigHdr
)) {
1928 FindVarstore
= TRUE
;
1931 FreePool (VarStoreName
);
1932 VarStoreName
= NULL
;
1936 case EFI_IFR_VARSTORE_NAME_VALUE_OP
:
1937 IfrNameValueVarStore
= (EFI_IFR_VARSTORE_NAME_VALUE
*) IfrOpHdr
;
1939 if (IsThisVarstore (&IfrNameValueVarStore
->Guid
, NULL
, ConfigHdr
)) {
1940 FindVarstore
= TRUE
;
1945 case EFI_IFR_FORM_OP
:
1946 case EFI_IFR_FORM_MAP_OP
:
1948 // No matched varstore is found and directly return.
1957 if (HiiFormPackage
!= NULL
) {
1958 FreePool (HiiFormPackage
);
1961 if (VarStoreName
!= NULL
) {
1962 FreePool (VarStoreName
);
1965 return FindVarstore
;
1969 Check whether the this op code is required.
1971 @param RequestBlockArray The array includes all the request info or NULL.
1972 @param HiiHandle The hii handle for this form package.
1973 @param VarStorageData The varstore data structure.
1974 @param IfrOpHdr Ifr opcode header for this opcode.
1975 @param VarWidth The buffer width for this opcode.
1976 @param ReturnData The data block added for this opcode.
1977 @param IsBitVar Whether the the opcode refers to bit storage.
1979 @retval EFI_SUCCESS This opcode is required.
1980 @retval EFI_NOT_FOUND This opcode is not required.
1981 @retval Others Contain some error.
1985 IsThisOpcodeRequired (
1986 IN IFR_BLOCK_DATA
*RequestBlockArray
,
1987 IN EFI_HII_HANDLE HiiHandle
,
1988 IN OUT IFR_VARSTORAGE_DATA
*VarStorageData
,
1989 IN EFI_IFR_OP_HEADER
*IfrOpHdr
,
1991 OUT IFR_BLOCK_DATA
**ReturnData
,
1995 IFR_BLOCK_DATA
*BlockData
;
1997 EFI_STRING_ID NameId
;
1998 EFI_IFR_QUESTION_HEADER
*IfrQuestionHdr
;
2007 IfrQuestionHdr
= (EFI_IFR_QUESTION_HEADER
*)((CHAR8
*) IfrOpHdr
+ sizeof (EFI_IFR_OP_HEADER
));
2009 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2010 NameId
= IfrQuestionHdr
->VarStoreInfo
.VarName
;
2013 // Check whether this question is in requested block array.
2015 if (!BlockArrayCheck (RequestBlockArray
, NameId
, 0, TRUE
, HiiHandle
)) {
2017 // This question is not in the requested string. Skip it.
2019 return EFI_NOT_FOUND
;
2023 // Get the byte offset/with and bit offset/width
2026 BitOffset
= IfrQuestionHdr
->VarStoreInfo
.VarOffset
;
2027 BitWidth
= VarWidth
;
2028 VarOffset
= BitOffset
/ 8;
2030 // Use current bit width and the bit width before current bit (with same byte offset) to calculate the byte width.
2032 TotalBits
= BitOffset
% 8 + BitWidth
;
2033 VarWidth
= (TotalBits
% 8 == 0 ? TotalBits
/ 8: TotalBits
/ 8 + 1);
2035 VarOffset
= IfrQuestionHdr
->VarStoreInfo
.VarOffset
;
2036 BitWidth
= VarWidth
;
2037 BitOffset
= VarOffset
* 8;
2041 // Check whether this question is in requested block array.
2043 if (!BlockArrayCheck (RequestBlockArray
, VarOffset
, VarWidth
, FALSE
, HiiHandle
)) {
2045 // This question is not in the requested string. Skip it.
2047 return EFI_NOT_FOUND
;
2051 // Check this var question is in the var storage
2053 if (((VarOffset
+ VarWidth
) > VarStorageData
->Size
)) {
2054 return EFI_INVALID_PARAMETER
;
2058 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
2059 if (BlockData
== NULL
) {
2060 return EFI_OUT_OF_RESOURCES
;
2063 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2064 BlockData
->Name
= InternalGetString(HiiHandle
, NameId
);
2066 BlockData
->Offset
= VarOffset
;
2069 BlockData
->Width
= VarWidth
;
2070 BlockData
->QuestionId
= IfrQuestionHdr
->QuestionId
;
2071 BlockData
->OpCode
= IfrOpHdr
->OpCode
;
2072 BlockData
->Scope
= IfrOpHdr
->Scope
;
2073 BlockData
->IsBitVar
= IsBitVar
;
2074 BlockData
->BitOffset
= BitOffset
;
2075 BlockData
->BitWidth
= BitWidth
;
2076 InitializeListHead (&BlockData
->DefaultValueEntry
);
2078 // Add Block Data into VarStorageData BlockEntry
2080 InsertBlockData (&VarStorageData
->BlockEntry
, &BlockData
);
2081 *ReturnData
= BlockData
;
2087 This function parses Form Package to get the block array and the default
2088 value array according to the request ConfigHdr.
2090 @param HiiHandle Hii Handle for this hii package.
2091 @param Package Pointer to the form package data.
2092 @param PackageLength Length of the package.
2093 @param ConfigHdr Request string ConfigHdr. If it is NULL,
2094 the first found varstore will be as ConfigHdr.
2095 @param RequestBlockArray The block array is retrieved from the request string.
2096 @param VarStorageData VarStorage structure contains the got block and default value.
2097 @param DefaultIdArray Point to the got default id and default name array.
2099 @retval EFI_SUCCESS The block array and the default value array are got.
2100 @retval EFI_INVALID_PARAMETER The varstore definition in the different form packages
2102 @retval EFI_OUT_OF_RESOURCES No enough memory.
2107 IN EFI_HII_HANDLE HiiHandle
,
2109 IN UINT32 PackageLength
,
2110 IN EFI_STRING ConfigHdr
,
2111 IN IFR_BLOCK_DATA
*RequestBlockArray
,
2112 IN OUT IFR_VARSTORAGE_DATA
*VarStorageData
,
2113 OUT IFR_DEFAULT_DATA
*DefaultIdArray
2118 UINTN PackageOffset
;
2119 EFI_IFR_VARSTORE
*IfrVarStore
;
2120 EFI_IFR_VARSTORE_EFI
*IfrEfiVarStore
;
2121 EFI_IFR_OP_HEADER
*IfrOpHdr
;
2122 EFI_IFR_ONE_OF
*IfrOneOf
;
2123 EFI_IFR_REF4
*IfrRef
;
2124 EFI_IFR_ONE_OF_OPTION
*IfrOneOfOption
;
2125 EFI_IFR_DEFAULT
*IfrDefault
;
2126 EFI_IFR_ORDERED_LIST
*IfrOrderedList
;
2127 EFI_IFR_CHECKBOX
*IfrCheckBox
;
2128 EFI_IFR_PASSWORD
*IfrPassword
;
2129 EFI_IFR_STRING
*IfrString
;
2130 EFI_IFR_DATE
*IfrDate
;
2131 EFI_IFR_TIME
*IfrTime
;
2132 IFR_DEFAULT_DATA DefaultData
;
2133 IFR_DEFAULT_DATA
*DefaultDataPtr
;
2134 IFR_BLOCK_DATA
*BlockData
;
2135 CHAR16
*VarStoreName
;
2138 UINT16 VarDefaultId
;
2139 BOOLEAN FirstOneOfOption
;
2140 BOOLEAN FirstOrderedList
;
2141 LIST_ENTRY
*LinkData
;
2142 LIST_ENTRY
*LinkDefault
;
2143 EFI_IFR_VARSTORE_NAME_VALUE
*IfrNameValueVarStore
;
2144 EFI_HII_PACKAGE_HEADER
*PackageHeader
;
2145 EFI_VARSTORE_ID VarStoreId
;
2146 UINT16 SmallestDefaultId
;
2147 BOOLEAN SmallestIdFromFlag
;
2148 BOOLEAN FromOtherDefaultOpcode
;
2149 BOOLEAN QuestionReferBitField
;
2151 Status
= EFI_SUCCESS
;
2153 DefaultDataPtr
= NULL
;
2154 FirstOneOfOption
= FALSE
;
2156 FirstOrderedList
= FALSE
;
2157 VarStoreName
= NULL
;
2158 ZeroMem (&DefaultData
, sizeof (IFR_DEFAULT_DATA
));
2159 SmallestDefaultId
= 0xFFFF;
2160 FromOtherDefaultOpcode
= FALSE
;
2161 QuestionReferBitField
= FALSE
;
2164 // Go through the form package to parse OpCode one by one.
2166 PackageOffset
= sizeof (EFI_HII_PACKAGE_HEADER
);
2167 PackageHeader
= (EFI_HII_PACKAGE_HEADER
*) Package
;
2168 IfrOffset
= PackageOffset
;
2169 while (IfrOffset
< PackageLength
) {
2172 // More than one form package found.
2174 if (PackageOffset
>= PackageHeader
->Length
) {
2176 // Already found varstore for this request, break;
2178 if (VarStoreId
!= 0) {
2183 // Get next package header info.
2185 IfrOffset
+= sizeof (EFI_HII_PACKAGE_HEADER
);
2186 PackageOffset
= sizeof (EFI_HII_PACKAGE_HEADER
);
2187 PackageHeader
= (EFI_HII_PACKAGE_HEADER
*) (Package
+ IfrOffset
);
2190 IfrOpHdr
= (EFI_IFR_OP_HEADER
*) (Package
+ IfrOffset
);
2191 switch (IfrOpHdr
->OpCode
) {
2192 case EFI_IFR_VARSTORE_OP
:
2194 // VarStore is found. Don't need to search any more.
2196 if (VarStoreId
!= 0) {
2200 IfrVarStore
= (EFI_IFR_VARSTORE
*) IfrOpHdr
;
2202 NameSize
= AsciiStrSize ((CHAR8
*)IfrVarStore
->Name
);
2203 VarStoreName
= AllocateZeroPool (NameSize
* sizeof (CHAR16
));
2204 if (VarStoreName
== NULL
) {
2205 Status
= EFI_OUT_OF_RESOURCES
;
2208 AsciiStrToUnicodeStrS ((CHAR8
*)IfrVarStore
->Name
, VarStoreName
, NameSize
);
2210 if (IsThisVarstore((VOID
*)&IfrVarStore
->Guid
, VarStoreName
, ConfigHdr
)) {
2212 // Find the matched VarStore
2214 CopyGuid (&VarStorageData
->Guid
, (EFI_GUID
*) (VOID
*) &IfrVarStore
->Guid
);
2215 VarStorageData
->Size
= IfrVarStore
->Size
;
2216 VarStorageData
->Name
= VarStoreName
;
2217 VarStorageData
->Type
= EFI_HII_VARSTORE_BUFFER
;
2218 VarStoreId
= IfrVarStore
->VarStoreId
;
2220 FreePool (VarStoreName
);
2221 VarStoreName
= NULL
;
2225 case EFI_IFR_VARSTORE_EFI_OP
:
2227 // VarStore is found. Don't need to search any more.
2229 if (VarStoreId
!= 0) {
2233 IfrEfiVarStore
= (EFI_IFR_VARSTORE_EFI
*) IfrOpHdr
;
2236 // If the length is small than the structure, this is from old efi
2237 // varstore definition. Old efi varstore get config directly from
2238 // GetVariable function.
2240 if (IfrOpHdr
->Length
< sizeof (EFI_IFR_VARSTORE_EFI
)) {
2244 NameSize
= AsciiStrSize ((CHAR8
*)IfrEfiVarStore
->Name
);
2245 VarStoreName
= AllocateZeroPool (NameSize
* sizeof (CHAR16
));
2246 if (VarStoreName
== NULL
) {
2247 Status
= EFI_OUT_OF_RESOURCES
;
2250 AsciiStrToUnicodeStrS ((CHAR8
*)IfrEfiVarStore
->Name
, VarStoreName
, NameSize
);
2252 if (IsThisVarstore (&IfrEfiVarStore
->Guid
, VarStoreName
, ConfigHdr
)) {
2254 // Find the matched VarStore
2256 CopyGuid (&VarStorageData
->Guid
, (EFI_GUID
*) (VOID
*) &IfrEfiVarStore
->Guid
);
2257 VarStorageData
->Size
= IfrEfiVarStore
->Size
;
2258 VarStorageData
->Name
= VarStoreName
;
2259 VarStorageData
->Type
= EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
;
2260 VarStoreId
= IfrEfiVarStore
->VarStoreId
;
2262 FreePool (VarStoreName
);
2263 VarStoreName
= NULL
;
2267 case EFI_IFR_VARSTORE_NAME_VALUE_OP
:
2269 // VarStore is found. Don't need to search any more.
2271 if (VarStoreId
!= 0) {
2275 IfrNameValueVarStore
= (EFI_IFR_VARSTORE_NAME_VALUE
*) IfrOpHdr
;
2277 if (IsThisVarstore (&IfrNameValueVarStore
->Guid
, NULL
, ConfigHdr
)) {
2279 // Find the matched VarStore
2281 CopyGuid (&VarStorageData
->Guid
, (EFI_GUID
*) (VOID
*) &IfrNameValueVarStore
->Guid
);
2282 VarStorageData
->Type
= EFI_HII_VARSTORE_NAME_VALUE
;
2283 VarStoreId
= IfrNameValueVarStore
->VarStoreId
;
2287 case EFI_IFR_DEFAULTSTORE_OP
:
2289 // Add new the map between default id and default name.
2291 DefaultDataPtr
= (IFR_DEFAULT_DATA
*) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
2292 if (DefaultDataPtr
== NULL
) {
2293 Status
= EFI_OUT_OF_RESOURCES
;
2296 DefaultDataPtr
->DefaultId
= ((EFI_IFR_DEFAULTSTORE
*) IfrOpHdr
)->DefaultId
;
2297 InsertTailList (&DefaultIdArray
->Entry
, &DefaultDataPtr
->Entry
);
2298 DefaultDataPtr
= NULL
;
2301 case EFI_IFR_FORM_OP
:
2302 case EFI_IFR_FORM_MAP_OP
:
2304 // No matched varstore is found and directly return.
2306 if ( VarStoreId
== 0) {
2307 Status
= EFI_SUCCESS
;
2312 case EFI_IFR_REF_OP
:
2314 // Ref question is not in IFR Form. This IFR form is not valid.
2316 if ( VarStoreId
== 0) {
2317 Status
= EFI_INVALID_PARAMETER
;
2321 // Check whether this question is for the requested varstore.
2323 IfrRef
= (EFI_IFR_REF4
*) IfrOpHdr
;
2324 if (IfrRef
->Question
.VarStoreId
!= VarStoreId
) {
2327 VarWidth
= (UINT16
) (sizeof (EFI_HII_REF
));
2330 // The BlockData may allocate by other opcode,need to clean.
2332 if (BlockData
!= NULL
){
2336 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
, FALSE
);
2337 if (EFI_ERROR (Status
)) {
2338 if (Status
== EFI_NOT_FOUND
){
2340 //The opcode is not required,exit and parse other opcode.
2348 case EFI_IFR_ONE_OF_OP
:
2349 case EFI_IFR_NUMERIC_OP
:
2351 // Numeric and OneOf has the same opcode structure.
2355 // Numeric and OneOf question is not in IFR Form. This IFR form is not valid.
2357 if (VarStoreId
== 0) {
2358 Status
= EFI_INVALID_PARAMETER
;
2362 // Check whether this question is for the requested varstore.
2364 IfrOneOf
= (EFI_IFR_ONE_OF
*) IfrOpHdr
;
2365 if (IfrOneOf
->Question
.VarStoreId
!= VarStoreId
) {
2369 if (QuestionReferBitField
) {
2370 VarWidth
= IfrOneOf
->Flags
& EDKII_IFR_NUMERIC_SIZE_BIT
;
2372 VarWidth
= (UINT16
) (1 << (IfrOneOf
->Flags
& EFI_IFR_NUMERIC_SIZE
));
2376 // The BlockData may allocate by other opcode,need to clean.
2378 if (BlockData
!= NULL
){
2382 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
, QuestionReferBitField
);
2383 if (EFI_ERROR (Status
)) {
2384 if (Status
== EFI_NOT_FOUND
){
2386 //The opcode is not required,exit and parse other opcode.
2394 //when go to there,BlockData can't be NULLL.
2396 ASSERT (BlockData
!= NULL
);
2398 if (IfrOpHdr
->OpCode
== EFI_IFR_ONE_OF_OP
) {
2400 // Set this flag to TRUE for the first oneof option.
2402 FirstOneOfOption
= TRUE
;
2403 } else if (IfrOpHdr
->OpCode
== EFI_IFR_NUMERIC_OP
) {
2405 // Numeric minimum value will be used as default value when no default is specified.
2407 DefaultData
.Type
= DefaultValueFromDefault
;
2408 if (QuestionReferBitField
) {
2410 // Since default value in bit field was stored as UINT32 type.
2412 CopyMem (&DefaultData
.Value
.u32
, &IfrOneOf
->data
.u32
.MinValue
, sizeof (UINT32
));
2414 switch (IfrOneOf
->Flags
& EFI_IFR_NUMERIC_SIZE
) {
2415 case EFI_IFR_NUMERIC_SIZE_1
:
2416 DefaultData
.Value
.u8
= IfrOneOf
->data
.u8
.MinValue
;
2419 case EFI_IFR_NUMERIC_SIZE_2
:
2420 CopyMem (&DefaultData
.Value
.u16
, &IfrOneOf
->data
.u16
.MinValue
, sizeof (UINT16
));
2423 case EFI_IFR_NUMERIC_SIZE_4
:
2424 CopyMem (&DefaultData
.Value
.u32
, &IfrOneOf
->data
.u32
.MinValue
, sizeof (UINT32
));
2427 case EFI_IFR_NUMERIC_SIZE_8
:
2428 CopyMem (&DefaultData
.Value
.u64
, &IfrOneOf
->data
.u64
.MinValue
, sizeof (UINT64
));
2432 Status
= EFI_INVALID_PARAMETER
;
2437 // Set default value base on the DefaultId list get from IFR data.
2439 for (LinkData
= DefaultIdArray
->Entry
.ForwardLink
; LinkData
!= &DefaultIdArray
->Entry
; LinkData
= LinkData
->ForwardLink
) {
2440 DefaultDataPtr
= BASE_CR (LinkData
, IFR_DEFAULT_DATA
, Entry
);
2441 DefaultData
.DefaultId
= DefaultDataPtr
->DefaultId
;
2442 InsertDefaultValue (BlockData
, &DefaultData
);
2447 case EFI_IFR_ORDERED_LIST_OP
:
2449 // offset by question header
2450 // width by EFI_IFR_ORDERED_LIST MaxContainers * OneofOption Type
2453 FirstOrderedList
= TRUE
;
2455 // OrderedList question is not in IFR Form. This IFR form is not valid.
2457 if (VarStoreId
== 0) {
2458 Status
= EFI_INVALID_PARAMETER
;
2462 // Check whether this question is for the requested varstore.
2464 IfrOrderedList
= (EFI_IFR_ORDERED_LIST
*) IfrOpHdr
;
2465 if (IfrOrderedList
->Question
.VarStoreId
!= VarStoreId
) {
2469 VarWidth
= IfrOrderedList
->MaxContainers
;
2472 // The BlockData may allocate by other opcode,need to clean.
2474 if (BlockData
!= NULL
){
2478 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
, FALSE
);
2479 if (EFI_ERROR (Status
)) {
2480 if (Status
== EFI_NOT_FOUND
){
2482 //The opcode is not required,exit and parse other opcode.
2490 case EFI_IFR_CHECKBOX_OP
:
2492 // EFI_IFR_DEFAULT_OP
2493 // offset by question header
2494 // width is 1 sizeof (BOOLEAN)
2495 // default id by CheckBox Flags if CheckBox flags (Default or Mau) is set, the default value is 1 to be set.
2496 // value by DefaultOption
2497 // default id by DeaultOption DefaultId can override CheckBox Flags and Default value.
2501 // CheckBox question is not in IFR Form. This IFR form is not valid.
2503 if (VarStoreId
== 0) {
2504 Status
= EFI_INVALID_PARAMETER
;
2508 // Check whether this question is for the requested varstore.
2510 IfrCheckBox
= (EFI_IFR_CHECKBOX
*) IfrOpHdr
;
2511 if (IfrCheckBox
->Question
.VarStoreId
!= VarStoreId
) {
2514 VarWidth
= (UINT16
) sizeof (BOOLEAN
);
2517 // The BlockData may allocate by other opcode,need to clean.
2519 if (BlockData
!= NULL
){
2523 if (QuestionReferBitField
) {
2526 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
, QuestionReferBitField
);
2527 if (EFI_ERROR (Status
)) {
2528 if (Status
== EFI_NOT_FOUND
){
2530 //The opcode is not required,exit and parse other opcode.
2538 //when go to there,BlockData can't be NULLL.
2540 ASSERT (BlockData
!= NULL
);
2542 SmallestIdFromFlag
= FALSE
;
2545 // Add default value for standard ID by CheckBox Flag
2547 VarDefaultId
= EFI_HII_DEFAULT_CLASS_STANDARD
;
2549 // Prepare new DefaultValue
2551 DefaultData
.DefaultId
= VarDefaultId
;
2552 if ((IfrCheckBox
->Flags
& EFI_IFR_CHECKBOX_DEFAULT
) == EFI_IFR_CHECKBOX_DEFAULT
) {
2554 // When flag is set, default value is TRUE.
2556 DefaultData
.Type
= DefaultValueFromFlag
;
2557 if (QuestionReferBitField
) {
2558 DefaultData
.Value
.u32
= TRUE
;
2560 DefaultData
.Value
.b
= TRUE
;
2562 InsertDefaultValue (BlockData
, &DefaultData
);
2564 if (SmallestDefaultId
> EFI_HII_DEFAULT_CLASS_STANDARD
) {
2566 // Record the SmallestDefaultId and update the SmallestIdFromFlag.
2568 SmallestDefaultId
= EFI_HII_DEFAULT_CLASS_STANDARD
;
2569 SmallestIdFromFlag
= TRUE
;
2574 // Add default value for Manufacture ID by CheckBox Flag
2576 VarDefaultId
= EFI_HII_DEFAULT_CLASS_MANUFACTURING
;
2578 // Prepare new DefaultValue
2580 DefaultData
.DefaultId
= VarDefaultId
;
2581 if ((IfrCheckBox
->Flags
& EFI_IFR_CHECKBOX_DEFAULT_MFG
) == EFI_IFR_CHECKBOX_DEFAULT_MFG
) {
2583 // When flag is set, default value is TRUE.
2585 DefaultData
.Type
= DefaultValueFromFlag
;
2586 if (QuestionReferBitField
) {
2587 DefaultData
.Value
.u32
= TRUE
;
2589 DefaultData
.Value
.b
= TRUE
;
2591 InsertDefaultValue (BlockData
, &DefaultData
);
2593 if (SmallestDefaultId
> EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
2595 // Record the SmallestDefaultId and update the SmallestIdFromFlag.
2597 SmallestDefaultId
= EFI_HII_DEFAULT_CLASS_MANUFACTURING
;
2598 SmallestIdFromFlag
= TRUE
;
2601 if (SmallestIdFromFlag
) {
2603 // When smallest default Id is given by the flag of CheckBox, set default value with TRUE for other default Id in the DefaultId list.
2605 DefaultData
.Type
= DefaultValueFromOtherDefault
;
2606 if (QuestionReferBitField
) {
2607 DefaultData
.Value
.u32
= TRUE
;
2609 DefaultData
.Value
.b
= TRUE
;
2612 // Set default value for all the default id in the DefaultId list.
2614 for (LinkData
= DefaultIdArray
->Entry
.ForwardLink
; LinkData
!= &DefaultIdArray
->Entry
; LinkData
= LinkData
->ForwardLink
) {
2615 DefaultDataPtr
= BASE_CR (LinkData
, IFR_DEFAULT_DATA
, Entry
);
2616 DefaultData
.DefaultId
= DefaultDataPtr
->DefaultId
;
2617 InsertDefaultValue (BlockData
, &DefaultData
);
2621 // When flag is not set, default value is FASLE.
2623 DefaultData
.Type
= DefaultValueFromDefault
;
2624 if (QuestionReferBitField
) {
2625 DefaultData
.Value
.u32
= FALSE
;
2627 DefaultData
.Value
.b
= FALSE
;
2630 // Set default value for all the default id in the DefaultId list.
2632 for (LinkData
= DefaultIdArray
->Entry
.ForwardLink
; LinkData
!= &DefaultIdArray
->Entry
; LinkData
= LinkData
->ForwardLink
) {
2633 DefaultDataPtr
= BASE_CR (LinkData
, IFR_DEFAULT_DATA
, Entry
);
2634 DefaultData
.DefaultId
= DefaultDataPtr
->DefaultId
;
2635 InsertDefaultValue (BlockData
, &DefaultData
);
2640 case EFI_IFR_DATE_OP
:
2642 // offset by question header
2643 // width MaxSize * sizeof (CHAR16)
2644 // no default value, only block array
2648 // Date question is not in IFR Form. This IFR form is not valid.
2650 if (VarStoreId
== 0) {
2651 Status
= EFI_INVALID_PARAMETER
;
2655 // Check whether this question is for the requested varstore.
2657 IfrDate
= (EFI_IFR_DATE
*) IfrOpHdr
;
2658 if (IfrDate
->Question
.VarStoreId
!= VarStoreId
) {
2663 // The BlockData may allocate by other opcode,need to clean.
2665 if (BlockData
!= NULL
){
2669 VarWidth
= (UINT16
) sizeof (EFI_HII_DATE
);
2670 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
, FALSE
);
2671 if (EFI_ERROR (Status
)) {
2672 if (Status
== EFI_NOT_FOUND
){
2674 //The opcode is not required,exit and parse other opcode.
2682 case EFI_IFR_TIME_OP
:
2684 // offset by question header
2685 // width MaxSize * sizeof (CHAR16)
2686 // no default value, only block array
2690 // Time question is not in IFR Form. This IFR form is not valid.
2692 if (VarStoreId
== 0) {
2693 Status
= EFI_INVALID_PARAMETER
;
2697 // Check whether this question is for the requested varstore.
2699 IfrTime
= (EFI_IFR_TIME
*) IfrOpHdr
;
2700 if (IfrTime
->Question
.VarStoreId
!= VarStoreId
) {
2705 // The BlockData may allocate by other opcode,need to clean.
2707 if (BlockData
!= NULL
){
2711 VarWidth
= (UINT16
) sizeof (EFI_HII_TIME
);
2712 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
, FALSE
);
2713 if (EFI_ERROR (Status
)) {
2714 if (Status
== EFI_NOT_FOUND
){
2716 //The opcode is not required,exit and parse other opcode.
2724 case EFI_IFR_STRING_OP
:
2726 // offset by question header
2727 // width MaxSize * sizeof (CHAR16)
2728 // no default value, only block array
2732 // String question is not in IFR Form. This IFR form is not valid.
2734 if (VarStoreId
== 0) {
2735 Status
= EFI_INVALID_PARAMETER
;
2739 // Check whether this question is for the requested varstore.
2741 IfrString
= (EFI_IFR_STRING
*) IfrOpHdr
;
2742 if (IfrString
->Question
.VarStoreId
!= VarStoreId
) {
2747 // The BlockData may allocate by other opcode,need to clean.
2749 if (BlockData
!= NULL
){
2753 VarWidth
= (UINT16
) (IfrString
->MaxSize
* sizeof (UINT16
));
2754 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
, FALSE
);
2755 if (EFI_ERROR (Status
)) {
2756 if (Status
== EFI_NOT_FOUND
){
2758 //The opcode is not required,exit and parse other opcode.
2766 case EFI_IFR_PASSWORD_OP
:
2768 // offset by question header
2769 // width MaxSize * sizeof (CHAR16)
2770 // no default value, only block array
2774 // Password question is not in IFR Form. This IFR form is not valid.
2776 if (VarStoreId
== 0) {
2777 Status
= EFI_INVALID_PARAMETER
;
2781 // Check whether this question is for the requested varstore.
2783 IfrPassword
= (EFI_IFR_PASSWORD
*) IfrOpHdr
;
2784 if (IfrPassword
->Question
.VarStoreId
!= VarStoreId
) {
2789 // The BlockData may allocate by other opcode,need to clean.
2791 if (BlockData
!= NULL
){
2795 VarWidth
= (UINT16
) (IfrPassword
->MaxSize
* sizeof (UINT16
));
2796 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
, FALSE
);
2797 if (EFI_ERROR (Status
)) {
2798 if (Status
== EFI_NOT_FOUND
){
2800 //The opcode is not required,exit and parse other opcode.
2808 // No default value for string.
2813 case EFI_IFR_ONE_OF_OPTION_OP
:
2815 // No matched block data is ignored.
2817 if (BlockData
== NULL
|| BlockData
->Scope
== 0) {
2821 IfrOneOfOption
= (EFI_IFR_ONE_OF_OPTION
*) IfrOpHdr
;
2822 if (BlockData
->OpCode
== EFI_IFR_ORDERED_LIST_OP
) {
2824 if (!FirstOrderedList
){
2828 // Get ordered list option data type.
2830 if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_8
|| IfrOneOfOption
->Type
== EFI_IFR_TYPE_BOOLEAN
) {
2832 } else if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_16
) {
2834 } else if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_32
) {
2836 } else if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_64
) {
2840 // Invalid ordered list option data type.
2842 Status
= EFI_INVALID_PARAMETER
;
2843 if (BlockData
->Name
!= NULL
) {
2844 FreePool (BlockData
->Name
);
2846 FreePool (BlockData
);
2851 // Calculate Ordered list QuestionId width.
2853 BlockData
->Width
= (UINT16
) (BlockData
->Width
* VarWidth
);
2855 // Check whether this question is in requested block array.
2857 if (!BlockArrayCheck (RequestBlockArray
, BlockData
->Offset
, BlockData
->Width
, (BOOLEAN
)(BlockData
->Name
!= NULL
), HiiHandle
)) {
2859 // This question is not in the requested string. Skip it.
2861 if (BlockData
->Name
!= NULL
) {
2862 FreePool (BlockData
->Name
);
2864 FreePool (BlockData
);
2869 // Check this var question is in the var storage
2871 if ((BlockData
->Name
== NULL
) && ((BlockData
->Offset
+ BlockData
->Width
) > VarStorageData
->Size
)) {
2872 Status
= EFI_INVALID_PARAMETER
;
2873 if (BlockData
->Name
!= NULL
) {
2874 FreePool (BlockData
->Name
);
2876 FreePool (BlockData
);
2880 // Add Block Data into VarStorageData BlockEntry
2882 InsertBlockData (&VarStorageData
->BlockEntry
, &BlockData
);
2884 FirstOrderedList
= FALSE
;
2890 // 1. Set default value for OneOf option when flag field has default attribute.
2891 // And set the default value with the smallest default id for other default id in the DefaultId list.
2893 if (((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT
) == EFI_IFR_OPTION_DEFAULT
) ||
2894 ((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT_MFG
) == EFI_IFR_OPTION_DEFAULT_MFG
)) {
2896 // This flag is used to specify whether this option is the first. Set it to FALSE for the following options.
2897 // The first oneof option value will be used as default value when no default value is specified.
2899 FirstOneOfOption
= FALSE
;
2901 SmallestIdFromFlag
= FALSE
;
2903 // Prepare new DefaultValue
2905 DefaultData
.Type
= DefaultValueFromFlag
;
2906 CopyMem (&DefaultData
.Value
, &IfrOneOfOption
->Value
, IfrOneOfOption
->Header
.Length
- OFFSET_OF (EFI_IFR_ONE_OF_OPTION
, Value
));
2907 if ((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT
) == EFI_IFR_OPTION_DEFAULT
) {
2908 DefaultData
.DefaultId
= EFI_HII_DEFAULT_CLASS_STANDARD
;
2909 InsertDefaultValue (BlockData
, &DefaultData
);
2910 if (SmallestDefaultId
> EFI_HII_DEFAULT_CLASS_STANDARD
) {
2912 // Record the SmallestDefaultId and update the SmallestIdFromFlag.
2914 SmallestDefaultId
= EFI_HII_DEFAULT_CLASS_STANDARD
;
2915 SmallestIdFromFlag
= TRUE
;
2918 if ((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT_MFG
) == EFI_IFR_OPTION_DEFAULT_MFG
) {
2919 DefaultData
.DefaultId
= EFI_HII_DEFAULT_CLASS_MANUFACTURING
;
2920 InsertDefaultValue (BlockData
, &DefaultData
);
2921 if (SmallestDefaultId
> EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
2923 // Record the SmallestDefaultId and update the SmallestIdFromFlag.
2925 SmallestDefaultId
= EFI_HII_DEFAULT_CLASS_MANUFACTURING
;
2926 SmallestIdFromFlag
= TRUE
;
2930 if (SmallestIdFromFlag
) {
2932 // When smallest default Id is given by the flag of oneofOption, set this option value for other default Id in the DefaultId list.
2934 DefaultData
.Type
= DefaultValueFromOtherDefault
;
2936 // Set default value for other default id in the DefaultId list.
2938 for (LinkData
= DefaultIdArray
->Entry
.ForwardLink
; LinkData
!= &DefaultIdArray
->Entry
; LinkData
= LinkData
->ForwardLink
) {
2939 DefaultDataPtr
= BASE_CR (LinkData
, IFR_DEFAULT_DATA
, Entry
);
2940 DefaultData
.DefaultId
= DefaultDataPtr
->DefaultId
;
2941 InsertDefaultValue (BlockData
, &DefaultData
);
2947 // 2. Set as the default value when this is the first option.
2948 // The first oneof option value will be used as default value when no default value is specified.
2950 if (FirstOneOfOption
) {
2951 // This flag is used to specify whether this option is the first. Set it to FALSE for the following options.
2952 FirstOneOfOption
= FALSE
;
2955 // Prepare new DefaultValue
2957 DefaultData
.Type
= DefaultValueFromDefault
;
2958 CopyMem (&DefaultData
.Value
, &IfrOneOfOption
->Value
, IfrOneOfOption
->Header
.Length
- OFFSET_OF (EFI_IFR_ONE_OF_OPTION
, Value
));
2959 for (LinkData
= DefaultIdArray
->Entry
.ForwardLink
; LinkData
!= &DefaultIdArray
->Entry
; LinkData
= LinkData
->ForwardLink
) {
2960 DefaultDataPtr
= BASE_CR (LinkData
, IFR_DEFAULT_DATA
, Entry
);
2961 DefaultData
.DefaultId
= DefaultDataPtr
->DefaultId
;
2962 InsertDefaultValue (BlockData
, &DefaultData
);
2967 case EFI_IFR_DEFAULT_OP
:
2969 // Update Current BlockData to the default value.
2971 if (BlockData
== NULL
|| BlockData
->Scope
== 0) {
2973 // No matched block data is ignored.
2979 // Get the DefaultId
2981 IfrDefault
= (EFI_IFR_DEFAULT
*) IfrOpHdr
;
2982 VarDefaultId
= IfrDefault
->DefaultId
;
2984 // Prepare new DefaultValue
2986 DefaultData
.Type
= DefaultValueFromOpcode
;
2987 DefaultData
.DefaultId
= VarDefaultId
;
2988 if (QuestionReferBitField
) {
2989 CopyMem (&DefaultData
.Value
.u32
, &IfrDefault
->Value
.u32
, sizeof (UINT32
));
2991 CopyMem (&DefaultData
.Value
, &IfrDefault
->Value
, IfrDefault
->Header
.Length
- OFFSET_OF (EFI_IFR_DEFAULT
, Value
));
2994 // If the value field is expression, set the cleaned flag.
2995 if (IfrDefault
->Type
== EFI_IFR_TYPE_OTHER
) {
2996 DefaultData
.Cleaned
= TRUE
;
2999 // Add DefaultValue into current BlockData
3001 InsertDefaultValue (BlockData
, &DefaultData
);
3004 // Set default value for other default id in the DefaultId list.
3005 // when SmallestDefaultId == VarDefaultId means there are two defaults with same default Id.
3006 // If the two defaults are both from default opcode, use the first default as the default value of other default Id.
3007 // If one from flag and the other form default opcode, use the default opcode value as the default value of other default Id.
3009 if ((SmallestDefaultId
> VarDefaultId
) || (SmallestDefaultId
== VarDefaultId
&& !FromOtherDefaultOpcode
)) {
3010 FromOtherDefaultOpcode
= TRUE
;
3011 SmallestDefaultId
= VarDefaultId
;
3012 for (LinkData
= DefaultIdArray
->Entry
.ForwardLink
; LinkData
!= &DefaultIdArray
->Entry
; LinkData
= LinkData
->ForwardLink
) {
3013 DefaultDataPtr
= BASE_CR (LinkData
, IFR_DEFAULT_DATA
, Entry
);
3014 if (DefaultDataPtr
->DefaultId
!= DefaultData
.DefaultId
){
3015 DefaultData
.Type
= DefaultValueFromOtherDefault
;
3016 DefaultData
.DefaultId
= DefaultDataPtr
->DefaultId
;
3017 InsertDefaultValue (BlockData
, &DefaultData
);
3023 // After insert the default value, reset the cleaned value for next
3024 // time used. If not set here, need to set the value before every time.
3027 DefaultData
.Cleaned
= FALSE
;
3030 case EFI_IFR_END_OP
:
3032 // End Opcode is for Var question.
3034 QuestionReferBitField
= FALSE
;
3035 if (BlockData
!= NULL
) {
3036 if (BlockData
->Scope
> 0) {
3039 if (BlockData
->Scope
== 0) {
3042 // when finishing parsing a question, clean the SmallestDefaultId and GetDefaultFromDefaultOpcode.
3044 SmallestDefaultId
= 0xFFFF;
3045 FromOtherDefaultOpcode
= FALSE
;
3051 case EFI_IFR_GUID_OP
:
3052 if (CompareGuid ((EFI_GUID
*)((UINT8
*)IfrOpHdr
+ sizeof (EFI_IFR_OP_HEADER
)), &gEdkiiIfrBitVarstoreGuid
)) {
3053 QuestionReferBitField
= TRUE
;
3058 if (BlockData
!= NULL
) {
3059 if (BlockData
->Scope
> 0) {
3060 BlockData
->Scope
= (UINT8
) (BlockData
->Scope
+ IfrOpHdr
->Scope
);
3063 if (BlockData
->Scope
== 0) {
3070 IfrOffset
+= IfrOpHdr
->Length
;
3071 PackageOffset
+= IfrOpHdr
->Length
;
3075 //if Status == EFI_NOT_FOUND, just means the opcode is not required,not contain any error,
3076 //so set the Status to EFI_SUCCESS.
3078 if (Status
== EFI_NOT_FOUND
){
3079 Status
= EFI_SUCCESS
;
3083 for (LinkData
= VarStorageData
->BlockEntry
.ForwardLink
; LinkData
!= &VarStorageData
->BlockEntry
; LinkData
= LinkData
->ForwardLink
) {
3084 BlockData
= BASE_CR (LinkData
, IFR_BLOCK_DATA
, Entry
);
3085 for (LinkDefault
= BlockData
->DefaultValueEntry
.ForwardLink
; LinkDefault
!= &BlockData
->DefaultValueEntry
; ) {
3086 DefaultDataPtr
= BASE_CR (LinkDefault
, IFR_DEFAULT_DATA
, Entry
);
3087 LinkDefault
= LinkDefault
->ForwardLink
;
3088 if (DefaultDataPtr
->Cleaned
== TRUE
) {
3089 RemoveEntryList (&DefaultDataPtr
->Entry
);
3090 FreePool (DefaultDataPtr
);
3099 parse the configrequest string, get the elements.
3101 @param ConfigRequest The input configrequest string.
3102 @param Progress Return the progress data.
3104 @retval Block data pointer.
3108 IN EFI_STRING ConfigRequest
,
3109 OUT EFI_STRING
*Progress
3112 EFI_STRING StringPtr
;
3113 IFR_BLOCK_DATA
*BlockData
;
3114 IFR_BLOCK_DATA
*RequestBlockArray
;
3120 IFR_BLOCK_DATA
*NextBlockData
;
3126 // Init RequestBlockArray
3128 RequestBlockArray
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
3129 if (RequestBlockArray
== NULL
) {
3132 InitializeListHead (&RequestBlockArray
->Entry
);
3135 // Get the request Block array from the request string
3140 // Parse each <RequestElement> if exists
3141 // Only <BlockName> format is supported by this help function.
3142 // <BlockName> ::= &'OFFSET='<Number>&'WIDTH='<Number>
3144 StringPtr
= ConfigRequest
;
3145 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) == 0) {
3147 // Skip the OFFSET string
3149 *Progress
= StringPtr
;
3150 StringPtr
+= StrLen (L
"&OFFSET=");
3154 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
3155 if (EFI_ERROR (Status
)) {
3162 (((Length
+ 1) / 2) < sizeof (UINT16
)) ? ((Length
+ 1) / 2) : sizeof (UINT16
)
3164 FreePool (TmpBuffer
);
3166 StringPtr
+= Length
;
3167 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
3170 StringPtr
+= StrLen (L
"&WIDTH=");
3175 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
3176 if (EFI_ERROR (Status
)) {
3183 (((Length
+ 1) / 2) < sizeof (UINT16
)) ? ((Length
+ 1) / 2) : sizeof (UINT16
)
3185 FreePool (TmpBuffer
);
3187 StringPtr
+= Length
;
3188 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
3195 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
3196 if (BlockData
== NULL
) {
3199 BlockData
->Offset
= Offset
;
3200 BlockData
->Width
= Width
;
3201 InsertBlockData (&RequestBlockArray
->Entry
, &BlockData
);
3204 // Skip &VALUE string if &VALUE does exists.
3206 if (StrnCmp (StringPtr
, L
"&VALUE=", StrLen (L
"&VALUE=")) == 0) {
3207 StringPtr
+= StrLen (L
"&VALUE=");
3212 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
3213 if (EFI_ERROR (Status
)) {
3216 FreePool (TmpBuffer
);
3217 StringPtr
+= Length
;
3218 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
3223 // If '\0', parsing is finished.
3225 if (*StringPtr
== 0) {
3231 // Merge the requested block data.
3233 Link
= RequestBlockArray
->Entry
.ForwardLink
;
3234 while ((Link
!= &RequestBlockArray
->Entry
) && (Link
->ForwardLink
!= &RequestBlockArray
->Entry
)) {
3235 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
3236 NextBlockData
= BASE_CR (Link
->ForwardLink
, IFR_BLOCK_DATA
, Entry
);
3237 if ((NextBlockData
->Offset
>= BlockData
->Offset
) && (NextBlockData
->Offset
<= (BlockData
->Offset
+ BlockData
->Width
))) {
3238 if ((NextBlockData
->Offset
+ NextBlockData
->Width
) > (BlockData
->Offset
+ BlockData
->Width
)) {
3239 BlockData
->Width
= (UINT16
) (NextBlockData
->Offset
+ NextBlockData
->Width
- BlockData
->Offset
);
3241 RemoveEntryList (Link
->ForwardLink
);
3242 FreePool (NextBlockData
);
3245 Link
= Link
->ForwardLink
;
3248 return RequestBlockArray
;
3251 if (RequestBlockArray
!= NULL
) {
3253 // Free Link Array RequestBlockArray
3255 while (!IsListEmpty (&RequestBlockArray
->Entry
)) {
3256 BlockData
= BASE_CR (RequestBlockArray
->Entry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
3257 RemoveEntryList (&BlockData
->Entry
);
3258 FreePool (BlockData
);
3261 FreePool (RequestBlockArray
);
3268 parse the configrequest string, get the elements.
3270 @param ConfigRequest The input config request string.
3271 @param Progress Return the progress data.
3273 @retval return data block array.
3277 IN EFI_STRING ConfigRequest
,
3278 OUT EFI_STRING
*Progress
3281 EFI_STRING StringPtr
;
3283 IFR_BLOCK_DATA
*BlockData
;
3284 IFR_BLOCK_DATA
*RequestBlockArray
;
3287 StringPtr
= ConfigRequest
;
3290 // Init RequestBlockArray
3292 RequestBlockArray
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
3293 if (RequestBlockArray
== NULL
) {
3296 InitializeListHead (&RequestBlockArray
->Entry
);
3299 // Get the request Block array from the request string
3303 // Parse each <RequestElement> if exists
3304 // Only <BlockName> format is supported by this help function.
3305 // <BlockName> ::= &'Name***=***
3307 while (StringPtr
!= NULL
&& *StringPtr
== L
'&') {
3309 *Progress
= StringPtr
;
3311 // Skip the L"&" string
3316 if ((NextTag
= StrStr (StringPtr
, L
"=")) != NULL
) {
3319 } else if ((NextTag
= StrStr (StringPtr
, L
"&")) != NULL
) {
3326 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
3327 if (BlockData
== NULL
) {
3334 BlockData
->Name
= AllocateCopyPool(StrSize (StringPtr
), StringPtr
);
3335 InsertBlockData (&RequestBlockArray
->Entry
, &BlockData
);
3339 // If has value, skip the value.
3341 StringPtr
= NextTag
+ 1;
3343 StringPtr
= StrStr (StringPtr
, L
"&");
3344 } else if (NextTag
!= NULL
) {
3346 // restore the '&' text.
3348 StringPtr
= NextTag
;
3353 return RequestBlockArray
;
3356 if (RequestBlockArray
!= NULL
) {
3358 // Free Link Array RequestBlockArray
3360 while (!IsListEmpty (&RequestBlockArray
->Entry
)) {
3361 BlockData
= BASE_CR (RequestBlockArray
->Entry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
3362 RemoveEntryList (&BlockData
->Entry
);
3363 if (BlockData
->Name
!= NULL
) {
3364 FreePool (BlockData
->Name
);
3366 FreePool (BlockData
);
3369 FreePool (RequestBlockArray
);
3376 Generate ConfigRequest string base on the varstore info.
3378 @param ConfigHdr The config header for this varstore.
3379 @param VarStorageData The varstore info.
3380 @param Status Return Status.
3381 @param ConfigRequest The ConfigRequest info may be return.
3383 @retval TRUE Need to continue
3384 @retval Others NO need to continue or error occur.
3387 GenerateConfigRequest (
3388 IN CHAR16
*ConfigHdr
,
3389 IN IFR_VARSTORAGE_DATA
*VarStorageData
,
3390 OUT EFI_STATUS
*Status
,
3391 IN OUT EFI_STRING
*ConfigRequest
3397 CHAR16
*FullConfigRequest
;
3399 IFR_BLOCK_DATA
*BlockData
;
3402 // Append VarStorageData BlockEntry into *Request string
3403 // Now support only one varstore in a form package.
3407 // Go through all VarStorageData Entry and get BlockEntry for each one for the multiple varstore in a single form package
3408 // Then construct them all to return MultiRequest string : ConfigHdr BlockConfig
3412 // Compute the length of the entire request starting with <ConfigHdr> and a
3416 Length
= StrLen (ConfigHdr
) + 1;
3418 for (Link
= VarStorageData
->BlockEntry
.ForwardLink
; Link
!= &VarStorageData
->BlockEntry
; Link
= Link
->ForwardLink
) {
3420 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
3421 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3423 // Add <BlockName> length for each Name
3425 // <BlockName> ::= &Name1&Name2&...
3426 // |1| StrLen(Name1)
3428 Length
= Length
+ (1 + StrLen (BlockData
->Name
));
3431 // Add <BlockName> length for each Offset/Width pair
3433 // <BlockName> ::= &OFFSET=1234&WIDTH=1234
3434 // | 8 | 4 | 7 | 4 |
3436 Length
= Length
+ (8 + 4 + 7 + 4);
3440 // No any request block data is found. The request string can't be constructed.
3443 *Status
= EFI_SUCCESS
;
3448 // Allocate buffer for the entire <ConfigRequest>
3450 FullConfigRequest
= AllocateZeroPool (Length
* sizeof (CHAR16
));
3451 if (FullConfigRequest
== NULL
) {
3452 *Status
= EFI_OUT_OF_RESOURCES
;
3455 StringPtr
= FullConfigRequest
;
3458 // Start with <ConfigHdr>
3460 StrCpyS (StringPtr
, Length
, ConfigHdr
);
3461 StringPtr
+= StrLen (StringPtr
);
3464 // Loop through all the Offset/Width pairs and append them to ConfigRequest
3466 for (Link
= VarStorageData
->BlockEntry
.ForwardLink
; Link
!= &VarStorageData
->BlockEntry
; Link
= Link
->ForwardLink
) {
3467 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
3468 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3474 (1 + StrLen (BlockData
->Name
) + 1) * sizeof (CHAR16
),
3480 // Append &OFFSET=XXXX&WIDTH=YYYY\0
3484 (8 + 4 + 7 + 4 + 1) * sizeof (CHAR16
),
3485 L
"&OFFSET=%04X&WIDTH=%04X",
3490 StringPtr
+= StrLen (StringPtr
);
3493 // Set to the got full request string.
3495 HiiToLower (FullConfigRequest
);
3497 if (*ConfigRequest
!= NULL
) {
3498 FreePool (*ConfigRequest
);
3500 *ConfigRequest
= FullConfigRequest
;
3506 Generate ConfigRequest Header base on the varstore info.
3508 @param VarStorageData The varstore info.
3509 @param DevicePath Device path for this varstore.
3510 @param ConfigHdr The config header for this varstore.
3512 @retval EFI_SUCCESS Generate the header success.
3513 @retval EFI_OUT_OF_RESOURCES Allocate buffer fail.
3517 IN IFR_VARSTORAGE_DATA
*VarStorageData
,
3518 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
3519 OUT EFI_STRING
*ConfigHdr
3528 Status
= EFI_SUCCESS
;
3534 // Construct <ConfigHdr> : "GUID=...&NAME=...&PATH=..." by VarStorageData Guid, Name and DriverHandle
3536 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*) &VarStorageData
->Guid
, 1, &GuidStr
);
3537 if (VarStorageData
->Name
!= NULL
) {
3538 GenerateSubStr (L
"NAME=", StrLen (VarStorageData
->Name
) * sizeof (CHAR16
), (VOID
*) VarStorageData
->Name
, 2, &NameStr
);
3540 GenerateSubStr (L
"NAME=", 0, NULL
, 2, &NameStr
);
3544 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) DevicePath
),
3545 (VOID
*) DevicePath
,
3549 Length
= StrLen (GuidStr
) + StrLen (NameStr
) + StrLen (PathStr
) + 1;
3550 if (VarStorageData
->Name
== NULL
) {
3554 *ConfigHdr
= AllocateZeroPool (Length
* sizeof (CHAR16
));
3555 if (*ConfigHdr
== NULL
) {
3556 Status
= EFI_OUT_OF_RESOURCES
;
3559 StrCpyS (*ConfigHdr
, Length
, GuidStr
);
3560 StrCatS (*ConfigHdr
, Length
, NameStr
);
3561 if (VarStorageData
->Name
== NULL
) {
3562 StrCatS (*ConfigHdr
, Length
, L
"&");
3564 StrCatS (*ConfigHdr
, Length
, PathStr
);
3567 // Remove the last character L'&'
3569 *(*ConfigHdr
+ StrLen (*ConfigHdr
) - 1) = L
'\0';
3572 if (GuidStr
!= NULL
) {
3576 if (NameStr
!= NULL
) {
3580 if (PathStr
!= NULL
) {
3589 Update the default value in the block data which is used as bit var store.
3592 A question value saved in a bit fied: bitoffset = 1; bitwidth = 2;default value = 1.
3593 And corresponding block data info: offset==0; width==1;currently the default value
3594 is saved as 1.Actually the default value 1 need to be set to bit field 1, so the
3595 default value of this block data shuold be:2.
3599 UINT8 Bit2 : 2; // Question saved in Bit2,so originalBlock info: offset = 0; width = 1;(byte level) defaul = 1.
3600 // (default value record for the bit field)
3604 After function UpdateDefaultValue,the Block info is: offset = 0; width = 1;(byte level) default = 2.
3605 (default value record for the Block)
3607 UpdateDefaultValue function update default value of bit var block based on the bit field info in the block.
3609 @param BlockLink The Link of the block data.
3613 UpdateDefaultValue (
3614 IN LIST_ENTRY
*BlockLink
3618 LIST_ENTRY
*ListEntry
;
3619 LIST_ENTRY
*LinkDefault
;
3620 IFR_BLOCK_DATA
*BlockData
;
3621 IFR_DEFAULT_DATA
*DefaultValueData
;
3624 UINT32 BitFieldDefaultValue
;
3626 for ( Link
= BlockLink
->ForwardLink
; Link
!= BlockLink
; Link
= Link
->ForwardLink
) {
3627 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
3628 if (!BlockData
->IsBitVar
) {
3631 ListEntry
= &BlockData
->DefaultValueEntry
;
3633 // Update the default value in the block data with all existing default id.
3635 for (LinkDefault
= ListEntry
->ForwardLink
; LinkDefault
!= ListEntry
; LinkDefault
= LinkDefault
->ForwardLink
) {
3637 // Get the default data, and the value of the default data is for some field in the block.
3638 // Note: Default value for bit field question is stored as UINT32.
3640 DefaultValueData
= BASE_CR (LinkDefault
, IFR_DEFAULT_DATA
, Entry
);
3641 BitFieldDefaultValue
= DefaultValueData
->Value
.u32
;
3643 StartBit
= BlockData
->BitOffset
% 8;
3644 EndBit
= StartBit
+ BlockData
->BitWidth
- 1;
3647 // Set the bit field default value to related bit filed, then we will got the new default vaule for the block data.
3649 DefaultValueData
->Value
.u32
= BitFieldWrite32 (0, StartBit
, EndBit
, BitFieldDefaultValue
);
3655 Merge the default value in two block datas which have overlap region.
3657 For bit fields, their related block data may have overlap region, such as:
3660 UINT16 Bit1 : 6; // Question1 refer Bit1, Block1: offset = 0; width = 1;(byte level) default = 1
3661 UINT16 Bit2 : 5; // Question2 refer Bit2, Block2: offset = 0; width = 2;(byte level) default = 5
3662 // (default value record for the bit field)
3666 After function UpdateDefaultValue:
3667 Block1: offset = 0; width = 1;(byte level) default = 1
3668 Block2: offset = 0; width = 2;(byte level) default = 320 (5 * (2 << 6))
3669 (default value record for block)
3671 After function MergeBlockDefaultValue:
3672 Block1: offset = 0; width = 1;(byte level) default = 65
3673 Block2: offset = 0; width = 2;(byte level) default = 321
3674 (Block1 and Block2 has overlap region, merge the overlap value to Block1 and Blcok2)
3676 Block1 and Block2 have overlap byte region, but currntly the default value of Block1 only contains
3677 value of Bit1 (low 6 bits),the default value of Block2 only contains the value of Bit2 (middle 5 bits).
3679 This fuction merge the default value of these two blocks, and make the default value of block1
3680 also contain the value of lower 2 bits of the Bit2. And make the default value of Block2 also
3681 contain the default value of Bit1.
3683 We can get the total value of the whole block that just cover these two blocks(in this case is:
3684 block: offset =0; width =2;) then the value of block2 is same as block, the value of block1 is
3685 the first byte value of block.
3687 @param FirstBlock Point to the block date whose default value need to be merged.
3688 @param SecondBlock Point to the block date whose default value need to be merged.
3692 MergeBlockDefaultValue (
3693 IN OUT IFR_BLOCK_DATA
*FirstBlock
,
3694 IN OUT IFR_BLOCK_DATA
*SecondBlock
3697 LIST_ENTRY
*FirstListEntry
;
3698 LIST_ENTRY
*SecondListEntry
;
3699 LIST_ENTRY
*FirstDefaultLink
;
3700 LIST_ENTRY
*SecondDefaultLink
;
3701 IFR_DEFAULT_DATA
*FirstDefaultValueData
;
3702 IFR_DEFAULT_DATA
*SecondDefaultValueData
;
3703 UINT32
*FirstDefaultValue
;
3704 UINT32
*SecondDefaultValue
;
3706 UINT64 ShiftedValue
;
3709 FirstListEntry
= &FirstBlock
->DefaultValueEntry
;
3710 for (FirstDefaultLink
= FirstListEntry
->ForwardLink
; FirstDefaultLink
!= FirstListEntry
; FirstDefaultLink
= FirstDefaultLink
->ForwardLink
) {
3711 FirstDefaultValueData
= BASE_CR (FirstDefaultLink
, IFR_DEFAULT_DATA
, Entry
);
3712 SecondListEntry
= &SecondBlock
->DefaultValueEntry
;
3713 for (SecondDefaultLink
= SecondListEntry
->ForwardLink
; SecondDefaultLink
!= SecondListEntry
; SecondDefaultLink
= SecondDefaultLink
->ForwardLink
) {
3714 SecondDefaultValueData
= BASE_CR (SecondDefaultLink
, IFR_DEFAULT_DATA
, Entry
);
3715 if (FirstDefaultValueData
->DefaultId
!= SecondDefaultValueData
->DefaultId
) {
3719 // Find default value with same default id in the two blocks.
3720 // Note: Default value for bit field question is stored as UINT32 type.
3722 FirstDefaultValue
= &FirstDefaultValueData
->Value
.u32
;
3723 SecondDefaultValue
= &SecondDefaultValueData
->Value
.u32
;
3725 // 1. Get the default value of the whole blcok that can just cover FirstBlock and SecondBlock.
3726 // 2. Get the default value of FirstBlock and SecondBlock form the value of whole block based
3727 // on the offset and width of FirstBlock and SecondBlock.
3729 if (FirstBlock
->Offset
> SecondBlock
->Offset
) {
3730 OffsetShift
= FirstBlock
->Offset
- SecondBlock
->Offset
;
3731 ShiftedValue
= LShiftU64 ((UINT64
) (*FirstDefaultValue
), OffsetShift
* 8);
3732 TotalValue
= ShiftedValue
| (UINT64
) (*SecondDefaultValue
);
3733 *SecondDefaultValue
= (UINT32
) BitFieldRead64 (TotalValue
, 0, SecondBlock
->Width
* 8 -1);
3734 *FirstDefaultValue
= (UINT32
) BitFieldRead64 (TotalValue
, OffsetShift
* 8, OffsetShift
* 8 + FirstBlock
->Width
*8 -1);
3736 OffsetShift
= SecondBlock
->Offset
-FirstBlock
->Offset
;
3737 ShiftedValue
= LShiftU64 ((UINT64
) (*SecondDefaultValue
), OffsetShift
* 8);
3738 TotalValue
= ShiftedValue
| (UINT64
) (*FirstDefaultValue
);
3739 *FirstDefaultValue
= (UINT32
) BitFieldRead64 (TotalValue
, 0, FirstBlock
->Width
* 8 -1);
3740 *SecondDefaultValue
= (UINT32
) BitFieldRead64 (TotalValue
, OffsetShift
* 8, OffsetShift
* 8 + SecondBlock
->Width
*8 -1);
3748 Update the default value in the block data which used as Bit VarStore
3750 @param BlockLink The Link of the block data.
3754 UpdateBlockDataArray (
3755 IN LIST_ENTRY
*BlockLink
3759 LIST_ENTRY
*TempLink
;
3760 IFR_BLOCK_DATA
*BlockData
;
3761 IFR_BLOCK_DATA
*NextBlockData
;
3764 // 1. Update default value in BitVar block data.
3765 // Sine some block datas are used as BitVarStore, then the default value recored in the block
3766 // is for related bit field in the block. so we need to set the default value to the related bit
3767 // fields in the block data if the block data is used as bit varstore, then the default value of
3768 // the block will be updated.
3770 UpdateDefaultValue (BlockLink
);
3773 // 2.Update default value for overlap BitVar blcok datas.
3774 // For block datas have overlap region, we need to merge the default value in different blocks.
3776 for (Link
= BlockLink
->ForwardLink
; Link
!= BlockLink
; Link
= Link
->ForwardLink
) {
3777 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
3778 if (!BlockData
->IsBitVar
) {
3781 for (TempLink
= Link
->ForwardLink
; TempLink
!= BlockLink
; TempLink
= TempLink
->ForwardLink
) {
3782 NextBlockData
= BASE_CR (TempLink
, IFR_BLOCK_DATA
, Entry
);
3783 if (!NextBlockData
->IsBitVar
|| NextBlockData
->Offset
>= BlockData
->Offset
+ BlockData
->Width
|| BlockData
->Offset
>= NextBlockData
->Offset
+ NextBlockData
->Width
) {
3787 // Find two blocks are used as bit VarStore and have overlap region, so need to merge default value of these two blocks.
3789 MergeBlockDefaultValue (BlockData
, NextBlockData
);
3795 Generate ConfigAltResp string base on the varstore info.
3797 @param HiiHandle Hii Handle for this hii package.
3798 @param ConfigHdr The config header for this varstore.
3799 @param VarStorageData The varstore info.
3800 @param DefaultIdArray The Default id array.
3801 @param DefaultAltCfgResp The DefaultAltCfgResp info may be return.
3803 @retval TRUE Need to continue
3804 @retval Others NO need to continue or error occur.
3807 GenerateAltConfigResp (
3808 IN EFI_HII_HANDLE HiiHandle
,
3809 IN CHAR16
*ConfigHdr
,
3810 IN IFR_VARSTORAGE_DATA
*VarStorageData
,
3811 IN IFR_DEFAULT_DATA
*DefaultIdArray
,
3812 IN OUT EFI_STRING
*DefaultAltCfgResp
3818 LIST_ENTRY
*LinkData
;
3819 LIST_ENTRY
*LinkDefault
;
3820 LIST_ENTRY
*ListEntry
;
3822 IFR_BLOCK_DATA
*BlockData
;
3823 IFR_DEFAULT_DATA
*DefaultId
;
3824 IFR_DEFAULT_DATA
*DefaultValueData
;
3827 CHAR16
*DefaultString
;
3832 DefaultString
= NULL
;
3834 // Add length for <ConfigHdr> + '\0'
3836 Length
= StrLen (ConfigHdr
) + 1;
3838 UpdateBlockDataArray (&VarStorageData
->BlockEntry
);
3840 for (Link
= DefaultIdArray
->Entry
.ForwardLink
; Link
!= &DefaultIdArray
->Entry
; Link
= Link
->ForwardLink
) {
3841 DefaultId
= BASE_CR (Link
, IFR_DEFAULT_DATA
, Entry
);
3843 // Add length for "&<ConfigHdr>&ALTCFG=XXXX"
3844 // |1| StrLen (ConfigHdr) | 8 | 4 |
3846 Length
+= (1 + StrLen (ConfigHdr
) + 8 + 4);
3848 for (LinkData
= VarStorageData
->BlockEntry
.ForwardLink
; LinkData
!= &VarStorageData
->BlockEntry
; LinkData
= LinkData
->ForwardLink
) {
3849 BlockData
= BASE_CR (LinkData
, IFR_BLOCK_DATA
, Entry
);
3850 ListEntry
= &BlockData
->DefaultValueEntry
;
3851 for (LinkDefault
= ListEntry
->ForwardLink
; LinkDefault
!= ListEntry
; LinkDefault
= LinkDefault
->ForwardLink
) {
3852 DefaultValueData
= BASE_CR (LinkDefault
, IFR_DEFAULT_DATA
, Entry
);
3853 if (DefaultValueData
->DefaultId
!= DefaultId
->DefaultId
) {
3856 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3858 // Add length for "&Name1=zzzzzzzzzzzz"
3861 Length
+= (1 + StrLen (BlockData
->Name
) + 1 + BlockData
->Width
* 2);
3864 // Add length for "&OFFSET=XXXX&WIDTH=YYYY&VALUE=zzzzzzzzzzzz"
3865 // | 8 | 4 | 7 | 4 | 7 | Width * 2 |
3867 Length
+= (8 + 4 + 7 + 4 + 7 + BlockData
->Width
* 2);
3875 // No default value is found. The default string doesn't exist.
3882 // Allocate buffer for the entire <DefaultAltCfgResp>
3884 *DefaultAltCfgResp
= AllocateZeroPool (Length
* sizeof (CHAR16
));
3885 if (*DefaultAltCfgResp
== NULL
) {
3886 return EFI_OUT_OF_RESOURCES
;
3888 StringPtr
= *DefaultAltCfgResp
;
3891 // Start with <ConfigHdr>
3893 StrCpyS (StringPtr
, Length
, ConfigHdr
);
3894 StringPtr
+= StrLen (StringPtr
);
3896 for (Link
= DefaultIdArray
->Entry
.ForwardLink
; Link
!= &DefaultIdArray
->Entry
; Link
= Link
->ForwardLink
) {
3897 DefaultId
= BASE_CR (Link
, IFR_DEFAULT_DATA
, Entry
);
3899 // Add <AltConfigHdr> of the form "&<ConfigHdr>&ALTCFG=XXXX\0"
3900 // |1| StrLen (ConfigHdr) | 8 | 4 |
3904 (1 + StrLen (ConfigHdr
) + 8 + 4 + 1) * sizeof (CHAR16
),
3907 DefaultId
->DefaultId
3909 StringPtr
+= StrLen (StringPtr
);
3911 for (LinkData
= VarStorageData
->BlockEntry
.ForwardLink
; LinkData
!= &VarStorageData
->BlockEntry
; LinkData
= LinkData
->ForwardLink
) {
3912 BlockData
= BASE_CR (LinkData
, IFR_BLOCK_DATA
, Entry
);
3913 ListEntry
= &BlockData
->DefaultValueEntry
;
3914 for (LinkDefault
= ListEntry
->ForwardLink
; LinkDefault
!= ListEntry
; LinkDefault
= LinkDefault
->ForwardLink
) {
3915 DefaultValueData
= BASE_CR (LinkDefault
, IFR_DEFAULT_DATA
, Entry
);
3916 if (DefaultValueData
->DefaultId
!= DefaultId
->DefaultId
) {
3919 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3922 (1 + StrLen (ConfigHdr
) + 1) * sizeof (CHAR16
),
3926 StringPtr
+= StrLen (StringPtr
);
3929 // Add <BlockConfig>
3930 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>
3934 (8 + 4 + 7 + 4 + 7 + 1) * sizeof (CHAR16
),
3935 L
"&OFFSET=%04X&WIDTH=%04X&VALUE=",
3939 StringPtr
+= StrLen (StringPtr
);
3941 Width
= BlockData
->Width
;
3943 // Convert Value to a hex string in "%x" format
3944 // NOTE: This is in the opposite byte that GUID and PATH use
3946 if (BlockData
->OpCode
== EFI_IFR_STRING_OP
){
3947 DefaultString
= InternalGetString(HiiHandle
, DefaultValueData
->Value
.string
);
3948 TmpBuffer
= AllocateZeroPool (Width
);
3949 ASSERT (TmpBuffer
!= NULL
);
3950 if (DefaultString
!= NULL
) {
3951 StrSize
= StrLen(DefaultString
)* sizeof (CHAR16
);
3952 if (StrSize
> Width
) {
3955 CopyMem (TmpBuffer
, (UINT8
*) DefaultString
, StrSize
);
3958 TmpBuffer
= (UINT8
*) &(DefaultValueData
->Value
);
3960 for (; Width
> 0 && (TmpBuffer
!= NULL
); Width
--) {
3961 UnicodeValueToStringS (
3963 Length
* sizeof (CHAR16
) - ((UINTN
)StringPtr
- (UINTN
)*DefaultAltCfgResp
),
3964 PREFIX_ZERO
| RADIX_HEX
,
3965 TmpBuffer
[Width
- 1],
3968 StringPtr
+= StrnLenS (StringPtr
, Length
- ((UINTN
)StringPtr
- (UINTN
)*DefaultAltCfgResp
) / sizeof (CHAR16
));
3970 if (DefaultString
!= NULL
){
3971 FreePool(DefaultString
);
3972 DefaultString
= NULL
;
3974 if (BlockData
->OpCode
== EFI_IFR_STRING_OP
&& TmpBuffer
!= NULL
) {
3975 FreePool(TmpBuffer
);
3982 HiiToLower (*DefaultAltCfgResp
);
3988 This function gets the full request string and full default value string by
3989 parsing IFR data in HII form packages.
3991 When Request points to NULL string, the request string and default value string
3992 for each varstore in form package will return.
3994 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
3995 @param DevicePath Device Path which Hii Config Access Protocol is registered.
3996 @param Request Pointer to a null-terminated Unicode string in
3997 <ConfigRequest> format. When it doesn't contain
3998 any RequestElement, it will be updated to return
3999 the full RequestElement retrieved from IFR data.
4000 If it points to NULL, the request string for the first
4001 varstore in form package will be merged into a
4002 <MultiConfigRequest> format string and return.
4003 @param AltCfgResp Pointer to a null-terminated Unicode string in
4004 <ConfigAltResp> format. When the pointer is to NULL,
4005 the full default value string retrieved from IFR data
4006 will return. When the pinter is to a string, the
4007 full default value string retrieved from IFR data
4008 will be merged into the input string and return.
4009 When Request points to NULL, the default value string
4010 for each varstore in form package will be merged into
4011 a <MultiConfigAltResp> format string and return.
4012 @param PointerProgress Optional parameter, it can be NULL.
4013 When it is not NULL, if Request is NULL, it returns NULL.
4014 On return, points to a character in the Request
4015 string. Points to the string's null terminator if
4016 request was successful. Points to the most recent
4017 & before the first failing name / value pair (or
4018 the beginning of the string if the failure is in
4019 the first name / value pair) if the request was
4021 @retval EFI_SUCCESS The Results string is set to the full request string.
4022 And AltCfgResp contains all default value string.
4023 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
4024 @retval EFI_NOT_FOUND The varstore (Guid and Name) in Request string
4025 can't be found in Form package.
4026 @retval EFI_NOT_FOUND HiiPackage can't be got on the input HiiHandle.
4027 @retval EFI_INVALID_PARAMETER Request points to NULL.
4032 GetFullStringFromHiiFormPackages (
4033 IN HII_DATABASE_RECORD
*DataBaseRecord
,
4034 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
4035 IN OUT EFI_STRING
*Request
,
4036 IN OUT EFI_STRING
*AltCfgResp
,
4037 OUT EFI_STRING
*PointerProgress OPTIONAL
4041 UINT8
*HiiFormPackage
;
4043 IFR_BLOCK_DATA
*RequestBlockArray
;
4044 IFR_BLOCK_DATA
*BlockData
;
4045 IFR_DEFAULT_DATA
*DefaultValueData
;
4046 IFR_DEFAULT_DATA
*DefaultId
;
4047 IFR_DEFAULT_DATA
*DefaultIdArray
;
4048 IFR_VARSTORAGE_DATA
*VarStorageData
;
4049 EFI_STRING DefaultAltCfgResp
;
4050 EFI_STRING ConfigHdr
;
4051 EFI_STRING StringPtr
;
4052 EFI_STRING Progress
;
4054 if (DataBaseRecord
== NULL
|| DevicePath
== NULL
|| Request
== NULL
|| AltCfgResp
== NULL
) {
4055 return EFI_INVALID_PARAMETER
;
4059 // Initialize the local variables.
4061 RequestBlockArray
= NULL
;
4062 DefaultIdArray
= NULL
;
4063 VarStorageData
= NULL
;
4064 DefaultAltCfgResp
= NULL
;
4066 HiiFormPackage
= NULL
;
4068 Progress
= *Request
;
4070 Status
= GetFormPackageData (DataBaseRecord
, &HiiFormPackage
, &PackageSize
);
4071 if (EFI_ERROR (Status
)) {
4076 // 1. Get the request block array by Request String when Request string contains the block array.
4079 if (*Request
!= NULL
) {
4080 StringPtr
= *Request
;
4084 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
4085 Status
= EFI_INVALID_PARAMETER
;
4088 StringPtr
+= StrLen (L
"GUID=");
4089 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&NAME=", StrLen (L
"&NAME=")) != 0) {
4092 if (*StringPtr
== L
'\0') {
4093 Status
= EFI_INVALID_PARAMETER
;
4096 StringPtr
+= StrLen (L
"&NAME=");
4097 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&PATH=", StrLen (L
"&PATH=")) != 0) {
4100 if (*StringPtr
== L
'\0') {
4101 Status
= EFI_INVALID_PARAMETER
;
4104 StringPtr
+= StrLen (L
"&PATH=");
4105 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
4109 if (*StringPtr
== L
'\0') {
4111 // No request block is found.
4118 // If StringPtr != NULL, get the request elements.
4120 if (StringPtr
!= NULL
) {
4121 if (StrStr (StringPtr
, L
"&OFFSET=") != NULL
) {
4122 RequestBlockArray
= GetBlockElement(StringPtr
, &Progress
);
4124 RequestBlockArray
= GetNameElement(StringPtr
, &Progress
);
4127 if (RequestBlockArray
== NULL
) {
4128 Status
= EFI_INVALID_PARAMETER
;
4134 // Initialize DefaultIdArray to store the map between DeaultId and DefaultName
4136 DefaultIdArray
= (IFR_DEFAULT_DATA
*) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
4137 if (DefaultIdArray
== NULL
) {
4138 Status
= EFI_OUT_OF_RESOURCES
;
4141 InitializeListHead (&DefaultIdArray
->Entry
);
4144 // Initialize VarStorageData to store the var store Block and Default value information.
4146 VarStorageData
= (IFR_VARSTORAGE_DATA
*) AllocateZeroPool (sizeof (IFR_VARSTORAGE_DATA
));
4147 if (VarStorageData
== NULL
) {
4148 Status
= EFI_OUT_OF_RESOURCES
;
4151 InitializeListHead (&VarStorageData
->Entry
);
4152 InitializeListHead (&VarStorageData
->BlockEntry
);
4155 // 2. Parse FormPackage to get BlockArray and DefaultId Array for the request BlockArray.
4159 // Parse the opcode in form package to get the default setting.
4161 Status
= ParseIfrData (DataBaseRecord
->Handle
,
4163 (UINT32
) PackageSize
,
4168 if (EFI_ERROR (Status
)) {
4173 // No requested varstore in IFR data and directly return
4175 if (VarStorageData
->Type
== 0 && VarStorageData
->Name
== NULL
) {
4176 Status
= EFI_SUCCESS
;
4181 // 3. Construct Request Element (Block Name) for 2.1 and 2.2 case.
4183 Status
= GenerateHdr (VarStorageData
, DevicePath
, &ConfigHdr
);
4184 if (EFI_ERROR (Status
)) {
4188 if (RequestBlockArray
== NULL
) {
4189 if (!GenerateConfigRequest(ConfigHdr
, VarStorageData
, &Status
, Request
)) {
4195 // 4. Construct Default Value string in AltResp according to request element.
4196 // Go through all VarStorageData Entry and get the DefaultId array for each one
4197 // Then construct them all to : ConfigHdr AltConfigHdr ConfigBody AltConfigHdr ConfigBody
4199 Status
= GenerateAltConfigResp (DataBaseRecord
->Handle
,ConfigHdr
, VarStorageData
, DefaultIdArray
, &DefaultAltCfgResp
);
4200 if (EFI_ERROR (Status
)) {
4205 // 5. Merge string into the input AltCfgResp if the input *AltCfgResp is not NULL.
4207 if (*AltCfgResp
!= NULL
&& DefaultAltCfgResp
!= NULL
) {
4208 Status
= MergeDefaultString (AltCfgResp
, DefaultAltCfgResp
);
4209 FreePool (DefaultAltCfgResp
);
4210 } else if (*AltCfgResp
== NULL
) {
4211 *AltCfgResp
= DefaultAltCfgResp
;
4215 if (RequestBlockArray
!= NULL
) {
4217 // Free Link Array RequestBlockArray
4219 while (!IsListEmpty (&RequestBlockArray
->Entry
)) {
4220 BlockData
= BASE_CR (RequestBlockArray
->Entry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
4221 RemoveEntryList (&BlockData
->Entry
);
4222 if (BlockData
->Name
!= NULL
) {
4223 FreePool (BlockData
->Name
);
4225 FreePool (BlockData
);
4228 FreePool (RequestBlockArray
);
4231 if (VarStorageData
!= NULL
) {
4233 // Free link array VarStorageData
4235 while (!IsListEmpty (&VarStorageData
->BlockEntry
)) {
4236 BlockData
= BASE_CR (VarStorageData
->BlockEntry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
4237 RemoveEntryList (&BlockData
->Entry
);
4238 if (BlockData
->Name
!= NULL
) {
4239 FreePool (BlockData
->Name
);
4242 // Free default value link array
4244 while (!IsListEmpty (&BlockData
->DefaultValueEntry
)) {
4245 DefaultValueData
= BASE_CR (BlockData
->DefaultValueEntry
.ForwardLink
, IFR_DEFAULT_DATA
, Entry
);
4246 RemoveEntryList (&DefaultValueData
->Entry
);
4247 FreePool (DefaultValueData
);
4249 FreePool (BlockData
);
4251 if (VarStorageData
->Name
!= NULL
) {
4252 FreePool (VarStorageData
->Name
);
4253 VarStorageData
->Name
= NULL
;
4255 FreePool (VarStorageData
);
4258 if (DefaultIdArray
!= NULL
) {
4260 // Free DefaultId Array
4262 while (!IsListEmpty (&DefaultIdArray
->Entry
)) {
4263 DefaultId
= BASE_CR (DefaultIdArray
->Entry
.ForwardLink
, IFR_DEFAULT_DATA
, Entry
);
4264 RemoveEntryList (&DefaultId
->Entry
);
4265 FreePool (DefaultId
);
4267 FreePool (DefaultIdArray
);
4271 // Free the allocated string
4273 if (ConfigHdr
!= NULL
) {
4274 FreePool (ConfigHdr
);
4278 // Free Package data
4280 if (HiiFormPackage
!= NULL
) {
4281 FreePool (HiiFormPackage
);
4284 if (PointerProgress
!= NULL
) {
4285 if (*Request
== NULL
) {
4286 *PointerProgress
= NULL
;
4287 } else if (EFI_ERROR (Status
)) {
4288 *PointerProgress
= *Request
;
4290 *PointerProgress
= *Request
+ StrLen (*Request
);
4298 This function gets the full request resp string by
4299 parsing IFR data in HII form packages.
4301 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
4303 @param EfiVarStoreInfo The efi varstore info which is save in the EFI
4304 varstore data structure.
4305 @param Request Pointer to a null-terminated Unicode string in
4306 <ConfigRequest> format.
4307 @param RequestResp Pointer to a null-terminated Unicode string in
4308 <ConfigResp> format.
4309 @param AccessProgress On return, points to a character in the Request
4310 string. Points to the string's null terminator if
4311 request was successful. Points to the most recent
4312 & before the first failing name / value pair (or
4313 the beginning of the string if the failure is in
4314 the first name / value pair) if the request was
4317 @retval EFI_SUCCESS The Results string is set to the full request string.
4318 And AltCfgResp contains all default value string.
4319 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
4320 @retval EFI_INVALID_PARAMETER Request points to NULL.
4324 GetConfigRespFromEfiVarStore (
4325 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
4326 IN EFI_IFR_VARSTORE_EFI
*EfiVarStoreInfo
,
4327 IN EFI_STRING Request
,
4328 OUT EFI_STRING
*RequestResp
,
4329 OUT EFI_STRING
*AccessProgress
4333 EFI_STRING VarStoreName
;
4338 Status
= EFI_SUCCESS
;
4341 VarStoreName
= NULL
;
4342 *AccessProgress
= Request
;
4344 NameSize
= AsciiStrSize ((CHAR8
*)EfiVarStoreInfo
->Name
);
4345 VarStoreName
= AllocateZeroPool (NameSize
* sizeof (CHAR16
));
4346 if (VarStoreName
== NULL
) {
4347 Status
= EFI_OUT_OF_RESOURCES
;
4350 AsciiStrToUnicodeStrS ((CHAR8
*) EfiVarStoreInfo
->Name
, VarStoreName
, NameSize
);
4353 Status
= gRT
->GetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, NULL
, &BufferSize
, NULL
);
4354 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
4358 VarStore
= AllocateZeroPool (BufferSize
);
4359 ASSERT (VarStore
!= NULL
);
4360 Status
= gRT
->GetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, NULL
, &BufferSize
, VarStore
);
4361 if (EFI_ERROR (Status
)) {
4365 Status
= HiiBlockToConfig(This
, Request
, VarStore
, BufferSize
, RequestResp
, AccessProgress
);
4366 if (EFI_ERROR (Status
)) {
4371 if (VarStoreName
!= NULL
) {
4372 FreePool (VarStoreName
);
4375 if (VarStore
!= NULL
) {
4376 FreePool (VarStore
);
4384 This function route the full request resp string for efi varstore.
4386 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
4388 @param EfiVarStoreInfo The efi varstore info which is save in the EFI
4389 varstore data structure.
4390 @param RequestResp Pointer to a null-terminated Unicode string in
4391 <ConfigResp> format.
4392 @param Result Pointer to a null-terminated Unicode string in
4393 <ConfigResp> format.
4395 @retval EFI_SUCCESS The Results string is set to the full request string.
4396 And AltCfgResp contains all default value string.
4397 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
4398 @retval EFI_INVALID_PARAMETER Request points to NULL.
4402 RouteConfigRespForEfiVarStore (
4403 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
4404 IN EFI_IFR_VARSTORE_EFI
*EfiVarStoreInfo
,
4405 IN EFI_STRING RequestResp
,
4406 OUT EFI_STRING
*Result
4410 EFI_STRING VarStoreName
;
4416 Status
= EFI_SUCCESS
;
4419 VarStoreName
= NULL
;
4420 *Result
= RequestResp
;
4422 NameSize
= AsciiStrSize ((CHAR8
*)EfiVarStoreInfo
->Name
);
4423 VarStoreName
= AllocateZeroPool (NameSize
* sizeof (CHAR16
));
4424 if (VarStoreName
== NULL
) {
4425 Status
= EFI_OUT_OF_RESOURCES
;
4428 AsciiStrToUnicodeStrS ((CHAR8
*) EfiVarStoreInfo
->Name
, VarStoreName
, NameSize
);
4430 Status
= gRT
->GetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, NULL
, &BufferSize
, NULL
);
4431 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
4432 DEBUG ((DEBUG_ERROR
, "The variable does not exist!"));
4436 BlockSize
= BufferSize
;
4437 VarStore
= AllocateZeroPool (BufferSize
);
4438 ASSERT (VarStore
!= NULL
);
4439 Status
= gRT
->GetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, NULL
, &BufferSize
, VarStore
);
4440 if (EFI_ERROR (Status
)) {
4444 Status
= HiiConfigToBlock(This
, RequestResp
, VarStore
, &BlockSize
, Result
);
4445 if (EFI_ERROR (Status
)) {
4449 Status
= gRT
->SetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, EfiVarStoreInfo
->Attributes
, BufferSize
, VarStore
);
4450 if (EFI_ERROR (Status
)) {
4451 *Result
= RequestResp
;
4456 if (VarStoreName
!= NULL
) {
4457 FreePool (VarStoreName
);
4460 if (VarStore
!= NULL
) {
4461 FreePool (VarStore
);
4468 Validate the config request elements.
4470 @param ConfigElements A null-terminated Unicode string in <ConfigRequest> format,
4471 without configHdr field.
4473 @retval CHAR16 * THE first Name/value pair not correct.
4474 @retval NULL Success parse the name/value pair
4477 OffsetWidthValidate (
4478 CHAR16
*ConfigElements
4484 StringPtr
= ConfigElements
;
4488 if (StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) != 0) {
4492 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
4495 if (*StringPtr
== L
'\0') {
4499 StringPtr
+= StrLen (L
"&WIDTH=");
4500 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) != 0) {
4504 if (*StringPtr
== L
'\0') {
4511 Validate the config request elements.
4513 @param ConfigElements A null-terminated Unicode string in <ConfigRequest> format,
4514 without configHdr field.
4516 @retval CHAR16 * THE first Name/value pair not correct.
4517 @retval NULL Success parse the name/value pair
4522 CHAR16
*ConfigElements
4528 StringPtr
= ConfigElements
;
4532 if (*StringPtr
!= L
'&') {
4537 StringPtr
= StrStr (StringPtr
, L
"&");
4539 if (StringPtr
== NULL
) {
4546 Validate the config request string.
4548 @param ConfigRequest A null-terminated Unicode string in <ConfigRequest> format.
4550 @retval CHAR16 * THE first element not correct.
4551 @retval NULL Success parse the name/value pair
4555 ConfigRequestValidate (
4556 CHAR16
*ConfigRequest
4559 BOOLEAN HasNameField
;
4562 HasNameField
= TRUE
;
4563 StringPtr
= ConfigRequest
;
4566 // Check <ConfigHdr>
4568 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
4569 return ConfigRequest
;
4571 StringPtr
+= StrLen (L
"GUID=");
4572 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&NAME=", StrLen (L
"&NAME=")) != 0) {
4575 if (*StringPtr
== L
'\0') {
4576 return ConfigRequest
;
4578 StringPtr
+= StrLen (L
"&NAME=");
4579 if (*StringPtr
== L
'&') {
4580 HasNameField
= FALSE
;
4582 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&PATH=", StrLen (L
"&PATH=")) != 0) {
4585 if (*StringPtr
== L
'\0') {
4586 return ConfigRequest
;
4588 StringPtr
+= StrLen (L
"&PATH=");
4589 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
4593 if (*StringPtr
== L
'\0') {
4599 // Should be Buffer varstore, config request should be "OFFSET/Width" pairs.
4601 return OffsetWidthValidate(StringPtr
);
4604 // Should be Name/Value varstore, config request should be "&name1&name2..." pairs.
4606 return NameValueValidate(StringPtr
);
4611 This function allows a caller to extract the current configuration
4612 for one or more named elements from one or more drivers.
4614 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
4616 @param Request A null-terminated Unicode string in
4617 <MultiConfigRequest> format.
4618 @param Progress On return, points to a character in the Request
4619 string. Points to the string's null terminator if
4620 request was successful. Points to the most recent
4621 & before the first failing name / value pair (or
4622 the beginning of the string if the failure is in
4623 the first name / value pair) if the request was
4625 @param Results Null-terminated Unicode string in
4626 <MultiConfigAltResp> format which has all values
4627 filled in for the names in the Request string.
4628 String to be allocated by the called function.
4630 @retval EFI_SUCCESS The Results string is filled with the values
4631 corresponding to all requested names.
4632 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
4633 results that must be stored awaiting possible
4635 @retval EFI_NOT_FOUND Routing data doesn't match any known driver.
4636 Progress set to the "G" in "GUID" of the routing
4637 header that doesn't match. Note: There is no
4638 requirement that all routing data be validated
4639 before any configuration extraction.
4640 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Request
4641 parameter would result in this type of error. The
4642 Progress parameter is set to NULL.
4643 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set to most recent &
4644 before the error or the beginning of the string.
4645 @retval EFI_INVALID_PARAMETER The ExtractConfig function of the underlying HII
4646 Configuration Access Protocol returned
4647 EFI_INVALID_PARAMETER. Progress set to most recent
4648 & before the error or the beginning of the string.
4653 HiiConfigRoutingExtractConfig (
4654 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
4655 IN CONST EFI_STRING Request
,
4656 OUT EFI_STRING
*Progress
,
4657 OUT EFI_STRING
*Results
4660 HII_DATABASE_PRIVATE_DATA
*Private
;
4661 EFI_STRING StringPtr
;
4662 EFI_STRING ConfigRequest
;
4664 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
4665 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
4668 HII_DATABASE_RECORD
*Database
;
4669 UINT8
*DevicePathPkg
;
4670 UINT8
*CurrentDevicePath
;
4671 EFI_HANDLE DriverHandle
;
4672 EFI_HII_HANDLE HiiHandle
;
4673 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
4674 EFI_STRING AccessProgress
;
4675 EFI_STRING AccessResults
;
4676 EFI_STRING AccessProgressBackup
;
4677 EFI_STRING AccessResultsBackup
;
4678 EFI_STRING DefaultResults
;
4679 BOOLEAN FirstElement
;
4680 BOOLEAN IfrDataParsedFlag
;
4681 BOOLEAN IsEfiVarStore
;
4682 EFI_IFR_VARSTORE_EFI
*EfiVarStoreInfo
;
4683 EFI_STRING ErrorPtr
;
4684 UINTN DevicePathSize
;
4685 UINTN ConigStringSize
;
4686 UINTN ConigStringSizeNewsize
;
4687 EFI_STRING ConfigStringPtr
;
4689 if (This
== NULL
|| Progress
== NULL
|| Results
== NULL
) {
4690 return EFI_INVALID_PARAMETER
;
4693 if (Request
== NULL
) {
4695 return EFI_INVALID_PARAMETER
;
4698 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
4699 StringPtr
= Request
;
4700 *Progress
= StringPtr
;
4701 DefaultResults
= NULL
;
4702 ConfigRequest
= NULL
;
4703 Status
= EFI_SUCCESS
;
4704 AccessResults
= NULL
;
4705 AccessProgress
= NULL
;
4706 AccessResultsBackup
= NULL
;
4707 AccessProgressBackup
= NULL
;
4709 IfrDataParsedFlag
= FALSE
;
4710 IsEfiVarStore
= FALSE
;
4711 EfiVarStoreInfo
= NULL
;
4714 // The first element of <MultiConfigRequest> should be
4715 // <GuidHdr>, which is in 'GUID='<Guid> syntax.
4717 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
4718 return EFI_INVALID_PARAMETER
;
4721 FirstElement
= TRUE
;
4724 // Allocate a fix length of memory to store Results. Reallocate memory for
4725 // Results if this fix length is insufficient.
4727 *Results
= (EFI_STRING
) AllocateZeroPool (MAX_STRING_LENGTH
);
4728 if (*Results
== NULL
) {
4729 return EFI_OUT_OF_RESOURCES
;
4732 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) == 0) {
4734 // If parsing error, set Progress to the beginning of the <MultiConfigRequest>
4735 // or most recent & before the error.
4737 if (StringPtr
== Request
) {
4738 *Progress
= StringPtr
;
4740 *Progress
= StringPtr
- 1;
4744 // Process each <ConfigRequest> of <MultiConfigRequest>
4746 Length
= CalculateConfigStringLen (StringPtr
);
4747 ConfigRequest
= AllocateCopyPool ((Length
+ 1) * sizeof (CHAR16
), StringPtr
);
4748 if (ConfigRequest
== NULL
) {
4749 Status
= EFI_OUT_OF_RESOURCES
;
4752 *(ConfigRequest
+ Length
) = 0;
4755 // Get the UEFI device path
4757 Status
= GetDevicePath (ConfigRequest
, (UINT8
**) &DevicePath
);
4758 if (EFI_ERROR (Status
)) {
4763 // Find driver which matches the routing data.
4765 DriverHandle
= NULL
;
4768 for (Link
= Private
->DatabaseList
.ForwardLink
;
4769 Link
!= &Private
->DatabaseList
;
4770 Link
= Link
->ForwardLink
4772 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
4773 if ((DevicePathPkg
= Database
->PackageList
->DevicePathPkg
) != NULL
) {
4774 CurrentDevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
4775 DevicePathSize
= GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) CurrentDevicePath
);
4776 if ((CompareMem (DevicePath
,CurrentDevicePath
,DevicePathSize
) == 0) && IsThisPackageList(Database
, ConfigRequest
)) {
4777 DriverHandle
= Database
->DriverHandle
;
4778 HiiHandle
= Database
->Handle
;
4785 // Try to find driver handle by device path.
4787 if (DriverHandle
== NULL
) {
4788 TempDevicePath
= DevicePath
;
4789 Status
= gBS
->LocateDevicePath (
4790 &gEfiDevicePathProtocolGuid
,
4794 if (EFI_ERROR (Status
) || (DriverHandle
== NULL
)) {
4796 // Routing data does not match any known driver.
4797 // Set Progress to the 'G' in "GUID" of the routing header.
4799 *Progress
= StringPtr
;
4800 Status
= EFI_NOT_FOUND
;
4806 // Validate ConfigRequest String.
4808 ErrorPtr
= ConfigRequestValidate(ConfigRequest
);
4809 if (ErrorPtr
!= NULL
) {
4810 *Progress
= StrStr (StringPtr
, ErrorPtr
);
4811 Status
= EFI_INVALID_PARAMETER
;
4816 // Check whether ConfigRequest contains request string.
4818 IfrDataParsedFlag
= FALSE
;
4819 if ((HiiHandle
!= NULL
) && !GetElementsFromRequest(ConfigRequest
)) {
4821 // Get the full request string from IFR when HiiPackage is registered to HiiHandle
4823 IfrDataParsedFlag
= TRUE
;
4824 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &ConfigRequest
, &DefaultResults
, &AccessProgress
);
4825 if (EFI_ERROR (Status
)) {
4827 // AccessProgress indicates the parsing progress on <ConfigRequest>.
4828 // Map it to the progress on <MultiConfigRequest> then return it.
4830 ASSERT (AccessProgress
!= NULL
);
4831 *Progress
= StrStr (StringPtr
, AccessProgress
);
4835 // Not any request block is found.
4837 if (!GetElementsFromRequest(ConfigRequest
)) {
4838 AccessResults
= AllocateCopyPool (StrSize (ConfigRequest
), ConfigRequest
);
4839 goto NextConfigString
;
4844 // Check whether this ConfigRequest is search from Efi varstore type storage.
4846 Status
= GetVarStoreType(Database
, ConfigRequest
, &IsEfiVarStore
, &EfiVarStoreInfo
);
4847 if (EFI_ERROR (Status
)) {
4851 if (IsEfiVarStore
) {
4853 // Call the GetVariable function to extract settings.
4855 Status
= GetConfigRespFromEfiVarStore(This
, EfiVarStoreInfo
, ConfigRequest
, &AccessResults
, &AccessProgress
);
4856 FreePool (EfiVarStoreInfo
);
4857 if (EFI_ERROR (Status
)) {
4859 // AccessProgress indicates the parsing progress on <ConfigRequest>.
4860 // Map it to the progress on <MultiConfigRequest> then return it.
4862 *Progress
= StrStr (StringPtr
, AccessProgress
);
4867 // For EfiVarstore, call corresponding ConfigAccess protocol to get the AltCfgResp from driver.
4869 Status
= gBS
->HandleProtocol (
4871 &gEfiHiiConfigAccessProtocolGuid
,
4872 (VOID
**) &ConfigAccess
4874 if (EFI_ERROR (Status
)) {
4876 // The driver has EfiVarStore, may not install ConfigAccess protocol.
4877 // So ignore the error status in this case.
4879 Status
= EFI_SUCCESS
;
4881 Status
= ConfigAccess
->ExtractConfig (
4884 &AccessProgressBackup
,
4885 &AccessResultsBackup
4887 if (!EFI_ERROR(Status
)) {
4889 //Merge the AltCfgResp in AccessResultsBackup to AccessResults
4891 if ((AccessResultsBackup
!= NULL
) && (StrStr (AccessResultsBackup
, L
"&ALTCFG=") != NULL
)) {
4892 ConigStringSize
= StrSize (AccessResults
);
4893 ConfigStringPtr
= StrStr (AccessResultsBackup
, L
"&GUID=");
4894 ConigStringSizeNewsize
= StrSize (ConfigStringPtr
) + ConigStringSize
+ sizeof (CHAR16
);
4895 AccessResults
= (EFI_STRING
) ReallocatePool (
4897 ConigStringSizeNewsize
,
4899 StrCatS (AccessResults
, ConigStringSizeNewsize
/ sizeof (CHAR16
), ConfigStringPtr
);
4903 // In the ExtractConfig function of some driver may not support EfiVarStore,
4904 // may return error status, just ignore the error status in this case.
4906 Status
= EFI_SUCCESS
;
4908 if (AccessResultsBackup
!= NULL
) {
4909 FreePool (AccessResultsBackup
);
4910 AccessResultsBackup
= NULL
;
4915 // Call corresponding ConfigAccess protocol to extract settings
4917 Status
= gBS
->HandleProtocol (
4919 &gEfiHiiConfigAccessProtocolGuid
,
4920 (VOID
**) &ConfigAccess
4922 if (EFI_ERROR (Status
)) {
4926 Status
= ConfigAccess
->ExtractConfig (
4933 if (EFI_ERROR (Status
)) {
4935 // AccessProgress indicates the parsing progress on <ConfigRequest>.
4936 // Map it to the progress on <MultiConfigRequest> then return it.
4938 *Progress
= StrStr (StringPtr
, AccessProgress
);
4943 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'
4944 // which separates the first <ConfigAltResp> and the following ones.
4946 ASSERT (*AccessProgress
== 0);
4949 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
4951 if (!IfrDataParsedFlag
&& HiiHandle
!= NULL
) {
4952 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &ConfigRequest
, &DefaultResults
, NULL
);
4953 ASSERT_EFI_ERROR (Status
);
4956 FreePool (DevicePath
);
4959 if (DefaultResults
!= NULL
) {
4960 Status
= MergeDefaultString (&AccessResults
, DefaultResults
);
4961 ASSERT_EFI_ERROR (Status
);
4962 FreePool (DefaultResults
);
4963 DefaultResults
= NULL
;
4967 if (!FirstElement
) {
4968 Status
= AppendToMultiString (Results
, L
"&");
4969 ASSERT_EFI_ERROR (Status
);
4972 Status
= AppendToMultiString (Results
, AccessResults
);
4973 ASSERT_EFI_ERROR (Status
);
4975 FirstElement
= FALSE
;
4977 FreePool (AccessResults
);
4978 AccessResults
= NULL
;
4979 FreePool (ConfigRequest
);
4980 ConfigRequest
= NULL
;
4983 // Go to next <ConfigRequest> (skip '&').
4985 StringPtr
+= Length
;
4986 if (*StringPtr
== 0) {
4987 *Progress
= StringPtr
;
4995 if (EFI_ERROR (Status
)) {
4996 FreePool (*Results
);
5000 if (ConfigRequest
!= NULL
) {
5001 FreePool (ConfigRequest
);
5004 if (AccessResults
!= NULL
) {
5005 FreePool (AccessResults
);
5008 if (DefaultResults
!= NULL
) {
5009 FreePool (DefaultResults
);
5012 if (DevicePath
!= NULL
) {
5013 FreePool (DevicePath
);
5021 This function allows the caller to request the current configuration for the
5022 entirety of the current HII database and returns the data in a
5023 null-terminated Unicode string.
5025 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
5027 @param Results Null-terminated Unicode string in
5028 <MultiConfigAltResp> format which has all values
5029 filled in for the entirety of the current HII
5030 database. String to be allocated by the called
5031 function. De-allocation is up to the caller.
5033 @retval EFI_SUCCESS The Results string is filled with the values
5034 corresponding to all requested names.
5035 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
5036 results that must be stored awaiting possible
5038 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Results
5039 parameter would result in this type of error.
5044 HiiConfigRoutingExportConfig (
5045 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
5046 OUT EFI_STRING
*Results
5050 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
5051 EFI_STRING AccessResults
;
5052 EFI_STRING Progress
;
5053 EFI_STRING StringPtr
;
5054 EFI_STRING ConfigRequest
;
5056 EFI_HANDLE
*ConfigAccessHandles
;
5057 UINTN NumberConfigAccessHandles
;
5058 BOOLEAN FirstElement
;
5059 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
5060 EFI_HII_HANDLE HiiHandle
;
5061 EFI_STRING DefaultResults
;
5062 HII_DATABASE_PRIVATE_DATA
*Private
;
5064 HII_DATABASE_RECORD
*Database
;
5065 UINT8
*DevicePathPkg
;
5066 UINT8
*CurrentDevicePath
;
5067 BOOLEAN IfrDataParsedFlag
;
5069 if (This
== NULL
|| Results
== NULL
) {
5070 return EFI_INVALID_PARAMETER
;
5073 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
5076 // Allocate a fix length of memory to store Results. Reallocate memory for
5077 // Results if this fix length is insufficient.
5079 *Results
= (EFI_STRING
) AllocateZeroPool (MAX_STRING_LENGTH
);
5080 if (*Results
== NULL
) {
5081 return EFI_OUT_OF_RESOURCES
;
5084 NumberConfigAccessHandles
= 0;
5085 Status
= gBS
->LocateHandleBuffer (
5087 &gEfiHiiConfigAccessProtocolGuid
,
5089 &NumberConfigAccessHandles
,
5090 &ConfigAccessHandles
5092 if (EFI_ERROR (Status
)) {
5096 FirstElement
= TRUE
;
5098 for (Index
= 0; Index
< NumberConfigAccessHandles
; Index
++) {
5099 Status
= gBS
->HandleProtocol (
5100 ConfigAccessHandles
[Index
],
5101 &gEfiHiiConfigAccessProtocolGuid
,
5102 (VOID
**) &ConfigAccess
5104 if (EFI_ERROR (Status
)) {
5109 // Get DevicePath and HiiHandle for this ConfigAccess driver handle
5111 IfrDataParsedFlag
= FALSE
;
5114 DefaultResults
= NULL
;
5116 ConfigRequest
= NULL
;
5117 DevicePath
= DevicePathFromHandle (ConfigAccessHandles
[Index
]);
5118 if (DevicePath
!= NULL
) {
5119 for (Link
= Private
->DatabaseList
.ForwardLink
;
5120 Link
!= &Private
->DatabaseList
;
5121 Link
= Link
->ForwardLink
5123 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
5124 if ((DevicePathPkg
= Database
->PackageList
->DevicePathPkg
) != NULL
) {
5125 CurrentDevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
5129 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) CurrentDevicePath
)
5131 HiiHandle
= Database
->Handle
;
5138 Status
= ConfigAccess
->ExtractConfig (
5144 if (EFI_ERROR (Status
)) {
5146 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
5148 if (HiiHandle
!= NULL
&& DevicePath
!= NULL
) {
5149 IfrDataParsedFlag
= TRUE
;
5150 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &ConfigRequest
, &DefaultResults
, NULL
);
5152 // Get the full request string to get the Current setting again.
5154 if (!EFI_ERROR (Status
) && ConfigRequest
!= NULL
) {
5155 Status
= ConfigAccess
->ExtractConfig (
5161 FreePool (ConfigRequest
);
5163 Status
= EFI_NOT_FOUND
;
5168 if (!EFI_ERROR (Status
)) {
5170 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
5172 if (!IfrDataParsedFlag
&& HiiHandle
!= NULL
&& DevicePath
!= NULL
) {
5173 StringPtr
= StrStr (AccessResults
, L
"&GUID=");
5174 if (StringPtr
!= NULL
) {
5177 if (GetElementsFromRequest (AccessResults
)) {
5178 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &AccessResults
, &DefaultResults
, NULL
);
5179 ASSERT_EFI_ERROR (Status
);
5181 if (StringPtr
!= NULL
) {
5186 // Merge the default sting from IFR code into the got setting from driver.
5188 if (DefaultResults
!= NULL
) {
5189 Status
= MergeDefaultString (&AccessResults
, DefaultResults
);
5190 ASSERT_EFI_ERROR (Status
);
5191 FreePool (DefaultResults
);
5192 DefaultResults
= NULL
;
5196 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'
5197 // which separates the first <ConfigAltResp> and the following ones.
5199 if (!FirstElement
) {
5200 Status
= AppendToMultiString (Results
, L
"&");
5201 ASSERT_EFI_ERROR (Status
);
5204 Status
= AppendToMultiString (Results
, AccessResults
);
5205 ASSERT_EFI_ERROR (Status
);
5207 FirstElement
= FALSE
;
5209 FreePool (AccessResults
);
5210 AccessResults
= NULL
;
5213 FreePool (ConfigAccessHandles
);
5220 This function processes the results of processing forms and routes it to the
5221 appropriate handlers or storage.
5223 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
5225 @param Configuration A null-terminated Unicode string in
5226 <MulltiConfigResp> format.
5227 @param Progress A pointer to a string filled in with the offset of
5228 the most recent & before the first failing name /
5229 value pair (or the beginning of the string if the
5230 failure is in the first name / value pair) or the
5231 terminating NULL if all was successful.
5233 @retval EFI_SUCCESS The results have been distributed or are awaiting
5235 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
5236 results that must be stored awaiting possible
5238 @retval EFI_INVALID_PARAMETER Passing in a NULL for the Configuration parameter
5239 would result in this type of error.
5240 @retval EFI_NOT_FOUND Target for the specified routing data was not
5246 HiiConfigRoutingRouteConfig (
5247 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
5248 IN CONST EFI_STRING Configuration
,
5249 OUT EFI_STRING
*Progress
5252 HII_DATABASE_PRIVATE_DATA
*Private
;
5253 EFI_STRING StringPtr
;
5254 EFI_STRING ConfigResp
;
5257 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
5258 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
5260 HII_DATABASE_RECORD
*Database
;
5261 UINT8
*DevicePathPkg
;
5262 UINT8
*CurrentDevicePath
;
5263 EFI_HANDLE DriverHandle
;
5264 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
5265 EFI_STRING AccessProgress
;
5266 EFI_IFR_VARSTORE_EFI
*EfiVarStoreInfo
;
5267 BOOLEAN IsEfiVarstore
;
5268 UINTN DevicePathSize
;
5270 if (This
== NULL
|| Progress
== NULL
) {
5271 return EFI_INVALID_PARAMETER
;
5274 if (Configuration
== NULL
) {
5276 return EFI_INVALID_PARAMETER
;
5279 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
5280 StringPtr
= Configuration
;
5281 *Progress
= StringPtr
;
5283 AccessProgress
= NULL
;
5284 EfiVarStoreInfo
= NULL
;
5285 IsEfiVarstore
= FALSE
;
5288 // The first element of <MultiConfigResp> should be
5289 // <GuidHdr>, which is in 'GUID='<Guid> syntax.
5291 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
5292 return EFI_INVALID_PARAMETER
;
5295 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) == 0) {
5297 // If parsing error, set Progress to the beginning of the <MultiConfigResp>
5298 // or most recent & before the error.
5300 if (StringPtr
== Configuration
) {
5301 *Progress
= StringPtr
;
5303 *Progress
= StringPtr
- 1;
5307 // Process each <ConfigResp> of <MultiConfigResp>
5309 Length
= CalculateConfigStringLen (StringPtr
);
5310 ConfigResp
= AllocateCopyPool ((Length
+ 1) * sizeof (CHAR16
), StringPtr
);
5311 if (ConfigResp
== NULL
) {
5312 return EFI_OUT_OF_RESOURCES
;
5315 // Append '\0' to the end of ConfigRequest
5317 *(ConfigResp
+ Length
) = 0;
5320 // Get the UEFI device path
5322 Status
= GetDevicePath (ConfigResp
, (UINT8
**) &DevicePath
);
5323 if (EFI_ERROR (Status
)) {
5324 FreePool (ConfigResp
);
5329 // Find driver which matches the routing data.
5331 DriverHandle
= NULL
;
5332 for (Link
= Private
->DatabaseList
.ForwardLink
;
5333 Link
!= &Private
->DatabaseList
;
5334 Link
= Link
->ForwardLink
5336 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
5338 if ((DevicePathPkg
= Database
->PackageList
->DevicePathPkg
) != NULL
) {
5339 CurrentDevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
5340 DevicePathSize
= GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) CurrentDevicePath
);
5341 if ((CompareMem (DevicePath
,CurrentDevicePath
,DevicePathSize
) == 0) && IsThisPackageList(Database
, ConfigResp
)) {
5342 DriverHandle
= Database
->DriverHandle
;
5349 // Try to find driver handle by device path.
5351 if (DriverHandle
== NULL
) {
5352 TempDevicePath
= DevicePath
;
5353 Status
= gBS
->LocateDevicePath (
5354 &gEfiDevicePathProtocolGuid
,
5358 if (EFI_ERROR (Status
) || (DriverHandle
== NULL
)) {
5360 // Routing data does not match any known driver.
5361 // Set Progress to the 'G' in "GUID" of the routing header.
5363 FreePool (DevicePath
);
5364 *Progress
= StringPtr
;
5365 FreePool (ConfigResp
);
5366 return EFI_NOT_FOUND
;
5370 FreePool (DevicePath
);
5373 // Check whether this ConfigRequest is search from Efi varstore type storage.
5375 Status
= GetVarStoreType(Database
, ConfigResp
, &IsEfiVarstore
, &EfiVarStoreInfo
);
5376 if (EFI_ERROR (Status
)) {
5380 if (IsEfiVarstore
) {
5382 // Call the SetVariable function to route settings.
5384 Status
= RouteConfigRespForEfiVarStore(This
, EfiVarStoreInfo
, ConfigResp
, &AccessProgress
);
5385 FreePool (EfiVarStoreInfo
);
5388 // Call corresponding ConfigAccess protocol to route settings
5390 Status
= gBS
->HandleProtocol (
5392 &gEfiHiiConfigAccessProtocolGuid
,
5393 (VOID
**) &ConfigAccess
5395 if (EFI_ERROR (Status
)) {
5396 *Progress
= StringPtr
;
5397 FreePool (ConfigResp
);
5398 return EFI_NOT_FOUND
;
5401 Status
= ConfigAccess
->RouteConfig (
5407 if (EFI_ERROR (Status
)) {
5408 ASSERT (AccessProgress
!= NULL
);
5410 // AccessProgress indicates the parsing progress on <ConfigResp>.
5411 // Map it to the progress on <MultiConfigResp> then return it.
5413 *Progress
= StrStr (StringPtr
, AccessProgress
);
5415 FreePool (ConfigResp
);
5419 FreePool (ConfigResp
);
5423 // Go to next <ConfigResp> (skip '&').
5425 StringPtr
+= Length
;
5426 if (*StringPtr
== 0) {
5427 *Progress
= StringPtr
;
5440 This helper function is to be called by drivers to map configuration data
5441 stored in byte array ("block") formats such as UEFI Variables into current
5442 configuration strings.
5444 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
5446 @param ConfigRequest A null-terminated Unicode string in
5447 <ConfigRequest> format.
5448 @param Block Array of bytes defining the block's configuration.
5449 @param BlockSize Length in bytes of Block.
5450 @param Config Filled-in configuration string. String allocated
5451 by the function. Returned only if call is
5452 successful. It is <ConfigResp> string format.
5453 @param Progress A pointer to a string filled in with the offset of
5454 the most recent & before the first failing
5455 name/value pair (or the beginning of the string if
5456 the failure is in the first name / value pair) or
5457 the terminating NULL if all was successful.
5459 @retval EFI_SUCCESS The request succeeded. Progress points to the null
5460 terminator at the end of the ConfigRequest
5462 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress
5463 points to the first character of ConfigRequest.
5464 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigRequest or
5465 Block parameter would result in this type of
5466 error. Progress points to the first character of
5468 @retval EFI_DEVICE_ERROR Block not large enough. Progress undefined.
5469 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted string.
5470 Block is left updated and Progress points at
5471 the "&" preceding the first non-<BlockName>.
5477 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
5478 IN CONST EFI_STRING ConfigRequest
,
5479 IN CONST UINT8
*Block
,
5480 IN CONST UINTN BlockSize
,
5481 OUT EFI_STRING
*Config
,
5482 OUT EFI_STRING
*Progress
5485 HII_DATABASE_PRIVATE_DATA
*Private
;
5486 EFI_STRING StringPtr
;
5494 EFI_STRING ValueStr
;
5495 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 TemChar
= *StringPtr
;
5568 AppendToMultiString(Config
, ConfigRequest
);
5569 *StringPtr
= TemChar
;
5572 // Parse each <RequestElement> if exists
5573 // Only <BlockName> format is supported by this help function.
5574 // <BlockName> ::= 'OFFSET='<Number>&'WIDTH='<Number>
5576 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"OFFSET=", StrLen (L
"OFFSET=")) == 0) {
5578 // Back up the header of one <BlockName>
5582 StringPtr
+= StrLen (L
"OFFSET=");
5586 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
5587 if (EFI_ERROR (Status
)) {
5588 *Progress
= TmpPtr
- 1;
5595 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
5597 FreePool (TmpBuffer
);
5599 StringPtr
+= Length
;
5600 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
5601 *Progress
= TmpPtr
- 1;
5602 Status
= EFI_INVALID_PARAMETER
;
5605 StringPtr
+= StrLen (L
"&WIDTH=");
5610 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
5611 if (EFI_ERROR (Status
)) {
5612 *Progress
= TmpPtr
- 1;
5619 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
5621 FreePool (TmpBuffer
);
5623 StringPtr
+= Length
;
5624 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
5625 *Progress
= TmpPtr
- 1;
5626 Status
= EFI_INVALID_PARAMETER
;
5631 // Calculate Value and convert it to hex string.
5633 if (Offset
+ Width
> BlockSize
) {
5634 *Progress
= StringPtr
;
5635 Status
= EFI_DEVICE_ERROR
;
5639 Value
= (UINT8
*) AllocateZeroPool (Width
);
5640 if (Value
== NULL
) {
5641 *Progress
= ConfigRequest
;
5642 Status
= EFI_OUT_OF_RESOURCES
;
5646 CopyMem (Value
, (UINT8
*) Block
+ Offset
, Width
);
5648 Length
= Width
* 2 + 1;
5649 ValueStr
= (EFI_STRING
) AllocateZeroPool (Length
* sizeof (CHAR16
));
5650 if (ValueStr
== NULL
) {
5651 *Progress
= ConfigRequest
;
5652 Status
= EFI_OUT_OF_RESOURCES
;
5656 TemString
= ValueStr
;
5657 TemBuffer
= Value
+ Width
- 1;
5658 for (Index
= 0; Index
< Width
; Index
++, TemBuffer
--) {
5659 UnicodeValueToStringS (
5661 Length
* sizeof (CHAR16
) - ((UINTN
)TemString
- (UINTN
)ValueStr
),
5662 PREFIX_ZERO
| RADIX_HEX
,
5666 TemString
+= StrnLenS (TemString
, Length
- ((UINTN
)TemString
- (UINTN
)ValueStr
) / sizeof (CHAR16
));
5673 // Build a ConfigElement
5675 Length
+= StringPtr
- TmpPtr
+ 1 + StrLen (L
"VALUE=");
5676 ConfigElement
= (EFI_STRING
) AllocateZeroPool (Length
* sizeof (CHAR16
));
5677 if (ConfigElement
== NULL
) {
5678 Status
= EFI_OUT_OF_RESOURCES
;
5681 CopyMem (ConfigElement
, TmpPtr
, (StringPtr
- TmpPtr
+ 1) * sizeof (CHAR16
));
5682 if (*StringPtr
== 0) {
5683 *(ConfigElement
+ (StringPtr
- TmpPtr
)) = L
'&';
5685 *(ConfigElement
+ (StringPtr
- TmpPtr
) + 1) = 0;
5686 StrCatS (ConfigElement
, Length
, L
"VALUE=");
5687 StrCatS (ConfigElement
, Length
, ValueStr
);
5689 AppendToMultiString (Config
, ConfigElement
);
5691 FreePool (ConfigElement
);
5692 FreePool (ValueStr
);
5693 ConfigElement
= NULL
;
5697 // If '\0', parsing is finished. Otherwise skip '&' to continue
5699 if (*StringPtr
== 0) {
5702 AppendToMultiString (Config
, L
"&");
5707 if (*StringPtr
!= 0) {
5708 *Progress
= StringPtr
- 1;
5709 Status
= EFI_INVALID_PARAMETER
;
5713 HiiToLower (*Config
);
5714 *Progress
= StringPtr
;
5718 if (*Config
!= NULL
) {
5722 if (ValueStr
!= NULL
) {
5723 FreePool (ValueStr
);
5725 if (Value
!= NULL
) {
5728 if (ConfigElement
!= NULL
) {
5729 FreePool (ConfigElement
);
5738 This helper function is to be called by drivers to map configuration strings
5739 to configurations stored in byte array ("block") formats such as UEFI Variables.
5741 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
5743 @param ConfigResp A null-terminated Unicode string in <ConfigResp>
5745 @param Block A possibly null array of bytes representing the
5746 current block. Only bytes referenced in the
5747 ConfigResp string in the block are modified. If
5748 this parameter is null or if the *BlockSize
5749 parameter is (on input) shorter than required by
5750 the Configuration string, only the BlockSize
5751 parameter is updated and an appropriate status
5752 (see below) is returned.
5753 @param BlockSize The length of the Block in units of UINT8. On
5754 input, this is the size of the Block. On output,
5755 if successful, contains the largest index of the
5756 modified byte in the Block, or the required buffer
5757 size if the Block is not large enough.
5758 @param Progress On return, points to an element of the ConfigResp
5759 string filled in with the offset of the most
5760 recent '&' before the first failing name / value
5761 pair (or the beginning of the string if the
5762 failure is in the first name / value pair) or the
5763 terminating NULL if all was successful.
5765 @retval EFI_SUCCESS The request succeeded. Progress points to the null
5766 terminator at the end of the ConfigResp string.
5767 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress
5768 points to the first character of ConfigResp.
5769 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigResp or
5770 Block parameter would result in this type of
5771 error. Progress points to the first character of
5773 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted name /
5774 value pair. Block is left updated and
5775 Progress points at the '&' preceding the first
5777 @retval EFI_BUFFER_TOO_SMALL Block not large enough. Progress undefined.
5778 BlockSize is updated with the required buffer size.
5779 @retval EFI_NOT_FOUND Target for the specified routing data was not found.
5780 Progress points to the "G" in "GUID" of the errant
5787 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
5788 IN CONST EFI_STRING ConfigResp
,
5789 IN OUT UINT8
*Block
,
5790 IN OUT UINTN
*BlockSize
,
5791 OUT EFI_STRING
*Progress
5794 HII_DATABASE_PRIVATE_DATA
*Private
;
5795 EFI_STRING StringPtr
;
5808 if (This
== NULL
|| BlockSize
== NULL
|| Progress
== NULL
) {
5809 return EFI_INVALID_PARAMETER
;
5812 *Progress
= ConfigResp
;
5813 if (ConfigResp
== NULL
) {
5814 return EFI_INVALID_PARAMETER
;
5817 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
5818 ASSERT (Private
!= NULL
);
5820 StringPtr
= ConfigResp
;
5821 BufferSize
= *BlockSize
;
5828 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
5829 *Progress
= StringPtr
;
5830 Status
= EFI_INVALID_PARAMETER
;
5833 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"PATH=", StrLen (L
"PATH=")) != 0) {
5836 if (*StringPtr
== 0) {
5837 *Progress
= StringPtr
;
5838 Status
= EFI_INVALID_PARAMETER
;
5842 while (*StringPtr
!= L
'&' && *StringPtr
!= 0) {
5845 if (*StringPtr
== 0) {
5846 *Progress
= StringPtr
;
5847 Status
= EFI_INVALID_PARAMETER
;
5852 // Parse each <ConfigElement> if exists
5853 // Only '&'<BlockConfig> format is supported by this help function.
5854 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE='<Number>
5856 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) == 0) {
5858 StringPtr
+= StrLen (L
"&OFFSET=");
5862 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
5863 if (EFI_ERROR (Status
)) {
5871 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
5873 FreePool (TmpBuffer
);
5875 StringPtr
+= Length
;
5876 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
5878 Status
= EFI_INVALID_PARAMETER
;
5881 StringPtr
+= StrLen (L
"&WIDTH=");
5886 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
5887 if (EFI_ERROR (Status
)) {
5895 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
5897 FreePool (TmpBuffer
);
5899 StringPtr
+= Length
;
5900 if (StrnCmp (StringPtr
, L
"&VALUE=", StrLen (L
"&VALUE=")) != 0) {
5902 Status
= EFI_INVALID_PARAMETER
;
5905 StringPtr
+= StrLen (L
"&VALUE=");
5910 Status
= GetValueOfNumber (StringPtr
, &Value
, &Length
);
5911 if (EFI_ERROR (Status
)) {
5916 StringPtr
+= Length
;
5917 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
5919 Status
= EFI_INVALID_PARAMETER
;
5924 // Update the Block with configuration info
5926 if ((Block
!= NULL
) && (Offset
+ Width
<= BufferSize
)) {
5927 CopyMem (Block
+ Offset
, Value
, Width
);
5929 if (Offset
+ Width
> MaxBlockSize
) {
5930 MaxBlockSize
= Offset
+ Width
;
5937 // If '\0', parsing is finished.
5939 if (*StringPtr
== 0) {
5945 // The input string is not ConfigResp format, return error.
5947 if (*StringPtr
!= 0) {
5948 *Progress
= StringPtr
;
5949 Status
= EFI_INVALID_PARAMETER
;
5953 *Progress
= StringPtr
+ StrLen (StringPtr
);
5954 *BlockSize
= MaxBlockSize
- 1;
5956 if (MaxBlockSize
> BufferSize
) {
5957 *BlockSize
= MaxBlockSize
;
5958 if (Block
!= NULL
) {
5959 return EFI_BUFFER_TOO_SMALL
;
5963 if (Block
== NULL
) {
5964 *Progress
= ConfigResp
;
5965 return EFI_INVALID_PARAMETER
;
5972 if (Value
!= NULL
) {
5980 This helper function is to be called by drivers to extract portions of
5981 a larger configuration string.
5983 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
5985 @param Configuration A null-terminated Unicode string in
5986 <MultiConfigAltResp> format.
5987 @param Guid A pointer to the GUID value to search for in the
5988 routing portion of the ConfigResp string when
5989 retrieving the requested data. If Guid is NULL,
5990 then all GUID values will be searched for.
5991 @param Name A pointer to the NAME value to search for in the
5992 routing portion of the ConfigResp string when
5993 retrieving the requested data. If Name is NULL,
5994 then all Name values will be searched for.
5995 @param DevicePath A pointer to the PATH value to search for in the
5996 routing portion of the ConfigResp string when
5997 retrieving the requested data. If DevicePath is
5998 NULL, then all DevicePath values will be searched
6000 @param AltCfgId A pointer to the ALTCFG value to search for in the
6001 routing portion of the ConfigResp string when
6002 retrieving the requested data. If this parameter
6003 is NULL, then the current setting will be
6005 @param AltCfgResp A pointer to a buffer which will be allocated by
6006 the function which contains the retrieved string
6007 as requested. This buffer is only allocated if
6008 the call was successful. It is <ConfigResp> format.
6010 @retval EFI_SUCCESS The request succeeded. The requested data was
6011 extracted and placed in the newly allocated
6013 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate AltCfgResp.
6014 @retval EFI_INVALID_PARAMETER Any parameter is invalid.
6015 @retval EFI_NOT_FOUND Target for the specified routing data was not
6022 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
6023 IN CONST EFI_STRING Configuration
,
6024 IN CONST EFI_GUID
*Guid
,
6025 IN CONST EFI_STRING Name
,
6026 IN CONST EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
6027 IN CONST UINT16
*AltCfgId
,
6028 OUT EFI_STRING
*AltCfgResp
6032 EFI_STRING StringPtr
;
6033 EFI_STRING HdrStart
;
6040 EFI_STRING AltIdStr
;
6057 if (This
== NULL
|| Configuration
== NULL
|| AltCfgResp
== NULL
) {
6058 return EFI_INVALID_PARAMETER
;
6061 StringPtr
= Configuration
;
6062 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
6063 return EFI_INVALID_PARAMETER
;
6067 // Generate the sub string for later matching.
6069 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*) Guid
, 1, &GuidStr
);
6072 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) DevicePath
),
6073 (VOID
*) DevicePath
,
6077 if (AltCfgId
!= NULL
) {
6078 GenerateSubStr (L
"ALTCFG=", sizeof (UINT16
), (VOID
*) AltCfgId
, 3, &AltIdStr
);
6081 GenerateSubStr (L
"NAME=", StrLen (Name
) * sizeof (CHAR16
), (VOID
*) Name
, 2, &NameStr
);
6083 GenerateSubStr (L
"NAME=", 0, NULL
, 2, &NameStr
);
6086 while (*StringPtr
!= 0) {
6088 // Try to match the GUID
6091 TmpPtr
= StrStr (StringPtr
, GuidStr
);
6092 if (TmpPtr
== NULL
) {
6093 Status
= EFI_NOT_FOUND
;
6099 // Jump to <NameHdr>
6102 StringPtr
= TmpPtr
+ StrLen (GuidStr
);
6104 StringPtr
= StrStr (TmpPtr
, L
"NAME=");
6105 if (StringPtr
== NULL
) {
6106 Status
= EFI_NOT_FOUND
;
6114 // Try to match the NAME
6116 if (GuidFlag
&& !NameFlag
) {
6117 if (StrnCmp (StringPtr
, NameStr
, StrLen (NameStr
)) != 0) {
6121 // Jump to <PathHdr>
6124 StringPtr
+= StrLen (NameStr
);
6126 StringPtr
= StrStr (StringPtr
, L
"PATH=");
6127 if (StringPtr
== NULL
) {
6128 Status
= EFI_NOT_FOUND
;
6137 // Try to match the DevicePath
6139 if (GuidFlag
&& NameFlag
&& !PathFlag
) {
6140 if (StrnCmp (StringPtr
, PathStr
, StrLen (PathStr
)) != 0) {
6145 // Jump to '&' before <DescHdr> or <ConfigBody>
6147 if (DevicePath
!= NULL
) {
6148 StringPtr
+= StrLen (PathStr
);
6150 StringPtr
= StrStr (StringPtr
, L
"&");
6151 if (StringPtr
== NULL
) {
6152 Status
= EFI_NOT_FOUND
;
6163 // Try to match the AltCfgId
6165 if (GuidFlag
&& NameFlag
&& PathFlag
) {
6166 if (AltCfgId
== NULL
) {
6168 // Return Current Setting when AltCfgId is NULL.
6170 Status
= OutputConfigBody (StringPtr
, &Result
);
6174 // Search the <ConfigAltResp> to get the <AltResp> with AltCfgId.
6176 if (StrnCmp (StringPtr
, AltIdStr
, StrLen (AltIdStr
)) != 0) {
6182 // Skip AltIdStr and &
6184 StringPtr
= StringPtr
+ StrLen (AltIdStr
);
6185 Status
= OutputConfigBody (StringPtr
, &Result
);
6191 Status
= EFI_NOT_FOUND
;
6195 if (!EFI_ERROR (Status
) && (Result
!= NULL
)) {
6197 // Copy the <ConfigHdr> and <ConfigBody>
6199 Length
= HdrEnd
- HdrStart
+ StrLen (Result
) + 1;
6200 *AltCfgResp
= AllocateZeroPool (Length
* sizeof (CHAR16
));
6201 if (*AltCfgResp
== NULL
) {
6202 Status
= EFI_OUT_OF_RESOURCES
;
6204 StrnCpyS (*AltCfgResp
, Length
, HdrStart
, HdrEnd
- HdrStart
);
6205 StrCatS (*AltCfgResp
, Length
, Result
);
6206 Status
= EFI_SUCCESS
;
6210 if (GuidStr
!= NULL
) {
6213 if (NameStr
!= NULL
) {
6216 if (PathStr
!= NULL
) {
6219 if (AltIdStr
!= NULL
) {
6220 FreePool (AltIdStr
);
6222 if (Result
!= NULL
) {