2 Implementation of interfaces function for EFI_HII_CONFIG_ROUTING_PROTOCOL.
4 Copyright (c) 2007 - 2017, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 #include "HiiDatabase.h"
17 extern HII_DATABASE_PRIVATE_DATA mPrivate
;
20 Calculate the number of Unicode characters of the incoming Configuration string,
21 not including NULL terminator.
23 This is a internal function.
25 @param String String in <MultiConfigRequest> or
26 <MultiConfigResp> format.
28 @return The number of Unicode characters.
32 CalculateConfigStringLen (
39 // "GUID=" should be the first element of incoming string.
41 ASSERT (String
!= NULL
);
42 ASSERT (StrnCmp (String
, L
"GUID=", StrLen (L
"GUID=")) == 0);
45 // The beginning of next <ConfigRequest>/<ConfigResp> should be "&GUID=".
46 // Will meet '\0' if there is only one <ConfigRequest>/<ConfigResp>.
48 TmpPtr
= StrStr (String
, L
"&GUID=");
50 return StrLen (String
);
53 return (TmpPtr
- String
);
58 Convert the hex UNICODE %02x encoding of a UEFI device path to binary
59 from <PathHdr> of <ConfigHdr>.
61 This is a internal function.
63 @param String UEFI configuration string
64 @param DevicePathData Binary of a UEFI device path.
66 @retval EFI_NOT_FOUND The device path is not invalid.
67 @retval EFI_INVALID_PARAMETER Any incoming parameter is invalid.
68 @retval EFI_OUT_OF_RESOURCES Lake of resources to store necessary structures.
69 @retval EFI_SUCCESS The device path is retrieved and translated to
76 OUT UINT8
**DevicePathData
81 UINT8
*DevicePathBuffer
;
85 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
88 if (String
== NULL
|| DevicePathData
== NULL
) {
89 return EFI_INVALID_PARAMETER
;
93 // Find the 'PATH=' of <PathHdr> and skip it.
95 for (; (*String
!= 0 && StrnCmp (String
, L
"PATH=", StrLen (L
"PATH=")) != 0); String
++);
97 return EFI_INVALID_PARAMETER
;
100 // Check whether path data does exist.
102 String
+= StrLen (L
"PATH=");
104 return EFI_INVALID_PARAMETER
;
109 // The content between 'PATH=' of <ConfigHdr> and '&' of next element
110 // or '\0' (end of configuration string) is the UNICODE %02x bytes encoding
111 // of UEFI device path.
113 for (Length
= 0; *String
!= 0 && *String
!= L
'&'; String
++, Length
++);
115 // Check DevicePath Length
117 if (((Length
+ 1) / 2) < sizeof (EFI_DEVICE_PATH_PROTOCOL
)) {
118 return EFI_NOT_FOUND
;
122 // The data in <PathHdr> is encoded as hex UNICODE %02x bytes in the same order
123 // as the device path resides in RAM memory.
124 // Translate the data into binary.
126 DevicePathBuffer
= (UINT8
*) AllocateZeroPool ((Length
+ 1) / 2);
127 if (DevicePathBuffer
== NULL
) {
128 return EFI_OUT_OF_RESOURCES
;
132 // Convert DevicePath
134 ZeroMem (TemStr
, sizeof (TemStr
));
135 for (Index
= 0; Index
< Length
; Index
++) {
136 TemStr
[0] = PathHdr
[Index
];
137 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
138 if ((Index
& 1) == 0) {
139 DevicePathBuffer
[Index
/2] = DigitUint8
;
141 DevicePathBuffer
[Index
/2] = (UINT8
) ((DevicePathBuffer
[Index
/2] << 4) + DigitUint8
);
146 // Validate DevicePath
148 DevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) DevicePathBuffer
;
149 while (!IsDevicePathEnd (DevicePath
)) {
150 if ((DevicePath
->Type
== 0) || (DevicePath
->SubType
== 0) || (DevicePathNodeLength (DevicePath
) < sizeof (EFI_DEVICE_PATH_PROTOCOL
))) {
152 // Invalid device path
154 FreePool (DevicePathBuffer
);
155 return EFI_NOT_FOUND
;
157 DevicePath
= NextDevicePathNode (DevicePath
);
161 // return the device path
163 *DevicePathData
= DevicePathBuffer
;
168 Converts the unicode character of the string from uppercase to lowercase.
169 This is a internal function.
171 @param ConfigString String to be converted
177 IN EFI_STRING ConfigString
183 ASSERT (ConfigString
!= NULL
);
186 // Convert all hex digits in range [A-F] in the configuration header to [a-f]
188 for (String
= ConfigString
, Lower
= FALSE
; *String
!= L
'\0'; String
++) {
189 if (*String
== L
'=') {
191 } else if (*String
== L
'&') {
193 } else if (Lower
&& *String
>= L
'A' && *String
<= L
'F') {
194 *String
= (CHAR16
) (*String
- L
'A' + L
'a');
202 Generate a sub string then output it.
204 This is a internal function.
206 @param String A constant string which is the prefix of the to be
207 generated string, e.g. GUID=
209 @param BufferLen The length of the Buffer in bytes.
211 @param Buffer Points to a buffer which will be converted to be the
212 content of the generated string.
214 @param Flag If 1, the buffer contains data for the value of GUID or PATH stored in
215 UINT8 *; if 2, the buffer contains unicode string for the value of NAME;
216 if 3, the buffer contains other data.
218 @param SubStr Points to the output string. It's caller's
219 responsibility to free this buffer.
225 IN CONST EFI_STRING String
,
229 OUT EFI_STRING
*SubStr
234 EFI_STRING StringHeader
;
240 ASSERT (String
!= NULL
&& SubStr
!= NULL
);
242 if (Buffer
== NULL
) {
243 *SubStr
= AllocateCopyPool (StrSize (String
), String
);
244 ASSERT (*SubStr
!= NULL
);
249 // Header + Data + '&' + '\0'
251 Length
= StrLen (String
) + BufferLen
* 2 + 1 + 1;
252 Str
= AllocateZeroPool (Length
* sizeof (CHAR16
));
253 ASSERT (Str
!= NULL
);
255 StrCpyS (Str
, Length
, String
);
257 StringHeader
= Str
+ StrLen (String
);
258 TemString
= (CHAR16
*) StringHeader
;
263 // Convert Buffer to Hex String in reverse order
265 TemBuffer
= ((UINT8
*) Buffer
);
266 for (Index
= 0; Index
< BufferLen
; Index
++, TemBuffer
++) {
267 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 necessary
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 necessary 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 necessary 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 necessary 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 necessary
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 request 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.
1154 // When default types are DEFAULT_VALUE_FROM_OTHER_DEFAULT, the default value can be overrode.
1156 if ((DefaultValueData
->Type
> DefaultValueArray
->Type
) || (DefaultValueData
->Type
== DefaultValueArray
->Type
&& DefaultValueData
->Type
== DefaultValueFromOtherDefault
)) {
1158 // Update the default value array in BlockData.
1160 CopyMem (&DefaultValueArray
->Value
, &DefaultValueData
->Value
, sizeof (EFI_IFR_TYPE_VALUE
));
1161 DefaultValueArray
->Type
= DefaultValueData
->Type
;
1162 DefaultValueArray
->Cleaned
= DefaultValueData
->Cleaned
;
1169 // Insert new default value data in tail.
1171 DefaultValueArray
= AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
1172 ASSERT (DefaultValueArray
!= NULL
);
1173 CopyMem (DefaultValueArray
, DefaultValueData
, sizeof (IFR_DEFAULT_DATA
));
1174 InsertTailList (Link
, &DefaultValueArray
->Entry
);
1178 This function inserts new BlockData into the block link
1180 @param BlockLink The list entry points to block array.
1181 @param BlockData The point to BlockData is added.
1186 IN LIST_ENTRY
*BlockLink
,
1187 IN IFR_BLOCK_DATA
**BlockData
1191 IFR_BLOCK_DATA
*BlockArray
;
1192 IFR_BLOCK_DATA
*BlockSingleData
;
1194 BlockSingleData
= *BlockData
;
1196 if (BlockSingleData
->Name
!= NULL
) {
1197 InsertTailList (BlockLink
, &BlockSingleData
->Entry
);
1202 // Insert block data in its Offset and Width order.
1204 for (Link
= BlockLink
->ForwardLink
; Link
!= BlockLink
; Link
= Link
->ForwardLink
) {
1205 BlockArray
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
1206 if (BlockArray
->Offset
== BlockSingleData
->Offset
) {
1207 if (BlockArray
->Width
> BlockSingleData
->Width
) {
1209 // Insert this block data in the front of block array
1211 InsertTailList (Link
, &BlockSingleData
->Entry
);
1215 if (BlockArray
->Width
== BlockSingleData
->Width
) {
1217 // The same block array has been added.
1219 if (BlockSingleData
!= BlockArray
) {
1220 FreePool (BlockSingleData
);
1221 *BlockData
= BlockArray
;
1225 } else if (BlockArray
->Offset
> BlockSingleData
->Offset
) {
1227 // Insert new block data in the front of block array
1229 InsertTailList (Link
, &BlockSingleData
->Entry
);
1235 // Add new block data into the tail.
1237 InsertTailList (Link
, &BlockSingleData
->Entry
);
1241 Retrieves a pointer to the a Null-terminated ASCII string containing the list
1242 of languages that an HII handle in the HII Database supports. The returned
1243 string is allocated using AllocatePool(). The caller is responsible for freeing
1244 the returned string using FreePool(). The format of the returned string follows
1245 the language format assumed the HII Database.
1247 If HiiHandle is NULL, then ASSERT().
1249 @param[in] HiiHandle A handle that was previously registered in the HII Database.
1251 @retval NULL HiiHandle is not registered in the HII database
1252 @retval NULL There are not enough resources available to retrieve the supported
1254 @retval NULL The list of supported languages could not be retrieved.
1255 @retval Other A pointer to the Null-terminated ASCII string of supported languages.
1259 GetSupportedLanguages (
1260 IN EFI_HII_HANDLE HiiHandle
1265 CHAR8 TempSupportedLanguages
;
1266 CHAR8
*SupportedLanguages
;
1268 ASSERT (HiiHandle
!= NULL
);
1271 // Retrieve the size required for the supported languages buffer.
1274 Status
= mPrivate
.HiiString
.GetLanguages (&mPrivate
.HiiString
, HiiHandle
, &TempSupportedLanguages
, &LanguageSize
);
1277 // If GetLanguages() returns EFI_SUCCESS for a zero size,
1278 // then there are no supported languages registered for HiiHandle. If GetLanguages()
1279 // returns an error other than EFI_BUFFER_TOO_SMALL, then HiiHandle is not present
1280 // in the HII Database
1282 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
1284 // Return NULL if the size can not be retrieved, or if HiiHandle is not in the HII Database
1290 // Allocate the supported languages buffer.
1292 SupportedLanguages
= AllocateZeroPool (LanguageSize
);
1293 if (SupportedLanguages
== NULL
) {
1295 // Return NULL if allocation fails.
1301 // Retrieve the supported languages string
1303 Status
= mPrivate
.HiiString
.GetLanguages (&mPrivate
.HiiString
, HiiHandle
, SupportedLanguages
, &LanguageSize
);
1304 if (EFI_ERROR (Status
)) {
1306 // Free the buffer and return NULL if the supported languages can not be retrieved.
1308 FreePool (SupportedLanguages
);
1313 // Return the Null-terminated ASCII string of supported languages
1315 return SupportedLanguages
;
1319 Retrieves a string from a string package.
1321 If HiiHandle is NULL, then ASSERT().
1322 If StringId is 0, then ASSET.
1324 @param[in] HiiHandle A handle that was previously registered in the HII Database.
1325 @param[in] StringId The identifier of the string to retrieved from the string
1326 package associated with HiiHandle.
1328 @retval NULL The string specified by StringId is not present in the string package.
1329 @retval Other The string was returned.
1334 IN EFI_HII_HANDLE HiiHandle
,
1335 IN EFI_STRING_ID StringId
1342 CHAR8
*SupportedLanguages
;
1343 CHAR8
*PlatformLanguage
;
1344 CHAR8
*BestLanguage
;
1347 ASSERT (HiiHandle
!= NULL
);
1348 ASSERT (StringId
!= 0);
1351 // Initialize all allocated buffers to NULL
1353 SupportedLanguages
= NULL
;
1354 PlatformLanguage
= NULL
;
1355 BestLanguage
= NULL
;
1360 // Get the languages that the package specified by HiiHandle supports
1362 SupportedLanguages
= GetSupportedLanguages (HiiHandle
);
1363 if (SupportedLanguages
== NULL
) {
1368 // Get the current platform language setting
1370 GetEfiGlobalVariable2 (L
"PlatformLang", (VOID
**)&PlatformLanguage
, NULL
);
1373 // Get the best matching language from SupportedLanguages
1375 BestLanguage
= GetBestLanguage (
1377 FALSE
, // RFC 4646 mode
1378 Language
, // Highest priority
1379 PlatformLanguage
!= NULL
? PlatformLanguage
: "", // Next highest priority
1380 SupportedLanguages
, // Lowest priority
1383 if (BestLanguage
== NULL
) {
1388 // Retrieve the size of the string in the string package for the BestLanguage
1391 Status
= mPrivate
.HiiString
.GetString (
1392 &mPrivate
.HiiString
,
1401 // If GetString() returns EFI_SUCCESS for a zero size,
1402 // then there are no supported languages registered for HiiHandle. If GetString()
1403 // returns an error other than EFI_BUFFER_TOO_SMALL, then HiiHandle is not present
1404 // in the HII Database
1406 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
1411 // Allocate a buffer for the return string
1413 String
= AllocateZeroPool (StringSize
);
1414 if (String
== NULL
) {
1419 // Retrieve the string from the string package
1421 Status
= mPrivate
.HiiString
.GetString (
1422 &mPrivate
.HiiString
,
1430 if (EFI_ERROR (Status
)) {
1432 // Free the buffer and return NULL if the supported languages can not be retrieved.
1440 // Free allocated buffers
1442 if (SupportedLanguages
!= NULL
) {
1443 FreePool (SupportedLanguages
);
1445 if (PlatformLanguage
!= NULL
) {
1446 FreePool (PlatformLanguage
);
1448 if (BestLanguage
!= NULL
) {
1449 FreePool (BestLanguage
);
1453 // Return the Null-terminated Unicode string
1459 This function checks VarOffset and VarWidth is in the block range.
1461 @param RequestBlockArray The block array is to be checked.
1462 @param VarOffset Offset of var to the structure
1463 @param VarWidth Width of var.
1464 @param IsNameValueType Whether this varstore is name/value varstore or not.
1465 @param HiiHandle Hii handle for this hii package.
1467 @retval TRUE This Var is in the block range.
1468 @retval FALSE This Var is not in the block range.
1472 IN IFR_BLOCK_DATA
*RequestBlockArray
,
1473 IN UINT16 VarOffset
,
1475 IN BOOLEAN IsNameValueType
,
1476 IN EFI_HII_HANDLE HiiHandle
1480 IFR_BLOCK_DATA
*BlockData
;
1484 // No Request Block array, all vars are got.
1486 if (RequestBlockArray
== NULL
) {
1491 // Check the input var is in the request block range.
1493 for (Link
= RequestBlockArray
->Entry
.ForwardLink
; Link
!= &RequestBlockArray
->Entry
; Link
= Link
->ForwardLink
) {
1494 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
1496 if (IsNameValueType
) {
1497 Name
= InternalGetString (HiiHandle
, VarOffset
);
1498 ASSERT (Name
!= NULL
);
1500 if (StrnCmp (BlockData
->Name
, Name
, StrLen (Name
)) == 0) {
1506 if ((VarOffset
>= BlockData
->Offset
) && ((VarOffset
+ VarWidth
) <= (BlockData
->Offset
+ BlockData
->Width
))) {
1516 Get form package data from data base.
1518 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
1519 @param HiiFormPackage The buffer saves the package data.
1520 @param PackageSize The buffer size of the package data.
1524 GetFormPackageData (
1525 IN HII_DATABASE_RECORD
*DataBaseRecord
,
1526 IN OUT UINT8
**HiiFormPackage
,
1527 OUT UINTN
*PackageSize
1534 if (DataBaseRecord
== NULL
|| HiiFormPackage
== NULL
|| PackageSize
== NULL
) {
1535 return EFI_INVALID_PARAMETER
;
1541 // 0. Get Hii Form Package by HiiHandle
1543 Status
= ExportFormPackages (
1545 DataBaseRecord
->Handle
,
1546 DataBaseRecord
->PackageList
,
1552 if (EFI_ERROR (Status
)) {
1556 (*HiiFormPackage
) = AllocatePool (ResultSize
);
1557 if (*HiiFormPackage
== NULL
) {
1558 Status
= EFI_OUT_OF_RESOURCES
;
1563 // Get HiiFormPackage by HiiHandle
1567 Status
= ExportFormPackages (
1569 DataBaseRecord
->Handle
,
1570 DataBaseRecord
->PackageList
,
1576 if (EFI_ERROR (Status
)) {
1577 FreePool (*HiiFormPackage
);
1580 *PackageSize
= Size
;
1587 This function parses Form Package to get the efi varstore info according to the request ConfigHdr.
1589 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
1590 @param ConfigHdr Request string ConfigHdr. If it is NULL,
1591 the first found varstore will be as ConfigHdr.
1592 @param IsEfiVarstore Whether the request storage type is efi varstore type.
1593 @param EfiVarStore The efi varstore info which will return.
1597 IN HII_DATABASE_RECORD
*DataBaseRecord
,
1598 IN EFI_STRING ConfigHdr
,
1599 OUT BOOLEAN
*IsEfiVarstore
,
1600 OUT EFI_IFR_VARSTORE_EFI
**EfiVarStore
1605 UINTN PackageOffset
;
1606 EFI_IFR_OP_HEADER
*IfrOpHdr
;
1607 CHAR16
*VarStoreName
;
1613 UINT8
*HiiFormPackage
;
1615 EFI_IFR_VARSTORE_EFI
*IfrEfiVarStore
;
1616 EFI_HII_PACKAGE_HEADER
*PackageHeader
;
1618 HiiFormPackage
= NULL
;
1620 Status
= EFI_SUCCESS
;
1624 *IsEfiVarstore
= FALSE
;
1626 Status
= GetFormPackageData(DataBaseRecord
, &HiiFormPackage
, &PackageSize
);
1627 if (EFI_ERROR (Status
)) {
1631 IfrOffset
= sizeof (EFI_HII_PACKAGE_HEADER
);
1632 PackageOffset
= IfrOffset
;
1633 PackageHeader
= (EFI_HII_PACKAGE_HEADER
*) HiiFormPackage
;
1635 while (IfrOffset
< PackageSize
) {
1637 // More than one form packages exist.
1639 if (PackageOffset
>= PackageHeader
->Length
) {
1641 // Process the new form package.
1643 PackageOffset
= sizeof (EFI_HII_PACKAGE_HEADER
);
1644 IfrOffset
+= PackageOffset
;
1645 PackageHeader
= (EFI_HII_PACKAGE_HEADER
*) (HiiFormPackage
+ IfrOffset
);
1648 IfrOpHdr
= (EFI_IFR_OP_HEADER
*) (HiiFormPackage
+ IfrOffset
);
1649 IfrOffset
+= IfrOpHdr
->Length
;
1650 PackageOffset
+= IfrOpHdr
->Length
;
1652 if (IfrOpHdr
->OpCode
== EFI_IFR_VARSTORE_EFI_OP
) {
1653 IfrEfiVarStore
= (EFI_IFR_VARSTORE_EFI
*) IfrOpHdr
;
1655 // If the length is small than the structure, this is from old efi
1656 // varstore definition. Old efi varstore get config directly from
1657 // GetVariable function.
1659 if (IfrOpHdr
->Length
< sizeof (EFI_IFR_VARSTORE_EFI
)) {
1663 NameSize
= AsciiStrSize ((CHAR8
*)IfrEfiVarStore
->Name
);
1664 VarStoreName
= AllocateZeroPool (NameSize
* sizeof (CHAR16
));
1665 if (VarStoreName
== NULL
) {
1666 Status
= EFI_OUT_OF_RESOURCES
;
1669 AsciiStrToUnicodeStrS ((CHAR8
*) IfrEfiVarStore
->Name
, VarStoreName
, NameSize
);
1671 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*) &IfrEfiVarStore
->Guid
, 1, &GuidStr
);
1672 GenerateSubStr (L
"NAME=", StrLen (VarStoreName
) * sizeof (CHAR16
), (VOID
*) VarStoreName
, 2, &NameStr
);
1673 LengthString
= StrLen (GuidStr
);
1674 LengthString
= LengthString
+ StrLen (NameStr
) + 1;
1675 TempStr
= AllocateZeroPool (LengthString
* sizeof (CHAR16
));
1676 if (TempStr
== NULL
) {
1679 FreePool (VarStoreName
);
1680 Status
= EFI_OUT_OF_RESOURCES
;
1683 StrCpyS (TempStr
, LengthString
, GuidStr
);
1684 StrCatS (TempStr
, LengthString
, NameStr
);
1685 if (ConfigHdr
== NULL
|| StrnCmp (ConfigHdr
, TempStr
, StrLen (TempStr
)) == 0) {
1686 *EfiVarStore
= (EFI_IFR_VARSTORE_EFI
*) AllocateZeroPool (IfrOpHdr
->Length
);
1687 if (*EfiVarStore
== NULL
) {
1688 FreePool (VarStoreName
);
1692 Status
= EFI_OUT_OF_RESOURCES
;
1695 *IsEfiVarstore
= TRUE
;
1696 CopyMem (*EfiVarStore
, IfrEfiVarStore
, IfrOpHdr
->Length
);
1700 // Free allocated temp string.
1702 FreePool (VarStoreName
);
1708 // Already found the varstore, break;
1710 if (*IsEfiVarstore
) {
1716 if (HiiFormPackage
!= NULL
) {
1717 FreePool (HiiFormPackage
);
1724 Check whether the ConfigRequest string has the request elements.
1725 For EFI_HII_VARSTORE_BUFFER type, the request has "&OFFSET=****&WIDTH=****..." format.
1726 For EFI_HII_VARSTORE_NAME_VALUE type, the request has "&NAME1**&NAME2..." format.
1728 @param ConfigRequest The input config request string.
1730 @retval TRUE The input include config request elements.
1731 @retval FALSE The input string not includes.
1735 GetElementsFromRequest (
1736 IN EFI_STRING ConfigRequest
1739 EFI_STRING TmpRequest
;
1741 TmpRequest
= StrStr (ConfigRequest
, L
"PATH=");
1742 ASSERT (TmpRequest
!= NULL
);
1744 if ((StrStr (TmpRequest
, L
"&OFFSET=") != NULL
) || (StrStr (TmpRequest
, L
"&") != NULL
)) {
1752 Check whether the this varstore is the request varstore.
1754 @param VarstoreGuid Varstore guid.
1755 @param Name Varstore name.
1756 @param ConfigHdr Current configRequest info.
1758 @retval TRUE This varstore is the request one.
1759 @retval FALSE This varstore is not the request one.
1764 IN EFI_GUID
*VarstoreGuid
,
1766 IN CHAR16
*ConfigHdr
1780 // If ConfigHdr has name field and varstore not has name, return FALSE.
1782 if (Name
== NULL
&& ConfigHdr
!= NULL
&& StrStr (ConfigHdr
, L
"NAME=&") == NULL
) {
1786 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*)VarstoreGuid
, 1, &GuidStr
);
1788 GenerateSubStr (L
"NAME=", StrLen (Name
) * sizeof (CHAR16
), (VOID
*) Name
, 2, &NameStr
);
1790 GenerateSubStr (L
"NAME=", 0, NULL
, 2, &NameStr
);
1792 LengthString
= StrLen (GuidStr
);
1793 LengthString
= LengthString
+ StrLen (NameStr
) + 1;
1794 TempStr
= AllocateZeroPool (LengthString
* sizeof (CHAR16
));
1795 if (TempStr
== NULL
) {
1799 StrCpyS (TempStr
, LengthString
, GuidStr
);
1800 StrCatS (TempStr
, LengthString
, NameStr
);
1802 if (ConfigHdr
== NULL
|| StrnCmp (ConfigHdr
, TempStr
, StrLen (TempStr
)) == 0) {
1807 if (GuidStr
!= NULL
) {
1811 if (NameStr
!= NULL
) {
1815 if (TempStr
!= NULL
) {
1823 This function parses Form Package to get the efi varstore info according to the request ConfigHdr.
1825 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
1826 @param ConfigHdr Request string ConfigHdr. If it is NULL,
1827 the first found varstore will be as ConfigHdr.
1828 @retval TRUE This hii package is the request one.
1829 @retval FALSE This hii package is not the request one.
1833 IN HII_DATABASE_RECORD
*DataBaseRecord
,
1834 IN EFI_STRING ConfigHdr
1839 UINTN PackageOffset
;
1840 EFI_IFR_OP_HEADER
*IfrOpHdr
;
1841 CHAR16
*VarStoreName
;
1843 UINT8
*HiiFormPackage
;
1845 EFI_IFR_VARSTORE_EFI
*IfrEfiVarStore
;
1846 EFI_HII_PACKAGE_HEADER
*PackageHeader
;
1847 EFI_IFR_VARSTORE
*IfrVarStore
;
1848 EFI_IFR_VARSTORE_NAME_VALUE
*IfrNameValueVarStore
;
1849 BOOLEAN FindVarstore
;
1851 HiiFormPackage
= NULL
;
1852 VarStoreName
= NULL
;
1853 Status
= EFI_SUCCESS
;
1854 FindVarstore
= FALSE
;
1856 Status
= GetFormPackageData(DataBaseRecord
, &HiiFormPackage
, &PackageSize
);
1857 if (EFI_ERROR (Status
)) {
1861 IfrOffset
= sizeof (EFI_HII_PACKAGE_HEADER
);
1862 PackageOffset
= IfrOffset
;
1863 PackageHeader
= (EFI_HII_PACKAGE_HEADER
*) HiiFormPackage
;
1865 while (IfrOffset
< PackageSize
) {
1867 // More than one form packages exist.
1869 if (PackageOffset
>= PackageHeader
->Length
) {
1871 // Process the new form package.
1873 PackageOffset
= sizeof (EFI_HII_PACKAGE_HEADER
);
1874 IfrOffset
+= PackageOffset
;
1875 PackageHeader
= (EFI_HII_PACKAGE_HEADER
*) (HiiFormPackage
+ IfrOffset
);
1878 IfrOpHdr
= (EFI_IFR_OP_HEADER
*) (HiiFormPackage
+ IfrOffset
);
1879 IfrOffset
+= IfrOpHdr
->Length
;
1880 PackageOffset
+= IfrOpHdr
->Length
;
1882 switch (IfrOpHdr
->OpCode
) {
1884 case EFI_IFR_VARSTORE_OP
:
1885 IfrVarStore
= (EFI_IFR_VARSTORE
*) IfrOpHdr
;
1887 NameSize
= AsciiStrSize ((CHAR8
*)IfrVarStore
->Name
);
1888 VarStoreName
= AllocateZeroPool (NameSize
* sizeof (CHAR16
));
1889 if (VarStoreName
== NULL
) {
1892 AsciiStrToUnicodeStrS ((CHAR8
*)IfrVarStore
->Name
, VarStoreName
, NameSize
);
1894 if (IsThisVarstore((VOID
*)&IfrVarStore
->Guid
, VarStoreName
, ConfigHdr
)) {
1895 FindVarstore
= TRUE
;
1898 FreePool (VarStoreName
);
1899 VarStoreName
= NULL
;
1903 case EFI_IFR_VARSTORE_EFI_OP
:
1904 IfrEfiVarStore
= (EFI_IFR_VARSTORE_EFI
*) IfrOpHdr
;
1905 NameSize
= AsciiStrSize ((CHAR8
*)IfrEfiVarStore
->Name
);
1906 VarStoreName
= AllocateZeroPool (NameSize
* sizeof (CHAR16
));
1907 if (VarStoreName
== NULL
) {
1910 AsciiStrToUnicodeStrS ((CHAR8
*)IfrEfiVarStore
->Name
, VarStoreName
, NameSize
);
1912 if (IsThisVarstore (&IfrEfiVarStore
->Guid
, VarStoreName
, ConfigHdr
)) {
1913 FindVarstore
= TRUE
;
1916 FreePool (VarStoreName
);
1917 VarStoreName
= NULL
;
1921 case EFI_IFR_VARSTORE_NAME_VALUE_OP
:
1922 IfrNameValueVarStore
= (EFI_IFR_VARSTORE_NAME_VALUE
*) IfrOpHdr
;
1924 if (IsThisVarstore (&IfrNameValueVarStore
->Guid
, NULL
, ConfigHdr
)) {
1925 FindVarstore
= TRUE
;
1930 case EFI_IFR_FORM_OP
:
1931 case EFI_IFR_FORM_MAP_OP
:
1933 // No matched varstore is found and directly return.
1942 if (HiiFormPackage
!= NULL
) {
1943 FreePool (HiiFormPackage
);
1946 if (VarStoreName
!= NULL
) {
1947 FreePool (VarStoreName
);
1950 return FindVarstore
;
1954 Check whether the this op code is required.
1956 @param RequestBlockArray The array includes all the request info or NULL.
1957 @param HiiHandle The hii handle for this form package.
1958 @param VarStorageData The varstore data structure.
1959 @param IfrOpHdr Ifr opcode header for this opcode.
1960 @param VarWidth The buffer width for this opcode.
1961 @param ReturnData The data block added for this opcode.
1963 @retval EFI_SUCCESS This opcode is required.
1964 @retval EFI_NOT_FOUND This opcode is not required.
1965 @retval Others Contain some error.
1969 IsThisOpcodeRequired (
1970 IN IFR_BLOCK_DATA
*RequestBlockArray
,
1971 IN EFI_HII_HANDLE HiiHandle
,
1972 IN OUT IFR_VARSTORAGE_DATA
*VarStorageData
,
1973 IN EFI_IFR_OP_HEADER
*IfrOpHdr
,
1975 OUT IFR_BLOCK_DATA
**ReturnData
1978 IFR_BLOCK_DATA
*BlockData
;
1980 EFI_STRING_ID NameId
;
1981 EFI_IFR_QUESTION_HEADER
*IfrQuestionHdr
;
1985 IfrQuestionHdr
= (EFI_IFR_QUESTION_HEADER
*)((CHAR8
*) IfrOpHdr
+ sizeof (EFI_IFR_OP_HEADER
));
1987 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
1988 NameId
= IfrQuestionHdr
->VarStoreInfo
.VarName
;
1991 // Check whether this question is in requested block array.
1993 if (!BlockArrayCheck (RequestBlockArray
, NameId
, 0, TRUE
, HiiHandle
)) {
1995 // This question is not in the requested string. Skip it.
1997 return EFI_NOT_FOUND
;
2000 VarOffset
= IfrQuestionHdr
->VarStoreInfo
.VarOffset
;
2003 // Check whether this question is in requested block array.
2005 if (!BlockArrayCheck (RequestBlockArray
, VarOffset
, VarWidth
, FALSE
, HiiHandle
)) {
2007 // This question is not in the requested string. Skip it.
2009 return EFI_NOT_FOUND
;
2013 // Check this var question is in the var storage
2015 if (((VarOffset
+ VarWidth
) > VarStorageData
->Size
)) {
2016 return EFI_INVALID_PARAMETER
;
2020 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
2021 if (BlockData
== NULL
) {
2022 return EFI_OUT_OF_RESOURCES
;
2025 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2026 BlockData
->Name
= InternalGetString(HiiHandle
, NameId
);
2028 BlockData
->Offset
= VarOffset
;
2031 BlockData
->Width
= VarWidth
;
2032 BlockData
->QuestionId
= IfrQuestionHdr
->QuestionId
;
2033 BlockData
->OpCode
= IfrOpHdr
->OpCode
;
2034 BlockData
->Scope
= IfrOpHdr
->Scope
;
2035 InitializeListHead (&BlockData
->DefaultValueEntry
);
2037 // Add Block Data into VarStorageData BlockEntry
2039 InsertBlockData (&VarStorageData
->BlockEntry
, &BlockData
);
2040 *ReturnData
= BlockData
;
2046 This function parses Form Package to get the block array and the default
2047 value array according to the request ConfigHdr.
2049 @param HiiHandle Hii Handle for this hii package.
2050 @param Package Pointer to the form package data.
2051 @param PackageLength Length of the package.
2052 @param ConfigHdr Request string ConfigHdr. If it is NULL,
2053 the first found varstore will be as ConfigHdr.
2054 @param RequestBlockArray The block array is retrieved from the request string.
2055 @param VarStorageData VarStorage structure contains the got block and default value.
2056 @param DefaultIdArray Point to the got default id and default name array.
2058 @retval EFI_SUCCESS The block array and the default value array are got.
2059 @retval EFI_INVALID_PARAMETER The varstore definition in the different form packages
2061 @retval EFI_OUT_OF_RESOURCES No enough memory.
2066 IN EFI_HII_HANDLE HiiHandle
,
2068 IN UINT32 PackageLength
,
2069 IN EFI_STRING ConfigHdr
,
2070 IN IFR_BLOCK_DATA
*RequestBlockArray
,
2071 IN OUT IFR_VARSTORAGE_DATA
*VarStorageData
,
2072 OUT IFR_DEFAULT_DATA
*DefaultIdArray
2077 UINTN PackageOffset
;
2078 EFI_IFR_VARSTORE
*IfrVarStore
;
2079 EFI_IFR_VARSTORE_EFI
*IfrEfiVarStore
;
2080 EFI_IFR_OP_HEADER
*IfrOpHdr
;
2081 EFI_IFR_ONE_OF
*IfrOneOf
;
2082 EFI_IFR_REF4
*IfrRef
;
2083 EFI_IFR_ONE_OF_OPTION
*IfrOneOfOption
;
2084 EFI_IFR_DEFAULT
*IfrDefault
;
2085 EFI_IFR_ORDERED_LIST
*IfrOrderedList
;
2086 EFI_IFR_CHECKBOX
*IfrCheckBox
;
2087 EFI_IFR_PASSWORD
*IfrPassword
;
2088 EFI_IFR_STRING
*IfrString
;
2089 EFI_IFR_DATE
*IfrDate
;
2090 EFI_IFR_TIME
*IfrTime
;
2091 IFR_DEFAULT_DATA DefaultData
;
2092 IFR_DEFAULT_DATA
*DefaultDataPtr
;
2093 IFR_BLOCK_DATA
*BlockData
;
2094 CHAR16
*VarStoreName
;
2097 UINT16 VarDefaultId
;
2098 BOOLEAN FirstOneOfOption
;
2099 BOOLEAN FirstOrderedList
;
2100 LIST_ENTRY
*LinkData
;
2101 LIST_ENTRY
*LinkDefault
;
2102 EFI_IFR_VARSTORE_NAME_VALUE
*IfrNameValueVarStore
;
2103 EFI_HII_PACKAGE_HEADER
*PackageHeader
;
2104 EFI_VARSTORE_ID VarStoreId
;
2105 UINT16 SmallestDefaultId
;
2106 BOOLEAN SmallestIdFromFlag
;
2107 BOOLEAN FromOtherDefaultOpcode
;
2109 Status
= EFI_SUCCESS
;
2111 DefaultDataPtr
= NULL
;
2112 FirstOneOfOption
= FALSE
;
2114 FirstOrderedList
= FALSE
;
2115 VarStoreName
= NULL
;
2116 ZeroMem (&DefaultData
, sizeof (IFR_DEFAULT_DATA
));
2117 SmallestDefaultId
= 0xFFFF;
2118 FromOtherDefaultOpcode
= FALSE
;
2121 // Go through the form package to parse OpCode one by one.
2123 PackageOffset
= sizeof (EFI_HII_PACKAGE_HEADER
);
2124 PackageHeader
= (EFI_HII_PACKAGE_HEADER
*) Package
;
2125 IfrOffset
= PackageOffset
;
2126 while (IfrOffset
< PackageLength
) {
2129 // More than one form package found.
2131 if (PackageOffset
>= PackageHeader
->Length
) {
2133 // Already found varstore for this request, break;
2135 if (VarStoreId
!= 0) {
2140 // Get next package header info.
2142 IfrOffset
+= sizeof (EFI_HII_PACKAGE_HEADER
);
2143 PackageOffset
= sizeof (EFI_HII_PACKAGE_HEADER
);
2144 PackageHeader
= (EFI_HII_PACKAGE_HEADER
*) (Package
+ IfrOffset
);
2147 IfrOpHdr
= (EFI_IFR_OP_HEADER
*) (Package
+ IfrOffset
);
2148 switch (IfrOpHdr
->OpCode
) {
2149 case EFI_IFR_VARSTORE_OP
:
2151 // VarStore is found. Don't need to search any more.
2153 if (VarStoreId
!= 0) {
2157 IfrVarStore
= (EFI_IFR_VARSTORE
*) IfrOpHdr
;
2159 NameSize
= AsciiStrSize ((CHAR8
*)IfrVarStore
->Name
);
2160 VarStoreName
= AllocateZeroPool (NameSize
* sizeof (CHAR16
));
2161 if (VarStoreName
== NULL
) {
2162 Status
= EFI_OUT_OF_RESOURCES
;
2165 AsciiStrToUnicodeStrS ((CHAR8
*)IfrVarStore
->Name
, VarStoreName
, NameSize
);
2167 if (IsThisVarstore((VOID
*)&IfrVarStore
->Guid
, VarStoreName
, ConfigHdr
)) {
2169 // Find the matched VarStore
2171 CopyGuid (&VarStorageData
->Guid
, (EFI_GUID
*) (VOID
*) &IfrVarStore
->Guid
);
2172 VarStorageData
->Size
= IfrVarStore
->Size
;
2173 VarStorageData
->Name
= VarStoreName
;
2174 VarStorageData
->Type
= EFI_HII_VARSTORE_BUFFER
;
2175 VarStoreId
= IfrVarStore
->VarStoreId
;
2177 FreePool (VarStoreName
);
2178 VarStoreName
= NULL
;
2182 case EFI_IFR_VARSTORE_EFI_OP
:
2184 // VarStore is found. Don't need to search any more.
2186 if (VarStoreId
!= 0) {
2190 IfrEfiVarStore
= (EFI_IFR_VARSTORE_EFI
*) IfrOpHdr
;
2193 // If the length is small than the structure, this is from old efi
2194 // varstore definition. Old efi varstore get config directly from
2195 // GetVariable function.
2197 if (IfrOpHdr
->Length
< sizeof (EFI_IFR_VARSTORE_EFI
)) {
2201 NameSize
= AsciiStrSize ((CHAR8
*)IfrEfiVarStore
->Name
);
2202 VarStoreName
= AllocateZeroPool (NameSize
* sizeof (CHAR16
));
2203 if (VarStoreName
== NULL
) {
2204 Status
= EFI_OUT_OF_RESOURCES
;
2207 AsciiStrToUnicodeStrS ((CHAR8
*)IfrEfiVarStore
->Name
, VarStoreName
, NameSize
);
2209 if (IsThisVarstore (&IfrEfiVarStore
->Guid
, VarStoreName
, ConfigHdr
)) {
2211 // Find the matched VarStore
2213 CopyGuid (&VarStorageData
->Guid
, (EFI_GUID
*) (VOID
*) &IfrEfiVarStore
->Guid
);
2214 VarStorageData
->Size
= IfrEfiVarStore
->Size
;
2215 VarStorageData
->Name
= VarStoreName
;
2216 VarStorageData
->Type
= EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
;
2217 VarStoreId
= IfrEfiVarStore
->VarStoreId
;
2219 FreePool (VarStoreName
);
2220 VarStoreName
= NULL
;
2224 case EFI_IFR_VARSTORE_NAME_VALUE_OP
:
2226 // VarStore is found. Don't need to search any more.
2228 if (VarStoreId
!= 0) {
2232 IfrNameValueVarStore
= (EFI_IFR_VARSTORE_NAME_VALUE
*) IfrOpHdr
;
2234 if (IsThisVarstore (&IfrNameValueVarStore
->Guid
, NULL
, ConfigHdr
)) {
2236 // Find the matched VarStore
2238 CopyGuid (&VarStorageData
->Guid
, (EFI_GUID
*) (VOID
*) &IfrNameValueVarStore
->Guid
);
2239 VarStorageData
->Type
= EFI_HII_VARSTORE_NAME_VALUE
;
2240 VarStoreId
= IfrNameValueVarStore
->VarStoreId
;
2244 case EFI_IFR_DEFAULTSTORE_OP
:
2246 // Add new the map between default id and default name.
2248 DefaultDataPtr
= (IFR_DEFAULT_DATA
*) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
2249 if (DefaultDataPtr
== NULL
) {
2250 Status
= EFI_OUT_OF_RESOURCES
;
2253 DefaultDataPtr
->DefaultId
= ((EFI_IFR_DEFAULTSTORE
*) IfrOpHdr
)->DefaultId
;
2254 InsertTailList (&DefaultIdArray
->Entry
, &DefaultDataPtr
->Entry
);
2255 DefaultDataPtr
= NULL
;
2258 case EFI_IFR_FORM_OP
:
2259 case EFI_IFR_FORM_MAP_OP
:
2261 // No matched varstore is found and directly return.
2263 if ( VarStoreId
== 0) {
2264 Status
= EFI_SUCCESS
;
2269 case EFI_IFR_REF_OP
:
2271 // Ref question is not in IFR Form. This IFR form is not valid.
2273 if ( VarStoreId
== 0) {
2274 Status
= EFI_INVALID_PARAMETER
;
2278 // Check whether this question is for the requested varstore.
2280 IfrRef
= (EFI_IFR_REF4
*) IfrOpHdr
;
2281 if (IfrRef
->Question
.VarStoreId
!= VarStoreId
) {
2284 VarWidth
= (UINT16
) (sizeof (EFI_HII_REF
));
2287 // The BlockData may allocate by other opcode,need to clean.
2289 if (BlockData
!= NULL
){
2293 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
2294 if (EFI_ERROR (Status
)) {
2295 if (Status
== EFI_NOT_FOUND
){
2297 //The opcode is not required,exit and parse other opcode.
2305 case EFI_IFR_ONE_OF_OP
:
2306 case EFI_IFR_NUMERIC_OP
:
2308 // Numeric and OneOf has the same opcode structure.
2312 // Numeric and OneOf question is not in IFR Form. This IFR form is not valid.
2314 if (VarStoreId
== 0) {
2315 Status
= EFI_INVALID_PARAMETER
;
2319 // Check whether this question is for the requested varstore.
2321 IfrOneOf
= (EFI_IFR_ONE_OF
*) IfrOpHdr
;
2322 if (IfrOneOf
->Question
.VarStoreId
!= VarStoreId
) {
2325 VarWidth
= (UINT16
) (1 << (IfrOneOf
->Flags
& EFI_IFR_NUMERIC_SIZE
));
2328 // The BlockData may allocate by other opcode,need to clean.
2330 if (BlockData
!= NULL
){
2334 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
2335 if (EFI_ERROR (Status
)) {
2336 if (Status
== EFI_NOT_FOUND
){
2338 //The opcode is not required,exit and parse other opcode.
2346 //when go to there,BlockData can't be NULLL.
2348 ASSERT (BlockData
!= NULL
);
2350 if (IfrOpHdr
->OpCode
== EFI_IFR_ONE_OF_OP
) {
2352 // Set this flag to TRUE for the first oneof option.
2354 FirstOneOfOption
= TRUE
;
2355 } else if (IfrOpHdr
->OpCode
== EFI_IFR_NUMERIC_OP
) {
2357 // Numeric minimum value will be used as default value when no default is specified.
2359 DefaultData
.Type
= DefaultValueFromDefault
;
2360 switch (IfrOneOf
->Flags
& EFI_IFR_NUMERIC_SIZE
) {
2361 case EFI_IFR_NUMERIC_SIZE_1
:
2362 DefaultData
.Value
.u8
= IfrOneOf
->data
.u8
.MinValue
;
2365 case EFI_IFR_NUMERIC_SIZE_2
:
2366 CopyMem (&DefaultData
.Value
.u16
, &IfrOneOf
->data
.u16
.MinValue
, sizeof (UINT16
));
2369 case EFI_IFR_NUMERIC_SIZE_4
:
2370 CopyMem (&DefaultData
.Value
.u32
, &IfrOneOf
->data
.u32
.MinValue
, sizeof (UINT32
));
2373 case EFI_IFR_NUMERIC_SIZE_8
:
2374 CopyMem (&DefaultData
.Value
.u64
, &IfrOneOf
->data
.u64
.MinValue
, sizeof (UINT64
));
2378 Status
= EFI_INVALID_PARAMETER
;
2382 // Set default value base on the DefaultId list get from IFR data.
2384 for (LinkData
= DefaultIdArray
->Entry
.ForwardLink
; LinkData
!= &DefaultIdArray
->Entry
; LinkData
= LinkData
->ForwardLink
) {
2385 DefaultDataPtr
= BASE_CR (LinkData
, IFR_DEFAULT_DATA
, Entry
);
2386 DefaultData
.DefaultId
= DefaultDataPtr
->DefaultId
;
2387 InsertDefaultValue (BlockData
, &DefaultData
);
2392 case EFI_IFR_ORDERED_LIST_OP
:
2394 // offset by question header
2395 // width by EFI_IFR_ORDERED_LIST MaxContainers * OneofOption Type
2398 FirstOrderedList
= TRUE
;
2400 // OrderedList question is not in IFR Form. This IFR form is not valid.
2402 if (VarStoreId
== 0) {
2403 Status
= EFI_INVALID_PARAMETER
;
2407 // Check whether this question is for the requested varstore.
2409 IfrOrderedList
= (EFI_IFR_ORDERED_LIST
*) IfrOpHdr
;
2410 if (IfrOrderedList
->Question
.VarStoreId
!= VarStoreId
) {
2414 VarWidth
= IfrOrderedList
->MaxContainers
;
2417 // The BlockData may allocate by other opcode,need to clean.
2419 if (BlockData
!= NULL
){
2423 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
2424 if (EFI_ERROR (Status
)) {
2425 if (Status
== EFI_NOT_FOUND
){
2427 //The opcode is not required,exit and parse other opcode.
2435 case EFI_IFR_CHECKBOX_OP
:
2437 // EFI_IFR_DEFAULT_OP
2438 // offset by question header
2439 // width is 1 sizeof (BOOLEAN)
2440 // default id by CheckBox Flags if CheckBox flags (Default or Mau) is set, the default value is 1 to be set.
2441 // value by DefaultOption
2442 // default id by DeaultOption DefaultId can override CheckBox Flags and Default value.
2446 // CheckBox question is not in IFR Form. This IFR form is not valid.
2448 if (VarStoreId
== 0) {
2449 Status
= EFI_INVALID_PARAMETER
;
2453 // Check whether this question is for the requested varstore.
2455 IfrCheckBox
= (EFI_IFR_CHECKBOX
*) IfrOpHdr
;
2456 if (IfrCheckBox
->Question
.VarStoreId
!= VarStoreId
) {
2459 VarWidth
= (UINT16
) sizeof (BOOLEAN
);
2462 // The BlockData may allocate by other opcode,need to clean.
2464 if (BlockData
!= NULL
){
2468 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
2469 if (EFI_ERROR (Status
)) {
2470 if (Status
== EFI_NOT_FOUND
){
2472 //The opcode is not required,exit and parse other opcode.
2480 //when go to there,BlockData can't be NULLL.
2482 ASSERT (BlockData
!= NULL
);
2484 SmallestIdFromFlag
= FALSE
;
2487 // Add default value for standard ID by CheckBox Flag
2489 VarDefaultId
= EFI_HII_DEFAULT_CLASS_STANDARD
;
2491 // Prepare new DefaultValue
2493 DefaultData
.DefaultId
= VarDefaultId
;
2494 if ((IfrCheckBox
->Flags
& EFI_IFR_CHECKBOX_DEFAULT
) == EFI_IFR_CHECKBOX_DEFAULT
) {
2496 // When flag is set, default value is TRUE.
2498 DefaultData
.Type
= DefaultValueFromFlag
;
2499 DefaultData
.Value
.b
= TRUE
;
2500 InsertDefaultValue (BlockData
, &DefaultData
);
2502 if (SmallestDefaultId
> EFI_HII_DEFAULT_CLASS_STANDARD
) {
2504 // Record the SmallestDefaultId and update the SmallestIdFromFlag.
2506 SmallestDefaultId
= EFI_HII_DEFAULT_CLASS_STANDARD
;
2507 SmallestIdFromFlag
= TRUE
;
2512 // Add default value for Manufacture ID by CheckBox Flag
2514 VarDefaultId
= EFI_HII_DEFAULT_CLASS_MANUFACTURING
;
2516 // Prepare new DefaultValue
2518 DefaultData
.DefaultId
= VarDefaultId
;
2519 if ((IfrCheckBox
->Flags
& EFI_IFR_CHECKBOX_DEFAULT_MFG
) == EFI_IFR_CHECKBOX_DEFAULT_MFG
) {
2521 // When flag is set, default value is TRUE.
2523 DefaultData
.Type
= DefaultValueFromFlag
;
2524 DefaultData
.Value
.b
= TRUE
;
2525 InsertDefaultValue (BlockData
, &DefaultData
);
2527 if (SmallestDefaultId
> EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
2529 // Record the SmallestDefaultId and update the SmallestIdFromFlag.
2531 SmallestDefaultId
= EFI_HII_DEFAULT_CLASS_MANUFACTURING
;
2532 SmallestIdFromFlag
= TRUE
;
2535 if (SmallestIdFromFlag
) {
2537 // When smallest default Id is given by the flag of CheckBox, set default value with TRUE for other default Id in the DefaultId list.
2539 DefaultData
.Type
= DefaultValueFromOtherDefault
;
2540 DefaultData
.Value
.b
= TRUE
;
2542 // Set default value for all the default id in the DefaultId list.
2544 for (LinkData
= DefaultIdArray
->Entry
.ForwardLink
; LinkData
!= &DefaultIdArray
->Entry
; LinkData
= LinkData
->ForwardLink
) {
2545 DefaultDataPtr
= BASE_CR (LinkData
, IFR_DEFAULT_DATA
, Entry
);
2546 DefaultData
.DefaultId
= DefaultDataPtr
->DefaultId
;
2547 InsertDefaultValue (BlockData
, &DefaultData
);
2551 // When flag is not set, default value is FASLE.
2553 DefaultData
.Type
= DefaultValueFromDefault
;
2554 DefaultData
.Value
.b
= FALSE
;
2556 // Set default value for all the default id in the DefaultId list.
2558 for (LinkData
= DefaultIdArray
->Entry
.ForwardLink
; LinkData
!= &DefaultIdArray
->Entry
; LinkData
= LinkData
->ForwardLink
) {
2559 DefaultDataPtr
= BASE_CR (LinkData
, IFR_DEFAULT_DATA
, Entry
);
2560 DefaultData
.DefaultId
= DefaultDataPtr
->DefaultId
;
2561 InsertDefaultValue (BlockData
, &DefaultData
);
2566 case EFI_IFR_DATE_OP
:
2568 // offset by question header
2569 // width MaxSize * sizeof (CHAR16)
2570 // no default value, only block array
2574 // Date question is not in IFR Form. This IFR form is not valid.
2576 if (VarStoreId
== 0) {
2577 Status
= EFI_INVALID_PARAMETER
;
2581 // Check whether this question is for the requested varstore.
2583 IfrDate
= (EFI_IFR_DATE
*) IfrOpHdr
;
2584 if (IfrDate
->Question
.VarStoreId
!= VarStoreId
) {
2589 // The BlockData may allocate by other opcode,need to clean.
2591 if (BlockData
!= NULL
){
2595 VarWidth
= (UINT16
) sizeof (EFI_HII_DATE
);
2596 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
2597 if (EFI_ERROR (Status
)) {
2598 if (Status
== EFI_NOT_FOUND
){
2600 //The opcode is not required,exit and parse other opcode.
2608 case EFI_IFR_TIME_OP
:
2610 // offset by question header
2611 // width MaxSize * sizeof (CHAR16)
2612 // no default value, only block array
2616 // Time question is not in IFR Form. This IFR form is not valid.
2618 if (VarStoreId
== 0) {
2619 Status
= EFI_INVALID_PARAMETER
;
2623 // Check whether this question is for the requested varstore.
2625 IfrTime
= (EFI_IFR_TIME
*) IfrOpHdr
;
2626 if (IfrTime
->Question
.VarStoreId
!= VarStoreId
) {
2631 // The BlockData may allocate by other opcode,need to clean.
2633 if (BlockData
!= NULL
){
2637 VarWidth
= (UINT16
) sizeof (EFI_HII_TIME
);
2638 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
2639 if (EFI_ERROR (Status
)) {
2640 if (Status
== EFI_NOT_FOUND
){
2642 //The opcode is not required,exit and parse other opcode.
2650 case EFI_IFR_STRING_OP
:
2652 // offset by question header
2653 // width MaxSize * sizeof (CHAR16)
2654 // no default value, only block array
2658 // String question is not in IFR Form. This IFR form is not valid.
2660 if (VarStoreId
== 0) {
2661 Status
= EFI_INVALID_PARAMETER
;
2665 // Check whether this question is for the requested varstore.
2667 IfrString
= (EFI_IFR_STRING
*) IfrOpHdr
;
2668 if (IfrString
->Question
.VarStoreId
!= VarStoreId
) {
2673 // The BlockData may allocate by other opcode,need to clean.
2675 if (BlockData
!= NULL
){
2679 VarWidth
= (UINT16
) (IfrString
->MaxSize
* sizeof (UINT16
));
2680 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
2681 if (EFI_ERROR (Status
)) {
2682 if (Status
== EFI_NOT_FOUND
){
2684 //The opcode is not required,exit and parse other opcode.
2692 case EFI_IFR_PASSWORD_OP
:
2694 // offset by question header
2695 // width MaxSize * sizeof (CHAR16)
2696 // no default value, only block array
2700 // Password question is not in IFR Form. This IFR form is not valid.
2702 if (VarStoreId
== 0) {
2703 Status
= EFI_INVALID_PARAMETER
;
2707 // Check whether this question is for the requested varstore.
2709 IfrPassword
= (EFI_IFR_PASSWORD
*) IfrOpHdr
;
2710 if (IfrPassword
->Question
.VarStoreId
!= VarStoreId
) {
2715 // The BlockData may allocate by other opcode,need to clean.
2717 if (BlockData
!= NULL
){
2721 VarWidth
= (UINT16
) (IfrPassword
->MaxSize
* sizeof (UINT16
));
2722 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
2723 if (EFI_ERROR (Status
)) {
2724 if (Status
== EFI_NOT_FOUND
){
2726 //The opcode is not required,exit and parse other opcode.
2734 // No default value for string.
2739 case EFI_IFR_ONE_OF_OPTION_OP
:
2741 // No matched block data is ignored.
2743 if (BlockData
== NULL
|| BlockData
->Scope
== 0) {
2747 IfrOneOfOption
= (EFI_IFR_ONE_OF_OPTION
*) IfrOpHdr
;
2748 if (BlockData
->OpCode
== EFI_IFR_ORDERED_LIST_OP
) {
2750 if (!FirstOrderedList
){
2754 // Get ordered list option data type.
2756 if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_8
|| IfrOneOfOption
->Type
== EFI_IFR_TYPE_BOOLEAN
) {
2758 } else if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_16
) {
2760 } else if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_32
) {
2762 } else if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_64
) {
2766 // Invalid ordered list option data type.
2768 Status
= EFI_INVALID_PARAMETER
;
2769 if (BlockData
->Name
!= NULL
) {
2770 FreePool (BlockData
->Name
);
2772 FreePool (BlockData
);
2777 // Calculate Ordered list QuestionId width.
2779 BlockData
->Width
= (UINT16
) (BlockData
->Width
* VarWidth
);
2781 // Check whether this question is in requested block array.
2783 if (!BlockArrayCheck (RequestBlockArray
, BlockData
->Offset
, BlockData
->Width
, (BOOLEAN
)(BlockData
->Name
!= NULL
), HiiHandle
)) {
2785 // This question is not in the requested string. Skip it.
2787 if (BlockData
->Name
!= NULL
) {
2788 FreePool (BlockData
->Name
);
2790 FreePool (BlockData
);
2795 // Check this var question is in the var storage
2797 if ((BlockData
->Name
== NULL
) && ((BlockData
->Offset
+ BlockData
->Width
) > VarStorageData
->Size
)) {
2798 Status
= EFI_INVALID_PARAMETER
;
2799 if (BlockData
->Name
!= NULL
) {
2800 FreePool (BlockData
->Name
);
2802 FreePool (BlockData
);
2806 // Add Block Data into VarStorageData BlockEntry
2808 InsertBlockData (&VarStorageData
->BlockEntry
, &BlockData
);
2810 FirstOrderedList
= FALSE
;
2816 // 1. Set default value for OneOf option when flag field has default attribute.
2817 // And set the default value with the smallest default id for other default id in the DefaultId list.
2819 if (((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT
) == EFI_IFR_OPTION_DEFAULT
) ||
2820 ((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT_MFG
) == EFI_IFR_OPTION_DEFAULT_MFG
)) {
2822 // This flag is used to specify whether this option is the first. Set it to FALSE for the following options.
2823 // The first oneof option value will be used as default value when no default value is specified.
2825 FirstOneOfOption
= FALSE
;
2827 SmallestIdFromFlag
= FALSE
;
2829 // Prepare new DefaultValue
2831 DefaultData
.Type
= DefaultValueFromFlag
;
2832 CopyMem (&DefaultData
.Value
, &IfrOneOfOption
->Value
, IfrOneOfOption
->Header
.Length
- OFFSET_OF (EFI_IFR_ONE_OF_OPTION
, Value
));
2833 if ((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT
) == EFI_IFR_OPTION_DEFAULT
) {
2834 DefaultData
.DefaultId
= EFI_HII_DEFAULT_CLASS_STANDARD
;
2835 InsertDefaultValue (BlockData
, &DefaultData
);
2836 if (SmallestDefaultId
> EFI_HII_DEFAULT_CLASS_STANDARD
) {
2838 // Record the SmallestDefaultId and update the SmallestIdFromFlag.
2840 SmallestDefaultId
= EFI_HII_DEFAULT_CLASS_STANDARD
;
2841 SmallestIdFromFlag
= TRUE
;
2844 if ((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT_MFG
) == EFI_IFR_OPTION_DEFAULT_MFG
) {
2845 DefaultData
.DefaultId
= EFI_HII_DEFAULT_CLASS_MANUFACTURING
;
2846 InsertDefaultValue (BlockData
, &DefaultData
);
2847 if (SmallestDefaultId
> EFI_HII_DEFAULT_CLASS_MANUFACTURING
) {
2849 // Record the SmallestDefaultId and update the SmallestIdFromFlag.
2851 SmallestDefaultId
= EFI_HII_DEFAULT_CLASS_MANUFACTURING
;
2852 SmallestIdFromFlag
= TRUE
;
2856 if (SmallestIdFromFlag
) {
2858 // When smallest default Id is given by the flag of oneofOption, set this option value for other default Id in the DefaultId list.
2860 DefaultData
.Type
= DefaultValueFromOtherDefault
;
2862 // Set default value for other default id in the DefaultId list.
2864 for (LinkData
= DefaultIdArray
->Entry
.ForwardLink
; LinkData
!= &DefaultIdArray
->Entry
; LinkData
= LinkData
->ForwardLink
) {
2865 DefaultDataPtr
= BASE_CR (LinkData
, IFR_DEFAULT_DATA
, Entry
);
2866 DefaultData
.DefaultId
= DefaultDataPtr
->DefaultId
;
2867 InsertDefaultValue (BlockData
, &DefaultData
);
2873 // 2. Set as the default value when this is the first option.
2874 // The first oneof option value will be used as default value when no default value is specified.
2876 if (FirstOneOfOption
) {
2877 // This flag is used to specify whether this option is the first. Set it to FALSE for the following options.
2878 FirstOneOfOption
= FALSE
;
2881 // Prepare new DefaultValue
2883 DefaultData
.Type
= DefaultValueFromDefault
;
2884 CopyMem (&DefaultData
.Value
, &IfrOneOfOption
->Value
, IfrOneOfOption
->Header
.Length
- OFFSET_OF (EFI_IFR_ONE_OF_OPTION
, Value
));
2885 for (LinkData
= DefaultIdArray
->Entry
.ForwardLink
; LinkData
!= &DefaultIdArray
->Entry
; LinkData
= LinkData
->ForwardLink
) {
2886 DefaultDataPtr
= BASE_CR (LinkData
, IFR_DEFAULT_DATA
, Entry
);
2887 DefaultData
.DefaultId
= DefaultDataPtr
->DefaultId
;
2888 InsertDefaultValue (BlockData
, &DefaultData
);
2893 case EFI_IFR_DEFAULT_OP
:
2895 // Update Current BlockData to the default value.
2897 if (BlockData
== NULL
|| BlockData
->Scope
== 0) {
2899 // No matched block data is ignored.
2905 // Get the DefaultId
2907 IfrDefault
= (EFI_IFR_DEFAULT
*) IfrOpHdr
;
2908 VarDefaultId
= IfrDefault
->DefaultId
;
2910 // Prepare new DefaultValue
2912 DefaultData
.Type
= DefaultValueFromOpcode
;
2913 DefaultData
.DefaultId
= VarDefaultId
;
2914 CopyMem (&DefaultData
.Value
, &IfrDefault
->Value
, IfrDefault
->Header
.Length
- OFFSET_OF (EFI_IFR_DEFAULT
, Value
));
2916 // If the value field is expression, set the cleaned flag.
2917 if (IfrDefault
->Type
== EFI_IFR_TYPE_OTHER
) {
2918 DefaultData
.Cleaned
= TRUE
;
2921 // Add DefaultValue into current BlockData
2923 InsertDefaultValue (BlockData
, &DefaultData
);
2926 // Set default value for other default id in the DefaultId list.
2927 // when SmallestDefaultId == VarDefaultId means there are two defaults with same default Id.
2928 // If the two defaults are both from default opcode, use the first default as the default value of other default Id.
2929 // If one from flag and the other form default opcode, use the default opcode value as the default value of other default Id.
2931 if ((SmallestDefaultId
> VarDefaultId
) || (SmallestDefaultId
== VarDefaultId
&& !FromOtherDefaultOpcode
)) {
2932 FromOtherDefaultOpcode
= TRUE
;
2933 SmallestDefaultId
= VarDefaultId
;
2934 for (LinkData
= DefaultIdArray
->Entry
.ForwardLink
; LinkData
!= &DefaultIdArray
->Entry
; LinkData
= LinkData
->ForwardLink
) {
2935 DefaultDataPtr
= BASE_CR (LinkData
, IFR_DEFAULT_DATA
, Entry
);
2936 if (DefaultDataPtr
->DefaultId
!= DefaultData
.DefaultId
){
2937 DefaultData
.Type
= DefaultValueFromOtherDefault
;
2938 DefaultData
.DefaultId
= DefaultDataPtr
->DefaultId
;
2939 InsertDefaultValue (BlockData
, &DefaultData
);
2945 // After insert the default value, reset the cleaned value for next
2946 // time used. If not set here, need to set the value before every time.
2949 DefaultData
.Cleaned
= FALSE
;
2952 case EFI_IFR_END_OP
:
2954 // End Opcode is for Var question.
2956 if (BlockData
!= NULL
) {
2957 if (BlockData
->Scope
> 0) {
2960 if (BlockData
->Scope
== 0) {
2963 // when finishing parsing a question, clean the SmallestDefaultId and GetDefaultFromDefaultOpcode.
2965 SmallestDefaultId
= 0xFFFF;
2966 FromOtherDefaultOpcode
= FALSE
;
2973 if (BlockData
!= NULL
) {
2974 if (BlockData
->Scope
> 0) {
2975 BlockData
->Scope
= (UINT8
) (BlockData
->Scope
+ IfrOpHdr
->Scope
);
2978 if (BlockData
->Scope
== 0) {
2985 IfrOffset
+= IfrOpHdr
->Length
;
2986 PackageOffset
+= IfrOpHdr
->Length
;
2990 //if Status == EFI_NOT_FOUND, just means the opcode is not required,not contain any error,
2991 //so set the Status to EFI_SUCCESS.
2993 if (Status
== EFI_NOT_FOUND
){
2994 Status
= EFI_SUCCESS
;
2998 for (LinkData
= VarStorageData
->BlockEntry
.ForwardLink
; LinkData
!= &VarStorageData
->BlockEntry
; LinkData
= LinkData
->ForwardLink
) {
2999 BlockData
= BASE_CR (LinkData
, IFR_BLOCK_DATA
, Entry
);
3000 for (LinkDefault
= BlockData
->DefaultValueEntry
.ForwardLink
; LinkDefault
!= &BlockData
->DefaultValueEntry
; ) {
3001 DefaultDataPtr
= BASE_CR (LinkDefault
, IFR_DEFAULT_DATA
, Entry
);
3002 LinkDefault
= LinkDefault
->ForwardLink
;
3003 if (DefaultDataPtr
->Cleaned
== TRUE
) {
3004 RemoveEntryList (&DefaultDataPtr
->Entry
);
3005 FreePool (DefaultDataPtr
);
3014 parse the configrequest string, get the elements.
3016 @param ConfigRequest The input configrequest string.
3017 @param Progress Return the progress data.
3019 @retval Block data pointer.
3023 IN EFI_STRING ConfigRequest
,
3024 OUT EFI_STRING
*Progress
3027 EFI_STRING StringPtr
;
3028 IFR_BLOCK_DATA
*BlockData
;
3029 IFR_BLOCK_DATA
*RequestBlockArray
;
3035 IFR_BLOCK_DATA
*NextBlockData
;
3041 // Init RequestBlockArray
3043 RequestBlockArray
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
3044 if (RequestBlockArray
== NULL
) {
3047 InitializeListHead (&RequestBlockArray
->Entry
);
3050 // Get the request Block array from the request string
3055 // Parse each <RequestElement> if exists
3056 // Only <BlockName> format is supported by this help function.
3057 // <BlockName> ::= &'OFFSET='<Number>&'WIDTH='<Number>
3059 StringPtr
= ConfigRequest
;
3060 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) == 0) {
3062 // Skip the OFFSET string
3064 *Progress
= StringPtr
;
3065 StringPtr
+= StrLen (L
"&OFFSET=");
3069 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
3070 if (EFI_ERROR (Status
)) {
3077 (((Length
+ 1) / 2) < sizeof (UINT16
)) ? ((Length
+ 1) / 2) : sizeof (UINT16
)
3079 FreePool (TmpBuffer
);
3081 StringPtr
+= Length
;
3082 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
3085 StringPtr
+= StrLen (L
"&WIDTH=");
3090 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
3091 if (EFI_ERROR (Status
)) {
3098 (((Length
+ 1) / 2) < sizeof (UINT16
)) ? ((Length
+ 1) / 2) : sizeof (UINT16
)
3100 FreePool (TmpBuffer
);
3102 StringPtr
+= Length
;
3103 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
3110 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
3111 if (BlockData
== NULL
) {
3114 BlockData
->Offset
= Offset
;
3115 BlockData
->Width
= Width
;
3116 InsertBlockData (&RequestBlockArray
->Entry
, &BlockData
);
3119 // Skip &VALUE string if &VALUE does exists.
3121 if (StrnCmp (StringPtr
, L
"&VALUE=", StrLen (L
"&VALUE=")) == 0) {
3122 StringPtr
+= StrLen (L
"&VALUE=");
3127 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
3128 if (EFI_ERROR (Status
)) {
3131 FreePool (TmpBuffer
);
3132 StringPtr
+= Length
;
3133 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
3138 // If '\0', parsing is finished.
3140 if (*StringPtr
== 0) {
3146 // Merge the requested block data.
3148 Link
= RequestBlockArray
->Entry
.ForwardLink
;
3149 while ((Link
!= &RequestBlockArray
->Entry
) && (Link
->ForwardLink
!= &RequestBlockArray
->Entry
)) {
3150 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
3151 NextBlockData
= BASE_CR (Link
->ForwardLink
, IFR_BLOCK_DATA
, Entry
);
3152 if ((NextBlockData
->Offset
>= BlockData
->Offset
) && (NextBlockData
->Offset
<= (BlockData
->Offset
+ BlockData
->Width
))) {
3153 if ((NextBlockData
->Offset
+ NextBlockData
->Width
) > (BlockData
->Offset
+ BlockData
->Width
)) {
3154 BlockData
->Width
= (UINT16
) (NextBlockData
->Offset
+ NextBlockData
->Width
- BlockData
->Offset
);
3156 RemoveEntryList (Link
->ForwardLink
);
3157 FreePool (NextBlockData
);
3160 Link
= Link
->ForwardLink
;
3163 return RequestBlockArray
;
3166 if (RequestBlockArray
!= NULL
) {
3168 // Free Link Array RequestBlockArray
3170 while (!IsListEmpty (&RequestBlockArray
->Entry
)) {
3171 BlockData
= BASE_CR (RequestBlockArray
->Entry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
3172 RemoveEntryList (&BlockData
->Entry
);
3173 FreePool (BlockData
);
3176 FreePool (RequestBlockArray
);
3183 parse the configrequest string, get the elements.
3185 @param ConfigRequest The input config request string.
3186 @param Progress Return the progress data.
3188 @retval return data block array.
3192 IN EFI_STRING ConfigRequest
,
3193 OUT EFI_STRING
*Progress
3196 EFI_STRING StringPtr
;
3198 IFR_BLOCK_DATA
*BlockData
;
3199 IFR_BLOCK_DATA
*RequestBlockArray
;
3202 StringPtr
= ConfigRequest
;
3205 // Init RequestBlockArray
3207 RequestBlockArray
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
3208 if (RequestBlockArray
== NULL
) {
3211 InitializeListHead (&RequestBlockArray
->Entry
);
3214 // Get the request Block array from the request string
3218 // Parse each <RequestElement> if exists
3219 // Only <BlockName> format is supported by this help function.
3220 // <BlockName> ::= &'Name***=***
3222 while (StringPtr
!= NULL
&& *StringPtr
== L
'&') {
3224 *Progress
= StringPtr
;
3226 // Skip the L"&" string
3231 if ((NextTag
= StrStr (StringPtr
, L
"=")) != NULL
) {
3234 } else if ((NextTag
= StrStr (StringPtr
, L
"&")) != NULL
) {
3241 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
3242 if (BlockData
== NULL
) {
3249 BlockData
->Name
= AllocateCopyPool(StrSize (StringPtr
), StringPtr
);
3250 InsertBlockData (&RequestBlockArray
->Entry
, &BlockData
);
3254 // If has value, skip the value.
3256 StringPtr
= NextTag
+ 1;
3258 StringPtr
= StrStr (StringPtr
, L
"&");
3259 } else if (NextTag
!= NULL
) {
3261 // restore the '&' text.
3263 StringPtr
= NextTag
;
3268 return RequestBlockArray
;
3271 if (RequestBlockArray
!= NULL
) {
3273 // Free Link Array RequestBlockArray
3275 while (!IsListEmpty (&RequestBlockArray
->Entry
)) {
3276 BlockData
= BASE_CR (RequestBlockArray
->Entry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
3277 RemoveEntryList (&BlockData
->Entry
);
3278 if (BlockData
->Name
!= NULL
) {
3279 FreePool (BlockData
->Name
);
3281 FreePool (BlockData
);
3284 FreePool (RequestBlockArray
);
3291 Generate ConfigRequest string base on the varstore info.
3293 @param ConfigHdr The config header for this varstore.
3294 @param VarStorageData The varstore info.
3295 @param Status Return Status.
3296 @param ConfigRequest The ConfigRequest info may be return.
3298 @retval TRUE Need to continue
3299 @retval Others NO need to continue or error occur.
3302 GenerateConfigRequest (
3303 IN CHAR16
*ConfigHdr
,
3304 IN IFR_VARSTORAGE_DATA
*VarStorageData
,
3305 OUT EFI_STATUS
*Status
,
3306 IN OUT EFI_STRING
*ConfigRequest
3312 CHAR16
*FullConfigRequest
;
3314 IFR_BLOCK_DATA
*BlockData
;
3317 // Append VarStorageData BlockEntry into *Request string
3318 // Now support only one varstore in a form package.
3322 // Go through all VarStorageData Entry and get BlockEntry for each one for the multiple varstore in a single form package
3323 // Then construct them all to return MultiRequest string : ConfigHdr BlockConfig
3327 // Compute the length of the entire request starting with <ConfigHdr> and a
3331 Length
= StrLen (ConfigHdr
) + 1;
3333 for (Link
= VarStorageData
->BlockEntry
.ForwardLink
; Link
!= &VarStorageData
->BlockEntry
; Link
= Link
->ForwardLink
) {
3335 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
3336 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3338 // Add <BlockName> length for each Name
3340 // <BlockName> ::= &Name1&Name2&...
3341 // |1| StrLen(Name1)
3343 Length
= Length
+ (1 + StrLen (BlockData
->Name
));
3346 // Add <BlockName> length for each Offset/Width pair
3348 // <BlockName> ::= &OFFSET=1234&WIDTH=1234
3349 // | 8 | 4 | 7 | 4 |
3351 Length
= Length
+ (8 + 4 + 7 + 4);
3355 // No any request block data is found. The request string can't be constructed.
3358 *Status
= EFI_SUCCESS
;
3363 // Allocate buffer for the entire <ConfigRequest>
3365 FullConfigRequest
= AllocateZeroPool (Length
* sizeof (CHAR16
));
3366 if (FullConfigRequest
== NULL
) {
3367 *Status
= EFI_OUT_OF_RESOURCES
;
3370 StringPtr
= FullConfigRequest
;
3373 // Start with <ConfigHdr>
3375 StrCpyS (StringPtr
, Length
, ConfigHdr
);
3376 StringPtr
+= StrLen (StringPtr
);
3379 // Loop through all the Offset/Width pairs and append them to ConfigRequest
3381 for (Link
= VarStorageData
->BlockEntry
.ForwardLink
; Link
!= &VarStorageData
->BlockEntry
; Link
= Link
->ForwardLink
) {
3382 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
3383 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3389 (1 + StrLen (BlockData
->Name
) + 1) * sizeof (CHAR16
),
3395 // Append &OFFSET=XXXX&WIDTH=YYYY\0
3399 (8 + 4 + 7 + 4 + 1) * sizeof (CHAR16
),
3400 L
"&OFFSET=%04X&WIDTH=%04X",
3405 StringPtr
+= StrLen (StringPtr
);
3408 // Set to the got full request string.
3410 HiiToLower (FullConfigRequest
);
3412 if (*ConfigRequest
!= NULL
) {
3413 FreePool (*ConfigRequest
);
3415 *ConfigRequest
= FullConfigRequest
;
3421 Generate ConfigRequest Header base on the varstore info.
3423 @param VarStorageData The varstore info.
3424 @param DevicePath Device path for this varstore.
3425 @param ConfigHdr The config header for this varstore.
3427 @retval EFI_SUCCESS Generate the header success.
3428 @retval EFI_OUT_OF_RESOURCES Allocate buffer fail.
3432 IN IFR_VARSTORAGE_DATA
*VarStorageData
,
3433 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
3434 OUT EFI_STRING
*ConfigHdr
3443 Status
= EFI_SUCCESS
;
3449 // Construct <ConfigHdr> : "GUID=...&NAME=...&PATH=..." by VarStorageData Guid, Name and DriverHandle
3451 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*) &VarStorageData
->Guid
, 1, &GuidStr
);
3452 if (VarStorageData
->Name
!= NULL
) {
3453 GenerateSubStr (L
"NAME=", StrLen (VarStorageData
->Name
) * sizeof (CHAR16
), (VOID
*) VarStorageData
->Name
, 2, &NameStr
);
3455 GenerateSubStr (L
"NAME=", 0, NULL
, 2, &NameStr
);
3459 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) DevicePath
),
3460 (VOID
*) DevicePath
,
3464 Length
= StrLen (GuidStr
) + StrLen (NameStr
) + StrLen (PathStr
) + 1;
3465 if (VarStorageData
->Name
== NULL
) {
3469 *ConfigHdr
= AllocateZeroPool (Length
* sizeof (CHAR16
));
3470 if (*ConfigHdr
== NULL
) {
3471 Status
= EFI_OUT_OF_RESOURCES
;
3474 StrCpyS (*ConfigHdr
, Length
, GuidStr
);
3475 StrCatS (*ConfigHdr
, Length
, NameStr
);
3476 if (VarStorageData
->Name
== NULL
) {
3477 StrCatS (*ConfigHdr
, Length
, L
"&");
3479 StrCatS (*ConfigHdr
, Length
, PathStr
);
3482 // Remove the last character L'&'
3484 *(*ConfigHdr
+ StrLen (*ConfigHdr
) - 1) = L
'\0';
3487 if (GuidStr
!= NULL
) {
3491 if (NameStr
!= NULL
) {
3495 if (PathStr
!= NULL
) {
3503 Get Data buffer size based on data type.
3505 @param ValueType The input data type.
3507 @retval The data buffer size for the input type.
3514 UINT16 StorageWidth
;
3516 switch (ValueType
) {
3517 case EFI_IFR_NUMERIC_SIZE_1
:
3518 case EFI_IFR_TYPE_BOOLEAN
:
3519 StorageWidth
= (UINT16
) sizeof (UINT8
);
3522 case EFI_IFR_NUMERIC_SIZE_2
:
3523 StorageWidth
= (UINT16
) sizeof (UINT16
);
3526 case EFI_IFR_NUMERIC_SIZE_4
:
3527 StorageWidth
= (UINT16
) sizeof (UINT32
);
3530 case EFI_IFR_NUMERIC_SIZE_8
:
3531 StorageWidth
= (UINT16
) sizeof (UINT64
);
3534 case EFI_IFR_TYPE_TIME
:
3535 StorageWidth
= (UINT16
) sizeof (EFI_IFR_TIME
);
3538 case EFI_IFR_TYPE_DATE
:
3539 StorageWidth
= (UINT16
) sizeof (EFI_IFR_DATE
);
3547 return StorageWidth
;
3551 Generate ConfigAltResp string base on the varstore info.
3553 @param HiiHandle Hii Handle for this hii package.
3554 @param ConfigHdr The config header for this varstore.
3555 @param VarStorageData The varstore info.
3556 @param DefaultIdArray The Default id array.
3557 @param DefaultAltCfgResp The DefaultAltCfgResp info may be return.
3559 @retval TRUE Need to continue
3560 @retval Others NO need to continue or error occur.
3563 GenerateAltConfigResp (
3564 IN EFI_HII_HANDLE HiiHandle
,
3565 IN CHAR16
*ConfigHdr
,
3566 IN IFR_VARSTORAGE_DATA
*VarStorageData
,
3567 IN IFR_DEFAULT_DATA
*DefaultIdArray
,
3568 IN OUT EFI_STRING
*DefaultAltCfgResp
3574 LIST_ENTRY
*LinkData
;
3575 LIST_ENTRY
*LinkDefault
;
3576 LIST_ENTRY
*ListEntry
;
3578 IFR_BLOCK_DATA
*BlockData
;
3579 IFR_DEFAULT_DATA
*DefaultId
;
3580 IFR_DEFAULT_DATA
*DefaultValueData
;
3583 CHAR16
*DefaultString
;
3588 DefaultString
= NULL
;
3590 // Add length for <ConfigHdr> + '\0'
3592 Length
= StrLen (ConfigHdr
) + 1;
3594 for (Link
= DefaultIdArray
->Entry
.ForwardLink
; Link
!= &DefaultIdArray
->Entry
; Link
= Link
->ForwardLink
) {
3595 DefaultId
= BASE_CR (Link
, IFR_DEFAULT_DATA
, Entry
);
3597 // Add length for "&<ConfigHdr>&ALTCFG=XXXX"
3598 // |1| StrLen (ConfigHdr) | 8 | 4 |
3600 Length
+= (1 + StrLen (ConfigHdr
) + 8 + 4);
3602 for (LinkData
= VarStorageData
->BlockEntry
.ForwardLink
; LinkData
!= &VarStorageData
->BlockEntry
; LinkData
= LinkData
->ForwardLink
) {
3603 BlockData
= BASE_CR (LinkData
, IFR_BLOCK_DATA
, Entry
);
3604 ListEntry
= &BlockData
->DefaultValueEntry
;
3605 for (LinkDefault
= ListEntry
->ForwardLink
; LinkDefault
!= ListEntry
; LinkDefault
= LinkDefault
->ForwardLink
) {
3606 DefaultValueData
= BASE_CR (LinkDefault
, IFR_DEFAULT_DATA
, Entry
);
3607 if (DefaultValueData
->DefaultId
!= DefaultId
->DefaultId
) {
3610 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3612 // Add length for "&Name1=zzzzzzzzzzzz"
3615 Length
+= (1 + StrLen (BlockData
->Name
) + 1 + BlockData
->Width
* 2);
3618 // Add length for "&OFFSET=XXXX&WIDTH=YYYY&VALUE=zzzzzzzzzzzz"
3619 // | 8 | 4 | 7 | 4 | 7 | Width * 2 |
3621 Length
+= (8 + 4 + 7 + 4 + 7 + BlockData
->Width
* 2);
3629 // No default value is found. The default string doesn't exist.
3636 // Allocate buffer for the entire <DefaultAltCfgResp>
3638 *DefaultAltCfgResp
= AllocateZeroPool (Length
* sizeof (CHAR16
));
3639 if (*DefaultAltCfgResp
== NULL
) {
3640 return EFI_OUT_OF_RESOURCES
;
3642 StringPtr
= *DefaultAltCfgResp
;
3645 // Start with <ConfigHdr>
3647 StrCpyS (StringPtr
, Length
, ConfigHdr
);
3648 StringPtr
+= StrLen (StringPtr
);
3650 for (Link
= DefaultIdArray
->Entry
.ForwardLink
; Link
!= &DefaultIdArray
->Entry
; Link
= Link
->ForwardLink
) {
3651 DefaultId
= BASE_CR (Link
, IFR_DEFAULT_DATA
, Entry
);
3653 // Add <AltConfigHdr> of the form "&<ConfigHdr>&ALTCFG=XXXX\0"
3654 // |1| StrLen (ConfigHdr) | 8 | 4 |
3658 (1 + StrLen (ConfigHdr
) + 8 + 4 + 1) * sizeof (CHAR16
),
3661 DefaultId
->DefaultId
3663 StringPtr
+= StrLen (StringPtr
);
3665 for (LinkData
= VarStorageData
->BlockEntry
.ForwardLink
; LinkData
!= &VarStorageData
->BlockEntry
; LinkData
= LinkData
->ForwardLink
) {
3666 BlockData
= BASE_CR (LinkData
, IFR_BLOCK_DATA
, Entry
);
3667 ListEntry
= &BlockData
->DefaultValueEntry
;
3668 for (LinkDefault
= ListEntry
->ForwardLink
; LinkDefault
!= ListEntry
; LinkDefault
= LinkDefault
->ForwardLink
) {
3669 DefaultValueData
= BASE_CR (LinkDefault
, IFR_DEFAULT_DATA
, Entry
);
3670 if (DefaultValueData
->DefaultId
!= DefaultId
->DefaultId
) {
3673 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3676 (1 + StrLen (ConfigHdr
) + 1) * sizeof (CHAR16
),
3680 StringPtr
+= StrLen (StringPtr
);
3683 // Add <BlockConfig>
3684 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>
3688 (8 + 4 + 7 + 4 + 7 + 1) * sizeof (CHAR16
),
3689 L
"&OFFSET=%04X&WIDTH=%04X&VALUE=",
3693 StringPtr
+= StrLen (StringPtr
);
3695 Width
= BlockData
->Width
;
3697 // Convert Value to a hex string in "%x" format
3698 // NOTE: This is in the opposite byte that GUID and PATH use
3700 if (BlockData
->OpCode
== EFI_IFR_STRING_OP
){
3701 DefaultString
= InternalGetString(HiiHandle
, DefaultValueData
->Value
.string
);
3702 TmpBuffer
= AllocateZeroPool (Width
);
3703 ASSERT (TmpBuffer
!= NULL
);
3704 if (DefaultString
!= NULL
) {
3705 StrSize
= StrLen(DefaultString
)* sizeof (CHAR16
);
3706 if (StrSize
> Width
) {
3709 CopyMem (TmpBuffer
, (UINT8
*) DefaultString
, StrSize
);
3712 TmpBuffer
= (UINT8
*) &(DefaultValueData
->Value
);
3714 for (; Width
> 0 && (TmpBuffer
!= NULL
); Width
--) {
3715 StringPtr
+= UnicodeValueToString (StringPtr
, PREFIX_ZERO
| RADIX_HEX
, TmpBuffer
[Width
- 1], 2);
3717 if (DefaultString
!= NULL
){
3718 FreePool(DefaultString
);
3719 DefaultString
= NULL
;
3721 if (BlockData
->OpCode
== EFI_IFR_STRING_OP
&& TmpBuffer
!= NULL
) {
3722 FreePool(TmpBuffer
);
3729 HiiToLower (*DefaultAltCfgResp
);
3735 This function gets the full request string and full default value string by
3736 parsing IFR data in HII form packages.
3738 When Request points to NULL string, the request string and default value string
3739 for each varstore in form package will return.
3741 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
3742 @param DevicePath Device Path which Hii Config Access Protocol is registered.
3743 @param Request Pointer to a null-terminated Unicode string in
3744 <ConfigRequest> format. When it doesn't contain
3745 any RequestElement, it will be updated to return
3746 the full RequestElement retrieved from IFR data.
3747 If it points to NULL, the request string for the first
3748 varstore in form package will be merged into a
3749 <MultiConfigRequest> format string and return.
3750 @param AltCfgResp Pointer to a null-terminated Unicode string in
3751 <ConfigAltResp> format. When the pointer is to NULL,
3752 the full default value string retrieved from IFR data
3753 will return. When the pinter is to a string, the
3754 full default value string retrieved from IFR data
3755 will be merged into the input string and return.
3756 When Request points to NULL, the default value string
3757 for each varstore in form package will be merged into
3758 a <MultiConfigAltResp> format string and return.
3759 @param PointerProgress Optional parameter, it can be NULL.
3760 When it is not NULL, if Request is NULL, it returns NULL.
3761 On return, points to a character in the Request
3762 string. Points to the string's null terminator if
3763 request was successful. Points to the most recent
3764 & before the first failing name / value pair (or
3765 the beginning of the string if the failure is in
3766 the first name / value pair) if the request was
3768 @retval EFI_SUCCESS The Results string is set to the full request string.
3769 And AltCfgResp contains all default value string.
3770 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
3771 @retval EFI_NOT_FOUND The varstore (Guid and Name) in Request string
3772 can't be found in Form package.
3773 @retval EFI_NOT_FOUND HiiPackage can't be got on the input HiiHandle.
3774 @retval EFI_INVALID_PARAMETER Request points to NULL.
3779 GetFullStringFromHiiFormPackages (
3780 IN HII_DATABASE_RECORD
*DataBaseRecord
,
3781 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
3782 IN OUT EFI_STRING
*Request
,
3783 IN OUT EFI_STRING
*AltCfgResp
,
3784 OUT EFI_STRING
*PointerProgress OPTIONAL
3788 UINT8
*HiiFormPackage
;
3790 IFR_BLOCK_DATA
*RequestBlockArray
;
3791 IFR_BLOCK_DATA
*BlockData
;
3792 IFR_DEFAULT_DATA
*DefaultValueData
;
3793 IFR_DEFAULT_DATA
*DefaultId
;
3794 IFR_DEFAULT_DATA
*DefaultIdArray
;
3795 IFR_VARSTORAGE_DATA
*VarStorageData
;
3796 EFI_STRING DefaultAltCfgResp
;
3797 EFI_STRING ConfigHdr
;
3798 EFI_STRING StringPtr
;
3799 EFI_STRING Progress
;
3801 if (DataBaseRecord
== NULL
|| DevicePath
== NULL
|| Request
== NULL
|| AltCfgResp
== NULL
) {
3802 return EFI_INVALID_PARAMETER
;
3806 // Initialize the local variables.
3808 RequestBlockArray
= NULL
;
3809 DefaultIdArray
= NULL
;
3810 VarStorageData
= NULL
;
3811 DefaultAltCfgResp
= NULL
;
3813 HiiFormPackage
= NULL
;
3815 Progress
= *Request
;
3817 Status
= GetFormPackageData (DataBaseRecord
, &HiiFormPackage
, &PackageSize
);
3818 if (EFI_ERROR (Status
)) {
3823 // 1. Get the request block array by Request String when Request string contains the block array.
3826 if (*Request
!= NULL
) {
3827 StringPtr
= *Request
;
3831 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
3832 Status
= EFI_INVALID_PARAMETER
;
3835 StringPtr
+= StrLen (L
"GUID=");
3836 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&NAME=", StrLen (L
"&NAME=")) != 0) {
3839 if (*StringPtr
== L
'\0') {
3840 Status
= EFI_INVALID_PARAMETER
;
3843 StringPtr
+= StrLen (L
"&NAME=");
3844 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&PATH=", StrLen (L
"&PATH=")) != 0) {
3847 if (*StringPtr
== L
'\0') {
3848 Status
= EFI_INVALID_PARAMETER
;
3851 StringPtr
+= StrLen (L
"&PATH=");
3852 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
3856 if (*StringPtr
== L
'\0') {
3858 // No request block is found.
3865 // If StringPtr != NULL, get the request elements.
3867 if (StringPtr
!= NULL
) {
3868 if (StrStr (StringPtr
, L
"&OFFSET=") != NULL
) {
3869 RequestBlockArray
= GetBlockElement(StringPtr
, &Progress
);
3871 RequestBlockArray
= GetNameElement(StringPtr
, &Progress
);
3874 if (RequestBlockArray
== NULL
) {
3875 Status
= EFI_INVALID_PARAMETER
;
3881 // Initialize DefaultIdArray to store the map between DeaultId and DefaultName
3883 DefaultIdArray
= (IFR_DEFAULT_DATA
*) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
3884 if (DefaultIdArray
== NULL
) {
3885 Status
= EFI_OUT_OF_RESOURCES
;
3888 InitializeListHead (&DefaultIdArray
->Entry
);
3891 // Initialize VarStorageData to store the var store Block and Default value information.
3893 VarStorageData
= (IFR_VARSTORAGE_DATA
*) AllocateZeroPool (sizeof (IFR_VARSTORAGE_DATA
));
3894 if (VarStorageData
== NULL
) {
3895 Status
= EFI_OUT_OF_RESOURCES
;
3898 InitializeListHead (&VarStorageData
->Entry
);
3899 InitializeListHead (&VarStorageData
->BlockEntry
);
3902 // 2. Parse FormPackage to get BlockArray and DefaultId Array for the request BlockArray.
3906 // Parse the opcode in form package to get the default setting.
3908 Status
= ParseIfrData (DataBaseRecord
->Handle
,
3910 (UINT32
) PackageSize
,
3915 if (EFI_ERROR (Status
)) {
3920 // No requested varstore in IFR data and directly return
3922 if (VarStorageData
->Type
== 0 && VarStorageData
->Name
== NULL
) {
3923 Status
= EFI_SUCCESS
;
3928 // 3. Construct Request Element (Block Name) for 2.1 and 2.2 case.
3930 Status
= GenerateHdr (VarStorageData
, DevicePath
, &ConfigHdr
);
3931 if (EFI_ERROR (Status
)) {
3935 if (RequestBlockArray
== NULL
) {
3936 if (!GenerateConfigRequest(ConfigHdr
, VarStorageData
, &Status
, Request
)) {
3942 // 4. Construct Default Value string in AltResp according to request element.
3943 // Go through all VarStorageData Entry and get the DefaultId array for each one
3944 // Then construct them all to : ConfigHdr AltConfigHdr ConfigBody AltConfigHdr ConfigBody
3946 Status
= GenerateAltConfigResp (DataBaseRecord
->Handle
,ConfigHdr
, VarStorageData
, DefaultIdArray
, &DefaultAltCfgResp
);
3947 if (EFI_ERROR (Status
)) {
3952 // 5. Merge string into the input AltCfgResp if the input *AltCfgResp is not NULL.
3954 if (*AltCfgResp
!= NULL
&& DefaultAltCfgResp
!= NULL
) {
3955 Status
= MergeDefaultString (AltCfgResp
, DefaultAltCfgResp
);
3956 FreePool (DefaultAltCfgResp
);
3957 } else if (*AltCfgResp
== NULL
) {
3958 *AltCfgResp
= DefaultAltCfgResp
;
3962 if (RequestBlockArray
!= NULL
) {
3964 // Free Link Array RequestBlockArray
3966 while (!IsListEmpty (&RequestBlockArray
->Entry
)) {
3967 BlockData
= BASE_CR (RequestBlockArray
->Entry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
3968 RemoveEntryList (&BlockData
->Entry
);
3969 if (BlockData
->Name
!= NULL
) {
3970 FreePool (BlockData
->Name
);
3972 FreePool (BlockData
);
3975 FreePool (RequestBlockArray
);
3978 if (VarStorageData
!= NULL
) {
3980 // Free link array VarStorageData
3982 while (!IsListEmpty (&VarStorageData
->BlockEntry
)) {
3983 BlockData
= BASE_CR (VarStorageData
->BlockEntry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
3984 RemoveEntryList (&BlockData
->Entry
);
3985 if (BlockData
->Name
!= NULL
) {
3986 FreePool (BlockData
->Name
);
3989 // Free default value link array
3991 while (!IsListEmpty (&BlockData
->DefaultValueEntry
)) {
3992 DefaultValueData
= BASE_CR (BlockData
->DefaultValueEntry
.ForwardLink
, IFR_DEFAULT_DATA
, Entry
);
3993 RemoveEntryList (&DefaultValueData
->Entry
);
3994 FreePool (DefaultValueData
);
3996 FreePool (BlockData
);
3998 if (VarStorageData
->Name
!= NULL
) {
3999 FreePool (VarStorageData
->Name
);
4000 VarStorageData
->Name
= NULL
;
4002 FreePool (VarStorageData
);
4005 if (DefaultIdArray
!= NULL
) {
4007 // Free DefaultId Array
4009 while (!IsListEmpty (&DefaultIdArray
->Entry
)) {
4010 DefaultId
= BASE_CR (DefaultIdArray
->Entry
.ForwardLink
, IFR_DEFAULT_DATA
, Entry
);
4011 RemoveEntryList (&DefaultId
->Entry
);
4012 FreePool (DefaultId
);
4014 FreePool (DefaultIdArray
);
4018 // Free the allocated string
4020 if (ConfigHdr
!= NULL
) {
4021 FreePool (ConfigHdr
);
4025 // Free Package data
4027 if (HiiFormPackage
!= NULL
) {
4028 FreePool (HiiFormPackage
);
4031 if (PointerProgress
!= NULL
) {
4032 if (*Request
== NULL
) {
4033 *PointerProgress
= NULL
;
4034 } else if (EFI_ERROR (Status
)) {
4035 *PointerProgress
= *Request
;
4037 *PointerProgress
= *Request
+ StrLen (*Request
);
4045 This function gets the full request resp string by
4046 parsing IFR data in HII form packages.
4048 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
4050 @param EfiVarStoreInfo The efi varstore info which is save in the EFI
4051 varstore data structure.
4052 @param Request Pointer to a null-terminated Unicode string in
4053 <ConfigRequest> format.
4054 @param RequestResp Pointer to a null-terminated Unicode string in
4055 <ConfigResp> format.
4056 @param AccessProgress On return, points to a character in the Request
4057 string. Points to the string's null terminator if
4058 request was successful. Points to the most recent
4059 & before the first failing name / value pair (or
4060 the beginning of the string if the failure is in
4061 the first name / value pair) if the request was
4064 @retval EFI_SUCCESS The Results string is set to the full request string.
4065 And AltCfgResp contains all default value string.
4066 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
4067 @retval EFI_INVALID_PARAMETER Request points to NULL.
4071 GetConfigRespFromEfiVarStore (
4072 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
4073 IN EFI_IFR_VARSTORE_EFI
*EfiVarStoreInfo
,
4074 IN EFI_STRING Request
,
4075 OUT EFI_STRING
*RequestResp
,
4076 OUT EFI_STRING
*AccessProgress
4080 EFI_STRING VarStoreName
;
4085 Status
= EFI_SUCCESS
;
4088 VarStoreName
= NULL
;
4089 *AccessProgress
= Request
;
4091 NameSize
= AsciiStrSize ((CHAR8
*)EfiVarStoreInfo
->Name
);
4092 VarStoreName
= AllocateZeroPool (NameSize
* sizeof (CHAR16
));
4093 if (VarStoreName
== NULL
) {
4094 Status
= EFI_OUT_OF_RESOURCES
;
4097 AsciiStrToUnicodeStrS ((CHAR8
*) EfiVarStoreInfo
->Name
, VarStoreName
, NameSize
);
4100 Status
= gRT
->GetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, NULL
, &BufferSize
, NULL
);
4101 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
4105 VarStore
= AllocateZeroPool (BufferSize
);
4106 ASSERT (VarStore
!= NULL
);
4107 Status
= gRT
->GetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, NULL
, &BufferSize
, VarStore
);
4108 if (EFI_ERROR (Status
)) {
4112 Status
= HiiBlockToConfig(This
, Request
, VarStore
, BufferSize
, RequestResp
, AccessProgress
);
4113 if (EFI_ERROR (Status
)) {
4118 if (VarStoreName
!= NULL
) {
4119 FreePool (VarStoreName
);
4122 if (VarStore
!= NULL
) {
4123 FreePool (VarStore
);
4131 This function route the full request resp string for efi varstore.
4133 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
4135 @param EfiVarStoreInfo The efi varstore info which is save in the EFI
4136 varstore data structure.
4137 @param RequestResp Pointer to a null-terminated Unicode string in
4138 <ConfigResp> format.
4139 @param Result Pointer to a null-terminated Unicode string in
4140 <ConfigResp> format.
4142 @retval EFI_SUCCESS The Results string is set to the full request string.
4143 And AltCfgResp contains all default value string.
4144 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
4145 @retval EFI_INVALID_PARAMETER Request points to NULL.
4149 RouteConfigRespForEfiVarStore (
4150 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
4151 IN EFI_IFR_VARSTORE_EFI
*EfiVarStoreInfo
,
4152 IN EFI_STRING RequestResp
,
4153 OUT EFI_STRING
*Result
4157 EFI_STRING VarStoreName
;
4163 Status
= EFI_SUCCESS
;
4166 VarStoreName
= NULL
;
4167 *Result
= RequestResp
;
4169 NameSize
= AsciiStrSize ((CHAR8
*)EfiVarStoreInfo
->Name
);
4170 VarStoreName
= AllocateZeroPool (NameSize
* sizeof (CHAR16
));
4171 if (VarStoreName
== NULL
) {
4172 Status
= EFI_OUT_OF_RESOURCES
;
4175 AsciiStrToUnicodeStrS ((CHAR8
*) EfiVarStoreInfo
->Name
, VarStoreName
, NameSize
);
4177 Status
= gRT
->GetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, NULL
, &BufferSize
, NULL
);
4178 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
4179 DEBUG ((DEBUG_ERROR
, "The variable does not exist!"));
4183 BlockSize
= BufferSize
;
4184 VarStore
= AllocateZeroPool (BufferSize
);
4185 ASSERT (VarStore
!= NULL
);
4186 Status
= gRT
->GetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, NULL
, &BufferSize
, VarStore
);
4187 if (EFI_ERROR (Status
)) {
4191 Status
= HiiConfigToBlock(This
, RequestResp
, VarStore
, &BlockSize
, Result
);
4192 if (EFI_ERROR (Status
)) {
4196 Status
= gRT
->SetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, EfiVarStoreInfo
->Attributes
, BufferSize
, VarStore
);
4197 if (EFI_ERROR (Status
)) {
4198 *Result
= RequestResp
;
4203 if (VarStoreName
!= NULL
) {
4204 FreePool (VarStoreName
);
4207 if (VarStore
!= NULL
) {
4208 FreePool (VarStore
);
4215 Validate the config request elements.
4217 @param ConfigElements A null-terminated Unicode string in <ConfigRequest> format,
4218 without configHdr field.
4220 @retval CHAR16 * THE first Name/value pair not correct.
4221 @retval NULL Success parse the name/value pair
4224 OffsetWidthValidate (
4225 CHAR16
*ConfigElements
4231 StringPtr
= ConfigElements
;
4235 if (StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) != 0) {
4239 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
4242 if (*StringPtr
== L
'\0') {
4246 StringPtr
+= StrLen (L
"&WIDTH=");
4247 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) != 0) {
4251 if (*StringPtr
== L
'\0') {
4258 Validate the config request elements.
4260 @param ConfigElements A null-terminated Unicode string in <ConfigRequest> format,
4261 without configHdr field.
4263 @retval CHAR16 * THE first Name/value pair not correct.
4264 @retval NULL Success parse the name/value pair
4269 CHAR16
*ConfigElements
4275 StringPtr
= ConfigElements
;
4279 if (*StringPtr
!= L
'&') {
4284 StringPtr
= StrStr (StringPtr
, L
"&");
4286 if (StringPtr
== NULL
) {
4293 Validate the config request string.
4295 @param ConfigRequest A null-terminated Unicode string in <ConfigRequest> format.
4297 @retval CHAR16 * THE first element not correct.
4298 @retval NULL Success parse the name/value pair
4302 ConfigRequestValidate (
4303 CHAR16
*ConfigRequest
4306 BOOLEAN HasNameField
;
4309 HasNameField
= TRUE
;
4310 StringPtr
= ConfigRequest
;
4313 // Check <ConfigHdr>
4315 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
4316 return ConfigRequest
;
4318 StringPtr
+= StrLen (L
"GUID=");
4319 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&NAME=", StrLen (L
"&NAME=")) != 0) {
4322 if (*StringPtr
== L
'\0') {
4323 return ConfigRequest
;
4325 StringPtr
+= StrLen (L
"&NAME=");
4326 if (*StringPtr
== L
'&') {
4327 HasNameField
= FALSE
;
4329 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&PATH=", StrLen (L
"&PATH=")) != 0) {
4332 if (*StringPtr
== L
'\0') {
4333 return ConfigRequest
;
4335 StringPtr
+= StrLen (L
"&PATH=");
4336 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
4340 if (*StringPtr
== L
'\0') {
4346 // Should be Buffer varstore, config request should be "OFFSET/Width" pairs.
4348 return OffsetWidthValidate(StringPtr
);
4351 // Should be Name/Value varstore, config request should be "&name1&name2..." pairs.
4353 return NameValueValidate(StringPtr
);
4358 This function allows a caller to extract the current configuration
4359 for one or more named elements from one or more drivers.
4361 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
4363 @param Request A null-terminated Unicode string in
4364 <MultiConfigRequest> format.
4365 @param Progress On return, points to a character in the Request
4366 string. Points to the string's null terminator if
4367 request was successful. Points to the most recent
4368 & before the first failing name / value pair (or
4369 the beginning of the string if the failure is in
4370 the first name / value pair) if the request was
4372 @param Results Null-terminated Unicode string in
4373 <MultiConfigAltResp> format which has all values
4374 filled in for the names in the Request string.
4375 String to be allocated by the called function.
4377 @retval EFI_SUCCESS The Results string is filled with the values
4378 corresponding to all requested names.
4379 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
4380 results that must be stored awaiting possible
4382 @retval EFI_NOT_FOUND Routing data doesn't match any known driver.
4383 Progress set to the "G" in "GUID" of the routing
4384 header that doesn't match. Note: There is no
4385 requirement that all routing data be validated
4386 before any configuration extraction.
4387 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Request
4388 parameter would result in this type of error. The
4389 Progress parameter is set to NULL.
4390 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set to most recent &
4391 before the error or the beginning of the string.
4392 @retval EFI_INVALID_PARAMETER The ExtractConfig function of the underlying HII
4393 Configuration Access Protocol returned
4394 EFI_INVALID_PARAMETER. Progress set to most recent
4395 & before the error or the beginning of the string.
4400 HiiConfigRoutingExtractConfig (
4401 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
4402 IN CONST EFI_STRING Request
,
4403 OUT EFI_STRING
*Progress
,
4404 OUT EFI_STRING
*Results
4407 HII_DATABASE_PRIVATE_DATA
*Private
;
4408 EFI_STRING StringPtr
;
4409 EFI_STRING ConfigRequest
;
4411 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
4412 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
4415 HII_DATABASE_RECORD
*Database
;
4416 UINT8
*DevicePathPkg
;
4417 UINT8
*CurrentDevicePath
;
4418 EFI_HANDLE DriverHandle
;
4419 EFI_HII_HANDLE HiiHandle
;
4420 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
4421 EFI_STRING AccessProgress
;
4422 EFI_STRING AccessResults
;
4423 EFI_STRING AccessProgressBackup
;
4424 EFI_STRING AccessResultsBackup
;
4425 EFI_STRING DefaultResults
;
4426 BOOLEAN FirstElement
;
4427 BOOLEAN IfrDataParsedFlag
;
4428 BOOLEAN IsEfiVarStore
;
4429 EFI_IFR_VARSTORE_EFI
*EfiVarStoreInfo
;
4430 EFI_STRING ErrorPtr
;
4431 UINTN DevicePathSize
;
4432 UINTN ConigStringSize
;
4433 UINTN ConigStringSizeNewsize
;
4434 EFI_STRING ConfigStringPtr
;
4436 if (This
== NULL
|| Progress
== NULL
|| Results
== NULL
) {
4437 return EFI_INVALID_PARAMETER
;
4440 if (Request
== NULL
) {
4442 return EFI_INVALID_PARAMETER
;
4445 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
4446 StringPtr
= Request
;
4447 *Progress
= StringPtr
;
4448 DefaultResults
= NULL
;
4449 ConfigRequest
= NULL
;
4450 Status
= EFI_SUCCESS
;
4451 AccessResults
= NULL
;
4452 AccessProgress
= NULL
;
4453 AccessResultsBackup
= NULL
;
4454 AccessProgressBackup
= NULL
;
4456 IfrDataParsedFlag
= FALSE
;
4457 IsEfiVarStore
= FALSE
;
4458 EfiVarStoreInfo
= NULL
;
4461 // The first element of <MultiConfigRequest> should be
4462 // <GuidHdr>, which is in 'GUID='<Guid> syntax.
4464 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
4465 return EFI_INVALID_PARAMETER
;
4468 FirstElement
= TRUE
;
4471 // Allocate a fix length of memory to store Results. Reallocate memory for
4472 // Results if this fix length is insufficient.
4474 *Results
= (EFI_STRING
) AllocateZeroPool (MAX_STRING_LENGTH
);
4475 if (*Results
== NULL
) {
4476 return EFI_OUT_OF_RESOURCES
;
4479 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) == 0) {
4481 // If parsing error, set Progress to the beginning of the <MultiConfigRequest>
4482 // or most recent & before the error.
4484 if (StringPtr
== Request
) {
4485 *Progress
= StringPtr
;
4487 *Progress
= StringPtr
- 1;
4491 // Process each <ConfigRequest> of <MultiConfigRequest>
4493 Length
= CalculateConfigStringLen (StringPtr
);
4494 ConfigRequest
= AllocateCopyPool ((Length
+ 1) * sizeof (CHAR16
), StringPtr
);
4495 if (ConfigRequest
== NULL
) {
4496 Status
= EFI_OUT_OF_RESOURCES
;
4499 *(ConfigRequest
+ Length
) = 0;
4502 // Get the UEFI device path
4504 Status
= GetDevicePath (ConfigRequest
, (UINT8
**) &DevicePath
);
4505 if (EFI_ERROR (Status
)) {
4510 // Find driver which matches the routing data.
4512 DriverHandle
= NULL
;
4515 for (Link
= Private
->DatabaseList
.ForwardLink
;
4516 Link
!= &Private
->DatabaseList
;
4517 Link
= Link
->ForwardLink
4519 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
4520 if ((DevicePathPkg
= Database
->PackageList
->DevicePathPkg
) != NULL
) {
4521 CurrentDevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
4522 DevicePathSize
= GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) CurrentDevicePath
);
4523 if ((CompareMem (DevicePath
,CurrentDevicePath
,DevicePathSize
) == 0) && IsThisPackageList(Database
, ConfigRequest
)) {
4524 DriverHandle
= Database
->DriverHandle
;
4525 HiiHandle
= Database
->Handle
;
4532 // Try to find driver handle by device path.
4534 if (DriverHandle
== NULL
) {
4535 TempDevicePath
= DevicePath
;
4536 Status
= gBS
->LocateDevicePath (
4537 &gEfiDevicePathProtocolGuid
,
4541 if (EFI_ERROR (Status
) || (DriverHandle
== NULL
)) {
4543 // Routing data does not match any known driver.
4544 // Set Progress to the 'G' in "GUID" of the routing header.
4546 *Progress
= StringPtr
;
4547 Status
= EFI_NOT_FOUND
;
4553 // Validate ConfigRequest String.
4555 ErrorPtr
= ConfigRequestValidate(ConfigRequest
);
4556 if (ErrorPtr
!= NULL
) {
4557 *Progress
= StrStr (StringPtr
, ErrorPtr
);
4558 Status
= EFI_INVALID_PARAMETER
;
4563 // Check whether ConfigRequest contains request string.
4565 IfrDataParsedFlag
= FALSE
;
4566 if ((HiiHandle
!= NULL
) && !GetElementsFromRequest(ConfigRequest
)) {
4568 // Get the full request string from IFR when HiiPackage is registered to HiiHandle
4570 IfrDataParsedFlag
= TRUE
;
4571 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &ConfigRequest
, &DefaultResults
, &AccessProgress
);
4572 if (EFI_ERROR (Status
)) {
4574 // AccessProgress indicates the parsing progress on <ConfigRequest>.
4575 // Map it to the progress on <MultiConfigRequest> then return it.
4577 ASSERT (AccessProgress
!= NULL
);
4578 *Progress
= StrStr (StringPtr
, AccessProgress
);
4582 // Not any request block is found.
4584 if (!GetElementsFromRequest(ConfigRequest
)) {
4585 AccessResults
= AllocateCopyPool (StrSize (ConfigRequest
), ConfigRequest
);
4586 goto NextConfigString
;
4591 // Check whether this ConfigRequest is search from Efi varstore type storage.
4593 Status
= GetVarStoreType(Database
, ConfigRequest
, &IsEfiVarStore
, &EfiVarStoreInfo
);
4594 if (EFI_ERROR (Status
)) {
4598 if (IsEfiVarStore
) {
4600 // Call the GetVariable function to extract settings.
4602 Status
= GetConfigRespFromEfiVarStore(This
, EfiVarStoreInfo
, ConfigRequest
, &AccessResults
, &AccessProgress
);
4603 FreePool (EfiVarStoreInfo
);
4604 if (EFI_ERROR (Status
)) {
4606 // AccessProgress indicates the parsing progress on <ConfigRequest>.
4607 // Map it to the progress on <MultiConfigRequest> then return it.
4609 *Progress
= StrStr (StringPtr
, AccessProgress
);
4614 // For EfiVarstore, call corresponding ConfigAccess protocol to get the AltCfgResp from driver.
4616 Status
= gBS
->HandleProtocol (
4618 &gEfiHiiConfigAccessProtocolGuid
,
4619 (VOID
**) &ConfigAccess
4621 if (EFI_ERROR (Status
)) {
4623 // The driver has EfiVarStore, may not install ConfigAccess protocol.
4624 // So ignore the error status in this case.
4626 Status
= EFI_SUCCESS
;
4628 Status
= ConfigAccess
->ExtractConfig (
4631 &AccessProgressBackup
,
4632 &AccessResultsBackup
4634 if (!EFI_ERROR(Status
)) {
4636 //Merge the AltCfgResp in AccessResultsBackup to AccessResults
4638 if ((AccessResultsBackup
!= NULL
) && (StrStr (AccessResultsBackup
, L
"&ALTCFG=") != NULL
)) {
4639 ConigStringSize
= StrSize (AccessResults
);
4640 ConfigStringPtr
= StrStr (AccessResultsBackup
, L
"&GUID=");
4641 ConigStringSizeNewsize
= StrSize (ConfigStringPtr
) + ConigStringSize
+ sizeof (CHAR16
);
4642 AccessResults
= (EFI_STRING
) ReallocatePool (
4644 ConigStringSizeNewsize
,
4646 StrCatS (AccessResults
, ConigStringSizeNewsize
/ sizeof (CHAR16
), ConfigStringPtr
);
4650 // In the ExtractConfig function of some driver may not support EfiVarStore,
4651 // may return error status, just ignore the error status in this case.
4653 Status
= EFI_SUCCESS
;
4655 if (AccessResultsBackup
!= NULL
) {
4656 FreePool (AccessResultsBackup
);
4657 AccessResultsBackup
= NULL
;
4662 // Call corresponding ConfigAccess protocol to extract settings
4664 Status
= gBS
->HandleProtocol (
4666 &gEfiHiiConfigAccessProtocolGuid
,
4667 (VOID
**) &ConfigAccess
4669 if (EFI_ERROR (Status
)) {
4673 Status
= ConfigAccess
->ExtractConfig (
4680 if (EFI_ERROR (Status
)) {
4682 // AccessProgress indicates the parsing progress on <ConfigRequest>.
4683 // Map it to the progress on <MultiConfigRequest> then return it.
4685 *Progress
= StrStr (StringPtr
, AccessProgress
);
4690 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'
4691 // which separates the first <ConfigAltResp> and the following ones.
4693 ASSERT (*AccessProgress
== 0);
4696 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
4698 if (!IfrDataParsedFlag
&& HiiHandle
!= NULL
) {
4699 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &ConfigRequest
, &DefaultResults
, NULL
);
4700 ASSERT_EFI_ERROR (Status
);
4703 FreePool (DevicePath
);
4706 if (DefaultResults
!= NULL
) {
4707 Status
= MergeDefaultString (&AccessResults
, DefaultResults
);
4708 ASSERT_EFI_ERROR (Status
);
4709 FreePool (DefaultResults
);
4710 DefaultResults
= NULL
;
4714 if (!FirstElement
) {
4715 Status
= AppendToMultiString (Results
, L
"&");
4716 ASSERT_EFI_ERROR (Status
);
4719 Status
= AppendToMultiString (Results
, AccessResults
);
4720 ASSERT_EFI_ERROR (Status
);
4722 FirstElement
= FALSE
;
4724 FreePool (AccessResults
);
4725 AccessResults
= NULL
;
4726 FreePool (ConfigRequest
);
4727 ConfigRequest
= NULL
;
4730 // Go to next <ConfigRequest> (skip '&').
4732 StringPtr
+= Length
;
4733 if (*StringPtr
== 0) {
4734 *Progress
= StringPtr
;
4742 if (EFI_ERROR (Status
)) {
4743 FreePool (*Results
);
4747 if (ConfigRequest
!= NULL
) {
4748 FreePool (ConfigRequest
);
4751 if (AccessResults
!= NULL
) {
4752 FreePool (AccessResults
);
4755 if (DefaultResults
!= NULL
) {
4756 FreePool (DefaultResults
);
4759 if (DevicePath
!= NULL
) {
4760 FreePool (DevicePath
);
4768 This function allows the caller to request the current configuration for the
4769 entirety of the current HII database and returns the data in a
4770 null-terminated Unicode string.
4772 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
4774 @param Results Null-terminated Unicode string in
4775 <MultiConfigAltResp> format which has all values
4776 filled in for the entirety of the current HII
4777 database. String to be allocated by the called
4778 function. De-allocation is up to the caller.
4780 @retval EFI_SUCCESS The Results string is filled with the values
4781 corresponding to all requested names.
4782 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
4783 results that must be stored awaiting possible
4785 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Results
4786 parameter would result in this type of error.
4791 HiiConfigRoutingExportConfig (
4792 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
4793 OUT EFI_STRING
*Results
4797 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
4798 EFI_STRING AccessResults
;
4799 EFI_STRING Progress
;
4800 EFI_STRING StringPtr
;
4801 EFI_STRING ConfigRequest
;
4803 EFI_HANDLE
*ConfigAccessHandles
;
4804 UINTN NumberConfigAccessHandles
;
4805 BOOLEAN FirstElement
;
4806 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
4807 EFI_HII_HANDLE HiiHandle
;
4808 EFI_STRING DefaultResults
;
4809 HII_DATABASE_PRIVATE_DATA
*Private
;
4811 HII_DATABASE_RECORD
*Database
;
4812 UINT8
*DevicePathPkg
;
4813 UINT8
*CurrentDevicePath
;
4814 BOOLEAN IfrDataParsedFlag
;
4816 if (This
== NULL
|| Results
== NULL
) {
4817 return EFI_INVALID_PARAMETER
;
4820 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
4823 // Allocate a fix length of memory to store Results. Reallocate memory for
4824 // Results if this fix length is insufficient.
4826 *Results
= (EFI_STRING
) AllocateZeroPool (MAX_STRING_LENGTH
);
4827 if (*Results
== NULL
) {
4828 return EFI_OUT_OF_RESOURCES
;
4831 NumberConfigAccessHandles
= 0;
4832 Status
= gBS
->LocateHandleBuffer (
4834 &gEfiHiiConfigAccessProtocolGuid
,
4836 &NumberConfigAccessHandles
,
4837 &ConfigAccessHandles
4839 if (EFI_ERROR (Status
)) {
4843 FirstElement
= TRUE
;
4845 for (Index
= 0; Index
< NumberConfigAccessHandles
; Index
++) {
4846 Status
= gBS
->HandleProtocol (
4847 ConfigAccessHandles
[Index
],
4848 &gEfiHiiConfigAccessProtocolGuid
,
4849 (VOID
**) &ConfigAccess
4851 if (EFI_ERROR (Status
)) {
4856 // Get DevicePath and HiiHandle for this ConfigAccess driver handle
4858 IfrDataParsedFlag
= FALSE
;
4861 DefaultResults
= NULL
;
4863 ConfigRequest
= NULL
;
4864 DevicePath
= DevicePathFromHandle (ConfigAccessHandles
[Index
]);
4865 if (DevicePath
!= NULL
) {
4866 for (Link
= Private
->DatabaseList
.ForwardLink
;
4867 Link
!= &Private
->DatabaseList
;
4868 Link
= Link
->ForwardLink
4870 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
4871 if ((DevicePathPkg
= Database
->PackageList
->DevicePathPkg
) != NULL
) {
4872 CurrentDevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
4876 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) CurrentDevicePath
)
4878 HiiHandle
= Database
->Handle
;
4885 Status
= ConfigAccess
->ExtractConfig (
4891 if (EFI_ERROR (Status
)) {
4893 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
4895 if (HiiHandle
!= NULL
&& DevicePath
!= NULL
) {
4896 IfrDataParsedFlag
= TRUE
;
4897 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &ConfigRequest
, &DefaultResults
, NULL
);
4899 // Get the full request string to get the Current setting again.
4901 if (!EFI_ERROR (Status
) && ConfigRequest
!= NULL
) {
4902 Status
= ConfigAccess
->ExtractConfig (
4908 FreePool (ConfigRequest
);
4910 Status
= EFI_NOT_FOUND
;
4915 if (!EFI_ERROR (Status
)) {
4917 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
4919 if (!IfrDataParsedFlag
&& HiiHandle
!= NULL
&& DevicePath
!= NULL
) {
4920 StringPtr
= StrStr (AccessResults
, L
"&GUID=");
4921 if (StringPtr
!= NULL
) {
4924 if (GetElementsFromRequest (AccessResults
)) {
4925 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &AccessResults
, &DefaultResults
, NULL
);
4926 ASSERT_EFI_ERROR (Status
);
4928 if (StringPtr
!= NULL
) {
4933 // Merge the default sting from IFR code into the got setting from driver.
4935 if (DefaultResults
!= NULL
) {
4936 Status
= MergeDefaultString (&AccessResults
, DefaultResults
);
4937 ASSERT_EFI_ERROR (Status
);
4938 FreePool (DefaultResults
);
4939 DefaultResults
= NULL
;
4943 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'
4944 // which separates the first <ConfigAltResp> and the following ones.
4946 if (!FirstElement
) {
4947 Status
= AppendToMultiString (Results
, L
"&");
4948 ASSERT_EFI_ERROR (Status
);
4951 Status
= AppendToMultiString (Results
, AccessResults
);
4952 ASSERT_EFI_ERROR (Status
);
4954 FirstElement
= FALSE
;
4956 FreePool (AccessResults
);
4957 AccessResults
= NULL
;
4960 FreePool (ConfigAccessHandles
);
4967 This function processes the results of processing forms and routes it to the
4968 appropriate handlers or storage.
4970 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
4972 @param Configuration A null-terminated Unicode string in
4973 <MulltiConfigResp> format.
4974 @param Progress A pointer to a string filled in with the offset of
4975 the most recent & before the first failing name /
4976 value pair (or the beginning of the string if the
4977 failure is in the first name / value pair) or the
4978 terminating NULL if all was successful.
4980 @retval EFI_SUCCESS The results have been distributed or are awaiting
4982 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
4983 results that must be stored awaiting possible
4985 @retval EFI_INVALID_PARAMETER Passing in a NULL for the Configuration parameter
4986 would result in this type of error.
4987 @retval EFI_NOT_FOUND Target for the specified routing data was not
4993 HiiConfigRoutingRouteConfig (
4994 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
4995 IN CONST EFI_STRING Configuration
,
4996 OUT EFI_STRING
*Progress
4999 HII_DATABASE_PRIVATE_DATA
*Private
;
5000 EFI_STRING StringPtr
;
5001 EFI_STRING ConfigResp
;
5004 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
5005 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
5007 HII_DATABASE_RECORD
*Database
;
5008 UINT8
*DevicePathPkg
;
5009 UINT8
*CurrentDevicePath
;
5010 EFI_HANDLE DriverHandle
;
5011 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
5012 EFI_STRING AccessProgress
;
5013 EFI_IFR_VARSTORE_EFI
*EfiVarStoreInfo
;
5014 BOOLEAN IsEfiVarstore
;
5015 UINTN DevicePathSize
;
5017 if (This
== NULL
|| Progress
== NULL
) {
5018 return EFI_INVALID_PARAMETER
;
5021 if (Configuration
== NULL
) {
5023 return EFI_INVALID_PARAMETER
;
5026 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
5027 StringPtr
= Configuration
;
5028 *Progress
= StringPtr
;
5030 AccessProgress
= NULL
;
5031 EfiVarStoreInfo
= NULL
;
5032 IsEfiVarstore
= FALSE
;
5035 // The first element of <MultiConfigResp> should be
5036 // <GuidHdr>, which is in 'GUID='<Guid> syntax.
5038 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
5039 return EFI_INVALID_PARAMETER
;
5042 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) == 0) {
5044 // If parsing error, set Progress to the beginning of the <MultiConfigResp>
5045 // or most recent & before the error.
5047 if (StringPtr
== Configuration
) {
5048 *Progress
= StringPtr
;
5050 *Progress
= StringPtr
- 1;
5054 // Process each <ConfigResp> of <MultiConfigResp>
5056 Length
= CalculateConfigStringLen (StringPtr
);
5057 ConfigResp
= AllocateCopyPool ((Length
+ 1) * sizeof (CHAR16
), StringPtr
);
5058 if (ConfigResp
== NULL
) {
5059 return EFI_OUT_OF_RESOURCES
;
5062 // Append '\0' to the end of ConfigRequest
5064 *(ConfigResp
+ Length
) = 0;
5067 // Get the UEFI device path
5069 Status
= GetDevicePath (ConfigResp
, (UINT8
**) &DevicePath
);
5070 if (EFI_ERROR (Status
)) {
5071 FreePool (ConfigResp
);
5076 // Find driver which matches the routing data.
5078 DriverHandle
= NULL
;
5079 for (Link
= Private
->DatabaseList
.ForwardLink
;
5080 Link
!= &Private
->DatabaseList
;
5081 Link
= Link
->ForwardLink
5083 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
5085 if ((DevicePathPkg
= Database
->PackageList
->DevicePathPkg
) != NULL
) {
5086 CurrentDevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
5087 DevicePathSize
= GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) CurrentDevicePath
);
5088 if ((CompareMem (DevicePath
,CurrentDevicePath
,DevicePathSize
) == 0) && IsThisPackageList(Database
, ConfigResp
)) {
5089 DriverHandle
= Database
->DriverHandle
;
5096 // Try to find driver handle by device path.
5098 if (DriverHandle
== NULL
) {
5099 TempDevicePath
= DevicePath
;
5100 Status
= gBS
->LocateDevicePath (
5101 &gEfiDevicePathProtocolGuid
,
5105 if (EFI_ERROR (Status
) || (DriverHandle
== NULL
)) {
5107 // Routing data does not match any known driver.
5108 // Set Progress to the 'G' in "GUID" of the routing header.
5110 FreePool (DevicePath
);
5111 *Progress
= StringPtr
;
5112 FreePool (ConfigResp
);
5113 return EFI_NOT_FOUND
;
5117 FreePool (DevicePath
);
5120 // Check whether this ConfigRequest is search from Efi varstore type storage.
5122 Status
= GetVarStoreType(Database
, ConfigResp
, &IsEfiVarstore
, &EfiVarStoreInfo
);
5123 if (EFI_ERROR (Status
)) {
5127 if (IsEfiVarstore
) {
5129 // Call the SetVariable function to route settings.
5131 Status
= RouteConfigRespForEfiVarStore(This
, EfiVarStoreInfo
, ConfigResp
, &AccessProgress
);
5132 FreePool (EfiVarStoreInfo
);
5135 // Call corresponding ConfigAccess protocol to route settings
5137 Status
= gBS
->HandleProtocol (
5139 &gEfiHiiConfigAccessProtocolGuid
,
5140 (VOID
**) &ConfigAccess
5142 if (EFI_ERROR (Status
)) {
5143 *Progress
= StringPtr
;
5144 FreePool (ConfigResp
);
5145 return EFI_NOT_FOUND
;
5148 Status
= ConfigAccess
->RouteConfig (
5154 if (EFI_ERROR (Status
)) {
5155 ASSERT (AccessProgress
!= NULL
);
5157 // AccessProgress indicates the parsing progress on <ConfigResp>.
5158 // Map it to the progress on <MultiConfigResp> then return it.
5160 *Progress
= StrStr (StringPtr
, AccessProgress
);
5162 FreePool (ConfigResp
);
5166 FreePool (ConfigResp
);
5170 // Go to next <ConfigResp> (skip '&').
5172 StringPtr
+= Length
;
5173 if (*StringPtr
== 0) {
5174 *Progress
= StringPtr
;
5187 This helper function is to be called by drivers to map configuration data
5188 stored in byte array ("block") formats such as UEFI Variables into current
5189 configuration strings.
5191 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
5193 @param ConfigRequest A null-terminated Unicode string in
5194 <ConfigRequest> format.
5195 @param Block Array of bytes defining the block's configuration.
5196 @param BlockSize Length in bytes of Block.
5197 @param Config Filled-in configuration string. String allocated
5198 by the function. Returned only if call is
5199 successful. It is <ConfigResp> string format.
5200 @param Progress A pointer to a string filled in with the offset of
5201 the most recent & before the first failing
5202 name/value pair (or the beginning of the string if
5203 the failure is in the first name / value pair) or
5204 the terminating NULL if all was successful.
5206 @retval EFI_SUCCESS The request succeeded. Progress points to the null
5207 terminator at the end of the ConfigRequest
5209 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress
5210 points to the first character of ConfigRequest.
5211 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigRequest or
5212 Block parameter would result in this type of
5213 error. Progress points to the first character of
5215 @retval EFI_DEVICE_ERROR Block not large enough. Progress undefined.
5216 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted string.
5217 Block is left updated and Progress points at
5218 the "&" preceding the first non-<BlockName>.
5224 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
5225 IN CONST EFI_STRING ConfigRequest
,
5226 IN CONST UINT8
*Block
,
5227 IN CONST UINTN BlockSize
,
5228 OUT EFI_STRING
*Config
,
5229 OUT EFI_STRING
*Progress
5232 HII_DATABASE_PRIVATE_DATA
*Private
;
5233 EFI_STRING StringPtr
;
5241 EFI_STRING ValueStr
;
5242 EFI_STRING ConfigElement
;
5250 if (This
== NULL
|| Progress
== NULL
|| Config
== NULL
) {
5251 return EFI_INVALID_PARAMETER
;
5254 if (Block
== NULL
|| ConfigRequest
== NULL
) {
5255 *Progress
= ConfigRequest
;
5256 return EFI_INVALID_PARAMETER
;
5260 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
5261 ASSERT (Private
!= NULL
);
5263 StringPtr
= ConfigRequest
;
5266 ConfigElement
= NULL
;
5269 // Allocate a fix length of memory to store Results. Reallocate memory for
5270 // Results if this fix length is insufficient.
5272 *Config
= (EFI_STRING
) AllocateZeroPool (MAX_STRING_LENGTH
);
5273 if (*Config
== NULL
) {
5274 return EFI_OUT_OF_RESOURCES
;
5280 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
5281 *Progress
= StringPtr
;
5282 Status
= EFI_INVALID_PARAMETER
;
5285 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"PATH=", StrLen (L
"PATH=")) != 0) {
5288 if (*StringPtr
== 0) {
5289 *Progress
= StringPtr
- 1;
5290 Status
= EFI_INVALID_PARAMETER
;
5294 while (*StringPtr
!= L
'&' && *StringPtr
!= 0) {
5297 if (*StringPtr
== 0) {
5298 *Progress
= StringPtr
;
5300 AppendToMultiString(Config
, ConfigRequest
);
5301 HiiToLower (*Config
);
5311 // Copy <ConfigHdr> and an additional '&' to <ConfigResp>
5313 TemChar
= *StringPtr
;
5315 AppendToMultiString(Config
, ConfigRequest
);
5316 *StringPtr
= TemChar
;
5319 // Parse each <RequestElement> if exists
5320 // Only <BlockName> format is supported by this help function.
5321 // <BlockName> ::= 'OFFSET='<Number>&'WIDTH='<Number>
5323 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"OFFSET=", StrLen (L
"OFFSET=")) == 0) {
5325 // Back up the header of one <BlockName>
5329 StringPtr
+= StrLen (L
"OFFSET=");
5333 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
5334 if (EFI_ERROR (Status
)) {
5335 *Progress
= TmpPtr
- 1;
5342 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
5344 FreePool (TmpBuffer
);
5346 StringPtr
+= Length
;
5347 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
5348 *Progress
= TmpPtr
- 1;
5349 Status
= EFI_INVALID_PARAMETER
;
5352 StringPtr
+= StrLen (L
"&WIDTH=");
5357 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
5358 if (EFI_ERROR (Status
)) {
5359 *Progress
= TmpPtr
- 1;
5366 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
5368 FreePool (TmpBuffer
);
5370 StringPtr
+= Length
;
5371 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
5372 *Progress
= TmpPtr
- 1;
5373 Status
= EFI_INVALID_PARAMETER
;
5378 // Calculate Value and convert it to hex string.
5380 if (Offset
+ Width
> BlockSize
) {
5381 *Progress
= StringPtr
;
5382 Status
= EFI_DEVICE_ERROR
;
5386 Value
= (UINT8
*) AllocateZeroPool (Width
);
5387 if (Value
== NULL
) {
5388 *Progress
= ConfigRequest
;
5389 Status
= EFI_OUT_OF_RESOURCES
;
5393 CopyMem (Value
, (UINT8
*) Block
+ Offset
, Width
);
5395 Length
= Width
* 2 + 1;
5396 ValueStr
= (EFI_STRING
) AllocateZeroPool (Length
* sizeof (CHAR16
));
5397 if (ValueStr
== NULL
) {
5398 *Progress
= ConfigRequest
;
5399 Status
= EFI_OUT_OF_RESOURCES
;
5403 TemString
= ValueStr
;
5404 TemBuffer
= Value
+ Width
- 1;
5405 for (Index
= 0; Index
< Width
; Index
++, TemBuffer
--) {
5406 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
5413 // Build a ConfigElement
5415 Length
+= StringPtr
- TmpPtr
+ 1 + StrLen (L
"VALUE=");
5416 ConfigElement
= (EFI_STRING
) AllocateZeroPool (Length
* sizeof (CHAR16
));
5417 if (ConfigElement
== NULL
) {
5418 Status
= EFI_OUT_OF_RESOURCES
;
5421 CopyMem (ConfigElement
, TmpPtr
, (StringPtr
- TmpPtr
+ 1) * sizeof (CHAR16
));
5422 if (*StringPtr
== 0) {
5423 *(ConfigElement
+ (StringPtr
- TmpPtr
)) = L
'&';
5425 *(ConfigElement
+ (StringPtr
- TmpPtr
) + 1) = 0;
5426 StrCatS (ConfigElement
, Length
, L
"VALUE=");
5427 StrCatS (ConfigElement
, Length
, ValueStr
);
5429 AppendToMultiString (Config
, ConfigElement
);
5431 FreePool (ConfigElement
);
5432 FreePool (ValueStr
);
5433 ConfigElement
= NULL
;
5437 // If '\0', parsing is finished. Otherwise skip '&' to continue
5439 if (*StringPtr
== 0) {
5442 AppendToMultiString (Config
, L
"&");
5447 if (*StringPtr
!= 0) {
5448 *Progress
= StringPtr
- 1;
5449 Status
= EFI_INVALID_PARAMETER
;
5453 HiiToLower (*Config
);
5454 *Progress
= StringPtr
;
5458 if (*Config
!= NULL
) {
5462 if (ValueStr
!= NULL
) {
5463 FreePool (ValueStr
);
5465 if (Value
!= NULL
) {
5468 if (ConfigElement
!= NULL
) {
5469 FreePool (ConfigElement
);
5478 This helper function is to be called by drivers to map configuration strings
5479 to configurations stored in byte array ("block") formats such as UEFI Variables.
5481 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
5483 @param ConfigResp A null-terminated Unicode string in <ConfigResp>
5485 @param Block A possibly null array of bytes representing the
5486 current block. Only bytes referenced in the
5487 ConfigResp string in the block are modified. If
5488 this parameter is null or if the *BlockSize
5489 parameter is (on input) shorter than required by
5490 the Configuration string, only the BlockSize
5491 parameter is updated and an appropriate status
5492 (see below) is returned.
5493 @param BlockSize The length of the Block in units of UINT8. On
5494 input, this is the size of the Block. On output,
5495 if successful, contains the largest index of the
5496 modified byte in the Block, or the required buffer
5497 size if the Block is not large enough.
5498 @param Progress On return, points to an element of the ConfigResp
5499 string filled in with the offset of the most
5500 recent '&' before the first failing name / value
5501 pair (or the beginning of the string if the
5502 failure is in the first name / value pair) or the
5503 terminating NULL if all was successful.
5505 @retval EFI_SUCCESS The request succeeded. Progress points to the null
5506 terminator at the end of the ConfigResp string.
5507 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress
5508 points to the first character of ConfigResp.
5509 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigResp or
5510 Block parameter would result in this type of
5511 error. Progress points to the first character of
5513 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted name /
5514 value pair. Block is left updated and
5515 Progress points at the '&' preceding the first
5517 @retval EFI_BUFFER_TOO_SMALL Block not large enough. Progress undefined.
5518 BlockSize is updated with the required buffer size.
5519 @retval EFI_NOT_FOUND Target for the specified routing data was not found.
5520 Progress points to the "G" in "GUID" of the errant
5527 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
5528 IN CONST EFI_STRING ConfigResp
,
5529 IN OUT UINT8
*Block
,
5530 IN OUT UINTN
*BlockSize
,
5531 OUT EFI_STRING
*Progress
5534 HII_DATABASE_PRIVATE_DATA
*Private
;
5535 EFI_STRING StringPtr
;
5548 if (This
== NULL
|| BlockSize
== NULL
|| Progress
== NULL
) {
5549 return EFI_INVALID_PARAMETER
;
5552 *Progress
= ConfigResp
;
5553 if (ConfigResp
== NULL
) {
5554 return EFI_INVALID_PARAMETER
;
5557 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
5558 ASSERT (Private
!= NULL
);
5560 StringPtr
= ConfigResp
;
5561 BufferSize
= *BlockSize
;
5568 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
5569 *Progress
= StringPtr
;
5570 Status
= EFI_INVALID_PARAMETER
;
5573 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"PATH=", StrLen (L
"PATH=")) != 0) {
5576 if (*StringPtr
== 0) {
5577 *Progress
= StringPtr
;
5578 Status
= EFI_INVALID_PARAMETER
;
5582 while (*StringPtr
!= L
'&' && *StringPtr
!= 0) {
5585 if (*StringPtr
== 0) {
5586 *Progress
= StringPtr
;
5587 Status
= EFI_INVALID_PARAMETER
;
5592 // Parse each <ConfigElement> if exists
5593 // Only '&'<BlockConfig> format is supported by this help function.
5594 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE='<Number>
5596 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) == 0) {
5598 StringPtr
+= StrLen (L
"&OFFSET=");
5602 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
5603 if (EFI_ERROR (Status
)) {
5611 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
5613 FreePool (TmpBuffer
);
5615 StringPtr
+= Length
;
5616 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
5618 Status
= EFI_INVALID_PARAMETER
;
5621 StringPtr
+= StrLen (L
"&WIDTH=");
5626 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
5627 if (EFI_ERROR (Status
)) {
5635 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
5637 FreePool (TmpBuffer
);
5639 StringPtr
+= Length
;
5640 if (StrnCmp (StringPtr
, L
"&VALUE=", StrLen (L
"&VALUE=")) != 0) {
5642 Status
= EFI_INVALID_PARAMETER
;
5645 StringPtr
+= StrLen (L
"&VALUE=");
5650 Status
= GetValueOfNumber (StringPtr
, &Value
, &Length
);
5651 if (EFI_ERROR (Status
)) {
5656 StringPtr
+= Length
;
5657 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
5659 Status
= EFI_INVALID_PARAMETER
;
5664 // Update the Block with configuration info
5666 if ((Block
!= NULL
) && (Offset
+ Width
<= BufferSize
)) {
5667 CopyMem (Block
+ Offset
, Value
, Width
);
5669 if (Offset
+ Width
> MaxBlockSize
) {
5670 MaxBlockSize
= Offset
+ Width
;
5677 // If '\0', parsing is finished.
5679 if (*StringPtr
== 0) {
5685 // The input string is not ConfigResp format, return error.
5687 if (*StringPtr
!= 0) {
5688 *Progress
= StringPtr
;
5689 Status
= EFI_INVALID_PARAMETER
;
5693 *Progress
= StringPtr
+ StrLen (StringPtr
);
5694 *BlockSize
= MaxBlockSize
- 1;
5696 if (MaxBlockSize
> BufferSize
) {
5697 *BlockSize
= MaxBlockSize
;
5698 if (Block
!= NULL
) {
5699 return EFI_BUFFER_TOO_SMALL
;
5703 if (Block
== NULL
) {
5704 *Progress
= ConfigResp
;
5705 return EFI_INVALID_PARAMETER
;
5712 if (Value
!= NULL
) {
5720 This helper function is to be called by drivers to extract portions of
5721 a larger configuration string.
5723 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
5725 @param Configuration A null-terminated Unicode string in
5726 <MultiConfigAltResp> format.
5727 @param Guid A pointer to the GUID value to search for in the
5728 routing portion of the ConfigResp string when
5729 retrieving the requested data. If Guid is NULL,
5730 then all GUID values will be searched for.
5731 @param Name A pointer to the NAME value to search for in the
5732 routing portion of the ConfigResp string when
5733 retrieving the requested data. If Name is NULL,
5734 then all Name values will be searched for.
5735 @param DevicePath A pointer to the PATH value to search for in the
5736 routing portion of the ConfigResp string when
5737 retrieving the requested data. If DevicePath is
5738 NULL, then all DevicePath values will be searched
5740 @param AltCfgId A pointer to the ALTCFG value to search for in the
5741 routing portion of the ConfigResp string when
5742 retrieving the requested data. If this parameter
5743 is NULL, then the current setting will be
5745 @param AltCfgResp A pointer to a buffer which will be allocated by
5746 the function which contains the retrieved string
5747 as requested. This buffer is only allocated if
5748 the call was successful. It is <ConfigResp> format.
5750 @retval EFI_SUCCESS The request succeeded. The requested data was
5751 extracted and placed in the newly allocated
5753 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate AltCfgResp.
5754 @retval EFI_INVALID_PARAMETER Any parameter is invalid.
5755 @retval EFI_NOT_FOUND Target for the specified routing data was not
5762 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
5763 IN CONST EFI_STRING Configuration
,
5764 IN CONST EFI_GUID
*Guid
,
5765 IN CONST EFI_STRING Name
,
5766 IN CONST EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
5767 IN CONST UINT16
*AltCfgId
,
5768 OUT EFI_STRING
*AltCfgResp
5772 EFI_STRING StringPtr
;
5773 EFI_STRING HdrStart
;
5780 EFI_STRING AltIdStr
;
5797 if (This
== NULL
|| Configuration
== NULL
|| AltCfgResp
== NULL
) {
5798 return EFI_INVALID_PARAMETER
;
5801 StringPtr
= Configuration
;
5802 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
5803 return EFI_INVALID_PARAMETER
;
5807 // Generate the sub string for later matching.
5809 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*) Guid
, 1, &GuidStr
);
5812 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) DevicePath
),
5813 (VOID
*) DevicePath
,
5817 if (AltCfgId
!= NULL
) {
5818 GenerateSubStr (L
"ALTCFG=", sizeof (UINT16
), (VOID
*) AltCfgId
, 3, &AltIdStr
);
5821 GenerateSubStr (L
"NAME=", StrLen (Name
) * sizeof (CHAR16
), (VOID
*) Name
, 2, &NameStr
);
5823 GenerateSubStr (L
"NAME=", 0, NULL
, 2, &NameStr
);
5826 while (*StringPtr
!= 0) {
5828 // Try to match the GUID
5831 TmpPtr
= StrStr (StringPtr
, GuidStr
);
5832 if (TmpPtr
== NULL
) {
5833 Status
= EFI_NOT_FOUND
;
5839 // Jump to <NameHdr>
5842 StringPtr
= TmpPtr
+ StrLen (GuidStr
);
5844 StringPtr
= StrStr (TmpPtr
, L
"NAME=");
5845 if (StringPtr
== NULL
) {
5846 Status
= EFI_NOT_FOUND
;
5854 // Try to match the NAME
5856 if (GuidFlag
&& !NameFlag
) {
5857 if (StrnCmp (StringPtr
, NameStr
, StrLen (NameStr
)) != 0) {
5861 // Jump to <PathHdr>
5864 StringPtr
+= StrLen (NameStr
);
5866 StringPtr
= StrStr (StringPtr
, L
"PATH=");
5867 if (StringPtr
== NULL
) {
5868 Status
= EFI_NOT_FOUND
;
5877 // Try to match the DevicePath
5879 if (GuidFlag
&& NameFlag
&& !PathFlag
) {
5880 if (StrnCmp (StringPtr
, PathStr
, StrLen (PathStr
)) != 0) {
5885 // Jump to '&' before <DescHdr> or <ConfigBody>
5887 if (DevicePath
!= NULL
) {
5888 StringPtr
+= StrLen (PathStr
);
5890 StringPtr
= StrStr (StringPtr
, L
"&");
5891 if (StringPtr
== NULL
) {
5892 Status
= EFI_NOT_FOUND
;
5903 // Try to match the AltCfgId
5905 if (GuidFlag
&& NameFlag
&& PathFlag
) {
5906 if (AltCfgId
== NULL
) {
5908 // Return Current Setting when AltCfgId is NULL.
5910 Status
= OutputConfigBody (StringPtr
, &Result
);
5914 // Search the <ConfigAltResp> to get the <AltResp> with AltCfgId.
5916 if (StrnCmp (StringPtr
, AltIdStr
, StrLen (AltIdStr
)) != 0) {
5922 // Skip AltIdStr and &
5924 StringPtr
= StringPtr
+ StrLen (AltIdStr
);
5925 Status
= OutputConfigBody (StringPtr
, &Result
);
5931 Status
= EFI_NOT_FOUND
;
5935 if (!EFI_ERROR (Status
) && (Result
!= NULL
)) {
5937 // Copy the <ConfigHdr> and <ConfigBody>
5939 Length
= HdrEnd
- HdrStart
+ StrLen (Result
) + 1;
5940 *AltCfgResp
= AllocateZeroPool (Length
* sizeof (CHAR16
));
5941 if (*AltCfgResp
== NULL
) {
5942 Status
= EFI_OUT_OF_RESOURCES
;
5944 StrnCpyS (*AltCfgResp
, Length
, HdrStart
, HdrEnd
- HdrStart
);
5945 StrCatS (*AltCfgResp
, Length
, Result
);
5946 Status
= EFI_SUCCESS
;
5950 if (GuidStr
!= NULL
) {
5953 if (NameStr
!= NULL
) {
5956 if (PathStr
!= NULL
) {
5959 if (AltIdStr
!= NULL
) {
5960 FreePool (AltIdStr
);
5962 if (Result
!= NULL
) {