2 Implementation of interfaces function for EFI_HII_CONFIG_ROUTING_PROTOCOL.
4 Copyright (c) 2007 - 2017, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 #include "HiiDatabase.h"
17 extern HII_DATABASE_PRIVATE_DATA mPrivate
;
20 Calculate the number of Unicode characters of the incoming Configuration string,
21 not including NULL terminator.
23 This is a internal function.
25 @param String String in <MultiConfigRequest> or
26 <MultiConfigResp> format.
28 @return The number of Unicode characters.
32 CalculateConfigStringLen (
39 // "GUID=" should be the first element of incoming string.
41 ASSERT (String
!= NULL
);
42 ASSERT (StrnCmp (String
, L
"GUID=", StrLen (L
"GUID=")) == 0);
45 // The beginning of next <ConfigRequest>/<ConfigResp> should be "&GUID=".
46 // Will meet '\0' if there is only one <ConfigRequest>/<ConfigResp>.
48 TmpPtr
= StrStr (String
, L
"&GUID=");
50 return StrLen (String
);
53 return (TmpPtr
- String
);
58 Convert the hex UNICODE %02x encoding of a UEFI device path to binary
59 from <PathHdr> of <ConfigHdr>.
61 This is a internal function.
63 @param String UEFI configuration string
64 @param DevicePathData Binary of a UEFI device path.
66 @retval EFI_NOT_FOUND The device path is not invalid.
67 @retval EFI_INVALID_PARAMETER Any incoming parameter is invalid.
68 @retval EFI_OUT_OF_RESOURCES Lake of resources to store necessary structures.
69 @retval EFI_SUCCESS The device path is retrieved and translated to
76 OUT UINT8
**DevicePathData
81 UINT8
*DevicePathBuffer
;
85 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
88 if (String
== NULL
|| DevicePathData
== NULL
) {
89 return EFI_INVALID_PARAMETER
;
93 // Find the 'PATH=' of <PathHdr> and skip it.
95 for (; (*String
!= 0 && StrnCmp (String
, L
"PATH=", StrLen (L
"PATH=")) != 0); String
++);
97 return EFI_INVALID_PARAMETER
;
100 // Check whether path data does exist.
102 String
+= StrLen (L
"PATH=");
104 return EFI_INVALID_PARAMETER
;
109 // The content between 'PATH=' of <ConfigHdr> and '&' of next element
110 // or '\0' (end of configuration string) is the UNICODE %02x bytes encoding
111 // of UEFI device path.
113 for (Length
= 0; *String
!= 0 && *String
!= L
'&'; String
++, Length
++);
115 // Check DevicePath Length
117 if (((Length
+ 1) / 2) < sizeof (EFI_DEVICE_PATH_PROTOCOL
)) {
118 return EFI_NOT_FOUND
;
122 // The data in <PathHdr> is encoded as hex UNICODE %02x bytes in the same order
123 // as the device path resides in RAM memory.
124 // Translate the data into binary.
126 DevicePathBuffer
= (UINT8
*) AllocateZeroPool ((Length
+ 1) / 2);
127 if (DevicePathBuffer
== NULL
) {
128 return EFI_OUT_OF_RESOURCES
;
132 // Convert DevicePath
134 ZeroMem (TemStr
, sizeof (TemStr
));
135 for (Index
= 0; Index
< Length
; Index
++) {
136 TemStr
[0] = PathHdr
[Index
];
137 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
138 if ((Index
& 1) == 0) {
139 DevicePathBuffer
[Index
/2] = DigitUint8
;
141 DevicePathBuffer
[Index
/2] = (UINT8
) ((DevicePathBuffer
[Index
/2] << 4) + DigitUint8
);
146 // Validate DevicePath
148 DevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) DevicePathBuffer
;
149 while (!IsDevicePathEnd (DevicePath
)) {
150 if ((DevicePath
->Type
== 0) || (DevicePath
->SubType
== 0) || (DevicePathNodeLength (DevicePath
) < sizeof (EFI_DEVICE_PATH_PROTOCOL
))) {
152 // Invalid device path
154 FreePool (DevicePathBuffer
);
155 return EFI_NOT_FOUND
;
157 DevicePath
= NextDevicePathNode (DevicePath
);
161 // return the device path
163 *DevicePathData
= DevicePathBuffer
;
168 Converts the unicode character of the string from uppercase to lowercase.
169 This is a internal function.
171 @param ConfigString String to be converted
177 IN EFI_STRING ConfigString
183 ASSERT (ConfigString
!= NULL
);
186 // Convert all hex digits in range [A-F] in the configuration header to [a-f]
188 for (String
= ConfigString
, Lower
= FALSE
; *String
!= L
'\0'; String
++) {
189 if (*String
== L
'=') {
191 } else if (*String
== L
'&') {
193 } else if (Lower
&& *String
>= L
'A' && *String
<= L
'F') {
194 *String
= (CHAR16
) (*String
- L
'A' + L
'a');
202 Generate a sub string then output it.
204 This is a internal function.
206 @param String A constant string which is the prefix of the to be
207 generated string, e.g. GUID=
209 @param BufferLen The length of the Buffer in bytes.
211 @param Buffer Points to a buffer which will be converted to be the
212 content of the generated string.
214 @param Flag If 1, the buffer contains data for the value of GUID or PATH stored in
215 UINT8 *; if 2, the buffer contains unicode string for the value of NAME;
216 if 3, the buffer contains other data.
218 @param SubStr Points to the output string. It's caller's
219 responsibility to free this buffer.
225 IN CONST EFI_STRING String
,
229 OUT EFI_STRING
*SubStr
234 EFI_STRING StringHeader
;
240 ASSERT (String
!= NULL
&& SubStr
!= NULL
);
242 if (Buffer
== NULL
) {
243 *SubStr
= AllocateCopyPool (StrSize (String
), String
);
244 ASSERT (*SubStr
!= NULL
);
249 // Header + Data + '&' + '\0'
251 Length
= StrLen (String
) + BufferLen
* 2 + 1 + 1;
252 Str
= AllocateZeroPool (Length
* sizeof (CHAR16
));
253 ASSERT (Str
!= NULL
);
255 StrCpyS (Str
, Length
, String
);
257 StringHeader
= Str
+ StrLen (String
);
258 TemString
= (CHAR16
*) StringHeader
;
263 // Convert Buffer to Hex String in reverse order
265 TemBuffer
= ((UINT8
*) Buffer
);
266 for (Index
= 0; Index
< BufferLen
; Index
++, TemBuffer
++) {
267 UnicodeValueToStringS (
269 sizeof (CHAR16
) * (Length
- StrnLenS (Str
, Length
)),
270 PREFIX_ZERO
| RADIX_HEX
,
274 TemString
+= StrnLenS (TemString
, Length
- StrnLenS (Str
, Length
));
279 // Check buffer is enough
281 TemName
= (CHAR16
*) Buffer
;
282 ASSERT ((BufferLen
* 2 + 1) >= (StrLen (TemName
) * 4 + 1));
284 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
286 for (; *TemName
!= L
'\0'; TemName
++) {
287 UnicodeValueToStringS (
289 sizeof (CHAR16
) * (Length
- StrnLenS (Str
, Length
)),
290 PREFIX_ZERO
| RADIX_HEX
,
294 TemString
+= StrnLenS (TemString
, Length
- StrnLenS (Str
, Length
));
299 // Convert Buffer to Hex String
301 TemBuffer
= ((UINT8
*) Buffer
) + BufferLen
- 1;
302 for (Index
= 0; Index
< BufferLen
; Index
++, TemBuffer
--) {
303 UnicodeValueToStringS (
305 sizeof (CHAR16
) * (Length
- StrnLenS (Str
, Length
)),
306 PREFIX_ZERO
| RADIX_HEX
,
310 TemString
+= StrnLenS (TemString
, Length
- StrnLenS (Str
, Length
));
318 // Convert the uppercase to lowercase since <HexAf> is defined in lowercase format.
320 StrCatS (Str
, Length
, L
"&");
328 Retrieve the <ConfigBody> from String then output it.
330 This is a internal function.
332 @param String A sub string of a configuration string in
333 <MultiConfigAltResp> format.
334 @param ConfigBody Points to the output string. It's caller's
335 responsibility to free this buffer.
337 @retval EFI_INVALID_PARAMETER There is no form package in current hii database.
338 @retval EFI_OUT_OF_RESOURCES Not enough memory to finish this operation.
339 @retval EFI_SUCCESS All existing storage is exported.
344 IN EFI_STRING String
,
345 OUT EFI_STRING
*ConfigBody
352 if (String
== NULL
|| ConfigBody
== NULL
) {
353 return EFI_INVALID_PARAMETER
;
357 // The setting information should start OFFSET, not ALTCFG.
359 if (StrnCmp (String
, L
"&ALTCFG=", StrLen (L
"&ALTCFG=")) == 0) {
360 return EFI_INVALID_PARAMETER
;
363 TmpPtr
= StrStr (String
, L
"GUID=");
364 if (TmpPtr
== NULL
) {
366 // It is the last <ConfigResp> of the incoming configuration string.
368 Result
= AllocateCopyPool (StrSize (String
), String
);
369 if (Result
== NULL
) {
370 return EFI_OUT_OF_RESOURCES
;
372 *ConfigBody
= Result
;
377 Length
= TmpPtr
- String
;
379 return EFI_NOT_FOUND
;
381 Result
= AllocateCopyPool (Length
* sizeof (CHAR16
), String
);
382 if (Result
== NULL
) {
383 return EFI_OUT_OF_RESOURCES
;
386 *(Result
+ Length
- 1) = 0;
387 *ConfigBody
= Result
;
392 Append a string to a multi-string format.
394 This is a internal function.
396 @param MultiString String in <MultiConfigRequest>,
397 <MultiConfigAltResp>, or <MultiConfigResp>. On
398 input, the buffer length of this string is
399 MAX_STRING_LENGTH. On output, the buffer length
401 @param AppendString NULL-terminated Unicode string.
403 @retval EFI_INVALID_PARAMETER Any incoming parameter is invalid.
404 @retval EFI_SUCCESS AppendString is append to the end of MultiString
408 AppendToMultiString (
409 IN OUT EFI_STRING
*MultiString
,
410 IN EFI_STRING AppendString
413 UINTN AppendStringSize
;
414 UINTN MultiStringSize
;
417 if (MultiString
== NULL
|| *MultiString
== NULL
|| AppendString
== NULL
) {
418 return EFI_INVALID_PARAMETER
;
421 AppendStringSize
= StrSize (AppendString
);
422 MultiStringSize
= StrSize (*MultiString
);
423 MaxLen
= MAX_STRING_LENGTH
/ sizeof (CHAR16
);
426 // Enlarge the buffer each time when length exceeds MAX_STRING_LENGTH.
428 if (MultiStringSize
+ AppendStringSize
> MAX_STRING_LENGTH
||
429 MultiStringSize
> MAX_STRING_LENGTH
) {
430 *MultiString
= (EFI_STRING
) ReallocatePool (
432 MultiStringSize
+ AppendStringSize
,
433 (VOID
*) (*MultiString
)
435 MaxLen
= (MultiStringSize
+ AppendStringSize
) / sizeof (CHAR16
);
436 ASSERT (*MultiString
!= NULL
);
439 // Append the incoming string
441 StrCatS (*MultiString
, MaxLen
, AppendString
);
448 Get the value of <Number> in <BlockConfig> format, i.e. the value of OFFSET
450 <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>
452 This is a internal function.
454 @param StringPtr String in <BlockConfig> format and points to the
455 first character of <Number>.
456 @param Number The output value. Caller takes the responsibility
458 @param Len Length of the <Number>, in characters.
460 @retval EFI_OUT_OF_RESOURCES Insufficient resources to store necessary
462 @retval EFI_SUCCESS Value of <Number> is outputted in Number
468 IN EFI_STRING StringPtr
,
482 if (StringPtr
== NULL
|| *StringPtr
== L
'\0' || Number
== NULL
|| Len
== NULL
) {
483 return EFI_INVALID_PARAMETER
;
489 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
492 *Len
= StringPtr
- TmpPtr
;
495 Str
= (EFI_STRING
) AllocateZeroPool (Length
* sizeof (CHAR16
));
497 Status
= EFI_OUT_OF_RESOURCES
;
500 CopyMem (Str
, TmpPtr
, *Len
* sizeof (CHAR16
));
501 *(Str
+ *Len
) = L
'\0';
503 Length
= (Length
+ 1) / 2;
504 Buf
= (UINT8
*) AllocateZeroPool (Length
);
506 Status
= EFI_OUT_OF_RESOURCES
;
511 ZeroMem (TemStr
, sizeof (TemStr
));
512 for (Index
= 0; Index
< Length
; Index
++) {
513 TemStr
[0] = Str
[Length
- Index
- 1];
514 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
515 if ((Index
& 1) == 0) {
516 Buf
[Index
/2] = DigitUint8
;
518 Buf
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Buf
[Index
/2]);
523 Status
= EFI_SUCCESS
;
534 To find the BlockName in the string with same value.
536 @param String Pointer to a Null-terminated Unicode string.
537 @param BlockName Pointer to a Null-terminated Unicode string to search for.
538 @param Buffer Pointer to the value correspond to the BlockName.
539 @param Found The Block whether has been found.
540 @param BufferLen The length of the buffer.
542 @retval EFI_OUT_OF_RESOURCES Insufficient resources to store necessary structures.
543 @retval EFI_SUCCESS The function finishes successfully.
547 FindSameBlockElement(
548 IN EFI_STRING String
,
549 IN EFI_STRING BlockName
,
562 BlockPtr
= StrStr (String
, BlockName
);
564 while (BlockPtr
!= NULL
) {
565 BlockPtr
+= StrLen (BlockName
);
566 Status
= GetValueOfNumber (BlockPtr
, &TempBuffer
, &Length
);
567 if (EFI_ERROR (Status
)) {
570 ASSERT (TempBuffer
!= NULL
);
571 if ((BufferLen
== Length
) && (0 == CompareMem (Buffer
, TempBuffer
, Length
))) {
573 FreePool (TempBuffer
);
577 FreePool (TempBuffer
);
579 BlockPtr
= StrStr (BlockPtr
+ 1, BlockName
);
586 Compare the <AltResp> in ConfigAltResp and DefaultAltCfgResp, if the <AltResp>
587 in DefaultAltCfgResp but not in ConfigAltResp,add it to the ConfigAltResp.
589 @param DefaultAltCfgResp Pointer to a null-terminated Unicode string in
590 <MultiConfigAltResp> format. The default value
591 string may contain more than one ConfigAltResp
592 string for the different varstore buffer.
593 @param ConfigAltResp Pointer to a null-terminated Unicode string in
594 <ConfigAltResp> format.
595 @param AltConfigHdr Pointer to a Unicode string in <AltConfigHdr> format.
596 @param ConfigAltRespChanged Whether the ConfigAltResp has been changed.
598 @retval EFI_OUT_OF_RESOURCES Insufficient resources to store necessary structures.
599 @retval EFI_SUCCESS The function finishes successfully.
603 CompareBlockElementDefault (
604 IN EFI_STRING DefaultAltCfgResp
,
605 IN OUT EFI_STRING
*ConfigAltResp
,
606 IN EFI_STRING AltConfigHdr
,
607 IN OUT BOOLEAN
*ConfigAltRespChanged
612 EFI_STRING BlockPtrStart
;
613 EFI_STRING StringPtr
;
614 EFI_STRING AppendString
;
615 EFI_STRING AltConfigHdrPtr
;
625 // Make BlockPtr point to the first <BlockConfig> with AltConfigHdr in DefaultAltCfgResp.
627 AltConfigHdrPtr
= StrStr (DefaultAltCfgResp
, AltConfigHdr
);
628 ASSERT (AltConfigHdrPtr
!= NULL
);
629 BlockPtr
= StrStr (AltConfigHdrPtr
, L
"&OFFSET=");
631 // Make StringPtr point to the AltConfigHdr in ConfigAltResp.
633 StringPtr
= StrStr (*ConfigAltResp
, AltConfigHdr
);
634 ASSERT (StringPtr
!= NULL
);
636 while (BlockPtr
!= NULL
) {
638 // Find the "&OFFSET=<Number>" block and get the value of the Number with AltConfigHdr in DefaultAltCfgResp.
640 BlockPtrStart
= BlockPtr
;
641 BlockPtr
+= StrLen (L
"&OFFSET=");
642 Status
= GetValueOfNumber (BlockPtr
, &TempBuffer
, &OffsetLength
);
643 if (EFI_ERROR (Status
)) {
644 Status
= EFI_OUT_OF_RESOURCES
;
648 // To find the same "&OFFSET=<Number>" block in ConfigAltResp.
650 Status
= FindSameBlockElement (StringPtr
, L
"&OFFSET=", TempBuffer
, &FoundOffset
, OffsetLength
);
651 if (TempBuffer
!= NULL
) {
652 FreePool (TempBuffer
);
655 if (EFI_ERROR (Status
)) {
656 Status
= EFI_OUT_OF_RESOURCES
;
661 // Don't find the same "&OFFSET=<Number>" block in ConfigAltResp.
662 // Calculate the size of <BlockConfig>.
663 // <BlockConfig>::='OFFSET='<Number>'&WIDTH='<Number>'&VALUE='<Number>.
665 BlockPtr
= StrStr (BlockPtr
+ 1, L
"&OFFSET=");
666 if (BlockPtr
!= NULL
) {
667 AppendSize
= (BlockPtr
- BlockPtrStart
) * sizeof (CHAR16
);
669 AppendSize
= StrSize (BlockPtrStart
);
672 // Copy the <BlockConfig> to AppendString.
674 if (AppendString
== NULL
) {
675 AppendString
= (EFI_STRING
) AllocateZeroPool (AppendSize
+ sizeof (CHAR16
));
676 StrnCatS (AppendString
, AppendSize
/ sizeof (CHAR16
) + 1, BlockPtrStart
, AppendSize
/ sizeof (CHAR16
));
678 TotalSize
= StrSize (AppendString
) + AppendSize
+ sizeof (CHAR16
);
679 AppendString
= (EFI_STRING
) ReallocatePool (
680 StrSize (AppendString
),
684 if (AppendString
== NULL
) {
685 Status
= EFI_OUT_OF_RESOURCES
;
688 StrnCatS (AppendString
, TotalSize
/ sizeof (CHAR16
), BlockPtrStart
, AppendSize
/ sizeof (CHAR16
));
692 // To find next "&OFFSET=<Number>" block with AltConfigHdr in DefaultAltCfgResp.
694 BlockPtr
= StrStr (BlockPtr
+ 1, L
"&OFFSET=");
698 if (AppendString
!= NULL
) {
700 // Reallocate ConfigAltResp to copy the AppendString.
702 TotalSize
= StrSize (*ConfigAltResp
) + StrSize (AppendString
) + sizeof (CHAR16
);
703 *ConfigAltResp
= (EFI_STRING
) ReallocatePool (
704 StrSize (*ConfigAltResp
),
708 if (*ConfigAltResp
== NULL
) {
709 Status
= EFI_OUT_OF_RESOURCES
;
712 StrCatS (*ConfigAltResp
, TotalSize
/ sizeof (CHAR16
), AppendString
);
713 *ConfigAltRespChanged
= TRUE
;
716 Status
= EFI_SUCCESS
;
719 if (AppendString
!= NULL
) {
720 FreePool (AppendString
);
727 Compare the <AltResp> in ConfigAltResp and DefaultAltCfgResp, if the <AltResp>
728 in DefaultAltCfgResp but not in ConfigAltResp,add it to the ConfigAltResp.
730 @param DefaultAltCfgResp Pointer to a null-terminated Unicode string in
731 <MultiConfigAltResp> format. The default value
732 string may contain more than one ConfigAltResp
733 string for the different varstore buffer.
734 @param ConfigAltResp Pointer to a null-terminated Unicode string in
735 <ConfigAltResp> format.
736 @param AltConfigHdr Pointer to a Unicode string in <AltConfigHdr> format.
737 @param ConfigAltRespChanged Whether the ConfigAltResp has been changed.
739 @retval EFI_OUT_OF_RESOURCES Insufficient resources to store necessary structures.
740 @retval EFI_SUCCESS The function finishes successfully.
744 CompareNameElementDefault (
745 IN EFI_STRING DefaultAltCfgResp
,
746 IN OUT EFI_STRING
*ConfigAltResp
,
747 IN EFI_STRING AltConfigHdr
,
748 IN OUT BOOLEAN
*ConfigAltRespChanged
752 EFI_STRING NvConfigPtr
;
753 EFI_STRING NvConfigStart
;
754 EFI_STRING NvConfigValuePtr
;
755 EFI_STRING StringPtr
;
756 EFI_STRING NvConfigExist
;
757 EFI_STRING AppendString
;
763 NvConfigExist
= NULL
;
765 // Make NvConfigPtr point to the first <NvConfig> with AltConfigHdr in DefaultAltCfgResp.
767 NvConfigPtr
= StrStr (DefaultAltCfgResp
, AltConfigHdr
);
768 ASSERT (NvConfigPtr
!= NULL
);
769 NvConfigPtr
= StrStr (NvConfigPtr
+ StrLen(AltConfigHdr
),L
"&");
771 // Make StringPtr point to the first <NvConfig> with AltConfigHdr in ConfigAltResp.
773 StringPtr
= StrStr (*ConfigAltResp
, AltConfigHdr
);
774 ASSERT (StringPtr
!= NULL
);
775 StringPtr
= StrStr (StringPtr
+ StrLen (AltConfigHdr
), L
"&");
776 ASSERT (StringPtr
!= NULL
);
778 while (NvConfigPtr
!= NULL
) {
780 // <NvConfig> ::= <Label>'='<String> | <Label>'='<Number>.
781 // Get the <Label> with AltConfigHdr in DefaultAltCfgResp.
783 NvConfigStart
= NvConfigPtr
;
784 NvConfigValuePtr
= StrStr (NvConfigPtr
+ 1, L
"=");
785 ASSERT (NvConfigValuePtr
!= NULL
);
786 TempChar
= *NvConfigValuePtr
;
787 *NvConfigValuePtr
= L
'\0';
789 // Get the <Label> with AltConfigHdr in ConfigAltResp.
791 NvConfigExist
= StrStr (StringPtr
, NvConfigPtr
);
792 if (NvConfigExist
== NULL
) {
794 // Don't find same <Label> in ConfigAltResp.
795 // Calculate the size of <NvConfig>.
797 *NvConfigValuePtr
= TempChar
;
798 NvConfigPtr
= StrStr (NvConfigPtr
+ 1, L
"&");
799 if (NvConfigPtr
!= NULL
) {
800 AppendSize
= (NvConfigPtr
- NvConfigStart
) * sizeof (CHAR16
);
802 AppendSize
= StrSize (NvConfigStart
);
805 // Copy the <NvConfig> to AppendString.
807 if (AppendString
== NULL
) {
808 AppendString
= (EFI_STRING
) AllocateZeroPool (AppendSize
+ sizeof (CHAR16
));
809 StrnCatS (AppendString
, AppendSize
/ sizeof (CHAR16
) + 1, NvConfigStart
, AppendSize
/ sizeof (CHAR16
));
811 TotalSize
= StrSize (AppendString
) + AppendSize
+ sizeof (CHAR16
);
812 AppendString
= (EFI_STRING
) ReallocatePool (
813 StrSize (AppendString
),
817 if (AppendString
== NULL
) {
818 Status
= EFI_OUT_OF_RESOURCES
;
821 StrnCatS (AppendString
, TotalSize
/ sizeof (CHAR16
), NvConfigStart
, AppendSize
/ sizeof (CHAR16
));
825 // To find next <Label> in DefaultAltCfgResp.
827 *NvConfigValuePtr
= TempChar
;
828 NvConfigPtr
= StrStr (NvConfigPtr
+ 1, L
"&");
831 if (AppendString
!= NULL
) {
833 // Reallocate ConfigAltResp to copy the AppendString.
835 TotalSize
= StrSize (*ConfigAltResp
) + StrSize (AppendString
) + sizeof (CHAR16
);
836 *ConfigAltResp
= (EFI_STRING
) ReallocatePool (
837 StrSize (*ConfigAltResp
),
838 StrSize (*ConfigAltResp
) + StrSize (AppendString
) + sizeof (CHAR16
),
841 if (*ConfigAltResp
== NULL
) {
842 Status
= EFI_OUT_OF_RESOURCES
;
845 StrCatS (*ConfigAltResp
, TotalSize
/ sizeof (CHAR16
), AppendString
);
846 *ConfigAltRespChanged
= TRUE
;
848 Status
= EFI_SUCCESS
;
851 if (AppendString
!= NULL
) {
852 FreePool (AppendString
);
858 Compare the <AltResp> in AltCfgResp and DefaultAltCfgResp, if the <AltResp>
859 in DefaultAltCfgResp but not in AltCfgResp,add it to the AltCfgResp.
861 @param AltCfgResp Pointer to a null-terminated Unicode string in
862 <ConfigAltResp> format.
863 @param DefaultAltCfgResp Pointer to a null-terminated Unicode string in
864 <MultiConfigAltResp> format. The default value
865 string may contain more than one ConfigAltResp
866 string for the different varstore buffer.
867 @param AltConfigHdr Pointer to a Unicode string in <AltConfigHdr> format.
869 @retval EFI_OUT_OF_RESOURCES Insufficient resources to store necessary
871 @retval EFI_SUCCESS The function finishes successfully.
875 CompareAndMergeDefaultString (
876 IN OUT EFI_STRING
*AltCfgResp
,
877 IN EFI_STRING DefaultAltCfgResp
,
878 IN EFI_STRING AltConfigHdr
882 EFI_STRING AltCfgRespBackup
;
883 EFI_STRING AltConfigHdrPtr
;
884 EFI_STRING AltConfigHdrPtrNext
;
885 EFI_STRING ConfigAltResp
;
886 EFI_STRING StringPtr
;
887 EFI_STRING StringPtrNext
;
889 UINTN ReallocateSize
;
892 BOOLEAN ConfigAltRespChanged
;
894 Status
= EFI_OUT_OF_RESOURCES
;
896 AltConfigHdrPtrNext
= NULL
;
897 StringPtrNext
= NULL
;
898 ConfigAltResp
= NULL
;
899 AltCfgRespBackup
= NULL
;
902 ConfigAltRespChanged
= FALSE
;
905 //To find the <AltResp> with AltConfigHdr in DefaultAltCfgResp, ignore other <AltResp> which follow it.
907 AltConfigHdrPtr
= StrStr (DefaultAltCfgResp
, AltConfigHdr
);
908 ASSERT (AltConfigHdrPtr
!= NULL
);
909 AltConfigHdrPtrNext
= StrStr (AltConfigHdrPtr
+ 1, L
"&GUID");
910 if (AltConfigHdrPtrNext
!= NULL
) {
911 TempChar
= *AltConfigHdrPtrNext
;
912 *AltConfigHdrPtrNext
= L
'\0';
915 // To find the <AltResp> with AltConfigHdr in AltCfgResp, ignore other <AltResp> which follow it.
917 StringPtr
= StrStr (*AltCfgResp
, AltConfigHdr
);
918 StringPtrNext
= StrStr (StringPtr
+ 1, L
"&GUID");
919 if (StringPtrNext
!= NULL
) {
920 TempCharA
= *StringPtrNext
;
921 *StringPtrNext
= L
'\0';
924 // Copy the content of <ConfigAltResp> which contain current AltConfigHdr in AltCfgResp.
926 ConfigAltResp
= AllocateCopyPool (StrSize (*AltCfgResp
), *AltCfgResp
);
927 if (ConfigAltResp
== NULL
) {
931 // To find the <ConfigBody> with AltConfigHdr in DefaultAltCfgResp.
933 BlockPtr
= StrStr (AltConfigHdrPtr
, L
"&OFFSET=");
934 if (BlockPtr
!= NULL
) {
936 // <BlockConfig>::='OFFSET='<Number>'&WIDTH='<Number>'&VALUE='<Number> style.
937 // Call function CompareBlockElementDefault to compare the <BlockConfig> in DefaultAltCfgResp and ConfigAltResp.
938 // The ConfigAltResp which may contain the new <BlockConfig> get from DefaultAltCfgResp.
940 Status
= CompareBlockElementDefault (DefaultAltCfgResp
, &ConfigAltResp
, AltConfigHdr
, &ConfigAltRespChanged
);
941 if (EFI_ERROR(Status
)) {
946 // <NvConfig> ::= <Label>'='<String> | <Label>'='<Number> style.
947 // Call function CompareNameElementDefault to compare the <NvConfig> in DefaultAltCfgResp and ConfigAltResp.
948 // The ConfigAltResp which may contain the new <NvConfig> get from DefaultAltCfgResp.
950 Status
= CompareNameElementDefault (DefaultAltCfgResp
, &ConfigAltResp
, AltConfigHdr
, &ConfigAltRespChanged
);
951 if (EFI_ERROR(Status
)) {
956 // Restore the AltCfgResp.
958 if (StringPtrNext
!= NULL
) {
959 *StringPtrNext
= TempCharA
;
963 // If the ConfigAltResp has no change,no need to update the content in AltCfgResp.
965 if (!ConfigAltRespChanged
) {
966 Status
= EFI_SUCCESS
;
970 // ConfigAltResp has been changed, need to update the content in AltCfgResp.
972 if (StringPtrNext
!= NULL
) {
973 ReallocateSize
= StrSize (ConfigAltResp
) + StrSize (StringPtrNext
) + sizeof (CHAR16
);
975 ReallocateSize
= StrSize (ConfigAltResp
) + sizeof (CHAR16
);
978 AltCfgRespBackup
= (EFI_STRING
) AllocateZeroPool (ReallocateSize
);
979 if (AltCfgRespBackup
== NULL
) {
983 StrCatS (AltCfgRespBackup
, ReallocateSize
/ sizeof (CHAR16
), ConfigAltResp
);
984 if (StringPtrNext
!= NULL
) {
985 StrCatS (AltCfgRespBackup
, ReallocateSize
/ sizeof (CHAR16
), StringPtrNext
);
988 FreePool (*AltCfgResp
);
989 *AltCfgResp
= AltCfgRespBackup
;
991 Status
= EFI_SUCCESS
;
994 if (ConfigAltResp
!= NULL
) {
995 FreePool(ConfigAltResp
);
998 // Restore the DefaultAltCfgResp.
1000 if ( AltConfigHdrPtrNext
!= NULL
) {
1001 *AltConfigHdrPtrNext
= TempChar
;
1002 AltConfigHdrPtrNext
= NULL
;
1009 This function merges DefaultAltCfgResp string into AltCfgResp string for
1010 the missing AltCfgId in AltCfgResq.
1012 @param AltCfgResp Pointer to a null-terminated Unicode string in
1013 <ConfigAltResp> format. The default value string
1014 will be merged into it.
1015 @param DefaultAltCfgResp Pointer to a null-terminated Unicode string in
1016 <MultiConfigAltResp> format. The default value
1017 string may contain more than one ConfigAltResp
1018 string for the different varstore buffer.
1020 @retval EFI_SUCCESS The merged string returns.
1021 @retval EFI_INVALID_PARAMETER *AltCfgResp is to NULL.
1025 MergeDefaultString (
1026 IN OUT EFI_STRING
*AltCfgResp
,
1027 IN EFI_STRING DefaultAltCfgResp
1030 EFI_STRING StringPtrDefault
;
1031 EFI_STRING StringPtrEnd
;
1033 EFI_STRING StringPtr
;
1034 EFI_STRING AltConfigHdr
;
1036 UINTN SizeAltCfgResp
;
1040 if (*AltCfgResp
== NULL
) {
1041 return EFI_INVALID_PARAMETER
;
1045 // Get the request ConfigHdr
1048 StringPtr
= *AltCfgResp
;
1051 // Find <ConfigHdr> GUID=...&NAME=...&PATH=...
1053 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
1054 return EFI_INVALID_PARAMETER
;
1056 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&NAME=", StrLen (L
"&NAME=")) != 0) {
1059 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&PATH=", StrLen (L
"&PATH=")) != 0) {
1062 if (*StringPtr
== L
'\0') {
1063 return EFI_INVALID_PARAMETER
;
1065 StringPtr
+= StrLen (L
"&PATH=");
1066 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
1069 HeaderLength
= StringPtr
- *AltCfgResp
;
1072 // Construct AltConfigHdr string "&<ConfigHdr>&ALTCFG=XXXX\0"
1073 // |1| StrLen (ConfigHdr) | 8 | 4 | 1 |
1075 MaxLen
= 1 + HeaderLength
+ 8 + 4 + 1;
1076 AltConfigHdr
= AllocateZeroPool (MaxLen
* sizeof (CHAR16
));
1077 if (AltConfigHdr
== NULL
) {
1078 return EFI_OUT_OF_RESOURCES
;
1080 StrCpyS (AltConfigHdr
, MaxLen
, L
"&");
1081 StrnCatS (AltConfigHdr
, MaxLen
, *AltCfgResp
, HeaderLength
);
1082 StrCatS (AltConfigHdr
, MaxLen
, L
"&ALTCFG=");
1083 HeaderLength
= StrLen (AltConfigHdr
);
1085 StringPtrDefault
= StrStr (DefaultAltCfgResp
, AltConfigHdr
);
1086 while (StringPtrDefault
!= NULL
) {
1090 StrnCatS (AltConfigHdr
, MaxLen
, StringPtrDefault
+ HeaderLength
, 4);
1091 StringPtr
= StrStr (*AltCfgResp
, AltConfigHdr
);
1094 // Append the found default value string to the input AltCfgResp
1096 if (StringPtr
== NULL
) {
1097 StringPtrEnd
= StrStr (StringPtrDefault
+ 1, L
"&GUID");
1098 SizeAltCfgResp
= StrSize (*AltCfgResp
);
1099 if (StringPtrEnd
== NULL
) {
1101 // No more default string is found.
1103 TotalSize
= SizeAltCfgResp
+ StrSize (StringPtrDefault
);
1104 *AltCfgResp
= (EFI_STRING
) ReallocatePool (
1107 (VOID
*) (*AltCfgResp
)
1109 if (*AltCfgResp
== NULL
) {
1110 FreePool (AltConfigHdr
);
1111 return EFI_OUT_OF_RESOURCES
;
1113 StrCatS (*AltCfgResp
, TotalSize
/ sizeof (CHAR16
), StringPtrDefault
);
1116 TempChar
= *StringPtrEnd
;
1117 *StringPtrEnd
= L
'\0';
1118 TotalSize
= SizeAltCfgResp
+ StrSize (StringPtrDefault
);
1119 *AltCfgResp
= (EFI_STRING
) ReallocatePool (
1122 (VOID
*) (*AltCfgResp
)
1124 if (*AltCfgResp
== NULL
) {
1125 FreePool (AltConfigHdr
);
1126 return EFI_OUT_OF_RESOURCES
;
1128 StrCatS (*AltCfgResp
, TotalSize
/ sizeof (CHAR16
), StringPtrDefault
);
1129 *StringPtrEnd
= TempChar
;
1133 // The AltCfgResp contains <AltCfgResp>.
1134 // If the <ConfigElement> in <AltCfgResp> in the DefaultAltCfgResp but not in the
1135 // related <AltCfgResp> in AltCfgResp, merge it to AltCfgResp. else no need to merge.
1137 CompareAndMergeDefaultString (AltCfgResp
, DefaultAltCfgResp
, AltConfigHdr
);
1141 // Find next AltCfg String
1143 *(AltConfigHdr
+ HeaderLength
) = L
'\0';
1144 StringPtrDefault
= StrStr (StringPtrDefault
+ 1, AltConfigHdr
);
1147 FreePool (AltConfigHdr
);
1152 This function inserts new DefaultValueData into the BlockData DefaultValue array.
1154 @param BlockData The BlockData is updated to add new default value.
1155 @param DefaultValueData The DefaultValue is added.
1159 InsertDefaultValue (
1160 IN IFR_BLOCK_DATA
*BlockData
,
1161 IN IFR_DEFAULT_DATA
*DefaultValueData
1165 IFR_DEFAULT_DATA
*DefaultValueArray
;
1166 LIST_ENTRY
*DefaultLink
;
1168 DefaultLink
= &BlockData
->DefaultValueEntry
;
1170 for (Link
= DefaultLink
->ForwardLink
; Link
!= DefaultLink
; Link
= Link
->ForwardLink
) {
1171 DefaultValueArray
= BASE_CR (Link
, IFR_DEFAULT_DATA
, Entry
);
1172 if (DefaultValueArray
->DefaultId
== DefaultValueData
->DefaultId
) {
1174 // DEFAULT_VALUE_FROM_OPCODE has high priority, DEFAULT_VALUE_FROM_DEFAULT has low priority.
1175 // When default types are DEFAULT_VALUE_FROM_OTHER_DEFAULT, the default value can be overrode.
1177 if ((DefaultValueData
->Type
> DefaultValueArray
->Type
) || (DefaultValueData
->Type
== DefaultValueArray
->Type
&& DefaultValueData
->Type
== DefaultValueFromOtherDefault
)) {
1179 // Update the default value array in BlockData.
1181 CopyMem (&DefaultValueArray
->Value
, &DefaultValueData
->Value
, sizeof (EFI_IFR_TYPE_VALUE
));
1182 DefaultValueArray
->Type
= DefaultValueData
->Type
;
1183 DefaultValueArray
->Cleaned
= DefaultValueData
->Cleaned
;
1190 // Insert new default value data in tail.
1192 DefaultValueArray
= AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
1193 ASSERT (DefaultValueArray
!= NULL
);
1194 CopyMem (DefaultValueArray
, DefaultValueData
, sizeof (IFR_DEFAULT_DATA
));
1195 InsertTailList (Link
, &DefaultValueArray
->Entry
);
1199 This function inserts new BlockData into the block link
1201 @param BlockLink The list entry points to block array.
1202 @param BlockData The point to BlockData is added.
1207 IN LIST_ENTRY
*BlockLink
,
1208 IN IFR_BLOCK_DATA
**BlockData
1212 IFR_BLOCK_DATA
*BlockArray
;
1213 IFR_BLOCK_DATA
*BlockSingleData
;
1215 BlockSingleData
= *BlockData
;
1217 if (BlockSingleData
->Name
!= NULL
) {
1218 InsertTailList (BlockLink
, &BlockSingleData
->Entry
);
1223 // Insert block data in its Offset and Width order.
1225 for (Link
= BlockLink
->ForwardLink
; Link
!= BlockLink
; Link
= Link
->ForwardLink
) {
1226 BlockArray
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
1227 if (BlockArray
->Offset
== BlockSingleData
->Offset
) {
1228 if ((BlockArray
->Width
> BlockSingleData
->Width
) || (BlockSingleData
->IsBitVar
&& BlockArray
->Width
== BlockSingleData
->Width
)) {
1230 // Insert this block data in the front of block array
1232 InsertTailList (Link
, &BlockSingleData
->Entry
);
1236 if ((!BlockSingleData
->IsBitVar
) && BlockArray
->Width
== BlockSingleData
->Width
) {
1238 // The same block array has been added.
1240 if (BlockSingleData
!= BlockArray
) {
1241 FreePool (BlockSingleData
);
1242 *BlockData
= BlockArray
;
1246 } else if (BlockArray
->Offset
> BlockSingleData
->Offset
) {
1248 // Insert new block data in the front of block array
1250 InsertTailList (Link
, &BlockSingleData
->Entry
);
1256 // Add new block data into the tail.
1258 InsertTailList (Link
, &BlockSingleData
->Entry
);
1262 Retrieves a pointer to the a Null-terminated ASCII string containing the list
1263 of languages that an HII handle in the HII Database supports. The returned
1264 string is allocated using AllocatePool(). The caller is responsible for freeing
1265 the returned string using FreePool(). The format of the returned string follows
1266 the language format assumed the HII Database.
1268 If HiiHandle is NULL, then ASSERT().
1270 @param[in] HiiHandle A handle that was previously registered in the HII Database.
1272 @retval NULL HiiHandle is not registered in the HII database
1273 @retval NULL There are not enough resources available to retrieve the supported
1275 @retval NULL The list of supported languages could not be retrieved.
1276 @retval Other A pointer to the Null-terminated ASCII string of supported languages.
1280 GetSupportedLanguages (
1281 IN EFI_HII_HANDLE HiiHandle
1286 CHAR8 TempSupportedLanguages
;
1287 CHAR8
*SupportedLanguages
;
1289 ASSERT (HiiHandle
!= NULL
);
1292 // Retrieve the size required for the supported languages buffer.
1295 Status
= mPrivate
.HiiString
.GetLanguages (&mPrivate
.HiiString
, HiiHandle
, &TempSupportedLanguages
, &LanguageSize
);
1298 // If GetLanguages() returns EFI_SUCCESS for a zero size,
1299 // then there are no supported languages registered for HiiHandle. If GetLanguages()
1300 // returns an error other than EFI_BUFFER_TOO_SMALL, then HiiHandle is not present
1301 // in the HII Database
1303 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
1305 // Return NULL if the size can not be retrieved, or if HiiHandle is not in the HII Database
1311 // Allocate the supported languages buffer.
1313 SupportedLanguages
= AllocateZeroPool (LanguageSize
);
1314 if (SupportedLanguages
== NULL
) {
1316 // Return NULL if allocation fails.
1322 // Retrieve the supported languages string
1324 Status
= mPrivate
.HiiString
.GetLanguages (&mPrivate
.HiiString
, HiiHandle
, SupportedLanguages
, &LanguageSize
);
1325 if (EFI_ERROR (Status
)) {
1327 // Free the buffer and return NULL if the supported languages can not be retrieved.
1329 FreePool (SupportedLanguages
);
1334 // Return the Null-terminated ASCII string of supported languages
1336 return SupportedLanguages
;
1340 Retrieves a string from a string package.
1342 If HiiHandle is NULL, then ASSERT().
1343 If StringId is 0, then ASSET.
1345 @param[in] HiiHandle A handle that was previously registered in the HII Database.
1346 @param[in] StringId The identifier of the string to retrieved from the string
1347 package associated with HiiHandle.
1349 @retval NULL The string specified by StringId is not present in the string package.
1350 @retval Other The string was returned.
1355 IN EFI_HII_HANDLE HiiHandle
,
1356 IN EFI_STRING_ID StringId
1363 CHAR8
*SupportedLanguages
;
1364 CHAR8
*PlatformLanguage
;
1365 CHAR8
*BestLanguage
;
1368 ASSERT (HiiHandle
!= NULL
);
1369 ASSERT (StringId
!= 0);
1372 // Initialize all allocated buffers to NULL
1374 SupportedLanguages
= NULL
;
1375 PlatformLanguage
= NULL
;
1376 BestLanguage
= NULL
;
1381 // Get the languages that the package specified by HiiHandle supports
1383 SupportedLanguages
= GetSupportedLanguages (HiiHandle
);
1384 if (SupportedLanguages
== NULL
) {
1389 // Get the current platform language setting
1391 GetEfiGlobalVariable2 (L
"PlatformLang", (VOID
**)&PlatformLanguage
, NULL
);
1394 // Get the best matching language from SupportedLanguages
1396 BestLanguage
= GetBestLanguage (
1398 FALSE
, // RFC 4646 mode
1399 Language
, // Highest priority
1400 PlatformLanguage
!= NULL
? PlatformLanguage
: "", // Next highest priority
1401 SupportedLanguages
, // Lowest priority
1404 if (BestLanguage
== NULL
) {
1409 // Retrieve the size of the string in the string package for the BestLanguage
1412 Status
= mPrivate
.HiiString
.GetString (
1413 &mPrivate
.HiiString
,
1422 // If GetString() returns EFI_SUCCESS for a zero size,
1423 // then there are no supported languages registered for HiiHandle. If GetString()
1424 // returns an error other than EFI_BUFFER_TOO_SMALL, then HiiHandle is not present
1425 // in the HII Database
1427 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
1432 // Allocate a buffer for the return string
1434 String
= AllocateZeroPool (StringSize
);
1435 if (String
== NULL
) {
1440 // Retrieve the string from the string package
1442 Status
= mPrivate
.HiiString
.GetString (
1443 &mPrivate
.HiiString
,
1451 if (EFI_ERROR (Status
)) {
1453 // Free the buffer and return NULL if the supported languages can not be retrieved.
1461 // Free allocated buffers
1463 if (SupportedLanguages
!= NULL
) {
1464 FreePool (SupportedLanguages
);
1466 if (PlatformLanguage
!= NULL
) {
1467 FreePool (PlatformLanguage
);
1469 if (BestLanguage
!= NULL
) {
1470 FreePool (BestLanguage
);
1474 // Return the Null-terminated Unicode string
1480 This function checks VarOffset and VarWidth is in the block range.
1482 @param RequestBlockArray The block array is to be checked.
1483 @param VarOffset Offset of var to the structure
1484 @param VarWidth Width of var.
1485 @param IsNameValueType Whether this varstore is name/value varstore or not.
1486 @param HiiHandle Hii handle for this hii package.
1488 @retval TRUE This Var is in the block range.
1489 @retval FALSE This Var is not in the block range.
1493 IN IFR_BLOCK_DATA
*RequestBlockArray
,
1494 IN UINT16 VarOffset
,
1496 IN BOOLEAN IsNameValueType
,
1497 IN EFI_HII_HANDLE HiiHandle
1501 IFR_BLOCK_DATA
*BlockData
;
1505 // No Request Block array, all vars are got.
1507 if (RequestBlockArray
== NULL
) {
1512 // Check the input var is in the request block range.
1514 for (Link
= RequestBlockArray
->Entry
.ForwardLink
; Link
!= &RequestBlockArray
->Entry
; Link
= Link
->ForwardLink
) {
1515 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
1517 if (IsNameValueType
) {
1518 Name
= InternalGetString (HiiHandle
, VarOffset
);
1519 ASSERT (Name
!= NULL
);
1521 if (StrnCmp (BlockData
->Name
, Name
, StrLen (Name
)) == 0) {
1527 if ((VarOffset
>= BlockData
->Offset
) && ((VarOffset
+ VarWidth
) <= (BlockData
->Offset
+ BlockData
->Width
))) {
1537 Get form package data from data base.
1539 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
1540 @param HiiFormPackage The buffer saves the package data.
1541 @param PackageSize The buffer size of the package data.
1545 GetFormPackageData (
1546 IN HII_DATABASE_RECORD
*DataBaseRecord
,
1547 IN OUT UINT8
**HiiFormPackage
,
1548 OUT UINTN
*PackageSize
1555 if (DataBaseRecord
== NULL
|| HiiFormPackage
== NULL
|| PackageSize
== NULL
) {
1556 return EFI_INVALID_PARAMETER
;
1562 // 0. Get Hii Form Package by HiiHandle
1564 Status
= ExportFormPackages (
1566 DataBaseRecord
->Handle
,
1567 DataBaseRecord
->PackageList
,
1573 if (EFI_ERROR (Status
)) {
1577 (*HiiFormPackage
) = AllocatePool (ResultSize
);
1578 if (*HiiFormPackage
== NULL
) {
1579 Status
= EFI_OUT_OF_RESOURCES
;
1584 // Get HiiFormPackage by HiiHandle
1588 Status
= ExportFormPackages (
1590 DataBaseRecord
->Handle
,
1591 DataBaseRecord
->PackageList
,
1597 if (EFI_ERROR (Status
)) {
1598 FreePool (*HiiFormPackage
);
1601 *PackageSize
= Size
;
1608 This function parses Form Package to get the efi varstore info according to the request ConfigHdr.
1610 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
1611 @param ConfigHdr Request string ConfigHdr. If it is NULL,
1612 the first found varstore will be as ConfigHdr.
1613 @param IsEfiVarstore Whether the request storage type is efi varstore type.
1614 @param EfiVarStore The efi varstore info which will return.
1618 IN HII_DATABASE_RECORD
*DataBaseRecord
,
1619 IN EFI_STRING ConfigHdr
,
1620 OUT BOOLEAN
*IsEfiVarstore
,
1621 OUT EFI_IFR_VARSTORE_EFI
**EfiVarStore
1626 UINTN PackageOffset
;
1627 EFI_IFR_OP_HEADER
*IfrOpHdr
;
1628 CHAR16
*VarStoreName
;
1634 UINT8
*HiiFormPackage
;
1636 EFI_IFR_VARSTORE_EFI
*IfrEfiVarStore
;
1637 EFI_HII_PACKAGE_HEADER
*PackageHeader
;
1639 HiiFormPackage
= NULL
;
1641 Status
= EFI_SUCCESS
;
1645 *IsEfiVarstore
= FALSE
;
1647 Status
= GetFormPackageData(DataBaseRecord
, &HiiFormPackage
, &PackageSize
);
1648 if (EFI_ERROR (Status
)) {
1652 IfrOffset
= sizeof (EFI_HII_PACKAGE_HEADER
);
1653 PackageOffset
= IfrOffset
;
1654 PackageHeader
= (EFI_HII_PACKAGE_HEADER
*) HiiFormPackage
;
1656 while (IfrOffset
< PackageSize
) {
1658 // More than one form packages exist.
1660 if (PackageOffset
>= PackageHeader
->Length
) {
1662 // Process the new form package.
1664 PackageOffset
= sizeof (EFI_HII_PACKAGE_HEADER
);
1665 IfrOffset
+= PackageOffset
;
1666 PackageHeader
= (EFI_HII_PACKAGE_HEADER
*) (HiiFormPackage
+ IfrOffset
);
1669 IfrOpHdr
= (EFI_IFR_OP_HEADER
*) (HiiFormPackage
+ IfrOffset
);
1670 IfrOffset
+= IfrOpHdr
->Length
;
1671 PackageOffset
+= IfrOpHdr
->Length
;
1673 if (IfrOpHdr
->OpCode
== EFI_IFR_VARSTORE_EFI_OP
) {
1674 IfrEfiVarStore
= (EFI_IFR_VARSTORE_EFI
*) IfrOpHdr
;
1676 // If the length is small than the structure, this is from old efi
1677 // varstore definition. Old efi varstore get config directly from
1678 // GetVariable function.
1680 if (IfrOpHdr
->Length
< sizeof (EFI_IFR_VARSTORE_EFI
)) {
1684 NameSize
= AsciiStrSize ((CHAR8
*)IfrEfiVarStore
->Name
);
1685 VarStoreName
= AllocateZeroPool (NameSize
* sizeof (CHAR16
));
1686 if (VarStoreName
== NULL
) {
1687 Status
= EFI_OUT_OF_RESOURCES
;
1690 AsciiStrToUnicodeStrS ((CHAR8
*) IfrEfiVarStore
->Name
, VarStoreName
, NameSize
);
1692 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*) &IfrEfiVarStore
->Guid
, 1, &GuidStr
);
1693 GenerateSubStr (L
"NAME=", StrLen (VarStoreName
) * sizeof (CHAR16
), (VOID
*) VarStoreName
, 2, &NameStr
);
1694 LengthString
= StrLen (GuidStr
);
1695 LengthString
= LengthString
+ StrLen (NameStr
) + 1;
1696 TempStr
= AllocateZeroPool (LengthString
* sizeof (CHAR16
));
1697 if (TempStr
== NULL
) {
1700 FreePool (VarStoreName
);
1701 Status
= EFI_OUT_OF_RESOURCES
;
1704 StrCpyS (TempStr
, LengthString
, GuidStr
);
1705 StrCatS (TempStr
, LengthString
, NameStr
);
1706 if (ConfigHdr
== NULL
|| StrnCmp (ConfigHdr
, TempStr
, StrLen (TempStr
)) == 0) {
1707 *EfiVarStore
= (EFI_IFR_VARSTORE_EFI
*) AllocateZeroPool (IfrOpHdr
->Length
);
1708 if (*EfiVarStore
== NULL
) {
1709 FreePool (VarStoreName
);
1713 Status
= EFI_OUT_OF_RESOURCES
;
1716 *IsEfiVarstore
= TRUE
;
1717 CopyMem (*EfiVarStore
, IfrEfiVarStore
, IfrOpHdr
->Length
);
1721 // Free allocated temp string.
1723 FreePool (VarStoreName
);
1729 // Already found the varstore, break;
1731 if (*IsEfiVarstore
) {
1737 if (HiiFormPackage
!= NULL
) {
1738 FreePool (HiiFormPackage
);
1745 Check whether the ConfigRequest string has the request elements.
1746 For EFI_HII_VARSTORE_BUFFER type, the request has "&OFFSET=****&WIDTH=****..." format.
1747 For EFI_HII_VARSTORE_NAME_VALUE type, the request has "&NAME1**&NAME2..." format.
1749 @param ConfigRequest The input config request string.
1751 @retval TRUE The input include config request elements.
1752 @retval FALSE The input string not includes.
1756 GetElementsFromRequest (
1757 IN EFI_STRING ConfigRequest
1760 EFI_STRING TmpRequest
;
1762 TmpRequest
= StrStr (ConfigRequest
, L
"PATH=");
1763 ASSERT (TmpRequest
!= NULL
);
1765 if ((StrStr (TmpRequest
, L
"&OFFSET=") != NULL
) || (StrStr (TmpRequest
, L
"&") != NULL
)) {
1773 Check whether the this varstore is the request varstore.
1775 @param VarstoreGuid Varstore guid.
1776 @param Name Varstore name.
1777 @param ConfigHdr Current configRequest info.
1779 @retval TRUE This varstore is the request one.
1780 @retval FALSE This varstore is not the request one.
1785 IN EFI_GUID
*VarstoreGuid
,
1787 IN CHAR16
*ConfigHdr
1801 // If ConfigHdr has name field and varstore not has name, return FALSE.
1803 if (Name
== NULL
&& ConfigHdr
!= NULL
&& StrStr (ConfigHdr
, L
"NAME=&") == NULL
) {
1807 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*)VarstoreGuid
, 1, &GuidStr
);
1809 GenerateSubStr (L
"NAME=", StrLen (Name
) * sizeof (CHAR16
), (VOID
*) Name
, 2, &NameStr
);
1811 GenerateSubStr (L
"NAME=", 0, NULL
, 2, &NameStr
);
1813 LengthString
= StrLen (GuidStr
);
1814 LengthString
= LengthString
+ StrLen (NameStr
) + 1;
1815 TempStr
= AllocateZeroPool (LengthString
* sizeof (CHAR16
));
1816 if (TempStr
== NULL
) {
1820 StrCpyS (TempStr
, LengthString
, GuidStr
);
1821 StrCatS (TempStr
, LengthString
, NameStr
);
1823 if (ConfigHdr
== NULL
|| StrnCmp (ConfigHdr
, TempStr
, StrLen (TempStr
)) == 0) {
1828 if (GuidStr
!= NULL
) {
1832 if (NameStr
!= NULL
) {
1836 if (TempStr
!= NULL
) {
1844 This function parses Form Package to get the efi varstore info according to the request ConfigHdr.
1846 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
1847 @param ConfigHdr Request string ConfigHdr. If it is NULL,
1848 the first found varstore will be as ConfigHdr.
1849 @retval TRUE This hii package is the request one.
1850 @retval FALSE This hii package is not the request one.
1854 IN HII_DATABASE_RECORD
*DataBaseRecord
,
1855 IN EFI_STRING ConfigHdr
1860 UINTN PackageOffset
;
1861 EFI_IFR_OP_HEADER
*IfrOpHdr
;
1862 CHAR16
*VarStoreName
;
1864 UINT8
*HiiFormPackage
;
1866 EFI_IFR_VARSTORE_EFI
*IfrEfiVarStore
;
1867 EFI_HII_PACKAGE_HEADER
*PackageHeader
;
1868 EFI_IFR_VARSTORE
*IfrVarStore
;
1869 EFI_IFR_VARSTORE_NAME_VALUE
*IfrNameValueVarStore
;
1870 BOOLEAN FindVarstore
;
1872 HiiFormPackage
= NULL
;
1873 VarStoreName
= NULL
;
1874 Status
= EFI_SUCCESS
;
1875 FindVarstore
= FALSE
;
1877 Status
= GetFormPackageData(DataBaseRecord
, &HiiFormPackage
, &PackageSize
);
1878 if (EFI_ERROR (Status
)) {
1882 IfrOffset
= sizeof (EFI_HII_PACKAGE_HEADER
);
1883 PackageOffset
= IfrOffset
;
1884 PackageHeader
= (EFI_HII_PACKAGE_HEADER
*) HiiFormPackage
;
1886 while (IfrOffset
< PackageSize
) {
1888 // More than one form packages exist.
1890 if (PackageOffset
>= PackageHeader
->Length
) {
1892 // Process the new form package.
1894 PackageOffset
= sizeof (EFI_HII_PACKAGE_HEADER
);
1895 IfrOffset
+= PackageOffset
;
1896 PackageHeader
= (EFI_HII_PACKAGE_HEADER
*) (HiiFormPackage
+ IfrOffset
);
1899 IfrOpHdr
= (EFI_IFR_OP_HEADER
*) (HiiFormPackage
+ IfrOffset
);
1900 IfrOffset
+= IfrOpHdr
->Length
;
1901 PackageOffset
+= IfrOpHdr
->Length
;
1903 switch (IfrOpHdr
->OpCode
) {
1905 case EFI_IFR_VARSTORE_OP
:
1906 IfrVarStore
= (EFI_IFR_VARSTORE
*) IfrOpHdr
;
1908 NameSize
= AsciiStrSize ((CHAR8
*)IfrVarStore
->Name
);
1909 VarStoreName
= AllocateZeroPool (NameSize
* sizeof (CHAR16
));
1910 if (VarStoreName
== NULL
) {
1913 AsciiStrToUnicodeStrS ((CHAR8
*)IfrVarStore
->Name
, VarStoreName
, NameSize
);
1915 if (IsThisVarstore((VOID
*)&IfrVarStore
->Guid
, VarStoreName
, ConfigHdr
)) {
1916 FindVarstore
= TRUE
;
1919 FreePool (VarStoreName
);
1920 VarStoreName
= NULL
;
1924 case EFI_IFR_VARSTORE_EFI_OP
:
1925 IfrEfiVarStore
= (EFI_IFR_VARSTORE_EFI
*) IfrOpHdr
;
1926 NameSize
= AsciiStrSize ((CHAR8
*)IfrEfiVarStore
->Name
);
1927 VarStoreName
= AllocateZeroPool (NameSize
* sizeof (CHAR16
));
1928 if (VarStoreName
== NULL
) {
1931 AsciiStrToUnicodeStrS ((CHAR8
*)IfrEfiVarStore
->Name
, VarStoreName
, NameSize
);
1933 if (IsThisVarstore (&IfrEfiVarStore
->Guid
, VarStoreName
, ConfigHdr
)) {
1934 FindVarstore
= TRUE
;
1937 FreePool (VarStoreName
);
1938 VarStoreName
= NULL
;
1942 case EFI_IFR_VARSTORE_NAME_VALUE_OP
:
1943 IfrNameValueVarStore
= (EFI_IFR_VARSTORE_NAME_VALUE
*) IfrOpHdr
;
1945 if (IsThisVarstore (&IfrNameValueVarStore
->Guid
, NULL
, ConfigHdr
)) {
1946 FindVarstore
= TRUE
;
1951 case EFI_IFR_FORM_OP
:
1952 case EFI_IFR_FORM_MAP_OP
:
1954 // No matched varstore is found and directly return.
1963 if (HiiFormPackage
!= NULL
) {
1964 FreePool (HiiFormPackage
);
1967 if (VarStoreName
!= NULL
) {
1968 FreePool (VarStoreName
);
1971 return FindVarstore
;
1975 Check whether the this op code is required.
1977 @param RequestBlockArray The array includes all the request info or NULL.
1978 @param HiiHandle The hii handle for this form package.
1979 @param VarStorageData The varstore data structure.
1980 @param IfrOpHdr Ifr opcode header for this opcode.
1981 @param VarWidth The buffer width for this opcode.
1982 @param ReturnData The data block added for this opcode.
1983 @param IsBitVar Whether the the opcode refers to bit storage.
1985 @retval EFI_SUCCESS This opcode is required.
1986 @retval EFI_NOT_FOUND This opcode is not required.
1987 @retval Others Contain some error.
1991 IsThisOpcodeRequired (
1992 IN IFR_BLOCK_DATA
*RequestBlockArray
,
1993 IN EFI_HII_HANDLE HiiHandle
,
1994 IN OUT IFR_VARSTORAGE_DATA
*VarStorageData
,
1995 IN EFI_IFR_OP_HEADER
*IfrOpHdr
,
1997 OUT IFR_BLOCK_DATA
**ReturnData
,
2001 IFR_BLOCK_DATA
*BlockData
;
2003 EFI_STRING_ID NameId
;
2004 EFI_IFR_QUESTION_HEADER
*IfrQuestionHdr
;
2013 IfrQuestionHdr
= (EFI_IFR_QUESTION_HEADER
*)((CHAR8
*) IfrOpHdr
+ sizeof (EFI_IFR_OP_HEADER
));
2015 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2016 NameId
= IfrQuestionHdr
->VarStoreInfo
.VarName
;
2019 // Check whether this question is in requested block array.
2021 if (!BlockArrayCheck (RequestBlockArray
, NameId
, 0, TRUE
, HiiHandle
)) {
2023 // This question is not in the requested string. Skip it.
2025 return EFI_NOT_FOUND
;
2029 // Get the byte offset/with and bit offset/width
2032 BitOffset
= IfrQuestionHdr
->VarStoreInfo
.VarOffset
;
2033 BitWidth
= VarWidth
;
2034 VarOffset
= BitOffset
/ 8;
2036 // Use current bit width and the bit width before current bit (with same byte offset) to calculate the byte width.
2038 TotalBits
= BitOffset
% 8 + BitWidth
;
2039 VarWidth
= (TotalBits
% 8 == 0 ? TotalBits
/ 8: TotalBits
/ 8 + 1);
2041 VarOffset
= IfrQuestionHdr
->VarStoreInfo
.VarOffset
;
2042 BitWidth
= VarWidth
;
2043 BitOffset
= VarOffset
* 8;
2047 // Check whether this question is in requested block array.
2049 if (!BlockArrayCheck (RequestBlockArray
, VarOffset
, VarWidth
, FALSE
, HiiHandle
)) {
2051 // This question is not in the requested string. Skip it.
2053 return EFI_NOT_FOUND
;
2057 // Check this var question is in the var storage
2059 if (((VarOffset
+ VarWidth
) > VarStorageData
->Size
)) {
2060 return EFI_INVALID_PARAMETER
;
2064 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
2065 if (BlockData
== NULL
) {
2066 return EFI_OUT_OF_RESOURCES
;
2069 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2070 BlockData
->Name
= InternalGetString(HiiHandle
, NameId
);
2072 BlockData
->Offset
= VarOffset
;
2075 BlockData
->Width
= VarWidth
;
2076 BlockData
->QuestionId
= IfrQuestionHdr
->QuestionId
;
2077 BlockData
->OpCode
= IfrOpHdr
->OpCode
;
2078 BlockData
->Scope
= IfrOpHdr
->Scope
;
2079 BlockData
->IsBitVar
= IsBitVar
;
2080 BlockData
->BitOffset
= BitOffset
;
2081 BlockData
->BitWidth
= BitWidth
;
2082 InitializeListHead (&BlockData
->DefaultValueEntry
);
2084 // Add Block Data into VarStorageData BlockEntry
2086 InsertBlockData (&VarStorageData
->BlockEntry
, &BlockData
);
2087 *ReturnData
= BlockData
;
2093 This function parses Form Package to get the block array and the default
2094 value array according to the request ConfigHdr.
2096 @param HiiHandle Hii Handle for this hii package.
2097 @param Package Pointer to the form package data.
2098 @param PackageLength Length of the package.
2099 @param ConfigHdr Request string ConfigHdr. If it is NULL,
2100 the first found varstore will be as ConfigHdr.
2101 @param RequestBlockArray The block array is retrieved from the request string.
2102 @param VarStorageData VarStorage structure contains the got block and default value.
2103 @param DefaultIdArray Point to the got default id and default name array.
2105 @retval EFI_SUCCESS The block array and the default value array are got.
2106 @retval EFI_INVALID_PARAMETER The varstore definition in the different form packages
2108 @retval EFI_OUT_OF_RESOURCES No enough memory.
2113 IN EFI_HII_HANDLE HiiHandle
,
2115 IN UINT32 PackageLength
,
2116 IN EFI_STRING ConfigHdr
,
2117 IN IFR_BLOCK_DATA
*RequestBlockArray
,
2118 IN OUT IFR_VARSTORAGE_DATA
*VarStorageData
,
2119 OUT IFR_DEFAULT_DATA
*DefaultIdArray
2124 UINTN PackageOffset
;
2125 EFI_IFR_VARSTORE
*IfrVarStore
;
2126 EFI_IFR_VARSTORE_EFI
*IfrEfiVarStore
;
2127 EFI_IFR_OP_HEADER
*IfrOpHdr
;
2128 EFI_IFR_ONE_OF
*IfrOneOf
;
2129 EFI_IFR_REF4
*IfrRef
;
2130 EFI_IFR_ONE_OF_OPTION
*IfrOneOfOption
;
2131 EFI_IFR_DEFAULT
*IfrDefault
;
2132 EFI_IFR_ORDERED_LIST
*IfrOrderedList
;
2133 EFI_IFR_CHECKBOX
*IfrCheckBox
;
2134 EFI_IFR_PASSWORD
*IfrPassword
;
2135 EFI_IFR_STRING
*IfrString
;
2136 EFI_IFR_DATE
*IfrDate
;
2137 EFI_IFR_TIME
*IfrTime
;
2138 IFR_DEFAULT_DATA DefaultData
;
2139 IFR_DEFAULT_DATA
*DefaultDataPtr
;
2140 IFR_BLOCK_DATA
*BlockData
;
2141 CHAR16
*VarStoreName
;
2144 UINT16 VarDefaultId
;
2145 BOOLEAN FirstOneOfOption
;
2146 BOOLEAN FirstOrderedList
;
2147 LIST_ENTRY
*LinkData
;
2148 LIST_ENTRY
*LinkDefault
;
2149 EFI_IFR_VARSTORE_NAME_VALUE
*IfrNameValueVarStore
;
2150 EFI_HII_PACKAGE_HEADER
*PackageHeader
;
2151 EFI_VARSTORE_ID VarStoreId
;
2152 UINT16 SmallestDefaultId
;
2153 BOOLEAN SmallestIdFromFlag
;
2154 BOOLEAN FromOtherDefaultOpcode
;
2155 BOOLEAN QuestionReferBitField
;
2157 Status
= EFI_SUCCESS
;
2159 DefaultDataPtr
= NULL
;
2160 FirstOneOfOption
= FALSE
;
2162 FirstOrderedList
= FALSE
;
2163 VarStoreName
= NULL
;
2164 ZeroMem (&DefaultData
, sizeof (IFR_DEFAULT_DATA
));
2165 SmallestDefaultId
= 0xFFFF;
2166 FromOtherDefaultOpcode
= FALSE
;
2167 QuestionReferBitField
= FALSE
;
2170 // Go through the form package to parse OpCode one by one.
2172 PackageOffset
= sizeof (EFI_HII_PACKAGE_HEADER
);
2173 PackageHeader
= (EFI_HII_PACKAGE_HEADER
*) Package
;
2174 IfrOffset
= PackageOffset
;
2175 while (IfrOffset
< PackageLength
) {
2178 // More than one form package found.
2180 if (PackageOffset
>= PackageHeader
->Length
) {
2182 // Already found varstore for this request, break;
2184 if (VarStoreId
!= 0) {
2189 // Get next package header info.
2191 IfrOffset
+= sizeof (EFI_HII_PACKAGE_HEADER
);
2192 PackageOffset
= sizeof (EFI_HII_PACKAGE_HEADER
);
2193 PackageHeader
= (EFI_HII_PACKAGE_HEADER
*) (Package
+ IfrOffset
);
2196 IfrOpHdr
= (EFI_IFR_OP_HEADER
*) (Package
+ IfrOffset
);
2197 switch (IfrOpHdr
->OpCode
) {
2198 case EFI_IFR_VARSTORE_OP
:
2200 // VarStore is found. Don't need to search any more.
2202 if (VarStoreId
!= 0) {
2206 IfrVarStore
= (EFI_IFR_VARSTORE
*) IfrOpHdr
;
2208 NameSize
= AsciiStrSize ((CHAR8
*)IfrVarStore
->Name
);
2209 VarStoreName
= AllocateZeroPool (NameSize
* sizeof (CHAR16
));
2210 if (VarStoreName
== NULL
) {
2211 Status
= EFI_OUT_OF_RESOURCES
;
2214 AsciiStrToUnicodeStrS ((CHAR8
*)IfrVarStore
->Name
, VarStoreName
, NameSize
);
2216 if (IsThisVarstore((VOID
*)&IfrVarStore
->Guid
, VarStoreName
, ConfigHdr
)) {
2218 // Find the matched VarStore
2220 CopyGuid (&VarStorageData
->Guid
, (EFI_GUID
*) (VOID
*) &IfrVarStore
->Guid
);
2221 VarStorageData
->Size
= IfrVarStore
->Size
;
2222 VarStorageData
->Name
= VarStoreName
;
2223 VarStorageData
->Type
= EFI_HII_VARSTORE_BUFFER
;
2224 VarStoreId
= IfrVarStore
->VarStoreId
;
2226 FreePool (VarStoreName
);
2227 VarStoreName
= NULL
;
2231 case EFI_IFR_VARSTORE_EFI_OP
:
2233 // VarStore is found. Don't need to search any more.
2235 if (VarStoreId
!= 0) {
2239 IfrEfiVarStore
= (EFI_IFR_VARSTORE_EFI
*) IfrOpHdr
;
2242 // If the length is small than the structure, this is from old efi
2243 // varstore definition. Old efi varstore get config directly from
2244 // GetVariable function.
2246 if (IfrOpHdr
->Length
< sizeof (EFI_IFR_VARSTORE_EFI
)) {
2250 NameSize
= AsciiStrSize ((CHAR8
*)IfrEfiVarStore
->Name
);
2251 VarStoreName
= AllocateZeroPool (NameSize
* sizeof (CHAR16
));
2252 if (VarStoreName
== NULL
) {
2253 Status
= EFI_OUT_OF_RESOURCES
;
2256 AsciiStrToUnicodeStrS ((CHAR8
*)IfrEfiVarStore
->Name
, VarStoreName
, NameSize
);
2258 if (IsThisVarstore (&IfrEfiVarStore
->Guid
, VarStoreName
, ConfigHdr
)) {
2260 // Find the matched VarStore
2262 CopyGuid (&VarStorageData
->Guid
, (EFI_GUID
*) (VOID
*) &IfrEfiVarStore
->Guid
);
2263 VarStorageData
->Size
= IfrEfiVarStore
->Size
;
2264 VarStorageData
->Name
= VarStoreName
;
2265 VarStorageData
->Type
= EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
;
2266 VarStoreId
= IfrEfiVarStore
->VarStoreId
;
2268 FreePool (VarStoreName
);
2269 VarStoreName
= NULL
;
2273 case EFI_IFR_VARSTORE_NAME_VALUE_OP
:
2275 // VarStore is found. Don't need to search any more.
2277 if (VarStoreId
!= 0) {
2281 IfrNameValueVarStore
= (EFI_IFR_VARSTORE_NAME_VALUE
*) IfrOpHdr
;
2283 if (IsThisVarstore (&IfrNameValueVarStore
->Guid
, NULL
, ConfigHdr
)) {
2285 // Find the matched VarStore
2287 CopyGuid (&VarStorageData
->Guid
, (EFI_GUID
*) (VOID
*) &IfrNameValueVarStore
->Guid
);
2288 VarStorageData
->Type
= EFI_HII_VARSTORE_NAME_VALUE
;
2289 VarStoreId
= IfrNameValueVarStore
->VarStoreId
;
2293 case EFI_IFR_DEFAULTSTORE_OP
:
2295 // Add new the map between default id and default name.
2297 DefaultDataPtr
= (IFR_DEFAULT_DATA
*) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
2298 if (DefaultDataPtr
== NULL
) {
2299 Status
= EFI_OUT_OF_RESOURCES
;
2302 DefaultDataPtr
->DefaultId
= ((EFI_IFR_DEFAULTSTORE
*) IfrOpHdr
)->DefaultId
;
2303 InsertTailList (&DefaultIdArray
->Entry
, &DefaultDataPtr
->Entry
);
2304 DefaultDataPtr
= NULL
;
2307 case EFI_IFR_FORM_OP
:
2308 case EFI_IFR_FORM_MAP_OP
:
2310 // No matched varstore is found and directly return.
2312 if ( VarStoreId
== 0) {
2313 Status
= EFI_SUCCESS
;
2318 case EFI_IFR_REF_OP
:
2320 // Ref question is not in IFR Form. This IFR form is not valid.
2322 if ( VarStoreId
== 0) {
2323 Status
= EFI_INVALID_PARAMETER
;
2327 // Check whether this question is for the requested varstore.
2329 IfrRef
= (EFI_IFR_REF4
*) IfrOpHdr
;
2330 if (IfrRef
->Question
.VarStoreId
!= VarStoreId
) {
2333 VarWidth
= (UINT16
) (sizeof (EFI_HII_REF
));
2336 // The BlockData may allocate by other opcode,need to clean.
2338 if (BlockData
!= NULL
){
2342 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
, FALSE
);
2343 if (EFI_ERROR (Status
)) {
2344 if (Status
== EFI_NOT_FOUND
){
2346 //The opcode is not required,exit and parse other opcode.
2354 case EFI_IFR_ONE_OF_OP
:
2355 case EFI_IFR_NUMERIC_OP
:
2357 // Numeric and OneOf has the same opcode structure.
2361 // Numeric and OneOf question is not in IFR Form. This IFR form is not valid.
2363 if (VarStoreId
== 0) {
2364 Status
= EFI_INVALID_PARAMETER
;
2368 // Check whether this question is for the requested varstore.
2370 IfrOneOf
= (EFI_IFR_ONE_OF
*) IfrOpHdr
;
2371 if (IfrOneOf
->Question
.VarStoreId
!= VarStoreId
) {
2375 if (QuestionReferBitField
) {
2376 VarWidth
= IfrOneOf
->Flags
& EDKII_IFR_NUMERIC_SIZE_BIT
;
2378 VarWidth
= (UINT16
) (1 << (IfrOneOf
->Flags
& EFI_IFR_NUMERIC_SIZE
));
2382 // The BlockData may allocate by other opcode,need to clean.
2384 if (BlockData
!= NULL
){
2388 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
, QuestionReferBitField
);
2389 if (EFI_ERROR (Status
)) {
2390 if (Status
== EFI_NOT_FOUND
){
2392 //The opcode is not required,exit and parse other opcode.
2400 //when go to there,BlockData can't be NULLL.
2402 ASSERT (BlockData
!= NULL
);
2404 if (IfrOpHdr
->OpCode
== EFI_IFR_ONE_OF_OP
) {
2406 // Set this flag to TRUE for the first oneof option.
2408 FirstOneOfOption
= TRUE
;
2409 } else if (IfrOpHdr
->OpCode
== EFI_IFR_NUMERIC_OP
) {
2411 // Numeric minimum value will be used as default value when no default is specified.
2413 DefaultData
.Type
= DefaultValueFromDefault
;
2414 if (QuestionReferBitField
) {
2416 // Since default value in bit field was stored as UINT32 type.
2418 CopyMem (&DefaultData
.Value
.u32
, &IfrOneOf
->data
.u32
.MinValue
, sizeof (UINT32
));
2420 switch (IfrOneOf
->Flags
& EFI_IFR_NUMERIC_SIZE
) {
2421 case EFI_IFR_NUMERIC_SIZE_1
:
2422 DefaultData
.Value
.u8
= IfrOneOf
->data
.u8
.MinValue
;
2425 case EFI_IFR_NUMERIC_SIZE_2
:
2426 CopyMem (&DefaultData
.Value
.u16
, &IfrOneOf
->data
.u16
.MinValue
, sizeof (UINT16
));
2429 case EFI_IFR_NUMERIC_SIZE_4
:
2430 CopyMem (&DefaultData
.Value
.u32
, &IfrOneOf
->data
.u32
.MinValue
, sizeof (UINT32
));
2433 case EFI_IFR_NUMERIC_SIZE_8
:
2434 CopyMem (&DefaultData
.Value
.u64
, &IfrOneOf
->data
.u64
.MinValue
, sizeof (UINT64
));
2438 Status
= EFI_INVALID_PARAMETER
;
2443 // Set default value base on the DefaultId list get from IFR data.
2445 for (LinkData
= DefaultIdArray
->Entry
.ForwardLink
; LinkData
!= &DefaultIdArray
->Entry
; LinkData
= LinkData
->ForwardLink
) {
2446 DefaultDataPtr
= BASE_CR (LinkData
, IFR_DEFAULT_DATA
, Entry
);
2447 DefaultData
.DefaultId
= DefaultDataPtr
->DefaultId
;
2448 InsertDefaultValue (BlockData
, &DefaultData
);
2453 case EFI_IFR_ORDERED_LIST_OP
:
2455 // offset by question header
2456 // width by EFI_IFR_ORDERED_LIST MaxContainers * OneofOption Type
2459 FirstOrderedList
= TRUE
;
2461 // OrderedList question is not in IFR Form. This IFR form is not valid.
2463 if (VarStoreId
== 0) {
2464 Status
= EFI_INVALID_PARAMETER
;
2468 // Check whether this question is for the requested varstore.
2470 IfrOrderedList
= (EFI_IFR_ORDERED_LIST
*) IfrOpHdr
;
2471 if (IfrOrderedList
->Question
.VarStoreId
!= VarStoreId
) {
2475 VarWidth
= IfrOrderedList
->MaxContainers
;
2478 // The BlockData may allocate by other opcode,need to clean.
2480 if (BlockData
!= NULL
){
2484 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
, FALSE
);
2485 if (EFI_ERROR (Status
)) {
2486 if (Status
== EFI_NOT_FOUND
){
2488 //The opcode is not required,exit and parse other opcode.
2496 case EFI_IFR_CHECKBOX_OP
:
2498 // EFI_IFR_DEFAULT_OP
2499 // offset by question header
2500 // width is 1 sizeof (BOOLEAN)
2501 // default id by CheckBox Flags if CheckBox flags (Default or Mau) is set, the default value is 1 to be set.
2502 // value by DefaultOption
2503 // default id by DeaultOption DefaultId can override CheckBox Flags and Default value.
2507 // CheckBox question is not in IFR Form. This IFR form is not valid.
2509 if (VarStoreId
== 0) {
2510 Status
= EFI_INVALID_PARAMETER
;
2514 // Check whether this question is for the requested varstore.
2516 IfrCheckBox
= (EFI_IFR_CHECKBOX
*) IfrOpHdr
;
2517 if (IfrCheckBox
->Question
.VarStoreId
!= VarStoreId
) {
2520 VarWidth
= (UINT16
) sizeof (BOOLEAN
);
2523 // The BlockData may allocate by other opcode,need to clean.
2525 if (BlockData
!= NULL
){
2529 if (QuestionReferBitField
) {
2532 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
, QuestionReferBitField
);
2533 if (EFI_ERROR (Status
)) {
2534 if (Status
== EFI_NOT_FOUND
){
2536 //The opcode is not required,exit and parse other opcode.
2544 //when go to there,BlockData can't be NULLL.
2546 ASSERT (BlockData
!= NULL
);
2548 SmallestIdFromFlag
= FALSE
;
2551 // Add default value for standard ID by CheckBox Flag
2553 VarDefaultId
= EFI_HII_DEFAULT_CLASS_STANDARD
;
2555 // Prepare new DefaultValue
2557 DefaultData
.DefaultId
= VarDefaultId
;
2558 if ((IfrCheckBox
->Flags
& EFI_IFR_CHECKBOX_DEFAULT
) == EFI_IFR_CHECKBOX_DEFAULT
) {
2560 // When flag is set, default value is TRUE.
2562 DefaultData
.Type
= DefaultValueFromFlag
;
2563 if (QuestionReferBitField
) {
2564 DefaultData
.Value
.u32
= TRUE
;
2566 DefaultData
.Value
.b
= TRUE
;
2568 InsertDefaultValue (BlockData
, &DefaultData
);
2570 if (SmallestDefaultId
> EFI_HII_DEFAULT_CLASS_STANDARD
) {
2572 // Record the SmallestDefaultId and update the SmallestIdFromFlag.
2574 SmallestDefaultId
= EFI_HII_DEFAULT_CLASS_STANDARD
;
2575 SmallestIdFromFlag
= TRUE
;
2580 // Add default value for Manufacture ID by CheckBox Flag
2582 VarDefaultId
= EFI_HII_DEFAULT_CLASS_MANUFACTURING
;
2584 // Prepare new DefaultValue
2586 DefaultData
.DefaultId
= VarDefaultId
;
2587 if ((IfrCheckBox
->Flags
& EFI_IFR_CHECKBOX_DEFAULT_MFG
) == EFI_IFR_CHECKBOX_DEFAULT_MFG
) {
2589 // When flag is set, default value is TRUE.
2591 DefaultData
.Type
= DefaultValueFromFlag
;
2592 if (QuestionReferBitField
) {
2593 DefaultData
.Value
.u32
= TRUE
;
2595 DefaultData
.Value
.b
= TRUE
;
2597 InsertDefaultValue (BlockData
, &DefaultData
);
2599 if (SmallestDefaultId
> EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
2601 // Record the SmallestDefaultId and update the SmallestIdFromFlag.
2603 SmallestDefaultId
= EFI_HII_DEFAULT_CLASS_MANUFACTURING
;
2604 SmallestIdFromFlag
= TRUE
;
2607 if (SmallestIdFromFlag
) {
2609 // When smallest default Id is given by the flag of CheckBox, set default value with TRUE for other default Id in the DefaultId list.
2611 DefaultData
.Type
= DefaultValueFromOtherDefault
;
2612 if (QuestionReferBitField
) {
2613 DefaultData
.Value
.u32
= TRUE
;
2615 DefaultData
.Value
.b
= TRUE
;
2618 // Set default value for all the default id in the DefaultId list.
2620 for (LinkData
= DefaultIdArray
->Entry
.ForwardLink
; LinkData
!= &DefaultIdArray
->Entry
; LinkData
= LinkData
->ForwardLink
) {
2621 DefaultDataPtr
= BASE_CR (LinkData
, IFR_DEFAULT_DATA
, Entry
);
2622 DefaultData
.DefaultId
= DefaultDataPtr
->DefaultId
;
2623 InsertDefaultValue (BlockData
, &DefaultData
);
2627 // When flag is not set, default value is FASLE.
2629 DefaultData
.Type
= DefaultValueFromDefault
;
2630 if (QuestionReferBitField
) {
2631 DefaultData
.Value
.u32
= FALSE
;
2633 DefaultData
.Value
.b
= FALSE
;
2636 // Set default value for all the default id in the DefaultId list.
2638 for (LinkData
= DefaultIdArray
->Entry
.ForwardLink
; LinkData
!= &DefaultIdArray
->Entry
; LinkData
= LinkData
->ForwardLink
) {
2639 DefaultDataPtr
= BASE_CR (LinkData
, IFR_DEFAULT_DATA
, Entry
);
2640 DefaultData
.DefaultId
= DefaultDataPtr
->DefaultId
;
2641 InsertDefaultValue (BlockData
, &DefaultData
);
2646 case EFI_IFR_DATE_OP
:
2648 // offset by question header
2649 // width MaxSize * sizeof (CHAR16)
2650 // no default value, only block array
2654 // Date question is not in IFR Form. This IFR form is not valid.
2656 if (VarStoreId
== 0) {
2657 Status
= EFI_INVALID_PARAMETER
;
2661 // Check whether this question is for the requested varstore.
2663 IfrDate
= (EFI_IFR_DATE
*) IfrOpHdr
;
2664 if (IfrDate
->Question
.VarStoreId
!= VarStoreId
) {
2669 // The BlockData may allocate by other opcode,need to clean.
2671 if (BlockData
!= NULL
){
2675 VarWidth
= (UINT16
) sizeof (EFI_HII_DATE
);
2676 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
, FALSE
);
2677 if (EFI_ERROR (Status
)) {
2678 if (Status
== EFI_NOT_FOUND
){
2680 //The opcode is not required,exit and parse other opcode.
2688 case EFI_IFR_TIME_OP
:
2690 // offset by question header
2691 // width MaxSize * sizeof (CHAR16)
2692 // no default value, only block array
2696 // Time question is not in IFR Form. This IFR form is not valid.
2698 if (VarStoreId
== 0) {
2699 Status
= EFI_INVALID_PARAMETER
;
2703 // Check whether this question is for the requested varstore.
2705 IfrTime
= (EFI_IFR_TIME
*) IfrOpHdr
;
2706 if (IfrTime
->Question
.VarStoreId
!= VarStoreId
) {
2711 // The BlockData may allocate by other opcode,need to clean.
2713 if (BlockData
!= NULL
){
2717 VarWidth
= (UINT16
) sizeof (EFI_HII_TIME
);
2718 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
, FALSE
);
2719 if (EFI_ERROR (Status
)) {
2720 if (Status
== EFI_NOT_FOUND
){
2722 //The opcode is not required,exit and parse other opcode.
2730 case EFI_IFR_STRING_OP
:
2732 // offset by question header
2733 // width MaxSize * sizeof (CHAR16)
2734 // no default value, only block array
2738 // String question is not in IFR Form. This IFR form is not valid.
2740 if (VarStoreId
== 0) {
2741 Status
= EFI_INVALID_PARAMETER
;
2745 // Check whether this question is for the requested varstore.
2747 IfrString
= (EFI_IFR_STRING
*) IfrOpHdr
;
2748 if (IfrString
->Question
.VarStoreId
!= VarStoreId
) {
2753 // The BlockData may allocate by other opcode,need to clean.
2755 if (BlockData
!= NULL
){
2759 VarWidth
= (UINT16
) (IfrString
->MaxSize
* sizeof (UINT16
));
2760 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
, FALSE
);
2761 if (EFI_ERROR (Status
)) {
2762 if (Status
== EFI_NOT_FOUND
){
2764 //The opcode is not required,exit and parse other opcode.
2772 case EFI_IFR_PASSWORD_OP
:
2774 // offset by question header
2775 // width MaxSize * sizeof (CHAR16)
2776 // no default value, only block array
2780 // Password question is not in IFR Form. This IFR form is not valid.
2782 if (VarStoreId
== 0) {
2783 Status
= EFI_INVALID_PARAMETER
;
2787 // Check whether this question is for the requested varstore.
2789 IfrPassword
= (EFI_IFR_PASSWORD
*) IfrOpHdr
;
2790 if (IfrPassword
->Question
.VarStoreId
!= VarStoreId
) {
2795 // The BlockData may allocate by other opcode,need to clean.
2797 if (BlockData
!= NULL
){
2801 VarWidth
= (UINT16
) (IfrPassword
->MaxSize
* sizeof (UINT16
));
2802 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
, FALSE
);
2803 if (EFI_ERROR (Status
)) {
2804 if (Status
== EFI_NOT_FOUND
){
2806 //The opcode is not required,exit and parse other opcode.
2814 // No default value for string.
2819 case EFI_IFR_ONE_OF_OPTION_OP
:
2821 // No matched block data is ignored.
2823 if (BlockData
== NULL
|| BlockData
->Scope
== 0) {
2827 IfrOneOfOption
= (EFI_IFR_ONE_OF_OPTION
*) IfrOpHdr
;
2828 if (BlockData
->OpCode
== EFI_IFR_ORDERED_LIST_OP
) {
2830 if (!FirstOrderedList
){
2834 // Get ordered list option data type.
2836 if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_8
|| IfrOneOfOption
->Type
== EFI_IFR_TYPE_BOOLEAN
) {
2838 } else if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_16
) {
2840 } else if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_32
) {
2842 } else if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_64
) {
2846 // Invalid ordered list option data type.
2848 Status
= EFI_INVALID_PARAMETER
;
2849 if (BlockData
->Name
!= NULL
) {
2850 FreePool (BlockData
->Name
);
2852 FreePool (BlockData
);
2857 // Calculate Ordered list QuestionId width.
2859 BlockData
->Width
= (UINT16
) (BlockData
->Width
* VarWidth
);
2861 // Check whether this question is in requested block array.
2863 if (!BlockArrayCheck (RequestBlockArray
, BlockData
->Offset
, BlockData
->Width
, (BOOLEAN
)(BlockData
->Name
!= NULL
), HiiHandle
)) {
2865 // This question is not in the requested string. Skip it.
2867 if (BlockData
->Name
!= NULL
) {
2868 FreePool (BlockData
->Name
);
2870 FreePool (BlockData
);
2875 // Check this var question is in the var storage
2877 if ((BlockData
->Name
== NULL
) && ((BlockData
->Offset
+ BlockData
->Width
) > VarStorageData
->Size
)) {
2878 Status
= EFI_INVALID_PARAMETER
;
2879 if (BlockData
->Name
!= NULL
) {
2880 FreePool (BlockData
->Name
);
2882 FreePool (BlockData
);
2886 // Add Block Data into VarStorageData BlockEntry
2888 InsertBlockData (&VarStorageData
->BlockEntry
, &BlockData
);
2890 FirstOrderedList
= FALSE
;
2896 // 1. Set default value for OneOf option when flag field has default attribute.
2897 // And set the default value with the smallest default id for other default id in the DefaultId list.
2899 if (((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT
) == EFI_IFR_OPTION_DEFAULT
) ||
2900 ((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT_MFG
) == EFI_IFR_OPTION_DEFAULT_MFG
)) {
2902 // This flag is used to specify whether this option is the first. Set it to FALSE for the following options.
2903 // The first oneof option value will be used as default value when no default value is specified.
2905 FirstOneOfOption
= FALSE
;
2907 SmallestIdFromFlag
= FALSE
;
2909 // Prepare new DefaultValue
2911 DefaultData
.Type
= DefaultValueFromFlag
;
2912 CopyMem (&DefaultData
.Value
, &IfrOneOfOption
->Value
, IfrOneOfOption
->Header
.Length
- OFFSET_OF (EFI_IFR_ONE_OF_OPTION
, Value
));
2913 if ((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT
) == EFI_IFR_OPTION_DEFAULT
) {
2914 DefaultData
.DefaultId
= EFI_HII_DEFAULT_CLASS_STANDARD
;
2915 InsertDefaultValue (BlockData
, &DefaultData
);
2916 if (SmallestDefaultId
> EFI_HII_DEFAULT_CLASS_STANDARD
) {
2918 // Record the SmallestDefaultId and update the SmallestIdFromFlag.
2920 SmallestDefaultId
= EFI_HII_DEFAULT_CLASS_STANDARD
;
2921 SmallestIdFromFlag
= TRUE
;
2924 if ((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT_MFG
) == EFI_IFR_OPTION_DEFAULT_MFG
) {
2925 DefaultData
.DefaultId
= EFI_HII_DEFAULT_CLASS_MANUFACTURING
;
2926 InsertDefaultValue (BlockData
, &DefaultData
);
2927 if (SmallestDefaultId
> EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
2929 // Record the SmallestDefaultId and update the SmallestIdFromFlag.
2931 SmallestDefaultId
= EFI_HII_DEFAULT_CLASS_MANUFACTURING
;
2932 SmallestIdFromFlag
= TRUE
;
2936 if (SmallestIdFromFlag
) {
2938 // When smallest default Id is given by the flag of oneofOption, set this option value for other default Id in the DefaultId list.
2940 DefaultData
.Type
= DefaultValueFromOtherDefault
;
2942 // Set default value for other default id in the DefaultId list.
2944 for (LinkData
= DefaultIdArray
->Entry
.ForwardLink
; LinkData
!= &DefaultIdArray
->Entry
; LinkData
= LinkData
->ForwardLink
) {
2945 DefaultDataPtr
= BASE_CR (LinkData
, IFR_DEFAULT_DATA
, Entry
);
2946 DefaultData
.DefaultId
= DefaultDataPtr
->DefaultId
;
2947 InsertDefaultValue (BlockData
, &DefaultData
);
2953 // 2. Set as the default value when this is the first option.
2954 // The first oneof option value will be used as default value when no default value is specified.
2956 if (FirstOneOfOption
) {
2957 // This flag is used to specify whether this option is the first. Set it to FALSE for the following options.
2958 FirstOneOfOption
= FALSE
;
2961 // Prepare new DefaultValue
2963 DefaultData
.Type
= DefaultValueFromDefault
;
2964 CopyMem (&DefaultData
.Value
, &IfrOneOfOption
->Value
, IfrOneOfOption
->Header
.Length
- OFFSET_OF (EFI_IFR_ONE_OF_OPTION
, Value
));
2965 for (LinkData
= DefaultIdArray
->Entry
.ForwardLink
; LinkData
!= &DefaultIdArray
->Entry
; LinkData
= LinkData
->ForwardLink
) {
2966 DefaultDataPtr
= BASE_CR (LinkData
, IFR_DEFAULT_DATA
, Entry
);
2967 DefaultData
.DefaultId
= DefaultDataPtr
->DefaultId
;
2968 InsertDefaultValue (BlockData
, &DefaultData
);
2973 case EFI_IFR_DEFAULT_OP
:
2975 // Update Current BlockData to the default value.
2977 if (BlockData
== NULL
|| BlockData
->Scope
== 0) {
2979 // No matched block data is ignored.
2985 // Get the DefaultId
2987 IfrDefault
= (EFI_IFR_DEFAULT
*) IfrOpHdr
;
2988 VarDefaultId
= IfrDefault
->DefaultId
;
2990 // Prepare new DefaultValue
2992 DefaultData
.Type
= DefaultValueFromOpcode
;
2993 DefaultData
.DefaultId
= VarDefaultId
;
2994 if (QuestionReferBitField
) {
2995 CopyMem (&DefaultData
.Value
.u32
, &IfrDefault
->Value
.u32
, sizeof (UINT32
));
2997 CopyMem (&DefaultData
.Value
, &IfrDefault
->Value
, IfrDefault
->Header
.Length
- OFFSET_OF (EFI_IFR_DEFAULT
, Value
));
3000 // If the value field is expression, set the cleaned flag.
3001 if (IfrDefault
->Type
== EFI_IFR_TYPE_OTHER
) {
3002 DefaultData
.Cleaned
= TRUE
;
3005 // Add DefaultValue into current BlockData
3007 InsertDefaultValue (BlockData
, &DefaultData
);
3010 // Set default value for other default id in the DefaultId list.
3011 // when SmallestDefaultId == VarDefaultId means there are two defaults with same default Id.
3012 // If the two defaults are both from default opcode, use the first default as the default value of other default Id.
3013 // If one from flag and the other form default opcode, use the default opcode value as the default value of other default Id.
3015 if ((SmallestDefaultId
> VarDefaultId
) || (SmallestDefaultId
== VarDefaultId
&& !FromOtherDefaultOpcode
)) {
3016 FromOtherDefaultOpcode
= TRUE
;
3017 SmallestDefaultId
= VarDefaultId
;
3018 for (LinkData
= DefaultIdArray
->Entry
.ForwardLink
; LinkData
!= &DefaultIdArray
->Entry
; LinkData
= LinkData
->ForwardLink
) {
3019 DefaultDataPtr
= BASE_CR (LinkData
, IFR_DEFAULT_DATA
, Entry
);
3020 if (DefaultDataPtr
->DefaultId
!= DefaultData
.DefaultId
){
3021 DefaultData
.Type
= DefaultValueFromOtherDefault
;
3022 DefaultData
.DefaultId
= DefaultDataPtr
->DefaultId
;
3023 InsertDefaultValue (BlockData
, &DefaultData
);
3029 // After insert the default value, reset the cleaned value for next
3030 // time used. If not set here, need to set the value before every time.
3033 DefaultData
.Cleaned
= FALSE
;
3036 case EFI_IFR_END_OP
:
3038 // End Opcode is for Var question.
3040 QuestionReferBitField
= FALSE
;
3041 if (BlockData
!= NULL
) {
3042 if (BlockData
->Scope
> 0) {
3045 if (BlockData
->Scope
== 0) {
3048 // when finishing parsing a question, clean the SmallestDefaultId and GetDefaultFromDefaultOpcode.
3050 SmallestDefaultId
= 0xFFFF;
3051 FromOtherDefaultOpcode
= FALSE
;
3057 case EFI_IFR_GUID_OP
:
3058 if (CompareGuid ((EFI_GUID
*)((UINT8
*)IfrOpHdr
+ sizeof (EFI_IFR_OP_HEADER
)), &gEdkiiIfrBitVarstoreGuid
)) {
3059 QuestionReferBitField
= TRUE
;
3064 if (BlockData
!= NULL
) {
3065 if (BlockData
->Scope
> 0) {
3066 BlockData
->Scope
= (UINT8
) (BlockData
->Scope
+ IfrOpHdr
->Scope
);
3069 if (BlockData
->Scope
== 0) {
3076 IfrOffset
+= IfrOpHdr
->Length
;
3077 PackageOffset
+= IfrOpHdr
->Length
;
3081 //if Status == EFI_NOT_FOUND, just means the opcode is not required,not contain any error,
3082 //so set the Status to EFI_SUCCESS.
3084 if (Status
== EFI_NOT_FOUND
){
3085 Status
= EFI_SUCCESS
;
3089 for (LinkData
= VarStorageData
->BlockEntry
.ForwardLink
; LinkData
!= &VarStorageData
->BlockEntry
; LinkData
= LinkData
->ForwardLink
) {
3090 BlockData
= BASE_CR (LinkData
, IFR_BLOCK_DATA
, Entry
);
3091 for (LinkDefault
= BlockData
->DefaultValueEntry
.ForwardLink
; LinkDefault
!= &BlockData
->DefaultValueEntry
; ) {
3092 DefaultDataPtr
= BASE_CR (LinkDefault
, IFR_DEFAULT_DATA
, Entry
);
3093 LinkDefault
= LinkDefault
->ForwardLink
;
3094 if (DefaultDataPtr
->Cleaned
== TRUE
) {
3095 RemoveEntryList (&DefaultDataPtr
->Entry
);
3096 FreePool (DefaultDataPtr
);
3105 parse the configrequest string, get the elements.
3107 @param ConfigRequest The input configrequest string.
3108 @param Progress Return the progress data.
3110 @retval Block data pointer.
3114 IN EFI_STRING ConfigRequest
,
3115 OUT EFI_STRING
*Progress
3118 EFI_STRING StringPtr
;
3119 IFR_BLOCK_DATA
*BlockData
;
3120 IFR_BLOCK_DATA
*RequestBlockArray
;
3126 IFR_BLOCK_DATA
*NextBlockData
;
3132 // Init RequestBlockArray
3134 RequestBlockArray
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
3135 if (RequestBlockArray
== NULL
) {
3138 InitializeListHead (&RequestBlockArray
->Entry
);
3141 // Get the request Block array from the request string
3146 // Parse each <RequestElement> if exists
3147 // Only <BlockName> format is supported by this help function.
3148 // <BlockName> ::= &'OFFSET='<Number>&'WIDTH='<Number>
3150 StringPtr
= ConfigRequest
;
3151 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) == 0) {
3153 // Skip the OFFSET string
3155 *Progress
= StringPtr
;
3156 StringPtr
+= StrLen (L
"&OFFSET=");
3160 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
3161 if (EFI_ERROR (Status
)) {
3168 (((Length
+ 1) / 2) < sizeof (UINT16
)) ? ((Length
+ 1) / 2) : sizeof (UINT16
)
3170 FreePool (TmpBuffer
);
3172 StringPtr
+= Length
;
3173 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
3176 StringPtr
+= StrLen (L
"&WIDTH=");
3181 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
3182 if (EFI_ERROR (Status
)) {
3189 (((Length
+ 1) / 2) < sizeof (UINT16
)) ? ((Length
+ 1) / 2) : sizeof (UINT16
)
3191 FreePool (TmpBuffer
);
3193 StringPtr
+= Length
;
3194 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
3201 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
3202 if (BlockData
== NULL
) {
3205 BlockData
->Offset
= Offset
;
3206 BlockData
->Width
= Width
;
3207 InsertBlockData (&RequestBlockArray
->Entry
, &BlockData
);
3210 // Skip &VALUE string if &VALUE does exists.
3212 if (StrnCmp (StringPtr
, L
"&VALUE=", StrLen (L
"&VALUE=")) == 0) {
3213 StringPtr
+= StrLen (L
"&VALUE=");
3218 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
3219 if (EFI_ERROR (Status
)) {
3222 FreePool (TmpBuffer
);
3223 StringPtr
+= Length
;
3224 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
3229 // If '\0', parsing is finished.
3231 if (*StringPtr
== 0) {
3237 // Merge the requested block data.
3239 Link
= RequestBlockArray
->Entry
.ForwardLink
;
3240 while ((Link
!= &RequestBlockArray
->Entry
) && (Link
->ForwardLink
!= &RequestBlockArray
->Entry
)) {
3241 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
3242 NextBlockData
= BASE_CR (Link
->ForwardLink
, IFR_BLOCK_DATA
, Entry
);
3243 if ((NextBlockData
->Offset
>= BlockData
->Offset
) && (NextBlockData
->Offset
<= (BlockData
->Offset
+ BlockData
->Width
))) {
3244 if ((NextBlockData
->Offset
+ NextBlockData
->Width
) > (BlockData
->Offset
+ BlockData
->Width
)) {
3245 BlockData
->Width
= (UINT16
) (NextBlockData
->Offset
+ NextBlockData
->Width
- BlockData
->Offset
);
3247 RemoveEntryList (Link
->ForwardLink
);
3248 FreePool (NextBlockData
);
3251 Link
= Link
->ForwardLink
;
3254 return RequestBlockArray
;
3257 if (RequestBlockArray
!= NULL
) {
3259 // Free Link Array RequestBlockArray
3261 while (!IsListEmpty (&RequestBlockArray
->Entry
)) {
3262 BlockData
= BASE_CR (RequestBlockArray
->Entry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
3263 RemoveEntryList (&BlockData
->Entry
);
3264 FreePool (BlockData
);
3267 FreePool (RequestBlockArray
);
3274 parse the configrequest string, get the elements.
3276 @param ConfigRequest The input config request string.
3277 @param Progress Return the progress data.
3279 @retval return data block array.
3283 IN EFI_STRING ConfigRequest
,
3284 OUT EFI_STRING
*Progress
3287 EFI_STRING StringPtr
;
3289 IFR_BLOCK_DATA
*BlockData
;
3290 IFR_BLOCK_DATA
*RequestBlockArray
;
3293 StringPtr
= ConfigRequest
;
3296 // Init RequestBlockArray
3298 RequestBlockArray
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
3299 if (RequestBlockArray
== NULL
) {
3302 InitializeListHead (&RequestBlockArray
->Entry
);
3305 // Get the request Block array from the request string
3309 // Parse each <RequestElement> if exists
3310 // Only <BlockName> format is supported by this help function.
3311 // <BlockName> ::= &'Name***=***
3313 while (StringPtr
!= NULL
&& *StringPtr
== L
'&') {
3315 *Progress
= StringPtr
;
3317 // Skip the L"&" string
3322 if ((NextTag
= StrStr (StringPtr
, L
"=")) != NULL
) {
3325 } else if ((NextTag
= StrStr (StringPtr
, L
"&")) != NULL
) {
3332 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
3333 if (BlockData
== NULL
) {
3340 BlockData
->Name
= AllocateCopyPool(StrSize (StringPtr
), StringPtr
);
3341 InsertBlockData (&RequestBlockArray
->Entry
, &BlockData
);
3345 // If has value, skip the value.
3347 StringPtr
= NextTag
+ 1;
3349 StringPtr
= StrStr (StringPtr
, L
"&");
3350 } else if (NextTag
!= NULL
) {
3352 // restore the '&' text.
3354 StringPtr
= NextTag
;
3359 return RequestBlockArray
;
3362 if (RequestBlockArray
!= NULL
) {
3364 // Free Link Array RequestBlockArray
3366 while (!IsListEmpty (&RequestBlockArray
->Entry
)) {
3367 BlockData
= BASE_CR (RequestBlockArray
->Entry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
3368 RemoveEntryList (&BlockData
->Entry
);
3369 if (BlockData
->Name
!= NULL
) {
3370 FreePool (BlockData
->Name
);
3372 FreePool (BlockData
);
3375 FreePool (RequestBlockArray
);
3382 Generate ConfigRequest string base on the varstore info.
3384 @param ConfigHdr The config header for this varstore.
3385 @param VarStorageData The varstore info.
3386 @param Status Return Status.
3387 @param ConfigRequest The ConfigRequest info may be return.
3389 @retval TRUE Need to continue
3390 @retval Others NO need to continue or error occur.
3393 GenerateConfigRequest (
3394 IN CHAR16
*ConfigHdr
,
3395 IN IFR_VARSTORAGE_DATA
*VarStorageData
,
3396 OUT EFI_STATUS
*Status
,
3397 IN OUT EFI_STRING
*ConfigRequest
3403 CHAR16
*FullConfigRequest
;
3405 IFR_BLOCK_DATA
*BlockData
;
3408 // Append VarStorageData BlockEntry into *Request string
3409 // Now support only one varstore in a form package.
3413 // Go through all VarStorageData Entry and get BlockEntry for each one for the multiple varstore in a single form package
3414 // Then construct them all to return MultiRequest string : ConfigHdr BlockConfig
3418 // Compute the length of the entire request starting with <ConfigHdr> and a
3422 Length
= StrLen (ConfigHdr
) + 1;
3424 for (Link
= VarStorageData
->BlockEntry
.ForwardLink
; Link
!= &VarStorageData
->BlockEntry
; Link
= Link
->ForwardLink
) {
3426 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
3427 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3429 // Add <BlockName> length for each Name
3431 // <BlockName> ::= &Name1&Name2&...
3432 // |1| StrLen(Name1)
3434 Length
= Length
+ (1 + StrLen (BlockData
->Name
));
3437 // Add <BlockName> length for each Offset/Width pair
3439 // <BlockName> ::= &OFFSET=1234&WIDTH=1234
3440 // | 8 | 4 | 7 | 4 |
3442 Length
= Length
+ (8 + 4 + 7 + 4);
3446 // No any request block data is found. The request string can't be constructed.
3449 *Status
= EFI_SUCCESS
;
3454 // Allocate buffer for the entire <ConfigRequest>
3456 FullConfigRequest
= AllocateZeroPool (Length
* sizeof (CHAR16
));
3457 if (FullConfigRequest
== NULL
) {
3458 *Status
= EFI_OUT_OF_RESOURCES
;
3461 StringPtr
= FullConfigRequest
;
3464 // Start with <ConfigHdr>
3466 StrCpyS (StringPtr
, Length
, ConfigHdr
);
3467 StringPtr
+= StrLen (StringPtr
);
3470 // Loop through all the Offset/Width pairs and append them to ConfigRequest
3472 for (Link
= VarStorageData
->BlockEntry
.ForwardLink
; Link
!= &VarStorageData
->BlockEntry
; Link
= Link
->ForwardLink
) {
3473 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
3474 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3480 (1 + StrLen (BlockData
->Name
) + 1) * sizeof (CHAR16
),
3486 // Append &OFFSET=XXXX&WIDTH=YYYY\0
3490 (8 + 4 + 7 + 4 + 1) * sizeof (CHAR16
),
3491 L
"&OFFSET=%04X&WIDTH=%04X",
3496 StringPtr
+= StrLen (StringPtr
);
3499 // Set to the got full request string.
3501 HiiToLower (FullConfigRequest
);
3503 if (*ConfigRequest
!= NULL
) {
3504 FreePool (*ConfigRequest
);
3506 *ConfigRequest
= FullConfigRequest
;
3512 Generate ConfigRequest Header base on the varstore info.
3514 @param VarStorageData The varstore info.
3515 @param DevicePath Device path for this varstore.
3516 @param ConfigHdr The config header for this varstore.
3518 @retval EFI_SUCCESS Generate the header success.
3519 @retval EFI_OUT_OF_RESOURCES Allocate buffer fail.
3523 IN IFR_VARSTORAGE_DATA
*VarStorageData
,
3524 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
3525 OUT EFI_STRING
*ConfigHdr
3534 Status
= EFI_SUCCESS
;
3540 // Construct <ConfigHdr> : "GUID=...&NAME=...&PATH=..." by VarStorageData Guid, Name and DriverHandle
3542 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*) &VarStorageData
->Guid
, 1, &GuidStr
);
3543 if (VarStorageData
->Name
!= NULL
) {
3544 GenerateSubStr (L
"NAME=", StrLen (VarStorageData
->Name
) * sizeof (CHAR16
), (VOID
*) VarStorageData
->Name
, 2, &NameStr
);
3546 GenerateSubStr (L
"NAME=", 0, NULL
, 2, &NameStr
);
3550 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) DevicePath
),
3551 (VOID
*) DevicePath
,
3555 Length
= StrLen (GuidStr
) + StrLen (NameStr
) + StrLen (PathStr
) + 1;
3556 if (VarStorageData
->Name
== NULL
) {
3560 *ConfigHdr
= AllocateZeroPool (Length
* sizeof (CHAR16
));
3561 if (*ConfigHdr
== NULL
) {
3562 Status
= EFI_OUT_OF_RESOURCES
;
3565 StrCpyS (*ConfigHdr
, Length
, GuidStr
);
3566 StrCatS (*ConfigHdr
, Length
, NameStr
);
3567 if (VarStorageData
->Name
== NULL
) {
3568 StrCatS (*ConfigHdr
, Length
, L
"&");
3570 StrCatS (*ConfigHdr
, Length
, PathStr
);
3573 // Remove the last character L'&'
3575 *(*ConfigHdr
+ StrLen (*ConfigHdr
) - 1) = L
'\0';
3578 if (GuidStr
!= NULL
) {
3582 if (NameStr
!= NULL
) {
3586 if (PathStr
!= NULL
) {
3594 Get Data buffer size based on data type.
3596 @param ValueType The input data type.
3598 @retval The data buffer size for the input type.
3605 UINT16 StorageWidth
;
3607 switch (ValueType
) {
3608 case EFI_IFR_NUMERIC_SIZE_1
:
3609 case EFI_IFR_TYPE_BOOLEAN
:
3610 StorageWidth
= (UINT16
) sizeof (UINT8
);
3613 case EFI_IFR_NUMERIC_SIZE_2
:
3614 StorageWidth
= (UINT16
) sizeof (UINT16
);
3617 case EFI_IFR_NUMERIC_SIZE_4
:
3618 StorageWidth
= (UINT16
) sizeof (UINT32
);
3621 case EFI_IFR_NUMERIC_SIZE_8
:
3622 StorageWidth
= (UINT16
) sizeof (UINT64
);
3625 case EFI_IFR_TYPE_TIME
:
3626 StorageWidth
= (UINT16
) sizeof (EFI_IFR_TIME
);
3629 case EFI_IFR_TYPE_DATE
:
3630 StorageWidth
= (UINT16
) sizeof (EFI_IFR_DATE
);
3638 return StorageWidth
;
3642 Update the default value in the block data which is used as bit var store.
3645 A question value saved in a bit fied: bitoffset = 1; bitwidth = 2;default value = 1.
3646 And corresponding block data info: offset==0; width==1;currently the default value
3647 is saved as 1.Actually the default value 1 need to be set to bit field 1, so the
3648 default value of this block data shuold be:2.
3652 UINT8 Bit2 : 2; // Question saved in Bit2,so originalBlock info: offset = 0; width = 1;(byte level) defaul = 1.
3653 // (default value record for the bit field)
3657 After function UpdateDefaultValue,the Block info is: offset = 0; width = 1;(byte level) default = 2.
3658 (default value record for the Block)
3660 UpdateDefaultValue function update default value of bit var block based on the bit field info in the block.
3662 @param BlockLink The Link of the block data.
3666 UpdateDefaultValue (
3667 IN LIST_ENTRY
*BlockLink
3671 LIST_ENTRY
*ListEntry
;
3672 LIST_ENTRY
*LinkDefault
;
3673 IFR_BLOCK_DATA
*BlockData
;
3674 IFR_DEFAULT_DATA
*DefaultValueData
;
3677 UINT32 BitFieldDefaultValue
;
3679 for ( Link
= BlockLink
->ForwardLink
; Link
!= BlockLink
; Link
= Link
->ForwardLink
) {
3680 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
3681 if (!BlockData
->IsBitVar
) {
3684 ListEntry
= &BlockData
->DefaultValueEntry
;
3686 // Update the default value in the block data with all existing default id.
3688 for (LinkDefault
= ListEntry
->ForwardLink
; LinkDefault
!= ListEntry
; LinkDefault
= LinkDefault
->ForwardLink
) {
3690 // Get the default data, and the value of the default data is for some field in the block.
3691 // Note: Default value for bit field question is stored as UINT32.
3693 DefaultValueData
= BASE_CR (LinkDefault
, IFR_DEFAULT_DATA
, Entry
);
3694 BitFieldDefaultValue
= DefaultValueData
->Value
.u32
;
3696 StartBit
= BlockData
->BitOffset
% 8;
3697 EndBit
= StartBit
+ BlockData
->BitWidth
- 1;
3700 // Set the bit field default value to related bit filed, then we will got the new default vaule for the block data.
3702 DefaultValueData
->Value
.u32
= BitFieldWrite32 (0, StartBit
, EndBit
, BitFieldDefaultValue
);
3708 Merge the default value in two block datas which have overlap region.
3710 For bit fields, their related block data may have overlap region, such as:
3713 UINT16 Bit1 : 6; // Question1 refer Bit1, Block1: offset = 0; width = 1;(byte level) default = 1
3714 UINT16 Bit2 : 5; // Question2 refer Bit2, Block2: offset = 0; width = 2;(byte level) default = 5
3715 // (default value record for the bit field)
3719 After function UpdateDefaultValue:
3720 Block1: offset = 0; width = 1;(byte level) default = 1
3721 Block2: offset = 0; width = 2;(byte level) default = 320 (5 * (2 << 6))
3722 (default value record for block)
3724 After function MergeBlockDefaultValue:
3725 Block1: offset = 0; width = 1;(byte level) default = 65
3726 Block2: offset = 0; width = 2;(byte level) default = 321
3727 (Block1 and Block2 has overlap region, merge the overlap value to Block1 and Blcok2)
3729 Block1 and Block2 have overlap byte region, but currntly the default value of Block1 only contains
3730 value of Bit1 (low 6 bits),the default value of Block2 only contains the value of Bit2 (middle 5 bits).
3732 This fuction merge the default value of these two blocks, and make the default value of block1
3733 also contain the value of lower 2 bits of the Bit2. And make the default value of Block2 also
3734 contain the default value of Bit1.
3736 We can get the total value of the whole block that just cover these two blocks(in this case is:
3737 block: offset =0; width =2;) then the value of block2 is same as block, the value of block1 is
3738 the first byte value of block.
3740 @param FirstBlock Point to the block date whose default value need to be merged.
3741 @param SecondBlock Point to the block date whose default value need to be merged.
3745 MergeBlockDefaultValue (
3746 IN OUT IFR_BLOCK_DATA
*FirstBlock
,
3747 IN OUT IFR_BLOCK_DATA
*SecondBlock
3750 LIST_ENTRY
*FirstListEntry
;
3751 LIST_ENTRY
*SecondListEntry
;
3752 LIST_ENTRY
*FirstDefaultLink
;
3753 LIST_ENTRY
*SecondDefaultLink
;
3754 IFR_DEFAULT_DATA
*FirstDefaultValueData
;
3755 IFR_DEFAULT_DATA
*SecondDefaultValueData
;
3756 UINT32
*FirstDefaultValue
;
3757 UINT32
*SecondDefaultValue
;
3759 UINT64 ShiftedValue
;
3762 FirstListEntry
= &FirstBlock
->DefaultValueEntry
;
3763 for (FirstDefaultLink
= FirstListEntry
->ForwardLink
; FirstDefaultLink
!= FirstListEntry
; FirstDefaultLink
= FirstDefaultLink
->ForwardLink
) {
3764 FirstDefaultValueData
= BASE_CR (FirstDefaultLink
, IFR_DEFAULT_DATA
, Entry
);
3765 SecondListEntry
= &SecondBlock
->DefaultValueEntry
;
3766 for (SecondDefaultLink
= SecondListEntry
->ForwardLink
; SecondDefaultLink
!= SecondListEntry
; SecondDefaultLink
= SecondDefaultLink
->ForwardLink
) {
3767 SecondDefaultValueData
= BASE_CR (SecondDefaultLink
, IFR_DEFAULT_DATA
, Entry
);
3768 if (FirstDefaultValueData
->DefaultId
!= SecondDefaultValueData
->DefaultId
) {
3772 // Find default value with same default id in the two blocks.
3773 // Note: Default value for bit field question is stored as UINT32 type.
3775 FirstDefaultValue
= &FirstDefaultValueData
->Value
.u32
;
3776 SecondDefaultValue
= &SecondDefaultValueData
->Value
.u32
;
3778 // 1. Get the default value of the whole blcok that can just cover FirstBlock and SecondBlock.
3779 // 2. Get the default value of FirstBlock and SecondBlock form the value of whole block based
3780 // on the offset and width of FirstBlock and SecondBlock.
3782 if (FirstBlock
->Offset
> SecondBlock
->Offset
) {
3783 OffsetShift
= FirstBlock
->Offset
- SecondBlock
->Offset
;
3784 ShiftedValue
= LShiftU64 ((UINT64
) (*FirstDefaultValue
), OffsetShift
* 8);
3785 TotalValue
= ShiftedValue
| (UINT64
) (*SecondDefaultValue
);
3786 *SecondDefaultValue
= (UINT32
) BitFieldRead64 (TotalValue
, 0, SecondBlock
->Width
* 8 -1);
3787 *FirstDefaultValue
= (UINT32
) BitFieldRead64 (TotalValue
, OffsetShift
* 8, OffsetShift
* 8 + FirstBlock
->Width
*8 -1);
3789 OffsetShift
= SecondBlock
->Offset
-FirstBlock
->Offset
;
3790 ShiftedValue
= LShiftU64 ((UINT64
) (*SecondDefaultValue
), OffsetShift
* 8);
3791 TotalValue
= ShiftedValue
| (UINT64
) (*FirstDefaultValue
);
3792 *FirstDefaultValue
= (UINT32
) BitFieldRead64 (TotalValue
, 0, FirstBlock
->Width
* 8 -1);
3793 *SecondDefaultValue
= (UINT32
) BitFieldRead64 (TotalValue
, OffsetShift
* 8, OffsetShift
* 8 + SecondBlock
->Width
*8 -1);
3801 Update the default value in the block data which used as Bit VarStore
3803 @param BlockLink The Link of the block data.
3807 UpdateBlockDataArray (
3808 IN LIST_ENTRY
*BlockLink
3812 LIST_ENTRY
*TempLink
;
3813 IFR_BLOCK_DATA
*BlockData
;
3814 IFR_BLOCK_DATA
*NextBlockData
;
3817 // 1. Update default value in BitVar block data.
3818 // Sine some block datas are used as BitVarStore, then the default value recored in the block
3819 // is for related bit field in the block. so we need to set the default value to the related bit
3820 // fields in the block data if the block data is used as bit varstore, then the default value of
3821 // the block will be updated.
3823 UpdateDefaultValue (BlockLink
);
3826 // 2.Update default value for overlap BitVar blcok datas.
3827 // For block datas have overlap region, we need to merge the default value in different blocks.
3829 for (Link
= BlockLink
->ForwardLink
; Link
!= BlockLink
; Link
= Link
->ForwardLink
) {
3830 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
3831 if (!BlockData
->IsBitVar
) {
3834 for (TempLink
= Link
->ForwardLink
; TempLink
!= BlockLink
; TempLink
= TempLink
->ForwardLink
) {
3835 NextBlockData
= BASE_CR (TempLink
, IFR_BLOCK_DATA
, Entry
);
3836 if (!NextBlockData
->IsBitVar
|| NextBlockData
->Offset
>= BlockData
->Offset
+ BlockData
->Width
|| BlockData
->Offset
>= NextBlockData
->Offset
+ NextBlockData
->Width
) {
3840 // Find two blocks are used as bit VarStore and have overlap region, so need to merge default value of these two blocks.
3842 MergeBlockDefaultValue (BlockData
, NextBlockData
);
3848 Generate ConfigAltResp string base on the varstore info.
3850 @param HiiHandle Hii Handle for this hii package.
3851 @param ConfigHdr The config header for this varstore.
3852 @param VarStorageData The varstore info.
3853 @param DefaultIdArray The Default id array.
3854 @param DefaultAltCfgResp The DefaultAltCfgResp info may be return.
3856 @retval TRUE Need to continue
3857 @retval Others NO need to continue or error occur.
3860 GenerateAltConfigResp (
3861 IN EFI_HII_HANDLE HiiHandle
,
3862 IN CHAR16
*ConfigHdr
,
3863 IN IFR_VARSTORAGE_DATA
*VarStorageData
,
3864 IN IFR_DEFAULT_DATA
*DefaultIdArray
,
3865 IN OUT EFI_STRING
*DefaultAltCfgResp
3871 LIST_ENTRY
*LinkData
;
3872 LIST_ENTRY
*LinkDefault
;
3873 LIST_ENTRY
*ListEntry
;
3875 IFR_BLOCK_DATA
*BlockData
;
3876 IFR_DEFAULT_DATA
*DefaultId
;
3877 IFR_DEFAULT_DATA
*DefaultValueData
;
3880 CHAR16
*DefaultString
;
3885 DefaultString
= NULL
;
3887 // Add length for <ConfigHdr> + '\0'
3889 Length
= StrLen (ConfigHdr
) + 1;
3891 UpdateBlockDataArray (&VarStorageData
->BlockEntry
);
3893 for (Link
= DefaultIdArray
->Entry
.ForwardLink
; Link
!= &DefaultIdArray
->Entry
; Link
= Link
->ForwardLink
) {
3894 DefaultId
= BASE_CR (Link
, IFR_DEFAULT_DATA
, Entry
);
3896 // Add length for "&<ConfigHdr>&ALTCFG=XXXX"
3897 // |1| StrLen (ConfigHdr) | 8 | 4 |
3899 Length
+= (1 + StrLen (ConfigHdr
) + 8 + 4);
3901 for (LinkData
= VarStorageData
->BlockEntry
.ForwardLink
; LinkData
!= &VarStorageData
->BlockEntry
; LinkData
= LinkData
->ForwardLink
) {
3902 BlockData
= BASE_CR (LinkData
, IFR_BLOCK_DATA
, Entry
);
3903 ListEntry
= &BlockData
->DefaultValueEntry
;
3904 for (LinkDefault
= ListEntry
->ForwardLink
; LinkDefault
!= ListEntry
; LinkDefault
= LinkDefault
->ForwardLink
) {
3905 DefaultValueData
= BASE_CR (LinkDefault
, IFR_DEFAULT_DATA
, Entry
);
3906 if (DefaultValueData
->DefaultId
!= DefaultId
->DefaultId
) {
3909 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3911 // Add length for "&Name1=zzzzzzzzzzzz"
3914 Length
+= (1 + StrLen (BlockData
->Name
) + 1 + BlockData
->Width
* 2);
3917 // Add length for "&OFFSET=XXXX&WIDTH=YYYY&VALUE=zzzzzzzzzzzz"
3918 // | 8 | 4 | 7 | 4 | 7 | Width * 2 |
3920 Length
+= (8 + 4 + 7 + 4 + 7 + BlockData
->Width
* 2);
3928 // No default value is found. The default string doesn't exist.
3935 // Allocate buffer for the entire <DefaultAltCfgResp>
3937 *DefaultAltCfgResp
= AllocateZeroPool (Length
* sizeof (CHAR16
));
3938 if (*DefaultAltCfgResp
== NULL
) {
3939 return EFI_OUT_OF_RESOURCES
;
3941 StringPtr
= *DefaultAltCfgResp
;
3944 // Start with <ConfigHdr>
3946 StrCpyS (StringPtr
, Length
, ConfigHdr
);
3947 StringPtr
+= StrLen (StringPtr
);
3949 for (Link
= DefaultIdArray
->Entry
.ForwardLink
; Link
!= &DefaultIdArray
->Entry
; Link
= Link
->ForwardLink
) {
3950 DefaultId
= BASE_CR (Link
, IFR_DEFAULT_DATA
, Entry
);
3952 // Add <AltConfigHdr> of the form "&<ConfigHdr>&ALTCFG=XXXX\0"
3953 // |1| StrLen (ConfigHdr) | 8 | 4 |
3957 (1 + StrLen (ConfigHdr
) + 8 + 4 + 1) * sizeof (CHAR16
),
3960 DefaultId
->DefaultId
3962 StringPtr
+= StrLen (StringPtr
);
3964 for (LinkData
= VarStorageData
->BlockEntry
.ForwardLink
; LinkData
!= &VarStorageData
->BlockEntry
; LinkData
= LinkData
->ForwardLink
) {
3965 BlockData
= BASE_CR (LinkData
, IFR_BLOCK_DATA
, Entry
);
3966 ListEntry
= &BlockData
->DefaultValueEntry
;
3967 for (LinkDefault
= ListEntry
->ForwardLink
; LinkDefault
!= ListEntry
; LinkDefault
= LinkDefault
->ForwardLink
) {
3968 DefaultValueData
= BASE_CR (LinkDefault
, IFR_DEFAULT_DATA
, Entry
);
3969 if (DefaultValueData
->DefaultId
!= DefaultId
->DefaultId
) {
3972 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3975 (1 + StrLen (ConfigHdr
) + 1) * sizeof (CHAR16
),
3979 StringPtr
+= StrLen (StringPtr
);
3982 // Add <BlockConfig>
3983 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>
3987 (8 + 4 + 7 + 4 + 7 + 1) * sizeof (CHAR16
),
3988 L
"&OFFSET=%04X&WIDTH=%04X&VALUE=",
3992 StringPtr
+= StrLen (StringPtr
);
3994 Width
= BlockData
->Width
;
3996 // Convert Value to a hex string in "%x" format
3997 // NOTE: This is in the opposite byte that GUID and PATH use
3999 if (BlockData
->OpCode
== EFI_IFR_STRING_OP
){
4000 DefaultString
= InternalGetString(HiiHandle
, DefaultValueData
->Value
.string
);
4001 TmpBuffer
= AllocateZeroPool (Width
);
4002 ASSERT (TmpBuffer
!= NULL
);
4003 if (DefaultString
!= NULL
) {
4004 StrSize
= StrLen(DefaultString
)* sizeof (CHAR16
);
4005 if (StrSize
> Width
) {
4008 CopyMem (TmpBuffer
, (UINT8
*) DefaultString
, StrSize
);
4011 TmpBuffer
= (UINT8
*) &(DefaultValueData
->Value
);
4013 for (; Width
> 0 && (TmpBuffer
!= NULL
); Width
--) {
4014 UnicodeValueToStringS (
4016 Length
* sizeof (CHAR16
) - ((UINTN
)StringPtr
- (UINTN
)*DefaultAltCfgResp
),
4017 PREFIX_ZERO
| RADIX_HEX
,
4018 TmpBuffer
[Width
- 1],
4021 StringPtr
+= StrnLenS (StringPtr
, Length
- ((UINTN
)StringPtr
- (UINTN
)*DefaultAltCfgResp
) / sizeof (CHAR16
));
4023 if (DefaultString
!= NULL
){
4024 FreePool(DefaultString
);
4025 DefaultString
= NULL
;
4027 if (BlockData
->OpCode
== EFI_IFR_STRING_OP
&& TmpBuffer
!= NULL
) {
4028 FreePool(TmpBuffer
);
4035 HiiToLower (*DefaultAltCfgResp
);
4041 This function gets the full request string and full default value string by
4042 parsing IFR data in HII form packages.
4044 When Request points to NULL string, the request string and default value string
4045 for each varstore in form package will return.
4047 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
4048 @param DevicePath Device Path which Hii Config Access Protocol is registered.
4049 @param Request Pointer to a null-terminated Unicode string in
4050 <ConfigRequest> format. When it doesn't contain
4051 any RequestElement, it will be updated to return
4052 the full RequestElement retrieved from IFR data.
4053 If it points to NULL, the request string for the first
4054 varstore in form package will be merged into a
4055 <MultiConfigRequest> format string and return.
4056 @param AltCfgResp Pointer to a null-terminated Unicode string in
4057 <ConfigAltResp> format. When the pointer is to NULL,
4058 the full default value string retrieved from IFR data
4059 will return. When the pinter is to a string, the
4060 full default value string retrieved from IFR data
4061 will be merged into the input string and return.
4062 When Request points to NULL, the default value string
4063 for each varstore in form package will be merged into
4064 a <MultiConfigAltResp> format string and return.
4065 @param PointerProgress Optional parameter, it can be NULL.
4066 When it is not NULL, if Request is NULL, it returns NULL.
4067 On return, points to a character in the Request
4068 string. Points to the string's null terminator if
4069 request was successful. Points to the most recent
4070 & before the first failing name / value pair (or
4071 the beginning of the string if the failure is in
4072 the first name / value pair) if the request was
4074 @retval EFI_SUCCESS The Results string is set to the full request string.
4075 And AltCfgResp contains all default value string.
4076 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
4077 @retval EFI_NOT_FOUND The varstore (Guid and Name) in Request string
4078 can't be found in Form package.
4079 @retval EFI_NOT_FOUND HiiPackage can't be got on the input HiiHandle.
4080 @retval EFI_INVALID_PARAMETER Request points to NULL.
4085 GetFullStringFromHiiFormPackages (
4086 IN HII_DATABASE_RECORD
*DataBaseRecord
,
4087 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
4088 IN OUT EFI_STRING
*Request
,
4089 IN OUT EFI_STRING
*AltCfgResp
,
4090 OUT EFI_STRING
*PointerProgress OPTIONAL
4094 UINT8
*HiiFormPackage
;
4096 IFR_BLOCK_DATA
*RequestBlockArray
;
4097 IFR_BLOCK_DATA
*BlockData
;
4098 IFR_DEFAULT_DATA
*DefaultValueData
;
4099 IFR_DEFAULT_DATA
*DefaultId
;
4100 IFR_DEFAULT_DATA
*DefaultIdArray
;
4101 IFR_VARSTORAGE_DATA
*VarStorageData
;
4102 EFI_STRING DefaultAltCfgResp
;
4103 EFI_STRING ConfigHdr
;
4104 EFI_STRING StringPtr
;
4105 EFI_STRING Progress
;
4107 if (DataBaseRecord
== NULL
|| DevicePath
== NULL
|| Request
== NULL
|| AltCfgResp
== NULL
) {
4108 return EFI_INVALID_PARAMETER
;
4112 // Initialize the local variables.
4114 RequestBlockArray
= NULL
;
4115 DefaultIdArray
= NULL
;
4116 VarStorageData
= NULL
;
4117 DefaultAltCfgResp
= NULL
;
4119 HiiFormPackage
= NULL
;
4121 Progress
= *Request
;
4123 Status
= GetFormPackageData (DataBaseRecord
, &HiiFormPackage
, &PackageSize
);
4124 if (EFI_ERROR (Status
)) {
4129 // 1. Get the request block array by Request String when Request string contains the block array.
4132 if (*Request
!= NULL
) {
4133 StringPtr
= *Request
;
4137 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
4138 Status
= EFI_INVALID_PARAMETER
;
4141 StringPtr
+= StrLen (L
"GUID=");
4142 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&NAME=", StrLen (L
"&NAME=")) != 0) {
4145 if (*StringPtr
== L
'\0') {
4146 Status
= EFI_INVALID_PARAMETER
;
4149 StringPtr
+= StrLen (L
"&NAME=");
4150 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&PATH=", StrLen (L
"&PATH=")) != 0) {
4153 if (*StringPtr
== L
'\0') {
4154 Status
= EFI_INVALID_PARAMETER
;
4157 StringPtr
+= StrLen (L
"&PATH=");
4158 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
4162 if (*StringPtr
== L
'\0') {
4164 // No request block is found.
4171 // If StringPtr != NULL, get the request elements.
4173 if (StringPtr
!= NULL
) {
4174 if (StrStr (StringPtr
, L
"&OFFSET=") != NULL
) {
4175 RequestBlockArray
= GetBlockElement(StringPtr
, &Progress
);
4177 RequestBlockArray
= GetNameElement(StringPtr
, &Progress
);
4180 if (RequestBlockArray
== NULL
) {
4181 Status
= EFI_INVALID_PARAMETER
;
4187 // Initialize DefaultIdArray to store the map between DeaultId and DefaultName
4189 DefaultIdArray
= (IFR_DEFAULT_DATA
*) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
4190 if (DefaultIdArray
== NULL
) {
4191 Status
= EFI_OUT_OF_RESOURCES
;
4194 InitializeListHead (&DefaultIdArray
->Entry
);
4197 // Initialize VarStorageData to store the var store Block and Default value information.
4199 VarStorageData
= (IFR_VARSTORAGE_DATA
*) AllocateZeroPool (sizeof (IFR_VARSTORAGE_DATA
));
4200 if (VarStorageData
== NULL
) {
4201 Status
= EFI_OUT_OF_RESOURCES
;
4204 InitializeListHead (&VarStorageData
->Entry
);
4205 InitializeListHead (&VarStorageData
->BlockEntry
);
4208 // 2. Parse FormPackage to get BlockArray and DefaultId Array for the request BlockArray.
4212 // Parse the opcode in form package to get the default setting.
4214 Status
= ParseIfrData (DataBaseRecord
->Handle
,
4216 (UINT32
) PackageSize
,
4221 if (EFI_ERROR (Status
)) {
4226 // No requested varstore in IFR data and directly return
4228 if (VarStorageData
->Type
== 0 && VarStorageData
->Name
== NULL
) {
4229 Status
= EFI_SUCCESS
;
4234 // 3. Construct Request Element (Block Name) for 2.1 and 2.2 case.
4236 Status
= GenerateHdr (VarStorageData
, DevicePath
, &ConfigHdr
);
4237 if (EFI_ERROR (Status
)) {
4241 if (RequestBlockArray
== NULL
) {
4242 if (!GenerateConfigRequest(ConfigHdr
, VarStorageData
, &Status
, Request
)) {
4248 // 4. Construct Default Value string in AltResp according to request element.
4249 // Go through all VarStorageData Entry and get the DefaultId array for each one
4250 // Then construct them all to : ConfigHdr AltConfigHdr ConfigBody AltConfigHdr ConfigBody
4252 Status
= GenerateAltConfigResp (DataBaseRecord
->Handle
,ConfigHdr
, VarStorageData
, DefaultIdArray
, &DefaultAltCfgResp
);
4253 if (EFI_ERROR (Status
)) {
4258 // 5. Merge string into the input AltCfgResp if the input *AltCfgResp is not NULL.
4260 if (*AltCfgResp
!= NULL
&& DefaultAltCfgResp
!= NULL
) {
4261 Status
= MergeDefaultString (AltCfgResp
, DefaultAltCfgResp
);
4262 FreePool (DefaultAltCfgResp
);
4263 } else if (*AltCfgResp
== NULL
) {
4264 *AltCfgResp
= DefaultAltCfgResp
;
4268 if (RequestBlockArray
!= NULL
) {
4270 // Free Link Array RequestBlockArray
4272 while (!IsListEmpty (&RequestBlockArray
->Entry
)) {
4273 BlockData
= BASE_CR (RequestBlockArray
->Entry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
4274 RemoveEntryList (&BlockData
->Entry
);
4275 if (BlockData
->Name
!= NULL
) {
4276 FreePool (BlockData
->Name
);
4278 FreePool (BlockData
);
4281 FreePool (RequestBlockArray
);
4284 if (VarStorageData
!= NULL
) {
4286 // Free link array VarStorageData
4288 while (!IsListEmpty (&VarStorageData
->BlockEntry
)) {
4289 BlockData
= BASE_CR (VarStorageData
->BlockEntry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
4290 RemoveEntryList (&BlockData
->Entry
);
4291 if (BlockData
->Name
!= NULL
) {
4292 FreePool (BlockData
->Name
);
4295 // Free default value link array
4297 while (!IsListEmpty (&BlockData
->DefaultValueEntry
)) {
4298 DefaultValueData
= BASE_CR (BlockData
->DefaultValueEntry
.ForwardLink
, IFR_DEFAULT_DATA
, Entry
);
4299 RemoveEntryList (&DefaultValueData
->Entry
);
4300 FreePool (DefaultValueData
);
4302 FreePool (BlockData
);
4304 if (VarStorageData
->Name
!= NULL
) {
4305 FreePool (VarStorageData
->Name
);
4306 VarStorageData
->Name
= NULL
;
4308 FreePool (VarStorageData
);
4311 if (DefaultIdArray
!= NULL
) {
4313 // Free DefaultId Array
4315 while (!IsListEmpty (&DefaultIdArray
->Entry
)) {
4316 DefaultId
= BASE_CR (DefaultIdArray
->Entry
.ForwardLink
, IFR_DEFAULT_DATA
, Entry
);
4317 RemoveEntryList (&DefaultId
->Entry
);
4318 FreePool (DefaultId
);
4320 FreePool (DefaultIdArray
);
4324 // Free the allocated string
4326 if (ConfigHdr
!= NULL
) {
4327 FreePool (ConfigHdr
);
4331 // Free Package data
4333 if (HiiFormPackage
!= NULL
) {
4334 FreePool (HiiFormPackage
);
4337 if (PointerProgress
!= NULL
) {
4338 if (*Request
== NULL
) {
4339 *PointerProgress
= NULL
;
4340 } else if (EFI_ERROR (Status
)) {
4341 *PointerProgress
= *Request
;
4343 *PointerProgress
= *Request
+ StrLen (*Request
);
4351 This function gets the full request resp string by
4352 parsing IFR data in HII form packages.
4354 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
4356 @param EfiVarStoreInfo The efi varstore info which is save in the EFI
4357 varstore data structure.
4358 @param Request Pointer to a null-terminated Unicode string in
4359 <ConfigRequest> format.
4360 @param RequestResp Pointer to a null-terminated Unicode string in
4361 <ConfigResp> format.
4362 @param AccessProgress On return, points to a character in the Request
4363 string. Points to the string's null terminator if
4364 request was successful. Points to the most recent
4365 & before the first failing name / value pair (or
4366 the beginning of the string if the failure is in
4367 the first name / value pair) if the request was
4370 @retval EFI_SUCCESS The Results string is set to the full request string.
4371 And AltCfgResp contains all default value string.
4372 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
4373 @retval EFI_INVALID_PARAMETER Request points to NULL.
4377 GetConfigRespFromEfiVarStore (
4378 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
4379 IN EFI_IFR_VARSTORE_EFI
*EfiVarStoreInfo
,
4380 IN EFI_STRING Request
,
4381 OUT EFI_STRING
*RequestResp
,
4382 OUT EFI_STRING
*AccessProgress
4386 EFI_STRING VarStoreName
;
4391 Status
= EFI_SUCCESS
;
4394 VarStoreName
= NULL
;
4395 *AccessProgress
= Request
;
4397 NameSize
= AsciiStrSize ((CHAR8
*)EfiVarStoreInfo
->Name
);
4398 VarStoreName
= AllocateZeroPool (NameSize
* sizeof (CHAR16
));
4399 if (VarStoreName
== NULL
) {
4400 Status
= EFI_OUT_OF_RESOURCES
;
4403 AsciiStrToUnicodeStrS ((CHAR8
*) EfiVarStoreInfo
->Name
, VarStoreName
, NameSize
);
4406 Status
= gRT
->GetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, NULL
, &BufferSize
, NULL
);
4407 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
4411 VarStore
= AllocateZeroPool (BufferSize
);
4412 ASSERT (VarStore
!= NULL
);
4413 Status
= gRT
->GetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, NULL
, &BufferSize
, VarStore
);
4414 if (EFI_ERROR (Status
)) {
4418 Status
= HiiBlockToConfig(This
, Request
, VarStore
, BufferSize
, RequestResp
, AccessProgress
);
4419 if (EFI_ERROR (Status
)) {
4424 if (VarStoreName
!= NULL
) {
4425 FreePool (VarStoreName
);
4428 if (VarStore
!= NULL
) {
4429 FreePool (VarStore
);
4437 This function route the full request resp string for efi varstore.
4439 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
4441 @param EfiVarStoreInfo The efi varstore info which is save in the EFI
4442 varstore data structure.
4443 @param RequestResp Pointer to a null-terminated Unicode string in
4444 <ConfigResp> format.
4445 @param Result Pointer to a null-terminated Unicode string in
4446 <ConfigResp> format.
4448 @retval EFI_SUCCESS The Results string is set to the full request string.
4449 And AltCfgResp contains all default value string.
4450 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
4451 @retval EFI_INVALID_PARAMETER Request points to NULL.
4455 RouteConfigRespForEfiVarStore (
4456 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
4457 IN EFI_IFR_VARSTORE_EFI
*EfiVarStoreInfo
,
4458 IN EFI_STRING RequestResp
,
4459 OUT EFI_STRING
*Result
4463 EFI_STRING VarStoreName
;
4469 Status
= EFI_SUCCESS
;
4472 VarStoreName
= NULL
;
4473 *Result
= RequestResp
;
4475 NameSize
= AsciiStrSize ((CHAR8
*)EfiVarStoreInfo
->Name
);
4476 VarStoreName
= AllocateZeroPool (NameSize
* sizeof (CHAR16
));
4477 if (VarStoreName
== NULL
) {
4478 Status
= EFI_OUT_OF_RESOURCES
;
4481 AsciiStrToUnicodeStrS ((CHAR8
*) EfiVarStoreInfo
->Name
, VarStoreName
, NameSize
);
4483 Status
= gRT
->GetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, NULL
, &BufferSize
, NULL
);
4484 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
4485 DEBUG ((DEBUG_ERROR
, "The variable does not exist!"));
4489 BlockSize
= BufferSize
;
4490 VarStore
= AllocateZeroPool (BufferSize
);
4491 ASSERT (VarStore
!= NULL
);
4492 Status
= gRT
->GetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, NULL
, &BufferSize
, VarStore
);
4493 if (EFI_ERROR (Status
)) {
4497 Status
= HiiConfigToBlock(This
, RequestResp
, VarStore
, &BlockSize
, Result
);
4498 if (EFI_ERROR (Status
)) {
4502 Status
= gRT
->SetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, EfiVarStoreInfo
->Attributes
, BufferSize
, VarStore
);
4503 if (EFI_ERROR (Status
)) {
4504 *Result
= RequestResp
;
4509 if (VarStoreName
!= NULL
) {
4510 FreePool (VarStoreName
);
4513 if (VarStore
!= NULL
) {
4514 FreePool (VarStore
);
4521 Validate the config request elements.
4523 @param ConfigElements A null-terminated Unicode string in <ConfigRequest> format,
4524 without configHdr field.
4526 @retval CHAR16 * THE first Name/value pair not correct.
4527 @retval NULL Success parse the name/value pair
4530 OffsetWidthValidate (
4531 CHAR16
*ConfigElements
4537 StringPtr
= ConfigElements
;
4541 if (StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) != 0) {
4545 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
4548 if (*StringPtr
== L
'\0') {
4552 StringPtr
+= StrLen (L
"&WIDTH=");
4553 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) != 0) {
4557 if (*StringPtr
== L
'\0') {
4564 Validate the config request elements.
4566 @param ConfigElements A null-terminated Unicode string in <ConfigRequest> format,
4567 without configHdr field.
4569 @retval CHAR16 * THE first Name/value pair not correct.
4570 @retval NULL Success parse the name/value pair
4575 CHAR16
*ConfigElements
4581 StringPtr
= ConfigElements
;
4585 if (*StringPtr
!= L
'&') {
4590 StringPtr
= StrStr (StringPtr
, L
"&");
4592 if (StringPtr
== NULL
) {
4599 Validate the config request string.
4601 @param ConfigRequest A null-terminated Unicode string in <ConfigRequest> format.
4603 @retval CHAR16 * THE first element not correct.
4604 @retval NULL Success parse the name/value pair
4608 ConfigRequestValidate (
4609 CHAR16
*ConfigRequest
4612 BOOLEAN HasNameField
;
4615 HasNameField
= TRUE
;
4616 StringPtr
= ConfigRequest
;
4619 // Check <ConfigHdr>
4621 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
4622 return ConfigRequest
;
4624 StringPtr
+= StrLen (L
"GUID=");
4625 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&NAME=", StrLen (L
"&NAME=")) != 0) {
4628 if (*StringPtr
== L
'\0') {
4629 return ConfigRequest
;
4631 StringPtr
+= StrLen (L
"&NAME=");
4632 if (*StringPtr
== L
'&') {
4633 HasNameField
= FALSE
;
4635 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&PATH=", StrLen (L
"&PATH=")) != 0) {
4638 if (*StringPtr
== L
'\0') {
4639 return ConfigRequest
;
4641 StringPtr
+= StrLen (L
"&PATH=");
4642 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
4646 if (*StringPtr
== L
'\0') {
4652 // Should be Buffer varstore, config request should be "OFFSET/Width" pairs.
4654 return OffsetWidthValidate(StringPtr
);
4657 // Should be Name/Value varstore, config request should be "&name1&name2..." pairs.
4659 return NameValueValidate(StringPtr
);
4664 This function allows a caller to extract the current configuration
4665 for one or more named elements from one or more drivers.
4667 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
4669 @param Request A null-terminated Unicode string in
4670 <MultiConfigRequest> format.
4671 @param Progress On return, points to a character in the Request
4672 string. Points to the string's null terminator if
4673 request was successful. Points to the most recent
4674 & before the first failing name / value pair (or
4675 the beginning of the string if the failure is in
4676 the first name / value pair) if the request was
4678 @param Results Null-terminated Unicode string in
4679 <MultiConfigAltResp> format which has all values
4680 filled in for the names in the Request string.
4681 String to be allocated by the called function.
4683 @retval EFI_SUCCESS The Results string is filled with the values
4684 corresponding to all requested names.
4685 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
4686 results that must be stored awaiting possible
4688 @retval EFI_NOT_FOUND Routing data doesn't match any known driver.
4689 Progress set to the "G" in "GUID" of the routing
4690 header that doesn't match. Note: There is no
4691 requirement that all routing data be validated
4692 before any configuration extraction.
4693 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Request
4694 parameter would result in this type of error. The
4695 Progress parameter is set to NULL.
4696 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set to most recent &
4697 before the error or the beginning of the string.
4698 @retval EFI_INVALID_PARAMETER The ExtractConfig function of the underlying HII
4699 Configuration Access Protocol returned
4700 EFI_INVALID_PARAMETER. Progress set to most recent
4701 & before the error or the beginning of the string.
4706 HiiConfigRoutingExtractConfig (
4707 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
4708 IN CONST EFI_STRING Request
,
4709 OUT EFI_STRING
*Progress
,
4710 OUT EFI_STRING
*Results
4713 HII_DATABASE_PRIVATE_DATA
*Private
;
4714 EFI_STRING StringPtr
;
4715 EFI_STRING ConfigRequest
;
4717 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
4718 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
4721 HII_DATABASE_RECORD
*Database
;
4722 UINT8
*DevicePathPkg
;
4723 UINT8
*CurrentDevicePath
;
4724 EFI_HANDLE DriverHandle
;
4725 EFI_HII_HANDLE HiiHandle
;
4726 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
4727 EFI_STRING AccessProgress
;
4728 EFI_STRING AccessResults
;
4729 EFI_STRING AccessProgressBackup
;
4730 EFI_STRING AccessResultsBackup
;
4731 EFI_STRING DefaultResults
;
4732 BOOLEAN FirstElement
;
4733 BOOLEAN IfrDataParsedFlag
;
4734 BOOLEAN IsEfiVarStore
;
4735 EFI_IFR_VARSTORE_EFI
*EfiVarStoreInfo
;
4736 EFI_STRING ErrorPtr
;
4737 UINTN DevicePathSize
;
4738 UINTN ConigStringSize
;
4739 UINTN ConigStringSizeNewsize
;
4740 EFI_STRING ConfigStringPtr
;
4742 if (This
== NULL
|| Progress
== NULL
|| Results
== NULL
) {
4743 return EFI_INVALID_PARAMETER
;
4746 if (Request
== NULL
) {
4748 return EFI_INVALID_PARAMETER
;
4751 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
4752 StringPtr
= Request
;
4753 *Progress
= StringPtr
;
4754 DefaultResults
= NULL
;
4755 ConfigRequest
= NULL
;
4756 Status
= EFI_SUCCESS
;
4757 AccessResults
= NULL
;
4758 AccessProgress
= NULL
;
4759 AccessResultsBackup
= NULL
;
4760 AccessProgressBackup
= NULL
;
4762 IfrDataParsedFlag
= FALSE
;
4763 IsEfiVarStore
= FALSE
;
4764 EfiVarStoreInfo
= NULL
;
4767 // The first element of <MultiConfigRequest> should be
4768 // <GuidHdr>, which is in 'GUID='<Guid> syntax.
4770 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
4771 return EFI_INVALID_PARAMETER
;
4774 FirstElement
= TRUE
;
4777 // Allocate a fix length of memory to store Results. Reallocate memory for
4778 // Results if this fix length is insufficient.
4780 *Results
= (EFI_STRING
) AllocateZeroPool (MAX_STRING_LENGTH
);
4781 if (*Results
== NULL
) {
4782 return EFI_OUT_OF_RESOURCES
;
4785 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) == 0) {
4787 // If parsing error, set Progress to the beginning of the <MultiConfigRequest>
4788 // or most recent & before the error.
4790 if (StringPtr
== Request
) {
4791 *Progress
= StringPtr
;
4793 *Progress
= StringPtr
- 1;
4797 // Process each <ConfigRequest> of <MultiConfigRequest>
4799 Length
= CalculateConfigStringLen (StringPtr
);
4800 ConfigRequest
= AllocateCopyPool ((Length
+ 1) * sizeof (CHAR16
), StringPtr
);
4801 if (ConfigRequest
== NULL
) {
4802 Status
= EFI_OUT_OF_RESOURCES
;
4805 *(ConfigRequest
+ Length
) = 0;
4808 // Get the UEFI device path
4810 Status
= GetDevicePath (ConfigRequest
, (UINT8
**) &DevicePath
);
4811 if (EFI_ERROR (Status
)) {
4816 // Find driver which matches the routing data.
4818 DriverHandle
= NULL
;
4821 for (Link
= Private
->DatabaseList
.ForwardLink
;
4822 Link
!= &Private
->DatabaseList
;
4823 Link
= Link
->ForwardLink
4825 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
4826 if ((DevicePathPkg
= Database
->PackageList
->DevicePathPkg
) != NULL
) {
4827 CurrentDevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
4828 DevicePathSize
= GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) CurrentDevicePath
);
4829 if ((CompareMem (DevicePath
,CurrentDevicePath
,DevicePathSize
) == 0) && IsThisPackageList(Database
, ConfigRequest
)) {
4830 DriverHandle
= Database
->DriverHandle
;
4831 HiiHandle
= Database
->Handle
;
4838 // Try to find driver handle by device path.
4840 if (DriverHandle
== NULL
) {
4841 TempDevicePath
= DevicePath
;
4842 Status
= gBS
->LocateDevicePath (
4843 &gEfiDevicePathProtocolGuid
,
4847 if (EFI_ERROR (Status
) || (DriverHandle
== NULL
)) {
4849 // Routing data does not match any known driver.
4850 // Set Progress to the 'G' in "GUID" of the routing header.
4852 *Progress
= StringPtr
;
4853 Status
= EFI_NOT_FOUND
;
4859 // Validate ConfigRequest String.
4861 ErrorPtr
= ConfigRequestValidate(ConfigRequest
);
4862 if (ErrorPtr
!= NULL
) {
4863 *Progress
= StrStr (StringPtr
, ErrorPtr
);
4864 Status
= EFI_INVALID_PARAMETER
;
4869 // Check whether ConfigRequest contains request string.
4871 IfrDataParsedFlag
= FALSE
;
4872 if ((HiiHandle
!= NULL
) && !GetElementsFromRequest(ConfigRequest
)) {
4874 // Get the full request string from IFR when HiiPackage is registered to HiiHandle
4876 IfrDataParsedFlag
= TRUE
;
4877 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &ConfigRequest
, &DefaultResults
, &AccessProgress
);
4878 if (EFI_ERROR (Status
)) {
4880 // AccessProgress indicates the parsing progress on <ConfigRequest>.
4881 // Map it to the progress on <MultiConfigRequest> then return it.
4883 ASSERT (AccessProgress
!= NULL
);
4884 *Progress
= StrStr (StringPtr
, AccessProgress
);
4888 // Not any request block is found.
4890 if (!GetElementsFromRequest(ConfigRequest
)) {
4891 AccessResults
= AllocateCopyPool (StrSize (ConfigRequest
), ConfigRequest
);
4892 goto NextConfigString
;
4897 // Check whether this ConfigRequest is search from Efi varstore type storage.
4899 Status
= GetVarStoreType(Database
, ConfigRequest
, &IsEfiVarStore
, &EfiVarStoreInfo
);
4900 if (EFI_ERROR (Status
)) {
4904 if (IsEfiVarStore
) {
4906 // Call the GetVariable function to extract settings.
4908 Status
= GetConfigRespFromEfiVarStore(This
, EfiVarStoreInfo
, ConfigRequest
, &AccessResults
, &AccessProgress
);
4909 FreePool (EfiVarStoreInfo
);
4910 if (EFI_ERROR (Status
)) {
4912 // AccessProgress indicates the parsing progress on <ConfigRequest>.
4913 // Map it to the progress on <MultiConfigRequest> then return it.
4915 *Progress
= StrStr (StringPtr
, AccessProgress
);
4920 // For EfiVarstore, call corresponding ConfigAccess protocol to get the AltCfgResp from driver.
4922 Status
= gBS
->HandleProtocol (
4924 &gEfiHiiConfigAccessProtocolGuid
,
4925 (VOID
**) &ConfigAccess
4927 if (EFI_ERROR (Status
)) {
4929 // The driver has EfiVarStore, may not install ConfigAccess protocol.
4930 // So ignore the error status in this case.
4932 Status
= EFI_SUCCESS
;
4934 Status
= ConfigAccess
->ExtractConfig (
4937 &AccessProgressBackup
,
4938 &AccessResultsBackup
4940 if (!EFI_ERROR(Status
)) {
4942 //Merge the AltCfgResp in AccessResultsBackup to AccessResults
4944 if ((AccessResultsBackup
!= NULL
) && (StrStr (AccessResultsBackup
, L
"&ALTCFG=") != NULL
)) {
4945 ConigStringSize
= StrSize (AccessResults
);
4946 ConfigStringPtr
= StrStr (AccessResultsBackup
, L
"&GUID=");
4947 ConigStringSizeNewsize
= StrSize (ConfigStringPtr
) + ConigStringSize
+ sizeof (CHAR16
);
4948 AccessResults
= (EFI_STRING
) ReallocatePool (
4950 ConigStringSizeNewsize
,
4952 StrCatS (AccessResults
, ConigStringSizeNewsize
/ sizeof (CHAR16
), ConfigStringPtr
);
4956 // In the ExtractConfig function of some driver may not support EfiVarStore,
4957 // may return error status, just ignore the error status in this case.
4959 Status
= EFI_SUCCESS
;
4961 if (AccessResultsBackup
!= NULL
) {
4962 FreePool (AccessResultsBackup
);
4963 AccessResultsBackup
= NULL
;
4968 // Call corresponding ConfigAccess protocol to extract settings
4970 Status
= gBS
->HandleProtocol (
4972 &gEfiHiiConfigAccessProtocolGuid
,
4973 (VOID
**) &ConfigAccess
4975 if (EFI_ERROR (Status
)) {
4979 Status
= ConfigAccess
->ExtractConfig (
4986 if (EFI_ERROR (Status
)) {
4988 // AccessProgress indicates the parsing progress on <ConfigRequest>.
4989 // Map it to the progress on <MultiConfigRequest> then return it.
4991 *Progress
= StrStr (StringPtr
, AccessProgress
);
4996 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'
4997 // which separates the first <ConfigAltResp> and the following ones.
4999 ASSERT (*AccessProgress
== 0);
5002 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
5004 if (!IfrDataParsedFlag
&& HiiHandle
!= NULL
) {
5005 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &ConfigRequest
, &DefaultResults
, NULL
);
5006 ASSERT_EFI_ERROR (Status
);
5009 FreePool (DevicePath
);
5012 if (DefaultResults
!= NULL
) {
5013 Status
= MergeDefaultString (&AccessResults
, DefaultResults
);
5014 ASSERT_EFI_ERROR (Status
);
5015 FreePool (DefaultResults
);
5016 DefaultResults
= NULL
;
5020 if (!FirstElement
) {
5021 Status
= AppendToMultiString (Results
, L
"&");
5022 ASSERT_EFI_ERROR (Status
);
5025 Status
= AppendToMultiString (Results
, AccessResults
);
5026 ASSERT_EFI_ERROR (Status
);
5028 FirstElement
= FALSE
;
5030 FreePool (AccessResults
);
5031 AccessResults
= NULL
;
5032 FreePool (ConfigRequest
);
5033 ConfigRequest
= NULL
;
5036 // Go to next <ConfigRequest> (skip '&').
5038 StringPtr
+= Length
;
5039 if (*StringPtr
== 0) {
5040 *Progress
= StringPtr
;
5048 if (EFI_ERROR (Status
)) {
5049 FreePool (*Results
);
5053 if (ConfigRequest
!= NULL
) {
5054 FreePool (ConfigRequest
);
5057 if (AccessResults
!= NULL
) {
5058 FreePool (AccessResults
);
5061 if (DefaultResults
!= NULL
) {
5062 FreePool (DefaultResults
);
5065 if (DevicePath
!= NULL
) {
5066 FreePool (DevicePath
);
5074 This function allows the caller to request the current configuration for the
5075 entirety of the current HII database and returns the data in a
5076 null-terminated Unicode string.
5078 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
5080 @param Results Null-terminated Unicode string in
5081 <MultiConfigAltResp> format which has all values
5082 filled in for the entirety of the current HII
5083 database. String to be allocated by the called
5084 function. De-allocation is up to the caller.
5086 @retval EFI_SUCCESS The Results string is filled with the values
5087 corresponding to all requested names.
5088 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
5089 results that must be stored awaiting possible
5091 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Results
5092 parameter would result in this type of error.
5097 HiiConfigRoutingExportConfig (
5098 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
5099 OUT EFI_STRING
*Results
5103 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
5104 EFI_STRING AccessResults
;
5105 EFI_STRING Progress
;
5106 EFI_STRING StringPtr
;
5107 EFI_STRING ConfigRequest
;
5109 EFI_HANDLE
*ConfigAccessHandles
;
5110 UINTN NumberConfigAccessHandles
;
5111 BOOLEAN FirstElement
;
5112 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
5113 EFI_HII_HANDLE HiiHandle
;
5114 EFI_STRING DefaultResults
;
5115 HII_DATABASE_PRIVATE_DATA
*Private
;
5117 HII_DATABASE_RECORD
*Database
;
5118 UINT8
*DevicePathPkg
;
5119 UINT8
*CurrentDevicePath
;
5120 BOOLEAN IfrDataParsedFlag
;
5122 if (This
== NULL
|| Results
== NULL
) {
5123 return EFI_INVALID_PARAMETER
;
5126 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
5129 // Allocate a fix length of memory to store Results. Reallocate memory for
5130 // Results if this fix length is insufficient.
5132 *Results
= (EFI_STRING
) AllocateZeroPool (MAX_STRING_LENGTH
);
5133 if (*Results
== NULL
) {
5134 return EFI_OUT_OF_RESOURCES
;
5137 NumberConfigAccessHandles
= 0;
5138 Status
= gBS
->LocateHandleBuffer (
5140 &gEfiHiiConfigAccessProtocolGuid
,
5142 &NumberConfigAccessHandles
,
5143 &ConfigAccessHandles
5145 if (EFI_ERROR (Status
)) {
5149 FirstElement
= TRUE
;
5151 for (Index
= 0; Index
< NumberConfigAccessHandles
; Index
++) {
5152 Status
= gBS
->HandleProtocol (
5153 ConfigAccessHandles
[Index
],
5154 &gEfiHiiConfigAccessProtocolGuid
,
5155 (VOID
**) &ConfigAccess
5157 if (EFI_ERROR (Status
)) {
5162 // Get DevicePath and HiiHandle for this ConfigAccess driver handle
5164 IfrDataParsedFlag
= FALSE
;
5167 DefaultResults
= NULL
;
5169 ConfigRequest
= NULL
;
5170 DevicePath
= DevicePathFromHandle (ConfigAccessHandles
[Index
]);
5171 if (DevicePath
!= NULL
) {
5172 for (Link
= Private
->DatabaseList
.ForwardLink
;
5173 Link
!= &Private
->DatabaseList
;
5174 Link
= Link
->ForwardLink
5176 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
5177 if ((DevicePathPkg
= Database
->PackageList
->DevicePathPkg
) != NULL
) {
5178 CurrentDevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
5182 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) CurrentDevicePath
)
5184 HiiHandle
= Database
->Handle
;
5191 Status
= ConfigAccess
->ExtractConfig (
5197 if (EFI_ERROR (Status
)) {
5199 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
5201 if (HiiHandle
!= NULL
&& DevicePath
!= NULL
) {
5202 IfrDataParsedFlag
= TRUE
;
5203 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &ConfigRequest
, &DefaultResults
, NULL
);
5205 // Get the full request string to get the Current setting again.
5207 if (!EFI_ERROR (Status
) && ConfigRequest
!= NULL
) {
5208 Status
= ConfigAccess
->ExtractConfig (
5214 FreePool (ConfigRequest
);
5216 Status
= EFI_NOT_FOUND
;
5221 if (!EFI_ERROR (Status
)) {
5223 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
5225 if (!IfrDataParsedFlag
&& HiiHandle
!= NULL
&& DevicePath
!= NULL
) {
5226 StringPtr
= StrStr (AccessResults
, L
"&GUID=");
5227 if (StringPtr
!= NULL
) {
5230 if (GetElementsFromRequest (AccessResults
)) {
5231 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &AccessResults
, &DefaultResults
, NULL
);
5232 ASSERT_EFI_ERROR (Status
);
5234 if (StringPtr
!= NULL
) {
5239 // Merge the default sting from IFR code into the got setting from driver.
5241 if (DefaultResults
!= NULL
) {
5242 Status
= MergeDefaultString (&AccessResults
, DefaultResults
);
5243 ASSERT_EFI_ERROR (Status
);
5244 FreePool (DefaultResults
);
5245 DefaultResults
= NULL
;
5249 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'
5250 // which separates the first <ConfigAltResp> and the following ones.
5252 if (!FirstElement
) {
5253 Status
= AppendToMultiString (Results
, L
"&");
5254 ASSERT_EFI_ERROR (Status
);
5257 Status
= AppendToMultiString (Results
, AccessResults
);
5258 ASSERT_EFI_ERROR (Status
);
5260 FirstElement
= FALSE
;
5262 FreePool (AccessResults
);
5263 AccessResults
= NULL
;
5266 FreePool (ConfigAccessHandles
);
5273 This function processes the results of processing forms and routes it to the
5274 appropriate handlers or storage.
5276 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
5278 @param Configuration A null-terminated Unicode string in
5279 <MulltiConfigResp> format.
5280 @param Progress A pointer to a string filled in with the offset of
5281 the most recent & before the first failing name /
5282 value pair (or the beginning of the string if the
5283 failure is in the first name / value pair) or the
5284 terminating NULL if all was successful.
5286 @retval EFI_SUCCESS The results have been distributed or are awaiting
5288 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
5289 results that must be stored awaiting possible
5291 @retval EFI_INVALID_PARAMETER Passing in a NULL for the Configuration parameter
5292 would result in this type of error.
5293 @retval EFI_NOT_FOUND Target for the specified routing data was not
5299 HiiConfigRoutingRouteConfig (
5300 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
5301 IN CONST EFI_STRING Configuration
,
5302 OUT EFI_STRING
*Progress
5305 HII_DATABASE_PRIVATE_DATA
*Private
;
5306 EFI_STRING StringPtr
;
5307 EFI_STRING ConfigResp
;
5310 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
5311 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
5313 HII_DATABASE_RECORD
*Database
;
5314 UINT8
*DevicePathPkg
;
5315 UINT8
*CurrentDevicePath
;
5316 EFI_HANDLE DriverHandle
;
5317 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
5318 EFI_STRING AccessProgress
;
5319 EFI_IFR_VARSTORE_EFI
*EfiVarStoreInfo
;
5320 BOOLEAN IsEfiVarstore
;
5321 UINTN DevicePathSize
;
5323 if (This
== NULL
|| Progress
== NULL
) {
5324 return EFI_INVALID_PARAMETER
;
5327 if (Configuration
== NULL
) {
5329 return EFI_INVALID_PARAMETER
;
5332 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
5333 StringPtr
= Configuration
;
5334 *Progress
= StringPtr
;
5336 AccessProgress
= NULL
;
5337 EfiVarStoreInfo
= NULL
;
5338 IsEfiVarstore
= FALSE
;
5341 // The first element of <MultiConfigResp> should be
5342 // <GuidHdr>, which is in 'GUID='<Guid> syntax.
5344 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
5345 return EFI_INVALID_PARAMETER
;
5348 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) == 0) {
5350 // If parsing error, set Progress to the beginning of the <MultiConfigResp>
5351 // or most recent & before the error.
5353 if (StringPtr
== Configuration
) {
5354 *Progress
= StringPtr
;
5356 *Progress
= StringPtr
- 1;
5360 // Process each <ConfigResp> of <MultiConfigResp>
5362 Length
= CalculateConfigStringLen (StringPtr
);
5363 ConfigResp
= AllocateCopyPool ((Length
+ 1) * sizeof (CHAR16
), StringPtr
);
5364 if (ConfigResp
== NULL
) {
5365 return EFI_OUT_OF_RESOURCES
;
5368 // Append '\0' to the end of ConfigRequest
5370 *(ConfigResp
+ Length
) = 0;
5373 // Get the UEFI device path
5375 Status
= GetDevicePath (ConfigResp
, (UINT8
**) &DevicePath
);
5376 if (EFI_ERROR (Status
)) {
5377 FreePool (ConfigResp
);
5382 // Find driver which matches the routing data.
5384 DriverHandle
= NULL
;
5385 for (Link
= Private
->DatabaseList
.ForwardLink
;
5386 Link
!= &Private
->DatabaseList
;
5387 Link
= Link
->ForwardLink
5389 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
5391 if ((DevicePathPkg
= Database
->PackageList
->DevicePathPkg
) != NULL
) {
5392 CurrentDevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
5393 DevicePathSize
= GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) CurrentDevicePath
);
5394 if ((CompareMem (DevicePath
,CurrentDevicePath
,DevicePathSize
) == 0) && IsThisPackageList(Database
, ConfigResp
)) {
5395 DriverHandle
= Database
->DriverHandle
;
5402 // Try to find driver handle by device path.
5404 if (DriverHandle
== NULL
) {
5405 TempDevicePath
= DevicePath
;
5406 Status
= gBS
->LocateDevicePath (
5407 &gEfiDevicePathProtocolGuid
,
5411 if (EFI_ERROR (Status
) || (DriverHandle
== NULL
)) {
5413 // Routing data does not match any known driver.
5414 // Set Progress to the 'G' in "GUID" of the routing header.
5416 FreePool (DevicePath
);
5417 *Progress
= StringPtr
;
5418 FreePool (ConfigResp
);
5419 return EFI_NOT_FOUND
;
5423 FreePool (DevicePath
);
5426 // Check whether this ConfigRequest is search from Efi varstore type storage.
5428 Status
= GetVarStoreType(Database
, ConfigResp
, &IsEfiVarstore
, &EfiVarStoreInfo
);
5429 if (EFI_ERROR (Status
)) {
5433 if (IsEfiVarstore
) {
5435 // Call the SetVariable function to route settings.
5437 Status
= RouteConfigRespForEfiVarStore(This
, EfiVarStoreInfo
, ConfigResp
, &AccessProgress
);
5438 FreePool (EfiVarStoreInfo
);
5441 // Call corresponding ConfigAccess protocol to route settings
5443 Status
= gBS
->HandleProtocol (
5445 &gEfiHiiConfigAccessProtocolGuid
,
5446 (VOID
**) &ConfigAccess
5448 if (EFI_ERROR (Status
)) {
5449 *Progress
= StringPtr
;
5450 FreePool (ConfigResp
);
5451 return EFI_NOT_FOUND
;
5454 Status
= ConfigAccess
->RouteConfig (
5460 if (EFI_ERROR (Status
)) {
5461 ASSERT (AccessProgress
!= NULL
);
5463 // AccessProgress indicates the parsing progress on <ConfigResp>.
5464 // Map it to the progress on <MultiConfigResp> then return it.
5466 *Progress
= StrStr (StringPtr
, AccessProgress
);
5468 FreePool (ConfigResp
);
5472 FreePool (ConfigResp
);
5476 // Go to next <ConfigResp> (skip '&').
5478 StringPtr
+= Length
;
5479 if (*StringPtr
== 0) {
5480 *Progress
= StringPtr
;
5493 This helper function is to be called by drivers to map configuration data
5494 stored in byte array ("block") formats such as UEFI Variables into current
5495 configuration strings.
5497 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
5499 @param ConfigRequest A null-terminated Unicode string in
5500 <ConfigRequest> format.
5501 @param Block Array of bytes defining the block's configuration.
5502 @param BlockSize Length in bytes of Block.
5503 @param Config Filled-in configuration string. String allocated
5504 by the function. Returned only if call is
5505 successful. It is <ConfigResp> string format.
5506 @param Progress A pointer to a string filled in with the offset of
5507 the most recent & before the first failing
5508 name/value pair (or the beginning of the string if
5509 the failure is in the first name / value pair) or
5510 the terminating NULL if all was successful.
5512 @retval EFI_SUCCESS The request succeeded. Progress points to the null
5513 terminator at the end of the ConfigRequest
5515 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress
5516 points to the first character of ConfigRequest.
5517 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigRequest or
5518 Block parameter would result in this type of
5519 error. Progress points to the first character of
5521 @retval EFI_DEVICE_ERROR Block not large enough. Progress undefined.
5522 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted string.
5523 Block is left updated and Progress points at
5524 the "&" preceding the first non-<BlockName>.
5530 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
5531 IN CONST EFI_STRING ConfigRequest
,
5532 IN CONST UINT8
*Block
,
5533 IN CONST UINTN BlockSize
,
5534 OUT EFI_STRING
*Config
,
5535 OUT EFI_STRING
*Progress
5538 HII_DATABASE_PRIVATE_DATA
*Private
;
5539 EFI_STRING StringPtr
;
5547 EFI_STRING ValueStr
;
5548 EFI_STRING ConfigElement
;
5556 if (This
== NULL
|| Progress
== NULL
|| Config
== NULL
) {
5557 return EFI_INVALID_PARAMETER
;
5560 if (Block
== NULL
|| ConfigRequest
== NULL
) {
5561 *Progress
= ConfigRequest
;
5562 return EFI_INVALID_PARAMETER
;
5566 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
5567 ASSERT (Private
!= NULL
);
5569 StringPtr
= ConfigRequest
;
5572 ConfigElement
= NULL
;
5575 // Allocate a fix length of memory to store Results. Reallocate memory for
5576 // Results if this fix length is insufficient.
5578 *Config
= (EFI_STRING
) AllocateZeroPool (MAX_STRING_LENGTH
);
5579 if (*Config
== NULL
) {
5580 return EFI_OUT_OF_RESOURCES
;
5586 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
5587 *Progress
= StringPtr
;
5588 Status
= EFI_INVALID_PARAMETER
;
5591 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"PATH=", StrLen (L
"PATH=")) != 0) {
5594 if (*StringPtr
== 0) {
5595 *Progress
= StringPtr
- 1;
5596 Status
= EFI_INVALID_PARAMETER
;
5600 while (*StringPtr
!= L
'&' && *StringPtr
!= 0) {
5603 if (*StringPtr
== 0) {
5604 *Progress
= StringPtr
;
5606 AppendToMultiString(Config
, ConfigRequest
);
5607 HiiToLower (*Config
);
5617 // Copy <ConfigHdr> and an additional '&' to <ConfigResp>
5619 TemChar
= *StringPtr
;
5621 AppendToMultiString(Config
, ConfigRequest
);
5622 *StringPtr
= TemChar
;
5625 // Parse each <RequestElement> if exists
5626 // Only <BlockName> format is supported by this help function.
5627 // <BlockName> ::= 'OFFSET='<Number>&'WIDTH='<Number>
5629 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"OFFSET=", StrLen (L
"OFFSET=")) == 0) {
5631 // Back up the header of one <BlockName>
5635 StringPtr
+= StrLen (L
"OFFSET=");
5639 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
5640 if (EFI_ERROR (Status
)) {
5641 *Progress
= TmpPtr
- 1;
5648 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
5650 FreePool (TmpBuffer
);
5652 StringPtr
+= Length
;
5653 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
5654 *Progress
= TmpPtr
- 1;
5655 Status
= EFI_INVALID_PARAMETER
;
5658 StringPtr
+= StrLen (L
"&WIDTH=");
5663 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
5664 if (EFI_ERROR (Status
)) {
5665 *Progress
= TmpPtr
- 1;
5672 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
5674 FreePool (TmpBuffer
);
5676 StringPtr
+= Length
;
5677 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
5678 *Progress
= TmpPtr
- 1;
5679 Status
= EFI_INVALID_PARAMETER
;
5684 // Calculate Value and convert it to hex string.
5686 if (Offset
+ Width
> BlockSize
) {
5687 *Progress
= StringPtr
;
5688 Status
= EFI_DEVICE_ERROR
;
5692 Value
= (UINT8
*) AllocateZeroPool (Width
);
5693 if (Value
== NULL
) {
5694 *Progress
= ConfigRequest
;
5695 Status
= EFI_OUT_OF_RESOURCES
;
5699 CopyMem (Value
, (UINT8
*) Block
+ Offset
, Width
);
5701 Length
= Width
* 2 + 1;
5702 ValueStr
= (EFI_STRING
) AllocateZeroPool (Length
* sizeof (CHAR16
));
5703 if (ValueStr
== NULL
) {
5704 *Progress
= ConfigRequest
;
5705 Status
= EFI_OUT_OF_RESOURCES
;
5709 TemString
= ValueStr
;
5710 TemBuffer
= Value
+ Width
- 1;
5711 for (Index
= 0; Index
< Width
; Index
++, TemBuffer
--) {
5712 UnicodeValueToStringS (
5714 Length
* sizeof (CHAR16
) - ((UINTN
)TemString
- (UINTN
)ValueStr
),
5715 PREFIX_ZERO
| RADIX_HEX
,
5719 TemString
+= StrnLenS (TemString
, Length
- ((UINTN
)TemString
- (UINTN
)ValueStr
) / sizeof (CHAR16
));
5726 // Build a ConfigElement
5728 Length
+= StringPtr
- TmpPtr
+ 1 + StrLen (L
"VALUE=");
5729 ConfigElement
= (EFI_STRING
) AllocateZeroPool (Length
* sizeof (CHAR16
));
5730 if (ConfigElement
== NULL
) {
5731 Status
= EFI_OUT_OF_RESOURCES
;
5734 CopyMem (ConfigElement
, TmpPtr
, (StringPtr
- TmpPtr
+ 1) * sizeof (CHAR16
));
5735 if (*StringPtr
== 0) {
5736 *(ConfigElement
+ (StringPtr
- TmpPtr
)) = L
'&';
5738 *(ConfigElement
+ (StringPtr
- TmpPtr
) + 1) = 0;
5739 StrCatS (ConfigElement
, Length
, L
"VALUE=");
5740 StrCatS (ConfigElement
, Length
, ValueStr
);
5742 AppendToMultiString (Config
, ConfigElement
);
5744 FreePool (ConfigElement
);
5745 FreePool (ValueStr
);
5746 ConfigElement
= NULL
;
5750 // If '\0', parsing is finished. Otherwise skip '&' to continue
5752 if (*StringPtr
== 0) {
5755 AppendToMultiString (Config
, L
"&");
5760 if (*StringPtr
!= 0) {
5761 *Progress
= StringPtr
- 1;
5762 Status
= EFI_INVALID_PARAMETER
;
5766 HiiToLower (*Config
);
5767 *Progress
= StringPtr
;
5771 if (*Config
!= NULL
) {
5775 if (ValueStr
!= NULL
) {
5776 FreePool (ValueStr
);
5778 if (Value
!= NULL
) {
5781 if (ConfigElement
!= NULL
) {
5782 FreePool (ConfigElement
);
5791 This helper function is to be called by drivers to map configuration strings
5792 to configurations stored in byte array ("block") formats such as UEFI Variables.
5794 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
5796 @param ConfigResp A null-terminated Unicode string in <ConfigResp>
5798 @param Block A possibly null array of bytes representing the
5799 current block. Only bytes referenced in the
5800 ConfigResp string in the block are modified. If
5801 this parameter is null or if the *BlockSize
5802 parameter is (on input) shorter than required by
5803 the Configuration string, only the BlockSize
5804 parameter is updated and an appropriate status
5805 (see below) is returned.
5806 @param BlockSize The length of the Block in units of UINT8. On
5807 input, this is the size of the Block. On output,
5808 if successful, contains the largest index of the
5809 modified byte in the Block, or the required buffer
5810 size if the Block is not large enough.
5811 @param Progress On return, points to an element of the ConfigResp
5812 string filled in with the offset of the most
5813 recent '&' before the first failing name / value
5814 pair (or the beginning of the string if the
5815 failure is in the first name / value pair) or the
5816 terminating NULL if all was successful.
5818 @retval EFI_SUCCESS The request succeeded. Progress points to the null
5819 terminator at the end of the ConfigResp string.
5820 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress
5821 points to the first character of ConfigResp.
5822 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigResp or
5823 Block parameter would result in this type of
5824 error. Progress points to the first character of
5826 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted name /
5827 value pair. Block is left updated and
5828 Progress points at the '&' preceding the first
5830 @retval EFI_BUFFER_TOO_SMALL Block not large enough. Progress undefined.
5831 BlockSize is updated with the required buffer size.
5832 @retval EFI_NOT_FOUND Target for the specified routing data was not found.
5833 Progress points to the "G" in "GUID" of the errant
5840 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
5841 IN CONST EFI_STRING ConfigResp
,
5842 IN OUT UINT8
*Block
,
5843 IN OUT UINTN
*BlockSize
,
5844 OUT EFI_STRING
*Progress
5847 HII_DATABASE_PRIVATE_DATA
*Private
;
5848 EFI_STRING StringPtr
;
5861 if (This
== NULL
|| BlockSize
== NULL
|| Progress
== NULL
) {
5862 return EFI_INVALID_PARAMETER
;
5865 *Progress
= ConfigResp
;
5866 if (ConfigResp
== NULL
) {
5867 return EFI_INVALID_PARAMETER
;
5870 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
5871 ASSERT (Private
!= NULL
);
5873 StringPtr
= ConfigResp
;
5874 BufferSize
= *BlockSize
;
5881 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
5882 *Progress
= StringPtr
;
5883 Status
= EFI_INVALID_PARAMETER
;
5886 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"PATH=", StrLen (L
"PATH=")) != 0) {
5889 if (*StringPtr
== 0) {
5890 *Progress
= StringPtr
;
5891 Status
= EFI_INVALID_PARAMETER
;
5895 while (*StringPtr
!= L
'&' && *StringPtr
!= 0) {
5898 if (*StringPtr
== 0) {
5899 *Progress
= StringPtr
;
5900 Status
= EFI_INVALID_PARAMETER
;
5905 // Parse each <ConfigElement> if exists
5906 // Only '&'<BlockConfig> format is supported by this help function.
5907 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE='<Number>
5909 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) == 0) {
5911 StringPtr
+= StrLen (L
"&OFFSET=");
5915 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
5916 if (EFI_ERROR (Status
)) {
5924 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
5926 FreePool (TmpBuffer
);
5928 StringPtr
+= Length
;
5929 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
5931 Status
= EFI_INVALID_PARAMETER
;
5934 StringPtr
+= StrLen (L
"&WIDTH=");
5939 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
5940 if (EFI_ERROR (Status
)) {
5948 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
5950 FreePool (TmpBuffer
);
5952 StringPtr
+= Length
;
5953 if (StrnCmp (StringPtr
, L
"&VALUE=", StrLen (L
"&VALUE=")) != 0) {
5955 Status
= EFI_INVALID_PARAMETER
;
5958 StringPtr
+= StrLen (L
"&VALUE=");
5963 Status
= GetValueOfNumber (StringPtr
, &Value
, &Length
);
5964 if (EFI_ERROR (Status
)) {
5969 StringPtr
+= Length
;
5970 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
5972 Status
= EFI_INVALID_PARAMETER
;
5977 // Update the Block with configuration info
5979 if ((Block
!= NULL
) && (Offset
+ Width
<= BufferSize
)) {
5980 CopyMem (Block
+ Offset
, Value
, Width
);
5982 if (Offset
+ Width
> MaxBlockSize
) {
5983 MaxBlockSize
= Offset
+ Width
;
5990 // If '\0', parsing is finished.
5992 if (*StringPtr
== 0) {
5998 // The input string is not ConfigResp format, return error.
6000 if (*StringPtr
!= 0) {
6001 *Progress
= StringPtr
;
6002 Status
= EFI_INVALID_PARAMETER
;
6006 *Progress
= StringPtr
+ StrLen (StringPtr
);
6007 *BlockSize
= MaxBlockSize
- 1;
6009 if (MaxBlockSize
> BufferSize
) {
6010 *BlockSize
= MaxBlockSize
;
6011 if (Block
!= NULL
) {
6012 return EFI_BUFFER_TOO_SMALL
;
6016 if (Block
== NULL
) {
6017 *Progress
= ConfigResp
;
6018 return EFI_INVALID_PARAMETER
;
6025 if (Value
!= NULL
) {
6033 This helper function is to be called by drivers to extract portions of
6034 a larger configuration string.
6036 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
6038 @param Configuration A null-terminated Unicode string in
6039 <MultiConfigAltResp> format.
6040 @param Guid A pointer to the GUID value to search for in the
6041 routing portion of the ConfigResp string when
6042 retrieving the requested data. If Guid is NULL,
6043 then all GUID values will be searched for.
6044 @param Name A pointer to the NAME value to search for in the
6045 routing portion of the ConfigResp string when
6046 retrieving the requested data. If Name is NULL,
6047 then all Name values will be searched for.
6048 @param DevicePath A pointer to the PATH value to search for in the
6049 routing portion of the ConfigResp string when
6050 retrieving the requested data. If DevicePath is
6051 NULL, then all DevicePath values will be searched
6053 @param AltCfgId A pointer to the ALTCFG value to search for in the
6054 routing portion of the ConfigResp string when
6055 retrieving the requested data. If this parameter
6056 is NULL, then the current setting will be
6058 @param AltCfgResp A pointer to a buffer which will be allocated by
6059 the function which contains the retrieved string
6060 as requested. This buffer is only allocated if
6061 the call was successful. It is <ConfigResp> format.
6063 @retval EFI_SUCCESS The request succeeded. The requested data was
6064 extracted and placed in the newly allocated
6066 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate AltCfgResp.
6067 @retval EFI_INVALID_PARAMETER Any parameter is invalid.
6068 @retval EFI_NOT_FOUND Target for the specified routing data was not
6075 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
6076 IN CONST EFI_STRING Configuration
,
6077 IN CONST EFI_GUID
*Guid
,
6078 IN CONST EFI_STRING Name
,
6079 IN CONST EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
6080 IN CONST UINT16
*AltCfgId
,
6081 OUT EFI_STRING
*AltCfgResp
6085 EFI_STRING StringPtr
;
6086 EFI_STRING HdrStart
;
6093 EFI_STRING AltIdStr
;
6110 if (This
== NULL
|| Configuration
== NULL
|| AltCfgResp
== NULL
) {
6111 return EFI_INVALID_PARAMETER
;
6114 StringPtr
= Configuration
;
6115 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
6116 return EFI_INVALID_PARAMETER
;
6120 // Generate the sub string for later matching.
6122 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*) Guid
, 1, &GuidStr
);
6125 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) DevicePath
),
6126 (VOID
*) DevicePath
,
6130 if (AltCfgId
!= NULL
) {
6131 GenerateSubStr (L
"ALTCFG=", sizeof (UINT16
), (VOID
*) AltCfgId
, 3, &AltIdStr
);
6134 GenerateSubStr (L
"NAME=", StrLen (Name
) * sizeof (CHAR16
), (VOID
*) Name
, 2, &NameStr
);
6136 GenerateSubStr (L
"NAME=", 0, NULL
, 2, &NameStr
);
6139 while (*StringPtr
!= 0) {
6141 // Try to match the GUID
6144 TmpPtr
= StrStr (StringPtr
, GuidStr
);
6145 if (TmpPtr
== NULL
) {
6146 Status
= EFI_NOT_FOUND
;
6152 // Jump to <NameHdr>
6155 StringPtr
= TmpPtr
+ StrLen (GuidStr
);
6157 StringPtr
= StrStr (TmpPtr
, L
"NAME=");
6158 if (StringPtr
== NULL
) {
6159 Status
= EFI_NOT_FOUND
;
6167 // Try to match the NAME
6169 if (GuidFlag
&& !NameFlag
) {
6170 if (StrnCmp (StringPtr
, NameStr
, StrLen (NameStr
)) != 0) {
6174 // Jump to <PathHdr>
6177 StringPtr
+= StrLen (NameStr
);
6179 StringPtr
= StrStr (StringPtr
, L
"PATH=");
6180 if (StringPtr
== NULL
) {
6181 Status
= EFI_NOT_FOUND
;
6190 // Try to match the DevicePath
6192 if (GuidFlag
&& NameFlag
&& !PathFlag
) {
6193 if (StrnCmp (StringPtr
, PathStr
, StrLen (PathStr
)) != 0) {
6198 // Jump to '&' before <DescHdr> or <ConfigBody>
6200 if (DevicePath
!= NULL
) {
6201 StringPtr
+= StrLen (PathStr
);
6203 StringPtr
= StrStr (StringPtr
, L
"&");
6204 if (StringPtr
== NULL
) {
6205 Status
= EFI_NOT_FOUND
;
6216 // Try to match the AltCfgId
6218 if (GuidFlag
&& NameFlag
&& PathFlag
) {
6219 if (AltCfgId
== NULL
) {
6221 // Return Current Setting when AltCfgId is NULL.
6223 Status
= OutputConfigBody (StringPtr
, &Result
);
6227 // Search the <ConfigAltResp> to get the <AltResp> with AltCfgId.
6229 if (StrnCmp (StringPtr
, AltIdStr
, StrLen (AltIdStr
)) != 0) {
6235 // Skip AltIdStr and &
6237 StringPtr
= StringPtr
+ StrLen (AltIdStr
);
6238 Status
= OutputConfigBody (StringPtr
, &Result
);
6244 Status
= EFI_NOT_FOUND
;
6248 if (!EFI_ERROR (Status
) && (Result
!= NULL
)) {
6250 // Copy the <ConfigHdr> and <ConfigBody>
6252 Length
= HdrEnd
- HdrStart
+ StrLen (Result
) + 1;
6253 *AltCfgResp
= AllocateZeroPool (Length
* sizeof (CHAR16
));
6254 if (*AltCfgResp
== NULL
) {
6255 Status
= EFI_OUT_OF_RESOURCES
;
6257 StrnCpyS (*AltCfgResp
, Length
, HdrStart
, HdrEnd
- HdrStart
);
6258 StrCatS (*AltCfgResp
, Length
, Result
);
6259 Status
= EFI_SUCCESS
;
6263 if (GuidStr
!= NULL
) {
6266 if (NameStr
!= NULL
) {
6269 if (PathStr
!= NULL
) {
6272 if (AltIdStr
!= NULL
) {
6273 FreePool (AltIdStr
);
6275 if (Result
!= NULL
) {