2 Implementation of interfaces function for EFI_HII_CONFIG_ROUTING_PROTOCOL.
4 Copyright (c) 2007 - 2016, 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 neccesary 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 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
272 // Check buffer is enough
274 TemName
= (CHAR16
*) Buffer
;
275 ASSERT ((BufferLen
* 2 + 1) >= (StrLen (TemName
) * 4 + 1));
277 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
279 for (; *TemName
!= L
'\0'; TemName
++) {
280 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemName
, 4);
285 // Convert Buffer to Hex String
287 TemBuffer
= ((UINT8
*) Buffer
) + BufferLen
- 1;
288 for (Index
= 0; Index
< BufferLen
; Index
++, TemBuffer
--) {
289 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
297 // Convert the uppercase to lowercase since <HexAf> is defined in lowercase format.
299 StrCatS (Str
, Length
, L
"&");
307 Retrieve the <ConfigBody> from String then output it.
309 This is a internal function.
311 @param String A sub string of a configuration string in
312 <MultiConfigAltResp> format.
313 @param ConfigBody Points to the output string. It's caller's
314 responsibility to free this buffer.
316 @retval EFI_INVALID_PARAMETER There is no form package in current hii database.
317 @retval EFI_OUT_OF_RESOURCES Not enough memory to finish this operation.
318 @retval EFI_SUCCESS All existing storage is exported.
323 IN EFI_STRING String
,
324 OUT EFI_STRING
*ConfigBody
331 if (String
== NULL
|| ConfigBody
== NULL
) {
332 return EFI_INVALID_PARAMETER
;
336 // The setting information should start OFFSET, not ALTCFG.
338 if (StrnCmp (String
, L
"&ALTCFG=", StrLen (L
"&ALTCFG=")) == 0) {
339 return EFI_INVALID_PARAMETER
;
342 TmpPtr
= StrStr (String
, L
"GUID=");
343 if (TmpPtr
== NULL
) {
345 // It is the last <ConfigResp> of the incoming configuration string.
347 Result
= AllocateCopyPool (StrSize (String
), String
);
348 if (Result
== NULL
) {
349 return EFI_OUT_OF_RESOURCES
;
351 *ConfigBody
= Result
;
356 Length
= TmpPtr
- String
;
358 return EFI_NOT_FOUND
;
360 Result
= AllocateCopyPool (Length
* sizeof (CHAR16
), String
);
361 if (Result
== NULL
) {
362 return EFI_OUT_OF_RESOURCES
;
365 *(Result
+ Length
- 1) = 0;
366 *ConfigBody
= Result
;
371 Append a string to a multi-string format.
373 This is a internal function.
375 @param MultiString String in <MultiConfigRequest>,
376 <MultiConfigAltResp>, or <MultiConfigResp>. On
377 input, the buffer length of this string is
378 MAX_STRING_LENGTH. On output, the buffer length
380 @param AppendString NULL-terminated Unicode string.
382 @retval EFI_INVALID_PARAMETER Any incoming parameter is invalid.
383 @retval EFI_SUCCESS AppendString is append to the end of MultiString
387 AppendToMultiString (
388 IN OUT EFI_STRING
*MultiString
,
389 IN EFI_STRING AppendString
392 UINTN AppendStringSize
;
393 UINTN MultiStringSize
;
396 if (MultiString
== NULL
|| *MultiString
== NULL
|| AppendString
== NULL
) {
397 return EFI_INVALID_PARAMETER
;
400 AppendStringSize
= StrSize (AppendString
);
401 MultiStringSize
= StrSize (*MultiString
);
402 MaxLen
= MAX_STRING_LENGTH
/ sizeof (CHAR16
);
405 // Enlarge the buffer each time when length exceeds MAX_STRING_LENGTH.
407 if (MultiStringSize
+ AppendStringSize
> MAX_STRING_LENGTH
||
408 MultiStringSize
> MAX_STRING_LENGTH
) {
409 *MultiString
= (EFI_STRING
) ReallocatePool (
411 MultiStringSize
+ AppendStringSize
,
412 (VOID
*) (*MultiString
)
414 MaxLen
= (MultiStringSize
+ AppendStringSize
) / sizeof (CHAR16
);
415 ASSERT (*MultiString
!= NULL
);
418 // Append the incoming string
420 StrCatS (*MultiString
, MaxLen
, AppendString
);
427 Get the value of <Number> in <BlockConfig> format, i.e. the value of OFFSET
429 <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>
431 This is a internal function.
433 @param StringPtr String in <BlockConfig> format and points to the
434 first character of <Number>.
435 @param Number The output value. Caller takes the responsibility
437 @param Len Length of the <Number>, in characters.
439 @retval EFI_OUT_OF_RESOURCES Insufficient resources to store neccessary
441 @retval EFI_SUCCESS Value of <Number> is outputted in Number
447 IN EFI_STRING StringPtr
,
461 if (StringPtr
== NULL
|| *StringPtr
== L
'\0' || Number
== NULL
|| Len
== NULL
) {
462 return EFI_INVALID_PARAMETER
;
468 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
471 *Len
= StringPtr
- TmpPtr
;
474 Str
= (EFI_STRING
) AllocateZeroPool (Length
* sizeof (CHAR16
));
476 Status
= EFI_OUT_OF_RESOURCES
;
479 CopyMem (Str
, TmpPtr
, *Len
* sizeof (CHAR16
));
480 *(Str
+ *Len
) = L
'\0';
482 Length
= (Length
+ 1) / 2;
483 Buf
= (UINT8
*) AllocateZeroPool (Length
);
485 Status
= EFI_OUT_OF_RESOURCES
;
490 ZeroMem (TemStr
, sizeof (TemStr
));
491 for (Index
= 0; Index
< Length
; Index
++) {
492 TemStr
[0] = Str
[Length
- Index
- 1];
493 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
494 if ((Index
& 1) == 0) {
495 Buf
[Index
/2] = DigitUint8
;
497 Buf
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Buf
[Index
/2]);
502 Status
= EFI_SUCCESS
;
513 To find the BlockName in the string with same value.
515 @param String Pointer to a Null-terminated Unicode string.
516 @param BlockName Pointer to a Null-terminated Unicode string to search for.
517 @param Buffer Pointer to the value correspond to the BlockName.
518 @param Found The Block whether has been found.
519 @param BufferLen The length of the buffer.
521 @retval EFI_OUT_OF_RESOURCES Insufficient resources to store neccessary structures.
522 @retval EFI_SUCCESS The function finishes successfully.
526 FindSameBlockElement(
527 IN EFI_STRING String
,
528 IN EFI_STRING BlockName
,
541 BlockPtr
= StrStr (String
, BlockName
);
543 while (BlockPtr
!= NULL
) {
544 BlockPtr
+= StrLen (BlockName
);
545 Status
= GetValueOfNumber (BlockPtr
, &TempBuffer
, &Length
);
546 if (EFI_ERROR (Status
)) {
549 ASSERT (TempBuffer
!= NULL
);
550 if ((BufferLen
== Length
) && (0 == CompareMem (Buffer
, TempBuffer
, Length
))) {
554 FreePool (TempBuffer
);
556 BlockPtr
= StrStr (BlockPtr
+ 1, BlockName
);
563 Compare the <AltResp> in ConfigAltResp and DefaultAltCfgResp, if the <AltResp>
564 in DefaultAltCfgResp but not in ConfigAltResp,add it to the ConfigAltResp.
566 @param DefaultAltCfgResp Pointer to a null-terminated Unicode string in
567 <MultiConfigAltResp> format. The default value
568 string may contain more than one ConfigAltResp
569 string for the different varstore buffer.
570 @param ConfigAltResp Pointer to a null-terminated Unicode string in
571 <ConfigAltResp> format.
572 @param AltConfigHdr Pointer to a Unicode string in <AltConfigHdr> format.
573 @param ConfigAltRespChanged Whether the ConfigAltResp has been changed.
575 @retval EFI_OUT_OF_RESOURCES Insufficient resources to store neccessary structures.
576 @retval EFI_SUCCESS The function finishes successfully.
580 CompareBlockElementDefault (
581 IN EFI_STRING DefaultAltCfgResp
,
582 IN OUT EFI_STRING
*ConfigAltResp
,
583 IN EFI_STRING AltConfigHdr
,
584 IN OUT BOOLEAN
*ConfigAltRespChanged
589 EFI_STRING BlockPtrStart
;
590 EFI_STRING StringPtr
;
591 EFI_STRING AppendString
;
592 EFI_STRING AltConfigHdrPtr
;
602 // Make BlockPtr point to the first <BlockConfig> with AltConfigHdr in DefaultAltCfgResp.
604 AltConfigHdrPtr
= StrStr (DefaultAltCfgResp
, AltConfigHdr
);
605 ASSERT (AltConfigHdrPtr
!= NULL
);
606 BlockPtr
= StrStr (AltConfigHdrPtr
, L
"&OFFSET=");
608 // Make StringPtr point to the AltConfigHdr in ConfigAltResp.
610 StringPtr
= StrStr (*ConfigAltResp
, AltConfigHdr
);
611 ASSERT (StringPtr
!= NULL
);
613 while (BlockPtr
!= NULL
) {
615 // Find the "&OFFSET=<Number>" block and get the value of the Number with AltConfigHdr in DefaultAltCfgResp.
617 BlockPtrStart
= BlockPtr
;
618 BlockPtr
+= StrLen (L
"&OFFSET=");
619 Status
= GetValueOfNumber (BlockPtr
, &TempBuffer
, &OffsetLength
);
620 if (EFI_ERROR (Status
)) {
621 Status
= EFI_OUT_OF_RESOURCES
;
625 // To find the same "&OFFSET=<Number>" block in ConfigAltResp.
627 Status
= FindSameBlockElement (StringPtr
, L
"&OFFSET=", TempBuffer
, &FoundOffset
, OffsetLength
);
628 if (TempBuffer
!= NULL
) {
629 FreePool (TempBuffer
);
632 if (EFI_ERROR (Status
)) {
633 Status
= EFI_OUT_OF_RESOURCES
;
638 // Don't find the same "&OFFSET=<Number>" block in ConfigAltResp.
639 // Calculate the size of <BlockConfig>.
640 // <BlockConfig>::='OFFSET='<Number>'&WIDTH='<Number>'&VALUE='<Number>.
642 BlockPtr
= StrStr (BlockPtr
+ 1, L
"&OFFSET=");
643 if (BlockPtr
!= NULL
) {
644 AppendSize
= (BlockPtr
- BlockPtrStart
) * sizeof (CHAR16
);
646 AppendSize
= StrSize (BlockPtrStart
);
649 // Copy the <BlockConfig> to AppendString.
651 if (AppendString
== NULL
) {
652 AppendString
= (EFI_STRING
) AllocateZeroPool (AppendSize
+ sizeof (CHAR16
));
653 StrnCatS (AppendString
, AppendSize
/ sizeof (CHAR16
) + 1, BlockPtrStart
, AppendSize
/ sizeof (CHAR16
));
655 TotalSize
= StrSize (AppendString
) + AppendSize
+ sizeof (CHAR16
);
656 AppendString
= (EFI_STRING
) ReallocatePool (
657 StrSize (AppendString
),
661 if (AppendString
== NULL
) {
662 Status
= EFI_OUT_OF_RESOURCES
;
665 StrnCatS (AppendString
, TotalSize
/ sizeof (CHAR16
), BlockPtrStart
, AppendSize
/ sizeof (CHAR16
));
669 // To find next "&OFFSET=<Number>" block with AltConfigHdr in DefaultAltCfgResp.
671 BlockPtr
= StrStr (BlockPtr
+ 1, L
"&OFFSET=");
675 if (AppendString
!= NULL
) {
677 // Reallocate ConfigAltResp to copy the AppendString.
679 TotalSize
= StrSize (*ConfigAltResp
) + StrSize (AppendString
) + sizeof (CHAR16
);
680 *ConfigAltResp
= (EFI_STRING
) ReallocatePool (
681 StrSize (*ConfigAltResp
),
685 if (*ConfigAltResp
== NULL
) {
686 Status
= EFI_OUT_OF_RESOURCES
;
689 StrCatS (*ConfigAltResp
, TotalSize
/ sizeof (CHAR16
), AppendString
);
690 *ConfigAltRespChanged
= TRUE
;
693 Status
= EFI_SUCCESS
;
696 if (AppendString
!= NULL
) {
697 FreePool (AppendString
);
704 Compare the <AltResp> in ConfigAltResp and DefaultAltCfgResp, if the <AltResp>
705 in DefaultAltCfgResp but not in ConfigAltResp,add it to the ConfigAltResp.
707 @param DefaultAltCfgResp Pointer to a null-terminated Unicode string in
708 <MultiConfigAltResp> format. The default value
709 string may contain more than one ConfigAltResp
710 string for the different varstore buffer.
711 @param ConfigAltResp Pointer to a null-terminated Unicode string in
712 <ConfigAltResp> format.
713 @param AltConfigHdr Pointer to a Unicode string in <AltConfigHdr> format.
714 @param ConfigAltRespChanged Whether the ConfigAltResp has been changed.
716 @retval EFI_OUT_OF_RESOURCES Insufficient resources to store neccessary structures.
717 @retval EFI_SUCCESS The function finishes successfully.
721 CompareNameElementDefault (
722 IN EFI_STRING DefaultAltCfgResp
,
723 IN OUT EFI_STRING
*ConfigAltResp
,
724 IN EFI_STRING AltConfigHdr
,
725 IN OUT BOOLEAN
*ConfigAltRespChanged
729 EFI_STRING NvConfigPtr
;
730 EFI_STRING NvConfigStart
;
731 EFI_STRING NvConfigValuePtr
;
732 EFI_STRING StringPtr
;
733 EFI_STRING NvConfigExist
;
734 EFI_STRING AppendString
;
740 NvConfigExist
= NULL
;
742 // Make NvConfigPtr point to the first <NvConfig> with AltConfigHdr in DefaultAltCfgResp.
744 NvConfigPtr
= StrStr (DefaultAltCfgResp
, AltConfigHdr
);
745 ASSERT (NvConfigPtr
!= NULL
);
746 NvConfigPtr
= StrStr (NvConfigPtr
+ StrLen(AltConfigHdr
),L
"&");
748 // Make StringPtr point to the first <NvConfig> with AltConfigHdr in ConfigAltResp.
750 StringPtr
= StrStr (*ConfigAltResp
, AltConfigHdr
);
751 ASSERT (StringPtr
!= NULL
);
752 StringPtr
= StrStr (StringPtr
+ StrLen (AltConfigHdr
), L
"&");
753 ASSERT (StringPtr
!= NULL
);
755 while (NvConfigPtr
!= NULL
) {
757 // <NvConfig> ::= <Label>'='<String> | <Label>'='<Number>.
758 // Get the <Label> with AltConfigHdr in DefaultAltCfgResp.
760 NvConfigStart
= NvConfigPtr
;
761 NvConfigValuePtr
= StrStr (NvConfigPtr
+ 1, L
"=");
762 ASSERT (NvConfigValuePtr
!= NULL
);
763 TempChar
= *NvConfigValuePtr
;
764 *NvConfigValuePtr
= L
'\0';
766 // Get the <Label> with AltConfigHdr in ConfigAltResp.
768 NvConfigExist
= StrStr (StringPtr
, NvConfigPtr
);
769 if (NvConfigExist
== NULL
) {
771 // Don't find same <Label> in ConfigAltResp.
772 // Calculate the size of <NvConfig>.
774 *NvConfigValuePtr
= TempChar
;
775 NvConfigPtr
= StrStr (NvConfigPtr
+ 1, L
"&");
776 if (NvConfigPtr
!= NULL
) {
777 AppendSize
= (NvConfigPtr
- NvConfigStart
) * sizeof (CHAR16
);
779 AppendSize
= StrSize (NvConfigStart
);
782 // Copy the <NvConfig> to AppendString.
784 if (AppendString
== NULL
) {
785 AppendString
= (EFI_STRING
) AllocateZeroPool (AppendSize
+ sizeof (CHAR16
));
786 StrnCatS (AppendString
, AppendSize
/ sizeof (CHAR16
) + 1, NvConfigStart
, AppendSize
/ sizeof (CHAR16
));
788 TotalSize
= StrSize (AppendString
) + AppendSize
+ sizeof (CHAR16
);
789 AppendString
= (EFI_STRING
) ReallocatePool (
790 StrSize (AppendString
),
794 if (AppendString
== NULL
) {
795 Status
= EFI_OUT_OF_RESOURCES
;
798 StrnCatS (AppendString
, TotalSize
/ sizeof (CHAR16
), NvConfigStart
, AppendSize
/ sizeof (CHAR16
));
802 // To find next <Label> in DefaultAltCfgResp.
804 *NvConfigValuePtr
= TempChar
;
805 NvConfigPtr
= StrStr (NvConfigPtr
+ 1, L
"&");
808 if (AppendString
!= NULL
) {
810 // Reallocate ConfigAltResp to copy the AppendString.
812 TotalSize
= StrSize (*ConfigAltResp
) + StrSize (AppendString
) + sizeof (CHAR16
);
813 *ConfigAltResp
= (EFI_STRING
) ReallocatePool (
814 StrSize (*ConfigAltResp
),
815 StrSize (*ConfigAltResp
) + StrSize (AppendString
) + sizeof (CHAR16
),
818 if (*ConfigAltResp
== NULL
) {
819 Status
= EFI_OUT_OF_RESOURCES
;
822 StrCatS (*ConfigAltResp
, TotalSize
/ sizeof (CHAR16
), AppendString
);
823 *ConfigAltRespChanged
= TRUE
;
825 Status
= EFI_SUCCESS
;
828 if (AppendString
!= NULL
) {
829 FreePool (AppendString
);
835 Compare the <AltResp> in AltCfgResp and DefaultAltCfgResp, if the <AltResp>
836 in DefaultAltCfgResp but not in AltCfgResp,add it to the AltCfgResp.
838 @param AltCfgResp Pointer to a null-terminated Unicode string in
839 <ConfigAltResp> format.
840 @param DefaultAltCfgResp Pointer to a null-terminated Unicode string in
841 <MultiConfigAltResp> format. The default value
842 string may contain more than one ConfigAltResp
843 string for the different varstore buffer.
844 @param AltConfigHdr Pointer to a Unicode string in <AltConfigHdr> format.
846 @retval EFI_OUT_OF_RESOURCES Insufficient resources to store neccessary
848 @retval EFI_SUCCESS The function finishes successfully.
852 CompareAndMergeDefaultString (
853 IN OUT EFI_STRING
*AltCfgResp
,
854 IN EFI_STRING DefaultAltCfgResp
,
855 IN EFI_STRING AltConfigHdr
859 EFI_STRING AltCfgRespBackup
;
860 EFI_STRING AltConfigHdrPtr
;
861 EFI_STRING AltConfigHdrPtrNext
;
862 EFI_STRING ConfigAltResp
;
863 EFI_STRING StringPtr
;
864 EFI_STRING StringPtrNext
;
866 UINTN ReallocateSize
;
869 BOOLEAN ConfigAltRespChanged
;
871 Status
= EFI_OUT_OF_RESOURCES
;
873 AltConfigHdrPtrNext
= NULL
;
874 StringPtrNext
= NULL
;
875 ConfigAltResp
= NULL
;
876 AltCfgRespBackup
= NULL
;
879 ConfigAltRespChanged
= FALSE
;
882 //To find the <AltResp> with AltConfigHdr in DefaultAltCfgResp, ignore other <AltResp> which follow it.
884 AltConfigHdrPtr
= StrStr (DefaultAltCfgResp
, AltConfigHdr
);
885 ASSERT (AltConfigHdrPtr
!= NULL
);
886 AltConfigHdrPtrNext
= StrStr (AltConfigHdrPtr
+ 1, L
"&GUID");
887 if (AltConfigHdrPtrNext
!= NULL
) {
888 TempChar
= *AltConfigHdrPtrNext
;
889 *AltConfigHdrPtrNext
= L
'\0';
892 // To find the <AltResp> with AltConfigHdr in AltCfgResp, ignore other <AltResp> which follow it.
894 StringPtr
= StrStr (*AltCfgResp
, AltConfigHdr
);
895 StringPtrNext
= StrStr (StringPtr
+ 1, L
"&GUID");
896 if (StringPtrNext
!= NULL
) {
897 TempCharA
= *StringPtrNext
;
898 *StringPtrNext
= L
'\0';
901 // Copy the content of <ConfigAltResp> which contain current AltConfigHdr in AltCfgResp.
903 ConfigAltResp
= AllocateCopyPool (StrSize (*AltCfgResp
), *AltCfgResp
);
904 if (ConfigAltResp
== NULL
) {
908 // To find the <ConfigBody> with AltConfigHdr in DefaultAltCfgResp.
910 BlockPtr
= StrStr (AltConfigHdrPtr
, L
"&OFFSET=");
911 if (BlockPtr
!= NULL
) {
913 // <BlockConfig>::='OFFSET='<Number>'&WIDTH='<Number>'&VALUE='<Number> style.
914 // Call function CompareBlockElementDefault to compare the <BlockConfig> in DefaultAltCfgResp and ConfigAltResp.
915 // The ConfigAltResp which may contain the new <BlockConfig> get from DefaultAltCfgResp.
917 Status
= CompareBlockElementDefault (DefaultAltCfgResp
, &ConfigAltResp
, AltConfigHdr
, &ConfigAltRespChanged
);
918 if (EFI_ERROR(Status
)) {
923 // <NvConfig> ::= <Label>'='<String> | <Label>'='<Number> style.
924 // Call function CompareNameElementDefault to compare the <NvConfig> in DefaultAltCfgResp and ConfigAltResp.
925 // The ConfigAltResp which may contain the new <NvConfig> get from DefaultAltCfgResp.
927 Status
= CompareNameElementDefault (DefaultAltCfgResp
, &ConfigAltResp
, AltConfigHdr
, &ConfigAltRespChanged
);
928 if (EFI_ERROR(Status
)) {
933 // Restore the AltCfgResp.
935 if (StringPtrNext
!= NULL
) {
936 *StringPtrNext
= TempCharA
;
940 // If the ConfigAltResp has no change,no need to update the content in AltCfgResp.
942 if (!ConfigAltRespChanged
) {
943 Status
= EFI_SUCCESS
;
947 // ConfigAltResp has been changed, need to update the content in AltCfgResp.
949 if (StringPtrNext
!= NULL
) {
950 ReallocateSize
= StrSize (ConfigAltResp
) + StrSize (StringPtrNext
) + sizeof (CHAR16
);
952 ReallocateSize
= StrSize (ConfigAltResp
) + sizeof (CHAR16
);
955 AltCfgRespBackup
= (EFI_STRING
) AllocateZeroPool (ReallocateSize
);
956 if (AltCfgRespBackup
== NULL
) {
960 StrCatS (AltCfgRespBackup
, ReallocateSize
/ sizeof (CHAR16
), ConfigAltResp
);
961 if (StringPtrNext
!= NULL
) {
962 StrCatS (AltCfgRespBackup
, ReallocateSize
/ sizeof (CHAR16
), StringPtrNext
);
965 FreePool (*AltCfgResp
);
966 *AltCfgResp
= AltCfgRespBackup
;
968 Status
= EFI_SUCCESS
;
971 if (ConfigAltResp
!= NULL
) {
972 FreePool(ConfigAltResp
);
975 // Restore the DefaultAltCfgResp.
977 if ( AltConfigHdrPtrNext
!= NULL
) {
978 *AltConfigHdrPtrNext
= TempChar
;
979 AltConfigHdrPtrNext
= NULL
;
986 This function merges DefaultAltCfgResp string into AltCfgResp string for
987 the missing AltCfgId in AltCfgResq.
989 @param AltCfgResp Pointer to a null-terminated Unicode string in
990 <ConfigAltResp> format. The default value string
991 will be merged into it.
992 @param DefaultAltCfgResp Pointer to a null-terminated Unicode string in
993 <MultiConfigAltResp> format. The default value
994 string may contain more than one ConfigAltResp
995 string for the different varstore buffer.
997 @retval EFI_SUCCESS The merged string returns.
998 @retval EFI_INVALID_PARAMETER *AltCfgResp is to NULL.
1002 MergeDefaultString (
1003 IN OUT EFI_STRING
*AltCfgResp
,
1004 IN EFI_STRING DefaultAltCfgResp
1007 EFI_STRING StringPtrDefault
;
1008 EFI_STRING StringPtrEnd
;
1010 EFI_STRING StringPtr
;
1011 EFI_STRING AltConfigHdr
;
1013 UINTN SizeAltCfgResp
;
1017 if (*AltCfgResp
== NULL
) {
1018 return EFI_INVALID_PARAMETER
;
1022 // Get the requestr ConfigHdr
1025 StringPtr
= *AltCfgResp
;
1028 // Find <ConfigHdr> GUID=...&NAME=...&PATH=...
1030 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
1031 return EFI_INVALID_PARAMETER
;
1033 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&NAME=", StrLen (L
"&NAME=")) != 0) {
1036 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&PATH=", StrLen (L
"&PATH=")) != 0) {
1039 if (*StringPtr
== L
'\0') {
1040 return EFI_INVALID_PARAMETER
;
1042 StringPtr
+= StrLen (L
"&PATH=");
1043 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
1046 HeaderLength
= StringPtr
- *AltCfgResp
;
1049 // Construct AltConfigHdr string "&<ConfigHdr>&ALTCFG=XXXX\0"
1050 // |1| StrLen (ConfigHdr) | 8 | 4 | 1 |
1052 MaxLen
= 1 + HeaderLength
+ 8 + 4 + 1;
1053 AltConfigHdr
= AllocateZeroPool (MaxLen
* sizeof (CHAR16
));
1054 if (AltConfigHdr
== NULL
) {
1055 return EFI_OUT_OF_RESOURCES
;
1057 StrCpyS (AltConfigHdr
, MaxLen
, L
"&");
1058 StrnCatS (AltConfigHdr
, MaxLen
, *AltCfgResp
, HeaderLength
);
1059 StrCatS (AltConfigHdr
, MaxLen
, L
"&ALTCFG=");
1060 HeaderLength
= StrLen (AltConfigHdr
);
1062 StringPtrDefault
= StrStr (DefaultAltCfgResp
, AltConfigHdr
);
1063 while (StringPtrDefault
!= NULL
) {
1067 StrnCatS (AltConfigHdr
, MaxLen
, StringPtrDefault
+ HeaderLength
, 4);
1068 StringPtr
= StrStr (*AltCfgResp
, AltConfigHdr
);
1071 // Append the found default value string to the input AltCfgResp
1073 if (StringPtr
== NULL
) {
1074 StringPtrEnd
= StrStr (StringPtrDefault
+ 1, L
"&GUID");
1075 SizeAltCfgResp
= StrSize (*AltCfgResp
);
1076 if (StringPtrEnd
== NULL
) {
1078 // No more default string is found.
1080 TotalSize
= SizeAltCfgResp
+ StrSize (StringPtrDefault
);
1081 *AltCfgResp
= (EFI_STRING
) ReallocatePool (
1084 (VOID
*) (*AltCfgResp
)
1086 if (*AltCfgResp
== NULL
) {
1087 FreePool (AltConfigHdr
);
1088 return EFI_OUT_OF_RESOURCES
;
1090 StrCatS (*AltCfgResp
, TotalSize
/ sizeof (CHAR16
), StringPtrDefault
);
1093 TempChar
= *StringPtrEnd
;
1094 *StringPtrEnd
= L
'\0';
1095 TotalSize
= SizeAltCfgResp
+ StrSize (StringPtrDefault
);
1096 *AltCfgResp
= (EFI_STRING
) ReallocatePool (
1099 (VOID
*) (*AltCfgResp
)
1101 if (*AltCfgResp
== NULL
) {
1102 FreePool (AltConfigHdr
);
1103 return EFI_OUT_OF_RESOURCES
;
1105 StrCatS (*AltCfgResp
, TotalSize
/ sizeof (CHAR16
), StringPtrDefault
);
1106 *StringPtrEnd
= TempChar
;
1110 // The AltCfgResp contains <AltCfgResp>.
1111 // If the <ConfigElement> in <AltCfgResp> in the DefaultAltCfgResp but not in the
1112 // related <AltCfgResp> in AltCfgResp, merge it to AltCfgResp. else no need to merge.
1114 CompareAndMergeDefaultString (AltCfgResp
, DefaultAltCfgResp
, AltConfigHdr
);
1118 // Find next AltCfg String
1120 *(AltConfigHdr
+ HeaderLength
) = L
'\0';
1121 StringPtrDefault
= StrStr (StringPtrDefault
+ 1, AltConfigHdr
);
1124 FreePool (AltConfigHdr
);
1129 This function inserts new DefaultValueData into the BlockData DefaultValue array.
1131 @param BlockData The BlockData is updated to add new default value.
1132 @param DefaultValueData The DefaultValue is added.
1136 InsertDefaultValue (
1137 IN IFR_BLOCK_DATA
*BlockData
,
1138 IN IFR_DEFAULT_DATA
*DefaultValueData
1142 IFR_DEFAULT_DATA
*DefaultValueArray
;
1143 LIST_ENTRY
*DefaultLink
;
1145 DefaultLink
= &BlockData
->DefaultValueEntry
;
1147 for (Link
= DefaultLink
->ForwardLink
; Link
!= DefaultLink
; Link
= Link
->ForwardLink
) {
1148 DefaultValueArray
= BASE_CR (Link
, IFR_DEFAULT_DATA
, Entry
);
1149 if (DefaultValueArray
->DefaultId
== DefaultValueData
->DefaultId
) {
1151 // DEFAULT_VALUE_FROM_OPCODE has high priority, DEFAULT_VALUE_FROM_DEFAULT has low priority.
1153 if (DefaultValueData
->Type
> DefaultValueArray
->Type
) {
1155 // Update the default value array in BlockData.
1157 CopyMem (&DefaultValueArray
->Value
, &DefaultValueData
->Value
, sizeof (EFI_IFR_TYPE_VALUE
));
1158 DefaultValueArray
->Type
= DefaultValueData
->Type
;
1159 DefaultValueArray
->Cleaned
= DefaultValueData
->Cleaned
;
1166 // Insert new default value data in tail.
1168 DefaultValueArray
= AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
1169 ASSERT (DefaultValueArray
!= NULL
);
1170 CopyMem (DefaultValueArray
, DefaultValueData
, sizeof (IFR_DEFAULT_DATA
));
1171 InsertTailList (Link
, &DefaultValueArray
->Entry
);
1175 This function inserts new BlockData into the block link
1177 @param BlockLink The list entry points to block array.
1178 @param BlockData The point to BlockData is added.
1183 IN LIST_ENTRY
*BlockLink
,
1184 IN IFR_BLOCK_DATA
**BlockData
1188 IFR_BLOCK_DATA
*BlockArray
;
1189 IFR_BLOCK_DATA
*BlockSingleData
;
1191 BlockSingleData
= *BlockData
;
1193 if (BlockSingleData
->Name
!= NULL
) {
1194 InsertTailList (BlockLink
, &BlockSingleData
->Entry
);
1199 // Insert block data in its Offset and Width order.
1201 for (Link
= BlockLink
->ForwardLink
; Link
!= BlockLink
; Link
= Link
->ForwardLink
) {
1202 BlockArray
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
1203 if (BlockArray
->Offset
== BlockSingleData
->Offset
) {
1204 if (BlockArray
->Width
> BlockSingleData
->Width
) {
1206 // Insert this block data in the front of block array
1208 InsertTailList (Link
, &BlockSingleData
->Entry
);
1212 if (BlockArray
->Width
== BlockSingleData
->Width
) {
1214 // The same block array has been added.
1216 if (BlockSingleData
!= BlockArray
) {
1217 FreePool (BlockSingleData
);
1218 *BlockData
= BlockArray
;
1222 } else if (BlockArray
->Offset
> BlockSingleData
->Offset
) {
1224 // Insert new block data in the front of block array
1226 InsertTailList (Link
, &BlockSingleData
->Entry
);
1232 // Add new block data into the tail.
1234 InsertTailList (Link
, &BlockSingleData
->Entry
);
1238 Retrieves a pointer to the a Null-terminated ASCII string containing the list
1239 of languages that an HII handle in the HII Database supports. The returned
1240 string is allocated using AllocatePool(). The caller is responsible for freeing
1241 the returned string using FreePool(). The format of the returned string follows
1242 the language format assumed the HII Database.
1244 If HiiHandle is NULL, then ASSERT().
1246 @param[in] HiiHandle A handle that was previously registered in the HII Database.
1248 @retval NULL HiiHandle is not registered in the HII database
1249 @retval NULL There are not enough resources available to retrieve the suported
1251 @retval NULL The list of suported languages could not be retrieved.
1252 @retval Other A pointer to the Null-terminated ASCII string of supported languages.
1256 GetSupportedLanguages (
1257 IN EFI_HII_HANDLE HiiHandle
1262 CHAR8 TempSupportedLanguages
;
1263 CHAR8
*SupportedLanguages
;
1265 ASSERT (HiiHandle
!= NULL
);
1268 // Retrieve the size required for the supported languages buffer.
1271 Status
= mPrivate
.HiiString
.GetLanguages (&mPrivate
.HiiString
, HiiHandle
, &TempSupportedLanguages
, &LanguageSize
);
1274 // If GetLanguages() returns EFI_SUCCESS for a zero size,
1275 // then there are no supported languages registered for HiiHandle. If GetLanguages()
1276 // returns an error other than EFI_BUFFER_TOO_SMALL, then HiiHandle is not present
1277 // in the HII Database
1279 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
1281 // Return NULL if the size can not be retrieved, or if HiiHandle is not in the HII Database
1287 // Allocate the supported languages buffer.
1289 SupportedLanguages
= AllocateZeroPool (LanguageSize
);
1290 if (SupportedLanguages
== NULL
) {
1292 // Return NULL if allocation fails.
1298 // Retrieve the supported languages string
1300 Status
= mPrivate
.HiiString
.GetLanguages (&mPrivate
.HiiString
, HiiHandle
, SupportedLanguages
, &LanguageSize
);
1301 if (EFI_ERROR (Status
)) {
1303 // Free the buffer and return NULL if the supported languages can not be retrieved.
1305 FreePool (SupportedLanguages
);
1310 // Return the Null-terminated ASCII string of supported languages
1312 return SupportedLanguages
;
1316 Retrieves a string from a string package.
1318 If HiiHandle is NULL, then ASSERT().
1319 If StringId is 0, then ASSET.
1321 @param[in] HiiHandle A handle that was previously registered in the HII Database.
1322 @param[in] StringId The identifier of the string to retrieved from the string
1323 package associated with HiiHandle.
1325 @retval NULL The string specified by StringId is not present in the string package.
1326 @retval Other The string was returned.
1331 IN EFI_HII_HANDLE HiiHandle
,
1332 IN EFI_STRING_ID StringId
1339 CHAR8
*SupportedLanguages
;
1340 CHAR8
*PlatformLanguage
;
1341 CHAR8
*BestLanguage
;
1344 ASSERT (HiiHandle
!= NULL
);
1345 ASSERT (StringId
!= 0);
1348 // Initialize all allocated buffers to NULL
1350 SupportedLanguages
= NULL
;
1351 PlatformLanguage
= NULL
;
1352 BestLanguage
= NULL
;
1357 // Get the languages that the package specified by HiiHandle supports
1359 SupportedLanguages
= GetSupportedLanguages (HiiHandle
);
1360 if (SupportedLanguages
== NULL
) {
1365 // Get the current platform language setting
1367 GetEfiGlobalVariable2 (L
"PlatformLang", (VOID
**)&PlatformLanguage
, NULL
);
1370 // Get the best matching language from SupportedLanguages
1372 BestLanguage
= GetBestLanguage (
1374 FALSE
, // RFC 4646 mode
1375 Language
, // Highest priority
1376 PlatformLanguage
!= NULL
? PlatformLanguage
: "", // Next highest priority
1377 SupportedLanguages
, // Lowest priority
1380 if (BestLanguage
== NULL
) {
1385 // Retrieve the size of the string in the string package for the BestLanguage
1388 Status
= mPrivate
.HiiString
.GetString (
1389 &mPrivate
.HiiString
,
1398 // If GetString() returns EFI_SUCCESS for a zero size,
1399 // then there are no supported languages registered for HiiHandle. If GetString()
1400 // returns an error other than EFI_BUFFER_TOO_SMALL, then HiiHandle is not present
1401 // in the HII Database
1403 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
1408 // Allocate a buffer for the return string
1410 String
= AllocateZeroPool (StringSize
);
1411 if (String
== NULL
) {
1416 // Retrieve the string from the string package
1418 Status
= mPrivate
.HiiString
.GetString (
1419 &mPrivate
.HiiString
,
1427 if (EFI_ERROR (Status
)) {
1429 // Free the buffer and return NULL if the supported languages can not be retrieved.
1437 // Free allocated buffers
1439 if (SupportedLanguages
!= NULL
) {
1440 FreePool (SupportedLanguages
);
1442 if (PlatformLanguage
!= NULL
) {
1443 FreePool (PlatformLanguage
);
1445 if (BestLanguage
!= NULL
) {
1446 FreePool (BestLanguage
);
1450 // Return the Null-terminated Unicode string
1456 This function checks VarOffset and VarWidth is in the block range.
1458 @param RequestBlockArray The block array is to be checked.
1459 @param VarOffset Offset of var to the structure
1460 @param VarWidth Width of var.
1461 @param IsNameValueType Whether this varstore is name/value varstore or not.
1462 @param HiiHandle Hii handle for this hii package.
1464 @retval TRUE This Var is in the block range.
1465 @retval FALSE This Var is not in the block range.
1469 IN IFR_BLOCK_DATA
*RequestBlockArray
,
1470 IN UINT16 VarOffset
,
1472 IN BOOLEAN IsNameValueType
,
1473 IN EFI_HII_HANDLE HiiHandle
1477 IFR_BLOCK_DATA
*BlockData
;
1481 // No Request Block array, all vars are got.
1483 if (RequestBlockArray
== NULL
) {
1488 // Check the input var is in the request block range.
1490 for (Link
= RequestBlockArray
->Entry
.ForwardLink
; Link
!= &RequestBlockArray
->Entry
; Link
= Link
->ForwardLink
) {
1491 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
1493 if (IsNameValueType
) {
1494 Name
= InternalGetString (HiiHandle
, VarOffset
);
1495 ASSERT (Name
!= NULL
);
1497 if (StrnCmp (BlockData
->Name
, Name
, StrLen (Name
)) == 0) {
1503 if ((VarOffset
>= BlockData
->Offset
) && ((VarOffset
+ VarWidth
) <= (BlockData
->Offset
+ BlockData
->Width
))) {
1513 Get form package data from data base.
1515 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
1516 @param HiiFormPackage The buffer saves the package data.
1517 @param PackageSize The buffer size of the package data.
1521 GetFormPackageData (
1522 IN HII_DATABASE_RECORD
*DataBaseRecord
,
1523 IN OUT UINT8
**HiiFormPackage
,
1524 OUT UINTN
*PackageSize
1531 if (DataBaseRecord
== NULL
|| HiiFormPackage
== NULL
|| PackageSize
== NULL
) {
1532 return EFI_INVALID_PARAMETER
;
1538 // 0. Get Hii Form Package by HiiHandle
1540 Status
= ExportFormPackages (
1542 DataBaseRecord
->Handle
,
1543 DataBaseRecord
->PackageList
,
1549 if (EFI_ERROR (Status
)) {
1553 (*HiiFormPackage
) = AllocatePool (ResultSize
);
1554 if (*HiiFormPackage
== NULL
) {
1555 Status
= EFI_OUT_OF_RESOURCES
;
1560 // Get HiiFormPackage by HiiHandle
1564 Status
= ExportFormPackages (
1566 DataBaseRecord
->Handle
,
1567 DataBaseRecord
->PackageList
,
1573 if (EFI_ERROR (Status
)) {
1574 FreePool (*HiiFormPackage
);
1577 *PackageSize
= Size
;
1584 This function parses Form Package to get the efi varstore info according to the request ConfigHdr.
1586 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
1587 @param ConfigHdr Request string ConfigHdr. If it is NULL,
1588 the first found varstore will be as ConfigHdr.
1589 @param IsEfiVarstore Whether the request storage type is efi varstore type.
1590 @param EfiVarStore The efi varstore info which will return.
1594 IN HII_DATABASE_RECORD
*DataBaseRecord
,
1595 IN EFI_STRING ConfigHdr
,
1596 OUT BOOLEAN
*IsEfiVarstore
,
1597 OUT EFI_IFR_VARSTORE_EFI
**EfiVarStore
1602 UINTN PackageOffset
;
1603 EFI_IFR_OP_HEADER
*IfrOpHdr
;
1604 CHAR16
*VarStoreName
;
1609 UINT8
*HiiFormPackage
;
1611 EFI_IFR_VARSTORE_EFI
*IfrEfiVarStore
;
1612 EFI_HII_PACKAGE_HEADER
*PackageHeader
;
1614 HiiFormPackage
= NULL
;
1616 Status
= EFI_SUCCESS
;
1620 *IsEfiVarstore
= FALSE
;
1622 Status
= GetFormPackageData(DataBaseRecord
, &HiiFormPackage
, &PackageSize
);
1623 if (EFI_ERROR (Status
)) {
1627 IfrOffset
= sizeof (EFI_HII_PACKAGE_HEADER
);
1628 PackageOffset
= IfrOffset
;
1629 PackageHeader
= (EFI_HII_PACKAGE_HEADER
*) HiiFormPackage
;
1631 while (IfrOffset
< PackageSize
) {
1633 // More than one form packages exist.
1635 if (PackageOffset
>= PackageHeader
->Length
) {
1637 // Process the new form package.
1639 PackageOffset
= sizeof (EFI_HII_PACKAGE_HEADER
);
1640 IfrOffset
+= PackageOffset
;
1641 PackageHeader
= (EFI_HII_PACKAGE_HEADER
*) (HiiFormPackage
+ IfrOffset
);
1644 IfrOpHdr
= (EFI_IFR_OP_HEADER
*) (HiiFormPackage
+ IfrOffset
);
1645 IfrOffset
+= IfrOpHdr
->Length
;
1646 PackageOffset
+= IfrOpHdr
->Length
;
1648 if (IfrOpHdr
->OpCode
== EFI_IFR_VARSTORE_EFI_OP
) {
1649 IfrEfiVarStore
= (EFI_IFR_VARSTORE_EFI
*) IfrOpHdr
;
1651 // If the length is small than the structure, this is from old efi
1652 // varstore definition. Old efi varstore get config directly from
1653 // GetVariable function.
1655 if (IfrOpHdr
->Length
< sizeof (EFI_IFR_VARSTORE_EFI
)) {
1659 VarStoreName
= AllocateZeroPool (AsciiStrSize ((CHAR8
*)IfrEfiVarStore
->Name
) * sizeof (CHAR16
));
1660 if (VarStoreName
== NULL
) {
1661 Status
= EFI_OUT_OF_RESOURCES
;
1664 AsciiStrToUnicodeStr ((CHAR8
*) IfrEfiVarStore
->Name
, VarStoreName
);
1666 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*) &IfrEfiVarStore
->Guid
, 1, &GuidStr
);
1667 GenerateSubStr (L
"NAME=", StrLen (VarStoreName
) * sizeof (CHAR16
), (VOID
*) VarStoreName
, 2, &NameStr
);
1668 LengthString
= StrLen (GuidStr
);
1669 LengthString
= LengthString
+ StrLen (NameStr
) + 1;
1670 TempStr
= AllocateZeroPool (LengthString
* sizeof (CHAR16
));
1671 if (TempStr
== NULL
) {
1674 FreePool (VarStoreName
);
1675 Status
= EFI_OUT_OF_RESOURCES
;
1678 StrCpyS (TempStr
, LengthString
, GuidStr
);
1679 StrCatS (TempStr
, LengthString
, NameStr
);
1680 if (ConfigHdr
== NULL
|| StrnCmp (ConfigHdr
, TempStr
, StrLen (TempStr
)) == 0) {
1681 *EfiVarStore
= (EFI_IFR_VARSTORE_EFI
*) AllocateZeroPool (IfrOpHdr
->Length
);
1682 if (*EfiVarStore
== NULL
) {
1683 FreePool (VarStoreName
);
1687 Status
= EFI_OUT_OF_RESOURCES
;
1690 *IsEfiVarstore
= TRUE
;
1691 CopyMem (*EfiVarStore
, IfrEfiVarStore
, IfrOpHdr
->Length
);
1695 // Free alllocated temp string.
1697 FreePool (VarStoreName
);
1703 // Already found the varstore, break;
1705 if (*IsEfiVarstore
) {
1711 if (HiiFormPackage
!= NULL
) {
1712 FreePool (HiiFormPackage
);
1719 Check whether the ConfigRequest string has the request elements.
1720 For EFI_HII_VARSTORE_BUFFER type, the request has "&OFFSET=****&WIDTH=****..." format.
1721 For EFI_HII_VARSTORE_NAME_VALUE type, the request has "&NAME1**&NAME2..." format.
1723 @param ConfigRequest The input config request string.
1725 @retval TRUE The input include config request elements.
1726 @retval FALSE The input string not includes.
1730 GetElementsFromRequest (
1731 IN EFI_STRING ConfigRequest
1734 EFI_STRING TmpRequest
;
1736 TmpRequest
= StrStr (ConfigRequest
, L
"PATH=");
1737 ASSERT (TmpRequest
!= NULL
);
1739 if ((StrStr (TmpRequest
, L
"&OFFSET=") != NULL
) || (StrStr (TmpRequest
, L
"&") != NULL
)) {
1747 Check whether the this varstore is the request varstore.
1749 @param VarstoreGuid Varstore guid.
1750 @param Name Varstore name.
1751 @param ConfigHdr Current configRequest info.
1753 @retval TRUE This varstore is the requst one.
1754 @retval FALSE This varstore is not the requst one.
1759 IN EFI_GUID
*VarstoreGuid
,
1761 IN CHAR16
*ConfigHdr
1775 // If ConfigHdr has name field and varstore not has name, return FALSE.
1777 if (Name
== NULL
&& ConfigHdr
!= NULL
&& StrStr (ConfigHdr
, L
"NAME=&") == NULL
) {
1781 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*)VarstoreGuid
, 1, &GuidStr
);
1783 GenerateSubStr (L
"NAME=", StrLen (Name
) * sizeof (CHAR16
), (VOID
*) Name
, 2, &NameStr
);
1785 GenerateSubStr (L
"NAME=", 0, NULL
, 2, &NameStr
);
1787 LengthString
= StrLen (GuidStr
);
1788 LengthString
= LengthString
+ StrLen (NameStr
) + 1;
1789 TempStr
= AllocateZeroPool (LengthString
* sizeof (CHAR16
));
1790 if (TempStr
== NULL
) {
1794 StrCpyS (TempStr
, LengthString
, GuidStr
);
1795 StrCatS (TempStr
, LengthString
, NameStr
);
1797 if (ConfigHdr
== NULL
|| StrnCmp (ConfigHdr
, TempStr
, StrLen (TempStr
)) == 0) {
1802 if (GuidStr
!= NULL
) {
1806 if (NameStr
!= NULL
) {
1810 if (TempStr
!= NULL
) {
1818 This function parses Form Package to get the efi varstore info according to the request ConfigHdr.
1820 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
1821 @param ConfigHdr Request string ConfigHdr. If it is NULL,
1822 the first found varstore will be as ConfigHdr.
1823 @retval TRUE This hii package is the reqeust one.
1824 @retval FALSE This hii package is not the reqeust one.
1828 IN HII_DATABASE_RECORD
*DataBaseRecord
,
1829 IN EFI_STRING ConfigHdr
1834 UINTN PackageOffset
;
1835 EFI_IFR_OP_HEADER
*IfrOpHdr
;
1836 CHAR16
*VarStoreName
;
1837 UINT8
*HiiFormPackage
;
1839 EFI_IFR_VARSTORE_EFI
*IfrEfiVarStore
;
1840 EFI_HII_PACKAGE_HEADER
*PackageHeader
;
1841 EFI_IFR_VARSTORE
*IfrVarStore
;
1842 EFI_IFR_VARSTORE_NAME_VALUE
*IfrNameValueVarStore
;
1843 BOOLEAN FindVarstore
;
1845 HiiFormPackage
= NULL
;
1846 VarStoreName
= NULL
;
1847 Status
= EFI_SUCCESS
;
1848 FindVarstore
= FALSE
;
1850 Status
= GetFormPackageData(DataBaseRecord
, &HiiFormPackage
, &PackageSize
);
1851 if (EFI_ERROR (Status
)) {
1855 IfrOffset
= sizeof (EFI_HII_PACKAGE_HEADER
);
1856 PackageOffset
= IfrOffset
;
1857 PackageHeader
= (EFI_HII_PACKAGE_HEADER
*) HiiFormPackage
;
1859 while (IfrOffset
< PackageSize
) {
1861 // More than one form packages exist.
1863 if (PackageOffset
>= PackageHeader
->Length
) {
1865 // Process the new form package.
1867 PackageOffset
= sizeof (EFI_HII_PACKAGE_HEADER
);
1868 IfrOffset
+= PackageOffset
;
1869 PackageHeader
= (EFI_HII_PACKAGE_HEADER
*) (HiiFormPackage
+ IfrOffset
);
1872 IfrOpHdr
= (EFI_IFR_OP_HEADER
*) (HiiFormPackage
+ IfrOffset
);
1873 IfrOffset
+= IfrOpHdr
->Length
;
1874 PackageOffset
+= IfrOpHdr
->Length
;
1876 switch (IfrOpHdr
->OpCode
) {
1878 case EFI_IFR_VARSTORE_OP
:
1879 IfrVarStore
= (EFI_IFR_VARSTORE
*) IfrOpHdr
;
1881 VarStoreName
= AllocateZeroPool (AsciiStrSize ((CHAR8
*)IfrVarStore
->Name
) * sizeof (CHAR16
));
1882 if (VarStoreName
== NULL
) {
1885 AsciiStrToUnicodeStr ((CHAR8
*)IfrVarStore
->Name
, VarStoreName
);
1887 if (IsThisVarstore((VOID
*)&IfrVarStore
->Guid
, VarStoreName
, ConfigHdr
)) {
1888 FindVarstore
= TRUE
;
1893 case EFI_IFR_VARSTORE_EFI_OP
:
1894 IfrEfiVarStore
= (EFI_IFR_VARSTORE_EFI
*) IfrOpHdr
;
1895 VarStoreName
= AllocateZeroPool (AsciiStrSize ((CHAR8
*)IfrEfiVarStore
->Name
) * sizeof (CHAR16
));
1896 if (VarStoreName
== NULL
) {
1899 AsciiStrToUnicodeStr ((CHAR8
*)IfrEfiVarStore
->Name
, VarStoreName
);
1901 if (IsThisVarstore (&IfrEfiVarStore
->Guid
, VarStoreName
, ConfigHdr
)) {
1902 FindVarstore
= TRUE
;
1907 case EFI_IFR_VARSTORE_NAME_VALUE_OP
:
1908 IfrNameValueVarStore
= (EFI_IFR_VARSTORE_NAME_VALUE
*) IfrOpHdr
;
1910 if (IsThisVarstore (&IfrNameValueVarStore
->Guid
, NULL
, ConfigHdr
)) {
1911 FindVarstore
= TRUE
;
1916 case EFI_IFR_FORM_OP
:
1917 case EFI_IFR_FORM_MAP_OP
:
1919 // No matched varstore is found and directly return.
1928 if (HiiFormPackage
!= NULL
) {
1929 FreePool (HiiFormPackage
);
1932 if (VarStoreName
!= NULL
) {
1933 FreePool (VarStoreName
);
1936 return FindVarstore
;
1940 Check whether the this op code is required.
1942 @param RequestBlockArray The array includes all the request info or NULL.
1943 @param HiiHandle The hii handle for this form package.
1944 @param VarStorageData The varstore data strucure.
1945 @param IfrOpHdr Ifr opcode header for this opcode.
1946 @param VarWidth The buffer width for this opcode.
1947 @param ReturnData The data block added for this opcode.
1949 @retval EFI_SUCCESS This opcode is required.
1950 @retval EFI_NOT_FOUND This opcode is not required.
1951 @retval Others Contain some error.
1955 IsThisOpcodeRequired (
1956 IN IFR_BLOCK_DATA
*RequestBlockArray
,
1957 IN EFI_HII_HANDLE HiiHandle
,
1958 IN OUT IFR_VARSTORAGE_DATA
*VarStorageData
,
1959 IN EFI_IFR_OP_HEADER
*IfrOpHdr
,
1961 OUT IFR_BLOCK_DATA
**ReturnData
1964 IFR_BLOCK_DATA
*BlockData
;
1966 EFI_STRING_ID NameId
;
1967 EFI_IFR_QUESTION_HEADER
*IfrQuestionHdr
;
1971 IfrQuestionHdr
= (EFI_IFR_QUESTION_HEADER
*)((CHAR8
*) IfrOpHdr
+ sizeof (EFI_IFR_OP_HEADER
));
1973 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
1974 NameId
= IfrQuestionHdr
->VarStoreInfo
.VarName
;
1977 // Check whether this question is in requested block array.
1979 if (!BlockArrayCheck (RequestBlockArray
, NameId
, 0, TRUE
, HiiHandle
)) {
1981 // This question is not in the requested string. Skip it.
1983 return EFI_NOT_FOUND
;
1986 VarOffset
= IfrQuestionHdr
->VarStoreInfo
.VarOffset
;
1989 // Check whether this question is in requested block array.
1991 if (!BlockArrayCheck (RequestBlockArray
, VarOffset
, VarWidth
, FALSE
, HiiHandle
)) {
1993 // This question is not in the requested string. Skip it.
1995 return EFI_NOT_FOUND
;
1999 // Check this var question is in the var storage
2001 if (((VarOffset
+ VarWidth
) > VarStorageData
->Size
)) {
2002 return EFI_INVALID_PARAMETER
;
2006 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
2007 if (BlockData
== NULL
) {
2008 return EFI_OUT_OF_RESOURCES
;
2011 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2012 BlockData
->Name
= InternalGetString(HiiHandle
, NameId
);
2014 BlockData
->Offset
= VarOffset
;
2017 BlockData
->Width
= VarWidth
;
2018 BlockData
->QuestionId
= IfrQuestionHdr
->QuestionId
;
2019 BlockData
->OpCode
= IfrOpHdr
->OpCode
;
2020 BlockData
->Scope
= IfrOpHdr
->Scope
;
2021 InitializeListHead (&BlockData
->DefaultValueEntry
);
2023 // Add Block Data into VarStorageData BlockEntry
2025 InsertBlockData (&VarStorageData
->BlockEntry
, &BlockData
);
2026 *ReturnData
= BlockData
;
2032 This function parses Form Package to get the block array and the default
2033 value array according to the request ConfigHdr.
2035 @param HiiHandle Hii Handle for this hii package.
2036 @param Package Pointer to the form package data.
2037 @param PackageLength Length of the pacakge.
2038 @param ConfigHdr Request string ConfigHdr. If it is NULL,
2039 the first found varstore will be as ConfigHdr.
2040 @param RequestBlockArray The block array is retrieved from the request string.
2041 @param VarStorageData VarStorage structure contains the got block and default value.
2042 @param DefaultIdArray Point to the got default id and default name array.
2044 @retval EFI_SUCCESS The block array and the default value array are got.
2045 @retval EFI_INVALID_PARAMETER The varstore defintion in the differnt form pacakges
2047 @retval EFI_OUT_OF_RESOURCES No enough memory.
2052 IN EFI_HII_HANDLE HiiHandle
,
2054 IN UINT32 PackageLength
,
2055 IN EFI_STRING ConfigHdr
,
2056 IN IFR_BLOCK_DATA
*RequestBlockArray
,
2057 IN OUT IFR_VARSTORAGE_DATA
*VarStorageData
,
2058 OUT IFR_DEFAULT_DATA
*DefaultIdArray
2063 UINTN PackageOffset
;
2064 EFI_IFR_VARSTORE
*IfrVarStore
;
2065 EFI_IFR_VARSTORE_EFI
*IfrEfiVarStore
;
2066 EFI_IFR_OP_HEADER
*IfrOpHdr
;
2067 EFI_IFR_ONE_OF
*IfrOneOf
;
2068 EFI_IFR_REF4
*IfrRef
;
2069 EFI_IFR_ONE_OF_OPTION
*IfrOneOfOption
;
2070 EFI_IFR_DEFAULT
*IfrDefault
;
2071 EFI_IFR_ORDERED_LIST
*IfrOrderedList
;
2072 EFI_IFR_CHECKBOX
*IfrCheckBox
;
2073 EFI_IFR_PASSWORD
*IfrPassword
;
2074 EFI_IFR_STRING
*IfrString
;
2075 EFI_IFR_DATE
*IfrDate
;
2076 EFI_IFR_TIME
*IfrTime
;
2077 IFR_DEFAULT_DATA DefaultData
;
2078 IFR_DEFAULT_DATA
*DefaultDataPtr
;
2079 IFR_BLOCK_DATA
*BlockData
;
2080 CHAR16
*VarStoreName
;
2082 UINT16 VarDefaultId
;
2083 BOOLEAN FirstOneOfOption
;
2084 BOOLEAN FirstOrderedList
;
2085 LIST_ENTRY
*LinkData
;
2086 LIST_ENTRY
*LinkDefault
;
2087 EFI_IFR_VARSTORE_NAME_VALUE
*IfrNameValueVarStore
;
2088 EFI_HII_PACKAGE_HEADER
*PackageHeader
;
2089 EFI_VARSTORE_ID VarStoreId
;
2091 Status
= EFI_SUCCESS
;
2093 DefaultDataPtr
= NULL
;
2094 FirstOneOfOption
= FALSE
;
2096 FirstOrderedList
= FALSE
;
2097 ZeroMem (&DefaultData
, sizeof (IFR_DEFAULT_DATA
));
2100 // Go through the form package to parse OpCode one by one.
2102 PackageOffset
= sizeof (EFI_HII_PACKAGE_HEADER
);
2103 PackageHeader
= (EFI_HII_PACKAGE_HEADER
*) Package
;
2104 IfrOffset
= PackageOffset
;
2105 while (IfrOffset
< PackageLength
) {
2108 // More than one form package found.
2110 if (PackageOffset
>= PackageHeader
->Length
) {
2112 // Already found varstore for this request, break;
2114 if (VarStoreId
!= 0) {
2119 // Get next package header info.
2121 IfrOffset
+= sizeof (EFI_HII_PACKAGE_HEADER
);
2122 PackageOffset
= sizeof (EFI_HII_PACKAGE_HEADER
);
2123 PackageHeader
= (EFI_HII_PACKAGE_HEADER
*) (Package
+ IfrOffset
);
2126 IfrOpHdr
= (EFI_IFR_OP_HEADER
*) (Package
+ IfrOffset
);
2127 switch (IfrOpHdr
->OpCode
) {
2128 case EFI_IFR_VARSTORE_OP
:
2130 // VarStore is found. Don't need to search any more.
2132 if (VarStoreId
!= 0) {
2136 IfrVarStore
= (EFI_IFR_VARSTORE
*) IfrOpHdr
;
2138 VarStoreName
= AllocateZeroPool (AsciiStrSize ((CHAR8
*)IfrVarStore
->Name
) * sizeof (CHAR16
));
2139 if (VarStoreName
== NULL
) {
2140 Status
= EFI_OUT_OF_RESOURCES
;
2143 AsciiStrToUnicodeStr ((CHAR8
*)IfrVarStore
->Name
, VarStoreName
);
2145 if (IsThisVarstore((VOID
*)&IfrVarStore
->Guid
, VarStoreName
, ConfigHdr
)) {
2147 // Find the matched VarStore
2149 CopyGuid (&VarStorageData
->Guid
, (EFI_GUID
*) (VOID
*) &IfrVarStore
->Guid
);
2150 VarStorageData
->Size
= IfrVarStore
->Size
;
2151 VarStorageData
->Name
= VarStoreName
;
2152 VarStorageData
->Type
= EFI_HII_VARSTORE_BUFFER
;
2153 VarStoreId
= IfrVarStore
->VarStoreId
;
2157 case EFI_IFR_VARSTORE_EFI_OP
:
2159 // VarStore is found. Don't need to search any more.
2161 if (VarStoreId
!= 0) {
2165 IfrEfiVarStore
= (EFI_IFR_VARSTORE_EFI
*) IfrOpHdr
;
2168 // If the length is small than the structure, this is from old efi
2169 // varstore definition. Old efi varstore get config directly from
2170 // GetVariable function.
2172 if (IfrOpHdr
->Length
< sizeof (EFI_IFR_VARSTORE_EFI
)) {
2176 VarStoreName
= AllocateZeroPool (AsciiStrSize ((CHAR8
*)IfrEfiVarStore
->Name
) * sizeof (CHAR16
));
2177 if (VarStoreName
== NULL
) {
2178 Status
= EFI_OUT_OF_RESOURCES
;
2181 AsciiStrToUnicodeStr ((CHAR8
*)IfrEfiVarStore
->Name
, VarStoreName
);
2183 if (IsThisVarstore (&IfrEfiVarStore
->Guid
, VarStoreName
, ConfigHdr
)) {
2185 // Find the matched VarStore
2187 CopyGuid (&VarStorageData
->Guid
, (EFI_GUID
*) (VOID
*) &IfrEfiVarStore
->Guid
);
2188 VarStorageData
->Size
= IfrEfiVarStore
->Size
;
2189 VarStorageData
->Name
= VarStoreName
;
2190 VarStorageData
->Type
= EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
;
2191 VarStoreId
= IfrEfiVarStore
->VarStoreId
;
2195 case EFI_IFR_VARSTORE_NAME_VALUE_OP
:
2197 // VarStore is found. Don't need to search any more.
2199 if (VarStoreId
!= 0) {
2203 IfrNameValueVarStore
= (EFI_IFR_VARSTORE_NAME_VALUE
*) IfrOpHdr
;
2205 if (IsThisVarstore (&IfrNameValueVarStore
->Guid
, NULL
, ConfigHdr
)) {
2207 // Find the matched VarStore
2209 CopyGuid (&VarStorageData
->Guid
, (EFI_GUID
*) (VOID
*) &IfrNameValueVarStore
->Guid
);
2210 VarStorageData
->Type
= EFI_HII_VARSTORE_NAME_VALUE
;
2211 VarStoreId
= IfrNameValueVarStore
->VarStoreId
;
2215 case EFI_IFR_DEFAULTSTORE_OP
:
2217 // Add new the map between default id and default name.
2219 DefaultDataPtr
= (IFR_DEFAULT_DATA
*) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
2220 if (DefaultDataPtr
== NULL
) {
2221 Status
= EFI_OUT_OF_RESOURCES
;
2224 DefaultDataPtr
->DefaultId
= ((EFI_IFR_DEFAULTSTORE
*) IfrOpHdr
)->DefaultId
;
2225 InsertTailList (&DefaultIdArray
->Entry
, &DefaultDataPtr
->Entry
);
2226 DefaultDataPtr
= NULL
;
2229 case EFI_IFR_FORM_OP
:
2230 case EFI_IFR_FORM_MAP_OP
:
2232 // No matched varstore is found and directly return.
2234 if ( VarStoreId
== 0) {
2235 Status
= EFI_SUCCESS
;
2240 case EFI_IFR_REF_OP
:
2242 // Ref question is not in IFR Form. This IFR form is not valid.
2244 if ( VarStoreId
== 0) {
2245 Status
= EFI_INVALID_PARAMETER
;
2249 // Check whether this question is for the requested varstore.
2251 IfrRef
= (EFI_IFR_REF4
*) IfrOpHdr
;
2252 if (IfrRef
->Question
.VarStoreId
!= VarStoreId
) {
2255 VarWidth
= (UINT16
) (sizeof (EFI_HII_REF
));
2258 // The BlockData may allocate by other opcode,need to clean.
2260 if (BlockData
!= NULL
){
2264 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
2265 if (EFI_ERROR (Status
)) {
2266 if (Status
== EFI_NOT_FOUND
){
2268 //The opcode is not required,exit and parse other opcode.
2276 case EFI_IFR_ONE_OF_OP
:
2277 case EFI_IFR_NUMERIC_OP
:
2279 // Numeric and OneOf has the same opcode structure.
2283 // Numeric and OneOf question is not in IFR Form. This IFR form is not valid.
2285 if (VarStoreId
== 0) {
2286 Status
= EFI_INVALID_PARAMETER
;
2290 // Check whether this question is for the requested varstore.
2292 IfrOneOf
= (EFI_IFR_ONE_OF
*) IfrOpHdr
;
2293 if (IfrOneOf
->Question
.VarStoreId
!= VarStoreId
) {
2296 VarWidth
= (UINT16
) (1 << (IfrOneOf
->Flags
& EFI_IFR_NUMERIC_SIZE
));
2299 // The BlockData may allocate by other opcode,need to clean.
2301 if (BlockData
!= NULL
){
2305 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
2306 if (EFI_ERROR (Status
)) {
2307 if (Status
== EFI_NOT_FOUND
){
2309 //The opcode is not required,exit and parse other opcode.
2317 //when go to there,BlockData can't be NULLL.
2319 ASSERT (BlockData
!= NULL
);
2321 if (IfrOpHdr
->OpCode
== EFI_IFR_ONE_OF_OP
) {
2323 // Set this flag to TRUE for the first oneof option.
2325 FirstOneOfOption
= TRUE
;
2326 } else if (IfrOpHdr
->OpCode
== EFI_IFR_NUMERIC_OP
) {
2328 // Numeric minimum value will be used as default value when no default is specified.
2330 DefaultData
.Type
= DefaultValueFromDefault
;
2331 switch (IfrOneOf
->Flags
& EFI_IFR_NUMERIC_SIZE
) {
2332 case EFI_IFR_NUMERIC_SIZE_1
:
2333 DefaultData
.Value
.u8
= IfrOneOf
->data
.u8
.MinValue
;
2336 case EFI_IFR_NUMERIC_SIZE_2
:
2337 CopyMem (&DefaultData
.Value
.u16
, &IfrOneOf
->data
.u16
.MinValue
, sizeof (UINT16
));
2340 case EFI_IFR_NUMERIC_SIZE_4
:
2341 CopyMem (&DefaultData
.Value
.u32
, &IfrOneOf
->data
.u32
.MinValue
, sizeof (UINT32
));
2344 case EFI_IFR_NUMERIC_SIZE_8
:
2345 CopyMem (&DefaultData
.Value
.u64
, &IfrOneOf
->data
.u64
.MinValue
, sizeof (UINT64
));
2349 Status
= EFI_INVALID_PARAMETER
;
2353 // Set default value base on the DefaultId list get from IFR data.
2355 for (LinkData
= DefaultIdArray
->Entry
.ForwardLink
; LinkData
!= &DefaultIdArray
->Entry
; LinkData
= LinkData
->ForwardLink
) {
2356 DefaultDataPtr
= BASE_CR (LinkData
, IFR_DEFAULT_DATA
, Entry
);
2357 DefaultData
.DefaultId
= DefaultDataPtr
->DefaultId
;
2358 InsertDefaultValue (BlockData
, &DefaultData
);
2363 case EFI_IFR_ORDERED_LIST_OP
:
2365 // offset by question header
2366 // width by EFI_IFR_ORDERED_LIST MaxContainers * OneofOption Type
2369 FirstOrderedList
= TRUE
;
2371 // OrderedList question is not in IFR Form. This IFR form is not valid.
2373 if (VarStoreId
== 0) {
2374 Status
= EFI_INVALID_PARAMETER
;
2378 // Check whether this question is for the requested varstore.
2380 IfrOrderedList
= (EFI_IFR_ORDERED_LIST
*) IfrOpHdr
;
2381 if (IfrOrderedList
->Question
.VarStoreId
!= VarStoreId
) {
2385 VarWidth
= IfrOrderedList
->MaxContainers
;
2388 // The BlockData may allocate by other opcode,need to clean.
2390 if (BlockData
!= NULL
){
2394 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
2395 if (EFI_ERROR (Status
)) {
2396 if (Status
== EFI_NOT_FOUND
){
2398 //The opcode is not required,exit and parse other opcode.
2406 case EFI_IFR_CHECKBOX_OP
:
2408 // EFI_IFR_DEFAULT_OP
2409 // offset by question header
2410 // width is 1 sizeof (BOOLEAN)
2411 // default id by CheckBox Flags if CheckBox flags (Default or Mau) is set, the default value is 1 to be set.
2412 // value by DefaultOption
2413 // default id by DeaultOption DefaultId can override CheckBox Flags and Default value.
2417 // CheckBox question is not in IFR Form. This IFR form is not valid.
2419 if (VarStoreId
== 0) {
2420 Status
= EFI_INVALID_PARAMETER
;
2424 // Check whether this question is for the requested varstore.
2426 IfrCheckBox
= (EFI_IFR_CHECKBOX
*) IfrOpHdr
;
2427 if (IfrCheckBox
->Question
.VarStoreId
!= VarStoreId
) {
2430 VarWidth
= (UINT16
) sizeof (BOOLEAN
);
2433 // The BlockData may allocate by other opcode,need to clean.
2435 if (BlockData
!= NULL
){
2439 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
2440 if (EFI_ERROR (Status
)) {
2441 if (Status
== EFI_NOT_FOUND
){
2443 //The opcode is not required,exit and parse other opcode.
2451 //when go to there,BlockData can't be NULLL.
2453 ASSERT (BlockData
!= NULL
);
2456 // Add default value for standard ID by CheckBox Flag
2458 VarDefaultId
= EFI_HII_DEFAULT_CLASS_STANDARD
;
2460 // Prepare new DefaultValue
2462 DefaultData
.DefaultId
= VarDefaultId
;
2463 if ((IfrCheckBox
->Flags
& EFI_IFR_CHECKBOX_DEFAULT
) == EFI_IFR_CHECKBOX_DEFAULT
) {
2465 // When flag is set, defautl value is TRUE.
2467 DefaultData
.Type
= DefaultValueFromFlag
;
2468 DefaultData
.Value
.b
= TRUE
;
2471 // When flag is not set, defautl value is FASLE.
2473 DefaultData
.Type
= DefaultValueFromDefault
;
2474 DefaultData
.Value
.b
= FALSE
;
2477 // Add DefaultValue into current BlockData
2479 InsertDefaultValue (BlockData
, &DefaultData
);
2482 // Add default value for Manufacture ID by CheckBox Flag
2484 VarDefaultId
= EFI_HII_DEFAULT_CLASS_MANUFACTURING
;
2486 // Prepare new DefaultValue
2488 DefaultData
.DefaultId
= VarDefaultId
;
2489 if ((IfrCheckBox
->Flags
& EFI_IFR_CHECKBOX_DEFAULT_MFG
) == EFI_IFR_CHECKBOX_DEFAULT_MFG
) {
2491 // When flag is set, defautl value is TRUE.
2493 DefaultData
.Type
= DefaultValueFromFlag
;
2494 DefaultData
.Value
.b
= TRUE
;
2497 // When flag is not set, defautl value is FASLE.
2499 DefaultData
.Type
= DefaultValueFromDefault
;
2500 DefaultData
.Value
.b
= FALSE
;
2503 // Add DefaultValue into current BlockData
2505 InsertDefaultValue (BlockData
, &DefaultData
);
2508 case EFI_IFR_DATE_OP
:
2510 // offset by question header
2511 // width MaxSize * sizeof (CHAR16)
2512 // no default value, only block array
2516 // Date question is not in IFR Form. This IFR form is not valid.
2518 if (VarStoreId
== 0) {
2519 Status
= EFI_INVALID_PARAMETER
;
2523 // Check whether this question is for the requested varstore.
2525 IfrDate
= (EFI_IFR_DATE
*) IfrOpHdr
;
2526 if (IfrDate
->Question
.VarStoreId
!= VarStoreId
) {
2531 // The BlockData may allocate by other opcode,need to clean.
2533 if (BlockData
!= NULL
){
2537 VarWidth
= (UINT16
) sizeof (EFI_HII_DATE
);
2538 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
2539 if (EFI_ERROR (Status
)) {
2540 if (Status
== EFI_NOT_FOUND
){
2542 //The opcode is not required,exit and parse other opcode.
2550 case EFI_IFR_TIME_OP
:
2552 // offset by question header
2553 // width MaxSize * sizeof (CHAR16)
2554 // no default value, only block array
2558 // Time question is not in IFR Form. This IFR form is not valid.
2560 if (VarStoreId
== 0) {
2561 Status
= EFI_INVALID_PARAMETER
;
2565 // Check whether this question is for the requested varstore.
2567 IfrTime
= (EFI_IFR_TIME
*) IfrOpHdr
;
2568 if (IfrTime
->Question
.VarStoreId
!= VarStoreId
) {
2573 // The BlockData may allocate by other opcode,need to clean.
2575 if (BlockData
!= NULL
){
2579 VarWidth
= (UINT16
) sizeof (EFI_HII_TIME
);
2580 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
2581 if (EFI_ERROR (Status
)) {
2582 if (Status
== EFI_NOT_FOUND
){
2584 //The opcode is not required,exit and parse other opcode.
2592 case EFI_IFR_STRING_OP
:
2594 // offset by question header
2595 // width MaxSize * sizeof (CHAR16)
2596 // no default value, only block array
2600 // String question is not in IFR Form. This IFR form is not valid.
2602 if (VarStoreId
== 0) {
2603 Status
= EFI_INVALID_PARAMETER
;
2607 // Check whether this question is for the requested varstore.
2609 IfrString
= (EFI_IFR_STRING
*) IfrOpHdr
;
2610 if (IfrString
->Question
.VarStoreId
!= VarStoreId
) {
2615 // The BlockData may allocate by other opcode,need to clean.
2617 if (BlockData
!= NULL
){
2621 VarWidth
= (UINT16
) (IfrString
->MaxSize
* sizeof (UINT16
));
2622 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
2623 if (EFI_ERROR (Status
)) {
2624 if (Status
== EFI_NOT_FOUND
){
2626 //The opcode is not required,exit and parse other opcode.
2634 case EFI_IFR_PASSWORD_OP
:
2636 // offset by question header
2637 // width MaxSize * sizeof (CHAR16)
2638 // no default value, only block array
2642 // Password question is not in IFR Form. This IFR form is not valid.
2644 if (VarStoreId
== 0) {
2645 Status
= EFI_INVALID_PARAMETER
;
2649 // Check whether this question is for the requested varstore.
2651 IfrPassword
= (EFI_IFR_PASSWORD
*) IfrOpHdr
;
2652 if (IfrPassword
->Question
.VarStoreId
!= VarStoreId
) {
2657 // The BlockData may allocate by other opcode,need to clean.
2659 if (BlockData
!= NULL
){
2663 VarWidth
= (UINT16
) (IfrPassword
->MaxSize
* sizeof (UINT16
));
2664 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
2665 if (EFI_ERROR (Status
)) {
2666 if (Status
== EFI_NOT_FOUND
){
2668 //The opcode is not required,exit and parse other opcode.
2676 // No default value for string.
2681 case EFI_IFR_ONE_OF_OPTION_OP
:
2683 // No matched block data is ignored.
2685 if (BlockData
== NULL
|| BlockData
->Scope
== 0) {
2689 IfrOneOfOption
= (EFI_IFR_ONE_OF_OPTION
*) IfrOpHdr
;
2690 if (BlockData
->OpCode
== EFI_IFR_ORDERED_LIST_OP
) {
2692 if (!FirstOrderedList
){
2696 // Get ordered list option data type.
2698 if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_8
|| IfrOneOfOption
->Type
== EFI_IFR_TYPE_BOOLEAN
) {
2700 } else if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_16
) {
2702 } else if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_32
) {
2704 } else if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_64
) {
2708 // Invalid ordered list option data type.
2710 Status
= EFI_INVALID_PARAMETER
;
2711 if (BlockData
->Name
!= NULL
) {
2712 FreePool (BlockData
->Name
);
2714 FreePool (BlockData
);
2719 // Calculate Ordered list QuestionId width.
2721 BlockData
->Width
= (UINT16
) (BlockData
->Width
* VarWidth
);
2723 // Check whether this question is in requested block array.
2725 if (!BlockArrayCheck (RequestBlockArray
, BlockData
->Offset
, BlockData
->Width
, (BOOLEAN
)(BlockData
->Name
!= NULL
), HiiHandle
)) {
2727 // This question is not in the requested string. Skip it.
2729 if (BlockData
->Name
!= NULL
) {
2730 FreePool (BlockData
->Name
);
2732 FreePool (BlockData
);
2737 // Check this var question is in the var storage
2739 if ((BlockData
->Name
== NULL
) && ((BlockData
->Offset
+ BlockData
->Width
) > VarStorageData
->Size
)) {
2740 Status
= EFI_INVALID_PARAMETER
;
2741 if (BlockData
->Name
!= NULL
) {
2742 FreePool (BlockData
->Name
);
2744 FreePool (BlockData
);
2748 // Add Block Data into VarStorageData BlockEntry
2750 InsertBlockData (&VarStorageData
->BlockEntry
, &BlockData
);
2752 FirstOrderedList
= FALSE
;
2758 // 1. Set default value for OneOf option when flag field has default attribute.
2760 if (((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT
) == EFI_IFR_OPTION_DEFAULT
) ||
2761 ((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT_MFG
) == EFI_IFR_OPTION_DEFAULT_MFG
)) {
2763 // This flag is used to specify whether this option is the first. Set it to FALSE for the following options.
2764 // The first oneof option value will be used as default value when no default value is specified.
2766 FirstOneOfOption
= FALSE
;
2768 // Prepare new DefaultValue
2770 DefaultData
.Type
= DefaultValueFromFlag
;
2771 CopyMem (&DefaultData
.Value
, &IfrOneOfOption
->Value
, IfrOneOfOption
->Header
.Length
- OFFSET_OF (EFI_IFR_ONE_OF_OPTION
, Value
));
2772 if ((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT
) == EFI_IFR_OPTION_DEFAULT
) {
2773 DefaultData
.DefaultId
= EFI_HII_DEFAULT_CLASS_STANDARD
;
2774 InsertDefaultValue (BlockData
, &DefaultData
);
2776 if ((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT_MFG
) == EFI_IFR_OPTION_DEFAULT_MFG
) {
2777 DefaultData
.DefaultId
= EFI_HII_DEFAULT_CLASS_MANUFACTURING
;
2778 InsertDefaultValue (BlockData
, &DefaultData
);
2783 // 2. Set as the default value when this is the first option.
2784 // The first oneof option value will be used as default value when no default value is specified.
2786 if (FirstOneOfOption
) {
2787 // This flag is used to specify whether this option is the first. Set it to FALSE for the following options.
2788 FirstOneOfOption
= FALSE
;
2791 // Prepare new DefaultValue
2793 DefaultData
.Type
= DefaultValueFromDefault
;
2794 CopyMem (&DefaultData
.Value
, &IfrOneOfOption
->Value
, IfrOneOfOption
->Header
.Length
- OFFSET_OF (EFI_IFR_ONE_OF_OPTION
, Value
));
2795 for (LinkData
= DefaultIdArray
->Entry
.ForwardLink
; LinkData
!= &DefaultIdArray
->Entry
; LinkData
= LinkData
->ForwardLink
) {
2796 DefaultDataPtr
= BASE_CR (LinkData
, IFR_DEFAULT_DATA
, Entry
);
2797 DefaultData
.DefaultId
= DefaultDataPtr
->DefaultId
;
2798 InsertDefaultValue (BlockData
, &DefaultData
);
2803 case EFI_IFR_DEFAULT_OP
:
2805 // Update Current BlockData to the default value.
2807 if (BlockData
== NULL
|| BlockData
->Scope
== 0) {
2809 // No matched block data is ignored.
2815 // Get the DefaultId
2817 IfrDefault
= (EFI_IFR_DEFAULT
*) IfrOpHdr
;
2818 VarDefaultId
= IfrDefault
->DefaultId
;
2820 // Prepare new DefaultValue
2822 DefaultData
.Type
= DefaultValueFromOpcode
;
2823 DefaultData
.DefaultId
= VarDefaultId
;
2824 CopyMem (&DefaultData
.Value
, &IfrDefault
->Value
, IfrDefault
->Header
.Length
- OFFSET_OF (EFI_IFR_DEFAULT
, Value
));
2826 // If the value field is expression, set the cleaned flag.
2827 if (IfrDefault
->Type
== EFI_IFR_TYPE_OTHER
) {
2828 DefaultData
.Cleaned
= TRUE
;
2831 // Add DefaultValue into current BlockData
2833 InsertDefaultValue (BlockData
, &DefaultData
);
2836 // After insert the default value, reset the cleaned value for next
2837 // time used. If not set here, need to set the value before everytime
2840 DefaultData
.Cleaned
= FALSE
;
2843 case EFI_IFR_END_OP
:
2845 // End Opcode is for Var question.
2847 if (BlockData
!= NULL
) {
2848 if (BlockData
->Scope
> 0) {
2851 if (BlockData
->Scope
== 0) {
2859 if (BlockData
!= NULL
) {
2860 if (BlockData
->Scope
> 0) {
2861 BlockData
->Scope
= (UINT8
) (BlockData
->Scope
+ IfrOpHdr
->Scope
);
2864 if (BlockData
->Scope
== 0) {
2871 IfrOffset
+= IfrOpHdr
->Length
;
2872 PackageOffset
+= IfrOpHdr
->Length
;
2876 //if Status == EFI_NOT_FOUND, just means the opcode is not required,not contain any error,
2877 //so set the Status to EFI_SUCCESS.
2879 if (Status
== EFI_NOT_FOUND
){
2880 Status
= EFI_SUCCESS
;
2884 for (LinkData
= VarStorageData
->BlockEntry
.ForwardLink
; LinkData
!= &VarStorageData
->BlockEntry
; LinkData
= LinkData
->ForwardLink
) {
2885 BlockData
= BASE_CR (LinkData
, IFR_BLOCK_DATA
, Entry
);
2886 for (LinkDefault
= BlockData
->DefaultValueEntry
.ForwardLink
; LinkDefault
!= &BlockData
->DefaultValueEntry
; ) {
2887 DefaultDataPtr
= BASE_CR (LinkDefault
, IFR_DEFAULT_DATA
, Entry
);
2888 LinkDefault
= LinkDefault
->ForwardLink
;
2889 if (DefaultDataPtr
->Cleaned
== TRUE
) {
2890 RemoveEntryList (&DefaultDataPtr
->Entry
);
2891 FreePool (DefaultDataPtr
);
2900 parse the configrequest string, get the elements.
2902 @param ConfigRequest The input configrequest string.
2903 @param Progress Return the progress data.
2905 @retval Block data pointer.
2909 IN EFI_STRING ConfigRequest
,
2910 OUT EFI_STRING
*Progress
2913 EFI_STRING StringPtr
;
2914 IFR_BLOCK_DATA
*BlockData
;
2915 IFR_BLOCK_DATA
*RequestBlockArray
;
2921 IFR_BLOCK_DATA
*NextBlockData
;
2927 // Init RequestBlockArray
2929 RequestBlockArray
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
2930 if (RequestBlockArray
== NULL
) {
2933 InitializeListHead (&RequestBlockArray
->Entry
);
2936 // Get the request Block array from the request string
2941 // Parse each <RequestElement> if exists
2942 // Only <BlockName> format is supported by this help function.
2943 // <BlockName> ::= &'OFFSET='<Number>&'WIDTH='<Number>
2945 StringPtr
= ConfigRequest
;
2946 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) == 0) {
2948 // Skip the OFFSET string
2950 *Progress
= StringPtr
;
2951 StringPtr
+= StrLen (L
"&OFFSET=");
2955 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
2956 if (EFI_ERROR (Status
)) {
2963 (((Length
+ 1) / 2) < sizeof (UINT16
)) ? ((Length
+ 1) / 2) : sizeof (UINT16
)
2965 FreePool (TmpBuffer
);
2967 StringPtr
+= Length
;
2968 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
2971 StringPtr
+= StrLen (L
"&WIDTH=");
2976 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
2977 if (EFI_ERROR (Status
)) {
2984 (((Length
+ 1) / 2) < sizeof (UINT16
)) ? ((Length
+ 1) / 2) : sizeof (UINT16
)
2986 FreePool (TmpBuffer
);
2988 StringPtr
+= Length
;
2989 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
2996 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
2997 if (BlockData
== NULL
) {
3000 BlockData
->Offset
= Offset
;
3001 BlockData
->Width
= Width
;
3002 InsertBlockData (&RequestBlockArray
->Entry
, &BlockData
);
3005 // Skip &VALUE string if &VALUE does exists.
3007 if (StrnCmp (StringPtr
, L
"&VALUE=", StrLen (L
"&VALUE=")) == 0) {
3008 StringPtr
+= StrLen (L
"&VALUE=");
3013 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
3014 if (EFI_ERROR (Status
)) {
3018 StringPtr
+= Length
;
3019 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
3024 // If '\0', parsing is finished.
3026 if (*StringPtr
== 0) {
3032 // Merge the requested block data.
3034 Link
= RequestBlockArray
->Entry
.ForwardLink
;
3035 while ((Link
!= &RequestBlockArray
->Entry
) && (Link
->ForwardLink
!= &RequestBlockArray
->Entry
)) {
3036 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
3037 NextBlockData
= BASE_CR (Link
->ForwardLink
, IFR_BLOCK_DATA
, Entry
);
3038 if ((NextBlockData
->Offset
>= BlockData
->Offset
) && (NextBlockData
->Offset
<= (BlockData
->Offset
+ BlockData
->Width
))) {
3039 if ((NextBlockData
->Offset
+ NextBlockData
->Width
) > (BlockData
->Offset
+ BlockData
->Width
)) {
3040 BlockData
->Width
= (UINT16
) (NextBlockData
->Offset
+ NextBlockData
->Width
- BlockData
->Offset
);
3042 RemoveEntryList (Link
->ForwardLink
);
3043 FreePool (NextBlockData
);
3046 Link
= Link
->ForwardLink
;
3049 return RequestBlockArray
;
3052 if (RequestBlockArray
!= NULL
) {
3054 // Free Link Array RequestBlockArray
3056 while (!IsListEmpty (&RequestBlockArray
->Entry
)) {
3057 BlockData
= BASE_CR (RequestBlockArray
->Entry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
3058 RemoveEntryList (&BlockData
->Entry
);
3059 FreePool (BlockData
);
3062 FreePool (RequestBlockArray
);
3069 parse the configrequest string, get the elements.
3071 @param ConfigRequest The input config request string.
3072 @param Progress Return the progress data.
3074 @retval return data block array.
3078 IN EFI_STRING ConfigRequest
,
3079 OUT EFI_STRING
*Progress
3082 EFI_STRING StringPtr
;
3084 IFR_BLOCK_DATA
*BlockData
;
3085 IFR_BLOCK_DATA
*RequestBlockArray
;
3088 StringPtr
= ConfigRequest
;
3091 // Init RequestBlockArray
3093 RequestBlockArray
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
3094 if (RequestBlockArray
== NULL
) {
3097 InitializeListHead (&RequestBlockArray
->Entry
);
3100 // Get the request Block array from the request string
3104 // Parse each <RequestElement> if exists
3105 // Only <BlockName> format is supported by this help function.
3106 // <BlockName> ::= &'Name***=***
3108 while (StringPtr
!= NULL
&& *StringPtr
== L
'&') {
3110 *Progress
= StringPtr
;
3112 // Skip the L"&" string
3117 if ((NextTag
= StrStr (StringPtr
, L
"=")) != NULL
) {
3120 } else if ((NextTag
= StrStr (StringPtr
, L
"&")) != NULL
) {
3127 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
3128 if (BlockData
== NULL
) {
3135 BlockData
->Name
= AllocateCopyPool(StrSize (StringPtr
), StringPtr
);
3136 InsertBlockData (&RequestBlockArray
->Entry
, &BlockData
);
3140 // If has value, skip the value.
3142 StringPtr
= NextTag
+ 1;
3144 StringPtr
= StrStr (StringPtr
, L
"&");
3145 } else if (NextTag
!= NULL
) {
3147 // restore the '&' text.
3149 StringPtr
= NextTag
;
3154 return RequestBlockArray
;
3157 if (RequestBlockArray
!= NULL
) {
3159 // Free Link Array RequestBlockArray
3161 while (!IsListEmpty (&RequestBlockArray
->Entry
)) {
3162 BlockData
= BASE_CR (RequestBlockArray
->Entry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
3163 RemoveEntryList (&BlockData
->Entry
);
3164 if (BlockData
->Name
!= NULL
) {
3165 FreePool (BlockData
->Name
);
3167 FreePool (BlockData
);
3170 FreePool (RequestBlockArray
);
3177 Generate ConfigRequest string base on the varstore info.
3179 @param ConfigHdr The config header for this varstore.
3180 @param VarStorageData The varstore info.
3181 @param Status Return Status.
3182 @param ConfigRequest The ConfigRequest info may be return.
3184 @retval TRUE Need to continue
3185 @retval Others NO need to continue or error occur.
3188 GenerateConfigRequest (
3189 IN CHAR16
*ConfigHdr
,
3190 IN IFR_VARSTORAGE_DATA
*VarStorageData
,
3191 OUT EFI_STATUS
*Status
,
3192 IN OUT EFI_STRING
*ConfigRequest
3198 CHAR16
*FullConfigRequest
;
3200 IFR_BLOCK_DATA
*BlockData
;
3203 // Append VarStorageData BlockEntry into *Request string
3204 // Now support only one varstore in a form package.
3208 // Go through all VarStorageData Entry and get BlockEntry for each one for the multiple varstore in a single form package
3209 // Then construct them all to return MultiRequest string : ConfigHdr BlockConfig
3213 // Compute the length of the entire request starting with <ConfigHdr> and a
3217 Length
= StrLen (ConfigHdr
) + 1;
3219 for (Link
= VarStorageData
->BlockEntry
.ForwardLink
; Link
!= &VarStorageData
->BlockEntry
; Link
= Link
->ForwardLink
) {
3221 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
3222 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3224 // Add <BlockName> length for each Name
3226 // <BlockName> ::= &Name1&Name2&...
3227 // |1| StrLen(Name1)
3229 Length
= Length
+ (1 + StrLen (BlockData
->Name
));
3232 // Add <BlockName> length for each Offset/Width pair
3234 // <BlockName> ::= &OFFSET=1234&WIDTH=1234
3235 // | 8 | 4 | 7 | 4 |
3237 Length
= Length
+ (8 + 4 + 7 + 4);
3241 // No any request block data is found. The request string can't be constructed.
3244 *Status
= EFI_SUCCESS
;
3249 // Allocate buffer for the entire <ConfigRequest>
3251 FullConfigRequest
= AllocateZeroPool (Length
* sizeof (CHAR16
));
3252 if (FullConfigRequest
== NULL
) {
3253 *Status
= EFI_OUT_OF_RESOURCES
;
3256 StringPtr
= FullConfigRequest
;
3259 // Start with <ConfigHdr>
3261 StrCpyS (StringPtr
, Length
, ConfigHdr
);
3262 StringPtr
+= StrLen (StringPtr
);
3265 // Loop through all the Offset/Width pairs and append them to ConfigRequest
3267 for (Link
= VarStorageData
->BlockEntry
.ForwardLink
; Link
!= &VarStorageData
->BlockEntry
; Link
= Link
->ForwardLink
) {
3268 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
3269 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3275 (1 + StrLen (BlockData
->Name
) + 1) * sizeof (CHAR16
),
3281 // Append &OFFSET=XXXX&WIDTH=YYYY\0
3285 (8 + 4 + 7 + 4 + 1) * sizeof (CHAR16
),
3286 L
"&OFFSET=%04X&WIDTH=%04X",
3291 StringPtr
+= StrLen (StringPtr
);
3294 // Set to the got full request string.
3296 HiiToLower (FullConfigRequest
);
3298 if (*ConfigRequest
!= NULL
) {
3299 FreePool (*ConfigRequest
);
3301 *ConfigRequest
= FullConfigRequest
;
3307 Generate ConfigRequest Header base on the varstore info.
3309 @param VarStorageData The varstore info.
3310 @param DevicePath Device path for this varstore.
3311 @param ConfigHdr The config header for this varstore.
3313 @retval EFI_SUCCESS Generate the header success.
3314 @retval EFI_OUT_OF_RESOURCES Allocate buffer fail.
3318 IN IFR_VARSTORAGE_DATA
*VarStorageData
,
3319 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
3320 OUT EFI_STRING
*ConfigHdr
3329 Status
= EFI_SUCCESS
;
3335 // Construct <ConfigHdr> : "GUID=...&NAME=...&PATH=..." by VarStorageData Guid, Name and DriverHandle
3337 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*) &VarStorageData
->Guid
, 1, &GuidStr
);
3338 if (VarStorageData
->Name
!= NULL
) {
3339 GenerateSubStr (L
"NAME=", StrLen (VarStorageData
->Name
) * sizeof (CHAR16
), (VOID
*) VarStorageData
->Name
, 2, &NameStr
);
3341 GenerateSubStr (L
"NAME=", 0, NULL
, 2, &NameStr
);
3345 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) DevicePath
),
3346 (VOID
*) DevicePath
,
3350 Length
= StrLen (GuidStr
) + StrLen (NameStr
) + StrLen (PathStr
) + 1;
3351 if (VarStorageData
->Name
== NULL
) {
3355 *ConfigHdr
= AllocateZeroPool (Length
* sizeof (CHAR16
));
3356 if (*ConfigHdr
== NULL
) {
3357 Status
= EFI_OUT_OF_RESOURCES
;
3360 StrCpyS (*ConfigHdr
, Length
, GuidStr
);
3361 StrCatS (*ConfigHdr
, Length
, NameStr
);
3362 if (VarStorageData
->Name
== NULL
) {
3363 StrCatS (*ConfigHdr
, Length
, L
"&");
3365 StrCatS (*ConfigHdr
, Length
, PathStr
);
3368 // Remove the last character L'&'
3370 *(*ConfigHdr
+ StrLen (*ConfigHdr
) - 1) = L
'\0';
3373 if (GuidStr
!= NULL
) {
3377 if (NameStr
!= NULL
) {
3381 if (PathStr
!= NULL
) {
3389 Get Data buffer size based on data type.
3391 @param ValueType The input data type.
3393 @retval The data buffer size for the input type.
3400 UINT16 StorageWidth
;
3402 switch (ValueType
) {
3403 case EFI_IFR_NUMERIC_SIZE_1
:
3404 case EFI_IFR_TYPE_BOOLEAN
:
3405 StorageWidth
= (UINT16
) sizeof (UINT8
);
3408 case EFI_IFR_NUMERIC_SIZE_2
:
3409 StorageWidth
= (UINT16
) sizeof (UINT16
);
3412 case EFI_IFR_NUMERIC_SIZE_4
:
3413 StorageWidth
= (UINT16
) sizeof (UINT32
);
3416 case EFI_IFR_NUMERIC_SIZE_8
:
3417 StorageWidth
= (UINT16
) sizeof (UINT64
);
3420 case EFI_IFR_TYPE_TIME
:
3421 StorageWidth
= (UINT16
) sizeof (EFI_IFR_TIME
);
3424 case EFI_IFR_TYPE_DATE
:
3425 StorageWidth
= (UINT16
) sizeof (EFI_IFR_DATE
);
3433 return StorageWidth
;
3437 Generate ConfigAltResp string base on the varstore info.
3439 @param HiiHandle Hii Handle for this hii package.
3440 @param ConfigHdr The config header for this varstore.
3441 @param VarStorageData The varstore info.
3442 @param DefaultIdArray The Default id array.
3443 @param DefaultAltCfgResp The DefaultAltCfgResp info may be return.
3445 @retval TRUE Need to continue
3446 @retval Others NO need to continue or error occur.
3449 GenerateAltConfigResp (
3450 IN EFI_HII_HANDLE HiiHandle
,
3451 IN CHAR16
*ConfigHdr
,
3452 IN IFR_VARSTORAGE_DATA
*VarStorageData
,
3453 IN IFR_DEFAULT_DATA
*DefaultIdArray
,
3454 IN OUT EFI_STRING
*DefaultAltCfgResp
3460 LIST_ENTRY
*LinkData
;
3461 LIST_ENTRY
*LinkDefault
;
3462 LIST_ENTRY
*ListEntry
;
3464 IFR_BLOCK_DATA
*BlockData
;
3465 IFR_DEFAULT_DATA
*DefaultId
;
3466 IFR_DEFAULT_DATA
*DefaultValueData
;
3469 CHAR16
*DefaultString
;
3473 DefaultString
= NULL
;
3475 // Add length for <ConfigHdr> + '\0'
3477 Length
= StrLen (ConfigHdr
) + 1;
3479 for (Link
= DefaultIdArray
->Entry
.ForwardLink
; Link
!= &DefaultIdArray
->Entry
; Link
= Link
->ForwardLink
) {
3480 DefaultId
= BASE_CR (Link
, IFR_DEFAULT_DATA
, Entry
);
3482 // Add length for "&<ConfigHdr>&ALTCFG=XXXX"
3483 // |1| StrLen (ConfigHdr) | 8 | 4 |
3485 Length
+= (1 + StrLen (ConfigHdr
) + 8 + 4);
3487 for (LinkData
= VarStorageData
->BlockEntry
.ForwardLink
; LinkData
!= &VarStorageData
->BlockEntry
; LinkData
= LinkData
->ForwardLink
) {
3488 BlockData
= BASE_CR (LinkData
, IFR_BLOCK_DATA
, Entry
);
3489 ListEntry
= &BlockData
->DefaultValueEntry
;
3490 for (LinkDefault
= ListEntry
->ForwardLink
; LinkDefault
!= ListEntry
; LinkDefault
= LinkDefault
->ForwardLink
) {
3491 DefaultValueData
= BASE_CR (LinkDefault
, IFR_DEFAULT_DATA
, Entry
);
3492 if (DefaultValueData
->DefaultId
!= DefaultId
->DefaultId
) {
3495 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3497 // Add length for "&Name1=zzzzzzzzzzzz"
3500 Length
+= (1 + StrLen (BlockData
->Name
) + 1 + BlockData
->Width
* 2);
3503 // Add length for "&OFFSET=XXXX&WIDTH=YYYY&VALUE=zzzzzzzzzzzz"
3504 // | 8 | 4 | 7 | 4 | 7 | Width * 2 |
3506 Length
+= (8 + 4 + 7 + 4 + 7 + BlockData
->Width
* 2);
3514 // No default value is found. The default string doesn't exist.
3521 // Allocate buffer for the entire <DefaultAltCfgResp>
3523 *DefaultAltCfgResp
= AllocateZeroPool (Length
* sizeof (CHAR16
));
3524 if (*DefaultAltCfgResp
== NULL
) {
3525 return EFI_OUT_OF_RESOURCES
;
3527 StringPtr
= *DefaultAltCfgResp
;
3530 // Start with <ConfigHdr>
3532 StrCpyS (StringPtr
, Length
, ConfigHdr
);
3533 StringPtr
+= StrLen (StringPtr
);
3535 for (Link
= DefaultIdArray
->Entry
.ForwardLink
; Link
!= &DefaultIdArray
->Entry
; Link
= Link
->ForwardLink
) {
3536 DefaultId
= BASE_CR (Link
, IFR_DEFAULT_DATA
, Entry
);
3538 // Add <AltConfigHdr> of the form "&<ConfigHdr>&ALTCFG=XXXX\0"
3539 // |1| StrLen (ConfigHdr) | 8 | 4 |
3543 (1 + StrLen (ConfigHdr
) + 8 + 4 + 1) * sizeof (CHAR16
),
3546 DefaultId
->DefaultId
3548 StringPtr
+= StrLen (StringPtr
);
3550 for (LinkData
= VarStorageData
->BlockEntry
.ForwardLink
; LinkData
!= &VarStorageData
->BlockEntry
; LinkData
= LinkData
->ForwardLink
) {
3551 BlockData
= BASE_CR (LinkData
, IFR_BLOCK_DATA
, Entry
);
3552 ListEntry
= &BlockData
->DefaultValueEntry
;
3553 for (LinkDefault
= ListEntry
->ForwardLink
; LinkDefault
!= ListEntry
; LinkDefault
= LinkDefault
->ForwardLink
) {
3554 DefaultValueData
= BASE_CR (LinkDefault
, IFR_DEFAULT_DATA
, Entry
);
3555 if (DefaultValueData
->DefaultId
!= DefaultId
->DefaultId
) {
3558 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3561 (1 + StrLen (ConfigHdr
) + 1) * sizeof (CHAR16
),
3565 StringPtr
+= StrLen (StringPtr
);
3568 // Add <BlockConfig>
3569 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>
3573 (8 + 4 + 7 + 4 + 7 + 1) * sizeof (CHAR16
),
3574 L
"&OFFSET=%04X&WIDTH=%04X&VALUE=",
3578 StringPtr
+= StrLen (StringPtr
);
3580 Width
= BlockData
->Width
;
3582 // Convert Value to a hex string in "%x" format
3583 // NOTE: This is in the opposite byte that GUID and PATH use
3585 if (BlockData
->OpCode
== EFI_IFR_STRING_OP
){
3586 DefaultString
= InternalGetString(HiiHandle
, DefaultValueData
->Value
.string
);
3587 TmpBuffer
= (UINT8
*) DefaultString
;
3589 TmpBuffer
= (UINT8
*) &(DefaultValueData
->Value
);
3591 for (; Width
> 0 && (TmpBuffer
!= NULL
); Width
--) {
3592 StringPtr
+= UnicodeValueToString (StringPtr
, PREFIX_ZERO
| RADIX_HEX
, TmpBuffer
[Width
- 1], 2);
3594 if (DefaultString
!= NULL
){
3595 FreePool(DefaultString
);
3596 DefaultString
= NULL
;
3602 HiiToLower (*DefaultAltCfgResp
);
3608 This function gets the full request string and full default value string by
3609 parsing IFR data in HII form packages.
3611 When Request points to NULL string, the request string and default value string
3612 for each varstore in form package will return.
3614 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
3615 @param DevicePath Device Path which Hii Config Access Protocol is registered.
3616 @param Request Pointer to a null-terminated Unicode string in
3617 <ConfigRequest> format. When it doesn't contain
3618 any RequestElement, it will be updated to return
3619 the full RequestElement retrieved from IFR data.
3620 If it points to NULL, the request string for the first
3621 varstore in form package will be merged into a
3622 <MultiConfigRequest> format string and return.
3623 @param AltCfgResp Pointer to a null-terminated Unicode string in
3624 <ConfigAltResp> format. When the pointer is to NULL,
3625 the full default value string retrieved from IFR data
3626 will return. When the pinter is to a string, the
3627 full default value string retrieved from IFR data
3628 will be merged into the input string and return.
3629 When Request points to NULL, the default value string
3630 for each varstore in form package will be merged into
3631 a <MultiConfigAltResp> format string and return.
3632 @param PointerProgress Optional parameter, it can be be NULL.
3633 When it is not NULL, if Request is NULL, it returns NULL.
3634 On return, points to a character in the Request
3635 string. Points to the string's null terminator if
3636 request was successful. Points to the most recent
3637 & before the first failing name / value pair (or
3638 the beginning of the string if the failure is in
3639 the first name / value pair) if the request was
3641 @retval EFI_SUCCESS The Results string is set to the full request string.
3642 And AltCfgResp contains all default value string.
3643 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
3644 @retval EFI_NOT_FOUND The varstore (Guid and Name) in Request string
3645 can't be found in Form package.
3646 @retval EFI_NOT_FOUND HiiPackage can't be got on the input HiiHandle.
3647 @retval EFI_INVALID_PARAMETER Request points to NULL.
3652 GetFullStringFromHiiFormPackages (
3653 IN HII_DATABASE_RECORD
*DataBaseRecord
,
3654 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
3655 IN OUT EFI_STRING
*Request
,
3656 IN OUT EFI_STRING
*AltCfgResp
,
3657 OUT EFI_STRING
*PointerProgress OPTIONAL
3661 UINT8
*HiiFormPackage
;
3663 IFR_BLOCK_DATA
*RequestBlockArray
;
3664 IFR_BLOCK_DATA
*BlockData
;
3665 IFR_DEFAULT_DATA
*DefaultValueData
;
3666 IFR_DEFAULT_DATA
*DefaultId
;
3667 IFR_DEFAULT_DATA
*DefaultIdArray
;
3668 IFR_VARSTORAGE_DATA
*VarStorageData
;
3669 EFI_STRING DefaultAltCfgResp
;
3670 EFI_STRING ConfigHdr
;
3671 EFI_STRING StringPtr
;
3672 EFI_STRING Progress
;
3674 if (DataBaseRecord
== NULL
|| DevicePath
== NULL
|| Request
== NULL
|| AltCfgResp
== NULL
) {
3675 return EFI_INVALID_PARAMETER
;
3679 // Initialize the local variables.
3681 RequestBlockArray
= NULL
;
3682 DefaultIdArray
= NULL
;
3683 VarStorageData
= NULL
;
3684 DefaultAltCfgResp
= NULL
;
3686 HiiFormPackage
= NULL
;
3688 Progress
= *Request
;
3690 Status
= GetFormPackageData (DataBaseRecord
, &HiiFormPackage
, &PackageSize
);
3691 if (EFI_ERROR (Status
)) {
3696 // 1. Get the request block array by Request String when Request string containts the block array.
3699 if (*Request
!= NULL
) {
3700 StringPtr
= *Request
;
3704 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
3705 Status
= EFI_INVALID_PARAMETER
;
3708 StringPtr
+= StrLen (L
"GUID=");
3709 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&NAME=", StrLen (L
"&NAME=")) != 0) {
3712 if (*StringPtr
== L
'\0') {
3713 Status
= EFI_INVALID_PARAMETER
;
3716 StringPtr
+= StrLen (L
"&NAME=");
3717 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&PATH=", StrLen (L
"&PATH=")) != 0) {
3720 if (*StringPtr
== L
'\0') {
3721 Status
= EFI_INVALID_PARAMETER
;
3724 StringPtr
+= StrLen (L
"&PATH=");
3725 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
3729 if (*StringPtr
== L
'\0') {
3731 // No request block is found.
3738 // If StringPtr != NULL, get the request elements.
3740 if (StringPtr
!= NULL
) {
3741 if (StrStr (StringPtr
, L
"&OFFSET=") != NULL
) {
3742 RequestBlockArray
= GetBlockElement(StringPtr
, &Progress
);
3744 RequestBlockArray
= GetNameElement(StringPtr
, &Progress
);
3747 if (RequestBlockArray
== NULL
) {
3748 Status
= EFI_INVALID_PARAMETER
;
3754 // Initialize DefaultIdArray to store the map between DeaultId and DefaultName
3756 DefaultIdArray
= (IFR_DEFAULT_DATA
*) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
3757 if (DefaultIdArray
== NULL
) {
3758 Status
= EFI_OUT_OF_RESOURCES
;
3761 InitializeListHead (&DefaultIdArray
->Entry
);
3764 // Initialize VarStorageData to store the var store Block and Default value information.
3766 VarStorageData
= (IFR_VARSTORAGE_DATA
*) AllocateZeroPool (sizeof (IFR_VARSTORAGE_DATA
));
3767 if (VarStorageData
== NULL
) {
3768 Status
= EFI_OUT_OF_RESOURCES
;
3771 InitializeListHead (&VarStorageData
->Entry
);
3772 InitializeListHead (&VarStorageData
->BlockEntry
);
3775 // 2. Parse FormPackage to get BlockArray and DefaultId Array for the request BlockArray.
3779 // Parse the opcode in form pacakge to get the default setting.
3781 Status
= ParseIfrData (DataBaseRecord
->Handle
,
3783 (UINT32
) PackageSize
,
3788 if (EFI_ERROR (Status
)) {
3793 // No requested varstore in IFR data and directly return
3795 if (VarStorageData
->Type
== 0 && VarStorageData
->Name
== NULL
) {
3796 Status
= EFI_SUCCESS
;
3801 // 3. Construct Request Element (Block Name) for 2.1 and 2.2 case.
3803 Status
= GenerateHdr (VarStorageData
, DevicePath
, &ConfigHdr
);
3804 if (EFI_ERROR (Status
)) {
3808 if (RequestBlockArray
== NULL
) {
3809 if (!GenerateConfigRequest(ConfigHdr
, VarStorageData
, &Status
, Request
)) {
3815 // 4. Construct Default Value string in AltResp according to request element.
3816 // Go through all VarStorageData Entry and get the DefaultId array for each one
3817 // Then construct them all to : ConfigHdr AltConfigHdr ConfigBody AltConfigHdr ConfigBody
3819 Status
= GenerateAltConfigResp (DataBaseRecord
->Handle
,ConfigHdr
, VarStorageData
, DefaultIdArray
, &DefaultAltCfgResp
);
3820 if (EFI_ERROR (Status
)) {
3825 // 5. Merge string into the input AltCfgResp if the iput *AltCfgResp is not NULL.
3827 if (*AltCfgResp
!= NULL
&& DefaultAltCfgResp
!= NULL
) {
3828 Status
= MergeDefaultString (AltCfgResp
, DefaultAltCfgResp
);
3829 FreePool (DefaultAltCfgResp
);
3830 } else if (*AltCfgResp
== NULL
) {
3831 *AltCfgResp
= DefaultAltCfgResp
;
3835 if (RequestBlockArray
!= NULL
) {
3837 // Free Link Array RequestBlockArray
3839 while (!IsListEmpty (&RequestBlockArray
->Entry
)) {
3840 BlockData
= BASE_CR (RequestBlockArray
->Entry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
3841 RemoveEntryList (&BlockData
->Entry
);
3842 if (BlockData
->Name
!= NULL
) {
3843 FreePool (BlockData
->Name
);
3845 FreePool (BlockData
);
3848 FreePool (RequestBlockArray
);
3851 if (VarStorageData
!= NULL
) {
3853 // Free link array VarStorageData
3855 while (!IsListEmpty (&VarStorageData
->BlockEntry
)) {
3856 BlockData
= BASE_CR (VarStorageData
->BlockEntry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
3857 RemoveEntryList (&BlockData
->Entry
);
3858 if (BlockData
->Name
!= NULL
) {
3859 FreePool (BlockData
->Name
);
3862 // Free default value link array
3864 while (!IsListEmpty (&BlockData
->DefaultValueEntry
)) {
3865 DefaultValueData
= BASE_CR (BlockData
->DefaultValueEntry
.ForwardLink
, IFR_DEFAULT_DATA
, Entry
);
3866 RemoveEntryList (&DefaultValueData
->Entry
);
3867 FreePool (DefaultValueData
);
3869 FreePool (BlockData
);
3871 FreePool (VarStorageData
);
3874 if (DefaultIdArray
!= NULL
) {
3876 // Free DefaultId Array
3878 while (!IsListEmpty (&DefaultIdArray
->Entry
)) {
3879 DefaultId
= BASE_CR (DefaultIdArray
->Entry
.ForwardLink
, IFR_DEFAULT_DATA
, Entry
);
3880 RemoveEntryList (&DefaultId
->Entry
);
3881 FreePool (DefaultId
);
3883 FreePool (DefaultIdArray
);
3887 // Free the allocated string
3889 if (ConfigHdr
!= NULL
) {
3890 FreePool (ConfigHdr
);
3894 // Free Pacakge data
3896 if (HiiFormPackage
!= NULL
) {
3897 FreePool (HiiFormPackage
);
3900 if (PointerProgress
!= NULL
) {
3901 if (*Request
== NULL
) {
3902 *PointerProgress
= NULL
;
3903 } else if (EFI_ERROR (Status
)) {
3904 *PointerProgress
= *Request
;
3906 *PointerProgress
= *Request
+ StrLen (*Request
);
3914 This function gets the full request resp string by
3915 parsing IFR data in HII form packages.
3917 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
3919 @param EfiVarStoreInfo The efi varstore info which is save in the EFI
3920 varstore data structure.
3921 @param Request Pointer to a null-terminated Unicode string in
3922 <ConfigRequest> format.
3923 @param RequestResp Pointer to a null-terminated Unicode string in
3924 <ConfigResp> format.
3925 @param AccessProgress On return, points to a character in the Request
3926 string. Points to the string's null terminator if
3927 request was successful. Points to the most recent
3928 & before the first failing name / value pair (or
3929 the beginning of the string if the failure is in
3930 the first name / value pair) if the request was
3933 @retval EFI_SUCCESS The Results string is set to the full request string.
3934 And AltCfgResp contains all default value string.
3935 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
3936 @retval EFI_INVALID_PARAMETER Request points to NULL.
3940 GetConfigRespFromEfiVarStore (
3941 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
3942 IN EFI_IFR_VARSTORE_EFI
*EfiVarStoreInfo
,
3943 IN EFI_STRING Request
,
3944 OUT EFI_STRING
*RequestResp
,
3945 OUT EFI_STRING
*AccessProgress
3949 EFI_STRING VarStoreName
;
3953 Status
= EFI_SUCCESS
;
3956 VarStoreName
= NULL
;
3957 *AccessProgress
= Request
;
3959 VarStoreName
= AllocateZeroPool (AsciiStrSize ((CHAR8
*)EfiVarStoreInfo
->Name
) * sizeof (CHAR16
));
3960 if (VarStoreName
== NULL
) {
3961 Status
= EFI_OUT_OF_RESOURCES
;
3964 AsciiStrToUnicodeStr ((CHAR8
*) EfiVarStoreInfo
->Name
, VarStoreName
);
3967 Status
= gRT
->GetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, NULL
, &BufferSize
, NULL
);
3968 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
3972 VarStore
= AllocateZeroPool (BufferSize
);
3973 ASSERT (VarStore
!= NULL
);
3974 Status
= gRT
->GetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, NULL
, &BufferSize
, VarStore
);
3975 if (EFI_ERROR (Status
)) {
3979 Status
= HiiBlockToConfig(This
, Request
, VarStore
, BufferSize
, RequestResp
, AccessProgress
);
3980 if (EFI_ERROR (Status
)) {
3985 if (VarStoreName
!= NULL
) {
3986 FreePool (VarStoreName
);
3989 if (VarStore
!= NULL
) {
3990 FreePool (VarStore
);
3998 This function route the full request resp string for efi varstore.
4000 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
4002 @param EfiVarStoreInfo The efi varstore info which is save in the EFI
4003 varstore data structure.
4004 @param RequestResp Pointer to a null-terminated Unicode string in
4005 <ConfigResp> format.
4006 @param Result Pointer to a null-terminated Unicode string in
4007 <ConfigResp> format.
4009 @retval EFI_SUCCESS The Results string is set to the full request string.
4010 And AltCfgResp contains all default value string.
4011 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
4012 @retval EFI_INVALID_PARAMETER Request points to NULL.
4016 RouteConfigRespForEfiVarStore (
4017 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
4018 IN EFI_IFR_VARSTORE_EFI
*EfiVarStoreInfo
,
4019 IN EFI_STRING RequestResp
,
4020 OUT EFI_STRING
*Result
4024 EFI_STRING VarStoreName
;
4029 Status
= EFI_SUCCESS
;
4032 VarStoreName
= NULL
;
4034 VarStoreName
= AllocateZeroPool (AsciiStrSize ((CHAR8
*)EfiVarStoreInfo
->Name
) * sizeof (CHAR16
));
4035 if (VarStoreName
== NULL
) {
4036 Status
= EFI_OUT_OF_RESOURCES
;
4039 AsciiStrToUnicodeStr ((CHAR8
*) EfiVarStoreInfo
->Name
, VarStoreName
);
4041 Status
= gRT
->GetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, NULL
, &BufferSize
, NULL
);
4042 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
4046 BlockSize
= BufferSize
;
4047 VarStore
= AllocateZeroPool (BufferSize
);
4048 ASSERT (VarStore
!= NULL
);
4049 Status
= gRT
->GetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, NULL
, &BufferSize
, VarStore
);
4050 if (EFI_ERROR (Status
)) {
4054 Status
= HiiConfigToBlock(This
, RequestResp
, VarStore
, &BlockSize
, Result
);
4055 if (EFI_ERROR (Status
)) {
4059 Status
= gRT
->SetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, EfiVarStoreInfo
->Attributes
, BufferSize
, VarStore
);
4060 if (EFI_ERROR (Status
)) {
4065 if (VarStoreName
!= NULL
) {
4066 FreePool (VarStoreName
);
4069 if (VarStore
!= NULL
) {
4070 FreePool (VarStore
);
4077 Validate the config request elements.
4079 @param ConfigElements A null-terminated Unicode string in <ConfigRequest> format,
4080 without configHdr field.
4082 @retval CHAR16 * THE first Name/value pair not correct.
4083 @retval NULL Success parse the name/value pair
4086 OffsetWidthValidate (
4087 CHAR16
*ConfigElements
4093 StringPtr
= ConfigElements
;
4097 if (StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) != 0) {
4101 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
4104 if (*StringPtr
== L
'\0') {
4108 StringPtr
+= StrLen (L
"&WIDTH=");
4109 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) != 0) {
4113 if (*StringPtr
== L
'\0') {
4120 Validate the config request elements.
4122 @param ConfigElements A null-terminated Unicode string in <ConfigRequest> format,
4123 without configHdr field.
4125 @retval CHAR16 * THE first Name/value pair not correct.
4126 @retval NULL Success parse the name/value pair
4131 CHAR16
*ConfigElements
4137 StringPtr
= ConfigElements
;
4141 if (*StringPtr
!= L
'&') {
4146 StringPtr
= StrStr (StringPtr
, L
"&");
4148 if (StringPtr
== NULL
) {
4155 Validate the config request string.
4157 @param ConfigRequest A null-terminated Unicode string in <ConfigRequest> format.
4159 @retval CHAR16 * THE first element not correct.
4160 @retval NULL Success parse the name/value pair
4164 ConfigRequestValidate (
4165 CHAR16
*ConfigRequest
4168 BOOLEAN HasNameField
;
4171 HasNameField
= TRUE
;
4172 StringPtr
= ConfigRequest
;
4175 // Check <ConfigHdr>
4177 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
4178 return ConfigRequest
;
4180 StringPtr
+= StrLen (L
"GUID=");
4181 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&NAME=", StrLen (L
"&NAME=")) != 0) {
4184 if (*StringPtr
== L
'\0') {
4185 return ConfigRequest
;
4187 StringPtr
+= StrLen (L
"&NAME=");
4188 if (*StringPtr
== L
'&') {
4189 HasNameField
= FALSE
;
4191 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&PATH=", StrLen (L
"&PATH=")) != 0) {
4194 if (*StringPtr
== L
'\0') {
4195 return ConfigRequest
;
4197 StringPtr
+= StrLen (L
"&PATH=");
4198 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
4202 if (*StringPtr
== L
'\0') {
4208 // Should be Buffer varstore, config request should be "OFFSET/Width" pairs.
4210 return OffsetWidthValidate(StringPtr
);
4213 // Should be Name/Value varstore, config request should be "&name1&name2..." pairs.
4215 return NameValueValidate(StringPtr
);
4220 This function allows a caller to extract the current configuration
4221 for one or more named elements from one or more drivers.
4223 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
4225 @param Request A null-terminated Unicode string in
4226 <MultiConfigRequest> format.
4227 @param Progress On return, points to a character in the Request
4228 string. Points to the string's null terminator if
4229 request was successful. Points to the most recent
4230 & before the first failing name / value pair (or
4231 the beginning of the string if the failure is in
4232 the first name / value pair) if the request was
4234 @param Results Null-terminated Unicode string in
4235 <MultiConfigAltResp> format which has all values
4236 filled in for the names in the Request string.
4237 String to be allocated by the called function.
4239 @retval EFI_SUCCESS The Results string is filled with the values
4240 corresponding to all requested names.
4241 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
4242 results that must be stored awaiting possible
4244 @retval EFI_NOT_FOUND Routing data doesn't match any known driver.
4245 Progress set to the "G" in "GUID" of the routing
4246 header that doesn't match. Note: There is no
4247 requirement that all routing data be validated
4248 before any configuration extraction.
4249 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Request
4250 parameter would result in this type of error. The
4251 Progress parameter is set to NULL.
4252 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set to most recent &
4253 before the error or the beginning of the string.
4254 @retval EFI_INVALID_PARAMETER The ExtractConfig function of the underlying HII
4255 Configuration Access Protocol returned
4256 EFI_INVALID_PARAMETER. Progress set to most recent
4257 & before the error or the beginning of the string.
4262 HiiConfigRoutingExtractConfig (
4263 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
4264 IN CONST EFI_STRING Request
,
4265 OUT EFI_STRING
*Progress
,
4266 OUT EFI_STRING
*Results
4269 HII_DATABASE_PRIVATE_DATA
*Private
;
4270 EFI_STRING StringPtr
;
4271 EFI_STRING ConfigRequest
;
4273 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
4274 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
4277 HII_DATABASE_RECORD
*Database
;
4278 UINT8
*DevicePathPkg
;
4279 UINT8
*CurrentDevicePath
;
4280 EFI_HANDLE DriverHandle
;
4281 EFI_HII_HANDLE HiiHandle
;
4282 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
4283 EFI_STRING AccessProgress
;
4284 EFI_STRING AccessResults
;
4285 EFI_STRING AccessProgressBackup
;
4286 EFI_STRING AccessResultsBackup
;
4287 EFI_STRING DefaultResults
;
4288 BOOLEAN FirstElement
;
4289 BOOLEAN IfrDataParsedFlag
;
4290 BOOLEAN IsEfiVarStore
;
4291 EFI_IFR_VARSTORE_EFI
*EfiVarStoreInfo
;
4292 EFI_STRING ErrorPtr
;
4293 UINTN DevicePathSize
;
4294 UINTN ConigStringSize
;
4295 UINTN ConigStringSizeNewsize
;
4296 EFI_STRING ConfigStringPtr
;
4298 if (This
== NULL
|| Progress
== NULL
|| Results
== NULL
) {
4299 return EFI_INVALID_PARAMETER
;
4302 if (Request
== NULL
) {
4304 return EFI_INVALID_PARAMETER
;
4307 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
4308 StringPtr
= Request
;
4309 *Progress
= StringPtr
;
4310 DefaultResults
= NULL
;
4311 ConfigRequest
= NULL
;
4312 Status
= EFI_SUCCESS
;
4313 AccessResults
= NULL
;
4314 AccessProgress
= NULL
;
4315 AccessResultsBackup
= NULL
;
4316 AccessProgressBackup
= NULL
;
4318 IfrDataParsedFlag
= FALSE
;
4319 IsEfiVarStore
= FALSE
;
4320 EfiVarStoreInfo
= NULL
;
4323 // The first element of <MultiConfigRequest> should be
4324 // <GuidHdr>, which is in 'GUID='<Guid> syntax.
4326 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
4327 return EFI_INVALID_PARAMETER
;
4330 FirstElement
= TRUE
;
4333 // Allocate a fix length of memory to store Results. Reallocate memory for
4334 // Results if this fix length is insufficient.
4336 *Results
= (EFI_STRING
) AllocateZeroPool (MAX_STRING_LENGTH
);
4337 if (*Results
== NULL
) {
4338 return EFI_OUT_OF_RESOURCES
;
4341 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) == 0) {
4343 // If parsing error, set Progress to the beginning of the <MultiConfigRequest>
4344 // or most recent & before the error.
4346 if (StringPtr
== Request
) {
4347 *Progress
= StringPtr
;
4349 *Progress
= StringPtr
- 1;
4353 // Process each <ConfigRequest> of <MultiConfigRequest>
4355 Length
= CalculateConfigStringLen (StringPtr
);
4356 ConfigRequest
= AllocateCopyPool ((Length
+ 1) * sizeof (CHAR16
), StringPtr
);
4357 if (ConfigRequest
== NULL
) {
4358 Status
= EFI_OUT_OF_RESOURCES
;
4361 *(ConfigRequest
+ Length
) = 0;
4364 // Get the UEFI device path
4366 Status
= GetDevicePath (ConfigRequest
, (UINT8
**) &DevicePath
);
4367 if (EFI_ERROR (Status
)) {
4372 // Find driver which matches the routing data.
4374 DriverHandle
= NULL
;
4377 for (Link
= Private
->DatabaseList
.ForwardLink
;
4378 Link
!= &Private
->DatabaseList
;
4379 Link
= Link
->ForwardLink
4381 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
4382 if ((DevicePathPkg
= Database
->PackageList
->DevicePathPkg
) != NULL
) {
4383 CurrentDevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
4384 DevicePathSize
= GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) CurrentDevicePath
);
4385 if ((CompareMem (DevicePath
,CurrentDevicePath
,DevicePathSize
) == 0) && IsThisPackageList(Database
, ConfigRequest
)) {
4386 DriverHandle
= Database
->DriverHandle
;
4387 HiiHandle
= Database
->Handle
;
4394 // Try to find driver handle by device path.
4396 if (DriverHandle
== NULL
) {
4397 TempDevicePath
= DevicePath
;
4398 Status
= gBS
->LocateDevicePath (
4399 &gEfiDevicePathProtocolGuid
,
4403 if (EFI_ERROR (Status
) || (DriverHandle
== NULL
)) {
4405 // Routing data does not match any known driver.
4406 // Set Progress to the 'G' in "GUID" of the routing header.
4408 *Progress
= StringPtr
;
4409 Status
= EFI_NOT_FOUND
;
4415 // Validate ConfigRequest String.
4417 ErrorPtr
= ConfigRequestValidate(ConfigRequest
);
4418 if (ErrorPtr
!= NULL
) {
4419 *Progress
= StrStr (StringPtr
, ErrorPtr
);
4420 Status
= EFI_INVALID_PARAMETER
;
4425 // Check whether ConfigRequest contains request string.
4427 IfrDataParsedFlag
= FALSE
;
4428 if ((HiiHandle
!= NULL
) && !GetElementsFromRequest(ConfigRequest
)) {
4430 // Get the full request string from IFR when HiiPackage is registered to HiiHandle
4432 IfrDataParsedFlag
= TRUE
;
4433 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &ConfigRequest
, &DefaultResults
, &AccessProgress
);
4434 if (EFI_ERROR (Status
)) {
4436 // AccessProgress indicates the parsing progress on <ConfigRequest>.
4437 // Map it to the progress on <MultiConfigRequest> then return it.
4439 ASSERT (AccessProgress
!= NULL
);
4440 *Progress
= StrStr (StringPtr
, AccessProgress
);
4444 // Not any request block is found.
4446 if (!GetElementsFromRequest(ConfigRequest
)) {
4447 AccessResults
= AllocateCopyPool (StrSize (ConfigRequest
), ConfigRequest
);
4448 goto NextConfigString
;
4453 // Check whether this ConfigRequest is search from Efi varstore type storage.
4455 Status
= GetVarStoreType(Database
, ConfigRequest
, &IsEfiVarStore
, &EfiVarStoreInfo
);
4456 if (EFI_ERROR (Status
)) {
4460 if (IsEfiVarStore
) {
4462 // Call the GetVariable function to extract settings.
4464 Status
= GetConfigRespFromEfiVarStore(This
, EfiVarStoreInfo
, ConfigRequest
, &AccessResults
, &AccessProgress
);
4465 FreePool (EfiVarStoreInfo
);
4466 if (EFI_ERROR (Status
)) {
4468 // AccessProgress indicates the parsing progress on <ConfigRequest>.
4469 // Map it to the progress on <MultiConfigRequest> then return it.
4471 *Progress
= StrStr (StringPtr
, AccessProgress
);
4476 // For EfiVarstore, call corresponding ConfigAccess protocol to get the AltCfgResp from driver.
4478 Status
= gBS
->HandleProtocol (
4480 &gEfiHiiConfigAccessProtocolGuid
,
4481 (VOID
**) &ConfigAccess
4483 if (EFI_ERROR (Status
)) {
4485 // The driver has EfiVarStore, may not install ConfigAccess protocol.
4486 // So ignore the error status in this case.
4488 Status
= EFI_SUCCESS
;
4490 Status
= ConfigAccess
->ExtractConfig (
4493 &AccessProgressBackup
,
4494 &AccessResultsBackup
4496 if (!EFI_ERROR(Status
)) {
4498 //Merge the AltCfgResp in AccessResultsBackup to AccessResults
4500 if ((AccessResultsBackup
!= NULL
) && (StrStr (AccessResultsBackup
, L
"&ALTCFG=") != NULL
)) {
4501 ConigStringSize
= StrSize (AccessResults
);
4502 ConfigStringPtr
= StrStr (AccessResultsBackup
, L
"&GUID=");
4503 ConigStringSizeNewsize
= StrSize (ConfigStringPtr
) + ConigStringSize
+ sizeof (CHAR16
);
4504 AccessResults
= (EFI_STRING
) ReallocatePool (
4506 ConigStringSizeNewsize
,
4508 StrCatS (AccessResults
, ConigStringSizeNewsize
/ sizeof (CHAR16
), ConfigStringPtr
);
4512 // In the ExtractConfig function of some driver may not support EfiVarStore,
4513 // may return error status, just ignore the error status in this case.
4515 Status
= EFI_SUCCESS
;
4517 if (AccessResultsBackup
!= NULL
) {
4518 FreePool (AccessResultsBackup
);
4519 AccessResultsBackup
= NULL
;
4524 // Call corresponding ConfigAccess protocol to extract settings
4526 Status
= gBS
->HandleProtocol (
4528 &gEfiHiiConfigAccessProtocolGuid
,
4529 (VOID
**) &ConfigAccess
4531 if (EFI_ERROR (Status
)) {
4535 Status
= ConfigAccess
->ExtractConfig (
4542 if (EFI_ERROR (Status
)) {
4544 // AccessProgress indicates the parsing progress on <ConfigRequest>.
4545 // Map it to the progress on <MultiConfigRequest> then return it.
4547 *Progress
= StrStr (StringPtr
, AccessProgress
);
4552 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'
4553 // which seperates the first <ConfigAltResp> and the following ones.
4555 ASSERT (*AccessProgress
== 0);
4558 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
4560 if (!IfrDataParsedFlag
&& HiiHandle
!= NULL
) {
4561 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &ConfigRequest
, &DefaultResults
, NULL
);
4562 ASSERT_EFI_ERROR (Status
);
4565 FreePool (DevicePath
);
4568 if (DefaultResults
!= NULL
) {
4569 Status
= MergeDefaultString (&AccessResults
, DefaultResults
);
4570 ASSERT_EFI_ERROR (Status
);
4571 FreePool (DefaultResults
);
4572 DefaultResults
= NULL
;
4576 if (!FirstElement
) {
4577 Status
= AppendToMultiString (Results
, L
"&");
4578 ASSERT_EFI_ERROR (Status
);
4581 Status
= AppendToMultiString (Results
, AccessResults
);
4582 ASSERT_EFI_ERROR (Status
);
4584 FirstElement
= FALSE
;
4586 FreePool (AccessResults
);
4587 AccessResults
= NULL
;
4588 FreePool (ConfigRequest
);
4589 ConfigRequest
= NULL
;
4592 // Go to next <ConfigRequest> (skip '&').
4594 StringPtr
+= Length
;
4595 if (*StringPtr
== 0) {
4596 *Progress
= StringPtr
;
4604 if (EFI_ERROR (Status
)) {
4605 FreePool (*Results
);
4609 if (ConfigRequest
!= NULL
) {
4610 FreePool (ConfigRequest
);
4613 if (AccessResults
!= NULL
) {
4614 FreePool (AccessResults
);
4617 if (DefaultResults
!= NULL
) {
4618 FreePool (DefaultResults
);
4621 if (DevicePath
!= NULL
) {
4622 FreePool (DevicePath
);
4630 This function allows the caller to request the current configuration for the
4631 entirety of the current HII database and returns the data in a
4632 null-terminated Unicode string.
4634 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
4636 @param Results Null-terminated Unicode string in
4637 <MultiConfigAltResp> format which has all values
4638 filled in for the entirety of the current HII
4639 database. String to be allocated by the called
4640 function. De-allocation is up to the caller.
4642 @retval EFI_SUCCESS The Results string is filled with the values
4643 corresponding to all requested names.
4644 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
4645 results that must be stored awaiting possible
4647 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Results
4648 parameter would result in this type of error.
4653 HiiConfigRoutingExportConfig (
4654 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
4655 OUT EFI_STRING
*Results
4659 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
4660 EFI_STRING AccessResults
;
4661 EFI_STRING Progress
;
4662 EFI_STRING StringPtr
;
4663 EFI_STRING ConfigRequest
;
4665 EFI_HANDLE
*ConfigAccessHandles
;
4666 UINTN NumberConfigAccessHandles
;
4667 BOOLEAN FirstElement
;
4668 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
4669 EFI_HII_HANDLE HiiHandle
;
4670 EFI_STRING DefaultResults
;
4671 HII_DATABASE_PRIVATE_DATA
*Private
;
4673 HII_DATABASE_RECORD
*Database
;
4674 UINT8
*DevicePathPkg
;
4675 UINT8
*CurrentDevicePath
;
4676 BOOLEAN IfrDataParsedFlag
;
4678 if (This
== NULL
|| Results
== NULL
) {
4679 return EFI_INVALID_PARAMETER
;
4682 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
4685 // Allocate a fix length of memory to store Results. Reallocate memory for
4686 // Results if this fix length is insufficient.
4688 *Results
= (EFI_STRING
) AllocateZeroPool (MAX_STRING_LENGTH
);
4689 if (*Results
== NULL
) {
4690 return EFI_OUT_OF_RESOURCES
;
4693 NumberConfigAccessHandles
= 0;
4694 Status
= gBS
->LocateHandleBuffer (
4696 &gEfiHiiConfigAccessProtocolGuid
,
4698 &NumberConfigAccessHandles
,
4699 &ConfigAccessHandles
4701 if (EFI_ERROR (Status
)) {
4705 FirstElement
= TRUE
;
4707 for (Index
= 0; Index
< NumberConfigAccessHandles
; Index
++) {
4708 Status
= gBS
->HandleProtocol (
4709 ConfigAccessHandles
[Index
],
4710 &gEfiHiiConfigAccessProtocolGuid
,
4711 (VOID
**) &ConfigAccess
4713 if (EFI_ERROR (Status
)) {
4718 // Get DevicePath and HiiHandle for this ConfigAccess driver handle
4720 IfrDataParsedFlag
= FALSE
;
4723 DefaultResults
= NULL
;
4725 ConfigRequest
= NULL
;
4726 DevicePath
= DevicePathFromHandle (ConfigAccessHandles
[Index
]);
4727 if (DevicePath
!= NULL
) {
4728 for (Link
= Private
->DatabaseList
.ForwardLink
;
4729 Link
!= &Private
->DatabaseList
;
4730 Link
= Link
->ForwardLink
4732 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
4733 if ((DevicePathPkg
= Database
->PackageList
->DevicePathPkg
) != NULL
) {
4734 CurrentDevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
4738 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) CurrentDevicePath
)
4740 HiiHandle
= Database
->Handle
;
4747 Status
= ConfigAccess
->ExtractConfig (
4753 if (EFI_ERROR (Status
)) {
4755 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
4757 if (HiiHandle
!= NULL
&& DevicePath
!= NULL
) {
4758 IfrDataParsedFlag
= TRUE
;
4759 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &ConfigRequest
, &DefaultResults
, NULL
);
4761 // Get the full request string to get the Current setting again.
4763 if (!EFI_ERROR (Status
) && ConfigRequest
!= NULL
) {
4764 Status
= ConfigAccess
->ExtractConfig (
4770 FreePool (ConfigRequest
);
4772 Status
= EFI_NOT_FOUND
;
4777 if (!EFI_ERROR (Status
)) {
4779 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
4781 if (!IfrDataParsedFlag
&& HiiHandle
!= NULL
&& DevicePath
!= NULL
) {
4782 StringPtr
= StrStr (AccessResults
, L
"&GUID=");
4783 if (StringPtr
!= NULL
) {
4786 if (GetElementsFromRequest (AccessResults
)) {
4787 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &AccessResults
, &DefaultResults
, NULL
);
4788 ASSERT_EFI_ERROR (Status
);
4790 if (StringPtr
!= NULL
) {
4795 // Merge the default sting from IFR code into the got setting from driver.
4797 if (DefaultResults
!= NULL
) {
4798 Status
= MergeDefaultString (&AccessResults
, DefaultResults
);
4799 ASSERT_EFI_ERROR (Status
);
4800 FreePool (DefaultResults
);
4801 DefaultResults
= NULL
;
4805 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'
4806 // which seperates the first <ConfigAltResp> and the following ones.
4808 if (!FirstElement
) {
4809 Status
= AppendToMultiString (Results
, L
"&");
4810 ASSERT_EFI_ERROR (Status
);
4813 Status
= AppendToMultiString (Results
, AccessResults
);
4814 ASSERT_EFI_ERROR (Status
);
4816 FirstElement
= FALSE
;
4818 FreePool (AccessResults
);
4819 AccessResults
= NULL
;
4822 FreePool (ConfigAccessHandles
);
4829 This function processes the results of processing forms and routes it to the
4830 appropriate handlers or storage.
4832 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
4834 @param Configuration A null-terminated Unicode string in
4835 <MulltiConfigResp> format.
4836 @param Progress A pointer to a string filled in with the offset of
4837 the most recent & before the first failing name /
4838 value pair (or the beginning of the string if the
4839 failure is in the first name / value pair) or the
4840 terminating NULL if all was successful.
4842 @retval EFI_SUCCESS The results have been distributed or are awaiting
4844 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
4845 results that must be stored awaiting possible
4847 @retval EFI_INVALID_PARAMETER Passing in a NULL for the Configuration parameter
4848 would result in this type of error.
4849 @retval EFI_NOT_FOUND Target for the specified routing data was not
4855 HiiConfigRoutingRouteConfig (
4856 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
4857 IN CONST EFI_STRING Configuration
,
4858 OUT EFI_STRING
*Progress
4861 HII_DATABASE_PRIVATE_DATA
*Private
;
4862 EFI_STRING StringPtr
;
4863 EFI_STRING ConfigResp
;
4866 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
4867 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
4869 HII_DATABASE_RECORD
*Database
;
4870 UINT8
*DevicePathPkg
;
4871 UINT8
*CurrentDevicePath
;
4872 EFI_HANDLE DriverHandle
;
4873 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
4874 EFI_STRING AccessProgress
;
4875 EFI_IFR_VARSTORE_EFI
*EfiVarStoreInfo
;
4876 BOOLEAN IsEfiVarstore
;
4877 UINTN DevicePathSize
;
4879 if (This
== NULL
|| Progress
== NULL
) {
4880 return EFI_INVALID_PARAMETER
;
4883 if (Configuration
== NULL
) {
4885 return EFI_INVALID_PARAMETER
;
4888 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
4889 StringPtr
= Configuration
;
4890 *Progress
= StringPtr
;
4892 AccessProgress
= NULL
;
4893 EfiVarStoreInfo
= NULL
;
4894 IsEfiVarstore
= FALSE
;
4897 // The first element of <MultiConfigResp> should be
4898 // <GuidHdr>, which is in 'GUID='<Guid> syntax.
4900 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
4901 return EFI_INVALID_PARAMETER
;
4904 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) == 0) {
4906 // If parsing error, set Progress to the beginning of the <MultiConfigResp>
4907 // or most recent & before the error.
4909 if (StringPtr
== Configuration
) {
4910 *Progress
= StringPtr
;
4912 *Progress
= StringPtr
- 1;
4916 // Process each <ConfigResp> of <MultiConfigResp>
4918 Length
= CalculateConfigStringLen (StringPtr
);
4919 ConfigResp
= AllocateCopyPool ((Length
+ 1) * sizeof (CHAR16
), StringPtr
);
4920 if (ConfigResp
== NULL
) {
4921 return EFI_OUT_OF_RESOURCES
;
4924 // Append '\0' to the end of ConfigRequest
4926 *(ConfigResp
+ Length
) = 0;
4929 // Get the UEFI device path
4931 Status
= GetDevicePath (ConfigResp
, (UINT8
**) &DevicePath
);
4932 if (EFI_ERROR (Status
)) {
4933 FreePool (ConfigResp
);
4938 // Find driver which matches the routing data.
4940 DriverHandle
= NULL
;
4941 for (Link
= Private
->DatabaseList
.ForwardLink
;
4942 Link
!= &Private
->DatabaseList
;
4943 Link
= Link
->ForwardLink
4945 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
4947 if ((DevicePathPkg
= Database
->PackageList
->DevicePathPkg
) != NULL
) {
4948 CurrentDevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
4949 DevicePathSize
= GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) CurrentDevicePath
);
4950 if ((CompareMem (DevicePath
,CurrentDevicePath
,DevicePathSize
) == 0) && IsThisPackageList(Database
, ConfigResp
)) {
4951 DriverHandle
= Database
->DriverHandle
;
4958 // Try to find driver handle by device path.
4960 if (DriverHandle
== NULL
) {
4961 TempDevicePath
= DevicePath
;
4962 Status
= gBS
->LocateDevicePath (
4963 &gEfiDevicePathProtocolGuid
,
4967 if (EFI_ERROR (Status
) || (DriverHandle
== NULL
)) {
4969 // Routing data does not match any known driver.
4970 // Set Progress to the 'G' in "GUID" of the routing header.
4972 FreePool (DevicePath
);
4973 *Progress
= StringPtr
;
4974 FreePool (ConfigResp
);
4975 return EFI_NOT_FOUND
;
4979 FreePool (DevicePath
);
4982 // Check whether this ConfigRequest is search from Efi varstore type storage.
4984 Status
= GetVarStoreType(Database
, ConfigResp
, &IsEfiVarstore
, &EfiVarStoreInfo
);
4985 if (EFI_ERROR (Status
)) {
4989 if (IsEfiVarstore
) {
4991 // Call the SetVariable function to route settings.
4993 Status
= RouteConfigRespForEfiVarStore(This
, EfiVarStoreInfo
, ConfigResp
, &AccessProgress
);
4994 FreePool (EfiVarStoreInfo
);
4997 // Call corresponding ConfigAccess protocol to route settings
4999 Status
= gBS
->HandleProtocol (
5001 &gEfiHiiConfigAccessProtocolGuid
,
5002 (VOID
**) &ConfigAccess
5004 if (EFI_ERROR (Status
)) {
5005 *Progress
= StringPtr
;
5006 FreePool (ConfigResp
);
5007 return EFI_NOT_FOUND
;
5010 Status
= ConfigAccess
->RouteConfig (
5016 if (EFI_ERROR (Status
)) {
5017 ASSERT (AccessProgress
!= NULL
);
5019 // AccessProgress indicates the parsing progress on <ConfigResp>.
5020 // Map it to the progress on <MultiConfigResp> then return it.
5022 *Progress
= StrStr (StringPtr
, AccessProgress
);
5024 FreePool (ConfigResp
);
5028 FreePool (ConfigResp
);
5032 // Go to next <ConfigResp> (skip '&').
5034 StringPtr
+= Length
;
5035 if (*StringPtr
== 0) {
5036 *Progress
= StringPtr
;
5049 This helper function is to be called by drivers to map configuration data
5050 stored in byte array ("block") formats such as UEFI Variables into current
5051 configuration strings.
5053 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
5055 @param ConfigRequest A null-terminated Unicode string in
5056 <ConfigRequest> format.
5057 @param Block Array of bytes defining the block's configuration.
5058 @param BlockSize Length in bytes of Block.
5059 @param Config Filled-in configuration string. String allocated
5060 by the function. Returned only if call is
5061 successful. It is <ConfigResp> string format.
5062 @param Progress A pointer to a string filled in with the offset of
5063 the most recent & before the first failing
5064 name/value pair (or the beginning of the string if
5065 the failure is in the first name / value pair) or
5066 the terminating NULL if all was successful.
5068 @retval EFI_SUCCESS The request succeeded. Progress points to the null
5069 terminator at the end of the ConfigRequest
5071 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress
5072 points to the first character of ConfigRequest.
5073 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigRequest or
5074 Block parameter would result in this type of
5075 error. Progress points to the first character of
5077 @retval EFI_DEVICE_ERROR Block not large enough. Progress undefined.
5078 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted string.
5079 Block is left updated and Progress points at
5080 the "&" preceding the first non-<BlockName>.
5086 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
5087 IN CONST EFI_STRING ConfigRequest
,
5088 IN CONST UINT8
*Block
,
5089 IN CONST UINTN BlockSize
,
5090 OUT EFI_STRING
*Config
,
5091 OUT EFI_STRING
*Progress
5094 HII_DATABASE_PRIVATE_DATA
*Private
;
5095 EFI_STRING StringPtr
;
5103 EFI_STRING ValueStr
;
5104 EFI_STRING ConfigElement
;
5112 if (This
== NULL
|| Progress
== NULL
|| Config
== NULL
) {
5113 return EFI_INVALID_PARAMETER
;
5116 if (Block
== NULL
|| ConfigRequest
== NULL
) {
5117 *Progress
= ConfigRequest
;
5118 return EFI_INVALID_PARAMETER
;
5122 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
5123 ASSERT (Private
!= NULL
);
5125 StringPtr
= ConfigRequest
;
5128 ConfigElement
= NULL
;
5131 // Allocate a fix length of memory to store Results. Reallocate memory for
5132 // Results if this fix length is insufficient.
5134 *Config
= (EFI_STRING
) AllocateZeroPool (MAX_STRING_LENGTH
);
5135 if (*Config
== NULL
) {
5136 return EFI_OUT_OF_RESOURCES
;
5142 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
5143 *Progress
= StringPtr
;
5144 Status
= EFI_INVALID_PARAMETER
;
5147 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"PATH=", StrLen (L
"PATH=")) != 0) {
5150 if (*StringPtr
== 0) {
5151 *Progress
= StringPtr
- 1;
5152 Status
= EFI_INVALID_PARAMETER
;
5156 while (*StringPtr
!= L
'&' && *StringPtr
!= 0) {
5159 if (*StringPtr
== 0) {
5160 *Progress
= StringPtr
;
5162 AppendToMultiString(Config
, ConfigRequest
);
5163 HiiToLower (*Config
);
5173 // Copy <ConfigHdr> and an additional '&' to <ConfigResp>
5175 TemChar
= *StringPtr
;
5177 AppendToMultiString(Config
, ConfigRequest
);
5178 *StringPtr
= TemChar
;
5181 // Parse each <RequestElement> if exists
5182 // Only <BlockName> format is supported by this help function.
5183 // <BlockName> ::= 'OFFSET='<Number>&'WIDTH='<Number>
5185 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"OFFSET=", StrLen (L
"OFFSET=")) == 0) {
5187 // Back up the header of one <BlockName>
5191 StringPtr
+= StrLen (L
"OFFSET=");
5195 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
5196 if (EFI_ERROR (Status
)) {
5197 *Progress
= TmpPtr
- 1;
5204 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
5206 FreePool (TmpBuffer
);
5208 StringPtr
+= Length
;
5209 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
5210 *Progress
= TmpPtr
- 1;
5211 Status
= EFI_INVALID_PARAMETER
;
5214 StringPtr
+= StrLen (L
"&WIDTH=");
5219 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
5220 if (EFI_ERROR (Status
)) {
5221 *Progress
= TmpPtr
- 1;
5228 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
5230 FreePool (TmpBuffer
);
5232 StringPtr
+= Length
;
5233 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
5234 *Progress
= TmpPtr
- 1;
5235 Status
= EFI_INVALID_PARAMETER
;
5240 // Calculate Value and convert it to hex string.
5242 if (Offset
+ Width
> BlockSize
) {
5243 *Progress
= StringPtr
;
5244 Status
= EFI_DEVICE_ERROR
;
5248 Value
= (UINT8
*) AllocateZeroPool (Width
);
5249 if (Value
== NULL
) {
5250 *Progress
= ConfigRequest
;
5251 Status
= EFI_OUT_OF_RESOURCES
;
5255 CopyMem (Value
, (UINT8
*) Block
+ Offset
, Width
);
5257 Length
= Width
* 2 + 1;
5258 ValueStr
= (EFI_STRING
) AllocateZeroPool (Length
* sizeof (CHAR16
));
5259 if (ValueStr
== NULL
) {
5260 *Progress
= ConfigRequest
;
5261 Status
= EFI_OUT_OF_RESOURCES
;
5265 TemString
= ValueStr
;
5266 TemBuffer
= Value
+ Width
- 1;
5267 for (Index
= 0; Index
< Width
; Index
++, TemBuffer
--) {
5268 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
5275 // Build a ConfigElement
5277 Length
+= StringPtr
- TmpPtr
+ 1 + StrLen (L
"VALUE=");
5278 ConfigElement
= (EFI_STRING
) AllocateZeroPool (Length
* sizeof (CHAR16
));
5279 if (ConfigElement
== NULL
) {
5280 Status
= EFI_OUT_OF_RESOURCES
;
5283 CopyMem (ConfigElement
, TmpPtr
, (StringPtr
- TmpPtr
+ 1) * sizeof (CHAR16
));
5284 if (*StringPtr
== 0) {
5285 *(ConfigElement
+ (StringPtr
- TmpPtr
)) = L
'&';
5287 *(ConfigElement
+ (StringPtr
- TmpPtr
) + 1) = 0;
5288 StrCatS (ConfigElement
, Length
, L
"VALUE=");
5289 StrCatS (ConfigElement
, Length
, ValueStr
);
5291 AppendToMultiString (Config
, ConfigElement
);
5293 FreePool (ConfigElement
);
5294 FreePool (ValueStr
);
5295 ConfigElement
= NULL
;
5299 // If '\0', parsing is finished. Otherwise skip '&' to continue
5301 if (*StringPtr
== 0) {
5304 AppendToMultiString (Config
, L
"&");
5309 if (*StringPtr
!= 0) {
5310 *Progress
= StringPtr
- 1;
5311 Status
= EFI_INVALID_PARAMETER
;
5315 HiiToLower (*Config
);
5316 *Progress
= StringPtr
;
5320 if (*Config
!= NULL
) {
5324 if (ValueStr
!= NULL
) {
5325 FreePool (ValueStr
);
5327 if (Value
!= NULL
) {
5330 if (ConfigElement
!= NULL
) {
5331 FreePool (ConfigElement
);
5340 This helper function is to be called by drivers to map configuration strings
5341 to configurations stored in byte array ("block") formats such as UEFI Variables.
5343 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
5345 @param ConfigResp A null-terminated Unicode string in <ConfigResp>
5347 @param Block A possibly null array of bytes representing the
5348 current block. Only bytes referenced in the
5349 ConfigResp string in the block are modified. If
5350 this parameter is null or if the *BlockSize
5351 parameter is (on input) shorter than required by
5352 the Configuration string, only the BlockSize
5353 parameter is updated and an appropriate status
5354 (see below) is returned.
5355 @param BlockSize The length of the Block in units of UINT8. On
5356 input, this is the size of the Block. On output,
5357 if successful, contains the largest index of the
5358 modified byte in the Block, or the required buffer
5359 size if the Block is not large enough.
5360 @param Progress On return, points to an element of the ConfigResp
5361 string filled in with the offset of the most
5362 recent '&' before the first failing name / value
5363 pair (or the beginning of the string if the
5364 failure is in the first name / value pair) or the
5365 terminating NULL if all was successful.
5367 @retval EFI_SUCCESS The request succeeded. Progress points to the null
5368 terminator at the end of the ConfigResp string.
5369 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress
5370 points to the first character of ConfigResp.
5371 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigResp or
5372 Block parameter would result in this type of
5373 error. Progress points to the first character of
5375 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted name /
5376 value pair. Block is left updated and
5377 Progress points at the '&' preceding the first
5379 @retval EFI_BUFFER_TOO_SMALL Block not large enough. Progress undefined.
5380 BlockSize is updated with the required buffer size.
5381 @retval EFI_NOT_FOUND Target for the specified routing data was not found.
5382 Progress points to the "G" in "GUID" of the errant
5389 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
5390 IN CONST EFI_STRING ConfigResp
,
5391 IN OUT UINT8
*Block
,
5392 IN OUT UINTN
*BlockSize
,
5393 OUT EFI_STRING
*Progress
5396 HII_DATABASE_PRIVATE_DATA
*Private
;
5397 EFI_STRING StringPtr
;
5410 if (This
== NULL
|| BlockSize
== NULL
|| Progress
== NULL
) {
5411 return EFI_INVALID_PARAMETER
;
5414 *Progress
= ConfigResp
;
5415 if (ConfigResp
== NULL
) {
5416 return EFI_INVALID_PARAMETER
;
5419 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
5420 ASSERT (Private
!= NULL
);
5422 StringPtr
= ConfigResp
;
5423 BufferSize
= *BlockSize
;
5430 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
5431 *Progress
= StringPtr
;
5432 Status
= EFI_INVALID_PARAMETER
;
5435 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"PATH=", StrLen (L
"PATH=")) != 0) {
5438 if (*StringPtr
== 0) {
5439 *Progress
= StringPtr
;
5440 Status
= EFI_INVALID_PARAMETER
;
5444 while (*StringPtr
!= L
'&' && *StringPtr
!= 0) {
5447 if (*StringPtr
== 0) {
5448 *Progress
= StringPtr
;
5449 Status
= EFI_INVALID_PARAMETER
;
5454 // Parse each <ConfigElement> if exists
5455 // Only '&'<BlockConfig> format is supported by this help function.
5456 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE='<Number>
5458 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) == 0) {
5460 StringPtr
+= StrLen (L
"&OFFSET=");
5464 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
5465 if (EFI_ERROR (Status
)) {
5473 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
5475 FreePool (TmpBuffer
);
5477 StringPtr
+= Length
;
5478 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
5480 Status
= EFI_INVALID_PARAMETER
;
5483 StringPtr
+= StrLen (L
"&WIDTH=");
5488 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
5489 if (EFI_ERROR (Status
)) {
5497 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
5499 FreePool (TmpBuffer
);
5501 StringPtr
+= Length
;
5502 if (StrnCmp (StringPtr
, L
"&VALUE=", StrLen (L
"&VALUE=")) != 0) {
5504 Status
= EFI_INVALID_PARAMETER
;
5507 StringPtr
+= StrLen (L
"&VALUE=");
5512 Status
= GetValueOfNumber (StringPtr
, &Value
, &Length
);
5513 if (EFI_ERROR (Status
)) {
5518 StringPtr
+= Length
;
5519 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
5521 Status
= EFI_INVALID_PARAMETER
;
5526 // Update the Block with configuration info
5528 if ((Block
!= NULL
) && (Offset
+ Width
<= BufferSize
)) {
5529 CopyMem (Block
+ Offset
, Value
, Width
);
5531 if (Offset
+ Width
> MaxBlockSize
) {
5532 MaxBlockSize
= Offset
+ Width
;
5539 // If '\0', parsing is finished.
5541 if (*StringPtr
== 0) {
5547 // The input string is not ConfigResp format, return error.
5549 if (*StringPtr
!= 0) {
5550 *Progress
= StringPtr
;
5551 Status
= EFI_INVALID_PARAMETER
;
5555 *Progress
= StringPtr
+ StrLen (StringPtr
);
5556 *BlockSize
= MaxBlockSize
- 1;
5558 if (MaxBlockSize
> BufferSize
) {
5559 *BlockSize
= MaxBlockSize
;
5560 if (Block
!= NULL
) {
5561 return EFI_BUFFER_TOO_SMALL
;
5565 if (Block
== NULL
) {
5566 *Progress
= ConfigResp
;
5567 return EFI_INVALID_PARAMETER
;
5574 if (Value
!= NULL
) {
5582 This helper function is to be called by drivers to extract portions of
5583 a larger configuration string.
5585 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
5587 @param Configuration A null-terminated Unicode string in
5588 <MultiConfigAltResp> format.
5589 @param Guid A pointer to the GUID value to search for in the
5590 routing portion of the ConfigResp string when
5591 retrieving the requested data. If Guid is NULL,
5592 then all GUID values will be searched for.
5593 @param Name A pointer to the NAME value to search for in the
5594 routing portion of the ConfigResp string when
5595 retrieving the requested data. If Name is NULL,
5596 then all Name values will be searched for.
5597 @param DevicePath A pointer to the PATH value to search for in the
5598 routing portion of the ConfigResp string when
5599 retrieving the requested data. If DevicePath is
5600 NULL, then all DevicePath values will be searched
5602 @param AltCfgId A pointer to the ALTCFG value to search for in the
5603 routing portion of the ConfigResp string when
5604 retrieving the requested data. If this parameter
5605 is NULL, then the current setting will be
5607 @param AltCfgResp A pointer to a buffer which will be allocated by
5608 the function which contains the retrieved string
5609 as requested. This buffer is only allocated if
5610 the call was successful. It is <ConfigResp> format.
5612 @retval EFI_SUCCESS The request succeeded. The requested data was
5613 extracted and placed in the newly allocated
5615 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate AltCfgResp.
5616 @retval EFI_INVALID_PARAMETER Any parameter is invalid.
5617 @retval EFI_NOT_FOUND Target for the specified routing data was not
5624 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
5625 IN CONST EFI_STRING Configuration
,
5626 IN CONST EFI_GUID
*Guid
,
5627 IN CONST EFI_STRING Name
,
5628 IN CONST EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
5629 IN CONST UINT16
*AltCfgId
,
5630 OUT EFI_STRING
*AltCfgResp
5634 EFI_STRING StringPtr
;
5635 EFI_STRING HdrStart
;
5642 EFI_STRING AltIdStr
;
5659 if (This
== NULL
|| Configuration
== NULL
|| AltCfgResp
== NULL
) {
5660 return EFI_INVALID_PARAMETER
;
5663 StringPtr
= Configuration
;
5664 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
5665 return EFI_INVALID_PARAMETER
;
5669 // Generate the sub string for later matching.
5671 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*) Guid
, 1, &GuidStr
);
5674 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) DevicePath
),
5675 (VOID
*) DevicePath
,
5679 if (AltCfgId
!= NULL
) {
5680 GenerateSubStr (L
"ALTCFG=", sizeof (UINT16
), (VOID
*) AltCfgId
, 3, &AltIdStr
);
5683 GenerateSubStr (L
"NAME=", StrLen (Name
) * sizeof (CHAR16
), (VOID
*) Name
, 2, &NameStr
);
5685 GenerateSubStr (L
"NAME=", 0, NULL
, 2, &NameStr
);
5688 while (*StringPtr
!= 0) {
5690 // Try to match the GUID
5693 TmpPtr
= StrStr (StringPtr
, GuidStr
);
5694 if (TmpPtr
== NULL
) {
5695 Status
= EFI_NOT_FOUND
;
5701 // Jump to <NameHdr>
5704 StringPtr
= TmpPtr
+ StrLen (GuidStr
);
5706 StringPtr
= StrStr (TmpPtr
, L
"NAME=");
5707 if (StringPtr
== NULL
) {
5708 Status
= EFI_NOT_FOUND
;
5716 // Try to match the NAME
5718 if (GuidFlag
&& !NameFlag
) {
5719 if (StrnCmp (StringPtr
, NameStr
, StrLen (NameStr
)) != 0) {
5723 // Jump to <PathHdr>
5726 StringPtr
+= StrLen (NameStr
);
5728 StringPtr
= StrStr (StringPtr
, L
"PATH=");
5729 if (StringPtr
== NULL
) {
5730 Status
= EFI_NOT_FOUND
;
5739 // Try to match the DevicePath
5741 if (GuidFlag
&& NameFlag
&& !PathFlag
) {
5742 if (StrnCmp (StringPtr
, PathStr
, StrLen (PathStr
)) != 0) {
5747 // Jump to '&' before <DescHdr> or <ConfigBody>
5749 if (DevicePath
!= NULL
) {
5750 StringPtr
+= StrLen (PathStr
);
5752 StringPtr
= StrStr (StringPtr
, L
"&");
5753 if (StringPtr
== NULL
) {
5754 Status
= EFI_NOT_FOUND
;
5765 // Try to match the AltCfgId
5767 if (GuidFlag
&& NameFlag
&& PathFlag
) {
5768 if (AltCfgId
== NULL
) {
5770 // Return Current Setting when AltCfgId is NULL.
5772 Status
= OutputConfigBody (StringPtr
, &Result
);
5776 // Search the <ConfigAltResp> to get the <AltResp> with AltCfgId.
5778 if (StrnCmp (StringPtr
, AltIdStr
, StrLen (AltIdStr
)) != 0) {
5784 // Skip AltIdStr and &
5786 StringPtr
= StringPtr
+ StrLen (AltIdStr
);
5787 Status
= OutputConfigBody (StringPtr
, &Result
);
5793 Status
= EFI_NOT_FOUND
;
5797 if (!EFI_ERROR (Status
) && (Result
!= NULL
)) {
5799 // Copy the <ConfigHdr> and <ConfigBody>
5801 Length
= HdrEnd
- HdrStart
+ StrLen (Result
) + 1;
5802 *AltCfgResp
= AllocateZeroPool (Length
* sizeof (CHAR16
));
5803 if (*AltCfgResp
== NULL
) {
5804 Status
= EFI_OUT_OF_RESOURCES
;
5806 StrnCpyS (*AltCfgResp
, Length
, HdrStart
, HdrEnd
- HdrStart
);
5807 StrCatS (*AltCfgResp
, Length
, Result
);
5808 Status
= EFI_SUCCESS
;
5812 if (GuidStr
!= NULL
) {
5815 if (NameStr
!= NULL
) {
5818 if (PathStr
!= NULL
) {
5821 if (AltIdStr
!= NULL
) {
5822 FreePool (AltIdStr
);
5824 if (Result
!= NULL
) {