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
) {
1230 // Insert this block data in the front of block array
1232 InsertTailList (Link
, &BlockSingleData
->Entry
);
1236 if (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.
1984 @retval EFI_SUCCESS This opcode is required.
1985 @retval EFI_NOT_FOUND This opcode is not required.
1986 @retval Others Contain some error.
1990 IsThisOpcodeRequired (
1991 IN IFR_BLOCK_DATA
*RequestBlockArray
,
1992 IN EFI_HII_HANDLE HiiHandle
,
1993 IN OUT IFR_VARSTORAGE_DATA
*VarStorageData
,
1994 IN EFI_IFR_OP_HEADER
*IfrOpHdr
,
1996 OUT IFR_BLOCK_DATA
**ReturnData
1999 IFR_BLOCK_DATA
*BlockData
;
2001 EFI_STRING_ID NameId
;
2002 EFI_IFR_QUESTION_HEADER
*IfrQuestionHdr
;
2006 IfrQuestionHdr
= (EFI_IFR_QUESTION_HEADER
*)((CHAR8
*) IfrOpHdr
+ sizeof (EFI_IFR_OP_HEADER
));
2008 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2009 NameId
= IfrQuestionHdr
->VarStoreInfo
.VarName
;
2012 // Check whether this question is in requested block array.
2014 if (!BlockArrayCheck (RequestBlockArray
, NameId
, 0, TRUE
, HiiHandle
)) {
2016 // This question is not in the requested string. Skip it.
2018 return EFI_NOT_FOUND
;
2021 VarOffset
= IfrQuestionHdr
->VarStoreInfo
.VarOffset
;
2024 // Check whether this question is in requested block array.
2026 if (!BlockArrayCheck (RequestBlockArray
, VarOffset
, VarWidth
, FALSE
, HiiHandle
)) {
2028 // This question is not in the requested string. Skip it.
2030 return EFI_NOT_FOUND
;
2034 // Check this var question is in the var storage
2036 if (((VarOffset
+ VarWidth
) > VarStorageData
->Size
)) {
2037 return EFI_INVALID_PARAMETER
;
2041 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
2042 if (BlockData
== NULL
) {
2043 return EFI_OUT_OF_RESOURCES
;
2046 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2047 BlockData
->Name
= InternalGetString(HiiHandle
, NameId
);
2049 BlockData
->Offset
= VarOffset
;
2052 BlockData
->Width
= VarWidth
;
2053 BlockData
->QuestionId
= IfrQuestionHdr
->QuestionId
;
2054 BlockData
->OpCode
= IfrOpHdr
->OpCode
;
2055 BlockData
->Scope
= IfrOpHdr
->Scope
;
2056 InitializeListHead (&BlockData
->DefaultValueEntry
);
2058 // Add Block Data into VarStorageData BlockEntry
2060 InsertBlockData (&VarStorageData
->BlockEntry
, &BlockData
);
2061 *ReturnData
= BlockData
;
2067 This function parses Form Package to get the block array and the default
2068 value array according to the request ConfigHdr.
2070 @param HiiHandle Hii Handle for this hii package.
2071 @param Package Pointer to the form package data.
2072 @param PackageLength Length of the package.
2073 @param ConfigHdr Request string ConfigHdr. If it is NULL,
2074 the first found varstore will be as ConfigHdr.
2075 @param RequestBlockArray The block array is retrieved from the request string.
2076 @param VarStorageData VarStorage structure contains the got block and default value.
2077 @param DefaultIdArray Point to the got default id and default name array.
2079 @retval EFI_SUCCESS The block array and the default value array are got.
2080 @retval EFI_INVALID_PARAMETER The varstore definition in the different form packages
2082 @retval EFI_OUT_OF_RESOURCES No enough memory.
2087 IN EFI_HII_HANDLE HiiHandle
,
2089 IN UINT32 PackageLength
,
2090 IN EFI_STRING ConfigHdr
,
2091 IN IFR_BLOCK_DATA
*RequestBlockArray
,
2092 IN OUT IFR_VARSTORAGE_DATA
*VarStorageData
,
2093 OUT IFR_DEFAULT_DATA
*DefaultIdArray
2098 UINTN PackageOffset
;
2099 EFI_IFR_VARSTORE
*IfrVarStore
;
2100 EFI_IFR_VARSTORE_EFI
*IfrEfiVarStore
;
2101 EFI_IFR_OP_HEADER
*IfrOpHdr
;
2102 EFI_IFR_ONE_OF
*IfrOneOf
;
2103 EFI_IFR_REF4
*IfrRef
;
2104 EFI_IFR_ONE_OF_OPTION
*IfrOneOfOption
;
2105 EFI_IFR_DEFAULT
*IfrDefault
;
2106 EFI_IFR_ORDERED_LIST
*IfrOrderedList
;
2107 EFI_IFR_CHECKBOX
*IfrCheckBox
;
2108 EFI_IFR_PASSWORD
*IfrPassword
;
2109 EFI_IFR_STRING
*IfrString
;
2110 EFI_IFR_DATE
*IfrDate
;
2111 EFI_IFR_TIME
*IfrTime
;
2112 IFR_DEFAULT_DATA DefaultData
;
2113 IFR_DEFAULT_DATA
*DefaultDataPtr
;
2114 IFR_BLOCK_DATA
*BlockData
;
2115 CHAR16
*VarStoreName
;
2118 UINT16 VarDefaultId
;
2119 BOOLEAN FirstOneOfOption
;
2120 BOOLEAN FirstOrderedList
;
2121 LIST_ENTRY
*LinkData
;
2122 LIST_ENTRY
*LinkDefault
;
2123 EFI_IFR_VARSTORE_NAME_VALUE
*IfrNameValueVarStore
;
2124 EFI_HII_PACKAGE_HEADER
*PackageHeader
;
2125 EFI_VARSTORE_ID VarStoreId
;
2126 UINT16 SmallestDefaultId
;
2127 BOOLEAN SmallestIdFromFlag
;
2128 BOOLEAN FromOtherDefaultOpcode
;
2130 Status
= EFI_SUCCESS
;
2132 DefaultDataPtr
= NULL
;
2133 FirstOneOfOption
= FALSE
;
2135 FirstOrderedList
= FALSE
;
2136 VarStoreName
= NULL
;
2137 ZeroMem (&DefaultData
, sizeof (IFR_DEFAULT_DATA
));
2138 SmallestDefaultId
= 0xFFFF;
2139 FromOtherDefaultOpcode
= FALSE
;
2142 // Go through the form package to parse OpCode one by one.
2144 PackageOffset
= sizeof (EFI_HII_PACKAGE_HEADER
);
2145 PackageHeader
= (EFI_HII_PACKAGE_HEADER
*) Package
;
2146 IfrOffset
= PackageOffset
;
2147 while (IfrOffset
< PackageLength
) {
2150 // More than one form package found.
2152 if (PackageOffset
>= PackageHeader
->Length
) {
2154 // Already found varstore for this request, break;
2156 if (VarStoreId
!= 0) {
2161 // Get next package header info.
2163 IfrOffset
+= sizeof (EFI_HII_PACKAGE_HEADER
);
2164 PackageOffset
= sizeof (EFI_HII_PACKAGE_HEADER
);
2165 PackageHeader
= (EFI_HII_PACKAGE_HEADER
*) (Package
+ IfrOffset
);
2168 IfrOpHdr
= (EFI_IFR_OP_HEADER
*) (Package
+ IfrOffset
);
2169 switch (IfrOpHdr
->OpCode
) {
2170 case EFI_IFR_VARSTORE_OP
:
2172 // VarStore is found. Don't need to search any more.
2174 if (VarStoreId
!= 0) {
2178 IfrVarStore
= (EFI_IFR_VARSTORE
*) IfrOpHdr
;
2180 NameSize
= AsciiStrSize ((CHAR8
*)IfrVarStore
->Name
);
2181 VarStoreName
= AllocateZeroPool (NameSize
* sizeof (CHAR16
));
2182 if (VarStoreName
== NULL
) {
2183 Status
= EFI_OUT_OF_RESOURCES
;
2186 AsciiStrToUnicodeStrS ((CHAR8
*)IfrVarStore
->Name
, VarStoreName
, NameSize
);
2188 if (IsThisVarstore((VOID
*)&IfrVarStore
->Guid
, VarStoreName
, ConfigHdr
)) {
2190 // Find the matched VarStore
2192 CopyGuid (&VarStorageData
->Guid
, (EFI_GUID
*) (VOID
*) &IfrVarStore
->Guid
);
2193 VarStorageData
->Size
= IfrVarStore
->Size
;
2194 VarStorageData
->Name
= VarStoreName
;
2195 VarStorageData
->Type
= EFI_HII_VARSTORE_BUFFER
;
2196 VarStoreId
= IfrVarStore
->VarStoreId
;
2198 FreePool (VarStoreName
);
2199 VarStoreName
= NULL
;
2203 case EFI_IFR_VARSTORE_EFI_OP
:
2205 // VarStore is found. Don't need to search any more.
2207 if (VarStoreId
!= 0) {
2211 IfrEfiVarStore
= (EFI_IFR_VARSTORE_EFI
*) IfrOpHdr
;
2214 // If the length is small than the structure, this is from old efi
2215 // varstore definition. Old efi varstore get config directly from
2216 // GetVariable function.
2218 if (IfrOpHdr
->Length
< sizeof (EFI_IFR_VARSTORE_EFI
)) {
2222 NameSize
= AsciiStrSize ((CHAR8
*)IfrEfiVarStore
->Name
);
2223 VarStoreName
= AllocateZeroPool (NameSize
* sizeof (CHAR16
));
2224 if (VarStoreName
== NULL
) {
2225 Status
= EFI_OUT_OF_RESOURCES
;
2228 AsciiStrToUnicodeStrS ((CHAR8
*)IfrEfiVarStore
->Name
, VarStoreName
, NameSize
);
2230 if (IsThisVarstore (&IfrEfiVarStore
->Guid
, VarStoreName
, ConfigHdr
)) {
2232 // Find the matched VarStore
2234 CopyGuid (&VarStorageData
->Guid
, (EFI_GUID
*) (VOID
*) &IfrEfiVarStore
->Guid
);
2235 VarStorageData
->Size
= IfrEfiVarStore
->Size
;
2236 VarStorageData
->Name
= VarStoreName
;
2237 VarStorageData
->Type
= EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
;
2238 VarStoreId
= IfrEfiVarStore
->VarStoreId
;
2240 FreePool (VarStoreName
);
2241 VarStoreName
= NULL
;
2245 case EFI_IFR_VARSTORE_NAME_VALUE_OP
:
2247 // VarStore is found. Don't need to search any more.
2249 if (VarStoreId
!= 0) {
2253 IfrNameValueVarStore
= (EFI_IFR_VARSTORE_NAME_VALUE
*) IfrOpHdr
;
2255 if (IsThisVarstore (&IfrNameValueVarStore
->Guid
, NULL
, ConfigHdr
)) {
2257 // Find the matched VarStore
2259 CopyGuid (&VarStorageData
->Guid
, (EFI_GUID
*) (VOID
*) &IfrNameValueVarStore
->Guid
);
2260 VarStorageData
->Type
= EFI_HII_VARSTORE_NAME_VALUE
;
2261 VarStoreId
= IfrNameValueVarStore
->VarStoreId
;
2265 case EFI_IFR_DEFAULTSTORE_OP
:
2267 // Add new the map between default id and default name.
2269 DefaultDataPtr
= (IFR_DEFAULT_DATA
*) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
2270 if (DefaultDataPtr
== NULL
) {
2271 Status
= EFI_OUT_OF_RESOURCES
;
2274 DefaultDataPtr
->DefaultId
= ((EFI_IFR_DEFAULTSTORE
*) IfrOpHdr
)->DefaultId
;
2275 InsertTailList (&DefaultIdArray
->Entry
, &DefaultDataPtr
->Entry
);
2276 DefaultDataPtr
= NULL
;
2279 case EFI_IFR_FORM_OP
:
2280 case EFI_IFR_FORM_MAP_OP
:
2282 // No matched varstore is found and directly return.
2284 if ( VarStoreId
== 0) {
2285 Status
= EFI_SUCCESS
;
2290 case EFI_IFR_REF_OP
:
2292 // Ref question is not in IFR Form. This IFR form is not valid.
2294 if ( VarStoreId
== 0) {
2295 Status
= EFI_INVALID_PARAMETER
;
2299 // Check whether this question is for the requested varstore.
2301 IfrRef
= (EFI_IFR_REF4
*) IfrOpHdr
;
2302 if (IfrRef
->Question
.VarStoreId
!= VarStoreId
) {
2305 VarWidth
= (UINT16
) (sizeof (EFI_HII_REF
));
2308 // The BlockData may allocate by other opcode,need to clean.
2310 if (BlockData
!= NULL
){
2314 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
2315 if (EFI_ERROR (Status
)) {
2316 if (Status
== EFI_NOT_FOUND
){
2318 //The opcode is not required,exit and parse other opcode.
2326 case EFI_IFR_ONE_OF_OP
:
2327 case EFI_IFR_NUMERIC_OP
:
2329 // Numeric and OneOf has the same opcode structure.
2333 // Numeric and OneOf question is not in IFR Form. This IFR form is not valid.
2335 if (VarStoreId
== 0) {
2336 Status
= EFI_INVALID_PARAMETER
;
2340 // Check whether this question is for the requested varstore.
2342 IfrOneOf
= (EFI_IFR_ONE_OF
*) IfrOpHdr
;
2343 if (IfrOneOf
->Question
.VarStoreId
!= VarStoreId
) {
2346 VarWidth
= (UINT16
) (1 << (IfrOneOf
->Flags
& EFI_IFR_NUMERIC_SIZE
));
2349 // The BlockData may allocate by other opcode,need to clean.
2351 if (BlockData
!= NULL
){
2355 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
2356 if (EFI_ERROR (Status
)) {
2357 if (Status
== EFI_NOT_FOUND
){
2359 //The opcode is not required,exit and parse other opcode.
2367 //when go to there,BlockData can't be NULLL.
2369 ASSERT (BlockData
!= NULL
);
2371 if (IfrOpHdr
->OpCode
== EFI_IFR_ONE_OF_OP
) {
2373 // Set this flag to TRUE for the first oneof option.
2375 FirstOneOfOption
= TRUE
;
2376 } else if (IfrOpHdr
->OpCode
== EFI_IFR_NUMERIC_OP
) {
2378 // Numeric minimum value will be used as default value when no default is specified.
2380 DefaultData
.Type
= DefaultValueFromDefault
;
2381 switch (IfrOneOf
->Flags
& EFI_IFR_NUMERIC_SIZE
) {
2382 case EFI_IFR_NUMERIC_SIZE_1
:
2383 DefaultData
.Value
.u8
= IfrOneOf
->data
.u8
.MinValue
;
2386 case EFI_IFR_NUMERIC_SIZE_2
:
2387 CopyMem (&DefaultData
.Value
.u16
, &IfrOneOf
->data
.u16
.MinValue
, sizeof (UINT16
));
2390 case EFI_IFR_NUMERIC_SIZE_4
:
2391 CopyMem (&DefaultData
.Value
.u32
, &IfrOneOf
->data
.u32
.MinValue
, sizeof (UINT32
));
2394 case EFI_IFR_NUMERIC_SIZE_8
:
2395 CopyMem (&DefaultData
.Value
.u64
, &IfrOneOf
->data
.u64
.MinValue
, sizeof (UINT64
));
2399 Status
= EFI_INVALID_PARAMETER
;
2403 // Set default value base on the DefaultId list get from IFR data.
2405 for (LinkData
= DefaultIdArray
->Entry
.ForwardLink
; LinkData
!= &DefaultIdArray
->Entry
; LinkData
= LinkData
->ForwardLink
) {
2406 DefaultDataPtr
= BASE_CR (LinkData
, IFR_DEFAULT_DATA
, Entry
);
2407 DefaultData
.DefaultId
= DefaultDataPtr
->DefaultId
;
2408 InsertDefaultValue (BlockData
, &DefaultData
);
2413 case EFI_IFR_ORDERED_LIST_OP
:
2415 // offset by question header
2416 // width by EFI_IFR_ORDERED_LIST MaxContainers * OneofOption Type
2419 FirstOrderedList
= TRUE
;
2421 // OrderedList question is not in IFR Form. This IFR form is not valid.
2423 if (VarStoreId
== 0) {
2424 Status
= EFI_INVALID_PARAMETER
;
2428 // Check whether this question is for the requested varstore.
2430 IfrOrderedList
= (EFI_IFR_ORDERED_LIST
*) IfrOpHdr
;
2431 if (IfrOrderedList
->Question
.VarStoreId
!= VarStoreId
) {
2435 VarWidth
= IfrOrderedList
->MaxContainers
;
2438 // The BlockData may allocate by other opcode,need to clean.
2440 if (BlockData
!= NULL
){
2444 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
2445 if (EFI_ERROR (Status
)) {
2446 if (Status
== EFI_NOT_FOUND
){
2448 //The opcode is not required,exit and parse other opcode.
2456 case EFI_IFR_CHECKBOX_OP
:
2458 // EFI_IFR_DEFAULT_OP
2459 // offset by question header
2460 // width is 1 sizeof (BOOLEAN)
2461 // default id by CheckBox Flags if CheckBox flags (Default or Mau) is set, the default value is 1 to be set.
2462 // value by DefaultOption
2463 // default id by DeaultOption DefaultId can override CheckBox Flags and Default value.
2467 // CheckBox question is not in IFR Form. This IFR form is not valid.
2469 if (VarStoreId
== 0) {
2470 Status
= EFI_INVALID_PARAMETER
;
2474 // Check whether this question is for the requested varstore.
2476 IfrCheckBox
= (EFI_IFR_CHECKBOX
*) IfrOpHdr
;
2477 if (IfrCheckBox
->Question
.VarStoreId
!= VarStoreId
) {
2480 VarWidth
= (UINT16
) sizeof (BOOLEAN
);
2483 // The BlockData may allocate by other opcode,need to clean.
2485 if (BlockData
!= NULL
){
2489 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
2490 if (EFI_ERROR (Status
)) {
2491 if (Status
== EFI_NOT_FOUND
){
2493 //The opcode is not required,exit and parse other opcode.
2501 //when go to there,BlockData can't be NULLL.
2503 ASSERT (BlockData
!= NULL
);
2505 SmallestIdFromFlag
= FALSE
;
2508 // Add default value for standard ID by CheckBox Flag
2510 VarDefaultId
= EFI_HII_DEFAULT_CLASS_STANDARD
;
2512 // Prepare new DefaultValue
2514 DefaultData
.DefaultId
= VarDefaultId
;
2515 if ((IfrCheckBox
->Flags
& EFI_IFR_CHECKBOX_DEFAULT
) == EFI_IFR_CHECKBOX_DEFAULT
) {
2517 // When flag is set, default value is TRUE.
2519 DefaultData
.Type
= DefaultValueFromFlag
;
2520 DefaultData
.Value
.b
= TRUE
;
2521 InsertDefaultValue (BlockData
, &DefaultData
);
2523 if (SmallestDefaultId
> EFI_HII_DEFAULT_CLASS_STANDARD
) {
2525 // Record the SmallestDefaultId and update the SmallestIdFromFlag.
2527 SmallestDefaultId
= EFI_HII_DEFAULT_CLASS_STANDARD
;
2528 SmallestIdFromFlag
= TRUE
;
2533 // Add default value for Manufacture ID by CheckBox Flag
2535 VarDefaultId
= EFI_HII_DEFAULT_CLASS_MANUFACTURING
;
2537 // Prepare new DefaultValue
2539 DefaultData
.DefaultId
= VarDefaultId
;
2540 if ((IfrCheckBox
->Flags
& EFI_IFR_CHECKBOX_DEFAULT_MFG
) == EFI_IFR_CHECKBOX_DEFAULT_MFG
) {
2542 // When flag is set, default value is TRUE.
2544 DefaultData
.Type
= DefaultValueFromFlag
;
2545 DefaultData
.Value
.b
= TRUE
;
2546 InsertDefaultValue (BlockData
, &DefaultData
);
2548 if (SmallestDefaultId
> EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
2550 // Record the SmallestDefaultId and update the SmallestIdFromFlag.
2552 SmallestDefaultId
= EFI_HII_DEFAULT_CLASS_MANUFACTURING
;
2553 SmallestIdFromFlag
= TRUE
;
2556 if (SmallestIdFromFlag
) {
2558 // When smallest default Id is given by the flag of CheckBox, set default value with TRUE for other default Id in the DefaultId list.
2560 DefaultData
.Type
= DefaultValueFromOtherDefault
;
2561 DefaultData
.Value
.b
= TRUE
;
2563 // Set default value for all the default id in the DefaultId list.
2565 for (LinkData
= DefaultIdArray
->Entry
.ForwardLink
; LinkData
!= &DefaultIdArray
->Entry
; LinkData
= LinkData
->ForwardLink
) {
2566 DefaultDataPtr
= BASE_CR (LinkData
, IFR_DEFAULT_DATA
, Entry
);
2567 DefaultData
.DefaultId
= DefaultDataPtr
->DefaultId
;
2568 InsertDefaultValue (BlockData
, &DefaultData
);
2572 // When flag is not set, default value is FASLE.
2574 DefaultData
.Type
= DefaultValueFromDefault
;
2575 DefaultData
.Value
.b
= FALSE
;
2577 // Set default value for all the default id in the DefaultId list.
2579 for (LinkData
= DefaultIdArray
->Entry
.ForwardLink
; LinkData
!= &DefaultIdArray
->Entry
; LinkData
= LinkData
->ForwardLink
) {
2580 DefaultDataPtr
= BASE_CR (LinkData
, IFR_DEFAULT_DATA
, Entry
);
2581 DefaultData
.DefaultId
= DefaultDataPtr
->DefaultId
;
2582 InsertDefaultValue (BlockData
, &DefaultData
);
2587 case EFI_IFR_DATE_OP
:
2589 // offset by question header
2590 // width MaxSize * sizeof (CHAR16)
2591 // no default value, only block array
2595 // Date question is not in IFR Form. This IFR form is not valid.
2597 if (VarStoreId
== 0) {
2598 Status
= EFI_INVALID_PARAMETER
;
2602 // Check whether this question is for the requested varstore.
2604 IfrDate
= (EFI_IFR_DATE
*) IfrOpHdr
;
2605 if (IfrDate
->Question
.VarStoreId
!= VarStoreId
) {
2610 // The BlockData may allocate by other opcode,need to clean.
2612 if (BlockData
!= NULL
){
2616 VarWidth
= (UINT16
) sizeof (EFI_HII_DATE
);
2617 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
2618 if (EFI_ERROR (Status
)) {
2619 if (Status
== EFI_NOT_FOUND
){
2621 //The opcode is not required,exit and parse other opcode.
2629 case EFI_IFR_TIME_OP
:
2631 // offset by question header
2632 // width MaxSize * sizeof (CHAR16)
2633 // no default value, only block array
2637 // Time question is not in IFR Form. This IFR form is not valid.
2639 if (VarStoreId
== 0) {
2640 Status
= EFI_INVALID_PARAMETER
;
2644 // Check whether this question is for the requested varstore.
2646 IfrTime
= (EFI_IFR_TIME
*) IfrOpHdr
;
2647 if (IfrTime
->Question
.VarStoreId
!= VarStoreId
) {
2652 // The BlockData may allocate by other opcode,need to clean.
2654 if (BlockData
!= NULL
){
2658 VarWidth
= (UINT16
) sizeof (EFI_HII_TIME
);
2659 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
2660 if (EFI_ERROR (Status
)) {
2661 if (Status
== EFI_NOT_FOUND
){
2663 //The opcode is not required,exit and parse other opcode.
2671 case EFI_IFR_STRING_OP
:
2673 // offset by question header
2674 // width MaxSize * sizeof (CHAR16)
2675 // no default value, only block array
2679 // String question is not in IFR Form. This IFR form is not valid.
2681 if (VarStoreId
== 0) {
2682 Status
= EFI_INVALID_PARAMETER
;
2686 // Check whether this question is for the requested varstore.
2688 IfrString
= (EFI_IFR_STRING
*) IfrOpHdr
;
2689 if (IfrString
->Question
.VarStoreId
!= VarStoreId
) {
2694 // The BlockData may allocate by other opcode,need to clean.
2696 if (BlockData
!= NULL
){
2700 VarWidth
= (UINT16
) (IfrString
->MaxSize
* sizeof (UINT16
));
2701 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
2702 if (EFI_ERROR (Status
)) {
2703 if (Status
== EFI_NOT_FOUND
){
2705 //The opcode is not required,exit and parse other opcode.
2713 case EFI_IFR_PASSWORD_OP
:
2715 // offset by question header
2716 // width MaxSize * sizeof (CHAR16)
2717 // no default value, only block array
2721 // Password question is not in IFR Form. This IFR form is not valid.
2723 if (VarStoreId
== 0) {
2724 Status
= EFI_INVALID_PARAMETER
;
2728 // Check whether this question is for the requested varstore.
2730 IfrPassword
= (EFI_IFR_PASSWORD
*) IfrOpHdr
;
2731 if (IfrPassword
->Question
.VarStoreId
!= VarStoreId
) {
2736 // The BlockData may allocate by other opcode,need to clean.
2738 if (BlockData
!= NULL
){
2742 VarWidth
= (UINT16
) (IfrPassword
->MaxSize
* sizeof (UINT16
));
2743 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
2744 if (EFI_ERROR (Status
)) {
2745 if (Status
== EFI_NOT_FOUND
){
2747 //The opcode is not required,exit and parse other opcode.
2755 // No default value for string.
2760 case EFI_IFR_ONE_OF_OPTION_OP
:
2762 // No matched block data is ignored.
2764 if (BlockData
== NULL
|| BlockData
->Scope
== 0) {
2768 IfrOneOfOption
= (EFI_IFR_ONE_OF_OPTION
*) IfrOpHdr
;
2769 if (BlockData
->OpCode
== EFI_IFR_ORDERED_LIST_OP
) {
2771 if (!FirstOrderedList
){
2775 // Get ordered list option data type.
2777 if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_8
|| IfrOneOfOption
->Type
== EFI_IFR_TYPE_BOOLEAN
) {
2779 } else if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_16
) {
2781 } else if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_32
) {
2783 } else if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_64
) {
2787 // Invalid ordered list option data type.
2789 Status
= EFI_INVALID_PARAMETER
;
2790 if (BlockData
->Name
!= NULL
) {
2791 FreePool (BlockData
->Name
);
2793 FreePool (BlockData
);
2798 // Calculate Ordered list QuestionId width.
2800 BlockData
->Width
= (UINT16
) (BlockData
->Width
* VarWidth
);
2802 // Check whether this question is in requested block array.
2804 if (!BlockArrayCheck (RequestBlockArray
, BlockData
->Offset
, BlockData
->Width
, (BOOLEAN
)(BlockData
->Name
!= NULL
), HiiHandle
)) {
2806 // This question is not in the requested string. Skip it.
2808 if (BlockData
->Name
!= NULL
) {
2809 FreePool (BlockData
->Name
);
2811 FreePool (BlockData
);
2816 // Check this var question is in the var storage
2818 if ((BlockData
->Name
== NULL
) && ((BlockData
->Offset
+ BlockData
->Width
) > VarStorageData
->Size
)) {
2819 Status
= EFI_INVALID_PARAMETER
;
2820 if (BlockData
->Name
!= NULL
) {
2821 FreePool (BlockData
->Name
);
2823 FreePool (BlockData
);
2827 // Add Block Data into VarStorageData BlockEntry
2829 InsertBlockData (&VarStorageData
->BlockEntry
, &BlockData
);
2831 FirstOrderedList
= FALSE
;
2837 // 1. Set default value for OneOf option when flag field has default attribute.
2838 // And set the default value with the smallest default id for other default id in the DefaultId list.
2840 if (((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT
) == EFI_IFR_OPTION_DEFAULT
) ||
2841 ((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT_MFG
) == EFI_IFR_OPTION_DEFAULT_MFG
)) {
2843 // This flag is used to specify whether this option is the first. Set it to FALSE for the following options.
2844 // The first oneof option value will be used as default value when no default value is specified.
2846 FirstOneOfOption
= FALSE
;
2848 SmallestIdFromFlag
= FALSE
;
2850 // Prepare new DefaultValue
2852 DefaultData
.Type
= DefaultValueFromFlag
;
2853 CopyMem (&DefaultData
.Value
, &IfrOneOfOption
->Value
, IfrOneOfOption
->Header
.Length
- OFFSET_OF (EFI_IFR_ONE_OF_OPTION
, Value
));
2854 if ((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT
) == EFI_IFR_OPTION_DEFAULT
) {
2855 DefaultData
.DefaultId
= EFI_HII_DEFAULT_CLASS_STANDARD
;
2856 InsertDefaultValue (BlockData
, &DefaultData
);
2857 if (SmallestDefaultId
> EFI_HII_DEFAULT_CLASS_STANDARD
) {
2859 // Record the SmallestDefaultId and update the SmallestIdFromFlag.
2861 SmallestDefaultId
= EFI_HII_DEFAULT_CLASS_STANDARD
;
2862 SmallestIdFromFlag
= TRUE
;
2865 if ((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT_MFG
) == EFI_IFR_OPTION_DEFAULT_MFG
) {
2866 DefaultData
.DefaultId
= EFI_HII_DEFAULT_CLASS_MANUFACTURING
;
2867 InsertDefaultValue (BlockData
, &DefaultData
);
2868 if (SmallestDefaultId
> EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
2870 // Record the SmallestDefaultId and update the SmallestIdFromFlag.
2872 SmallestDefaultId
= EFI_HII_DEFAULT_CLASS_MANUFACTURING
;
2873 SmallestIdFromFlag
= TRUE
;
2877 if (SmallestIdFromFlag
) {
2879 // When smallest default Id is given by the flag of oneofOption, set this option value for other default Id in the DefaultId list.
2881 DefaultData
.Type
= DefaultValueFromOtherDefault
;
2883 // Set default value for other default id in the DefaultId list.
2885 for (LinkData
= DefaultIdArray
->Entry
.ForwardLink
; LinkData
!= &DefaultIdArray
->Entry
; LinkData
= LinkData
->ForwardLink
) {
2886 DefaultDataPtr
= BASE_CR (LinkData
, IFR_DEFAULT_DATA
, Entry
);
2887 DefaultData
.DefaultId
= DefaultDataPtr
->DefaultId
;
2888 InsertDefaultValue (BlockData
, &DefaultData
);
2894 // 2. Set as the default value when this is the first option.
2895 // The first oneof option value will be used as default value when no default value is specified.
2897 if (FirstOneOfOption
) {
2898 // This flag is used to specify whether this option is the first. Set it to FALSE for the following options.
2899 FirstOneOfOption
= FALSE
;
2902 // Prepare new DefaultValue
2904 DefaultData
.Type
= DefaultValueFromDefault
;
2905 CopyMem (&DefaultData
.Value
, &IfrOneOfOption
->Value
, IfrOneOfOption
->Header
.Length
- OFFSET_OF (EFI_IFR_ONE_OF_OPTION
, Value
));
2906 for (LinkData
= DefaultIdArray
->Entry
.ForwardLink
; LinkData
!= &DefaultIdArray
->Entry
; LinkData
= LinkData
->ForwardLink
) {
2907 DefaultDataPtr
= BASE_CR (LinkData
, IFR_DEFAULT_DATA
, Entry
);
2908 DefaultData
.DefaultId
= DefaultDataPtr
->DefaultId
;
2909 InsertDefaultValue (BlockData
, &DefaultData
);
2914 case EFI_IFR_DEFAULT_OP
:
2916 // Update Current BlockData to the default value.
2918 if (BlockData
== NULL
|| BlockData
->Scope
== 0) {
2920 // No matched block data is ignored.
2926 // Get the DefaultId
2928 IfrDefault
= (EFI_IFR_DEFAULT
*) IfrOpHdr
;
2929 VarDefaultId
= IfrDefault
->DefaultId
;
2931 // Prepare new DefaultValue
2933 DefaultData
.Type
= DefaultValueFromOpcode
;
2934 DefaultData
.DefaultId
= VarDefaultId
;
2935 CopyMem (&DefaultData
.Value
, &IfrDefault
->Value
, IfrDefault
->Header
.Length
- OFFSET_OF (EFI_IFR_DEFAULT
, Value
));
2937 // If the value field is expression, set the cleaned flag.
2938 if (IfrDefault
->Type
== EFI_IFR_TYPE_OTHER
) {
2939 DefaultData
.Cleaned
= TRUE
;
2942 // Add DefaultValue into current BlockData
2944 InsertDefaultValue (BlockData
, &DefaultData
);
2947 // Set default value for other default id in the DefaultId list.
2948 // when SmallestDefaultId == VarDefaultId means there are two defaults with same default Id.
2949 // If the two defaults are both from default opcode, use the first default as the default value of other default Id.
2950 // If one from flag and the other form default opcode, use the default opcode value as the default value of other default Id.
2952 if ((SmallestDefaultId
> VarDefaultId
) || (SmallestDefaultId
== VarDefaultId
&& !FromOtherDefaultOpcode
)) {
2953 FromOtherDefaultOpcode
= TRUE
;
2954 SmallestDefaultId
= VarDefaultId
;
2955 for (LinkData
= DefaultIdArray
->Entry
.ForwardLink
; LinkData
!= &DefaultIdArray
->Entry
; LinkData
= LinkData
->ForwardLink
) {
2956 DefaultDataPtr
= BASE_CR (LinkData
, IFR_DEFAULT_DATA
, Entry
);
2957 if (DefaultDataPtr
->DefaultId
!= DefaultData
.DefaultId
){
2958 DefaultData
.Type
= DefaultValueFromOtherDefault
;
2959 DefaultData
.DefaultId
= DefaultDataPtr
->DefaultId
;
2960 InsertDefaultValue (BlockData
, &DefaultData
);
2966 // After insert the default value, reset the cleaned value for next
2967 // time used. If not set here, need to set the value before every time.
2970 DefaultData
.Cleaned
= FALSE
;
2973 case EFI_IFR_END_OP
:
2975 // End Opcode is for Var question.
2977 if (BlockData
!= NULL
) {
2978 if (BlockData
->Scope
> 0) {
2981 if (BlockData
->Scope
== 0) {
2984 // when finishing parsing a question, clean the SmallestDefaultId and GetDefaultFromDefaultOpcode.
2986 SmallestDefaultId
= 0xFFFF;
2987 FromOtherDefaultOpcode
= FALSE
;
2994 if (BlockData
!= NULL
) {
2995 if (BlockData
->Scope
> 0) {
2996 BlockData
->Scope
= (UINT8
) (BlockData
->Scope
+ IfrOpHdr
->Scope
);
2999 if (BlockData
->Scope
== 0) {
3006 IfrOffset
+= IfrOpHdr
->Length
;
3007 PackageOffset
+= IfrOpHdr
->Length
;
3011 //if Status == EFI_NOT_FOUND, just means the opcode is not required,not contain any error,
3012 //so set the Status to EFI_SUCCESS.
3014 if (Status
== EFI_NOT_FOUND
){
3015 Status
= EFI_SUCCESS
;
3019 for (LinkData
= VarStorageData
->BlockEntry
.ForwardLink
; LinkData
!= &VarStorageData
->BlockEntry
; LinkData
= LinkData
->ForwardLink
) {
3020 BlockData
= BASE_CR (LinkData
, IFR_BLOCK_DATA
, Entry
);
3021 for (LinkDefault
= BlockData
->DefaultValueEntry
.ForwardLink
; LinkDefault
!= &BlockData
->DefaultValueEntry
; ) {
3022 DefaultDataPtr
= BASE_CR (LinkDefault
, IFR_DEFAULT_DATA
, Entry
);
3023 LinkDefault
= LinkDefault
->ForwardLink
;
3024 if (DefaultDataPtr
->Cleaned
== TRUE
) {
3025 RemoveEntryList (&DefaultDataPtr
->Entry
);
3026 FreePool (DefaultDataPtr
);
3035 parse the configrequest string, get the elements.
3037 @param ConfigRequest The input configrequest string.
3038 @param Progress Return the progress data.
3040 @retval Block data pointer.
3044 IN EFI_STRING ConfigRequest
,
3045 OUT EFI_STRING
*Progress
3048 EFI_STRING StringPtr
;
3049 IFR_BLOCK_DATA
*BlockData
;
3050 IFR_BLOCK_DATA
*RequestBlockArray
;
3056 IFR_BLOCK_DATA
*NextBlockData
;
3062 // Init RequestBlockArray
3064 RequestBlockArray
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
3065 if (RequestBlockArray
== NULL
) {
3068 InitializeListHead (&RequestBlockArray
->Entry
);
3071 // Get the request Block array from the request string
3076 // Parse each <RequestElement> if exists
3077 // Only <BlockName> format is supported by this help function.
3078 // <BlockName> ::= &'OFFSET='<Number>&'WIDTH='<Number>
3080 StringPtr
= ConfigRequest
;
3081 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) == 0) {
3083 // Skip the OFFSET string
3085 *Progress
= StringPtr
;
3086 StringPtr
+= StrLen (L
"&OFFSET=");
3090 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
3091 if (EFI_ERROR (Status
)) {
3098 (((Length
+ 1) / 2) < sizeof (UINT16
)) ? ((Length
+ 1) / 2) : sizeof (UINT16
)
3100 FreePool (TmpBuffer
);
3102 StringPtr
+= Length
;
3103 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
3106 StringPtr
+= StrLen (L
"&WIDTH=");
3111 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
3112 if (EFI_ERROR (Status
)) {
3119 (((Length
+ 1) / 2) < sizeof (UINT16
)) ? ((Length
+ 1) / 2) : sizeof (UINT16
)
3121 FreePool (TmpBuffer
);
3123 StringPtr
+= Length
;
3124 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
3131 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
3132 if (BlockData
== NULL
) {
3135 BlockData
->Offset
= Offset
;
3136 BlockData
->Width
= Width
;
3137 InsertBlockData (&RequestBlockArray
->Entry
, &BlockData
);
3140 // Skip &VALUE string if &VALUE does exists.
3142 if (StrnCmp (StringPtr
, L
"&VALUE=", StrLen (L
"&VALUE=")) == 0) {
3143 StringPtr
+= StrLen (L
"&VALUE=");
3148 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
3149 if (EFI_ERROR (Status
)) {
3152 FreePool (TmpBuffer
);
3153 StringPtr
+= Length
;
3154 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
3159 // If '\0', parsing is finished.
3161 if (*StringPtr
== 0) {
3167 // Merge the requested block data.
3169 Link
= RequestBlockArray
->Entry
.ForwardLink
;
3170 while ((Link
!= &RequestBlockArray
->Entry
) && (Link
->ForwardLink
!= &RequestBlockArray
->Entry
)) {
3171 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
3172 NextBlockData
= BASE_CR (Link
->ForwardLink
, IFR_BLOCK_DATA
, Entry
);
3173 if ((NextBlockData
->Offset
>= BlockData
->Offset
) && (NextBlockData
->Offset
<= (BlockData
->Offset
+ BlockData
->Width
))) {
3174 if ((NextBlockData
->Offset
+ NextBlockData
->Width
) > (BlockData
->Offset
+ BlockData
->Width
)) {
3175 BlockData
->Width
= (UINT16
) (NextBlockData
->Offset
+ NextBlockData
->Width
- BlockData
->Offset
);
3177 RemoveEntryList (Link
->ForwardLink
);
3178 FreePool (NextBlockData
);
3181 Link
= Link
->ForwardLink
;
3184 return RequestBlockArray
;
3187 if (RequestBlockArray
!= NULL
) {
3189 // Free Link Array RequestBlockArray
3191 while (!IsListEmpty (&RequestBlockArray
->Entry
)) {
3192 BlockData
= BASE_CR (RequestBlockArray
->Entry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
3193 RemoveEntryList (&BlockData
->Entry
);
3194 FreePool (BlockData
);
3197 FreePool (RequestBlockArray
);
3204 parse the configrequest string, get the elements.
3206 @param ConfigRequest The input config request string.
3207 @param Progress Return the progress data.
3209 @retval return data block array.
3213 IN EFI_STRING ConfigRequest
,
3214 OUT EFI_STRING
*Progress
3217 EFI_STRING StringPtr
;
3219 IFR_BLOCK_DATA
*BlockData
;
3220 IFR_BLOCK_DATA
*RequestBlockArray
;
3223 StringPtr
= ConfigRequest
;
3226 // Init RequestBlockArray
3228 RequestBlockArray
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
3229 if (RequestBlockArray
== NULL
) {
3232 InitializeListHead (&RequestBlockArray
->Entry
);
3235 // Get the request Block array from the request string
3239 // Parse each <RequestElement> if exists
3240 // Only <BlockName> format is supported by this help function.
3241 // <BlockName> ::= &'Name***=***
3243 while (StringPtr
!= NULL
&& *StringPtr
== L
'&') {
3245 *Progress
= StringPtr
;
3247 // Skip the L"&" string
3252 if ((NextTag
= StrStr (StringPtr
, L
"=")) != NULL
) {
3255 } else if ((NextTag
= StrStr (StringPtr
, L
"&")) != NULL
) {
3262 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
3263 if (BlockData
== NULL
) {
3270 BlockData
->Name
= AllocateCopyPool(StrSize (StringPtr
), StringPtr
);
3271 InsertBlockData (&RequestBlockArray
->Entry
, &BlockData
);
3275 // If has value, skip the value.
3277 StringPtr
= NextTag
+ 1;
3279 StringPtr
= StrStr (StringPtr
, L
"&");
3280 } else if (NextTag
!= NULL
) {
3282 // restore the '&' text.
3284 StringPtr
= NextTag
;
3289 return RequestBlockArray
;
3292 if (RequestBlockArray
!= NULL
) {
3294 // Free Link Array RequestBlockArray
3296 while (!IsListEmpty (&RequestBlockArray
->Entry
)) {
3297 BlockData
= BASE_CR (RequestBlockArray
->Entry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
3298 RemoveEntryList (&BlockData
->Entry
);
3299 if (BlockData
->Name
!= NULL
) {
3300 FreePool (BlockData
->Name
);
3302 FreePool (BlockData
);
3305 FreePool (RequestBlockArray
);
3312 Generate ConfigRequest string base on the varstore info.
3314 @param ConfigHdr The config header for this varstore.
3315 @param VarStorageData The varstore info.
3316 @param Status Return Status.
3317 @param ConfigRequest The ConfigRequest info may be return.
3319 @retval TRUE Need to continue
3320 @retval Others NO need to continue or error occur.
3323 GenerateConfigRequest (
3324 IN CHAR16
*ConfigHdr
,
3325 IN IFR_VARSTORAGE_DATA
*VarStorageData
,
3326 OUT EFI_STATUS
*Status
,
3327 IN OUT EFI_STRING
*ConfigRequest
3333 CHAR16
*FullConfigRequest
;
3335 IFR_BLOCK_DATA
*BlockData
;
3338 // Append VarStorageData BlockEntry into *Request string
3339 // Now support only one varstore in a form package.
3343 // Go through all VarStorageData Entry and get BlockEntry for each one for the multiple varstore in a single form package
3344 // Then construct them all to return MultiRequest string : ConfigHdr BlockConfig
3348 // Compute the length of the entire request starting with <ConfigHdr> and a
3352 Length
= StrLen (ConfigHdr
) + 1;
3354 for (Link
= VarStorageData
->BlockEntry
.ForwardLink
; Link
!= &VarStorageData
->BlockEntry
; Link
= Link
->ForwardLink
) {
3356 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
3357 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3359 // Add <BlockName> length for each Name
3361 // <BlockName> ::= &Name1&Name2&...
3362 // |1| StrLen(Name1)
3364 Length
= Length
+ (1 + StrLen (BlockData
->Name
));
3367 // Add <BlockName> length for each Offset/Width pair
3369 // <BlockName> ::= &OFFSET=1234&WIDTH=1234
3370 // | 8 | 4 | 7 | 4 |
3372 Length
= Length
+ (8 + 4 + 7 + 4);
3376 // No any request block data is found. The request string can't be constructed.
3379 *Status
= EFI_SUCCESS
;
3384 // Allocate buffer for the entire <ConfigRequest>
3386 FullConfigRequest
= AllocateZeroPool (Length
* sizeof (CHAR16
));
3387 if (FullConfigRequest
== NULL
) {
3388 *Status
= EFI_OUT_OF_RESOURCES
;
3391 StringPtr
= FullConfigRequest
;
3394 // Start with <ConfigHdr>
3396 StrCpyS (StringPtr
, Length
, ConfigHdr
);
3397 StringPtr
+= StrLen (StringPtr
);
3400 // Loop through all the Offset/Width pairs and append them to ConfigRequest
3402 for (Link
= VarStorageData
->BlockEntry
.ForwardLink
; Link
!= &VarStorageData
->BlockEntry
; Link
= Link
->ForwardLink
) {
3403 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
3404 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3410 (1 + StrLen (BlockData
->Name
) + 1) * sizeof (CHAR16
),
3416 // Append &OFFSET=XXXX&WIDTH=YYYY\0
3420 (8 + 4 + 7 + 4 + 1) * sizeof (CHAR16
),
3421 L
"&OFFSET=%04X&WIDTH=%04X",
3426 StringPtr
+= StrLen (StringPtr
);
3429 // Set to the got full request string.
3431 HiiToLower (FullConfigRequest
);
3433 if (*ConfigRequest
!= NULL
) {
3434 FreePool (*ConfigRequest
);
3436 *ConfigRequest
= FullConfigRequest
;
3442 Generate ConfigRequest Header base on the varstore info.
3444 @param VarStorageData The varstore info.
3445 @param DevicePath Device path for this varstore.
3446 @param ConfigHdr The config header for this varstore.
3448 @retval EFI_SUCCESS Generate the header success.
3449 @retval EFI_OUT_OF_RESOURCES Allocate buffer fail.
3453 IN IFR_VARSTORAGE_DATA
*VarStorageData
,
3454 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
3455 OUT EFI_STRING
*ConfigHdr
3464 Status
= EFI_SUCCESS
;
3470 // Construct <ConfigHdr> : "GUID=...&NAME=...&PATH=..." by VarStorageData Guid, Name and DriverHandle
3472 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*) &VarStorageData
->Guid
, 1, &GuidStr
);
3473 if (VarStorageData
->Name
!= NULL
) {
3474 GenerateSubStr (L
"NAME=", StrLen (VarStorageData
->Name
) * sizeof (CHAR16
), (VOID
*) VarStorageData
->Name
, 2, &NameStr
);
3476 GenerateSubStr (L
"NAME=", 0, NULL
, 2, &NameStr
);
3480 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) DevicePath
),
3481 (VOID
*) DevicePath
,
3485 Length
= StrLen (GuidStr
) + StrLen (NameStr
) + StrLen (PathStr
) + 1;
3486 if (VarStorageData
->Name
== NULL
) {
3490 *ConfigHdr
= AllocateZeroPool (Length
* sizeof (CHAR16
));
3491 if (*ConfigHdr
== NULL
) {
3492 Status
= EFI_OUT_OF_RESOURCES
;
3495 StrCpyS (*ConfigHdr
, Length
, GuidStr
);
3496 StrCatS (*ConfigHdr
, Length
, NameStr
);
3497 if (VarStorageData
->Name
== NULL
) {
3498 StrCatS (*ConfigHdr
, Length
, L
"&");
3500 StrCatS (*ConfigHdr
, Length
, PathStr
);
3503 // Remove the last character L'&'
3505 *(*ConfigHdr
+ StrLen (*ConfigHdr
) - 1) = L
'\0';
3508 if (GuidStr
!= NULL
) {
3512 if (NameStr
!= NULL
) {
3516 if (PathStr
!= NULL
) {
3524 Get Data buffer size based on data type.
3526 @param ValueType The input data type.
3528 @retval The data buffer size for the input type.
3535 UINT16 StorageWidth
;
3537 switch (ValueType
) {
3538 case EFI_IFR_NUMERIC_SIZE_1
:
3539 case EFI_IFR_TYPE_BOOLEAN
:
3540 StorageWidth
= (UINT16
) sizeof (UINT8
);
3543 case EFI_IFR_NUMERIC_SIZE_2
:
3544 StorageWidth
= (UINT16
) sizeof (UINT16
);
3547 case EFI_IFR_NUMERIC_SIZE_4
:
3548 StorageWidth
= (UINT16
) sizeof (UINT32
);
3551 case EFI_IFR_NUMERIC_SIZE_8
:
3552 StorageWidth
= (UINT16
) sizeof (UINT64
);
3555 case EFI_IFR_TYPE_TIME
:
3556 StorageWidth
= (UINT16
) sizeof (EFI_IFR_TIME
);
3559 case EFI_IFR_TYPE_DATE
:
3560 StorageWidth
= (UINT16
) sizeof (EFI_IFR_DATE
);
3568 return StorageWidth
;
3572 Generate ConfigAltResp string base on the varstore info.
3574 @param HiiHandle Hii Handle for this hii package.
3575 @param ConfigHdr The config header for this varstore.
3576 @param VarStorageData The varstore info.
3577 @param DefaultIdArray The Default id array.
3578 @param DefaultAltCfgResp The DefaultAltCfgResp info may be return.
3580 @retval TRUE Need to continue
3581 @retval Others NO need to continue or error occur.
3584 GenerateAltConfigResp (
3585 IN EFI_HII_HANDLE HiiHandle
,
3586 IN CHAR16
*ConfigHdr
,
3587 IN IFR_VARSTORAGE_DATA
*VarStorageData
,
3588 IN IFR_DEFAULT_DATA
*DefaultIdArray
,
3589 IN OUT EFI_STRING
*DefaultAltCfgResp
3595 LIST_ENTRY
*LinkData
;
3596 LIST_ENTRY
*LinkDefault
;
3597 LIST_ENTRY
*ListEntry
;
3599 IFR_BLOCK_DATA
*BlockData
;
3600 IFR_DEFAULT_DATA
*DefaultId
;
3601 IFR_DEFAULT_DATA
*DefaultValueData
;
3604 CHAR16
*DefaultString
;
3609 DefaultString
= NULL
;
3611 // Add length for <ConfigHdr> + '\0'
3613 Length
= StrLen (ConfigHdr
) + 1;
3615 for (Link
= DefaultIdArray
->Entry
.ForwardLink
; Link
!= &DefaultIdArray
->Entry
; Link
= Link
->ForwardLink
) {
3616 DefaultId
= BASE_CR (Link
, IFR_DEFAULT_DATA
, Entry
);
3618 // Add length for "&<ConfigHdr>&ALTCFG=XXXX"
3619 // |1| StrLen (ConfigHdr) | 8 | 4 |
3621 Length
+= (1 + StrLen (ConfigHdr
) + 8 + 4);
3623 for (LinkData
= VarStorageData
->BlockEntry
.ForwardLink
; LinkData
!= &VarStorageData
->BlockEntry
; LinkData
= LinkData
->ForwardLink
) {
3624 BlockData
= BASE_CR (LinkData
, IFR_BLOCK_DATA
, Entry
);
3625 ListEntry
= &BlockData
->DefaultValueEntry
;
3626 for (LinkDefault
= ListEntry
->ForwardLink
; LinkDefault
!= ListEntry
; LinkDefault
= LinkDefault
->ForwardLink
) {
3627 DefaultValueData
= BASE_CR (LinkDefault
, IFR_DEFAULT_DATA
, Entry
);
3628 if (DefaultValueData
->DefaultId
!= DefaultId
->DefaultId
) {
3631 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3633 // Add length for "&Name1=zzzzzzzzzzzz"
3636 Length
+= (1 + StrLen (BlockData
->Name
) + 1 + BlockData
->Width
* 2);
3639 // Add length for "&OFFSET=XXXX&WIDTH=YYYY&VALUE=zzzzzzzzzzzz"
3640 // | 8 | 4 | 7 | 4 | 7 | Width * 2 |
3642 Length
+= (8 + 4 + 7 + 4 + 7 + BlockData
->Width
* 2);
3650 // No default value is found. The default string doesn't exist.
3657 // Allocate buffer for the entire <DefaultAltCfgResp>
3659 *DefaultAltCfgResp
= AllocateZeroPool (Length
* sizeof (CHAR16
));
3660 if (*DefaultAltCfgResp
== NULL
) {
3661 return EFI_OUT_OF_RESOURCES
;
3663 StringPtr
= *DefaultAltCfgResp
;
3666 // Start with <ConfigHdr>
3668 StrCpyS (StringPtr
, Length
, ConfigHdr
);
3669 StringPtr
+= StrLen (StringPtr
);
3671 for (Link
= DefaultIdArray
->Entry
.ForwardLink
; Link
!= &DefaultIdArray
->Entry
; Link
= Link
->ForwardLink
) {
3672 DefaultId
= BASE_CR (Link
, IFR_DEFAULT_DATA
, Entry
);
3674 // Add <AltConfigHdr> of the form "&<ConfigHdr>&ALTCFG=XXXX\0"
3675 // |1| StrLen (ConfigHdr) | 8 | 4 |
3679 (1 + StrLen (ConfigHdr
) + 8 + 4 + 1) * sizeof (CHAR16
),
3682 DefaultId
->DefaultId
3684 StringPtr
+= StrLen (StringPtr
);
3686 for (LinkData
= VarStorageData
->BlockEntry
.ForwardLink
; LinkData
!= &VarStorageData
->BlockEntry
; LinkData
= LinkData
->ForwardLink
) {
3687 BlockData
= BASE_CR (LinkData
, IFR_BLOCK_DATA
, Entry
);
3688 ListEntry
= &BlockData
->DefaultValueEntry
;
3689 for (LinkDefault
= ListEntry
->ForwardLink
; LinkDefault
!= ListEntry
; LinkDefault
= LinkDefault
->ForwardLink
) {
3690 DefaultValueData
= BASE_CR (LinkDefault
, IFR_DEFAULT_DATA
, Entry
);
3691 if (DefaultValueData
->DefaultId
!= DefaultId
->DefaultId
) {
3694 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3697 (1 + StrLen (ConfigHdr
) + 1) * sizeof (CHAR16
),
3701 StringPtr
+= StrLen (StringPtr
);
3704 // Add <BlockConfig>
3705 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>
3709 (8 + 4 + 7 + 4 + 7 + 1) * sizeof (CHAR16
),
3710 L
"&OFFSET=%04X&WIDTH=%04X&VALUE=",
3714 StringPtr
+= StrLen (StringPtr
);
3716 Width
= BlockData
->Width
;
3718 // Convert Value to a hex string in "%x" format
3719 // NOTE: This is in the opposite byte that GUID and PATH use
3721 if (BlockData
->OpCode
== EFI_IFR_STRING_OP
){
3722 DefaultString
= InternalGetString(HiiHandle
, DefaultValueData
->Value
.string
);
3723 TmpBuffer
= AllocateZeroPool (Width
);
3724 ASSERT (TmpBuffer
!= NULL
);
3725 if (DefaultString
!= NULL
) {
3726 StrSize
= StrLen(DefaultString
)* sizeof (CHAR16
);
3727 if (StrSize
> Width
) {
3730 CopyMem (TmpBuffer
, (UINT8
*) DefaultString
, StrSize
);
3733 TmpBuffer
= (UINT8
*) &(DefaultValueData
->Value
);
3735 for (; Width
> 0 && (TmpBuffer
!= NULL
); Width
--) {
3736 UnicodeValueToStringS (
3738 Length
* sizeof (CHAR16
) - ((UINTN
)StringPtr
- (UINTN
)*DefaultAltCfgResp
),
3739 PREFIX_ZERO
| RADIX_HEX
,
3740 TmpBuffer
[Width
- 1],
3743 StringPtr
+= StrnLenS (StringPtr
, Length
- ((UINTN
)StringPtr
- (UINTN
)*DefaultAltCfgResp
) / sizeof (CHAR16
));
3745 if (DefaultString
!= NULL
){
3746 FreePool(DefaultString
);
3747 DefaultString
= NULL
;
3749 if (BlockData
->OpCode
== EFI_IFR_STRING_OP
&& TmpBuffer
!= NULL
) {
3750 FreePool(TmpBuffer
);
3757 HiiToLower (*DefaultAltCfgResp
);
3763 This function gets the full request string and full default value string by
3764 parsing IFR data in HII form packages.
3766 When Request points to NULL string, the request string and default value string
3767 for each varstore in form package will return.
3769 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
3770 @param DevicePath Device Path which Hii Config Access Protocol is registered.
3771 @param Request Pointer to a null-terminated Unicode string in
3772 <ConfigRequest> format. When it doesn't contain
3773 any RequestElement, it will be updated to return
3774 the full RequestElement retrieved from IFR data.
3775 If it points to NULL, the request string for the first
3776 varstore in form package will be merged into a
3777 <MultiConfigRequest> format string and return.
3778 @param AltCfgResp Pointer to a null-terminated Unicode string in
3779 <ConfigAltResp> format. When the pointer is to NULL,
3780 the full default value string retrieved from IFR data
3781 will return. When the pinter is to a string, the
3782 full default value string retrieved from IFR data
3783 will be merged into the input string and return.
3784 When Request points to NULL, the default value string
3785 for each varstore in form package will be merged into
3786 a <MultiConfigAltResp> format string and return.
3787 @param PointerProgress Optional parameter, it can be NULL.
3788 When it is not NULL, if Request is NULL, it returns NULL.
3789 On return, points to a character in the Request
3790 string. Points to the string's null terminator if
3791 request was successful. Points to the most recent
3792 & before the first failing name / value pair (or
3793 the beginning of the string if the failure is in
3794 the first name / value pair) if the request was
3796 @retval EFI_SUCCESS The Results string is set to the full request string.
3797 And AltCfgResp contains all default value string.
3798 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
3799 @retval EFI_NOT_FOUND The varstore (Guid and Name) in Request string
3800 can't be found in Form package.
3801 @retval EFI_NOT_FOUND HiiPackage can't be got on the input HiiHandle.
3802 @retval EFI_INVALID_PARAMETER Request points to NULL.
3807 GetFullStringFromHiiFormPackages (
3808 IN HII_DATABASE_RECORD
*DataBaseRecord
,
3809 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
3810 IN OUT EFI_STRING
*Request
,
3811 IN OUT EFI_STRING
*AltCfgResp
,
3812 OUT EFI_STRING
*PointerProgress OPTIONAL
3816 UINT8
*HiiFormPackage
;
3818 IFR_BLOCK_DATA
*RequestBlockArray
;
3819 IFR_BLOCK_DATA
*BlockData
;
3820 IFR_DEFAULT_DATA
*DefaultValueData
;
3821 IFR_DEFAULT_DATA
*DefaultId
;
3822 IFR_DEFAULT_DATA
*DefaultIdArray
;
3823 IFR_VARSTORAGE_DATA
*VarStorageData
;
3824 EFI_STRING DefaultAltCfgResp
;
3825 EFI_STRING ConfigHdr
;
3826 EFI_STRING StringPtr
;
3827 EFI_STRING Progress
;
3829 if (DataBaseRecord
== NULL
|| DevicePath
== NULL
|| Request
== NULL
|| AltCfgResp
== NULL
) {
3830 return EFI_INVALID_PARAMETER
;
3834 // Initialize the local variables.
3836 RequestBlockArray
= NULL
;
3837 DefaultIdArray
= NULL
;
3838 VarStorageData
= NULL
;
3839 DefaultAltCfgResp
= NULL
;
3841 HiiFormPackage
= NULL
;
3843 Progress
= *Request
;
3845 Status
= GetFormPackageData (DataBaseRecord
, &HiiFormPackage
, &PackageSize
);
3846 if (EFI_ERROR (Status
)) {
3851 // 1. Get the request block array by Request String when Request string contains the block array.
3854 if (*Request
!= NULL
) {
3855 StringPtr
= *Request
;
3859 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
3860 Status
= EFI_INVALID_PARAMETER
;
3863 StringPtr
+= StrLen (L
"GUID=");
3864 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&NAME=", StrLen (L
"&NAME=")) != 0) {
3867 if (*StringPtr
== L
'\0') {
3868 Status
= EFI_INVALID_PARAMETER
;
3871 StringPtr
+= StrLen (L
"&NAME=");
3872 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&PATH=", StrLen (L
"&PATH=")) != 0) {
3875 if (*StringPtr
== L
'\0') {
3876 Status
= EFI_INVALID_PARAMETER
;
3879 StringPtr
+= StrLen (L
"&PATH=");
3880 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
3884 if (*StringPtr
== L
'\0') {
3886 // No request block is found.
3893 // If StringPtr != NULL, get the request elements.
3895 if (StringPtr
!= NULL
) {
3896 if (StrStr (StringPtr
, L
"&OFFSET=") != NULL
) {
3897 RequestBlockArray
= GetBlockElement(StringPtr
, &Progress
);
3899 RequestBlockArray
= GetNameElement(StringPtr
, &Progress
);
3902 if (RequestBlockArray
== NULL
) {
3903 Status
= EFI_INVALID_PARAMETER
;
3909 // Initialize DefaultIdArray to store the map between DeaultId and DefaultName
3911 DefaultIdArray
= (IFR_DEFAULT_DATA
*) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
3912 if (DefaultIdArray
== NULL
) {
3913 Status
= EFI_OUT_OF_RESOURCES
;
3916 InitializeListHead (&DefaultIdArray
->Entry
);
3919 // Initialize VarStorageData to store the var store Block and Default value information.
3921 VarStorageData
= (IFR_VARSTORAGE_DATA
*) AllocateZeroPool (sizeof (IFR_VARSTORAGE_DATA
));
3922 if (VarStorageData
== NULL
) {
3923 Status
= EFI_OUT_OF_RESOURCES
;
3926 InitializeListHead (&VarStorageData
->Entry
);
3927 InitializeListHead (&VarStorageData
->BlockEntry
);
3930 // 2. Parse FormPackage to get BlockArray and DefaultId Array for the request BlockArray.
3934 // Parse the opcode in form package to get the default setting.
3936 Status
= ParseIfrData (DataBaseRecord
->Handle
,
3938 (UINT32
) PackageSize
,
3943 if (EFI_ERROR (Status
)) {
3948 // No requested varstore in IFR data and directly return
3950 if (VarStorageData
->Type
== 0 && VarStorageData
->Name
== NULL
) {
3951 Status
= EFI_SUCCESS
;
3956 // 3. Construct Request Element (Block Name) for 2.1 and 2.2 case.
3958 Status
= GenerateHdr (VarStorageData
, DevicePath
, &ConfigHdr
);
3959 if (EFI_ERROR (Status
)) {
3963 if (RequestBlockArray
== NULL
) {
3964 if (!GenerateConfigRequest(ConfigHdr
, VarStorageData
, &Status
, Request
)) {
3970 // 4. Construct Default Value string in AltResp according to request element.
3971 // Go through all VarStorageData Entry and get the DefaultId array for each one
3972 // Then construct them all to : ConfigHdr AltConfigHdr ConfigBody AltConfigHdr ConfigBody
3974 Status
= GenerateAltConfigResp (DataBaseRecord
->Handle
,ConfigHdr
, VarStorageData
, DefaultIdArray
, &DefaultAltCfgResp
);
3975 if (EFI_ERROR (Status
)) {
3980 // 5. Merge string into the input AltCfgResp if the input *AltCfgResp is not NULL.
3982 if (*AltCfgResp
!= NULL
&& DefaultAltCfgResp
!= NULL
) {
3983 Status
= MergeDefaultString (AltCfgResp
, DefaultAltCfgResp
);
3984 FreePool (DefaultAltCfgResp
);
3985 } else if (*AltCfgResp
== NULL
) {
3986 *AltCfgResp
= DefaultAltCfgResp
;
3990 if (RequestBlockArray
!= NULL
) {
3992 // Free Link Array RequestBlockArray
3994 while (!IsListEmpty (&RequestBlockArray
->Entry
)) {
3995 BlockData
= BASE_CR (RequestBlockArray
->Entry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
3996 RemoveEntryList (&BlockData
->Entry
);
3997 if (BlockData
->Name
!= NULL
) {
3998 FreePool (BlockData
->Name
);
4000 FreePool (BlockData
);
4003 FreePool (RequestBlockArray
);
4006 if (VarStorageData
!= NULL
) {
4008 // Free link array VarStorageData
4010 while (!IsListEmpty (&VarStorageData
->BlockEntry
)) {
4011 BlockData
= BASE_CR (VarStorageData
->BlockEntry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
4012 RemoveEntryList (&BlockData
->Entry
);
4013 if (BlockData
->Name
!= NULL
) {
4014 FreePool (BlockData
->Name
);
4017 // Free default value link array
4019 while (!IsListEmpty (&BlockData
->DefaultValueEntry
)) {
4020 DefaultValueData
= BASE_CR (BlockData
->DefaultValueEntry
.ForwardLink
, IFR_DEFAULT_DATA
, Entry
);
4021 RemoveEntryList (&DefaultValueData
->Entry
);
4022 FreePool (DefaultValueData
);
4024 FreePool (BlockData
);
4026 if (VarStorageData
->Name
!= NULL
) {
4027 FreePool (VarStorageData
->Name
);
4028 VarStorageData
->Name
= NULL
;
4030 FreePool (VarStorageData
);
4033 if (DefaultIdArray
!= NULL
) {
4035 // Free DefaultId Array
4037 while (!IsListEmpty (&DefaultIdArray
->Entry
)) {
4038 DefaultId
= BASE_CR (DefaultIdArray
->Entry
.ForwardLink
, IFR_DEFAULT_DATA
, Entry
);
4039 RemoveEntryList (&DefaultId
->Entry
);
4040 FreePool (DefaultId
);
4042 FreePool (DefaultIdArray
);
4046 // Free the allocated string
4048 if (ConfigHdr
!= NULL
) {
4049 FreePool (ConfigHdr
);
4053 // Free Package data
4055 if (HiiFormPackage
!= NULL
) {
4056 FreePool (HiiFormPackage
);
4059 if (PointerProgress
!= NULL
) {
4060 if (*Request
== NULL
) {
4061 *PointerProgress
= NULL
;
4062 } else if (EFI_ERROR (Status
)) {
4063 *PointerProgress
= *Request
;
4065 *PointerProgress
= *Request
+ StrLen (*Request
);
4073 This function gets the full request resp string by
4074 parsing IFR data in HII form packages.
4076 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
4078 @param EfiVarStoreInfo The efi varstore info which is save in the EFI
4079 varstore data structure.
4080 @param Request Pointer to a null-terminated Unicode string in
4081 <ConfigRequest> format.
4082 @param RequestResp Pointer to a null-terminated Unicode string in
4083 <ConfigResp> format.
4084 @param AccessProgress On return, points to a character in the Request
4085 string. Points to the string's null terminator if
4086 request was successful. Points to the most recent
4087 & before the first failing name / value pair (or
4088 the beginning of the string if the failure is in
4089 the first name / value pair) if the request was
4092 @retval EFI_SUCCESS The Results string is set to the full request string.
4093 And AltCfgResp contains all default value string.
4094 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
4095 @retval EFI_INVALID_PARAMETER Request points to NULL.
4099 GetConfigRespFromEfiVarStore (
4100 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
4101 IN EFI_IFR_VARSTORE_EFI
*EfiVarStoreInfo
,
4102 IN EFI_STRING Request
,
4103 OUT EFI_STRING
*RequestResp
,
4104 OUT EFI_STRING
*AccessProgress
4108 EFI_STRING VarStoreName
;
4113 Status
= EFI_SUCCESS
;
4116 VarStoreName
= NULL
;
4117 *AccessProgress
= Request
;
4119 NameSize
= AsciiStrSize ((CHAR8
*)EfiVarStoreInfo
->Name
);
4120 VarStoreName
= AllocateZeroPool (NameSize
* sizeof (CHAR16
));
4121 if (VarStoreName
== NULL
) {
4122 Status
= EFI_OUT_OF_RESOURCES
;
4125 AsciiStrToUnicodeStrS ((CHAR8
*) EfiVarStoreInfo
->Name
, VarStoreName
, NameSize
);
4128 Status
= gRT
->GetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, NULL
, &BufferSize
, NULL
);
4129 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
4133 VarStore
= AllocateZeroPool (BufferSize
);
4134 ASSERT (VarStore
!= NULL
);
4135 Status
= gRT
->GetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, NULL
, &BufferSize
, VarStore
);
4136 if (EFI_ERROR (Status
)) {
4140 Status
= HiiBlockToConfig(This
, Request
, VarStore
, BufferSize
, RequestResp
, AccessProgress
);
4141 if (EFI_ERROR (Status
)) {
4146 if (VarStoreName
!= NULL
) {
4147 FreePool (VarStoreName
);
4150 if (VarStore
!= NULL
) {
4151 FreePool (VarStore
);
4159 This function route the full request resp string for efi varstore.
4161 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
4163 @param EfiVarStoreInfo The efi varstore info which is save in the EFI
4164 varstore data structure.
4165 @param RequestResp Pointer to a null-terminated Unicode string in
4166 <ConfigResp> format.
4167 @param Result Pointer to a null-terminated Unicode string in
4168 <ConfigResp> format.
4170 @retval EFI_SUCCESS The Results string is set to the full request string.
4171 And AltCfgResp contains all default value string.
4172 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
4173 @retval EFI_INVALID_PARAMETER Request points to NULL.
4177 RouteConfigRespForEfiVarStore (
4178 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
4179 IN EFI_IFR_VARSTORE_EFI
*EfiVarStoreInfo
,
4180 IN EFI_STRING RequestResp
,
4181 OUT EFI_STRING
*Result
4185 EFI_STRING VarStoreName
;
4191 Status
= EFI_SUCCESS
;
4194 VarStoreName
= NULL
;
4195 *Result
= RequestResp
;
4197 NameSize
= AsciiStrSize ((CHAR8
*)EfiVarStoreInfo
->Name
);
4198 VarStoreName
= AllocateZeroPool (NameSize
* sizeof (CHAR16
));
4199 if (VarStoreName
== NULL
) {
4200 Status
= EFI_OUT_OF_RESOURCES
;
4203 AsciiStrToUnicodeStrS ((CHAR8
*) EfiVarStoreInfo
->Name
, VarStoreName
, NameSize
);
4205 Status
= gRT
->GetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, NULL
, &BufferSize
, NULL
);
4206 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
4207 DEBUG ((DEBUG_ERROR
, "The variable does not exist!"));
4211 BlockSize
= BufferSize
;
4212 VarStore
= AllocateZeroPool (BufferSize
);
4213 ASSERT (VarStore
!= NULL
);
4214 Status
= gRT
->GetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, NULL
, &BufferSize
, VarStore
);
4215 if (EFI_ERROR (Status
)) {
4219 Status
= HiiConfigToBlock(This
, RequestResp
, VarStore
, &BlockSize
, Result
);
4220 if (EFI_ERROR (Status
)) {
4224 Status
= gRT
->SetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, EfiVarStoreInfo
->Attributes
, BufferSize
, VarStore
);
4225 if (EFI_ERROR (Status
)) {
4226 *Result
= RequestResp
;
4231 if (VarStoreName
!= NULL
) {
4232 FreePool (VarStoreName
);
4235 if (VarStore
!= NULL
) {
4236 FreePool (VarStore
);
4243 Validate the config request elements.
4245 @param ConfigElements A null-terminated Unicode string in <ConfigRequest> format,
4246 without configHdr field.
4248 @retval CHAR16 * THE first Name/value pair not correct.
4249 @retval NULL Success parse the name/value pair
4252 OffsetWidthValidate (
4253 CHAR16
*ConfigElements
4259 StringPtr
= ConfigElements
;
4263 if (StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) != 0) {
4267 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
4270 if (*StringPtr
== L
'\0') {
4274 StringPtr
+= StrLen (L
"&WIDTH=");
4275 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) != 0) {
4279 if (*StringPtr
== L
'\0') {
4286 Validate the config request elements.
4288 @param ConfigElements A null-terminated Unicode string in <ConfigRequest> format,
4289 without configHdr field.
4291 @retval CHAR16 * THE first Name/value pair not correct.
4292 @retval NULL Success parse the name/value pair
4297 CHAR16
*ConfigElements
4303 StringPtr
= ConfigElements
;
4307 if (*StringPtr
!= L
'&') {
4312 StringPtr
= StrStr (StringPtr
, L
"&");
4314 if (StringPtr
== NULL
) {
4321 Validate the config request string.
4323 @param ConfigRequest A null-terminated Unicode string in <ConfigRequest> format.
4325 @retval CHAR16 * THE first element not correct.
4326 @retval NULL Success parse the name/value pair
4330 ConfigRequestValidate (
4331 CHAR16
*ConfigRequest
4334 BOOLEAN HasNameField
;
4337 HasNameField
= TRUE
;
4338 StringPtr
= ConfigRequest
;
4341 // Check <ConfigHdr>
4343 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
4344 return ConfigRequest
;
4346 StringPtr
+= StrLen (L
"GUID=");
4347 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&NAME=", StrLen (L
"&NAME=")) != 0) {
4350 if (*StringPtr
== L
'\0') {
4351 return ConfigRequest
;
4353 StringPtr
+= StrLen (L
"&NAME=");
4354 if (*StringPtr
== L
'&') {
4355 HasNameField
= FALSE
;
4357 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&PATH=", StrLen (L
"&PATH=")) != 0) {
4360 if (*StringPtr
== L
'\0') {
4361 return ConfigRequest
;
4363 StringPtr
+= StrLen (L
"&PATH=");
4364 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
4368 if (*StringPtr
== L
'\0') {
4374 // Should be Buffer varstore, config request should be "OFFSET/Width" pairs.
4376 return OffsetWidthValidate(StringPtr
);
4379 // Should be Name/Value varstore, config request should be "&name1&name2..." pairs.
4381 return NameValueValidate(StringPtr
);
4386 This function allows a caller to extract the current configuration
4387 for one or more named elements from one or more drivers.
4389 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
4391 @param Request A null-terminated Unicode string in
4392 <MultiConfigRequest> format.
4393 @param Progress On return, points to a character in the Request
4394 string. Points to the string's null terminator if
4395 request was successful. Points to the most recent
4396 & before the first failing name / value pair (or
4397 the beginning of the string if the failure is in
4398 the first name / value pair) if the request was
4400 @param Results Null-terminated Unicode string in
4401 <MultiConfigAltResp> format which has all values
4402 filled in for the names in the Request string.
4403 String to be allocated by the called function.
4405 @retval EFI_SUCCESS The Results string is filled with the values
4406 corresponding to all requested names.
4407 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
4408 results that must be stored awaiting possible
4410 @retval EFI_NOT_FOUND Routing data doesn't match any known driver.
4411 Progress set to the "G" in "GUID" of the routing
4412 header that doesn't match. Note: There is no
4413 requirement that all routing data be validated
4414 before any configuration extraction.
4415 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Request
4416 parameter would result in this type of error. The
4417 Progress parameter is set to NULL.
4418 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set to most recent &
4419 before the error or the beginning of the string.
4420 @retval EFI_INVALID_PARAMETER The ExtractConfig function of the underlying HII
4421 Configuration Access Protocol returned
4422 EFI_INVALID_PARAMETER. Progress set to most recent
4423 & before the error or the beginning of the string.
4428 HiiConfigRoutingExtractConfig (
4429 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
4430 IN CONST EFI_STRING Request
,
4431 OUT EFI_STRING
*Progress
,
4432 OUT EFI_STRING
*Results
4435 HII_DATABASE_PRIVATE_DATA
*Private
;
4436 EFI_STRING StringPtr
;
4437 EFI_STRING ConfigRequest
;
4439 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
4440 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
4443 HII_DATABASE_RECORD
*Database
;
4444 UINT8
*DevicePathPkg
;
4445 UINT8
*CurrentDevicePath
;
4446 EFI_HANDLE DriverHandle
;
4447 EFI_HII_HANDLE HiiHandle
;
4448 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
4449 EFI_STRING AccessProgress
;
4450 EFI_STRING AccessResults
;
4451 EFI_STRING AccessProgressBackup
;
4452 EFI_STRING AccessResultsBackup
;
4453 EFI_STRING DefaultResults
;
4454 BOOLEAN FirstElement
;
4455 BOOLEAN IfrDataParsedFlag
;
4456 BOOLEAN IsEfiVarStore
;
4457 EFI_IFR_VARSTORE_EFI
*EfiVarStoreInfo
;
4458 EFI_STRING ErrorPtr
;
4459 UINTN DevicePathSize
;
4460 UINTN ConigStringSize
;
4461 UINTN ConigStringSizeNewsize
;
4462 EFI_STRING ConfigStringPtr
;
4464 if (This
== NULL
|| Progress
== NULL
|| Results
== NULL
) {
4465 return EFI_INVALID_PARAMETER
;
4468 if (Request
== NULL
) {
4470 return EFI_INVALID_PARAMETER
;
4473 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
4474 StringPtr
= Request
;
4475 *Progress
= StringPtr
;
4476 DefaultResults
= NULL
;
4477 ConfigRequest
= NULL
;
4478 Status
= EFI_SUCCESS
;
4479 AccessResults
= NULL
;
4480 AccessProgress
= NULL
;
4481 AccessResultsBackup
= NULL
;
4482 AccessProgressBackup
= NULL
;
4484 IfrDataParsedFlag
= FALSE
;
4485 IsEfiVarStore
= FALSE
;
4486 EfiVarStoreInfo
= NULL
;
4489 // The first element of <MultiConfigRequest> should be
4490 // <GuidHdr>, which is in 'GUID='<Guid> syntax.
4492 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
4493 return EFI_INVALID_PARAMETER
;
4496 FirstElement
= TRUE
;
4499 // Allocate a fix length of memory to store Results. Reallocate memory for
4500 // Results if this fix length is insufficient.
4502 *Results
= (EFI_STRING
) AllocateZeroPool (MAX_STRING_LENGTH
);
4503 if (*Results
== NULL
) {
4504 return EFI_OUT_OF_RESOURCES
;
4507 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) == 0) {
4509 // If parsing error, set Progress to the beginning of the <MultiConfigRequest>
4510 // or most recent & before the error.
4512 if (StringPtr
== Request
) {
4513 *Progress
= StringPtr
;
4515 *Progress
= StringPtr
- 1;
4519 // Process each <ConfigRequest> of <MultiConfigRequest>
4521 Length
= CalculateConfigStringLen (StringPtr
);
4522 ConfigRequest
= AllocateCopyPool ((Length
+ 1) * sizeof (CHAR16
), StringPtr
);
4523 if (ConfigRequest
== NULL
) {
4524 Status
= EFI_OUT_OF_RESOURCES
;
4527 *(ConfigRequest
+ Length
) = 0;
4530 // Get the UEFI device path
4532 Status
= GetDevicePath (ConfigRequest
, (UINT8
**) &DevicePath
);
4533 if (EFI_ERROR (Status
)) {
4538 // Find driver which matches the routing data.
4540 DriverHandle
= NULL
;
4543 for (Link
= Private
->DatabaseList
.ForwardLink
;
4544 Link
!= &Private
->DatabaseList
;
4545 Link
= Link
->ForwardLink
4547 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
4548 if ((DevicePathPkg
= Database
->PackageList
->DevicePathPkg
) != NULL
) {
4549 CurrentDevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
4550 DevicePathSize
= GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) CurrentDevicePath
);
4551 if ((CompareMem (DevicePath
,CurrentDevicePath
,DevicePathSize
) == 0) && IsThisPackageList(Database
, ConfigRequest
)) {
4552 DriverHandle
= Database
->DriverHandle
;
4553 HiiHandle
= Database
->Handle
;
4560 // Try to find driver handle by device path.
4562 if (DriverHandle
== NULL
) {
4563 TempDevicePath
= DevicePath
;
4564 Status
= gBS
->LocateDevicePath (
4565 &gEfiDevicePathProtocolGuid
,
4569 if (EFI_ERROR (Status
) || (DriverHandle
== NULL
)) {
4571 // Routing data does not match any known driver.
4572 // Set Progress to the 'G' in "GUID" of the routing header.
4574 *Progress
= StringPtr
;
4575 Status
= EFI_NOT_FOUND
;
4581 // Validate ConfigRequest String.
4583 ErrorPtr
= ConfigRequestValidate(ConfigRequest
);
4584 if (ErrorPtr
!= NULL
) {
4585 *Progress
= StrStr (StringPtr
, ErrorPtr
);
4586 Status
= EFI_INVALID_PARAMETER
;
4591 // Check whether ConfigRequest contains request string.
4593 IfrDataParsedFlag
= FALSE
;
4594 if ((HiiHandle
!= NULL
) && !GetElementsFromRequest(ConfigRequest
)) {
4596 // Get the full request string from IFR when HiiPackage is registered to HiiHandle
4598 IfrDataParsedFlag
= TRUE
;
4599 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &ConfigRequest
, &DefaultResults
, &AccessProgress
);
4600 if (EFI_ERROR (Status
)) {
4602 // AccessProgress indicates the parsing progress on <ConfigRequest>.
4603 // Map it to the progress on <MultiConfigRequest> then return it.
4605 ASSERT (AccessProgress
!= NULL
);
4606 *Progress
= StrStr (StringPtr
, AccessProgress
);
4610 // Not any request block is found.
4612 if (!GetElementsFromRequest(ConfigRequest
)) {
4613 AccessResults
= AllocateCopyPool (StrSize (ConfigRequest
), ConfigRequest
);
4614 goto NextConfigString
;
4619 // Check whether this ConfigRequest is search from Efi varstore type storage.
4621 Status
= GetVarStoreType(Database
, ConfigRequest
, &IsEfiVarStore
, &EfiVarStoreInfo
);
4622 if (EFI_ERROR (Status
)) {
4626 if (IsEfiVarStore
) {
4628 // Call the GetVariable function to extract settings.
4630 Status
= GetConfigRespFromEfiVarStore(This
, EfiVarStoreInfo
, ConfigRequest
, &AccessResults
, &AccessProgress
);
4631 FreePool (EfiVarStoreInfo
);
4632 if (EFI_ERROR (Status
)) {
4634 // AccessProgress indicates the parsing progress on <ConfigRequest>.
4635 // Map it to the progress on <MultiConfigRequest> then return it.
4637 *Progress
= StrStr (StringPtr
, AccessProgress
);
4642 // For EfiVarstore, call corresponding ConfigAccess protocol to get the AltCfgResp from driver.
4644 Status
= gBS
->HandleProtocol (
4646 &gEfiHiiConfigAccessProtocolGuid
,
4647 (VOID
**) &ConfigAccess
4649 if (EFI_ERROR (Status
)) {
4651 // The driver has EfiVarStore, may not install ConfigAccess protocol.
4652 // So ignore the error status in this case.
4654 Status
= EFI_SUCCESS
;
4656 Status
= ConfigAccess
->ExtractConfig (
4659 &AccessProgressBackup
,
4660 &AccessResultsBackup
4662 if (!EFI_ERROR(Status
)) {
4664 //Merge the AltCfgResp in AccessResultsBackup to AccessResults
4666 if ((AccessResultsBackup
!= NULL
) && (StrStr (AccessResultsBackup
, L
"&ALTCFG=") != NULL
)) {
4667 ConigStringSize
= StrSize (AccessResults
);
4668 ConfigStringPtr
= StrStr (AccessResultsBackup
, L
"&GUID=");
4669 ConigStringSizeNewsize
= StrSize (ConfigStringPtr
) + ConigStringSize
+ sizeof (CHAR16
);
4670 AccessResults
= (EFI_STRING
) ReallocatePool (
4672 ConigStringSizeNewsize
,
4674 StrCatS (AccessResults
, ConigStringSizeNewsize
/ sizeof (CHAR16
), ConfigStringPtr
);
4678 // In the ExtractConfig function of some driver may not support EfiVarStore,
4679 // may return error status, just ignore the error status in this case.
4681 Status
= EFI_SUCCESS
;
4683 if (AccessResultsBackup
!= NULL
) {
4684 FreePool (AccessResultsBackup
);
4685 AccessResultsBackup
= NULL
;
4690 // Call corresponding ConfigAccess protocol to extract settings
4692 Status
= gBS
->HandleProtocol (
4694 &gEfiHiiConfigAccessProtocolGuid
,
4695 (VOID
**) &ConfigAccess
4697 if (EFI_ERROR (Status
)) {
4701 Status
= ConfigAccess
->ExtractConfig (
4708 if (EFI_ERROR (Status
)) {
4710 // AccessProgress indicates the parsing progress on <ConfigRequest>.
4711 // Map it to the progress on <MultiConfigRequest> then return it.
4713 *Progress
= StrStr (StringPtr
, AccessProgress
);
4718 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'
4719 // which separates the first <ConfigAltResp> and the following ones.
4721 ASSERT (*AccessProgress
== 0);
4724 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
4726 if (!IfrDataParsedFlag
&& HiiHandle
!= NULL
) {
4727 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &ConfigRequest
, &DefaultResults
, NULL
);
4728 ASSERT_EFI_ERROR (Status
);
4731 FreePool (DevicePath
);
4734 if (DefaultResults
!= NULL
) {
4735 Status
= MergeDefaultString (&AccessResults
, DefaultResults
);
4736 ASSERT_EFI_ERROR (Status
);
4737 FreePool (DefaultResults
);
4738 DefaultResults
= NULL
;
4742 if (!FirstElement
) {
4743 Status
= AppendToMultiString (Results
, L
"&");
4744 ASSERT_EFI_ERROR (Status
);
4747 Status
= AppendToMultiString (Results
, AccessResults
);
4748 ASSERT_EFI_ERROR (Status
);
4750 FirstElement
= FALSE
;
4752 FreePool (AccessResults
);
4753 AccessResults
= NULL
;
4754 FreePool (ConfigRequest
);
4755 ConfigRequest
= NULL
;
4758 // Go to next <ConfigRequest> (skip '&').
4760 StringPtr
+= Length
;
4761 if (*StringPtr
== 0) {
4762 *Progress
= StringPtr
;
4770 if (EFI_ERROR (Status
)) {
4771 FreePool (*Results
);
4775 if (ConfigRequest
!= NULL
) {
4776 FreePool (ConfigRequest
);
4779 if (AccessResults
!= NULL
) {
4780 FreePool (AccessResults
);
4783 if (DefaultResults
!= NULL
) {
4784 FreePool (DefaultResults
);
4787 if (DevicePath
!= NULL
) {
4788 FreePool (DevicePath
);
4796 This function allows the caller to request the current configuration for the
4797 entirety of the current HII database and returns the data in a
4798 null-terminated Unicode string.
4800 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
4802 @param Results Null-terminated Unicode string in
4803 <MultiConfigAltResp> format which has all values
4804 filled in for the entirety of the current HII
4805 database. String to be allocated by the called
4806 function. De-allocation is up to the caller.
4808 @retval EFI_SUCCESS The Results string is filled with the values
4809 corresponding to all requested names.
4810 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
4811 results that must be stored awaiting possible
4813 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Results
4814 parameter would result in this type of error.
4819 HiiConfigRoutingExportConfig (
4820 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
4821 OUT EFI_STRING
*Results
4825 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
4826 EFI_STRING AccessResults
;
4827 EFI_STRING Progress
;
4828 EFI_STRING StringPtr
;
4829 EFI_STRING ConfigRequest
;
4831 EFI_HANDLE
*ConfigAccessHandles
;
4832 UINTN NumberConfigAccessHandles
;
4833 BOOLEAN FirstElement
;
4834 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
4835 EFI_HII_HANDLE HiiHandle
;
4836 EFI_STRING DefaultResults
;
4837 HII_DATABASE_PRIVATE_DATA
*Private
;
4839 HII_DATABASE_RECORD
*Database
;
4840 UINT8
*DevicePathPkg
;
4841 UINT8
*CurrentDevicePath
;
4842 BOOLEAN IfrDataParsedFlag
;
4844 if (This
== NULL
|| Results
== NULL
) {
4845 return EFI_INVALID_PARAMETER
;
4848 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
4851 // Allocate a fix length of memory to store Results. Reallocate memory for
4852 // Results if this fix length is insufficient.
4854 *Results
= (EFI_STRING
) AllocateZeroPool (MAX_STRING_LENGTH
);
4855 if (*Results
== NULL
) {
4856 return EFI_OUT_OF_RESOURCES
;
4859 NumberConfigAccessHandles
= 0;
4860 Status
= gBS
->LocateHandleBuffer (
4862 &gEfiHiiConfigAccessProtocolGuid
,
4864 &NumberConfigAccessHandles
,
4865 &ConfigAccessHandles
4867 if (EFI_ERROR (Status
)) {
4871 FirstElement
= TRUE
;
4873 for (Index
= 0; Index
< NumberConfigAccessHandles
; Index
++) {
4874 Status
= gBS
->HandleProtocol (
4875 ConfigAccessHandles
[Index
],
4876 &gEfiHiiConfigAccessProtocolGuid
,
4877 (VOID
**) &ConfigAccess
4879 if (EFI_ERROR (Status
)) {
4884 // Get DevicePath and HiiHandle for this ConfigAccess driver handle
4886 IfrDataParsedFlag
= FALSE
;
4889 DefaultResults
= NULL
;
4891 ConfigRequest
= NULL
;
4892 DevicePath
= DevicePathFromHandle (ConfigAccessHandles
[Index
]);
4893 if (DevicePath
!= NULL
) {
4894 for (Link
= Private
->DatabaseList
.ForwardLink
;
4895 Link
!= &Private
->DatabaseList
;
4896 Link
= Link
->ForwardLink
4898 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
4899 if ((DevicePathPkg
= Database
->PackageList
->DevicePathPkg
) != NULL
) {
4900 CurrentDevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
4904 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) CurrentDevicePath
)
4906 HiiHandle
= Database
->Handle
;
4913 Status
= ConfigAccess
->ExtractConfig (
4919 if (EFI_ERROR (Status
)) {
4921 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
4923 if (HiiHandle
!= NULL
&& DevicePath
!= NULL
) {
4924 IfrDataParsedFlag
= TRUE
;
4925 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &ConfigRequest
, &DefaultResults
, NULL
);
4927 // Get the full request string to get the Current setting again.
4929 if (!EFI_ERROR (Status
) && ConfigRequest
!= NULL
) {
4930 Status
= ConfigAccess
->ExtractConfig (
4936 FreePool (ConfigRequest
);
4938 Status
= EFI_NOT_FOUND
;
4943 if (!EFI_ERROR (Status
)) {
4945 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
4947 if (!IfrDataParsedFlag
&& HiiHandle
!= NULL
&& DevicePath
!= NULL
) {
4948 StringPtr
= StrStr (AccessResults
, L
"&GUID=");
4949 if (StringPtr
!= NULL
) {
4952 if (GetElementsFromRequest (AccessResults
)) {
4953 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &AccessResults
, &DefaultResults
, NULL
);
4954 ASSERT_EFI_ERROR (Status
);
4956 if (StringPtr
!= NULL
) {
4961 // Merge the default sting from IFR code into the got setting from driver.
4963 if (DefaultResults
!= NULL
) {
4964 Status
= MergeDefaultString (&AccessResults
, DefaultResults
);
4965 ASSERT_EFI_ERROR (Status
);
4966 FreePool (DefaultResults
);
4967 DefaultResults
= NULL
;
4971 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'
4972 // which separates the first <ConfigAltResp> and the following ones.
4974 if (!FirstElement
) {
4975 Status
= AppendToMultiString (Results
, L
"&");
4976 ASSERT_EFI_ERROR (Status
);
4979 Status
= AppendToMultiString (Results
, AccessResults
);
4980 ASSERT_EFI_ERROR (Status
);
4982 FirstElement
= FALSE
;
4984 FreePool (AccessResults
);
4985 AccessResults
= NULL
;
4988 FreePool (ConfigAccessHandles
);
4995 This function processes the results of processing forms and routes it to the
4996 appropriate handlers or storage.
4998 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
5000 @param Configuration A null-terminated Unicode string in
5001 <MulltiConfigResp> format.
5002 @param Progress A pointer to a string filled in with the offset of
5003 the most recent & before the first failing name /
5004 value pair (or the beginning of the string if the
5005 failure is in the first name / value pair) or the
5006 terminating NULL if all was successful.
5008 @retval EFI_SUCCESS The results have been distributed or are awaiting
5010 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
5011 results that must be stored awaiting possible
5013 @retval EFI_INVALID_PARAMETER Passing in a NULL for the Configuration parameter
5014 would result in this type of error.
5015 @retval EFI_NOT_FOUND Target for the specified routing data was not
5021 HiiConfigRoutingRouteConfig (
5022 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
5023 IN CONST EFI_STRING Configuration
,
5024 OUT EFI_STRING
*Progress
5027 HII_DATABASE_PRIVATE_DATA
*Private
;
5028 EFI_STRING StringPtr
;
5029 EFI_STRING ConfigResp
;
5032 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
5033 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
5035 HII_DATABASE_RECORD
*Database
;
5036 UINT8
*DevicePathPkg
;
5037 UINT8
*CurrentDevicePath
;
5038 EFI_HANDLE DriverHandle
;
5039 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
5040 EFI_STRING AccessProgress
;
5041 EFI_IFR_VARSTORE_EFI
*EfiVarStoreInfo
;
5042 BOOLEAN IsEfiVarstore
;
5043 UINTN DevicePathSize
;
5045 if (This
== NULL
|| Progress
== NULL
) {
5046 return EFI_INVALID_PARAMETER
;
5049 if (Configuration
== NULL
) {
5051 return EFI_INVALID_PARAMETER
;
5054 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
5055 StringPtr
= Configuration
;
5056 *Progress
= StringPtr
;
5058 AccessProgress
= NULL
;
5059 EfiVarStoreInfo
= NULL
;
5060 IsEfiVarstore
= FALSE
;
5063 // The first element of <MultiConfigResp> should be
5064 // <GuidHdr>, which is in 'GUID='<Guid> syntax.
5066 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
5067 return EFI_INVALID_PARAMETER
;
5070 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) == 0) {
5072 // If parsing error, set Progress to the beginning of the <MultiConfigResp>
5073 // or most recent & before the error.
5075 if (StringPtr
== Configuration
) {
5076 *Progress
= StringPtr
;
5078 *Progress
= StringPtr
- 1;
5082 // Process each <ConfigResp> of <MultiConfigResp>
5084 Length
= CalculateConfigStringLen (StringPtr
);
5085 ConfigResp
= AllocateCopyPool ((Length
+ 1) * sizeof (CHAR16
), StringPtr
);
5086 if (ConfigResp
== NULL
) {
5087 return EFI_OUT_OF_RESOURCES
;
5090 // Append '\0' to the end of ConfigRequest
5092 *(ConfigResp
+ Length
) = 0;
5095 // Get the UEFI device path
5097 Status
= GetDevicePath (ConfigResp
, (UINT8
**) &DevicePath
);
5098 if (EFI_ERROR (Status
)) {
5099 FreePool (ConfigResp
);
5104 // Find driver which matches the routing data.
5106 DriverHandle
= NULL
;
5107 for (Link
= Private
->DatabaseList
.ForwardLink
;
5108 Link
!= &Private
->DatabaseList
;
5109 Link
= Link
->ForwardLink
5111 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
5113 if ((DevicePathPkg
= Database
->PackageList
->DevicePathPkg
) != NULL
) {
5114 CurrentDevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
5115 DevicePathSize
= GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) CurrentDevicePath
);
5116 if ((CompareMem (DevicePath
,CurrentDevicePath
,DevicePathSize
) == 0) && IsThisPackageList(Database
, ConfigResp
)) {
5117 DriverHandle
= Database
->DriverHandle
;
5124 // Try to find driver handle by device path.
5126 if (DriverHandle
== NULL
) {
5127 TempDevicePath
= DevicePath
;
5128 Status
= gBS
->LocateDevicePath (
5129 &gEfiDevicePathProtocolGuid
,
5133 if (EFI_ERROR (Status
) || (DriverHandle
== NULL
)) {
5135 // Routing data does not match any known driver.
5136 // Set Progress to the 'G' in "GUID" of the routing header.
5138 FreePool (DevicePath
);
5139 *Progress
= StringPtr
;
5140 FreePool (ConfigResp
);
5141 return EFI_NOT_FOUND
;
5145 FreePool (DevicePath
);
5148 // Check whether this ConfigRequest is search from Efi varstore type storage.
5150 Status
= GetVarStoreType(Database
, ConfigResp
, &IsEfiVarstore
, &EfiVarStoreInfo
);
5151 if (EFI_ERROR (Status
)) {
5155 if (IsEfiVarstore
) {
5157 // Call the SetVariable function to route settings.
5159 Status
= RouteConfigRespForEfiVarStore(This
, EfiVarStoreInfo
, ConfigResp
, &AccessProgress
);
5160 FreePool (EfiVarStoreInfo
);
5163 // Call corresponding ConfigAccess protocol to route settings
5165 Status
= gBS
->HandleProtocol (
5167 &gEfiHiiConfigAccessProtocolGuid
,
5168 (VOID
**) &ConfigAccess
5170 if (EFI_ERROR (Status
)) {
5171 *Progress
= StringPtr
;
5172 FreePool (ConfigResp
);
5173 return EFI_NOT_FOUND
;
5176 Status
= ConfigAccess
->RouteConfig (
5182 if (EFI_ERROR (Status
)) {
5183 ASSERT (AccessProgress
!= NULL
);
5185 // AccessProgress indicates the parsing progress on <ConfigResp>.
5186 // Map it to the progress on <MultiConfigResp> then return it.
5188 *Progress
= StrStr (StringPtr
, AccessProgress
);
5190 FreePool (ConfigResp
);
5194 FreePool (ConfigResp
);
5198 // Go to next <ConfigResp> (skip '&').
5200 StringPtr
+= Length
;
5201 if (*StringPtr
== 0) {
5202 *Progress
= StringPtr
;
5215 This helper function is to be called by drivers to map configuration data
5216 stored in byte array ("block") formats such as UEFI Variables into current
5217 configuration strings.
5219 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
5221 @param ConfigRequest A null-terminated Unicode string in
5222 <ConfigRequest> format.
5223 @param Block Array of bytes defining the block's configuration.
5224 @param BlockSize Length in bytes of Block.
5225 @param Config Filled-in configuration string. String allocated
5226 by the function. Returned only if call is
5227 successful. It is <ConfigResp> string format.
5228 @param Progress A pointer to a string filled in with the offset of
5229 the most recent & before the first failing
5230 name/value pair (or the beginning of the string if
5231 the failure is in the first name / value pair) or
5232 the terminating NULL if all was successful.
5234 @retval EFI_SUCCESS The request succeeded. Progress points to the null
5235 terminator at the end of the ConfigRequest
5237 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress
5238 points to the first character of ConfigRequest.
5239 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigRequest or
5240 Block parameter would result in this type of
5241 error. Progress points to the first character of
5243 @retval EFI_DEVICE_ERROR Block not large enough. Progress undefined.
5244 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted string.
5245 Block is left updated and Progress points at
5246 the "&" preceding the first non-<BlockName>.
5252 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
5253 IN CONST EFI_STRING ConfigRequest
,
5254 IN CONST UINT8
*Block
,
5255 IN CONST UINTN BlockSize
,
5256 OUT EFI_STRING
*Config
,
5257 OUT EFI_STRING
*Progress
5260 HII_DATABASE_PRIVATE_DATA
*Private
;
5261 EFI_STRING StringPtr
;
5269 EFI_STRING ValueStr
;
5270 EFI_STRING ConfigElement
;
5278 if (This
== NULL
|| Progress
== NULL
|| Config
== NULL
) {
5279 return EFI_INVALID_PARAMETER
;
5282 if (Block
== NULL
|| ConfigRequest
== NULL
) {
5283 *Progress
= ConfigRequest
;
5284 return EFI_INVALID_PARAMETER
;
5288 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
5289 ASSERT (Private
!= NULL
);
5291 StringPtr
= ConfigRequest
;
5294 ConfigElement
= NULL
;
5297 // Allocate a fix length of memory to store Results. Reallocate memory for
5298 // Results if this fix length is insufficient.
5300 *Config
= (EFI_STRING
) AllocateZeroPool (MAX_STRING_LENGTH
);
5301 if (*Config
== NULL
) {
5302 return EFI_OUT_OF_RESOURCES
;
5308 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
5309 *Progress
= StringPtr
;
5310 Status
= EFI_INVALID_PARAMETER
;
5313 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"PATH=", StrLen (L
"PATH=")) != 0) {
5316 if (*StringPtr
== 0) {
5317 *Progress
= StringPtr
- 1;
5318 Status
= EFI_INVALID_PARAMETER
;
5322 while (*StringPtr
!= L
'&' && *StringPtr
!= 0) {
5325 if (*StringPtr
== 0) {
5326 *Progress
= StringPtr
;
5328 AppendToMultiString(Config
, ConfigRequest
);
5329 HiiToLower (*Config
);
5339 // Copy <ConfigHdr> and an additional '&' to <ConfigResp>
5341 TemChar
= *StringPtr
;
5343 AppendToMultiString(Config
, ConfigRequest
);
5344 *StringPtr
= TemChar
;
5347 // Parse each <RequestElement> if exists
5348 // Only <BlockName> format is supported by this help function.
5349 // <BlockName> ::= 'OFFSET='<Number>&'WIDTH='<Number>
5351 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"OFFSET=", StrLen (L
"OFFSET=")) == 0) {
5353 // Back up the header of one <BlockName>
5357 StringPtr
+= StrLen (L
"OFFSET=");
5361 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
5362 if (EFI_ERROR (Status
)) {
5363 *Progress
= TmpPtr
- 1;
5370 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
5372 FreePool (TmpBuffer
);
5374 StringPtr
+= Length
;
5375 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
5376 *Progress
= TmpPtr
- 1;
5377 Status
= EFI_INVALID_PARAMETER
;
5380 StringPtr
+= StrLen (L
"&WIDTH=");
5385 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
5386 if (EFI_ERROR (Status
)) {
5387 *Progress
= TmpPtr
- 1;
5394 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
5396 FreePool (TmpBuffer
);
5398 StringPtr
+= Length
;
5399 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
5400 *Progress
= TmpPtr
- 1;
5401 Status
= EFI_INVALID_PARAMETER
;
5406 // Calculate Value and convert it to hex string.
5408 if (Offset
+ Width
> BlockSize
) {
5409 *Progress
= StringPtr
;
5410 Status
= EFI_DEVICE_ERROR
;
5414 Value
= (UINT8
*) AllocateZeroPool (Width
);
5415 if (Value
== NULL
) {
5416 *Progress
= ConfigRequest
;
5417 Status
= EFI_OUT_OF_RESOURCES
;
5421 CopyMem (Value
, (UINT8
*) Block
+ Offset
, Width
);
5423 Length
= Width
* 2 + 1;
5424 ValueStr
= (EFI_STRING
) AllocateZeroPool (Length
* sizeof (CHAR16
));
5425 if (ValueStr
== NULL
) {
5426 *Progress
= ConfigRequest
;
5427 Status
= EFI_OUT_OF_RESOURCES
;
5431 TemString
= ValueStr
;
5432 TemBuffer
= Value
+ Width
- 1;
5433 for (Index
= 0; Index
< Width
; Index
++, TemBuffer
--) {
5434 UnicodeValueToStringS (
5436 Length
* sizeof (CHAR16
) - ((UINTN
)TemString
- (UINTN
)ValueStr
),
5437 PREFIX_ZERO
| RADIX_HEX
,
5441 TemString
+= StrnLenS (TemString
, Length
- ((UINTN
)TemString
- (UINTN
)ValueStr
) / sizeof (CHAR16
));
5448 // Build a ConfigElement
5450 Length
+= StringPtr
- TmpPtr
+ 1 + StrLen (L
"VALUE=");
5451 ConfigElement
= (EFI_STRING
) AllocateZeroPool (Length
* sizeof (CHAR16
));
5452 if (ConfigElement
== NULL
) {
5453 Status
= EFI_OUT_OF_RESOURCES
;
5456 CopyMem (ConfigElement
, TmpPtr
, (StringPtr
- TmpPtr
+ 1) * sizeof (CHAR16
));
5457 if (*StringPtr
== 0) {
5458 *(ConfigElement
+ (StringPtr
- TmpPtr
)) = L
'&';
5460 *(ConfigElement
+ (StringPtr
- TmpPtr
) + 1) = 0;
5461 StrCatS (ConfigElement
, Length
, L
"VALUE=");
5462 StrCatS (ConfigElement
, Length
, ValueStr
);
5464 AppendToMultiString (Config
, ConfigElement
);
5466 FreePool (ConfigElement
);
5467 FreePool (ValueStr
);
5468 ConfigElement
= NULL
;
5472 // If '\0', parsing is finished. Otherwise skip '&' to continue
5474 if (*StringPtr
== 0) {
5477 AppendToMultiString (Config
, L
"&");
5482 if (*StringPtr
!= 0) {
5483 *Progress
= StringPtr
- 1;
5484 Status
= EFI_INVALID_PARAMETER
;
5488 HiiToLower (*Config
);
5489 *Progress
= StringPtr
;
5493 if (*Config
!= NULL
) {
5497 if (ValueStr
!= NULL
) {
5498 FreePool (ValueStr
);
5500 if (Value
!= NULL
) {
5503 if (ConfigElement
!= NULL
) {
5504 FreePool (ConfigElement
);
5513 This helper function is to be called by drivers to map configuration strings
5514 to configurations stored in byte array ("block") formats such as UEFI Variables.
5516 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
5518 @param ConfigResp A null-terminated Unicode string in <ConfigResp>
5520 @param Block A possibly null array of bytes representing the
5521 current block. Only bytes referenced in the
5522 ConfigResp string in the block are modified. If
5523 this parameter is null or if the *BlockSize
5524 parameter is (on input) shorter than required by
5525 the Configuration string, only the BlockSize
5526 parameter is updated and an appropriate status
5527 (see below) is returned.
5528 @param BlockSize The length of the Block in units of UINT8. On
5529 input, this is the size of the Block. On output,
5530 if successful, contains the largest index of the
5531 modified byte in the Block, or the required buffer
5532 size if the Block is not large enough.
5533 @param Progress On return, points to an element of the ConfigResp
5534 string filled in with the offset of the most
5535 recent '&' before the first failing name / value
5536 pair (or the beginning of the string if the
5537 failure is in the first name / value pair) or the
5538 terminating NULL if all was successful.
5540 @retval EFI_SUCCESS The request succeeded. Progress points to the null
5541 terminator at the end of the ConfigResp string.
5542 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress
5543 points to the first character of ConfigResp.
5544 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigResp or
5545 Block parameter would result in this type of
5546 error. Progress points to the first character of
5548 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted name /
5549 value pair. Block is left updated and
5550 Progress points at the '&' preceding the first
5552 @retval EFI_BUFFER_TOO_SMALL Block not large enough. Progress undefined.
5553 BlockSize is updated with the required buffer size.
5554 @retval EFI_NOT_FOUND Target for the specified routing data was not found.
5555 Progress points to the "G" in "GUID" of the errant
5562 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
5563 IN CONST EFI_STRING ConfigResp
,
5564 IN OUT UINT8
*Block
,
5565 IN OUT UINTN
*BlockSize
,
5566 OUT EFI_STRING
*Progress
5569 HII_DATABASE_PRIVATE_DATA
*Private
;
5570 EFI_STRING StringPtr
;
5583 if (This
== NULL
|| BlockSize
== NULL
|| Progress
== NULL
) {
5584 return EFI_INVALID_PARAMETER
;
5587 *Progress
= ConfigResp
;
5588 if (ConfigResp
== NULL
) {
5589 return EFI_INVALID_PARAMETER
;
5592 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
5593 ASSERT (Private
!= NULL
);
5595 StringPtr
= ConfigResp
;
5596 BufferSize
= *BlockSize
;
5603 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
5604 *Progress
= StringPtr
;
5605 Status
= EFI_INVALID_PARAMETER
;
5608 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"PATH=", StrLen (L
"PATH=")) != 0) {
5611 if (*StringPtr
== 0) {
5612 *Progress
= StringPtr
;
5613 Status
= EFI_INVALID_PARAMETER
;
5617 while (*StringPtr
!= L
'&' && *StringPtr
!= 0) {
5620 if (*StringPtr
== 0) {
5621 *Progress
= StringPtr
;
5622 Status
= EFI_INVALID_PARAMETER
;
5627 // Parse each <ConfigElement> if exists
5628 // Only '&'<BlockConfig> format is supported by this help function.
5629 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE='<Number>
5631 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) == 0) {
5633 StringPtr
+= StrLen (L
"&OFFSET=");
5637 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
5638 if (EFI_ERROR (Status
)) {
5646 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
5648 FreePool (TmpBuffer
);
5650 StringPtr
+= Length
;
5651 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
5653 Status
= EFI_INVALID_PARAMETER
;
5656 StringPtr
+= StrLen (L
"&WIDTH=");
5661 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
5662 if (EFI_ERROR (Status
)) {
5670 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
5672 FreePool (TmpBuffer
);
5674 StringPtr
+= Length
;
5675 if (StrnCmp (StringPtr
, L
"&VALUE=", StrLen (L
"&VALUE=")) != 0) {
5677 Status
= EFI_INVALID_PARAMETER
;
5680 StringPtr
+= StrLen (L
"&VALUE=");
5685 Status
= GetValueOfNumber (StringPtr
, &Value
, &Length
);
5686 if (EFI_ERROR (Status
)) {
5691 StringPtr
+= Length
;
5692 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
5694 Status
= EFI_INVALID_PARAMETER
;
5699 // Update the Block with configuration info
5701 if ((Block
!= NULL
) && (Offset
+ Width
<= BufferSize
)) {
5702 CopyMem (Block
+ Offset
, Value
, Width
);
5704 if (Offset
+ Width
> MaxBlockSize
) {
5705 MaxBlockSize
= Offset
+ Width
;
5712 // If '\0', parsing is finished.
5714 if (*StringPtr
== 0) {
5720 // The input string is not ConfigResp format, return error.
5722 if (*StringPtr
!= 0) {
5723 *Progress
= StringPtr
;
5724 Status
= EFI_INVALID_PARAMETER
;
5728 *Progress
= StringPtr
+ StrLen (StringPtr
);
5729 *BlockSize
= MaxBlockSize
- 1;
5731 if (MaxBlockSize
> BufferSize
) {
5732 *BlockSize
= MaxBlockSize
;
5733 if (Block
!= NULL
) {
5734 return EFI_BUFFER_TOO_SMALL
;
5738 if (Block
== NULL
) {
5739 *Progress
= ConfigResp
;
5740 return EFI_INVALID_PARAMETER
;
5747 if (Value
!= NULL
) {
5755 This helper function is to be called by drivers to extract portions of
5756 a larger configuration string.
5758 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
5760 @param Configuration A null-terminated Unicode string in
5761 <MultiConfigAltResp> format.
5762 @param Guid A pointer to the GUID value to search for in the
5763 routing portion of the ConfigResp string when
5764 retrieving the requested data. If Guid is NULL,
5765 then all GUID values will be searched for.
5766 @param Name A pointer to the NAME value to search for in the
5767 routing portion of the ConfigResp string when
5768 retrieving the requested data. If Name is NULL,
5769 then all Name values will be searched for.
5770 @param DevicePath A pointer to the PATH value to search for in the
5771 routing portion of the ConfigResp string when
5772 retrieving the requested data. If DevicePath is
5773 NULL, then all DevicePath values will be searched
5775 @param AltCfgId A pointer to the ALTCFG value to search for in the
5776 routing portion of the ConfigResp string when
5777 retrieving the requested data. If this parameter
5778 is NULL, then the current setting will be
5780 @param AltCfgResp A pointer to a buffer which will be allocated by
5781 the function which contains the retrieved string
5782 as requested. This buffer is only allocated if
5783 the call was successful. It is <ConfigResp> format.
5785 @retval EFI_SUCCESS The request succeeded. The requested data was
5786 extracted and placed in the newly allocated
5788 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate AltCfgResp.
5789 @retval EFI_INVALID_PARAMETER Any parameter is invalid.
5790 @retval EFI_NOT_FOUND Target for the specified routing data was not
5797 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
5798 IN CONST EFI_STRING Configuration
,
5799 IN CONST EFI_GUID
*Guid
,
5800 IN CONST EFI_STRING Name
,
5801 IN CONST EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
5802 IN CONST UINT16
*AltCfgId
,
5803 OUT EFI_STRING
*AltCfgResp
5807 EFI_STRING StringPtr
;
5808 EFI_STRING HdrStart
;
5815 EFI_STRING AltIdStr
;
5832 if (This
== NULL
|| Configuration
== NULL
|| AltCfgResp
== NULL
) {
5833 return EFI_INVALID_PARAMETER
;
5836 StringPtr
= Configuration
;
5837 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
5838 return EFI_INVALID_PARAMETER
;
5842 // Generate the sub string for later matching.
5844 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*) Guid
, 1, &GuidStr
);
5847 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) DevicePath
),
5848 (VOID
*) DevicePath
,
5852 if (AltCfgId
!= NULL
) {
5853 GenerateSubStr (L
"ALTCFG=", sizeof (UINT16
), (VOID
*) AltCfgId
, 3, &AltIdStr
);
5856 GenerateSubStr (L
"NAME=", StrLen (Name
) * sizeof (CHAR16
), (VOID
*) Name
, 2, &NameStr
);
5858 GenerateSubStr (L
"NAME=", 0, NULL
, 2, &NameStr
);
5861 while (*StringPtr
!= 0) {
5863 // Try to match the GUID
5866 TmpPtr
= StrStr (StringPtr
, GuidStr
);
5867 if (TmpPtr
== NULL
) {
5868 Status
= EFI_NOT_FOUND
;
5874 // Jump to <NameHdr>
5877 StringPtr
= TmpPtr
+ StrLen (GuidStr
);
5879 StringPtr
= StrStr (TmpPtr
, L
"NAME=");
5880 if (StringPtr
== NULL
) {
5881 Status
= EFI_NOT_FOUND
;
5889 // Try to match the NAME
5891 if (GuidFlag
&& !NameFlag
) {
5892 if (StrnCmp (StringPtr
, NameStr
, StrLen (NameStr
)) != 0) {
5896 // Jump to <PathHdr>
5899 StringPtr
+= StrLen (NameStr
);
5901 StringPtr
= StrStr (StringPtr
, L
"PATH=");
5902 if (StringPtr
== NULL
) {
5903 Status
= EFI_NOT_FOUND
;
5912 // Try to match the DevicePath
5914 if (GuidFlag
&& NameFlag
&& !PathFlag
) {
5915 if (StrnCmp (StringPtr
, PathStr
, StrLen (PathStr
)) != 0) {
5920 // Jump to '&' before <DescHdr> or <ConfigBody>
5922 if (DevicePath
!= NULL
) {
5923 StringPtr
+= StrLen (PathStr
);
5925 StringPtr
= StrStr (StringPtr
, L
"&");
5926 if (StringPtr
== NULL
) {
5927 Status
= EFI_NOT_FOUND
;
5938 // Try to match the AltCfgId
5940 if (GuidFlag
&& NameFlag
&& PathFlag
) {
5941 if (AltCfgId
== NULL
) {
5943 // Return Current Setting when AltCfgId is NULL.
5945 Status
= OutputConfigBody (StringPtr
, &Result
);
5949 // Search the <ConfigAltResp> to get the <AltResp> with AltCfgId.
5951 if (StrnCmp (StringPtr
, AltIdStr
, StrLen (AltIdStr
)) != 0) {
5957 // Skip AltIdStr and &
5959 StringPtr
= StringPtr
+ StrLen (AltIdStr
);
5960 Status
= OutputConfigBody (StringPtr
, &Result
);
5966 Status
= EFI_NOT_FOUND
;
5970 if (!EFI_ERROR (Status
) && (Result
!= NULL
)) {
5972 // Copy the <ConfigHdr> and <ConfigBody>
5974 Length
= HdrEnd
- HdrStart
+ StrLen (Result
) + 1;
5975 *AltCfgResp
= AllocateZeroPool (Length
* sizeof (CHAR16
));
5976 if (*AltCfgResp
== NULL
) {
5977 Status
= EFI_OUT_OF_RESOURCES
;
5979 StrnCpyS (*AltCfgResp
, Length
, HdrStart
, HdrEnd
- HdrStart
);
5980 StrCatS (*AltCfgResp
, Length
, Result
);
5981 Status
= EFI_SUCCESS
;
5985 if (GuidStr
!= NULL
) {
5988 if (NameStr
!= NULL
) {
5991 if (PathStr
!= NULL
) {
5994 if (AltIdStr
!= NULL
) {
5995 FreePool (AltIdStr
);
5997 if (Result
!= NULL
) {