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
))) {
552 FreePool (TempBuffer
);
556 FreePool (TempBuffer
);
558 BlockPtr
= StrStr (BlockPtr
+ 1, BlockName
);
565 Compare the <AltResp> in ConfigAltResp and DefaultAltCfgResp, if the <AltResp>
566 in DefaultAltCfgResp but not in ConfigAltResp,add it to the ConfigAltResp.
568 @param DefaultAltCfgResp Pointer to a null-terminated Unicode string in
569 <MultiConfigAltResp> format. The default value
570 string may contain more than one ConfigAltResp
571 string for the different varstore buffer.
572 @param ConfigAltResp Pointer to a null-terminated Unicode string in
573 <ConfigAltResp> format.
574 @param AltConfigHdr Pointer to a Unicode string in <AltConfigHdr> format.
575 @param ConfigAltRespChanged Whether the ConfigAltResp has been changed.
577 @retval EFI_OUT_OF_RESOURCES Insufficient resources to store neccessary structures.
578 @retval EFI_SUCCESS The function finishes successfully.
582 CompareBlockElementDefault (
583 IN EFI_STRING DefaultAltCfgResp
,
584 IN OUT EFI_STRING
*ConfigAltResp
,
585 IN EFI_STRING AltConfigHdr
,
586 IN OUT BOOLEAN
*ConfigAltRespChanged
591 EFI_STRING BlockPtrStart
;
592 EFI_STRING StringPtr
;
593 EFI_STRING AppendString
;
594 EFI_STRING AltConfigHdrPtr
;
604 // Make BlockPtr point to the first <BlockConfig> with AltConfigHdr in DefaultAltCfgResp.
606 AltConfigHdrPtr
= StrStr (DefaultAltCfgResp
, AltConfigHdr
);
607 ASSERT (AltConfigHdrPtr
!= NULL
);
608 BlockPtr
= StrStr (AltConfigHdrPtr
, L
"&OFFSET=");
610 // Make StringPtr point to the AltConfigHdr in ConfigAltResp.
612 StringPtr
= StrStr (*ConfigAltResp
, AltConfigHdr
);
613 ASSERT (StringPtr
!= NULL
);
615 while (BlockPtr
!= NULL
) {
617 // Find the "&OFFSET=<Number>" block and get the value of the Number with AltConfigHdr in DefaultAltCfgResp.
619 BlockPtrStart
= BlockPtr
;
620 BlockPtr
+= StrLen (L
"&OFFSET=");
621 Status
= GetValueOfNumber (BlockPtr
, &TempBuffer
, &OffsetLength
);
622 if (EFI_ERROR (Status
)) {
623 Status
= EFI_OUT_OF_RESOURCES
;
627 // To find the same "&OFFSET=<Number>" block in ConfigAltResp.
629 Status
= FindSameBlockElement (StringPtr
, L
"&OFFSET=", TempBuffer
, &FoundOffset
, OffsetLength
);
630 if (TempBuffer
!= NULL
) {
631 FreePool (TempBuffer
);
634 if (EFI_ERROR (Status
)) {
635 Status
= EFI_OUT_OF_RESOURCES
;
640 // Don't find the same "&OFFSET=<Number>" block in ConfigAltResp.
641 // Calculate the size of <BlockConfig>.
642 // <BlockConfig>::='OFFSET='<Number>'&WIDTH='<Number>'&VALUE='<Number>.
644 BlockPtr
= StrStr (BlockPtr
+ 1, L
"&OFFSET=");
645 if (BlockPtr
!= NULL
) {
646 AppendSize
= (BlockPtr
- BlockPtrStart
) * sizeof (CHAR16
);
648 AppendSize
= StrSize (BlockPtrStart
);
651 // Copy the <BlockConfig> to AppendString.
653 if (AppendString
== NULL
) {
654 AppendString
= (EFI_STRING
) AllocateZeroPool (AppendSize
+ sizeof (CHAR16
));
655 StrnCatS (AppendString
, AppendSize
/ sizeof (CHAR16
) + 1, BlockPtrStart
, AppendSize
/ sizeof (CHAR16
));
657 TotalSize
= StrSize (AppendString
) + AppendSize
+ sizeof (CHAR16
);
658 AppendString
= (EFI_STRING
) ReallocatePool (
659 StrSize (AppendString
),
663 if (AppendString
== NULL
) {
664 Status
= EFI_OUT_OF_RESOURCES
;
667 StrnCatS (AppendString
, TotalSize
/ sizeof (CHAR16
), BlockPtrStart
, AppendSize
/ sizeof (CHAR16
));
671 // To find next "&OFFSET=<Number>" block with AltConfigHdr in DefaultAltCfgResp.
673 BlockPtr
= StrStr (BlockPtr
+ 1, L
"&OFFSET=");
677 if (AppendString
!= NULL
) {
679 // Reallocate ConfigAltResp to copy the AppendString.
681 TotalSize
= StrSize (*ConfigAltResp
) + StrSize (AppendString
) + sizeof (CHAR16
);
682 *ConfigAltResp
= (EFI_STRING
) ReallocatePool (
683 StrSize (*ConfigAltResp
),
687 if (*ConfigAltResp
== NULL
) {
688 Status
= EFI_OUT_OF_RESOURCES
;
691 StrCatS (*ConfigAltResp
, TotalSize
/ sizeof (CHAR16
), AppendString
);
692 *ConfigAltRespChanged
= TRUE
;
695 Status
= EFI_SUCCESS
;
698 if (AppendString
!= NULL
) {
699 FreePool (AppendString
);
706 Compare the <AltResp> in ConfigAltResp and DefaultAltCfgResp, if the <AltResp>
707 in DefaultAltCfgResp but not in ConfigAltResp,add it to the ConfigAltResp.
709 @param DefaultAltCfgResp Pointer to a null-terminated Unicode string in
710 <MultiConfigAltResp> format. The default value
711 string may contain more than one ConfigAltResp
712 string for the different varstore buffer.
713 @param ConfigAltResp Pointer to a null-terminated Unicode string in
714 <ConfigAltResp> format.
715 @param AltConfigHdr Pointer to a Unicode string in <AltConfigHdr> format.
716 @param ConfigAltRespChanged Whether the ConfigAltResp has been changed.
718 @retval EFI_OUT_OF_RESOURCES Insufficient resources to store neccessary structures.
719 @retval EFI_SUCCESS The function finishes successfully.
723 CompareNameElementDefault (
724 IN EFI_STRING DefaultAltCfgResp
,
725 IN OUT EFI_STRING
*ConfigAltResp
,
726 IN EFI_STRING AltConfigHdr
,
727 IN OUT BOOLEAN
*ConfigAltRespChanged
731 EFI_STRING NvConfigPtr
;
732 EFI_STRING NvConfigStart
;
733 EFI_STRING NvConfigValuePtr
;
734 EFI_STRING StringPtr
;
735 EFI_STRING NvConfigExist
;
736 EFI_STRING AppendString
;
742 NvConfigExist
= NULL
;
744 // Make NvConfigPtr point to the first <NvConfig> with AltConfigHdr in DefaultAltCfgResp.
746 NvConfigPtr
= StrStr (DefaultAltCfgResp
, AltConfigHdr
);
747 ASSERT (NvConfigPtr
!= NULL
);
748 NvConfigPtr
= StrStr (NvConfigPtr
+ StrLen(AltConfigHdr
),L
"&");
750 // Make StringPtr point to the first <NvConfig> with AltConfigHdr in ConfigAltResp.
752 StringPtr
= StrStr (*ConfigAltResp
, AltConfigHdr
);
753 ASSERT (StringPtr
!= NULL
);
754 StringPtr
= StrStr (StringPtr
+ StrLen (AltConfigHdr
), L
"&");
755 ASSERT (StringPtr
!= NULL
);
757 while (NvConfigPtr
!= NULL
) {
759 // <NvConfig> ::= <Label>'='<String> | <Label>'='<Number>.
760 // Get the <Label> with AltConfigHdr in DefaultAltCfgResp.
762 NvConfigStart
= NvConfigPtr
;
763 NvConfigValuePtr
= StrStr (NvConfigPtr
+ 1, L
"=");
764 ASSERT (NvConfigValuePtr
!= NULL
);
765 TempChar
= *NvConfigValuePtr
;
766 *NvConfigValuePtr
= L
'\0';
768 // Get the <Label> with AltConfigHdr in ConfigAltResp.
770 NvConfigExist
= StrStr (StringPtr
, NvConfigPtr
);
771 if (NvConfigExist
== NULL
) {
773 // Don't find same <Label> in ConfigAltResp.
774 // Calculate the size of <NvConfig>.
776 *NvConfigValuePtr
= TempChar
;
777 NvConfigPtr
= StrStr (NvConfigPtr
+ 1, L
"&");
778 if (NvConfigPtr
!= NULL
) {
779 AppendSize
= (NvConfigPtr
- NvConfigStart
) * sizeof (CHAR16
);
781 AppendSize
= StrSize (NvConfigStart
);
784 // Copy the <NvConfig> to AppendString.
786 if (AppendString
== NULL
) {
787 AppendString
= (EFI_STRING
) AllocateZeroPool (AppendSize
+ sizeof (CHAR16
));
788 StrnCatS (AppendString
, AppendSize
/ sizeof (CHAR16
) + 1, NvConfigStart
, AppendSize
/ sizeof (CHAR16
));
790 TotalSize
= StrSize (AppendString
) + AppendSize
+ sizeof (CHAR16
);
791 AppendString
= (EFI_STRING
) ReallocatePool (
792 StrSize (AppendString
),
796 if (AppendString
== NULL
) {
797 Status
= EFI_OUT_OF_RESOURCES
;
800 StrnCatS (AppendString
, TotalSize
/ sizeof (CHAR16
), NvConfigStart
, AppendSize
/ sizeof (CHAR16
));
804 // To find next <Label> in DefaultAltCfgResp.
806 *NvConfigValuePtr
= TempChar
;
807 NvConfigPtr
= StrStr (NvConfigPtr
+ 1, L
"&");
810 if (AppendString
!= NULL
) {
812 // Reallocate ConfigAltResp to copy the AppendString.
814 TotalSize
= StrSize (*ConfigAltResp
) + StrSize (AppendString
) + sizeof (CHAR16
);
815 *ConfigAltResp
= (EFI_STRING
) ReallocatePool (
816 StrSize (*ConfigAltResp
),
817 StrSize (*ConfigAltResp
) + StrSize (AppendString
) + sizeof (CHAR16
),
820 if (*ConfigAltResp
== NULL
) {
821 Status
= EFI_OUT_OF_RESOURCES
;
824 StrCatS (*ConfigAltResp
, TotalSize
/ sizeof (CHAR16
), AppendString
);
825 *ConfigAltRespChanged
= TRUE
;
827 Status
= EFI_SUCCESS
;
830 if (AppendString
!= NULL
) {
831 FreePool (AppendString
);
837 Compare the <AltResp> in AltCfgResp and DefaultAltCfgResp, if the <AltResp>
838 in DefaultAltCfgResp but not in AltCfgResp,add it to the AltCfgResp.
840 @param AltCfgResp Pointer to a null-terminated Unicode string in
841 <ConfigAltResp> format.
842 @param DefaultAltCfgResp Pointer to a null-terminated Unicode string in
843 <MultiConfigAltResp> format. The default value
844 string may contain more than one ConfigAltResp
845 string for the different varstore buffer.
846 @param AltConfigHdr Pointer to a Unicode string in <AltConfigHdr> format.
848 @retval EFI_OUT_OF_RESOURCES Insufficient resources to store neccessary
850 @retval EFI_SUCCESS The function finishes successfully.
854 CompareAndMergeDefaultString (
855 IN OUT EFI_STRING
*AltCfgResp
,
856 IN EFI_STRING DefaultAltCfgResp
,
857 IN EFI_STRING AltConfigHdr
861 EFI_STRING AltCfgRespBackup
;
862 EFI_STRING AltConfigHdrPtr
;
863 EFI_STRING AltConfigHdrPtrNext
;
864 EFI_STRING ConfigAltResp
;
865 EFI_STRING StringPtr
;
866 EFI_STRING StringPtrNext
;
868 UINTN ReallocateSize
;
871 BOOLEAN ConfigAltRespChanged
;
873 Status
= EFI_OUT_OF_RESOURCES
;
875 AltConfigHdrPtrNext
= NULL
;
876 StringPtrNext
= NULL
;
877 ConfigAltResp
= NULL
;
878 AltCfgRespBackup
= NULL
;
881 ConfigAltRespChanged
= FALSE
;
884 //To find the <AltResp> with AltConfigHdr in DefaultAltCfgResp, ignore other <AltResp> which follow it.
886 AltConfigHdrPtr
= StrStr (DefaultAltCfgResp
, AltConfigHdr
);
887 ASSERT (AltConfigHdrPtr
!= NULL
);
888 AltConfigHdrPtrNext
= StrStr (AltConfigHdrPtr
+ 1, L
"&GUID");
889 if (AltConfigHdrPtrNext
!= NULL
) {
890 TempChar
= *AltConfigHdrPtrNext
;
891 *AltConfigHdrPtrNext
= L
'\0';
894 // To find the <AltResp> with AltConfigHdr in AltCfgResp, ignore other <AltResp> which follow it.
896 StringPtr
= StrStr (*AltCfgResp
, AltConfigHdr
);
897 StringPtrNext
= StrStr (StringPtr
+ 1, L
"&GUID");
898 if (StringPtrNext
!= NULL
) {
899 TempCharA
= *StringPtrNext
;
900 *StringPtrNext
= L
'\0';
903 // Copy the content of <ConfigAltResp> which contain current AltConfigHdr in AltCfgResp.
905 ConfigAltResp
= AllocateCopyPool (StrSize (*AltCfgResp
), *AltCfgResp
);
906 if (ConfigAltResp
== NULL
) {
910 // To find the <ConfigBody> with AltConfigHdr in DefaultAltCfgResp.
912 BlockPtr
= StrStr (AltConfigHdrPtr
, L
"&OFFSET=");
913 if (BlockPtr
!= NULL
) {
915 // <BlockConfig>::='OFFSET='<Number>'&WIDTH='<Number>'&VALUE='<Number> style.
916 // Call function CompareBlockElementDefault to compare the <BlockConfig> in DefaultAltCfgResp and ConfigAltResp.
917 // The ConfigAltResp which may contain the new <BlockConfig> get from DefaultAltCfgResp.
919 Status
= CompareBlockElementDefault (DefaultAltCfgResp
, &ConfigAltResp
, AltConfigHdr
, &ConfigAltRespChanged
);
920 if (EFI_ERROR(Status
)) {
925 // <NvConfig> ::= <Label>'='<String> | <Label>'='<Number> style.
926 // Call function CompareNameElementDefault to compare the <NvConfig> in DefaultAltCfgResp and ConfigAltResp.
927 // The ConfigAltResp which may contain the new <NvConfig> get from DefaultAltCfgResp.
929 Status
= CompareNameElementDefault (DefaultAltCfgResp
, &ConfigAltResp
, AltConfigHdr
, &ConfigAltRespChanged
);
930 if (EFI_ERROR(Status
)) {
935 // Restore the AltCfgResp.
937 if (StringPtrNext
!= NULL
) {
938 *StringPtrNext
= TempCharA
;
942 // If the ConfigAltResp has no change,no need to update the content in AltCfgResp.
944 if (!ConfigAltRespChanged
) {
945 Status
= EFI_SUCCESS
;
949 // ConfigAltResp has been changed, need to update the content in AltCfgResp.
951 if (StringPtrNext
!= NULL
) {
952 ReallocateSize
= StrSize (ConfigAltResp
) + StrSize (StringPtrNext
) + sizeof (CHAR16
);
954 ReallocateSize
= StrSize (ConfigAltResp
) + sizeof (CHAR16
);
957 AltCfgRespBackup
= (EFI_STRING
) AllocateZeroPool (ReallocateSize
);
958 if (AltCfgRespBackup
== NULL
) {
962 StrCatS (AltCfgRespBackup
, ReallocateSize
/ sizeof (CHAR16
), ConfigAltResp
);
963 if (StringPtrNext
!= NULL
) {
964 StrCatS (AltCfgRespBackup
, ReallocateSize
/ sizeof (CHAR16
), StringPtrNext
);
967 FreePool (*AltCfgResp
);
968 *AltCfgResp
= AltCfgRespBackup
;
970 Status
= EFI_SUCCESS
;
973 if (ConfigAltResp
!= NULL
) {
974 FreePool(ConfigAltResp
);
977 // Restore the DefaultAltCfgResp.
979 if ( AltConfigHdrPtrNext
!= NULL
) {
980 *AltConfigHdrPtrNext
= TempChar
;
981 AltConfigHdrPtrNext
= NULL
;
988 This function merges DefaultAltCfgResp string into AltCfgResp string for
989 the missing AltCfgId in AltCfgResq.
991 @param AltCfgResp Pointer to a null-terminated Unicode string in
992 <ConfigAltResp> format. The default value string
993 will be merged into it.
994 @param DefaultAltCfgResp Pointer to a null-terminated Unicode string in
995 <MultiConfigAltResp> format. The default value
996 string may contain more than one ConfigAltResp
997 string for the different varstore buffer.
999 @retval EFI_SUCCESS The merged string returns.
1000 @retval EFI_INVALID_PARAMETER *AltCfgResp is to NULL.
1004 MergeDefaultString (
1005 IN OUT EFI_STRING
*AltCfgResp
,
1006 IN EFI_STRING DefaultAltCfgResp
1009 EFI_STRING StringPtrDefault
;
1010 EFI_STRING StringPtrEnd
;
1012 EFI_STRING StringPtr
;
1013 EFI_STRING AltConfigHdr
;
1015 UINTN SizeAltCfgResp
;
1019 if (*AltCfgResp
== NULL
) {
1020 return EFI_INVALID_PARAMETER
;
1024 // Get the requestr ConfigHdr
1027 StringPtr
= *AltCfgResp
;
1030 // Find <ConfigHdr> GUID=...&NAME=...&PATH=...
1032 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
1033 return EFI_INVALID_PARAMETER
;
1035 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&NAME=", StrLen (L
"&NAME=")) != 0) {
1038 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&PATH=", StrLen (L
"&PATH=")) != 0) {
1041 if (*StringPtr
== L
'\0') {
1042 return EFI_INVALID_PARAMETER
;
1044 StringPtr
+= StrLen (L
"&PATH=");
1045 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
1048 HeaderLength
= StringPtr
- *AltCfgResp
;
1051 // Construct AltConfigHdr string "&<ConfigHdr>&ALTCFG=XXXX\0"
1052 // |1| StrLen (ConfigHdr) | 8 | 4 | 1 |
1054 MaxLen
= 1 + HeaderLength
+ 8 + 4 + 1;
1055 AltConfigHdr
= AllocateZeroPool (MaxLen
* sizeof (CHAR16
));
1056 if (AltConfigHdr
== NULL
) {
1057 return EFI_OUT_OF_RESOURCES
;
1059 StrCpyS (AltConfigHdr
, MaxLen
, L
"&");
1060 StrnCatS (AltConfigHdr
, MaxLen
, *AltCfgResp
, HeaderLength
);
1061 StrCatS (AltConfigHdr
, MaxLen
, L
"&ALTCFG=");
1062 HeaderLength
= StrLen (AltConfigHdr
);
1064 StringPtrDefault
= StrStr (DefaultAltCfgResp
, AltConfigHdr
);
1065 while (StringPtrDefault
!= NULL
) {
1069 StrnCatS (AltConfigHdr
, MaxLen
, StringPtrDefault
+ HeaderLength
, 4);
1070 StringPtr
= StrStr (*AltCfgResp
, AltConfigHdr
);
1073 // Append the found default value string to the input AltCfgResp
1075 if (StringPtr
== NULL
) {
1076 StringPtrEnd
= StrStr (StringPtrDefault
+ 1, L
"&GUID");
1077 SizeAltCfgResp
= StrSize (*AltCfgResp
);
1078 if (StringPtrEnd
== NULL
) {
1080 // No more default string is found.
1082 TotalSize
= SizeAltCfgResp
+ StrSize (StringPtrDefault
);
1083 *AltCfgResp
= (EFI_STRING
) ReallocatePool (
1086 (VOID
*) (*AltCfgResp
)
1088 if (*AltCfgResp
== NULL
) {
1089 FreePool (AltConfigHdr
);
1090 return EFI_OUT_OF_RESOURCES
;
1092 StrCatS (*AltCfgResp
, TotalSize
/ sizeof (CHAR16
), StringPtrDefault
);
1095 TempChar
= *StringPtrEnd
;
1096 *StringPtrEnd
= L
'\0';
1097 TotalSize
= SizeAltCfgResp
+ StrSize (StringPtrDefault
);
1098 *AltCfgResp
= (EFI_STRING
) ReallocatePool (
1101 (VOID
*) (*AltCfgResp
)
1103 if (*AltCfgResp
== NULL
) {
1104 FreePool (AltConfigHdr
);
1105 return EFI_OUT_OF_RESOURCES
;
1107 StrCatS (*AltCfgResp
, TotalSize
/ sizeof (CHAR16
), StringPtrDefault
);
1108 *StringPtrEnd
= TempChar
;
1112 // The AltCfgResp contains <AltCfgResp>.
1113 // If the <ConfigElement> in <AltCfgResp> in the DefaultAltCfgResp but not in the
1114 // related <AltCfgResp> in AltCfgResp, merge it to AltCfgResp. else no need to merge.
1116 CompareAndMergeDefaultString (AltCfgResp
, DefaultAltCfgResp
, AltConfigHdr
);
1120 // Find next AltCfg String
1122 *(AltConfigHdr
+ HeaderLength
) = L
'\0';
1123 StringPtrDefault
= StrStr (StringPtrDefault
+ 1, AltConfigHdr
);
1126 FreePool (AltConfigHdr
);
1131 This function inserts new DefaultValueData into the BlockData DefaultValue array.
1133 @param BlockData The BlockData is updated to add new default value.
1134 @param DefaultValueData The DefaultValue is added.
1138 InsertDefaultValue (
1139 IN IFR_BLOCK_DATA
*BlockData
,
1140 IN IFR_DEFAULT_DATA
*DefaultValueData
1144 IFR_DEFAULT_DATA
*DefaultValueArray
;
1145 LIST_ENTRY
*DefaultLink
;
1147 DefaultLink
= &BlockData
->DefaultValueEntry
;
1149 for (Link
= DefaultLink
->ForwardLink
; Link
!= DefaultLink
; Link
= Link
->ForwardLink
) {
1150 DefaultValueArray
= BASE_CR (Link
, IFR_DEFAULT_DATA
, Entry
);
1151 if (DefaultValueArray
->DefaultId
== DefaultValueData
->DefaultId
) {
1153 // DEFAULT_VALUE_FROM_OPCODE has high priority, DEFAULT_VALUE_FROM_DEFAULT has low priority.
1155 if (DefaultValueData
->Type
> DefaultValueArray
->Type
) {
1157 // Update the default value array in BlockData.
1159 CopyMem (&DefaultValueArray
->Value
, &DefaultValueData
->Value
, sizeof (EFI_IFR_TYPE_VALUE
));
1160 DefaultValueArray
->Type
= DefaultValueData
->Type
;
1161 DefaultValueArray
->Cleaned
= DefaultValueData
->Cleaned
;
1168 // Insert new default value data in tail.
1170 DefaultValueArray
= AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
1171 ASSERT (DefaultValueArray
!= NULL
);
1172 CopyMem (DefaultValueArray
, DefaultValueData
, sizeof (IFR_DEFAULT_DATA
));
1173 InsertTailList (Link
, &DefaultValueArray
->Entry
);
1177 This function inserts new BlockData into the block link
1179 @param BlockLink The list entry points to block array.
1180 @param BlockData The point to BlockData is added.
1185 IN LIST_ENTRY
*BlockLink
,
1186 IN IFR_BLOCK_DATA
**BlockData
1190 IFR_BLOCK_DATA
*BlockArray
;
1191 IFR_BLOCK_DATA
*BlockSingleData
;
1193 BlockSingleData
= *BlockData
;
1195 if (BlockSingleData
->Name
!= NULL
) {
1196 InsertTailList (BlockLink
, &BlockSingleData
->Entry
);
1201 // Insert block data in its Offset and Width order.
1203 for (Link
= BlockLink
->ForwardLink
; Link
!= BlockLink
; Link
= Link
->ForwardLink
) {
1204 BlockArray
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
1205 if (BlockArray
->Offset
== BlockSingleData
->Offset
) {
1206 if (BlockArray
->Width
> BlockSingleData
->Width
) {
1208 // Insert this block data in the front of block array
1210 InsertTailList (Link
, &BlockSingleData
->Entry
);
1214 if (BlockArray
->Width
== BlockSingleData
->Width
) {
1216 // The same block array has been added.
1218 if (BlockSingleData
!= BlockArray
) {
1219 FreePool (BlockSingleData
);
1220 *BlockData
= BlockArray
;
1224 } else if (BlockArray
->Offset
> BlockSingleData
->Offset
) {
1226 // Insert new block data in the front of block array
1228 InsertTailList (Link
, &BlockSingleData
->Entry
);
1234 // Add new block data into the tail.
1236 InsertTailList (Link
, &BlockSingleData
->Entry
);
1240 Retrieves a pointer to the a Null-terminated ASCII string containing the list
1241 of languages that an HII handle in the HII Database supports. The returned
1242 string is allocated using AllocatePool(). The caller is responsible for freeing
1243 the returned string using FreePool(). The format of the returned string follows
1244 the language format assumed the HII Database.
1246 If HiiHandle is NULL, then ASSERT().
1248 @param[in] HiiHandle A handle that was previously registered in the HII Database.
1250 @retval NULL HiiHandle is not registered in the HII database
1251 @retval NULL There are not enough resources available to retrieve the suported
1253 @retval NULL The list of suported languages could not be retrieved.
1254 @retval Other A pointer to the Null-terminated ASCII string of supported languages.
1258 GetSupportedLanguages (
1259 IN EFI_HII_HANDLE HiiHandle
1264 CHAR8 TempSupportedLanguages
;
1265 CHAR8
*SupportedLanguages
;
1267 ASSERT (HiiHandle
!= NULL
);
1270 // Retrieve the size required for the supported languages buffer.
1273 Status
= mPrivate
.HiiString
.GetLanguages (&mPrivate
.HiiString
, HiiHandle
, &TempSupportedLanguages
, &LanguageSize
);
1276 // If GetLanguages() returns EFI_SUCCESS for a zero size,
1277 // then there are no supported languages registered for HiiHandle. If GetLanguages()
1278 // returns an error other than EFI_BUFFER_TOO_SMALL, then HiiHandle is not present
1279 // in the HII Database
1281 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
1283 // Return NULL if the size can not be retrieved, or if HiiHandle is not in the HII Database
1289 // Allocate the supported languages buffer.
1291 SupportedLanguages
= AllocateZeroPool (LanguageSize
);
1292 if (SupportedLanguages
== NULL
) {
1294 // Return NULL if allocation fails.
1300 // Retrieve the supported languages string
1302 Status
= mPrivate
.HiiString
.GetLanguages (&mPrivate
.HiiString
, HiiHandle
, SupportedLanguages
, &LanguageSize
);
1303 if (EFI_ERROR (Status
)) {
1305 // Free the buffer and return NULL if the supported languages can not be retrieved.
1307 FreePool (SupportedLanguages
);
1312 // Return the Null-terminated ASCII string of supported languages
1314 return SupportedLanguages
;
1318 Retrieves a string from a string package.
1320 If HiiHandle is NULL, then ASSERT().
1321 If StringId is 0, then ASSET.
1323 @param[in] HiiHandle A handle that was previously registered in the HII Database.
1324 @param[in] StringId The identifier of the string to retrieved from the string
1325 package associated with HiiHandle.
1327 @retval NULL The string specified by StringId is not present in the string package.
1328 @retval Other The string was returned.
1333 IN EFI_HII_HANDLE HiiHandle
,
1334 IN EFI_STRING_ID StringId
1341 CHAR8
*SupportedLanguages
;
1342 CHAR8
*PlatformLanguage
;
1343 CHAR8
*BestLanguage
;
1346 ASSERT (HiiHandle
!= NULL
);
1347 ASSERT (StringId
!= 0);
1350 // Initialize all allocated buffers to NULL
1352 SupportedLanguages
= NULL
;
1353 PlatformLanguage
= NULL
;
1354 BestLanguage
= NULL
;
1359 // Get the languages that the package specified by HiiHandle supports
1361 SupportedLanguages
= GetSupportedLanguages (HiiHandle
);
1362 if (SupportedLanguages
== NULL
) {
1367 // Get the current platform language setting
1369 GetEfiGlobalVariable2 (L
"PlatformLang", (VOID
**)&PlatformLanguage
, NULL
);
1372 // Get the best matching language from SupportedLanguages
1374 BestLanguage
= GetBestLanguage (
1376 FALSE
, // RFC 4646 mode
1377 Language
, // Highest priority
1378 PlatformLanguage
!= NULL
? PlatformLanguage
: "", // Next highest priority
1379 SupportedLanguages
, // Lowest priority
1382 if (BestLanguage
== NULL
) {
1387 // Retrieve the size of the string in the string package for the BestLanguage
1390 Status
= mPrivate
.HiiString
.GetString (
1391 &mPrivate
.HiiString
,
1400 // If GetString() returns EFI_SUCCESS for a zero size,
1401 // then there are no supported languages registered for HiiHandle. If GetString()
1402 // returns an error other than EFI_BUFFER_TOO_SMALL, then HiiHandle is not present
1403 // in the HII Database
1405 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
1410 // Allocate a buffer for the return string
1412 String
= AllocateZeroPool (StringSize
);
1413 if (String
== NULL
) {
1418 // Retrieve the string from the string package
1420 Status
= mPrivate
.HiiString
.GetString (
1421 &mPrivate
.HiiString
,
1429 if (EFI_ERROR (Status
)) {
1431 // Free the buffer and return NULL if the supported languages can not be retrieved.
1439 // Free allocated buffers
1441 if (SupportedLanguages
!= NULL
) {
1442 FreePool (SupportedLanguages
);
1444 if (PlatformLanguage
!= NULL
) {
1445 FreePool (PlatformLanguage
);
1447 if (BestLanguage
!= NULL
) {
1448 FreePool (BestLanguage
);
1452 // Return the Null-terminated Unicode string
1458 This function checks VarOffset and VarWidth is in the block range.
1460 @param RequestBlockArray The block array is to be checked.
1461 @param VarOffset Offset of var to the structure
1462 @param VarWidth Width of var.
1463 @param IsNameValueType Whether this varstore is name/value varstore or not.
1464 @param HiiHandle Hii handle for this hii package.
1466 @retval TRUE This Var is in the block range.
1467 @retval FALSE This Var is not in the block range.
1471 IN IFR_BLOCK_DATA
*RequestBlockArray
,
1472 IN UINT16 VarOffset
,
1474 IN BOOLEAN IsNameValueType
,
1475 IN EFI_HII_HANDLE HiiHandle
1479 IFR_BLOCK_DATA
*BlockData
;
1483 // No Request Block array, all vars are got.
1485 if (RequestBlockArray
== NULL
) {
1490 // Check the input var is in the request block range.
1492 for (Link
= RequestBlockArray
->Entry
.ForwardLink
; Link
!= &RequestBlockArray
->Entry
; Link
= Link
->ForwardLink
) {
1493 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
1495 if (IsNameValueType
) {
1496 Name
= InternalGetString (HiiHandle
, VarOffset
);
1497 ASSERT (Name
!= NULL
);
1499 if (StrnCmp (BlockData
->Name
, Name
, StrLen (Name
)) == 0) {
1505 if ((VarOffset
>= BlockData
->Offset
) && ((VarOffset
+ VarWidth
) <= (BlockData
->Offset
+ BlockData
->Width
))) {
1515 Get form package data from data base.
1517 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
1518 @param HiiFormPackage The buffer saves the package data.
1519 @param PackageSize The buffer size of the package data.
1523 GetFormPackageData (
1524 IN HII_DATABASE_RECORD
*DataBaseRecord
,
1525 IN OUT UINT8
**HiiFormPackage
,
1526 OUT UINTN
*PackageSize
1533 if (DataBaseRecord
== NULL
|| HiiFormPackage
== NULL
|| PackageSize
== NULL
) {
1534 return EFI_INVALID_PARAMETER
;
1540 // 0. Get Hii Form Package by HiiHandle
1542 Status
= ExportFormPackages (
1544 DataBaseRecord
->Handle
,
1545 DataBaseRecord
->PackageList
,
1551 if (EFI_ERROR (Status
)) {
1555 (*HiiFormPackage
) = AllocatePool (ResultSize
);
1556 if (*HiiFormPackage
== NULL
) {
1557 Status
= EFI_OUT_OF_RESOURCES
;
1562 // Get HiiFormPackage by HiiHandle
1566 Status
= ExportFormPackages (
1568 DataBaseRecord
->Handle
,
1569 DataBaseRecord
->PackageList
,
1575 if (EFI_ERROR (Status
)) {
1576 FreePool (*HiiFormPackage
);
1579 *PackageSize
= Size
;
1586 This function parses Form Package to get the efi varstore info according to the request ConfigHdr.
1588 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
1589 @param ConfigHdr Request string ConfigHdr. If it is NULL,
1590 the first found varstore will be as ConfigHdr.
1591 @param IsEfiVarstore Whether the request storage type is efi varstore type.
1592 @param EfiVarStore The efi varstore info which will return.
1596 IN HII_DATABASE_RECORD
*DataBaseRecord
,
1597 IN EFI_STRING ConfigHdr
,
1598 OUT BOOLEAN
*IsEfiVarstore
,
1599 OUT EFI_IFR_VARSTORE_EFI
**EfiVarStore
1604 UINTN PackageOffset
;
1605 EFI_IFR_OP_HEADER
*IfrOpHdr
;
1606 CHAR16
*VarStoreName
;
1611 UINT8
*HiiFormPackage
;
1613 EFI_IFR_VARSTORE_EFI
*IfrEfiVarStore
;
1614 EFI_HII_PACKAGE_HEADER
*PackageHeader
;
1616 HiiFormPackage
= NULL
;
1618 Status
= EFI_SUCCESS
;
1622 *IsEfiVarstore
= FALSE
;
1624 Status
= GetFormPackageData(DataBaseRecord
, &HiiFormPackage
, &PackageSize
);
1625 if (EFI_ERROR (Status
)) {
1629 IfrOffset
= sizeof (EFI_HII_PACKAGE_HEADER
);
1630 PackageOffset
= IfrOffset
;
1631 PackageHeader
= (EFI_HII_PACKAGE_HEADER
*) HiiFormPackage
;
1633 while (IfrOffset
< PackageSize
) {
1635 // More than one form packages exist.
1637 if (PackageOffset
>= PackageHeader
->Length
) {
1639 // Process the new form package.
1641 PackageOffset
= sizeof (EFI_HII_PACKAGE_HEADER
);
1642 IfrOffset
+= PackageOffset
;
1643 PackageHeader
= (EFI_HII_PACKAGE_HEADER
*) (HiiFormPackage
+ IfrOffset
);
1646 IfrOpHdr
= (EFI_IFR_OP_HEADER
*) (HiiFormPackage
+ IfrOffset
);
1647 IfrOffset
+= IfrOpHdr
->Length
;
1648 PackageOffset
+= IfrOpHdr
->Length
;
1650 if (IfrOpHdr
->OpCode
== EFI_IFR_VARSTORE_EFI_OP
) {
1651 IfrEfiVarStore
= (EFI_IFR_VARSTORE_EFI
*) IfrOpHdr
;
1653 // If the length is small than the structure, this is from old efi
1654 // varstore definition. Old efi varstore get config directly from
1655 // GetVariable function.
1657 if (IfrOpHdr
->Length
< sizeof (EFI_IFR_VARSTORE_EFI
)) {
1661 VarStoreName
= AllocateZeroPool (AsciiStrSize ((CHAR8
*)IfrEfiVarStore
->Name
) * sizeof (CHAR16
));
1662 if (VarStoreName
== NULL
) {
1663 Status
= EFI_OUT_OF_RESOURCES
;
1666 AsciiStrToUnicodeStr ((CHAR8
*) IfrEfiVarStore
->Name
, VarStoreName
);
1668 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*) &IfrEfiVarStore
->Guid
, 1, &GuidStr
);
1669 GenerateSubStr (L
"NAME=", StrLen (VarStoreName
) * sizeof (CHAR16
), (VOID
*) VarStoreName
, 2, &NameStr
);
1670 LengthString
= StrLen (GuidStr
);
1671 LengthString
= LengthString
+ StrLen (NameStr
) + 1;
1672 TempStr
= AllocateZeroPool (LengthString
* sizeof (CHAR16
));
1673 if (TempStr
== NULL
) {
1676 FreePool (VarStoreName
);
1677 Status
= EFI_OUT_OF_RESOURCES
;
1680 StrCpyS (TempStr
, LengthString
, GuidStr
);
1681 StrCatS (TempStr
, LengthString
, NameStr
);
1682 if (ConfigHdr
== NULL
|| StrnCmp (ConfigHdr
, TempStr
, StrLen (TempStr
)) == 0) {
1683 *EfiVarStore
= (EFI_IFR_VARSTORE_EFI
*) AllocateZeroPool (IfrOpHdr
->Length
);
1684 if (*EfiVarStore
== NULL
) {
1685 FreePool (VarStoreName
);
1689 Status
= EFI_OUT_OF_RESOURCES
;
1692 *IsEfiVarstore
= TRUE
;
1693 CopyMem (*EfiVarStore
, IfrEfiVarStore
, IfrOpHdr
->Length
);
1697 // Free alllocated temp string.
1699 FreePool (VarStoreName
);
1705 // Already found the varstore, break;
1707 if (*IsEfiVarstore
) {
1713 if (HiiFormPackage
!= NULL
) {
1714 FreePool (HiiFormPackage
);
1721 Check whether the ConfigRequest string has the request elements.
1722 For EFI_HII_VARSTORE_BUFFER type, the request has "&OFFSET=****&WIDTH=****..." format.
1723 For EFI_HII_VARSTORE_NAME_VALUE type, the request has "&NAME1**&NAME2..." format.
1725 @param ConfigRequest The input config request string.
1727 @retval TRUE The input include config request elements.
1728 @retval FALSE The input string not includes.
1732 GetElementsFromRequest (
1733 IN EFI_STRING ConfigRequest
1736 EFI_STRING TmpRequest
;
1738 TmpRequest
= StrStr (ConfigRequest
, L
"PATH=");
1739 ASSERT (TmpRequest
!= NULL
);
1741 if ((StrStr (TmpRequest
, L
"&OFFSET=") != NULL
) || (StrStr (TmpRequest
, L
"&") != NULL
)) {
1749 Check whether the this varstore is the request varstore.
1751 @param VarstoreGuid Varstore guid.
1752 @param Name Varstore name.
1753 @param ConfigHdr Current configRequest info.
1755 @retval TRUE This varstore is the requst one.
1756 @retval FALSE This varstore is not the requst one.
1761 IN EFI_GUID
*VarstoreGuid
,
1763 IN CHAR16
*ConfigHdr
1777 // If ConfigHdr has name field and varstore not has name, return FALSE.
1779 if (Name
== NULL
&& ConfigHdr
!= NULL
&& StrStr (ConfigHdr
, L
"NAME=&") == NULL
) {
1783 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*)VarstoreGuid
, 1, &GuidStr
);
1785 GenerateSubStr (L
"NAME=", StrLen (Name
) * sizeof (CHAR16
), (VOID
*) Name
, 2, &NameStr
);
1787 GenerateSubStr (L
"NAME=", 0, NULL
, 2, &NameStr
);
1789 LengthString
= StrLen (GuidStr
);
1790 LengthString
= LengthString
+ StrLen (NameStr
) + 1;
1791 TempStr
= AllocateZeroPool (LengthString
* sizeof (CHAR16
));
1792 if (TempStr
== NULL
) {
1796 StrCpyS (TempStr
, LengthString
, GuidStr
);
1797 StrCatS (TempStr
, LengthString
, NameStr
);
1799 if (ConfigHdr
== NULL
|| StrnCmp (ConfigHdr
, TempStr
, StrLen (TempStr
)) == 0) {
1804 if (GuidStr
!= NULL
) {
1808 if (NameStr
!= NULL
) {
1812 if (TempStr
!= NULL
) {
1820 This function parses Form Package to get the efi varstore info according to the request ConfigHdr.
1822 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
1823 @param ConfigHdr Request string ConfigHdr. If it is NULL,
1824 the first found varstore will be as ConfigHdr.
1825 @retval TRUE This hii package is the reqeust one.
1826 @retval FALSE This hii package is not the reqeust one.
1830 IN HII_DATABASE_RECORD
*DataBaseRecord
,
1831 IN EFI_STRING ConfigHdr
1836 UINTN PackageOffset
;
1837 EFI_IFR_OP_HEADER
*IfrOpHdr
;
1838 CHAR16
*VarStoreName
;
1839 UINT8
*HiiFormPackage
;
1841 EFI_IFR_VARSTORE_EFI
*IfrEfiVarStore
;
1842 EFI_HII_PACKAGE_HEADER
*PackageHeader
;
1843 EFI_IFR_VARSTORE
*IfrVarStore
;
1844 EFI_IFR_VARSTORE_NAME_VALUE
*IfrNameValueVarStore
;
1845 BOOLEAN FindVarstore
;
1847 HiiFormPackage
= NULL
;
1848 VarStoreName
= NULL
;
1849 Status
= EFI_SUCCESS
;
1850 FindVarstore
= FALSE
;
1852 Status
= GetFormPackageData(DataBaseRecord
, &HiiFormPackage
, &PackageSize
);
1853 if (EFI_ERROR (Status
)) {
1857 IfrOffset
= sizeof (EFI_HII_PACKAGE_HEADER
);
1858 PackageOffset
= IfrOffset
;
1859 PackageHeader
= (EFI_HII_PACKAGE_HEADER
*) HiiFormPackage
;
1861 while (IfrOffset
< PackageSize
) {
1863 // More than one form packages exist.
1865 if (PackageOffset
>= PackageHeader
->Length
) {
1867 // Process the new form package.
1869 PackageOffset
= sizeof (EFI_HII_PACKAGE_HEADER
);
1870 IfrOffset
+= PackageOffset
;
1871 PackageHeader
= (EFI_HII_PACKAGE_HEADER
*) (HiiFormPackage
+ IfrOffset
);
1874 IfrOpHdr
= (EFI_IFR_OP_HEADER
*) (HiiFormPackage
+ IfrOffset
);
1875 IfrOffset
+= IfrOpHdr
->Length
;
1876 PackageOffset
+= IfrOpHdr
->Length
;
1878 switch (IfrOpHdr
->OpCode
) {
1880 case EFI_IFR_VARSTORE_OP
:
1881 IfrVarStore
= (EFI_IFR_VARSTORE
*) IfrOpHdr
;
1883 VarStoreName
= AllocateZeroPool (AsciiStrSize ((CHAR8
*)IfrVarStore
->Name
) * sizeof (CHAR16
));
1884 if (VarStoreName
== NULL
) {
1887 AsciiStrToUnicodeStr ((CHAR8
*)IfrVarStore
->Name
, VarStoreName
);
1889 if (IsThisVarstore((VOID
*)&IfrVarStore
->Guid
, VarStoreName
, ConfigHdr
)) {
1890 FindVarstore
= TRUE
;
1893 FreePool (VarStoreName
);
1894 VarStoreName
= NULL
;
1898 case EFI_IFR_VARSTORE_EFI_OP
:
1899 IfrEfiVarStore
= (EFI_IFR_VARSTORE_EFI
*) IfrOpHdr
;
1900 VarStoreName
= AllocateZeroPool (AsciiStrSize ((CHAR8
*)IfrEfiVarStore
->Name
) * sizeof (CHAR16
));
1901 if (VarStoreName
== NULL
) {
1904 AsciiStrToUnicodeStr ((CHAR8
*)IfrEfiVarStore
->Name
, VarStoreName
);
1906 if (IsThisVarstore (&IfrEfiVarStore
->Guid
, VarStoreName
, ConfigHdr
)) {
1907 FindVarstore
= TRUE
;
1910 FreePool (VarStoreName
);
1911 VarStoreName
= NULL
;
1915 case EFI_IFR_VARSTORE_NAME_VALUE_OP
:
1916 IfrNameValueVarStore
= (EFI_IFR_VARSTORE_NAME_VALUE
*) IfrOpHdr
;
1918 if (IsThisVarstore (&IfrNameValueVarStore
->Guid
, NULL
, ConfigHdr
)) {
1919 FindVarstore
= TRUE
;
1924 case EFI_IFR_FORM_OP
:
1925 case EFI_IFR_FORM_MAP_OP
:
1927 // No matched varstore is found and directly return.
1936 if (HiiFormPackage
!= NULL
) {
1937 FreePool (HiiFormPackage
);
1940 if (VarStoreName
!= NULL
) {
1941 FreePool (VarStoreName
);
1944 return FindVarstore
;
1948 Check whether the this op code is required.
1950 @param RequestBlockArray The array includes all the request info or NULL.
1951 @param HiiHandle The hii handle for this form package.
1952 @param VarStorageData The varstore data strucure.
1953 @param IfrOpHdr Ifr opcode header for this opcode.
1954 @param VarWidth The buffer width for this opcode.
1955 @param ReturnData The data block added for this opcode.
1957 @retval EFI_SUCCESS This opcode is required.
1958 @retval EFI_NOT_FOUND This opcode is not required.
1959 @retval Others Contain some error.
1963 IsThisOpcodeRequired (
1964 IN IFR_BLOCK_DATA
*RequestBlockArray
,
1965 IN EFI_HII_HANDLE HiiHandle
,
1966 IN OUT IFR_VARSTORAGE_DATA
*VarStorageData
,
1967 IN EFI_IFR_OP_HEADER
*IfrOpHdr
,
1969 OUT IFR_BLOCK_DATA
**ReturnData
1972 IFR_BLOCK_DATA
*BlockData
;
1974 EFI_STRING_ID NameId
;
1975 EFI_IFR_QUESTION_HEADER
*IfrQuestionHdr
;
1979 IfrQuestionHdr
= (EFI_IFR_QUESTION_HEADER
*)((CHAR8
*) IfrOpHdr
+ sizeof (EFI_IFR_OP_HEADER
));
1981 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
1982 NameId
= IfrQuestionHdr
->VarStoreInfo
.VarName
;
1985 // Check whether this question is in requested block array.
1987 if (!BlockArrayCheck (RequestBlockArray
, NameId
, 0, TRUE
, HiiHandle
)) {
1989 // This question is not in the requested string. Skip it.
1991 return EFI_NOT_FOUND
;
1994 VarOffset
= IfrQuestionHdr
->VarStoreInfo
.VarOffset
;
1997 // Check whether this question is in requested block array.
1999 if (!BlockArrayCheck (RequestBlockArray
, VarOffset
, VarWidth
, FALSE
, HiiHandle
)) {
2001 // This question is not in the requested string. Skip it.
2003 return EFI_NOT_FOUND
;
2007 // Check this var question is in the var storage
2009 if (((VarOffset
+ VarWidth
) > VarStorageData
->Size
)) {
2010 return EFI_INVALID_PARAMETER
;
2014 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
2015 if (BlockData
== NULL
) {
2016 return EFI_OUT_OF_RESOURCES
;
2019 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2020 BlockData
->Name
= InternalGetString(HiiHandle
, NameId
);
2022 BlockData
->Offset
= VarOffset
;
2025 BlockData
->Width
= VarWidth
;
2026 BlockData
->QuestionId
= IfrQuestionHdr
->QuestionId
;
2027 BlockData
->OpCode
= IfrOpHdr
->OpCode
;
2028 BlockData
->Scope
= IfrOpHdr
->Scope
;
2029 InitializeListHead (&BlockData
->DefaultValueEntry
);
2031 // Add Block Data into VarStorageData BlockEntry
2033 InsertBlockData (&VarStorageData
->BlockEntry
, &BlockData
);
2034 *ReturnData
= BlockData
;
2040 This function parses Form Package to get the block array and the default
2041 value array according to the request ConfigHdr.
2043 @param HiiHandle Hii Handle for this hii package.
2044 @param Package Pointer to the form package data.
2045 @param PackageLength Length of the pacakge.
2046 @param ConfigHdr Request string ConfigHdr. If it is NULL,
2047 the first found varstore will be as ConfigHdr.
2048 @param RequestBlockArray The block array is retrieved from the request string.
2049 @param VarStorageData VarStorage structure contains the got block and default value.
2050 @param DefaultIdArray Point to the got default id and default name array.
2052 @retval EFI_SUCCESS The block array and the default value array are got.
2053 @retval EFI_INVALID_PARAMETER The varstore defintion in the differnt form pacakges
2055 @retval EFI_OUT_OF_RESOURCES No enough memory.
2060 IN EFI_HII_HANDLE HiiHandle
,
2062 IN UINT32 PackageLength
,
2063 IN EFI_STRING ConfigHdr
,
2064 IN IFR_BLOCK_DATA
*RequestBlockArray
,
2065 IN OUT IFR_VARSTORAGE_DATA
*VarStorageData
,
2066 OUT IFR_DEFAULT_DATA
*DefaultIdArray
2071 UINTN PackageOffset
;
2072 EFI_IFR_VARSTORE
*IfrVarStore
;
2073 EFI_IFR_VARSTORE_EFI
*IfrEfiVarStore
;
2074 EFI_IFR_OP_HEADER
*IfrOpHdr
;
2075 EFI_IFR_ONE_OF
*IfrOneOf
;
2076 EFI_IFR_REF4
*IfrRef
;
2077 EFI_IFR_ONE_OF_OPTION
*IfrOneOfOption
;
2078 EFI_IFR_DEFAULT
*IfrDefault
;
2079 EFI_IFR_ORDERED_LIST
*IfrOrderedList
;
2080 EFI_IFR_CHECKBOX
*IfrCheckBox
;
2081 EFI_IFR_PASSWORD
*IfrPassword
;
2082 EFI_IFR_STRING
*IfrString
;
2083 EFI_IFR_DATE
*IfrDate
;
2084 EFI_IFR_TIME
*IfrTime
;
2085 IFR_DEFAULT_DATA DefaultData
;
2086 IFR_DEFAULT_DATA
*DefaultDataPtr
;
2087 IFR_BLOCK_DATA
*BlockData
;
2088 CHAR16
*VarStoreName
;
2090 UINT16 VarDefaultId
;
2091 BOOLEAN FirstOneOfOption
;
2092 BOOLEAN FirstOrderedList
;
2093 LIST_ENTRY
*LinkData
;
2094 LIST_ENTRY
*LinkDefault
;
2095 EFI_IFR_VARSTORE_NAME_VALUE
*IfrNameValueVarStore
;
2096 EFI_HII_PACKAGE_HEADER
*PackageHeader
;
2097 EFI_VARSTORE_ID VarStoreId
;
2099 Status
= EFI_SUCCESS
;
2101 DefaultDataPtr
= NULL
;
2102 FirstOneOfOption
= FALSE
;
2104 FirstOrderedList
= FALSE
;
2105 VarStoreName
= NULL
;
2106 ZeroMem (&DefaultData
, sizeof (IFR_DEFAULT_DATA
));
2109 // Go through the form package to parse OpCode one by one.
2111 PackageOffset
= sizeof (EFI_HII_PACKAGE_HEADER
);
2112 PackageHeader
= (EFI_HII_PACKAGE_HEADER
*) Package
;
2113 IfrOffset
= PackageOffset
;
2114 while (IfrOffset
< PackageLength
) {
2117 // More than one form package found.
2119 if (PackageOffset
>= PackageHeader
->Length
) {
2121 // Already found varstore for this request, break;
2123 if (VarStoreId
!= 0) {
2128 // Get next package header info.
2130 IfrOffset
+= sizeof (EFI_HII_PACKAGE_HEADER
);
2131 PackageOffset
= sizeof (EFI_HII_PACKAGE_HEADER
);
2132 PackageHeader
= (EFI_HII_PACKAGE_HEADER
*) (Package
+ IfrOffset
);
2135 IfrOpHdr
= (EFI_IFR_OP_HEADER
*) (Package
+ IfrOffset
);
2136 switch (IfrOpHdr
->OpCode
) {
2137 case EFI_IFR_VARSTORE_OP
:
2139 // VarStore is found. Don't need to search any more.
2141 if (VarStoreId
!= 0) {
2145 IfrVarStore
= (EFI_IFR_VARSTORE
*) IfrOpHdr
;
2147 VarStoreName
= AllocateZeroPool (AsciiStrSize ((CHAR8
*)IfrVarStore
->Name
) * sizeof (CHAR16
));
2148 if (VarStoreName
== NULL
) {
2149 Status
= EFI_OUT_OF_RESOURCES
;
2152 AsciiStrToUnicodeStr ((CHAR8
*)IfrVarStore
->Name
, VarStoreName
);
2154 if (IsThisVarstore((VOID
*)&IfrVarStore
->Guid
, VarStoreName
, ConfigHdr
)) {
2156 // Find the matched VarStore
2158 CopyGuid (&VarStorageData
->Guid
, (EFI_GUID
*) (VOID
*) &IfrVarStore
->Guid
);
2159 VarStorageData
->Size
= IfrVarStore
->Size
;
2160 VarStorageData
->Name
= VarStoreName
;
2161 VarStorageData
->Type
= EFI_HII_VARSTORE_BUFFER
;
2162 VarStoreId
= IfrVarStore
->VarStoreId
;
2164 FreePool (VarStoreName
);
2165 VarStoreName
= NULL
;
2169 case EFI_IFR_VARSTORE_EFI_OP
:
2171 // VarStore is found. Don't need to search any more.
2173 if (VarStoreId
!= 0) {
2177 IfrEfiVarStore
= (EFI_IFR_VARSTORE_EFI
*) IfrOpHdr
;
2180 // If the length is small than the structure, this is from old efi
2181 // varstore definition. Old efi varstore get config directly from
2182 // GetVariable function.
2184 if (IfrOpHdr
->Length
< sizeof (EFI_IFR_VARSTORE_EFI
)) {
2188 VarStoreName
= AllocateZeroPool (AsciiStrSize ((CHAR8
*)IfrEfiVarStore
->Name
) * sizeof (CHAR16
));
2189 if (VarStoreName
== NULL
) {
2190 Status
= EFI_OUT_OF_RESOURCES
;
2193 AsciiStrToUnicodeStr ((CHAR8
*)IfrEfiVarStore
->Name
, VarStoreName
);
2195 if (IsThisVarstore (&IfrEfiVarStore
->Guid
, VarStoreName
, ConfigHdr
)) {
2197 // Find the matched VarStore
2199 CopyGuid (&VarStorageData
->Guid
, (EFI_GUID
*) (VOID
*) &IfrEfiVarStore
->Guid
);
2200 VarStorageData
->Size
= IfrEfiVarStore
->Size
;
2201 VarStorageData
->Name
= VarStoreName
;
2202 VarStorageData
->Type
= EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
;
2203 VarStoreId
= IfrEfiVarStore
->VarStoreId
;
2205 FreePool (VarStoreName
);
2206 VarStoreName
= NULL
;
2210 case EFI_IFR_VARSTORE_NAME_VALUE_OP
:
2212 // VarStore is found. Don't need to search any more.
2214 if (VarStoreId
!= 0) {
2218 IfrNameValueVarStore
= (EFI_IFR_VARSTORE_NAME_VALUE
*) IfrOpHdr
;
2220 if (IsThisVarstore (&IfrNameValueVarStore
->Guid
, NULL
, ConfigHdr
)) {
2222 // Find the matched VarStore
2224 CopyGuid (&VarStorageData
->Guid
, (EFI_GUID
*) (VOID
*) &IfrNameValueVarStore
->Guid
);
2225 VarStorageData
->Type
= EFI_HII_VARSTORE_NAME_VALUE
;
2226 VarStoreId
= IfrNameValueVarStore
->VarStoreId
;
2230 case EFI_IFR_DEFAULTSTORE_OP
:
2232 // Add new the map between default id and default name.
2234 DefaultDataPtr
= (IFR_DEFAULT_DATA
*) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
2235 if (DefaultDataPtr
== NULL
) {
2236 Status
= EFI_OUT_OF_RESOURCES
;
2239 DefaultDataPtr
->DefaultId
= ((EFI_IFR_DEFAULTSTORE
*) IfrOpHdr
)->DefaultId
;
2240 InsertTailList (&DefaultIdArray
->Entry
, &DefaultDataPtr
->Entry
);
2241 DefaultDataPtr
= NULL
;
2244 case EFI_IFR_FORM_OP
:
2245 case EFI_IFR_FORM_MAP_OP
:
2247 // No matched varstore is found and directly return.
2249 if ( VarStoreId
== 0) {
2250 Status
= EFI_SUCCESS
;
2255 case EFI_IFR_REF_OP
:
2257 // Ref question is not in IFR Form. This IFR form is not valid.
2259 if ( VarStoreId
== 0) {
2260 Status
= EFI_INVALID_PARAMETER
;
2264 // Check whether this question is for the requested varstore.
2266 IfrRef
= (EFI_IFR_REF4
*) IfrOpHdr
;
2267 if (IfrRef
->Question
.VarStoreId
!= VarStoreId
) {
2270 VarWidth
= (UINT16
) (sizeof (EFI_HII_REF
));
2273 // The BlockData may allocate by other opcode,need to clean.
2275 if (BlockData
!= NULL
){
2279 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
2280 if (EFI_ERROR (Status
)) {
2281 if (Status
== EFI_NOT_FOUND
){
2283 //The opcode is not required,exit and parse other opcode.
2291 case EFI_IFR_ONE_OF_OP
:
2292 case EFI_IFR_NUMERIC_OP
:
2294 // Numeric and OneOf has the same opcode structure.
2298 // Numeric and OneOf question is not in IFR Form. This IFR form is not valid.
2300 if (VarStoreId
== 0) {
2301 Status
= EFI_INVALID_PARAMETER
;
2305 // Check whether this question is for the requested varstore.
2307 IfrOneOf
= (EFI_IFR_ONE_OF
*) IfrOpHdr
;
2308 if (IfrOneOf
->Question
.VarStoreId
!= VarStoreId
) {
2311 VarWidth
= (UINT16
) (1 << (IfrOneOf
->Flags
& EFI_IFR_NUMERIC_SIZE
));
2314 // The BlockData may allocate by other opcode,need to clean.
2316 if (BlockData
!= NULL
){
2320 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
2321 if (EFI_ERROR (Status
)) {
2322 if (Status
== EFI_NOT_FOUND
){
2324 //The opcode is not required,exit and parse other opcode.
2332 //when go to there,BlockData can't be NULLL.
2334 ASSERT (BlockData
!= NULL
);
2336 if (IfrOpHdr
->OpCode
== EFI_IFR_ONE_OF_OP
) {
2338 // Set this flag to TRUE for the first oneof option.
2340 FirstOneOfOption
= TRUE
;
2341 } else if (IfrOpHdr
->OpCode
== EFI_IFR_NUMERIC_OP
) {
2343 // Numeric minimum value will be used as default value when no default is specified.
2345 DefaultData
.Type
= DefaultValueFromDefault
;
2346 switch (IfrOneOf
->Flags
& EFI_IFR_NUMERIC_SIZE
) {
2347 case EFI_IFR_NUMERIC_SIZE_1
:
2348 DefaultData
.Value
.u8
= IfrOneOf
->data
.u8
.MinValue
;
2351 case EFI_IFR_NUMERIC_SIZE_2
:
2352 CopyMem (&DefaultData
.Value
.u16
, &IfrOneOf
->data
.u16
.MinValue
, sizeof (UINT16
));
2355 case EFI_IFR_NUMERIC_SIZE_4
:
2356 CopyMem (&DefaultData
.Value
.u32
, &IfrOneOf
->data
.u32
.MinValue
, sizeof (UINT32
));
2359 case EFI_IFR_NUMERIC_SIZE_8
:
2360 CopyMem (&DefaultData
.Value
.u64
, &IfrOneOf
->data
.u64
.MinValue
, sizeof (UINT64
));
2364 Status
= EFI_INVALID_PARAMETER
;
2368 // Set default value base on the DefaultId list get from IFR data.
2370 for (LinkData
= DefaultIdArray
->Entry
.ForwardLink
; LinkData
!= &DefaultIdArray
->Entry
; LinkData
= LinkData
->ForwardLink
) {
2371 DefaultDataPtr
= BASE_CR (LinkData
, IFR_DEFAULT_DATA
, Entry
);
2372 DefaultData
.DefaultId
= DefaultDataPtr
->DefaultId
;
2373 InsertDefaultValue (BlockData
, &DefaultData
);
2378 case EFI_IFR_ORDERED_LIST_OP
:
2380 // offset by question header
2381 // width by EFI_IFR_ORDERED_LIST MaxContainers * OneofOption Type
2384 FirstOrderedList
= TRUE
;
2386 // OrderedList question is not in IFR Form. This IFR form is not valid.
2388 if (VarStoreId
== 0) {
2389 Status
= EFI_INVALID_PARAMETER
;
2393 // Check whether this question is for the requested varstore.
2395 IfrOrderedList
= (EFI_IFR_ORDERED_LIST
*) IfrOpHdr
;
2396 if (IfrOrderedList
->Question
.VarStoreId
!= VarStoreId
) {
2400 VarWidth
= IfrOrderedList
->MaxContainers
;
2403 // The BlockData may allocate by other opcode,need to clean.
2405 if (BlockData
!= NULL
){
2409 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
2410 if (EFI_ERROR (Status
)) {
2411 if (Status
== EFI_NOT_FOUND
){
2413 //The opcode is not required,exit and parse other opcode.
2421 case EFI_IFR_CHECKBOX_OP
:
2423 // EFI_IFR_DEFAULT_OP
2424 // offset by question header
2425 // width is 1 sizeof (BOOLEAN)
2426 // default id by CheckBox Flags if CheckBox flags (Default or Mau) is set, the default value is 1 to be set.
2427 // value by DefaultOption
2428 // default id by DeaultOption DefaultId can override CheckBox Flags and Default value.
2432 // CheckBox question is not in IFR Form. This IFR form is not valid.
2434 if (VarStoreId
== 0) {
2435 Status
= EFI_INVALID_PARAMETER
;
2439 // Check whether this question is for the requested varstore.
2441 IfrCheckBox
= (EFI_IFR_CHECKBOX
*) IfrOpHdr
;
2442 if (IfrCheckBox
->Question
.VarStoreId
!= VarStoreId
) {
2445 VarWidth
= (UINT16
) sizeof (BOOLEAN
);
2448 // The BlockData may allocate by other opcode,need to clean.
2450 if (BlockData
!= NULL
){
2454 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
2455 if (EFI_ERROR (Status
)) {
2456 if (Status
== EFI_NOT_FOUND
){
2458 //The opcode is not required,exit and parse other opcode.
2466 //when go to there,BlockData can't be NULLL.
2468 ASSERT (BlockData
!= NULL
);
2471 // Add default value for standard ID by CheckBox Flag
2473 VarDefaultId
= EFI_HII_DEFAULT_CLASS_STANDARD
;
2475 // Prepare new DefaultValue
2477 DefaultData
.DefaultId
= VarDefaultId
;
2478 if ((IfrCheckBox
->Flags
& EFI_IFR_CHECKBOX_DEFAULT
) == EFI_IFR_CHECKBOX_DEFAULT
) {
2480 // When flag is set, defautl value is TRUE.
2482 DefaultData
.Type
= DefaultValueFromFlag
;
2483 DefaultData
.Value
.b
= TRUE
;
2486 // When flag is not set, defautl value is FASLE.
2488 DefaultData
.Type
= DefaultValueFromDefault
;
2489 DefaultData
.Value
.b
= FALSE
;
2492 // Add DefaultValue into current BlockData
2494 InsertDefaultValue (BlockData
, &DefaultData
);
2497 // Add default value for Manufacture ID by CheckBox Flag
2499 VarDefaultId
= EFI_HII_DEFAULT_CLASS_MANUFACTURING
;
2501 // Prepare new DefaultValue
2503 DefaultData
.DefaultId
= VarDefaultId
;
2504 if ((IfrCheckBox
->Flags
& EFI_IFR_CHECKBOX_DEFAULT_MFG
) == EFI_IFR_CHECKBOX_DEFAULT_MFG
) {
2506 // When flag is set, defautl value is TRUE.
2508 DefaultData
.Type
= DefaultValueFromFlag
;
2509 DefaultData
.Value
.b
= TRUE
;
2512 // When flag is not set, defautl value is FASLE.
2514 DefaultData
.Type
= DefaultValueFromDefault
;
2515 DefaultData
.Value
.b
= FALSE
;
2518 // Add DefaultValue into current BlockData
2520 InsertDefaultValue (BlockData
, &DefaultData
);
2523 case EFI_IFR_DATE_OP
:
2525 // offset by question header
2526 // width MaxSize * sizeof (CHAR16)
2527 // no default value, only block array
2531 // Date question is not in IFR Form. This IFR form is not valid.
2533 if (VarStoreId
== 0) {
2534 Status
= EFI_INVALID_PARAMETER
;
2538 // Check whether this question is for the requested varstore.
2540 IfrDate
= (EFI_IFR_DATE
*) IfrOpHdr
;
2541 if (IfrDate
->Question
.VarStoreId
!= VarStoreId
) {
2546 // The BlockData may allocate by other opcode,need to clean.
2548 if (BlockData
!= NULL
){
2552 VarWidth
= (UINT16
) sizeof (EFI_HII_DATE
);
2553 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
2554 if (EFI_ERROR (Status
)) {
2555 if (Status
== EFI_NOT_FOUND
){
2557 //The opcode is not required,exit and parse other opcode.
2565 case EFI_IFR_TIME_OP
:
2567 // offset by question header
2568 // width MaxSize * sizeof (CHAR16)
2569 // no default value, only block array
2573 // Time question is not in IFR Form. This IFR form is not valid.
2575 if (VarStoreId
== 0) {
2576 Status
= EFI_INVALID_PARAMETER
;
2580 // Check whether this question is for the requested varstore.
2582 IfrTime
= (EFI_IFR_TIME
*) IfrOpHdr
;
2583 if (IfrTime
->Question
.VarStoreId
!= VarStoreId
) {
2588 // The BlockData may allocate by other opcode,need to clean.
2590 if (BlockData
!= NULL
){
2594 VarWidth
= (UINT16
) sizeof (EFI_HII_TIME
);
2595 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
2596 if (EFI_ERROR (Status
)) {
2597 if (Status
== EFI_NOT_FOUND
){
2599 //The opcode is not required,exit and parse other opcode.
2607 case EFI_IFR_STRING_OP
:
2609 // offset by question header
2610 // width MaxSize * sizeof (CHAR16)
2611 // no default value, only block array
2615 // String question is not in IFR Form. This IFR form is not valid.
2617 if (VarStoreId
== 0) {
2618 Status
= EFI_INVALID_PARAMETER
;
2622 // Check whether this question is for the requested varstore.
2624 IfrString
= (EFI_IFR_STRING
*) IfrOpHdr
;
2625 if (IfrString
->Question
.VarStoreId
!= VarStoreId
) {
2630 // The BlockData may allocate by other opcode,need to clean.
2632 if (BlockData
!= NULL
){
2636 VarWidth
= (UINT16
) (IfrString
->MaxSize
* sizeof (UINT16
));
2637 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
2638 if (EFI_ERROR (Status
)) {
2639 if (Status
== EFI_NOT_FOUND
){
2641 //The opcode is not required,exit and parse other opcode.
2649 case EFI_IFR_PASSWORD_OP
:
2651 // offset by question header
2652 // width MaxSize * sizeof (CHAR16)
2653 // no default value, only block array
2657 // Password question is not in IFR Form. This IFR form is not valid.
2659 if (VarStoreId
== 0) {
2660 Status
= EFI_INVALID_PARAMETER
;
2664 // Check whether this question is for the requested varstore.
2666 IfrPassword
= (EFI_IFR_PASSWORD
*) IfrOpHdr
;
2667 if (IfrPassword
->Question
.VarStoreId
!= VarStoreId
) {
2672 // The BlockData may allocate by other opcode,need to clean.
2674 if (BlockData
!= NULL
){
2678 VarWidth
= (UINT16
) (IfrPassword
->MaxSize
* sizeof (UINT16
));
2679 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
2680 if (EFI_ERROR (Status
)) {
2681 if (Status
== EFI_NOT_FOUND
){
2683 //The opcode is not required,exit and parse other opcode.
2691 // No default value for string.
2696 case EFI_IFR_ONE_OF_OPTION_OP
:
2698 // No matched block data is ignored.
2700 if (BlockData
== NULL
|| BlockData
->Scope
== 0) {
2704 IfrOneOfOption
= (EFI_IFR_ONE_OF_OPTION
*) IfrOpHdr
;
2705 if (BlockData
->OpCode
== EFI_IFR_ORDERED_LIST_OP
) {
2707 if (!FirstOrderedList
){
2711 // Get ordered list option data type.
2713 if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_8
|| IfrOneOfOption
->Type
== EFI_IFR_TYPE_BOOLEAN
) {
2715 } else if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_16
) {
2717 } else if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_32
) {
2719 } else if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_64
) {
2723 // Invalid ordered list option data type.
2725 Status
= EFI_INVALID_PARAMETER
;
2726 if (BlockData
->Name
!= NULL
) {
2727 FreePool (BlockData
->Name
);
2729 FreePool (BlockData
);
2734 // Calculate Ordered list QuestionId width.
2736 BlockData
->Width
= (UINT16
) (BlockData
->Width
* VarWidth
);
2738 // Check whether this question is in requested block array.
2740 if (!BlockArrayCheck (RequestBlockArray
, BlockData
->Offset
, BlockData
->Width
, (BOOLEAN
)(BlockData
->Name
!= NULL
), HiiHandle
)) {
2742 // This question is not in the requested string. Skip it.
2744 if (BlockData
->Name
!= NULL
) {
2745 FreePool (BlockData
->Name
);
2747 FreePool (BlockData
);
2752 // Check this var question is in the var storage
2754 if ((BlockData
->Name
== NULL
) && ((BlockData
->Offset
+ BlockData
->Width
) > VarStorageData
->Size
)) {
2755 Status
= EFI_INVALID_PARAMETER
;
2756 if (BlockData
->Name
!= NULL
) {
2757 FreePool (BlockData
->Name
);
2759 FreePool (BlockData
);
2763 // Add Block Data into VarStorageData BlockEntry
2765 InsertBlockData (&VarStorageData
->BlockEntry
, &BlockData
);
2767 FirstOrderedList
= FALSE
;
2773 // 1. Set default value for OneOf option when flag field has default attribute.
2775 if (((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT
) == EFI_IFR_OPTION_DEFAULT
) ||
2776 ((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT_MFG
) == EFI_IFR_OPTION_DEFAULT_MFG
)) {
2778 // This flag is used to specify whether this option is the first. Set it to FALSE for the following options.
2779 // The first oneof option value will be used as default value when no default value is specified.
2781 FirstOneOfOption
= FALSE
;
2783 // Prepare new DefaultValue
2785 DefaultData
.Type
= DefaultValueFromFlag
;
2786 CopyMem (&DefaultData
.Value
, &IfrOneOfOption
->Value
, IfrOneOfOption
->Header
.Length
- OFFSET_OF (EFI_IFR_ONE_OF_OPTION
, Value
));
2787 if ((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT
) == EFI_IFR_OPTION_DEFAULT
) {
2788 DefaultData
.DefaultId
= EFI_HII_DEFAULT_CLASS_STANDARD
;
2789 InsertDefaultValue (BlockData
, &DefaultData
);
2791 if ((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT_MFG
) == EFI_IFR_OPTION_DEFAULT_MFG
) {
2792 DefaultData
.DefaultId
= EFI_HII_DEFAULT_CLASS_MANUFACTURING
;
2793 InsertDefaultValue (BlockData
, &DefaultData
);
2798 // 2. Set as the default value when this is the first option.
2799 // The first oneof option value will be used as default value when no default value is specified.
2801 if (FirstOneOfOption
) {
2802 // This flag is used to specify whether this option is the first. Set it to FALSE for the following options.
2803 FirstOneOfOption
= FALSE
;
2806 // Prepare new DefaultValue
2808 DefaultData
.Type
= DefaultValueFromDefault
;
2809 CopyMem (&DefaultData
.Value
, &IfrOneOfOption
->Value
, IfrOneOfOption
->Header
.Length
- OFFSET_OF (EFI_IFR_ONE_OF_OPTION
, Value
));
2810 for (LinkData
= DefaultIdArray
->Entry
.ForwardLink
; LinkData
!= &DefaultIdArray
->Entry
; LinkData
= LinkData
->ForwardLink
) {
2811 DefaultDataPtr
= BASE_CR (LinkData
, IFR_DEFAULT_DATA
, Entry
);
2812 DefaultData
.DefaultId
= DefaultDataPtr
->DefaultId
;
2813 InsertDefaultValue (BlockData
, &DefaultData
);
2818 case EFI_IFR_DEFAULT_OP
:
2820 // Update Current BlockData to the default value.
2822 if (BlockData
== NULL
|| BlockData
->Scope
== 0) {
2824 // No matched block data is ignored.
2830 // Get the DefaultId
2832 IfrDefault
= (EFI_IFR_DEFAULT
*) IfrOpHdr
;
2833 VarDefaultId
= IfrDefault
->DefaultId
;
2835 // Prepare new DefaultValue
2837 DefaultData
.Type
= DefaultValueFromOpcode
;
2838 DefaultData
.DefaultId
= VarDefaultId
;
2839 CopyMem (&DefaultData
.Value
, &IfrDefault
->Value
, IfrDefault
->Header
.Length
- OFFSET_OF (EFI_IFR_DEFAULT
, Value
));
2841 // If the value field is expression, set the cleaned flag.
2842 if (IfrDefault
->Type
== EFI_IFR_TYPE_OTHER
) {
2843 DefaultData
.Cleaned
= TRUE
;
2846 // Add DefaultValue into current BlockData
2848 InsertDefaultValue (BlockData
, &DefaultData
);
2851 // After insert the default value, reset the cleaned value for next
2852 // time used. If not set here, need to set the value before everytime
2855 DefaultData
.Cleaned
= FALSE
;
2858 case EFI_IFR_END_OP
:
2860 // End Opcode is for Var question.
2862 if (BlockData
!= NULL
) {
2863 if (BlockData
->Scope
> 0) {
2866 if (BlockData
->Scope
== 0) {
2874 if (BlockData
!= NULL
) {
2875 if (BlockData
->Scope
> 0) {
2876 BlockData
->Scope
= (UINT8
) (BlockData
->Scope
+ IfrOpHdr
->Scope
);
2879 if (BlockData
->Scope
== 0) {
2886 IfrOffset
+= IfrOpHdr
->Length
;
2887 PackageOffset
+= IfrOpHdr
->Length
;
2891 //if Status == EFI_NOT_FOUND, just means the opcode is not required,not contain any error,
2892 //so set the Status to EFI_SUCCESS.
2894 if (Status
== EFI_NOT_FOUND
){
2895 Status
= EFI_SUCCESS
;
2899 for (LinkData
= VarStorageData
->BlockEntry
.ForwardLink
; LinkData
!= &VarStorageData
->BlockEntry
; LinkData
= LinkData
->ForwardLink
) {
2900 BlockData
= BASE_CR (LinkData
, IFR_BLOCK_DATA
, Entry
);
2901 for (LinkDefault
= BlockData
->DefaultValueEntry
.ForwardLink
; LinkDefault
!= &BlockData
->DefaultValueEntry
; ) {
2902 DefaultDataPtr
= BASE_CR (LinkDefault
, IFR_DEFAULT_DATA
, Entry
);
2903 LinkDefault
= LinkDefault
->ForwardLink
;
2904 if (DefaultDataPtr
->Cleaned
== TRUE
) {
2905 RemoveEntryList (&DefaultDataPtr
->Entry
);
2906 FreePool (DefaultDataPtr
);
2915 parse the configrequest string, get the elements.
2917 @param ConfigRequest The input configrequest string.
2918 @param Progress Return the progress data.
2920 @retval Block data pointer.
2924 IN EFI_STRING ConfigRequest
,
2925 OUT EFI_STRING
*Progress
2928 EFI_STRING StringPtr
;
2929 IFR_BLOCK_DATA
*BlockData
;
2930 IFR_BLOCK_DATA
*RequestBlockArray
;
2936 IFR_BLOCK_DATA
*NextBlockData
;
2942 // Init RequestBlockArray
2944 RequestBlockArray
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
2945 if (RequestBlockArray
== NULL
) {
2948 InitializeListHead (&RequestBlockArray
->Entry
);
2951 // Get the request Block array from the request string
2956 // Parse each <RequestElement> if exists
2957 // Only <BlockName> format is supported by this help function.
2958 // <BlockName> ::= &'OFFSET='<Number>&'WIDTH='<Number>
2960 StringPtr
= ConfigRequest
;
2961 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) == 0) {
2963 // Skip the OFFSET string
2965 *Progress
= StringPtr
;
2966 StringPtr
+= StrLen (L
"&OFFSET=");
2970 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
2971 if (EFI_ERROR (Status
)) {
2978 (((Length
+ 1) / 2) < sizeof (UINT16
)) ? ((Length
+ 1) / 2) : sizeof (UINT16
)
2980 FreePool (TmpBuffer
);
2982 StringPtr
+= Length
;
2983 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
2986 StringPtr
+= StrLen (L
"&WIDTH=");
2991 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
2992 if (EFI_ERROR (Status
)) {
2999 (((Length
+ 1) / 2) < sizeof (UINT16
)) ? ((Length
+ 1) / 2) : sizeof (UINT16
)
3001 FreePool (TmpBuffer
);
3003 StringPtr
+= Length
;
3004 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
3011 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
3012 if (BlockData
== NULL
) {
3015 BlockData
->Offset
= Offset
;
3016 BlockData
->Width
= Width
;
3017 InsertBlockData (&RequestBlockArray
->Entry
, &BlockData
);
3020 // Skip &VALUE string if &VALUE does exists.
3022 if (StrnCmp (StringPtr
, L
"&VALUE=", StrLen (L
"&VALUE=")) == 0) {
3023 StringPtr
+= StrLen (L
"&VALUE=");
3028 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
3029 if (EFI_ERROR (Status
)) {
3032 FreePool (TmpBuffer
);
3033 StringPtr
+= Length
;
3034 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
3039 // If '\0', parsing is finished.
3041 if (*StringPtr
== 0) {
3047 // Merge the requested block data.
3049 Link
= RequestBlockArray
->Entry
.ForwardLink
;
3050 while ((Link
!= &RequestBlockArray
->Entry
) && (Link
->ForwardLink
!= &RequestBlockArray
->Entry
)) {
3051 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
3052 NextBlockData
= BASE_CR (Link
->ForwardLink
, IFR_BLOCK_DATA
, Entry
);
3053 if ((NextBlockData
->Offset
>= BlockData
->Offset
) && (NextBlockData
->Offset
<= (BlockData
->Offset
+ BlockData
->Width
))) {
3054 if ((NextBlockData
->Offset
+ NextBlockData
->Width
) > (BlockData
->Offset
+ BlockData
->Width
)) {
3055 BlockData
->Width
= (UINT16
) (NextBlockData
->Offset
+ NextBlockData
->Width
- BlockData
->Offset
);
3057 RemoveEntryList (Link
->ForwardLink
);
3058 FreePool (NextBlockData
);
3061 Link
= Link
->ForwardLink
;
3064 return RequestBlockArray
;
3067 if (RequestBlockArray
!= NULL
) {
3069 // Free Link Array RequestBlockArray
3071 while (!IsListEmpty (&RequestBlockArray
->Entry
)) {
3072 BlockData
= BASE_CR (RequestBlockArray
->Entry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
3073 RemoveEntryList (&BlockData
->Entry
);
3074 FreePool (BlockData
);
3077 FreePool (RequestBlockArray
);
3084 parse the configrequest string, get the elements.
3086 @param ConfigRequest The input config request string.
3087 @param Progress Return the progress data.
3089 @retval return data block array.
3093 IN EFI_STRING ConfigRequest
,
3094 OUT EFI_STRING
*Progress
3097 EFI_STRING StringPtr
;
3099 IFR_BLOCK_DATA
*BlockData
;
3100 IFR_BLOCK_DATA
*RequestBlockArray
;
3103 StringPtr
= ConfigRequest
;
3106 // Init RequestBlockArray
3108 RequestBlockArray
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
3109 if (RequestBlockArray
== NULL
) {
3112 InitializeListHead (&RequestBlockArray
->Entry
);
3115 // Get the request Block array from the request string
3119 // Parse each <RequestElement> if exists
3120 // Only <BlockName> format is supported by this help function.
3121 // <BlockName> ::= &'Name***=***
3123 while (StringPtr
!= NULL
&& *StringPtr
== L
'&') {
3125 *Progress
= StringPtr
;
3127 // Skip the L"&" string
3132 if ((NextTag
= StrStr (StringPtr
, L
"=")) != NULL
) {
3135 } else if ((NextTag
= StrStr (StringPtr
, L
"&")) != NULL
) {
3142 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
3143 if (BlockData
== NULL
) {
3150 BlockData
->Name
= AllocateCopyPool(StrSize (StringPtr
), StringPtr
);
3151 InsertBlockData (&RequestBlockArray
->Entry
, &BlockData
);
3155 // If has value, skip the value.
3157 StringPtr
= NextTag
+ 1;
3159 StringPtr
= StrStr (StringPtr
, L
"&");
3160 } else if (NextTag
!= NULL
) {
3162 // restore the '&' text.
3164 StringPtr
= NextTag
;
3169 return RequestBlockArray
;
3172 if (RequestBlockArray
!= NULL
) {
3174 // Free Link Array RequestBlockArray
3176 while (!IsListEmpty (&RequestBlockArray
->Entry
)) {
3177 BlockData
= BASE_CR (RequestBlockArray
->Entry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
3178 RemoveEntryList (&BlockData
->Entry
);
3179 if (BlockData
->Name
!= NULL
) {
3180 FreePool (BlockData
->Name
);
3182 FreePool (BlockData
);
3185 FreePool (RequestBlockArray
);
3192 Generate ConfigRequest string base on the varstore info.
3194 @param ConfigHdr The config header for this varstore.
3195 @param VarStorageData The varstore info.
3196 @param Status Return Status.
3197 @param ConfigRequest The ConfigRequest info may be return.
3199 @retval TRUE Need to continue
3200 @retval Others NO need to continue or error occur.
3203 GenerateConfigRequest (
3204 IN CHAR16
*ConfigHdr
,
3205 IN IFR_VARSTORAGE_DATA
*VarStorageData
,
3206 OUT EFI_STATUS
*Status
,
3207 IN OUT EFI_STRING
*ConfigRequest
3213 CHAR16
*FullConfigRequest
;
3215 IFR_BLOCK_DATA
*BlockData
;
3218 // Append VarStorageData BlockEntry into *Request string
3219 // Now support only one varstore in a form package.
3223 // Go through all VarStorageData Entry and get BlockEntry for each one for the multiple varstore in a single form package
3224 // Then construct them all to return MultiRequest string : ConfigHdr BlockConfig
3228 // Compute the length of the entire request starting with <ConfigHdr> and a
3232 Length
= StrLen (ConfigHdr
) + 1;
3234 for (Link
= VarStorageData
->BlockEntry
.ForwardLink
; Link
!= &VarStorageData
->BlockEntry
; Link
= Link
->ForwardLink
) {
3236 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
3237 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3239 // Add <BlockName> length for each Name
3241 // <BlockName> ::= &Name1&Name2&...
3242 // |1| StrLen(Name1)
3244 Length
= Length
+ (1 + StrLen (BlockData
->Name
));
3247 // Add <BlockName> length for each Offset/Width pair
3249 // <BlockName> ::= &OFFSET=1234&WIDTH=1234
3250 // | 8 | 4 | 7 | 4 |
3252 Length
= Length
+ (8 + 4 + 7 + 4);
3256 // No any request block data is found. The request string can't be constructed.
3259 *Status
= EFI_SUCCESS
;
3264 // Allocate buffer for the entire <ConfigRequest>
3266 FullConfigRequest
= AllocateZeroPool (Length
* sizeof (CHAR16
));
3267 if (FullConfigRequest
== NULL
) {
3268 *Status
= EFI_OUT_OF_RESOURCES
;
3271 StringPtr
= FullConfigRequest
;
3274 // Start with <ConfigHdr>
3276 StrCpyS (StringPtr
, Length
, ConfigHdr
);
3277 StringPtr
+= StrLen (StringPtr
);
3280 // Loop through all the Offset/Width pairs and append them to ConfigRequest
3282 for (Link
= VarStorageData
->BlockEntry
.ForwardLink
; Link
!= &VarStorageData
->BlockEntry
; Link
= Link
->ForwardLink
) {
3283 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
3284 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3290 (1 + StrLen (BlockData
->Name
) + 1) * sizeof (CHAR16
),
3296 // Append &OFFSET=XXXX&WIDTH=YYYY\0
3300 (8 + 4 + 7 + 4 + 1) * sizeof (CHAR16
),
3301 L
"&OFFSET=%04X&WIDTH=%04X",
3306 StringPtr
+= StrLen (StringPtr
);
3309 // Set to the got full request string.
3311 HiiToLower (FullConfigRequest
);
3313 if (*ConfigRequest
!= NULL
) {
3314 FreePool (*ConfigRequest
);
3316 *ConfigRequest
= FullConfigRequest
;
3322 Generate ConfigRequest Header base on the varstore info.
3324 @param VarStorageData The varstore info.
3325 @param DevicePath Device path for this varstore.
3326 @param ConfigHdr The config header for this varstore.
3328 @retval EFI_SUCCESS Generate the header success.
3329 @retval EFI_OUT_OF_RESOURCES Allocate buffer fail.
3333 IN IFR_VARSTORAGE_DATA
*VarStorageData
,
3334 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
3335 OUT EFI_STRING
*ConfigHdr
3344 Status
= EFI_SUCCESS
;
3350 // Construct <ConfigHdr> : "GUID=...&NAME=...&PATH=..." by VarStorageData Guid, Name and DriverHandle
3352 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*) &VarStorageData
->Guid
, 1, &GuidStr
);
3353 if (VarStorageData
->Name
!= NULL
) {
3354 GenerateSubStr (L
"NAME=", StrLen (VarStorageData
->Name
) * sizeof (CHAR16
), (VOID
*) VarStorageData
->Name
, 2, &NameStr
);
3356 GenerateSubStr (L
"NAME=", 0, NULL
, 2, &NameStr
);
3360 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) DevicePath
),
3361 (VOID
*) DevicePath
,
3365 Length
= StrLen (GuidStr
) + StrLen (NameStr
) + StrLen (PathStr
) + 1;
3366 if (VarStorageData
->Name
== NULL
) {
3370 *ConfigHdr
= AllocateZeroPool (Length
* sizeof (CHAR16
));
3371 if (*ConfigHdr
== NULL
) {
3372 Status
= EFI_OUT_OF_RESOURCES
;
3375 StrCpyS (*ConfigHdr
, Length
, GuidStr
);
3376 StrCatS (*ConfigHdr
, Length
, NameStr
);
3377 if (VarStorageData
->Name
== NULL
) {
3378 StrCatS (*ConfigHdr
, Length
, L
"&");
3380 StrCatS (*ConfigHdr
, Length
, PathStr
);
3383 // Remove the last character L'&'
3385 *(*ConfigHdr
+ StrLen (*ConfigHdr
) - 1) = L
'\0';
3388 if (GuidStr
!= NULL
) {
3392 if (NameStr
!= NULL
) {
3396 if (PathStr
!= NULL
) {
3404 Get Data buffer size based on data type.
3406 @param ValueType The input data type.
3408 @retval The data buffer size for the input type.
3415 UINT16 StorageWidth
;
3417 switch (ValueType
) {
3418 case EFI_IFR_NUMERIC_SIZE_1
:
3419 case EFI_IFR_TYPE_BOOLEAN
:
3420 StorageWidth
= (UINT16
) sizeof (UINT8
);
3423 case EFI_IFR_NUMERIC_SIZE_2
:
3424 StorageWidth
= (UINT16
) sizeof (UINT16
);
3427 case EFI_IFR_NUMERIC_SIZE_4
:
3428 StorageWidth
= (UINT16
) sizeof (UINT32
);
3431 case EFI_IFR_NUMERIC_SIZE_8
:
3432 StorageWidth
= (UINT16
) sizeof (UINT64
);
3435 case EFI_IFR_TYPE_TIME
:
3436 StorageWidth
= (UINT16
) sizeof (EFI_IFR_TIME
);
3439 case EFI_IFR_TYPE_DATE
:
3440 StorageWidth
= (UINT16
) sizeof (EFI_IFR_DATE
);
3448 return StorageWidth
;
3452 Generate ConfigAltResp string base on the varstore info.
3454 @param HiiHandle Hii Handle for this hii package.
3455 @param ConfigHdr The config header for this varstore.
3456 @param VarStorageData The varstore info.
3457 @param DefaultIdArray The Default id array.
3458 @param DefaultAltCfgResp The DefaultAltCfgResp info may be return.
3460 @retval TRUE Need to continue
3461 @retval Others NO need to continue or error occur.
3464 GenerateAltConfigResp (
3465 IN EFI_HII_HANDLE HiiHandle
,
3466 IN CHAR16
*ConfigHdr
,
3467 IN IFR_VARSTORAGE_DATA
*VarStorageData
,
3468 IN IFR_DEFAULT_DATA
*DefaultIdArray
,
3469 IN OUT EFI_STRING
*DefaultAltCfgResp
3475 LIST_ENTRY
*LinkData
;
3476 LIST_ENTRY
*LinkDefault
;
3477 LIST_ENTRY
*ListEntry
;
3479 IFR_BLOCK_DATA
*BlockData
;
3480 IFR_DEFAULT_DATA
*DefaultId
;
3481 IFR_DEFAULT_DATA
*DefaultValueData
;
3484 CHAR16
*DefaultString
;
3488 DefaultString
= NULL
;
3490 // Add length for <ConfigHdr> + '\0'
3492 Length
= StrLen (ConfigHdr
) + 1;
3494 for (Link
= DefaultIdArray
->Entry
.ForwardLink
; Link
!= &DefaultIdArray
->Entry
; Link
= Link
->ForwardLink
) {
3495 DefaultId
= BASE_CR (Link
, IFR_DEFAULT_DATA
, Entry
);
3497 // Add length for "&<ConfigHdr>&ALTCFG=XXXX"
3498 // |1| StrLen (ConfigHdr) | 8 | 4 |
3500 Length
+= (1 + StrLen (ConfigHdr
) + 8 + 4);
3502 for (LinkData
= VarStorageData
->BlockEntry
.ForwardLink
; LinkData
!= &VarStorageData
->BlockEntry
; LinkData
= LinkData
->ForwardLink
) {
3503 BlockData
= BASE_CR (LinkData
, IFR_BLOCK_DATA
, Entry
);
3504 ListEntry
= &BlockData
->DefaultValueEntry
;
3505 for (LinkDefault
= ListEntry
->ForwardLink
; LinkDefault
!= ListEntry
; LinkDefault
= LinkDefault
->ForwardLink
) {
3506 DefaultValueData
= BASE_CR (LinkDefault
, IFR_DEFAULT_DATA
, Entry
);
3507 if (DefaultValueData
->DefaultId
!= DefaultId
->DefaultId
) {
3510 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3512 // Add length for "&Name1=zzzzzzzzzzzz"
3515 Length
+= (1 + StrLen (BlockData
->Name
) + 1 + BlockData
->Width
* 2);
3518 // Add length for "&OFFSET=XXXX&WIDTH=YYYY&VALUE=zzzzzzzzzzzz"
3519 // | 8 | 4 | 7 | 4 | 7 | Width * 2 |
3521 Length
+= (8 + 4 + 7 + 4 + 7 + BlockData
->Width
* 2);
3529 // No default value is found. The default string doesn't exist.
3536 // Allocate buffer for the entire <DefaultAltCfgResp>
3538 *DefaultAltCfgResp
= AllocateZeroPool (Length
* sizeof (CHAR16
));
3539 if (*DefaultAltCfgResp
== NULL
) {
3540 return EFI_OUT_OF_RESOURCES
;
3542 StringPtr
= *DefaultAltCfgResp
;
3545 // Start with <ConfigHdr>
3547 StrCpyS (StringPtr
, Length
, ConfigHdr
);
3548 StringPtr
+= StrLen (StringPtr
);
3550 for (Link
= DefaultIdArray
->Entry
.ForwardLink
; Link
!= &DefaultIdArray
->Entry
; Link
= Link
->ForwardLink
) {
3551 DefaultId
= BASE_CR (Link
, IFR_DEFAULT_DATA
, Entry
);
3553 // Add <AltConfigHdr> of the form "&<ConfigHdr>&ALTCFG=XXXX\0"
3554 // |1| StrLen (ConfigHdr) | 8 | 4 |
3558 (1 + StrLen (ConfigHdr
) + 8 + 4 + 1) * sizeof (CHAR16
),
3561 DefaultId
->DefaultId
3563 StringPtr
+= StrLen (StringPtr
);
3565 for (LinkData
= VarStorageData
->BlockEntry
.ForwardLink
; LinkData
!= &VarStorageData
->BlockEntry
; LinkData
= LinkData
->ForwardLink
) {
3566 BlockData
= BASE_CR (LinkData
, IFR_BLOCK_DATA
, Entry
);
3567 ListEntry
= &BlockData
->DefaultValueEntry
;
3568 for (LinkDefault
= ListEntry
->ForwardLink
; LinkDefault
!= ListEntry
; LinkDefault
= LinkDefault
->ForwardLink
) {
3569 DefaultValueData
= BASE_CR (LinkDefault
, IFR_DEFAULT_DATA
, Entry
);
3570 if (DefaultValueData
->DefaultId
!= DefaultId
->DefaultId
) {
3573 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3576 (1 + StrLen (ConfigHdr
) + 1) * sizeof (CHAR16
),
3580 StringPtr
+= StrLen (StringPtr
);
3583 // Add <BlockConfig>
3584 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>
3588 (8 + 4 + 7 + 4 + 7 + 1) * sizeof (CHAR16
),
3589 L
"&OFFSET=%04X&WIDTH=%04X&VALUE=",
3593 StringPtr
+= StrLen (StringPtr
);
3595 Width
= BlockData
->Width
;
3597 // Convert Value to a hex string in "%x" format
3598 // NOTE: This is in the opposite byte that GUID and PATH use
3600 if (BlockData
->OpCode
== EFI_IFR_STRING_OP
){
3601 DefaultString
= InternalGetString(HiiHandle
, DefaultValueData
->Value
.string
);
3602 TmpBuffer
= (UINT8
*) DefaultString
;
3604 TmpBuffer
= (UINT8
*) &(DefaultValueData
->Value
);
3606 for (; Width
> 0 && (TmpBuffer
!= NULL
); Width
--) {
3607 StringPtr
+= UnicodeValueToString (StringPtr
, PREFIX_ZERO
| RADIX_HEX
, TmpBuffer
[Width
- 1], 2);
3609 if (DefaultString
!= NULL
){
3610 FreePool(DefaultString
);
3611 DefaultString
= NULL
;
3617 HiiToLower (*DefaultAltCfgResp
);
3623 This function gets the full request string and full default value string by
3624 parsing IFR data in HII form packages.
3626 When Request points to NULL string, the request string and default value string
3627 for each varstore in form package will return.
3629 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
3630 @param DevicePath Device Path which Hii Config Access Protocol is registered.
3631 @param Request Pointer to a null-terminated Unicode string in
3632 <ConfigRequest> format. When it doesn't contain
3633 any RequestElement, it will be updated to return
3634 the full RequestElement retrieved from IFR data.
3635 If it points to NULL, the request string for the first
3636 varstore in form package will be merged into a
3637 <MultiConfigRequest> format string and return.
3638 @param AltCfgResp Pointer to a null-terminated Unicode string in
3639 <ConfigAltResp> format. When the pointer is to NULL,
3640 the full default value string retrieved from IFR data
3641 will return. When the pinter is to a string, the
3642 full default value string retrieved from IFR data
3643 will be merged into the input string and return.
3644 When Request points to NULL, the default value string
3645 for each varstore in form package will be merged into
3646 a <MultiConfigAltResp> format string and return.
3647 @param PointerProgress Optional parameter, it can be be NULL.
3648 When it is not NULL, if Request is NULL, it returns NULL.
3649 On return, points to a character in the Request
3650 string. Points to the string's null terminator if
3651 request was successful. Points to the most recent
3652 & before the first failing name / value pair (or
3653 the beginning of the string if the failure is in
3654 the first name / value pair) if the request was
3656 @retval EFI_SUCCESS The Results string is set to the full request string.
3657 And AltCfgResp contains all default value string.
3658 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
3659 @retval EFI_NOT_FOUND The varstore (Guid and Name) in Request string
3660 can't be found in Form package.
3661 @retval EFI_NOT_FOUND HiiPackage can't be got on the input HiiHandle.
3662 @retval EFI_INVALID_PARAMETER Request points to NULL.
3667 GetFullStringFromHiiFormPackages (
3668 IN HII_DATABASE_RECORD
*DataBaseRecord
,
3669 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
3670 IN OUT EFI_STRING
*Request
,
3671 IN OUT EFI_STRING
*AltCfgResp
,
3672 OUT EFI_STRING
*PointerProgress OPTIONAL
3676 UINT8
*HiiFormPackage
;
3678 IFR_BLOCK_DATA
*RequestBlockArray
;
3679 IFR_BLOCK_DATA
*BlockData
;
3680 IFR_DEFAULT_DATA
*DefaultValueData
;
3681 IFR_DEFAULT_DATA
*DefaultId
;
3682 IFR_DEFAULT_DATA
*DefaultIdArray
;
3683 IFR_VARSTORAGE_DATA
*VarStorageData
;
3684 EFI_STRING DefaultAltCfgResp
;
3685 EFI_STRING ConfigHdr
;
3686 EFI_STRING StringPtr
;
3687 EFI_STRING Progress
;
3689 if (DataBaseRecord
== NULL
|| DevicePath
== NULL
|| Request
== NULL
|| AltCfgResp
== NULL
) {
3690 return EFI_INVALID_PARAMETER
;
3694 // Initialize the local variables.
3696 RequestBlockArray
= NULL
;
3697 DefaultIdArray
= NULL
;
3698 VarStorageData
= NULL
;
3699 DefaultAltCfgResp
= NULL
;
3701 HiiFormPackage
= NULL
;
3703 Progress
= *Request
;
3705 Status
= GetFormPackageData (DataBaseRecord
, &HiiFormPackage
, &PackageSize
);
3706 if (EFI_ERROR (Status
)) {
3711 // 1. Get the request block array by Request String when Request string containts the block array.
3714 if (*Request
!= NULL
) {
3715 StringPtr
= *Request
;
3719 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
3720 Status
= EFI_INVALID_PARAMETER
;
3723 StringPtr
+= StrLen (L
"GUID=");
3724 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&NAME=", StrLen (L
"&NAME=")) != 0) {
3727 if (*StringPtr
== L
'\0') {
3728 Status
= EFI_INVALID_PARAMETER
;
3731 StringPtr
+= StrLen (L
"&NAME=");
3732 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&PATH=", StrLen (L
"&PATH=")) != 0) {
3735 if (*StringPtr
== L
'\0') {
3736 Status
= EFI_INVALID_PARAMETER
;
3739 StringPtr
+= StrLen (L
"&PATH=");
3740 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
3744 if (*StringPtr
== L
'\0') {
3746 // No request block is found.
3753 // If StringPtr != NULL, get the request elements.
3755 if (StringPtr
!= NULL
) {
3756 if (StrStr (StringPtr
, L
"&OFFSET=") != NULL
) {
3757 RequestBlockArray
= GetBlockElement(StringPtr
, &Progress
);
3759 RequestBlockArray
= GetNameElement(StringPtr
, &Progress
);
3762 if (RequestBlockArray
== NULL
) {
3763 Status
= EFI_INVALID_PARAMETER
;
3769 // Initialize DefaultIdArray to store the map between DeaultId and DefaultName
3771 DefaultIdArray
= (IFR_DEFAULT_DATA
*) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
3772 if (DefaultIdArray
== NULL
) {
3773 Status
= EFI_OUT_OF_RESOURCES
;
3776 InitializeListHead (&DefaultIdArray
->Entry
);
3779 // Initialize VarStorageData to store the var store Block and Default value information.
3781 VarStorageData
= (IFR_VARSTORAGE_DATA
*) AllocateZeroPool (sizeof (IFR_VARSTORAGE_DATA
));
3782 if (VarStorageData
== NULL
) {
3783 Status
= EFI_OUT_OF_RESOURCES
;
3786 InitializeListHead (&VarStorageData
->Entry
);
3787 InitializeListHead (&VarStorageData
->BlockEntry
);
3790 // 2. Parse FormPackage to get BlockArray and DefaultId Array for the request BlockArray.
3794 // Parse the opcode in form pacakge to get the default setting.
3796 Status
= ParseIfrData (DataBaseRecord
->Handle
,
3798 (UINT32
) PackageSize
,
3803 if (EFI_ERROR (Status
)) {
3808 // No requested varstore in IFR data and directly return
3810 if (VarStorageData
->Type
== 0 && VarStorageData
->Name
== NULL
) {
3811 Status
= EFI_SUCCESS
;
3816 // 3. Construct Request Element (Block Name) for 2.1 and 2.2 case.
3818 Status
= GenerateHdr (VarStorageData
, DevicePath
, &ConfigHdr
);
3819 if (EFI_ERROR (Status
)) {
3823 if (RequestBlockArray
== NULL
) {
3824 if (!GenerateConfigRequest(ConfigHdr
, VarStorageData
, &Status
, Request
)) {
3830 // 4. Construct Default Value string in AltResp according to request element.
3831 // Go through all VarStorageData Entry and get the DefaultId array for each one
3832 // Then construct them all to : ConfigHdr AltConfigHdr ConfigBody AltConfigHdr ConfigBody
3834 Status
= GenerateAltConfigResp (DataBaseRecord
->Handle
,ConfigHdr
, VarStorageData
, DefaultIdArray
, &DefaultAltCfgResp
);
3835 if (EFI_ERROR (Status
)) {
3840 // 5. Merge string into the input AltCfgResp if the iput *AltCfgResp is not NULL.
3842 if (*AltCfgResp
!= NULL
&& DefaultAltCfgResp
!= NULL
) {
3843 Status
= MergeDefaultString (AltCfgResp
, DefaultAltCfgResp
);
3844 FreePool (DefaultAltCfgResp
);
3845 } else if (*AltCfgResp
== NULL
) {
3846 *AltCfgResp
= DefaultAltCfgResp
;
3850 if (RequestBlockArray
!= NULL
) {
3852 // Free Link Array RequestBlockArray
3854 while (!IsListEmpty (&RequestBlockArray
->Entry
)) {
3855 BlockData
= BASE_CR (RequestBlockArray
->Entry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
3856 RemoveEntryList (&BlockData
->Entry
);
3857 if (BlockData
->Name
!= NULL
) {
3858 FreePool (BlockData
->Name
);
3860 FreePool (BlockData
);
3863 FreePool (RequestBlockArray
);
3866 if (VarStorageData
!= NULL
) {
3868 // Free link array VarStorageData
3870 while (!IsListEmpty (&VarStorageData
->BlockEntry
)) {
3871 BlockData
= BASE_CR (VarStorageData
->BlockEntry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
3872 RemoveEntryList (&BlockData
->Entry
);
3873 if (BlockData
->Name
!= NULL
) {
3874 FreePool (BlockData
->Name
);
3877 // Free default value link array
3879 while (!IsListEmpty (&BlockData
->DefaultValueEntry
)) {
3880 DefaultValueData
= BASE_CR (BlockData
->DefaultValueEntry
.ForwardLink
, IFR_DEFAULT_DATA
, Entry
);
3881 RemoveEntryList (&DefaultValueData
->Entry
);
3882 FreePool (DefaultValueData
);
3884 FreePool (BlockData
);
3886 if (VarStorageData
->Name
!= NULL
) {
3887 FreePool (VarStorageData
->Name
);
3888 VarStorageData
->Name
= NULL
;
3890 FreePool (VarStorageData
);
3893 if (DefaultIdArray
!= NULL
) {
3895 // Free DefaultId Array
3897 while (!IsListEmpty (&DefaultIdArray
->Entry
)) {
3898 DefaultId
= BASE_CR (DefaultIdArray
->Entry
.ForwardLink
, IFR_DEFAULT_DATA
, Entry
);
3899 RemoveEntryList (&DefaultId
->Entry
);
3900 FreePool (DefaultId
);
3902 FreePool (DefaultIdArray
);
3906 // Free the allocated string
3908 if (ConfigHdr
!= NULL
) {
3909 FreePool (ConfigHdr
);
3913 // Free Pacakge data
3915 if (HiiFormPackage
!= NULL
) {
3916 FreePool (HiiFormPackage
);
3919 if (PointerProgress
!= NULL
) {
3920 if (*Request
== NULL
) {
3921 *PointerProgress
= NULL
;
3922 } else if (EFI_ERROR (Status
)) {
3923 *PointerProgress
= *Request
;
3925 *PointerProgress
= *Request
+ StrLen (*Request
);
3933 This function gets the full request resp string by
3934 parsing IFR data in HII form packages.
3936 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
3938 @param EfiVarStoreInfo The efi varstore info which is save in the EFI
3939 varstore data structure.
3940 @param Request Pointer to a null-terminated Unicode string in
3941 <ConfigRequest> format.
3942 @param RequestResp Pointer to a null-terminated Unicode string in
3943 <ConfigResp> format.
3944 @param AccessProgress On return, points to a character in the Request
3945 string. Points to the string's null terminator if
3946 request was successful. Points to the most recent
3947 & before the first failing name / value pair (or
3948 the beginning of the string if the failure is in
3949 the first name / value pair) if the request was
3952 @retval EFI_SUCCESS The Results string is set to the full request string.
3953 And AltCfgResp contains all default value string.
3954 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
3955 @retval EFI_INVALID_PARAMETER Request points to NULL.
3959 GetConfigRespFromEfiVarStore (
3960 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
3961 IN EFI_IFR_VARSTORE_EFI
*EfiVarStoreInfo
,
3962 IN EFI_STRING Request
,
3963 OUT EFI_STRING
*RequestResp
,
3964 OUT EFI_STRING
*AccessProgress
3968 EFI_STRING VarStoreName
;
3972 Status
= EFI_SUCCESS
;
3975 VarStoreName
= NULL
;
3976 *AccessProgress
= Request
;
3978 VarStoreName
= AllocateZeroPool (AsciiStrSize ((CHAR8
*)EfiVarStoreInfo
->Name
) * sizeof (CHAR16
));
3979 if (VarStoreName
== NULL
) {
3980 Status
= EFI_OUT_OF_RESOURCES
;
3983 AsciiStrToUnicodeStr ((CHAR8
*) EfiVarStoreInfo
->Name
, VarStoreName
);
3986 Status
= gRT
->GetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, NULL
, &BufferSize
, NULL
);
3987 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
3991 VarStore
= AllocateZeroPool (BufferSize
);
3992 ASSERT (VarStore
!= NULL
);
3993 Status
= gRT
->GetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, NULL
, &BufferSize
, VarStore
);
3994 if (EFI_ERROR (Status
)) {
3998 Status
= HiiBlockToConfig(This
, Request
, VarStore
, BufferSize
, RequestResp
, AccessProgress
);
3999 if (EFI_ERROR (Status
)) {
4004 if (VarStoreName
!= NULL
) {
4005 FreePool (VarStoreName
);
4008 if (VarStore
!= NULL
) {
4009 FreePool (VarStore
);
4017 This function route the full request resp string for efi varstore.
4019 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
4021 @param EfiVarStoreInfo The efi varstore info which is save in the EFI
4022 varstore data structure.
4023 @param RequestResp Pointer to a null-terminated Unicode string in
4024 <ConfigResp> format.
4025 @param Result Pointer to a null-terminated Unicode string in
4026 <ConfigResp> format.
4028 @retval EFI_SUCCESS The Results string is set to the full request string.
4029 And AltCfgResp contains all default value string.
4030 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
4031 @retval EFI_INVALID_PARAMETER Request points to NULL.
4035 RouteConfigRespForEfiVarStore (
4036 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
4037 IN EFI_IFR_VARSTORE_EFI
*EfiVarStoreInfo
,
4038 IN EFI_STRING RequestResp
,
4039 OUT EFI_STRING
*Result
4043 EFI_STRING VarStoreName
;
4048 Status
= EFI_SUCCESS
;
4051 VarStoreName
= NULL
;
4053 VarStoreName
= AllocateZeroPool (AsciiStrSize ((CHAR8
*)EfiVarStoreInfo
->Name
) * sizeof (CHAR16
));
4054 if (VarStoreName
== NULL
) {
4055 Status
= EFI_OUT_OF_RESOURCES
;
4058 AsciiStrToUnicodeStr ((CHAR8
*) EfiVarStoreInfo
->Name
, VarStoreName
);
4060 Status
= gRT
->GetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, NULL
, &BufferSize
, NULL
);
4061 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
4065 BlockSize
= BufferSize
;
4066 VarStore
= AllocateZeroPool (BufferSize
);
4067 ASSERT (VarStore
!= NULL
);
4068 Status
= gRT
->GetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, NULL
, &BufferSize
, VarStore
);
4069 if (EFI_ERROR (Status
)) {
4073 Status
= HiiConfigToBlock(This
, RequestResp
, VarStore
, &BlockSize
, Result
);
4074 if (EFI_ERROR (Status
)) {
4078 Status
= gRT
->SetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, EfiVarStoreInfo
->Attributes
, BufferSize
, VarStore
);
4079 if (EFI_ERROR (Status
)) {
4084 if (VarStoreName
!= NULL
) {
4085 FreePool (VarStoreName
);
4088 if (VarStore
!= NULL
) {
4089 FreePool (VarStore
);
4096 Validate the config request elements.
4098 @param ConfigElements A null-terminated Unicode string in <ConfigRequest> format,
4099 without configHdr field.
4101 @retval CHAR16 * THE first Name/value pair not correct.
4102 @retval NULL Success parse the name/value pair
4105 OffsetWidthValidate (
4106 CHAR16
*ConfigElements
4112 StringPtr
= ConfigElements
;
4116 if (StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) != 0) {
4120 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
4123 if (*StringPtr
== L
'\0') {
4127 StringPtr
+= StrLen (L
"&WIDTH=");
4128 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) != 0) {
4132 if (*StringPtr
== L
'\0') {
4139 Validate the config request elements.
4141 @param ConfigElements A null-terminated Unicode string in <ConfigRequest> format,
4142 without configHdr field.
4144 @retval CHAR16 * THE first Name/value pair not correct.
4145 @retval NULL Success parse the name/value pair
4150 CHAR16
*ConfigElements
4156 StringPtr
= ConfigElements
;
4160 if (*StringPtr
!= L
'&') {
4165 StringPtr
= StrStr (StringPtr
, L
"&");
4167 if (StringPtr
== NULL
) {
4174 Validate the config request string.
4176 @param ConfigRequest A null-terminated Unicode string in <ConfigRequest> format.
4178 @retval CHAR16 * THE first element not correct.
4179 @retval NULL Success parse the name/value pair
4183 ConfigRequestValidate (
4184 CHAR16
*ConfigRequest
4187 BOOLEAN HasNameField
;
4190 HasNameField
= TRUE
;
4191 StringPtr
= ConfigRequest
;
4194 // Check <ConfigHdr>
4196 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
4197 return ConfigRequest
;
4199 StringPtr
+= StrLen (L
"GUID=");
4200 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&NAME=", StrLen (L
"&NAME=")) != 0) {
4203 if (*StringPtr
== L
'\0') {
4204 return ConfigRequest
;
4206 StringPtr
+= StrLen (L
"&NAME=");
4207 if (*StringPtr
== L
'&') {
4208 HasNameField
= FALSE
;
4210 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&PATH=", StrLen (L
"&PATH=")) != 0) {
4213 if (*StringPtr
== L
'\0') {
4214 return ConfigRequest
;
4216 StringPtr
+= StrLen (L
"&PATH=");
4217 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
4221 if (*StringPtr
== L
'\0') {
4227 // Should be Buffer varstore, config request should be "OFFSET/Width" pairs.
4229 return OffsetWidthValidate(StringPtr
);
4232 // Should be Name/Value varstore, config request should be "&name1&name2..." pairs.
4234 return NameValueValidate(StringPtr
);
4239 This function allows a caller to extract the current configuration
4240 for one or more named elements from one or more drivers.
4242 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
4244 @param Request A null-terminated Unicode string in
4245 <MultiConfigRequest> format.
4246 @param Progress On return, points to a character in the Request
4247 string. Points to the string's null terminator if
4248 request was successful. Points to the most recent
4249 & before the first failing name / value pair (or
4250 the beginning of the string if the failure is in
4251 the first name / value pair) if the request was
4253 @param Results Null-terminated Unicode string in
4254 <MultiConfigAltResp> format which has all values
4255 filled in for the names in the Request string.
4256 String to be allocated by the called function.
4258 @retval EFI_SUCCESS The Results string is filled with the values
4259 corresponding to all requested names.
4260 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
4261 results that must be stored awaiting possible
4263 @retval EFI_NOT_FOUND Routing data doesn't match any known driver.
4264 Progress set to the "G" in "GUID" of the routing
4265 header that doesn't match. Note: There is no
4266 requirement that all routing data be validated
4267 before any configuration extraction.
4268 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Request
4269 parameter would result in this type of error. The
4270 Progress parameter is set to NULL.
4271 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set to most recent &
4272 before the error or the beginning of the string.
4273 @retval EFI_INVALID_PARAMETER The ExtractConfig function of the underlying HII
4274 Configuration Access Protocol returned
4275 EFI_INVALID_PARAMETER. Progress set to most recent
4276 & before the error or the beginning of the string.
4281 HiiConfigRoutingExtractConfig (
4282 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
4283 IN CONST EFI_STRING Request
,
4284 OUT EFI_STRING
*Progress
,
4285 OUT EFI_STRING
*Results
4288 HII_DATABASE_PRIVATE_DATA
*Private
;
4289 EFI_STRING StringPtr
;
4290 EFI_STRING ConfigRequest
;
4292 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
4293 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
4296 HII_DATABASE_RECORD
*Database
;
4297 UINT8
*DevicePathPkg
;
4298 UINT8
*CurrentDevicePath
;
4299 EFI_HANDLE DriverHandle
;
4300 EFI_HII_HANDLE HiiHandle
;
4301 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
4302 EFI_STRING AccessProgress
;
4303 EFI_STRING AccessResults
;
4304 EFI_STRING AccessProgressBackup
;
4305 EFI_STRING AccessResultsBackup
;
4306 EFI_STRING DefaultResults
;
4307 BOOLEAN FirstElement
;
4308 BOOLEAN IfrDataParsedFlag
;
4309 BOOLEAN IsEfiVarStore
;
4310 EFI_IFR_VARSTORE_EFI
*EfiVarStoreInfo
;
4311 EFI_STRING ErrorPtr
;
4312 UINTN DevicePathSize
;
4313 UINTN ConigStringSize
;
4314 UINTN ConigStringSizeNewsize
;
4315 EFI_STRING ConfigStringPtr
;
4317 if (This
== NULL
|| Progress
== NULL
|| Results
== NULL
) {
4318 return EFI_INVALID_PARAMETER
;
4321 if (Request
== NULL
) {
4323 return EFI_INVALID_PARAMETER
;
4326 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
4327 StringPtr
= Request
;
4328 *Progress
= StringPtr
;
4329 DefaultResults
= NULL
;
4330 ConfigRequest
= NULL
;
4331 Status
= EFI_SUCCESS
;
4332 AccessResults
= NULL
;
4333 AccessProgress
= NULL
;
4334 AccessResultsBackup
= NULL
;
4335 AccessProgressBackup
= NULL
;
4337 IfrDataParsedFlag
= FALSE
;
4338 IsEfiVarStore
= FALSE
;
4339 EfiVarStoreInfo
= NULL
;
4342 // The first element of <MultiConfigRequest> should be
4343 // <GuidHdr>, which is in 'GUID='<Guid> syntax.
4345 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
4346 return EFI_INVALID_PARAMETER
;
4349 FirstElement
= TRUE
;
4352 // Allocate a fix length of memory to store Results. Reallocate memory for
4353 // Results if this fix length is insufficient.
4355 *Results
= (EFI_STRING
) AllocateZeroPool (MAX_STRING_LENGTH
);
4356 if (*Results
== NULL
) {
4357 return EFI_OUT_OF_RESOURCES
;
4360 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) == 0) {
4362 // If parsing error, set Progress to the beginning of the <MultiConfigRequest>
4363 // or most recent & before the error.
4365 if (StringPtr
== Request
) {
4366 *Progress
= StringPtr
;
4368 *Progress
= StringPtr
- 1;
4372 // Process each <ConfigRequest> of <MultiConfigRequest>
4374 Length
= CalculateConfigStringLen (StringPtr
);
4375 ConfigRequest
= AllocateCopyPool ((Length
+ 1) * sizeof (CHAR16
), StringPtr
);
4376 if (ConfigRequest
== NULL
) {
4377 Status
= EFI_OUT_OF_RESOURCES
;
4380 *(ConfigRequest
+ Length
) = 0;
4383 // Get the UEFI device path
4385 Status
= GetDevicePath (ConfigRequest
, (UINT8
**) &DevicePath
);
4386 if (EFI_ERROR (Status
)) {
4391 // Find driver which matches the routing data.
4393 DriverHandle
= NULL
;
4396 for (Link
= Private
->DatabaseList
.ForwardLink
;
4397 Link
!= &Private
->DatabaseList
;
4398 Link
= Link
->ForwardLink
4400 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
4401 if ((DevicePathPkg
= Database
->PackageList
->DevicePathPkg
) != NULL
) {
4402 CurrentDevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
4403 DevicePathSize
= GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) CurrentDevicePath
);
4404 if ((CompareMem (DevicePath
,CurrentDevicePath
,DevicePathSize
) == 0) && IsThisPackageList(Database
, ConfigRequest
)) {
4405 DriverHandle
= Database
->DriverHandle
;
4406 HiiHandle
= Database
->Handle
;
4413 // Try to find driver handle by device path.
4415 if (DriverHandle
== NULL
) {
4416 TempDevicePath
= DevicePath
;
4417 Status
= gBS
->LocateDevicePath (
4418 &gEfiDevicePathProtocolGuid
,
4422 if (EFI_ERROR (Status
) || (DriverHandle
== NULL
)) {
4424 // Routing data does not match any known driver.
4425 // Set Progress to the 'G' in "GUID" of the routing header.
4427 *Progress
= StringPtr
;
4428 Status
= EFI_NOT_FOUND
;
4434 // Validate ConfigRequest String.
4436 ErrorPtr
= ConfigRequestValidate(ConfigRequest
);
4437 if (ErrorPtr
!= NULL
) {
4438 *Progress
= StrStr (StringPtr
, ErrorPtr
);
4439 Status
= EFI_INVALID_PARAMETER
;
4444 // Check whether ConfigRequest contains request string.
4446 IfrDataParsedFlag
= FALSE
;
4447 if ((HiiHandle
!= NULL
) && !GetElementsFromRequest(ConfigRequest
)) {
4449 // Get the full request string from IFR when HiiPackage is registered to HiiHandle
4451 IfrDataParsedFlag
= TRUE
;
4452 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &ConfigRequest
, &DefaultResults
, &AccessProgress
);
4453 if (EFI_ERROR (Status
)) {
4455 // AccessProgress indicates the parsing progress on <ConfigRequest>.
4456 // Map it to the progress on <MultiConfigRequest> then return it.
4458 ASSERT (AccessProgress
!= NULL
);
4459 *Progress
= StrStr (StringPtr
, AccessProgress
);
4463 // Not any request block is found.
4465 if (!GetElementsFromRequest(ConfigRequest
)) {
4466 AccessResults
= AllocateCopyPool (StrSize (ConfigRequest
), ConfigRequest
);
4467 goto NextConfigString
;
4472 // Check whether this ConfigRequest is search from Efi varstore type storage.
4474 Status
= GetVarStoreType(Database
, ConfigRequest
, &IsEfiVarStore
, &EfiVarStoreInfo
);
4475 if (EFI_ERROR (Status
)) {
4479 if (IsEfiVarStore
) {
4481 // Call the GetVariable function to extract settings.
4483 Status
= GetConfigRespFromEfiVarStore(This
, EfiVarStoreInfo
, ConfigRequest
, &AccessResults
, &AccessProgress
);
4484 FreePool (EfiVarStoreInfo
);
4485 if (EFI_ERROR (Status
)) {
4487 // AccessProgress indicates the parsing progress on <ConfigRequest>.
4488 // Map it to the progress on <MultiConfigRequest> then return it.
4490 *Progress
= StrStr (StringPtr
, AccessProgress
);
4495 // For EfiVarstore, call corresponding ConfigAccess protocol to get the AltCfgResp from driver.
4497 Status
= gBS
->HandleProtocol (
4499 &gEfiHiiConfigAccessProtocolGuid
,
4500 (VOID
**) &ConfigAccess
4502 if (EFI_ERROR (Status
)) {
4504 // The driver has EfiVarStore, may not install ConfigAccess protocol.
4505 // So ignore the error status in this case.
4507 Status
= EFI_SUCCESS
;
4509 Status
= ConfigAccess
->ExtractConfig (
4512 &AccessProgressBackup
,
4513 &AccessResultsBackup
4515 if (!EFI_ERROR(Status
)) {
4517 //Merge the AltCfgResp in AccessResultsBackup to AccessResults
4519 if ((AccessResultsBackup
!= NULL
) && (StrStr (AccessResultsBackup
, L
"&ALTCFG=") != NULL
)) {
4520 ConigStringSize
= StrSize (AccessResults
);
4521 ConfigStringPtr
= StrStr (AccessResultsBackup
, L
"&GUID=");
4522 ConigStringSizeNewsize
= StrSize (ConfigStringPtr
) + ConigStringSize
+ sizeof (CHAR16
);
4523 AccessResults
= (EFI_STRING
) ReallocatePool (
4525 ConigStringSizeNewsize
,
4527 StrCatS (AccessResults
, ConigStringSizeNewsize
/ sizeof (CHAR16
), ConfigStringPtr
);
4531 // In the ExtractConfig function of some driver may not support EfiVarStore,
4532 // may return error status, just ignore the error status in this case.
4534 Status
= EFI_SUCCESS
;
4536 if (AccessResultsBackup
!= NULL
) {
4537 FreePool (AccessResultsBackup
);
4538 AccessResultsBackup
= NULL
;
4543 // Call corresponding ConfigAccess protocol to extract settings
4545 Status
= gBS
->HandleProtocol (
4547 &gEfiHiiConfigAccessProtocolGuid
,
4548 (VOID
**) &ConfigAccess
4550 if (EFI_ERROR (Status
)) {
4554 Status
= ConfigAccess
->ExtractConfig (
4561 if (EFI_ERROR (Status
)) {
4563 // AccessProgress indicates the parsing progress on <ConfigRequest>.
4564 // Map it to the progress on <MultiConfigRequest> then return it.
4566 *Progress
= StrStr (StringPtr
, AccessProgress
);
4571 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'
4572 // which seperates the first <ConfigAltResp> and the following ones.
4574 ASSERT (*AccessProgress
== 0);
4577 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
4579 if (!IfrDataParsedFlag
&& HiiHandle
!= NULL
) {
4580 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &ConfigRequest
, &DefaultResults
, NULL
);
4581 ASSERT_EFI_ERROR (Status
);
4584 FreePool (DevicePath
);
4587 if (DefaultResults
!= NULL
) {
4588 Status
= MergeDefaultString (&AccessResults
, DefaultResults
);
4589 ASSERT_EFI_ERROR (Status
);
4590 FreePool (DefaultResults
);
4591 DefaultResults
= NULL
;
4595 if (!FirstElement
) {
4596 Status
= AppendToMultiString (Results
, L
"&");
4597 ASSERT_EFI_ERROR (Status
);
4600 Status
= AppendToMultiString (Results
, AccessResults
);
4601 ASSERT_EFI_ERROR (Status
);
4603 FirstElement
= FALSE
;
4605 FreePool (AccessResults
);
4606 AccessResults
= NULL
;
4607 FreePool (ConfigRequest
);
4608 ConfigRequest
= NULL
;
4611 // Go to next <ConfigRequest> (skip '&').
4613 StringPtr
+= Length
;
4614 if (*StringPtr
== 0) {
4615 *Progress
= StringPtr
;
4623 if (EFI_ERROR (Status
)) {
4624 FreePool (*Results
);
4628 if (ConfigRequest
!= NULL
) {
4629 FreePool (ConfigRequest
);
4632 if (AccessResults
!= NULL
) {
4633 FreePool (AccessResults
);
4636 if (DefaultResults
!= NULL
) {
4637 FreePool (DefaultResults
);
4640 if (DevicePath
!= NULL
) {
4641 FreePool (DevicePath
);
4649 This function allows the caller to request the current configuration for the
4650 entirety of the current HII database and returns the data in a
4651 null-terminated Unicode string.
4653 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
4655 @param Results Null-terminated Unicode string in
4656 <MultiConfigAltResp> format which has all values
4657 filled in for the entirety of the current HII
4658 database. String to be allocated by the called
4659 function. De-allocation is up to the caller.
4661 @retval EFI_SUCCESS The Results string is filled with the values
4662 corresponding to all requested names.
4663 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
4664 results that must be stored awaiting possible
4666 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Results
4667 parameter would result in this type of error.
4672 HiiConfigRoutingExportConfig (
4673 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
4674 OUT EFI_STRING
*Results
4678 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
4679 EFI_STRING AccessResults
;
4680 EFI_STRING Progress
;
4681 EFI_STRING StringPtr
;
4682 EFI_STRING ConfigRequest
;
4684 EFI_HANDLE
*ConfigAccessHandles
;
4685 UINTN NumberConfigAccessHandles
;
4686 BOOLEAN FirstElement
;
4687 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
4688 EFI_HII_HANDLE HiiHandle
;
4689 EFI_STRING DefaultResults
;
4690 HII_DATABASE_PRIVATE_DATA
*Private
;
4692 HII_DATABASE_RECORD
*Database
;
4693 UINT8
*DevicePathPkg
;
4694 UINT8
*CurrentDevicePath
;
4695 BOOLEAN IfrDataParsedFlag
;
4697 if (This
== NULL
|| Results
== NULL
) {
4698 return EFI_INVALID_PARAMETER
;
4701 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
4704 // Allocate a fix length of memory to store Results. Reallocate memory for
4705 // Results if this fix length is insufficient.
4707 *Results
= (EFI_STRING
) AllocateZeroPool (MAX_STRING_LENGTH
);
4708 if (*Results
== NULL
) {
4709 return EFI_OUT_OF_RESOURCES
;
4712 NumberConfigAccessHandles
= 0;
4713 Status
= gBS
->LocateHandleBuffer (
4715 &gEfiHiiConfigAccessProtocolGuid
,
4717 &NumberConfigAccessHandles
,
4718 &ConfigAccessHandles
4720 if (EFI_ERROR (Status
)) {
4724 FirstElement
= TRUE
;
4726 for (Index
= 0; Index
< NumberConfigAccessHandles
; Index
++) {
4727 Status
= gBS
->HandleProtocol (
4728 ConfigAccessHandles
[Index
],
4729 &gEfiHiiConfigAccessProtocolGuid
,
4730 (VOID
**) &ConfigAccess
4732 if (EFI_ERROR (Status
)) {
4737 // Get DevicePath and HiiHandle for this ConfigAccess driver handle
4739 IfrDataParsedFlag
= FALSE
;
4742 DefaultResults
= NULL
;
4744 ConfigRequest
= NULL
;
4745 DevicePath
= DevicePathFromHandle (ConfigAccessHandles
[Index
]);
4746 if (DevicePath
!= NULL
) {
4747 for (Link
= Private
->DatabaseList
.ForwardLink
;
4748 Link
!= &Private
->DatabaseList
;
4749 Link
= Link
->ForwardLink
4751 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
4752 if ((DevicePathPkg
= Database
->PackageList
->DevicePathPkg
) != NULL
) {
4753 CurrentDevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
4757 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) CurrentDevicePath
)
4759 HiiHandle
= Database
->Handle
;
4766 Status
= ConfigAccess
->ExtractConfig (
4772 if (EFI_ERROR (Status
)) {
4774 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
4776 if (HiiHandle
!= NULL
&& DevicePath
!= NULL
) {
4777 IfrDataParsedFlag
= TRUE
;
4778 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &ConfigRequest
, &DefaultResults
, NULL
);
4780 // Get the full request string to get the Current setting again.
4782 if (!EFI_ERROR (Status
) && ConfigRequest
!= NULL
) {
4783 Status
= ConfigAccess
->ExtractConfig (
4789 FreePool (ConfigRequest
);
4791 Status
= EFI_NOT_FOUND
;
4796 if (!EFI_ERROR (Status
)) {
4798 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
4800 if (!IfrDataParsedFlag
&& HiiHandle
!= NULL
&& DevicePath
!= NULL
) {
4801 StringPtr
= StrStr (AccessResults
, L
"&GUID=");
4802 if (StringPtr
!= NULL
) {
4805 if (GetElementsFromRequest (AccessResults
)) {
4806 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &AccessResults
, &DefaultResults
, NULL
);
4807 ASSERT_EFI_ERROR (Status
);
4809 if (StringPtr
!= NULL
) {
4814 // Merge the default sting from IFR code into the got setting from driver.
4816 if (DefaultResults
!= NULL
) {
4817 Status
= MergeDefaultString (&AccessResults
, DefaultResults
);
4818 ASSERT_EFI_ERROR (Status
);
4819 FreePool (DefaultResults
);
4820 DefaultResults
= NULL
;
4824 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'
4825 // which seperates the first <ConfigAltResp> and the following ones.
4827 if (!FirstElement
) {
4828 Status
= AppendToMultiString (Results
, L
"&");
4829 ASSERT_EFI_ERROR (Status
);
4832 Status
= AppendToMultiString (Results
, AccessResults
);
4833 ASSERT_EFI_ERROR (Status
);
4835 FirstElement
= FALSE
;
4837 FreePool (AccessResults
);
4838 AccessResults
= NULL
;
4841 FreePool (ConfigAccessHandles
);
4848 This function processes the results of processing forms and routes it to the
4849 appropriate handlers or storage.
4851 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
4853 @param Configuration A null-terminated Unicode string in
4854 <MulltiConfigResp> format.
4855 @param Progress A pointer to a string filled in with the offset of
4856 the most recent & before the first failing name /
4857 value pair (or the beginning of the string if the
4858 failure is in the first name / value pair) or the
4859 terminating NULL if all was successful.
4861 @retval EFI_SUCCESS The results have been distributed or are awaiting
4863 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
4864 results that must be stored awaiting possible
4866 @retval EFI_INVALID_PARAMETER Passing in a NULL for the Configuration parameter
4867 would result in this type of error.
4868 @retval EFI_NOT_FOUND Target for the specified routing data was not
4874 HiiConfigRoutingRouteConfig (
4875 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
4876 IN CONST EFI_STRING Configuration
,
4877 OUT EFI_STRING
*Progress
4880 HII_DATABASE_PRIVATE_DATA
*Private
;
4881 EFI_STRING StringPtr
;
4882 EFI_STRING ConfigResp
;
4885 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
4886 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
4888 HII_DATABASE_RECORD
*Database
;
4889 UINT8
*DevicePathPkg
;
4890 UINT8
*CurrentDevicePath
;
4891 EFI_HANDLE DriverHandle
;
4892 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
4893 EFI_STRING AccessProgress
;
4894 EFI_IFR_VARSTORE_EFI
*EfiVarStoreInfo
;
4895 BOOLEAN IsEfiVarstore
;
4896 UINTN DevicePathSize
;
4898 if (This
== NULL
|| Progress
== NULL
) {
4899 return EFI_INVALID_PARAMETER
;
4902 if (Configuration
== NULL
) {
4904 return EFI_INVALID_PARAMETER
;
4907 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
4908 StringPtr
= Configuration
;
4909 *Progress
= StringPtr
;
4911 AccessProgress
= NULL
;
4912 EfiVarStoreInfo
= NULL
;
4913 IsEfiVarstore
= FALSE
;
4916 // The first element of <MultiConfigResp> should be
4917 // <GuidHdr>, which is in 'GUID='<Guid> syntax.
4919 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
4920 return EFI_INVALID_PARAMETER
;
4923 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) == 0) {
4925 // If parsing error, set Progress to the beginning of the <MultiConfigResp>
4926 // or most recent & before the error.
4928 if (StringPtr
== Configuration
) {
4929 *Progress
= StringPtr
;
4931 *Progress
= StringPtr
- 1;
4935 // Process each <ConfigResp> of <MultiConfigResp>
4937 Length
= CalculateConfigStringLen (StringPtr
);
4938 ConfigResp
= AllocateCopyPool ((Length
+ 1) * sizeof (CHAR16
), StringPtr
);
4939 if (ConfigResp
== NULL
) {
4940 return EFI_OUT_OF_RESOURCES
;
4943 // Append '\0' to the end of ConfigRequest
4945 *(ConfigResp
+ Length
) = 0;
4948 // Get the UEFI device path
4950 Status
= GetDevicePath (ConfigResp
, (UINT8
**) &DevicePath
);
4951 if (EFI_ERROR (Status
)) {
4952 FreePool (ConfigResp
);
4957 // Find driver which matches the routing data.
4959 DriverHandle
= NULL
;
4960 for (Link
= Private
->DatabaseList
.ForwardLink
;
4961 Link
!= &Private
->DatabaseList
;
4962 Link
= Link
->ForwardLink
4964 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
4966 if ((DevicePathPkg
= Database
->PackageList
->DevicePathPkg
) != NULL
) {
4967 CurrentDevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
4968 DevicePathSize
= GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) CurrentDevicePath
);
4969 if ((CompareMem (DevicePath
,CurrentDevicePath
,DevicePathSize
) == 0) && IsThisPackageList(Database
, ConfigResp
)) {
4970 DriverHandle
= Database
->DriverHandle
;
4977 // Try to find driver handle by device path.
4979 if (DriverHandle
== NULL
) {
4980 TempDevicePath
= DevicePath
;
4981 Status
= gBS
->LocateDevicePath (
4982 &gEfiDevicePathProtocolGuid
,
4986 if (EFI_ERROR (Status
) || (DriverHandle
== NULL
)) {
4988 // Routing data does not match any known driver.
4989 // Set Progress to the 'G' in "GUID" of the routing header.
4991 FreePool (DevicePath
);
4992 *Progress
= StringPtr
;
4993 FreePool (ConfigResp
);
4994 return EFI_NOT_FOUND
;
4998 FreePool (DevicePath
);
5001 // Check whether this ConfigRequest is search from Efi varstore type storage.
5003 Status
= GetVarStoreType(Database
, ConfigResp
, &IsEfiVarstore
, &EfiVarStoreInfo
);
5004 if (EFI_ERROR (Status
)) {
5008 if (IsEfiVarstore
) {
5010 // Call the SetVariable function to route settings.
5012 Status
= RouteConfigRespForEfiVarStore(This
, EfiVarStoreInfo
, ConfigResp
, &AccessProgress
);
5013 FreePool (EfiVarStoreInfo
);
5016 // Call corresponding ConfigAccess protocol to route settings
5018 Status
= gBS
->HandleProtocol (
5020 &gEfiHiiConfigAccessProtocolGuid
,
5021 (VOID
**) &ConfigAccess
5023 if (EFI_ERROR (Status
)) {
5024 *Progress
= StringPtr
;
5025 FreePool (ConfigResp
);
5026 return EFI_NOT_FOUND
;
5029 Status
= ConfigAccess
->RouteConfig (
5035 if (EFI_ERROR (Status
)) {
5036 ASSERT (AccessProgress
!= NULL
);
5038 // AccessProgress indicates the parsing progress on <ConfigResp>.
5039 // Map it to the progress on <MultiConfigResp> then return it.
5041 *Progress
= StrStr (StringPtr
, AccessProgress
);
5043 FreePool (ConfigResp
);
5047 FreePool (ConfigResp
);
5051 // Go to next <ConfigResp> (skip '&').
5053 StringPtr
+= Length
;
5054 if (*StringPtr
== 0) {
5055 *Progress
= StringPtr
;
5068 This helper function is to be called by drivers to map configuration data
5069 stored in byte array ("block") formats such as UEFI Variables into current
5070 configuration strings.
5072 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
5074 @param ConfigRequest A null-terminated Unicode string in
5075 <ConfigRequest> format.
5076 @param Block Array of bytes defining the block's configuration.
5077 @param BlockSize Length in bytes of Block.
5078 @param Config Filled-in configuration string. String allocated
5079 by the function. Returned only if call is
5080 successful. It is <ConfigResp> string format.
5081 @param Progress A pointer to a string filled in with the offset of
5082 the most recent & before the first failing
5083 name/value pair (or the beginning of the string if
5084 the failure is in the first name / value pair) or
5085 the terminating NULL if all was successful.
5087 @retval EFI_SUCCESS The request succeeded. Progress points to the null
5088 terminator at the end of the ConfigRequest
5090 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress
5091 points to the first character of ConfigRequest.
5092 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigRequest or
5093 Block parameter would result in this type of
5094 error. Progress points to the first character of
5096 @retval EFI_DEVICE_ERROR Block not large enough. Progress undefined.
5097 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted string.
5098 Block is left updated and Progress points at
5099 the "&" preceding the first non-<BlockName>.
5105 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
5106 IN CONST EFI_STRING ConfigRequest
,
5107 IN CONST UINT8
*Block
,
5108 IN CONST UINTN BlockSize
,
5109 OUT EFI_STRING
*Config
,
5110 OUT EFI_STRING
*Progress
5113 HII_DATABASE_PRIVATE_DATA
*Private
;
5114 EFI_STRING StringPtr
;
5122 EFI_STRING ValueStr
;
5123 EFI_STRING ConfigElement
;
5131 if (This
== NULL
|| Progress
== NULL
|| Config
== NULL
) {
5132 return EFI_INVALID_PARAMETER
;
5135 if (Block
== NULL
|| ConfigRequest
== NULL
) {
5136 *Progress
= ConfigRequest
;
5137 return EFI_INVALID_PARAMETER
;
5141 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
5142 ASSERT (Private
!= NULL
);
5144 StringPtr
= ConfigRequest
;
5147 ConfigElement
= NULL
;
5150 // Allocate a fix length of memory to store Results. Reallocate memory for
5151 // Results if this fix length is insufficient.
5153 *Config
= (EFI_STRING
) AllocateZeroPool (MAX_STRING_LENGTH
);
5154 if (*Config
== NULL
) {
5155 return EFI_OUT_OF_RESOURCES
;
5161 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
5162 *Progress
= StringPtr
;
5163 Status
= EFI_INVALID_PARAMETER
;
5166 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"PATH=", StrLen (L
"PATH=")) != 0) {
5169 if (*StringPtr
== 0) {
5170 *Progress
= StringPtr
- 1;
5171 Status
= EFI_INVALID_PARAMETER
;
5175 while (*StringPtr
!= L
'&' && *StringPtr
!= 0) {
5178 if (*StringPtr
== 0) {
5179 *Progress
= StringPtr
;
5181 AppendToMultiString(Config
, ConfigRequest
);
5182 HiiToLower (*Config
);
5192 // Copy <ConfigHdr> and an additional '&' to <ConfigResp>
5194 TemChar
= *StringPtr
;
5196 AppendToMultiString(Config
, ConfigRequest
);
5197 *StringPtr
= TemChar
;
5200 // Parse each <RequestElement> if exists
5201 // Only <BlockName> format is supported by this help function.
5202 // <BlockName> ::= 'OFFSET='<Number>&'WIDTH='<Number>
5204 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"OFFSET=", StrLen (L
"OFFSET=")) == 0) {
5206 // Back up the header of one <BlockName>
5210 StringPtr
+= StrLen (L
"OFFSET=");
5214 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
5215 if (EFI_ERROR (Status
)) {
5216 *Progress
= TmpPtr
- 1;
5223 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
5225 FreePool (TmpBuffer
);
5227 StringPtr
+= Length
;
5228 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
5229 *Progress
= TmpPtr
- 1;
5230 Status
= EFI_INVALID_PARAMETER
;
5233 StringPtr
+= StrLen (L
"&WIDTH=");
5238 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
5239 if (EFI_ERROR (Status
)) {
5240 *Progress
= TmpPtr
- 1;
5247 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
5249 FreePool (TmpBuffer
);
5251 StringPtr
+= Length
;
5252 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
5253 *Progress
= TmpPtr
- 1;
5254 Status
= EFI_INVALID_PARAMETER
;
5259 // Calculate Value and convert it to hex string.
5261 if (Offset
+ Width
> BlockSize
) {
5262 *Progress
= StringPtr
;
5263 Status
= EFI_DEVICE_ERROR
;
5267 Value
= (UINT8
*) AllocateZeroPool (Width
);
5268 if (Value
== NULL
) {
5269 *Progress
= ConfigRequest
;
5270 Status
= EFI_OUT_OF_RESOURCES
;
5274 CopyMem (Value
, (UINT8
*) Block
+ Offset
, Width
);
5276 Length
= Width
* 2 + 1;
5277 ValueStr
= (EFI_STRING
) AllocateZeroPool (Length
* sizeof (CHAR16
));
5278 if (ValueStr
== NULL
) {
5279 *Progress
= ConfigRequest
;
5280 Status
= EFI_OUT_OF_RESOURCES
;
5284 TemString
= ValueStr
;
5285 TemBuffer
= Value
+ Width
- 1;
5286 for (Index
= 0; Index
< Width
; Index
++, TemBuffer
--) {
5287 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
5294 // Build a ConfigElement
5296 Length
+= StringPtr
- TmpPtr
+ 1 + StrLen (L
"VALUE=");
5297 ConfigElement
= (EFI_STRING
) AllocateZeroPool (Length
* sizeof (CHAR16
));
5298 if (ConfigElement
== NULL
) {
5299 Status
= EFI_OUT_OF_RESOURCES
;
5302 CopyMem (ConfigElement
, TmpPtr
, (StringPtr
- TmpPtr
+ 1) * sizeof (CHAR16
));
5303 if (*StringPtr
== 0) {
5304 *(ConfigElement
+ (StringPtr
- TmpPtr
)) = L
'&';
5306 *(ConfigElement
+ (StringPtr
- TmpPtr
) + 1) = 0;
5307 StrCatS (ConfigElement
, Length
, L
"VALUE=");
5308 StrCatS (ConfigElement
, Length
, ValueStr
);
5310 AppendToMultiString (Config
, ConfigElement
);
5312 FreePool (ConfigElement
);
5313 FreePool (ValueStr
);
5314 ConfigElement
= NULL
;
5318 // If '\0', parsing is finished. Otherwise skip '&' to continue
5320 if (*StringPtr
== 0) {
5323 AppendToMultiString (Config
, L
"&");
5328 if (*StringPtr
!= 0) {
5329 *Progress
= StringPtr
- 1;
5330 Status
= EFI_INVALID_PARAMETER
;
5334 HiiToLower (*Config
);
5335 *Progress
= StringPtr
;
5339 if (*Config
!= NULL
) {
5343 if (ValueStr
!= NULL
) {
5344 FreePool (ValueStr
);
5346 if (Value
!= NULL
) {
5349 if (ConfigElement
!= NULL
) {
5350 FreePool (ConfigElement
);
5359 This helper function is to be called by drivers to map configuration strings
5360 to configurations stored in byte array ("block") formats such as UEFI Variables.
5362 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
5364 @param ConfigResp A null-terminated Unicode string in <ConfigResp>
5366 @param Block A possibly null array of bytes representing the
5367 current block. Only bytes referenced in the
5368 ConfigResp string in the block are modified. If
5369 this parameter is null or if the *BlockSize
5370 parameter is (on input) shorter than required by
5371 the Configuration string, only the BlockSize
5372 parameter is updated and an appropriate status
5373 (see below) is returned.
5374 @param BlockSize The length of the Block in units of UINT8. On
5375 input, this is the size of the Block. On output,
5376 if successful, contains the largest index of the
5377 modified byte in the Block, or the required buffer
5378 size if the Block is not large enough.
5379 @param Progress On return, points to an element of the ConfigResp
5380 string filled in with the offset of the most
5381 recent '&' before the first failing name / value
5382 pair (or the beginning of the string if the
5383 failure is in the first name / value pair) or the
5384 terminating NULL if all was successful.
5386 @retval EFI_SUCCESS The request succeeded. Progress points to the null
5387 terminator at the end of the ConfigResp string.
5388 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress
5389 points to the first character of ConfigResp.
5390 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigResp or
5391 Block parameter would result in this type of
5392 error. Progress points to the first character of
5394 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted name /
5395 value pair. Block is left updated and
5396 Progress points at the '&' preceding the first
5398 @retval EFI_BUFFER_TOO_SMALL Block not large enough. Progress undefined.
5399 BlockSize is updated with the required buffer size.
5400 @retval EFI_NOT_FOUND Target for the specified routing data was not found.
5401 Progress points to the "G" in "GUID" of the errant
5408 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
5409 IN CONST EFI_STRING ConfigResp
,
5410 IN OUT UINT8
*Block
,
5411 IN OUT UINTN
*BlockSize
,
5412 OUT EFI_STRING
*Progress
5415 HII_DATABASE_PRIVATE_DATA
*Private
;
5416 EFI_STRING StringPtr
;
5429 if (This
== NULL
|| BlockSize
== NULL
|| Progress
== NULL
) {
5430 return EFI_INVALID_PARAMETER
;
5433 *Progress
= ConfigResp
;
5434 if (ConfigResp
== NULL
) {
5435 return EFI_INVALID_PARAMETER
;
5438 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
5439 ASSERT (Private
!= NULL
);
5441 StringPtr
= ConfigResp
;
5442 BufferSize
= *BlockSize
;
5449 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
5450 *Progress
= StringPtr
;
5451 Status
= EFI_INVALID_PARAMETER
;
5454 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"PATH=", StrLen (L
"PATH=")) != 0) {
5457 if (*StringPtr
== 0) {
5458 *Progress
= StringPtr
;
5459 Status
= EFI_INVALID_PARAMETER
;
5463 while (*StringPtr
!= L
'&' && *StringPtr
!= 0) {
5466 if (*StringPtr
== 0) {
5467 *Progress
= StringPtr
;
5468 Status
= EFI_INVALID_PARAMETER
;
5473 // Parse each <ConfigElement> if exists
5474 // Only '&'<BlockConfig> format is supported by this help function.
5475 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE='<Number>
5477 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) == 0) {
5479 StringPtr
+= StrLen (L
"&OFFSET=");
5483 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
5484 if (EFI_ERROR (Status
)) {
5492 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
5494 FreePool (TmpBuffer
);
5496 StringPtr
+= Length
;
5497 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
5499 Status
= EFI_INVALID_PARAMETER
;
5502 StringPtr
+= StrLen (L
"&WIDTH=");
5507 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
5508 if (EFI_ERROR (Status
)) {
5516 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
5518 FreePool (TmpBuffer
);
5520 StringPtr
+= Length
;
5521 if (StrnCmp (StringPtr
, L
"&VALUE=", StrLen (L
"&VALUE=")) != 0) {
5523 Status
= EFI_INVALID_PARAMETER
;
5526 StringPtr
+= StrLen (L
"&VALUE=");
5531 Status
= GetValueOfNumber (StringPtr
, &Value
, &Length
);
5532 if (EFI_ERROR (Status
)) {
5537 StringPtr
+= Length
;
5538 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
5540 Status
= EFI_INVALID_PARAMETER
;
5545 // Update the Block with configuration info
5547 if ((Block
!= NULL
) && (Offset
+ Width
<= BufferSize
)) {
5548 CopyMem (Block
+ Offset
, Value
, Width
);
5550 if (Offset
+ Width
> MaxBlockSize
) {
5551 MaxBlockSize
= Offset
+ Width
;
5558 // If '\0', parsing is finished.
5560 if (*StringPtr
== 0) {
5566 // The input string is not ConfigResp format, return error.
5568 if (*StringPtr
!= 0) {
5569 *Progress
= StringPtr
;
5570 Status
= EFI_INVALID_PARAMETER
;
5574 *Progress
= StringPtr
+ StrLen (StringPtr
);
5575 *BlockSize
= MaxBlockSize
- 1;
5577 if (MaxBlockSize
> BufferSize
) {
5578 *BlockSize
= MaxBlockSize
;
5579 if (Block
!= NULL
) {
5580 return EFI_BUFFER_TOO_SMALL
;
5584 if (Block
== NULL
) {
5585 *Progress
= ConfigResp
;
5586 return EFI_INVALID_PARAMETER
;
5593 if (Value
!= NULL
) {
5601 This helper function is to be called by drivers to extract portions of
5602 a larger configuration string.
5604 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
5606 @param Configuration A null-terminated Unicode string in
5607 <MultiConfigAltResp> format.
5608 @param Guid A pointer to the GUID value to search for in the
5609 routing portion of the ConfigResp string when
5610 retrieving the requested data. If Guid is NULL,
5611 then all GUID values will be searched for.
5612 @param Name A pointer to the NAME value to search for in the
5613 routing portion of the ConfigResp string when
5614 retrieving the requested data. If Name is NULL,
5615 then all Name values will be searched for.
5616 @param DevicePath A pointer to the PATH value to search for in the
5617 routing portion of the ConfigResp string when
5618 retrieving the requested data. If DevicePath is
5619 NULL, then all DevicePath values will be searched
5621 @param AltCfgId A pointer to the ALTCFG value to search for in the
5622 routing portion of the ConfigResp string when
5623 retrieving the requested data. If this parameter
5624 is NULL, then the current setting will be
5626 @param AltCfgResp A pointer to a buffer which will be allocated by
5627 the function which contains the retrieved string
5628 as requested. This buffer is only allocated if
5629 the call was successful. It is <ConfigResp> format.
5631 @retval EFI_SUCCESS The request succeeded. The requested data was
5632 extracted and placed in the newly allocated
5634 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate AltCfgResp.
5635 @retval EFI_INVALID_PARAMETER Any parameter is invalid.
5636 @retval EFI_NOT_FOUND Target for the specified routing data was not
5643 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
5644 IN CONST EFI_STRING Configuration
,
5645 IN CONST EFI_GUID
*Guid
,
5646 IN CONST EFI_STRING Name
,
5647 IN CONST EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
5648 IN CONST UINT16
*AltCfgId
,
5649 OUT EFI_STRING
*AltCfgResp
5653 EFI_STRING StringPtr
;
5654 EFI_STRING HdrStart
;
5661 EFI_STRING AltIdStr
;
5678 if (This
== NULL
|| Configuration
== NULL
|| AltCfgResp
== NULL
) {
5679 return EFI_INVALID_PARAMETER
;
5682 StringPtr
= Configuration
;
5683 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
5684 return EFI_INVALID_PARAMETER
;
5688 // Generate the sub string for later matching.
5690 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*) Guid
, 1, &GuidStr
);
5693 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) DevicePath
),
5694 (VOID
*) DevicePath
,
5698 if (AltCfgId
!= NULL
) {
5699 GenerateSubStr (L
"ALTCFG=", sizeof (UINT16
), (VOID
*) AltCfgId
, 3, &AltIdStr
);
5702 GenerateSubStr (L
"NAME=", StrLen (Name
) * sizeof (CHAR16
), (VOID
*) Name
, 2, &NameStr
);
5704 GenerateSubStr (L
"NAME=", 0, NULL
, 2, &NameStr
);
5707 while (*StringPtr
!= 0) {
5709 // Try to match the GUID
5712 TmpPtr
= StrStr (StringPtr
, GuidStr
);
5713 if (TmpPtr
== NULL
) {
5714 Status
= EFI_NOT_FOUND
;
5720 // Jump to <NameHdr>
5723 StringPtr
= TmpPtr
+ StrLen (GuidStr
);
5725 StringPtr
= StrStr (TmpPtr
, L
"NAME=");
5726 if (StringPtr
== NULL
) {
5727 Status
= EFI_NOT_FOUND
;
5735 // Try to match the NAME
5737 if (GuidFlag
&& !NameFlag
) {
5738 if (StrnCmp (StringPtr
, NameStr
, StrLen (NameStr
)) != 0) {
5742 // Jump to <PathHdr>
5745 StringPtr
+= StrLen (NameStr
);
5747 StringPtr
= StrStr (StringPtr
, L
"PATH=");
5748 if (StringPtr
== NULL
) {
5749 Status
= EFI_NOT_FOUND
;
5758 // Try to match the DevicePath
5760 if (GuidFlag
&& NameFlag
&& !PathFlag
) {
5761 if (StrnCmp (StringPtr
, PathStr
, StrLen (PathStr
)) != 0) {
5766 // Jump to '&' before <DescHdr> or <ConfigBody>
5768 if (DevicePath
!= NULL
) {
5769 StringPtr
+= StrLen (PathStr
);
5771 StringPtr
= StrStr (StringPtr
, L
"&");
5772 if (StringPtr
== NULL
) {
5773 Status
= EFI_NOT_FOUND
;
5784 // Try to match the AltCfgId
5786 if (GuidFlag
&& NameFlag
&& PathFlag
) {
5787 if (AltCfgId
== NULL
) {
5789 // Return Current Setting when AltCfgId is NULL.
5791 Status
= OutputConfigBody (StringPtr
, &Result
);
5795 // Search the <ConfigAltResp> to get the <AltResp> with AltCfgId.
5797 if (StrnCmp (StringPtr
, AltIdStr
, StrLen (AltIdStr
)) != 0) {
5803 // Skip AltIdStr and &
5805 StringPtr
= StringPtr
+ StrLen (AltIdStr
);
5806 Status
= OutputConfigBody (StringPtr
, &Result
);
5812 Status
= EFI_NOT_FOUND
;
5816 if (!EFI_ERROR (Status
) && (Result
!= NULL
)) {
5818 // Copy the <ConfigHdr> and <ConfigBody>
5820 Length
= HdrEnd
- HdrStart
+ StrLen (Result
) + 1;
5821 *AltCfgResp
= AllocateZeroPool (Length
* sizeof (CHAR16
));
5822 if (*AltCfgResp
== NULL
) {
5823 Status
= EFI_OUT_OF_RESOURCES
;
5825 StrnCpyS (*AltCfgResp
, Length
, HdrStart
, HdrEnd
- HdrStart
);
5826 StrCatS (*AltCfgResp
, Length
, Result
);
5827 Status
= EFI_SUCCESS
;
5831 if (GuidStr
!= NULL
) {
5834 if (NameStr
!= NULL
) {
5837 if (PathStr
!= NULL
) {
5840 if (AltIdStr
!= NULL
) {
5841 FreePool (AltIdStr
);
5843 if (Result
!= NULL
) {