2 Implementation of interfaces function for EFI_HII_CONFIG_ROUTING_PROTOCOL.
4 Copyright (c) 2007 - 2016, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 #include "HiiDatabase.h"
17 extern HII_DATABASE_PRIVATE_DATA mPrivate
;
20 Calculate the number of Unicode characters of the incoming Configuration string,
21 not including NULL terminator.
23 This is a internal function.
25 @param String String in <MultiConfigRequest> or
26 <MultiConfigResp> format.
28 @return The number of Unicode characters.
32 CalculateConfigStringLen (
39 // "GUID=" should be the first element of incoming string.
41 ASSERT (String
!= NULL
);
42 ASSERT (StrnCmp (String
, L
"GUID=", StrLen (L
"GUID=")) == 0);
45 // The beginning of next <ConfigRequest>/<ConfigResp> should be "&GUID=".
46 // Will meet '\0' if there is only one <ConfigRequest>/<ConfigResp>.
48 TmpPtr
= StrStr (String
, L
"&GUID=");
50 return StrLen (String
);
53 return (TmpPtr
- String
);
58 Convert the hex UNICODE %02x encoding of a UEFI device path to binary
59 from <PathHdr> of <ConfigHdr>.
61 This is a internal function.
63 @param String UEFI configuration string
64 @param DevicePathData Binary of a UEFI device path.
66 @retval EFI_NOT_FOUND The device path is not invalid.
67 @retval EFI_INVALID_PARAMETER Any incoming parameter is invalid.
68 @retval EFI_OUT_OF_RESOURCES Lake of resources to store neccesary structures.
69 @retval EFI_SUCCESS The device path is retrieved and translated to
76 OUT UINT8
**DevicePathData
81 UINT8
*DevicePathBuffer
;
85 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
88 if (String
== NULL
|| DevicePathData
== NULL
) {
89 return EFI_INVALID_PARAMETER
;
93 // Find the 'PATH=' of <PathHdr> and skip it.
95 for (; (*String
!= 0 && StrnCmp (String
, L
"PATH=", StrLen (L
"PATH=")) != 0); String
++);
97 return EFI_INVALID_PARAMETER
;
100 // Check whether path data does exist.
102 String
+= StrLen (L
"PATH=");
104 return EFI_INVALID_PARAMETER
;
109 // The content between 'PATH=' of <ConfigHdr> and '&' of next element
110 // or '\0' (end of configuration string) is the UNICODE %02x bytes encoding
111 // of UEFI device path.
113 for (Length
= 0; *String
!= 0 && *String
!= L
'&'; String
++, Length
++);
115 // Check DevicePath Length
117 if (((Length
+ 1) / 2) < sizeof (EFI_DEVICE_PATH_PROTOCOL
)) {
118 return EFI_NOT_FOUND
;
122 // The data in <PathHdr> is encoded as hex UNICODE %02x bytes in the same order
123 // as the device path resides in RAM memory.
124 // Translate the data into binary.
126 DevicePathBuffer
= (UINT8
*) AllocateZeroPool ((Length
+ 1) / 2);
127 if (DevicePathBuffer
== NULL
) {
128 return EFI_OUT_OF_RESOURCES
;
132 // Convert DevicePath
134 ZeroMem (TemStr
, sizeof (TemStr
));
135 for (Index
= 0; Index
< Length
; Index
++) {
136 TemStr
[0] = PathHdr
[Index
];
137 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
138 if ((Index
& 1) == 0) {
139 DevicePathBuffer
[Index
/2] = DigitUint8
;
141 DevicePathBuffer
[Index
/2] = (UINT8
) ((DevicePathBuffer
[Index
/2] << 4) + DigitUint8
);
146 // Validate DevicePath
148 DevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) DevicePathBuffer
;
149 while (!IsDevicePathEnd (DevicePath
)) {
150 if ((DevicePath
->Type
== 0) || (DevicePath
->SubType
== 0) || (DevicePathNodeLength (DevicePath
) < sizeof (EFI_DEVICE_PATH_PROTOCOL
))) {
152 // Invalid device path
154 FreePool (DevicePathBuffer
);
155 return EFI_NOT_FOUND
;
157 DevicePath
= NextDevicePathNode (DevicePath
);
161 // return the device path
163 *DevicePathData
= DevicePathBuffer
;
168 Converts the unicode character of the string from uppercase to lowercase.
169 This is a internal function.
171 @param ConfigString String to be converted
177 IN EFI_STRING ConfigString
183 ASSERT (ConfigString
!= NULL
);
186 // Convert all hex digits in range [A-F] in the configuration header to [a-f]
188 for (String
= ConfigString
, Lower
= FALSE
; *String
!= L
'\0'; String
++) {
189 if (*String
== L
'=') {
191 } else if (*String
== L
'&') {
193 } else if (Lower
&& *String
>= L
'A' && *String
<= L
'F') {
194 *String
= (CHAR16
) (*String
- L
'A' + L
'a');
202 Generate a sub string then output it.
204 This is a internal function.
206 @param String A constant string which is the prefix of the to be
207 generated string, e.g. GUID=
209 @param BufferLen The length of the Buffer in bytes.
211 @param Buffer Points to a buffer which will be converted to be the
212 content of the generated string.
214 @param Flag If 1, the buffer contains data for the value of GUID or PATH stored in
215 UINT8 *; if 2, the buffer contains unicode string for the value of NAME;
216 if 3, the buffer contains other data.
218 @param SubStr Points to the output string. It's caller's
219 responsibility to free this buffer.
225 IN CONST EFI_STRING String
,
229 OUT EFI_STRING
*SubStr
234 EFI_STRING StringHeader
;
240 ASSERT (String
!= NULL
&& SubStr
!= NULL
);
242 if (Buffer
== NULL
) {
243 *SubStr
= AllocateCopyPool (StrSize (String
), String
);
244 ASSERT (*SubStr
!= NULL
);
249 // Header + Data + '&' + '\0'
251 Length
= StrLen (String
) + BufferLen
* 2 + 1 + 1;
252 Str
= AllocateZeroPool (Length
* sizeof (CHAR16
));
253 ASSERT (Str
!= NULL
);
255 StrCpyS (Str
, Length
, String
);
257 StringHeader
= Str
+ StrLen (String
);
258 TemString
= (CHAR16
*) StringHeader
;
263 // Convert Buffer to Hex String in reverse order
265 TemBuffer
= ((UINT8
*) Buffer
);
266 for (Index
= 0; Index
< BufferLen
; Index
++, TemBuffer
++) {
267 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
272 // Check buffer is enough
274 TemName
= (CHAR16
*) Buffer
;
275 ASSERT ((BufferLen
* 2 + 1) >= (StrLen (TemName
) * 4 + 1));
277 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
279 for (; *TemName
!= L
'\0'; TemName
++) {
280 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemName
, 4);
285 // Convert Buffer to Hex String
287 TemBuffer
= ((UINT8
*) Buffer
) + BufferLen
- 1;
288 for (Index
= 0; Index
< BufferLen
; Index
++, TemBuffer
--) {
289 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
297 // Convert the uppercase to lowercase since <HexAf> is defined in lowercase format.
299 StrCatS (Str
, Length
, L
"&");
307 Retrieve the <ConfigBody> from String then output it.
309 This is a internal function.
311 @param String A sub string of a configuration string in
312 <MultiConfigAltResp> format.
313 @param ConfigBody Points to the output string. It's caller's
314 responsibility to free this buffer.
316 @retval EFI_INVALID_PARAMETER There is no form package in current hii database.
317 @retval EFI_OUT_OF_RESOURCES Not enough memory to finish this operation.
318 @retval EFI_SUCCESS All existing storage is exported.
323 IN EFI_STRING String
,
324 OUT EFI_STRING
*ConfigBody
331 if (String
== NULL
|| ConfigBody
== NULL
) {
332 return EFI_INVALID_PARAMETER
;
336 // The setting information should start OFFSET, not ALTCFG.
338 if (StrnCmp (String
, L
"&ALTCFG=", StrLen (L
"&ALTCFG=")) == 0) {
339 return EFI_INVALID_PARAMETER
;
342 TmpPtr
= StrStr (String
, L
"GUID=");
343 if (TmpPtr
== NULL
) {
345 // It is the last <ConfigResp> of the incoming configuration string.
347 Result
= AllocateCopyPool (StrSize (String
), String
);
348 if (Result
== NULL
) {
349 return EFI_OUT_OF_RESOURCES
;
351 *ConfigBody
= Result
;
356 Length
= TmpPtr
- String
;
358 return EFI_NOT_FOUND
;
360 Result
= AllocateCopyPool (Length
* sizeof (CHAR16
), String
);
361 if (Result
== NULL
) {
362 return EFI_OUT_OF_RESOURCES
;
365 *(Result
+ Length
- 1) = 0;
366 *ConfigBody
= Result
;
371 Append a string to a multi-string format.
373 This is a internal function.
375 @param MultiString String in <MultiConfigRequest>,
376 <MultiConfigAltResp>, or <MultiConfigResp>. On
377 input, the buffer length of this string is
378 MAX_STRING_LENGTH. On output, the buffer length
380 @param AppendString NULL-terminated Unicode string.
382 @retval EFI_INVALID_PARAMETER Any incoming parameter is invalid.
383 @retval EFI_SUCCESS AppendString is append to the end of MultiString
387 AppendToMultiString (
388 IN OUT EFI_STRING
*MultiString
,
389 IN EFI_STRING AppendString
392 UINTN AppendStringSize
;
393 UINTN MultiStringSize
;
396 if (MultiString
== NULL
|| *MultiString
== NULL
|| AppendString
== NULL
) {
397 return EFI_INVALID_PARAMETER
;
400 AppendStringSize
= StrSize (AppendString
);
401 MultiStringSize
= StrSize (*MultiString
);
402 MaxLen
= MAX_STRING_LENGTH
/ sizeof (CHAR16
);
405 // Enlarge the buffer each time when length exceeds MAX_STRING_LENGTH.
407 if (MultiStringSize
+ AppendStringSize
> MAX_STRING_LENGTH
||
408 MultiStringSize
> MAX_STRING_LENGTH
) {
409 *MultiString
= (EFI_STRING
) ReallocatePool (
411 MultiStringSize
+ AppendStringSize
,
412 (VOID
*) (*MultiString
)
414 MaxLen
= (MultiStringSize
+ AppendStringSize
) / sizeof (CHAR16
);
415 ASSERT (*MultiString
!= NULL
);
418 // Append the incoming string
420 StrCatS (*MultiString
, MaxLen
, AppendString
);
427 Get the value of <Number> in <BlockConfig> format, i.e. the value of OFFSET
429 <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>
431 This is a internal function.
433 @param StringPtr String in <BlockConfig> format and points to the
434 first character of <Number>.
435 @param Number The output value. Caller takes the responsibility
437 @param Len Length of the <Number>, in characters.
439 @retval EFI_OUT_OF_RESOURCES Insufficient resources to store neccessary
441 @retval EFI_SUCCESS Value of <Number> is outputted in Number
447 IN EFI_STRING StringPtr
,
461 if (StringPtr
== NULL
|| *StringPtr
== L
'\0' || Number
== NULL
|| Len
== NULL
) {
462 return EFI_INVALID_PARAMETER
;
468 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
471 *Len
= StringPtr
- TmpPtr
;
474 Str
= (EFI_STRING
) AllocateZeroPool (Length
* sizeof (CHAR16
));
476 Status
= EFI_OUT_OF_RESOURCES
;
479 CopyMem (Str
, TmpPtr
, *Len
* sizeof (CHAR16
));
480 *(Str
+ *Len
) = L
'\0';
482 Length
= (Length
+ 1) / 2;
483 Buf
= (UINT8
*) AllocateZeroPool (Length
);
485 Status
= EFI_OUT_OF_RESOURCES
;
490 ZeroMem (TemStr
, sizeof (TemStr
));
491 for (Index
= 0; Index
< Length
; Index
++) {
492 TemStr
[0] = Str
[Length
- Index
- 1];
493 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
494 if ((Index
& 1) == 0) {
495 Buf
[Index
/2] = DigitUint8
;
497 Buf
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Buf
[Index
/2]);
502 Status
= EFI_SUCCESS
;
513 This function merges DefaultAltCfgResp string into AltCfgResp string for
514 the missing AltCfgId in AltCfgResq.
516 @param AltCfgResp Pointer to a null-terminated Unicode string in
517 <ConfigAltResp> format. The default value string
518 will be merged into it.
519 @param DefaultAltCfgResp Pointer to a null-terminated Unicode string in
520 <MultiConfigAltResp> format. The default value
521 string may contain more than one ConfigAltResp
522 string for the different varstore buffer.
524 @retval EFI_SUCCESS The merged string returns.
525 @retval EFI_INVALID_PARAMETER *AltCfgResp is to NULL.
530 IN OUT EFI_STRING
*AltCfgResp
,
531 IN EFI_STRING DefaultAltCfgResp
534 EFI_STRING StringPtrDefault
;
535 EFI_STRING StringPtrEnd
;
537 EFI_STRING StringPtr
;
538 EFI_STRING AltConfigHdr
;
540 UINTN SizeAltCfgResp
;
544 if (*AltCfgResp
== NULL
) {
545 return EFI_INVALID_PARAMETER
;
549 // Get the requestr ConfigHdr
552 StringPtr
= *AltCfgResp
;
555 // Find <ConfigHdr> GUID=...&NAME=...&PATH=...
557 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
558 return EFI_INVALID_PARAMETER
;
560 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&NAME=", StrLen (L
"&NAME=")) != 0) {
563 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&PATH=", StrLen (L
"&PATH=")) != 0) {
566 if (*StringPtr
== L
'\0') {
567 return EFI_INVALID_PARAMETER
;
569 StringPtr
+= StrLen (L
"&PATH=");
570 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
573 HeaderLength
= StringPtr
- *AltCfgResp
;
576 // Construct AltConfigHdr string "&<ConfigHdr>&ALTCFG=XXXX\0"
577 // |1| StrLen (ConfigHdr) | 8 | 4 | 1 |
579 MaxLen
= 1 + HeaderLength
+ 8 + 4 + 1;
580 AltConfigHdr
= AllocateZeroPool (MaxLen
* sizeof (CHAR16
));
581 if (AltConfigHdr
== NULL
) {
582 return EFI_OUT_OF_RESOURCES
;
584 StrCpyS (AltConfigHdr
, MaxLen
, L
"&");
585 StrnCatS (AltConfigHdr
, MaxLen
, *AltCfgResp
, HeaderLength
);
586 StrCatS (AltConfigHdr
, MaxLen
, L
"&ALTCFG=");
587 HeaderLength
= StrLen (AltConfigHdr
);
589 StringPtrDefault
= StrStr (DefaultAltCfgResp
, AltConfigHdr
);
590 while (StringPtrDefault
!= NULL
) {
594 StrnCatS (AltConfigHdr
, MaxLen
, StringPtrDefault
+ HeaderLength
, 4);
595 StringPtr
= StrStr (*AltCfgResp
, AltConfigHdr
);
598 // Append the found default value string to the input AltCfgResp
600 if (StringPtr
== NULL
) {
601 StringPtrEnd
= StrStr (StringPtrDefault
+ 1, L
"&GUID");
602 SizeAltCfgResp
= StrSize (*AltCfgResp
);
603 TotalSize
= SizeAltCfgResp
+ StrSize (StringPtrDefault
);
604 if (StringPtrEnd
== NULL
) {
606 // No more default string is found.
608 *AltCfgResp
= (EFI_STRING
) ReallocatePool (
611 (VOID
*) (*AltCfgResp
)
613 if (*AltCfgResp
== NULL
) {
614 FreePool (AltConfigHdr
);
615 return EFI_OUT_OF_RESOURCES
;
617 StrCatS (*AltCfgResp
, TotalSize
/ sizeof (CHAR16
), StringPtrDefault
);
620 TempChar
= *StringPtrEnd
;
621 *StringPtrEnd
= L
'\0';
622 *AltCfgResp
= (EFI_STRING
) ReallocatePool (
625 (VOID
*) (*AltCfgResp
)
627 if (*AltCfgResp
== NULL
) {
628 FreePool (AltConfigHdr
);
629 return EFI_OUT_OF_RESOURCES
;
631 StrCatS (*AltCfgResp
, TotalSize
/ sizeof (CHAR16
), StringPtrDefault
);
632 *StringPtrEnd
= TempChar
;
637 // Find next AltCfg String
639 *(AltConfigHdr
+ HeaderLength
) = L
'\0';
640 StringPtrDefault
= StrStr (StringPtrDefault
+ 1, AltConfigHdr
);
643 FreePool (AltConfigHdr
);
648 This function inserts new DefaultValueData into the BlockData DefaultValue array.
650 @param BlockData The BlockData is updated to add new default value.
651 @param DefaultValueData The DefaultValue is added.
656 IN IFR_BLOCK_DATA
*BlockData
,
657 IN IFR_DEFAULT_DATA
*DefaultValueData
661 IFR_DEFAULT_DATA
*DefaultValueArray
;
662 LIST_ENTRY
*DefaultLink
;
664 DefaultLink
= &BlockData
->DefaultValueEntry
;
666 for (Link
= DefaultLink
->ForwardLink
; Link
!= DefaultLink
; Link
= Link
->ForwardLink
) {
667 DefaultValueArray
= BASE_CR (Link
, IFR_DEFAULT_DATA
, Entry
);
668 if (DefaultValueArray
->DefaultId
== DefaultValueData
->DefaultId
) {
670 // DEFAULT_VALUE_FROM_OPCODE has high priority, DEFAULT_VALUE_FROM_DEFAULT has low priority.
672 if (DefaultValueData
->Type
> DefaultValueArray
->Type
) {
674 // Update the default value array in BlockData.
676 CopyMem (&DefaultValueArray
->Value
, &DefaultValueData
->Value
, sizeof (EFI_IFR_TYPE_VALUE
));
677 DefaultValueArray
->Type
= DefaultValueData
->Type
;
678 DefaultValueArray
->Cleaned
= DefaultValueData
->Cleaned
;
685 // Insert new default value data in tail.
687 DefaultValueArray
= AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
688 ASSERT (DefaultValueArray
!= NULL
);
689 CopyMem (DefaultValueArray
, DefaultValueData
, sizeof (IFR_DEFAULT_DATA
));
690 InsertTailList (Link
, &DefaultValueArray
->Entry
);
694 This function inserts new BlockData into the block link
696 @param BlockLink The list entry points to block array.
697 @param BlockData The point to BlockData is added.
702 IN LIST_ENTRY
*BlockLink
,
703 IN IFR_BLOCK_DATA
**BlockData
707 IFR_BLOCK_DATA
*BlockArray
;
708 IFR_BLOCK_DATA
*BlockSingleData
;
710 BlockSingleData
= *BlockData
;
712 if (BlockSingleData
->Name
!= NULL
) {
713 InsertTailList (BlockLink
, &BlockSingleData
->Entry
);
718 // Insert block data in its Offset and Width order.
720 for (Link
= BlockLink
->ForwardLink
; Link
!= BlockLink
; Link
= Link
->ForwardLink
) {
721 BlockArray
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
722 if (BlockArray
->Offset
== BlockSingleData
->Offset
) {
723 if (BlockArray
->Width
> BlockSingleData
->Width
) {
725 // Insert this block data in the front of block array
727 InsertTailList (Link
, &BlockSingleData
->Entry
);
731 if (BlockArray
->Width
== BlockSingleData
->Width
) {
733 // The same block array has been added.
735 if (BlockSingleData
!= BlockArray
) {
736 FreePool (BlockSingleData
);
737 *BlockData
= BlockArray
;
741 } else if (BlockArray
->Offset
> BlockSingleData
->Offset
) {
743 // Insert new block data in the front of block array
745 InsertTailList (Link
, &BlockSingleData
->Entry
);
751 // Add new block data into the tail.
753 InsertTailList (Link
, &BlockSingleData
->Entry
);
757 Retrieves a pointer to the a Null-terminated ASCII string containing the list
758 of languages that an HII handle in the HII Database supports. The returned
759 string is allocated using AllocatePool(). The caller is responsible for freeing
760 the returned string using FreePool(). The format of the returned string follows
761 the language format assumed the HII Database.
763 If HiiHandle is NULL, then ASSERT().
765 @param[in] HiiHandle A handle that was previously registered in the HII Database.
767 @retval NULL HiiHandle is not registered in the HII database
768 @retval NULL There are not enough resources available to retrieve the suported
770 @retval NULL The list of suported languages could not be retrieved.
771 @retval Other A pointer to the Null-terminated ASCII string of supported languages.
775 GetSupportedLanguages (
776 IN EFI_HII_HANDLE HiiHandle
781 CHAR8 TempSupportedLanguages
;
782 CHAR8
*SupportedLanguages
;
784 ASSERT (HiiHandle
!= NULL
);
787 // Retrieve the size required for the supported languages buffer.
790 Status
= mPrivate
.HiiString
.GetLanguages (&mPrivate
.HiiString
, HiiHandle
, &TempSupportedLanguages
, &LanguageSize
);
793 // If GetLanguages() returns EFI_SUCCESS for a zero size,
794 // then there are no supported languages registered for HiiHandle. If GetLanguages()
795 // returns an error other than EFI_BUFFER_TOO_SMALL, then HiiHandle is not present
796 // in the HII Database
798 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
800 // Return NULL if the size can not be retrieved, or if HiiHandle is not in the HII Database
806 // Allocate the supported languages buffer.
808 SupportedLanguages
= AllocateZeroPool (LanguageSize
);
809 if (SupportedLanguages
== NULL
) {
811 // Return NULL if allocation fails.
817 // Retrieve the supported languages string
819 Status
= mPrivate
.HiiString
.GetLanguages (&mPrivate
.HiiString
, HiiHandle
, SupportedLanguages
, &LanguageSize
);
820 if (EFI_ERROR (Status
)) {
822 // Free the buffer and return NULL if the supported languages can not be retrieved.
824 FreePool (SupportedLanguages
);
829 // Return the Null-terminated ASCII string of supported languages
831 return SupportedLanguages
;
835 Retrieves a string from a string package.
837 If HiiHandle is NULL, then ASSERT().
838 If StringId is 0, then ASSET.
840 @param[in] HiiHandle A handle that was previously registered in the HII Database.
841 @param[in] StringId The identifier of the string to retrieved from the string
842 package associated with HiiHandle.
844 @retval NULL The string specified by StringId is not present in the string package.
845 @retval Other The string was returned.
850 IN EFI_HII_HANDLE HiiHandle
,
851 IN EFI_STRING_ID StringId
858 CHAR8
*SupportedLanguages
;
859 CHAR8
*PlatformLanguage
;
863 ASSERT (HiiHandle
!= NULL
);
864 ASSERT (StringId
!= 0);
867 // Initialize all allocated buffers to NULL
869 SupportedLanguages
= NULL
;
870 PlatformLanguage
= NULL
;
876 // Get the languages that the package specified by HiiHandle supports
878 SupportedLanguages
= GetSupportedLanguages (HiiHandle
);
879 if (SupportedLanguages
== NULL
) {
884 // Get the current platform language setting
886 GetEfiGlobalVariable2 (L
"PlatformLang", (VOID
**)&PlatformLanguage
, NULL
);
889 // Get the best matching language from SupportedLanguages
891 BestLanguage
= GetBestLanguage (
893 FALSE
, // RFC 4646 mode
894 Language
, // Highest priority
895 PlatformLanguage
!= NULL
? PlatformLanguage
: "", // Next highest priority
896 SupportedLanguages
, // Lowest priority
899 if (BestLanguage
== NULL
) {
904 // Retrieve the size of the string in the string package for the BestLanguage
907 Status
= mPrivate
.HiiString
.GetString (
917 // If GetString() returns EFI_SUCCESS for a zero size,
918 // then there are no supported languages registered for HiiHandle. If GetString()
919 // returns an error other than EFI_BUFFER_TOO_SMALL, then HiiHandle is not present
920 // in the HII Database
922 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
927 // Allocate a buffer for the return string
929 String
= AllocateZeroPool (StringSize
);
930 if (String
== NULL
) {
935 // Retrieve the string from the string package
937 Status
= mPrivate
.HiiString
.GetString (
946 if (EFI_ERROR (Status
)) {
948 // Free the buffer and return NULL if the supported languages can not be retrieved.
956 // Free allocated buffers
958 if (SupportedLanguages
!= NULL
) {
959 FreePool (SupportedLanguages
);
961 if (PlatformLanguage
!= NULL
) {
962 FreePool (PlatformLanguage
);
964 if (BestLanguage
!= NULL
) {
965 FreePool (BestLanguage
);
969 // Return the Null-terminated Unicode string
975 This function checks VarOffset and VarWidth is in the block range.
977 @param RequestBlockArray The block array is to be checked.
978 @param VarOffset Offset of var to the structure
979 @param VarWidth Width of var.
980 @param IsNameValueType Whether this varstore is name/value varstore or not.
981 @param HiiHandle Hii handle for this hii package.
983 @retval TRUE This Var is in the block range.
984 @retval FALSE This Var is not in the block range.
988 IN IFR_BLOCK_DATA
*RequestBlockArray
,
991 IN BOOLEAN IsNameValueType
,
992 IN EFI_HII_HANDLE HiiHandle
996 IFR_BLOCK_DATA
*BlockData
;
1000 // No Request Block array, all vars are got.
1002 if (RequestBlockArray
== NULL
) {
1007 // Check the input var is in the request block range.
1009 for (Link
= RequestBlockArray
->Entry
.ForwardLink
; Link
!= &RequestBlockArray
->Entry
; Link
= Link
->ForwardLink
) {
1010 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
1012 if (IsNameValueType
) {
1013 Name
= InternalGetString (HiiHandle
, VarOffset
);
1014 ASSERT (Name
!= NULL
);
1016 if (StrnCmp (BlockData
->Name
, Name
, StrLen (Name
)) == 0) {
1022 if ((VarOffset
>= BlockData
->Offset
) && ((VarOffset
+ VarWidth
) <= (BlockData
->Offset
+ BlockData
->Width
))) {
1032 Get form package data from data base.
1034 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
1035 @param HiiFormPackage The buffer saves the package data.
1036 @param PackageSize The buffer size of the package data.
1040 GetFormPackageData (
1041 IN HII_DATABASE_RECORD
*DataBaseRecord
,
1042 IN OUT UINT8
**HiiFormPackage
,
1043 OUT UINTN
*PackageSize
1050 if (DataBaseRecord
== NULL
|| HiiFormPackage
== NULL
|| PackageSize
== NULL
) {
1051 return EFI_INVALID_PARAMETER
;
1057 // 0. Get Hii Form Package by HiiHandle
1059 Status
= ExportFormPackages (
1061 DataBaseRecord
->Handle
,
1062 DataBaseRecord
->PackageList
,
1068 if (EFI_ERROR (Status
)) {
1072 (*HiiFormPackage
) = AllocatePool (ResultSize
);
1073 if (*HiiFormPackage
== NULL
) {
1074 Status
= EFI_OUT_OF_RESOURCES
;
1079 // Get HiiFormPackage by HiiHandle
1083 Status
= ExportFormPackages (
1085 DataBaseRecord
->Handle
,
1086 DataBaseRecord
->PackageList
,
1092 if (EFI_ERROR (Status
)) {
1093 FreePool (*HiiFormPackage
);
1096 *PackageSize
= Size
;
1103 This function parses Form Package to get the efi varstore info according to the request ConfigHdr.
1105 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
1106 @param ConfigHdr Request string ConfigHdr. If it is NULL,
1107 the first found varstore will be as ConfigHdr.
1108 @param IsEfiVarstore Whether the request storage type is efi varstore type.
1109 @param EfiVarStore The efi varstore info which will return.
1113 IN HII_DATABASE_RECORD
*DataBaseRecord
,
1114 IN EFI_STRING ConfigHdr
,
1115 OUT BOOLEAN
*IsEfiVarstore
,
1116 OUT EFI_IFR_VARSTORE_EFI
**EfiVarStore
1121 UINTN PackageOffset
;
1122 EFI_IFR_OP_HEADER
*IfrOpHdr
;
1123 CHAR16
*VarStoreName
;
1128 UINT8
*HiiFormPackage
;
1130 EFI_IFR_VARSTORE_EFI
*IfrEfiVarStore
;
1131 EFI_HII_PACKAGE_HEADER
*PackageHeader
;
1133 HiiFormPackage
= NULL
;
1135 Status
= EFI_SUCCESS
;
1139 *IsEfiVarstore
= FALSE
;
1141 Status
= GetFormPackageData(DataBaseRecord
, &HiiFormPackage
, &PackageSize
);
1142 if (EFI_ERROR (Status
)) {
1146 IfrOffset
= sizeof (EFI_HII_PACKAGE_HEADER
);
1147 PackageOffset
= IfrOffset
;
1148 PackageHeader
= (EFI_HII_PACKAGE_HEADER
*) HiiFormPackage
;
1150 while (IfrOffset
< PackageSize
) {
1152 // More than one form packages exist.
1154 if (PackageOffset
>= PackageHeader
->Length
) {
1156 // Process the new form package.
1158 PackageOffset
= sizeof (EFI_HII_PACKAGE_HEADER
);
1159 IfrOffset
+= PackageOffset
;
1160 PackageHeader
= (EFI_HII_PACKAGE_HEADER
*) (HiiFormPackage
+ IfrOffset
);
1163 IfrOpHdr
= (EFI_IFR_OP_HEADER
*) (HiiFormPackage
+ IfrOffset
);
1164 IfrOffset
+= IfrOpHdr
->Length
;
1165 PackageOffset
+= IfrOpHdr
->Length
;
1167 if (IfrOpHdr
->OpCode
== EFI_IFR_VARSTORE_EFI_OP
) {
1168 IfrEfiVarStore
= (EFI_IFR_VARSTORE_EFI
*) IfrOpHdr
;
1170 // If the length is small than the structure, this is from old efi
1171 // varstore definition. Old efi varstore get config directly from
1172 // GetVariable function.
1174 if (IfrOpHdr
->Length
< sizeof (EFI_IFR_VARSTORE_EFI
)) {
1178 VarStoreName
= AllocateZeroPool (AsciiStrSize ((CHAR8
*)IfrEfiVarStore
->Name
) * sizeof (CHAR16
));
1179 if (VarStoreName
== NULL
) {
1180 Status
= EFI_OUT_OF_RESOURCES
;
1183 AsciiStrToUnicodeStr ((CHAR8
*) IfrEfiVarStore
->Name
, VarStoreName
);
1185 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*) &IfrEfiVarStore
->Guid
, 1, &GuidStr
);
1186 GenerateSubStr (L
"NAME=", StrLen (VarStoreName
) * sizeof (CHAR16
), (VOID
*) VarStoreName
, 2, &NameStr
);
1187 LengthString
= StrLen (GuidStr
);
1188 LengthString
= LengthString
+ StrLen (NameStr
) + 1;
1189 TempStr
= AllocateZeroPool (LengthString
* sizeof (CHAR16
));
1190 if (TempStr
== NULL
) {
1193 FreePool (VarStoreName
);
1194 Status
= EFI_OUT_OF_RESOURCES
;
1197 StrCpyS (TempStr
, LengthString
, GuidStr
);
1198 StrCatS (TempStr
, LengthString
, NameStr
);
1199 if (ConfigHdr
== NULL
|| StrnCmp (ConfigHdr
, TempStr
, StrLen (TempStr
)) == 0) {
1200 *EfiVarStore
= (EFI_IFR_VARSTORE_EFI
*) AllocateZeroPool (IfrOpHdr
->Length
);
1201 if (*EfiVarStore
== NULL
) {
1202 FreePool (VarStoreName
);
1206 Status
= EFI_OUT_OF_RESOURCES
;
1209 *IsEfiVarstore
= TRUE
;
1210 CopyMem (*EfiVarStore
, IfrEfiVarStore
, IfrOpHdr
->Length
);
1214 // Free alllocated temp string.
1216 FreePool (VarStoreName
);
1222 // Already found the varstore, break;
1224 if (*IsEfiVarstore
) {
1230 if (HiiFormPackage
!= NULL
) {
1231 FreePool (HiiFormPackage
);
1238 Check whether the ConfigRequest string has the request elements.
1239 For EFI_HII_VARSTORE_BUFFER type, the request has "&OFFSET=****&WIDTH=****..." format.
1240 For EFI_HII_VARSTORE_NAME_VALUE type, the request has "&NAME1**&NAME2..." format.
1242 @param ConfigRequest The input config request string.
1244 @retval TRUE The input include config request elements.
1245 @retval FALSE The input string not includes.
1249 GetElementsFromRequest (
1250 IN EFI_STRING ConfigRequest
1253 EFI_STRING TmpRequest
;
1255 TmpRequest
= StrStr (ConfigRequest
, L
"PATH=");
1256 ASSERT (TmpRequest
!= NULL
);
1258 if ((StrStr (TmpRequest
, L
"&OFFSET=") != NULL
) || (StrStr (TmpRequest
, L
"&") != NULL
)) {
1266 Check whether the this varstore is the request varstore.
1268 @param VarstoreGuid Varstore guid.
1269 @param Name Varstore name.
1270 @param ConfigHdr Current configRequest info.
1272 @retval TRUE This varstore is the requst one.
1273 @retval FALSE This varstore is not the requst one.
1278 IN EFI_GUID
*VarstoreGuid
,
1280 IN CHAR16
*ConfigHdr
1294 // If ConfigHdr has name field and varstore not has name, return FALSE.
1296 if (Name
== NULL
&& ConfigHdr
!= NULL
&& StrStr (ConfigHdr
, L
"NAME=&") == NULL
) {
1300 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*)VarstoreGuid
, 1, &GuidStr
);
1302 GenerateSubStr (L
"NAME=", StrLen (Name
) * sizeof (CHAR16
), (VOID
*) Name
, 2, &NameStr
);
1304 GenerateSubStr (L
"NAME=", 0, NULL
, 2, &NameStr
);
1306 LengthString
= StrLen (GuidStr
);
1307 LengthString
= LengthString
+ StrLen (NameStr
) + 1;
1308 TempStr
= AllocateZeroPool (LengthString
* sizeof (CHAR16
));
1309 if (TempStr
== NULL
) {
1313 StrCpyS (TempStr
, LengthString
, GuidStr
);
1314 StrCatS (TempStr
, LengthString
, NameStr
);
1316 if (ConfigHdr
== NULL
|| StrnCmp (ConfigHdr
, TempStr
, StrLen (TempStr
)) == 0) {
1321 if (GuidStr
!= NULL
) {
1325 if (NameStr
!= NULL
) {
1329 if (TempStr
!= NULL
) {
1337 This function parses Form Package to get the efi varstore info according to the request ConfigHdr.
1339 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
1340 @param ConfigHdr Request string ConfigHdr. If it is NULL,
1341 the first found varstore will be as ConfigHdr.
1342 @retval TRUE This hii package is the reqeust one.
1343 @retval FALSE This hii package is not the reqeust one.
1347 IN HII_DATABASE_RECORD
*DataBaseRecord
,
1348 IN EFI_STRING ConfigHdr
1353 UINTN PackageOffset
;
1354 EFI_IFR_OP_HEADER
*IfrOpHdr
;
1355 CHAR16
*VarStoreName
;
1356 UINT8
*HiiFormPackage
;
1358 EFI_IFR_VARSTORE_EFI
*IfrEfiVarStore
;
1359 EFI_HII_PACKAGE_HEADER
*PackageHeader
;
1360 EFI_IFR_VARSTORE
*IfrVarStore
;
1361 EFI_IFR_VARSTORE_NAME_VALUE
*IfrNameValueVarStore
;
1362 BOOLEAN FindVarstore
;
1364 HiiFormPackage
= NULL
;
1365 VarStoreName
= NULL
;
1366 Status
= EFI_SUCCESS
;
1367 FindVarstore
= FALSE
;
1369 Status
= GetFormPackageData(DataBaseRecord
, &HiiFormPackage
, &PackageSize
);
1370 if (EFI_ERROR (Status
)) {
1374 IfrOffset
= sizeof (EFI_HII_PACKAGE_HEADER
);
1375 PackageOffset
= IfrOffset
;
1376 PackageHeader
= (EFI_HII_PACKAGE_HEADER
*) HiiFormPackage
;
1378 while (IfrOffset
< PackageSize
) {
1380 // More than one form packages exist.
1382 if (PackageOffset
>= PackageHeader
->Length
) {
1384 // Process the new form package.
1386 PackageOffset
= sizeof (EFI_HII_PACKAGE_HEADER
);
1387 IfrOffset
+= PackageOffset
;
1388 PackageHeader
= (EFI_HII_PACKAGE_HEADER
*) (HiiFormPackage
+ IfrOffset
);
1391 IfrOpHdr
= (EFI_IFR_OP_HEADER
*) (HiiFormPackage
+ IfrOffset
);
1392 IfrOffset
+= IfrOpHdr
->Length
;
1393 PackageOffset
+= IfrOpHdr
->Length
;
1395 switch (IfrOpHdr
->OpCode
) {
1397 case EFI_IFR_VARSTORE_OP
:
1398 IfrVarStore
= (EFI_IFR_VARSTORE
*) IfrOpHdr
;
1400 VarStoreName
= AllocateZeroPool (AsciiStrSize ((CHAR8
*)IfrVarStore
->Name
) * sizeof (CHAR16
));
1401 if (VarStoreName
== NULL
) {
1404 AsciiStrToUnicodeStr ((CHAR8
*)IfrVarStore
->Name
, VarStoreName
);
1406 if (IsThisVarstore((VOID
*)&IfrVarStore
->Guid
, VarStoreName
, ConfigHdr
)) {
1407 FindVarstore
= TRUE
;
1412 case EFI_IFR_VARSTORE_EFI_OP
:
1413 IfrEfiVarStore
= (EFI_IFR_VARSTORE_EFI
*) IfrOpHdr
;
1414 VarStoreName
= AllocateZeroPool (AsciiStrSize ((CHAR8
*)IfrEfiVarStore
->Name
) * sizeof (CHAR16
));
1415 if (VarStoreName
== NULL
) {
1418 AsciiStrToUnicodeStr ((CHAR8
*)IfrEfiVarStore
->Name
, VarStoreName
);
1420 if (IsThisVarstore (&IfrEfiVarStore
->Guid
, VarStoreName
, ConfigHdr
)) {
1421 FindVarstore
= TRUE
;
1426 case EFI_IFR_VARSTORE_NAME_VALUE_OP
:
1427 IfrNameValueVarStore
= (EFI_IFR_VARSTORE_NAME_VALUE
*) IfrOpHdr
;
1429 if (IsThisVarstore (&IfrNameValueVarStore
->Guid
, NULL
, ConfigHdr
)) {
1430 FindVarstore
= TRUE
;
1435 case EFI_IFR_FORM_OP
:
1436 case EFI_IFR_FORM_MAP_OP
:
1438 // No matched varstore is found and directly return.
1447 if (HiiFormPackage
!= NULL
) {
1448 FreePool (HiiFormPackage
);
1451 if (VarStoreName
!= NULL
) {
1452 FreePool (VarStoreName
);
1455 return FindVarstore
;
1459 Check whether the this op code is required.
1461 @param RequestBlockArray The array includes all the request info or NULL.
1462 @param HiiHandle The hii handle for this form package.
1463 @param VarStorageData The varstore data strucure.
1464 @param IfrOpHdr Ifr opcode header for this opcode.
1465 @param VarWidth The buffer width for this opcode.
1466 @param ReturnData The data block added for this opcode.
1468 @retval EFI_SUCCESS This opcode is required.
1469 @retval EFI_NOT_FOUND This opcode is not required.
1470 @retval Others Contain some error.
1474 IsThisOpcodeRequired (
1475 IN IFR_BLOCK_DATA
*RequestBlockArray
,
1476 IN EFI_HII_HANDLE HiiHandle
,
1477 IN OUT IFR_VARSTORAGE_DATA
*VarStorageData
,
1478 IN EFI_IFR_OP_HEADER
*IfrOpHdr
,
1480 OUT IFR_BLOCK_DATA
**ReturnData
1483 IFR_BLOCK_DATA
*BlockData
;
1485 EFI_STRING_ID NameId
;
1486 EFI_IFR_QUESTION_HEADER
*IfrQuestionHdr
;
1490 IfrQuestionHdr
= (EFI_IFR_QUESTION_HEADER
*)((CHAR8
*) IfrOpHdr
+ sizeof (EFI_IFR_OP_HEADER
));
1492 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
1493 NameId
= IfrQuestionHdr
->VarStoreInfo
.VarName
;
1496 // Check whether this question is in requested block array.
1498 if (!BlockArrayCheck (RequestBlockArray
, NameId
, 0, TRUE
, HiiHandle
)) {
1500 // This question is not in the requested string. Skip it.
1502 return EFI_NOT_FOUND
;
1505 VarOffset
= IfrQuestionHdr
->VarStoreInfo
.VarOffset
;
1508 // Check whether this question is in requested block array.
1510 if (!BlockArrayCheck (RequestBlockArray
, VarOffset
, VarWidth
, FALSE
, HiiHandle
)) {
1512 // This question is not in the requested string. Skip it.
1514 return EFI_NOT_FOUND
;
1518 // Check this var question is in the var storage
1520 if (((VarOffset
+ VarWidth
) > VarStorageData
->Size
)) {
1521 return EFI_INVALID_PARAMETER
;
1525 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
1526 if (BlockData
== NULL
) {
1527 return EFI_OUT_OF_RESOURCES
;
1530 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
1531 BlockData
->Name
= InternalGetString(HiiHandle
, NameId
);
1533 BlockData
->Offset
= VarOffset
;
1536 BlockData
->Width
= VarWidth
;
1537 BlockData
->QuestionId
= IfrQuestionHdr
->QuestionId
;
1538 BlockData
->OpCode
= IfrOpHdr
->OpCode
;
1539 BlockData
->Scope
= IfrOpHdr
->Scope
;
1540 InitializeListHead (&BlockData
->DefaultValueEntry
);
1542 // Add Block Data into VarStorageData BlockEntry
1544 InsertBlockData (&VarStorageData
->BlockEntry
, &BlockData
);
1545 *ReturnData
= BlockData
;
1551 This function parses Form Package to get the block array and the default
1552 value array according to the request ConfigHdr.
1554 @param HiiHandle Hii Handle for this hii package.
1555 @param Package Pointer to the form package data.
1556 @param PackageLength Length of the pacakge.
1557 @param ConfigHdr Request string ConfigHdr. If it is NULL,
1558 the first found varstore will be as ConfigHdr.
1559 @param RequestBlockArray The block array is retrieved from the request string.
1560 @param VarStorageData VarStorage structure contains the got block and default value.
1561 @param DefaultIdArray Point to the got default id and default name array.
1563 @retval EFI_SUCCESS The block array and the default value array are got.
1564 @retval EFI_INVALID_PARAMETER The varstore defintion in the differnt form pacakges
1566 @retval EFI_OUT_OF_RESOURCES No enough memory.
1571 IN EFI_HII_HANDLE HiiHandle
,
1573 IN UINT32 PackageLength
,
1574 IN EFI_STRING ConfigHdr
,
1575 IN IFR_BLOCK_DATA
*RequestBlockArray
,
1576 IN OUT IFR_VARSTORAGE_DATA
*VarStorageData
,
1577 OUT IFR_DEFAULT_DATA
*DefaultIdArray
1582 UINTN PackageOffset
;
1583 EFI_IFR_VARSTORE
*IfrVarStore
;
1584 EFI_IFR_VARSTORE_EFI
*IfrEfiVarStore
;
1585 EFI_IFR_OP_HEADER
*IfrOpHdr
;
1586 EFI_IFR_ONE_OF
*IfrOneOf
;
1587 EFI_IFR_REF4
*IfrRef
;
1588 EFI_IFR_ONE_OF_OPTION
*IfrOneOfOption
;
1589 EFI_IFR_DEFAULT
*IfrDefault
;
1590 EFI_IFR_ORDERED_LIST
*IfrOrderedList
;
1591 EFI_IFR_CHECKBOX
*IfrCheckBox
;
1592 EFI_IFR_PASSWORD
*IfrPassword
;
1593 EFI_IFR_STRING
*IfrString
;
1594 EFI_IFR_DATE
*IfrDate
;
1595 EFI_IFR_TIME
*IfrTime
;
1596 IFR_DEFAULT_DATA DefaultData
;
1597 IFR_DEFAULT_DATA
*DefaultDataPtr
;
1598 IFR_BLOCK_DATA
*BlockData
;
1599 CHAR16
*VarStoreName
;
1601 UINT16 VarDefaultId
;
1602 BOOLEAN FirstOneOfOption
;
1603 BOOLEAN FirstOrderedList
;
1604 LIST_ENTRY
*LinkData
;
1605 LIST_ENTRY
*LinkDefault
;
1606 EFI_IFR_VARSTORE_NAME_VALUE
*IfrNameValueVarStore
;
1607 EFI_HII_PACKAGE_HEADER
*PackageHeader
;
1608 EFI_VARSTORE_ID VarStoreId
;
1610 Status
= EFI_SUCCESS
;
1612 DefaultDataPtr
= NULL
;
1613 FirstOneOfOption
= FALSE
;
1615 FirstOrderedList
= FALSE
;
1616 ZeroMem (&DefaultData
, sizeof (IFR_DEFAULT_DATA
));
1619 // Go through the form package to parse OpCode one by one.
1621 PackageOffset
= sizeof (EFI_HII_PACKAGE_HEADER
);
1622 PackageHeader
= (EFI_HII_PACKAGE_HEADER
*) Package
;
1623 IfrOffset
= PackageOffset
;
1624 while (IfrOffset
< PackageLength
) {
1627 // More than one form package found.
1629 if (PackageOffset
>= PackageHeader
->Length
) {
1631 // Already found varstore for this request, break;
1633 if (VarStoreId
!= 0) {
1638 // Get next package header info.
1640 IfrOffset
+= sizeof (EFI_HII_PACKAGE_HEADER
);
1641 PackageOffset
= sizeof (EFI_HII_PACKAGE_HEADER
);
1642 PackageHeader
= (EFI_HII_PACKAGE_HEADER
*) (Package
+ IfrOffset
);
1645 IfrOpHdr
= (EFI_IFR_OP_HEADER
*) (Package
+ IfrOffset
);
1646 switch (IfrOpHdr
->OpCode
) {
1647 case EFI_IFR_VARSTORE_OP
:
1649 // VarStore is found. Don't need to search any more.
1651 if (VarStoreId
!= 0) {
1655 IfrVarStore
= (EFI_IFR_VARSTORE
*) IfrOpHdr
;
1657 VarStoreName
= AllocateZeroPool (AsciiStrSize ((CHAR8
*)IfrVarStore
->Name
) * sizeof (CHAR16
));
1658 if (VarStoreName
== NULL
) {
1659 Status
= EFI_OUT_OF_RESOURCES
;
1662 AsciiStrToUnicodeStr ((CHAR8
*)IfrVarStore
->Name
, VarStoreName
);
1664 if (IsThisVarstore((VOID
*)&IfrVarStore
->Guid
, VarStoreName
, ConfigHdr
)) {
1666 // Find the matched VarStore
1668 CopyGuid (&VarStorageData
->Guid
, (EFI_GUID
*) (VOID
*) &IfrVarStore
->Guid
);
1669 VarStorageData
->Size
= IfrVarStore
->Size
;
1670 VarStorageData
->Name
= VarStoreName
;
1671 VarStorageData
->Type
= EFI_HII_VARSTORE_BUFFER
;
1672 VarStoreId
= IfrVarStore
->VarStoreId
;
1676 case EFI_IFR_VARSTORE_EFI_OP
:
1678 // VarStore is found. Don't need to search any more.
1680 if (VarStoreId
!= 0) {
1684 IfrEfiVarStore
= (EFI_IFR_VARSTORE_EFI
*) IfrOpHdr
;
1687 // If the length is small than the structure, this is from old efi
1688 // varstore definition. Old efi varstore get config directly from
1689 // GetVariable function.
1691 if (IfrOpHdr
->Length
< sizeof (EFI_IFR_VARSTORE_EFI
)) {
1695 VarStoreName
= AllocateZeroPool (AsciiStrSize ((CHAR8
*)IfrEfiVarStore
->Name
) * sizeof (CHAR16
));
1696 if (VarStoreName
== NULL
) {
1697 Status
= EFI_OUT_OF_RESOURCES
;
1700 AsciiStrToUnicodeStr ((CHAR8
*)IfrEfiVarStore
->Name
, VarStoreName
);
1702 if (IsThisVarstore (&IfrEfiVarStore
->Guid
, VarStoreName
, ConfigHdr
)) {
1704 // Find the matched VarStore
1706 CopyGuid (&VarStorageData
->Guid
, (EFI_GUID
*) (VOID
*) &IfrEfiVarStore
->Guid
);
1707 VarStorageData
->Size
= IfrEfiVarStore
->Size
;
1708 VarStorageData
->Name
= VarStoreName
;
1709 VarStorageData
->Type
= EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
;
1710 VarStoreId
= IfrEfiVarStore
->VarStoreId
;
1714 case EFI_IFR_VARSTORE_NAME_VALUE_OP
:
1716 // VarStore is found. Don't need to search any more.
1718 if (VarStoreId
!= 0) {
1722 IfrNameValueVarStore
= (EFI_IFR_VARSTORE_NAME_VALUE
*) IfrOpHdr
;
1724 if (IsThisVarstore (&IfrNameValueVarStore
->Guid
, NULL
, ConfigHdr
)) {
1726 // Find the matched VarStore
1728 CopyGuid (&VarStorageData
->Guid
, (EFI_GUID
*) (VOID
*) &IfrNameValueVarStore
->Guid
);
1729 VarStorageData
->Type
= EFI_HII_VARSTORE_NAME_VALUE
;
1730 VarStoreId
= IfrNameValueVarStore
->VarStoreId
;
1734 case EFI_IFR_DEFAULTSTORE_OP
:
1736 // Add new the map between default id and default name.
1738 DefaultDataPtr
= (IFR_DEFAULT_DATA
*) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
1739 if (DefaultDataPtr
== NULL
) {
1740 Status
= EFI_OUT_OF_RESOURCES
;
1743 DefaultDataPtr
->DefaultId
= ((EFI_IFR_DEFAULTSTORE
*) IfrOpHdr
)->DefaultId
;
1744 InsertTailList (&DefaultIdArray
->Entry
, &DefaultDataPtr
->Entry
);
1745 DefaultDataPtr
= NULL
;
1748 case EFI_IFR_FORM_OP
:
1749 case EFI_IFR_FORM_MAP_OP
:
1751 // No matched varstore is found and directly return.
1753 if ( VarStoreId
== 0) {
1754 Status
= EFI_SUCCESS
;
1759 case EFI_IFR_REF_OP
:
1761 // Ref question is not in IFR Form. This IFR form is not valid.
1763 if ( VarStoreId
== 0) {
1764 Status
= EFI_INVALID_PARAMETER
;
1768 // Check whether this question is for the requested varstore.
1770 IfrRef
= (EFI_IFR_REF4
*) IfrOpHdr
;
1771 if (IfrRef
->Question
.VarStoreId
!= VarStoreId
) {
1774 VarWidth
= (UINT16
) (sizeof (EFI_HII_REF
));
1777 // The BlockData may allocate by other opcode,need to clean.
1779 if (BlockData
!= NULL
){
1783 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
1784 if (EFI_ERROR (Status
)) {
1785 if (Status
== EFI_NOT_FOUND
){
1787 //The opcode is not required,exit and parse other opcode.
1795 case EFI_IFR_ONE_OF_OP
:
1796 case EFI_IFR_NUMERIC_OP
:
1798 // Numeric and OneOf has the same opcode structure.
1802 // Numeric and OneOf question is not in IFR Form. This IFR form is not valid.
1804 if (VarStoreId
== 0) {
1805 Status
= EFI_INVALID_PARAMETER
;
1809 // Check whether this question is for the requested varstore.
1811 IfrOneOf
= (EFI_IFR_ONE_OF
*) IfrOpHdr
;
1812 if (IfrOneOf
->Question
.VarStoreId
!= VarStoreId
) {
1815 VarWidth
= (UINT16
) (1 << (IfrOneOf
->Flags
& EFI_IFR_NUMERIC_SIZE
));
1818 // The BlockData may allocate by other opcode,need to clean.
1820 if (BlockData
!= NULL
){
1824 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
1825 if (EFI_ERROR (Status
)) {
1826 if (Status
== EFI_NOT_FOUND
){
1828 //The opcode is not required,exit and parse other opcode.
1836 //when go to there,BlockData can't be NULLL.
1838 ASSERT (BlockData
!= NULL
);
1840 if (IfrOpHdr
->OpCode
== EFI_IFR_ONE_OF_OP
) {
1842 // Set this flag to TRUE for the first oneof option.
1844 FirstOneOfOption
= TRUE
;
1845 } else if (IfrOpHdr
->OpCode
== EFI_IFR_NUMERIC_OP
) {
1847 // Numeric minimum value will be used as default value when no default is specified.
1849 DefaultData
.Type
= DefaultValueFromDefault
;
1850 switch (IfrOneOf
->Flags
& EFI_IFR_NUMERIC_SIZE
) {
1851 case EFI_IFR_NUMERIC_SIZE_1
:
1852 DefaultData
.Value
.u8
= IfrOneOf
->data
.u8
.MinValue
;
1855 case EFI_IFR_NUMERIC_SIZE_2
:
1856 CopyMem (&DefaultData
.Value
.u16
, &IfrOneOf
->data
.u16
.MinValue
, sizeof (UINT16
));
1859 case EFI_IFR_NUMERIC_SIZE_4
:
1860 CopyMem (&DefaultData
.Value
.u32
, &IfrOneOf
->data
.u32
.MinValue
, sizeof (UINT32
));
1863 case EFI_IFR_NUMERIC_SIZE_8
:
1864 CopyMem (&DefaultData
.Value
.u64
, &IfrOneOf
->data
.u64
.MinValue
, sizeof (UINT64
));
1868 Status
= EFI_INVALID_PARAMETER
;
1872 // Set default value base on the DefaultId list get from IFR data.
1874 for (LinkData
= DefaultIdArray
->Entry
.ForwardLink
; LinkData
!= &DefaultIdArray
->Entry
; LinkData
= LinkData
->ForwardLink
) {
1875 DefaultDataPtr
= BASE_CR (LinkData
, IFR_DEFAULT_DATA
, Entry
);
1876 DefaultData
.DefaultId
= DefaultDataPtr
->DefaultId
;
1877 InsertDefaultValue (BlockData
, &DefaultData
);
1882 case EFI_IFR_ORDERED_LIST_OP
:
1884 // offset by question header
1885 // width by EFI_IFR_ORDERED_LIST MaxContainers * OneofOption Type
1888 FirstOrderedList
= TRUE
;
1890 // OrderedList question is not in IFR Form. This IFR form is not valid.
1892 if (VarStoreId
== 0) {
1893 Status
= EFI_INVALID_PARAMETER
;
1897 // Check whether this question is for the requested varstore.
1899 IfrOrderedList
= (EFI_IFR_ORDERED_LIST
*) IfrOpHdr
;
1900 if (IfrOrderedList
->Question
.VarStoreId
!= VarStoreId
) {
1904 VarWidth
= IfrOrderedList
->MaxContainers
;
1907 // The BlockData may allocate by other opcode,need to clean.
1909 if (BlockData
!= NULL
){
1913 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
1914 if (EFI_ERROR (Status
)) {
1915 if (Status
== EFI_NOT_FOUND
){
1917 //The opcode is not required,exit and parse other opcode.
1925 case EFI_IFR_CHECKBOX_OP
:
1927 // EFI_IFR_DEFAULT_OP
1928 // offset by question header
1929 // width is 1 sizeof (BOOLEAN)
1930 // default id by CheckBox Flags if CheckBox flags (Default or Mau) is set, the default value is 1 to be set.
1931 // value by DefaultOption
1932 // default id by DeaultOption DefaultId can override CheckBox Flags and Default value.
1936 // CheckBox question is not in IFR Form. This IFR form is not valid.
1938 if (VarStoreId
== 0) {
1939 Status
= EFI_INVALID_PARAMETER
;
1943 // Check whether this question is for the requested varstore.
1945 IfrCheckBox
= (EFI_IFR_CHECKBOX
*) IfrOpHdr
;
1946 if (IfrCheckBox
->Question
.VarStoreId
!= VarStoreId
) {
1949 VarWidth
= (UINT16
) sizeof (BOOLEAN
);
1952 // The BlockData may allocate by other opcode,need to clean.
1954 if (BlockData
!= NULL
){
1958 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
1959 if (EFI_ERROR (Status
)) {
1960 if (Status
== EFI_NOT_FOUND
){
1962 //The opcode is not required,exit and parse other opcode.
1970 //when go to there,BlockData can't be NULLL.
1972 ASSERT (BlockData
!= NULL
);
1975 // Add default value for standard ID by CheckBox Flag
1977 VarDefaultId
= EFI_HII_DEFAULT_CLASS_STANDARD
;
1979 // Prepare new DefaultValue
1981 DefaultData
.DefaultId
= VarDefaultId
;
1982 if ((IfrCheckBox
->Flags
& EFI_IFR_CHECKBOX_DEFAULT
) == EFI_IFR_CHECKBOX_DEFAULT
) {
1984 // When flag is set, defautl value is TRUE.
1986 DefaultData
.Type
= DefaultValueFromFlag
;
1987 DefaultData
.Value
.b
= TRUE
;
1990 // When flag is not set, defautl value is FASLE.
1992 DefaultData
.Type
= DefaultValueFromDefault
;
1993 DefaultData
.Value
.b
= FALSE
;
1996 // Add DefaultValue into current BlockData
1998 InsertDefaultValue (BlockData
, &DefaultData
);
2001 // Add default value for Manufacture ID by CheckBox Flag
2003 VarDefaultId
= EFI_HII_DEFAULT_CLASS_MANUFACTURING
;
2005 // Prepare new DefaultValue
2007 DefaultData
.DefaultId
= VarDefaultId
;
2008 if ((IfrCheckBox
->Flags
& EFI_IFR_CHECKBOX_DEFAULT_MFG
) == EFI_IFR_CHECKBOX_DEFAULT_MFG
) {
2010 // When flag is set, defautl value is TRUE.
2012 DefaultData
.Type
= DefaultValueFromFlag
;
2013 DefaultData
.Value
.b
= TRUE
;
2016 // When flag is not set, defautl value is FASLE.
2018 DefaultData
.Type
= DefaultValueFromDefault
;
2019 DefaultData
.Value
.b
= FALSE
;
2022 // Add DefaultValue into current BlockData
2024 InsertDefaultValue (BlockData
, &DefaultData
);
2027 case EFI_IFR_DATE_OP
:
2029 // offset by question header
2030 // width MaxSize * sizeof (CHAR16)
2031 // no default value, only block array
2035 // Date question is not in IFR Form. This IFR form is not valid.
2037 if (VarStoreId
== 0) {
2038 Status
= EFI_INVALID_PARAMETER
;
2042 // Check whether this question is for the requested varstore.
2044 IfrDate
= (EFI_IFR_DATE
*) IfrOpHdr
;
2045 if (IfrDate
->Question
.VarStoreId
!= VarStoreId
) {
2050 // The BlockData may allocate by other opcode,need to clean.
2052 if (BlockData
!= NULL
){
2056 VarWidth
= (UINT16
) sizeof (EFI_HII_DATE
);
2057 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
2058 if (EFI_ERROR (Status
)) {
2059 if (Status
== EFI_NOT_FOUND
){
2061 //The opcode is not required,exit and parse other opcode.
2069 case EFI_IFR_TIME_OP
:
2071 // offset by question header
2072 // width MaxSize * sizeof (CHAR16)
2073 // no default value, only block array
2077 // Time question is not in IFR Form. This IFR form is not valid.
2079 if (VarStoreId
== 0) {
2080 Status
= EFI_INVALID_PARAMETER
;
2084 // Check whether this question is for the requested varstore.
2086 IfrTime
= (EFI_IFR_TIME
*) IfrOpHdr
;
2087 if (IfrTime
->Question
.VarStoreId
!= VarStoreId
) {
2092 // The BlockData may allocate by other opcode,need to clean.
2094 if (BlockData
!= NULL
){
2098 VarWidth
= (UINT16
) sizeof (EFI_HII_TIME
);
2099 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
2100 if (EFI_ERROR (Status
)) {
2101 if (Status
== EFI_NOT_FOUND
){
2103 //The opcode is not required,exit and parse other opcode.
2111 case EFI_IFR_STRING_OP
:
2113 // offset by question header
2114 // width MaxSize * sizeof (CHAR16)
2115 // no default value, only block array
2119 // String question is not in IFR Form. This IFR form is not valid.
2121 if (VarStoreId
== 0) {
2122 Status
= EFI_INVALID_PARAMETER
;
2126 // Check whether this question is for the requested varstore.
2128 IfrString
= (EFI_IFR_STRING
*) IfrOpHdr
;
2129 if (IfrString
->Question
.VarStoreId
!= VarStoreId
) {
2134 // The BlockData may allocate by other opcode,need to clean.
2136 if (BlockData
!= NULL
){
2140 VarWidth
= (UINT16
) (IfrString
->MaxSize
* sizeof (UINT16
));
2141 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
2142 if (EFI_ERROR (Status
)) {
2143 if (Status
== EFI_NOT_FOUND
){
2145 //The opcode is not required,exit and parse other opcode.
2153 case EFI_IFR_PASSWORD_OP
:
2155 // offset by question header
2156 // width MaxSize * sizeof (CHAR16)
2157 // no default value, only block array
2161 // Password question is not in IFR Form. This IFR form is not valid.
2163 if (VarStoreId
== 0) {
2164 Status
= EFI_INVALID_PARAMETER
;
2168 // Check whether this question is for the requested varstore.
2170 IfrPassword
= (EFI_IFR_PASSWORD
*) IfrOpHdr
;
2171 if (IfrPassword
->Question
.VarStoreId
!= VarStoreId
) {
2176 // The BlockData may allocate by other opcode,need to clean.
2178 if (BlockData
!= NULL
){
2182 VarWidth
= (UINT16
) (IfrPassword
->MaxSize
* sizeof (UINT16
));
2183 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
2184 if (EFI_ERROR (Status
)) {
2185 if (Status
== EFI_NOT_FOUND
){
2187 //The opcode is not required,exit and parse other opcode.
2195 // No default value for string.
2200 case EFI_IFR_ONE_OF_OPTION_OP
:
2202 // No matched block data is ignored.
2204 if (BlockData
== NULL
|| BlockData
->Scope
== 0) {
2208 IfrOneOfOption
= (EFI_IFR_ONE_OF_OPTION
*) IfrOpHdr
;
2209 if (BlockData
->OpCode
== EFI_IFR_ORDERED_LIST_OP
) {
2211 if (!FirstOrderedList
){
2215 // Get ordered list option data type.
2217 if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_8
|| IfrOneOfOption
->Type
== EFI_IFR_TYPE_BOOLEAN
) {
2219 } else if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_16
) {
2221 } else if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_32
) {
2223 } else if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_64
) {
2227 // Invalid ordered list option data type.
2229 Status
= EFI_INVALID_PARAMETER
;
2230 if (BlockData
->Name
!= NULL
) {
2231 FreePool (BlockData
->Name
);
2233 FreePool (BlockData
);
2238 // Calculate Ordered list QuestionId width.
2240 BlockData
->Width
= (UINT16
) (BlockData
->Width
* VarWidth
);
2242 // Check whether this question is in requested block array.
2244 if (!BlockArrayCheck (RequestBlockArray
, BlockData
->Offset
, BlockData
->Width
, (BOOLEAN
)(BlockData
->Name
!= NULL
), HiiHandle
)) {
2246 // This question is not in the requested string. Skip it.
2248 if (BlockData
->Name
!= NULL
) {
2249 FreePool (BlockData
->Name
);
2251 FreePool (BlockData
);
2256 // Check this var question is in the var storage
2258 if ((BlockData
->Name
== NULL
) && ((BlockData
->Offset
+ BlockData
->Width
) > VarStorageData
->Size
)) {
2259 Status
= EFI_INVALID_PARAMETER
;
2260 if (BlockData
->Name
!= NULL
) {
2261 FreePool (BlockData
->Name
);
2263 FreePool (BlockData
);
2267 // Add Block Data into VarStorageData BlockEntry
2269 InsertBlockData (&VarStorageData
->BlockEntry
, &BlockData
);
2271 FirstOrderedList
= FALSE
;
2277 // 1. Set default value for OneOf option when flag field has default attribute.
2279 if (((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT
) == EFI_IFR_OPTION_DEFAULT
) ||
2280 ((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT_MFG
) == EFI_IFR_OPTION_DEFAULT_MFG
)) {
2282 // This flag is used to specify whether this option is the first. Set it to FALSE for the following options.
2283 // The first oneof option value will be used as default value when no default value is specified.
2285 FirstOneOfOption
= FALSE
;
2287 // Prepare new DefaultValue
2289 DefaultData
.Type
= DefaultValueFromFlag
;
2290 CopyMem (&DefaultData
.Value
, &IfrOneOfOption
->Value
, IfrOneOfOption
->Header
.Length
- OFFSET_OF (EFI_IFR_ONE_OF_OPTION
, Value
));
2291 if ((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT
) == EFI_IFR_OPTION_DEFAULT
) {
2292 DefaultData
.DefaultId
= EFI_HII_DEFAULT_CLASS_STANDARD
;
2293 InsertDefaultValue (BlockData
, &DefaultData
);
2295 if ((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT_MFG
) == EFI_IFR_OPTION_DEFAULT_MFG
) {
2296 DefaultData
.DefaultId
= EFI_HII_DEFAULT_CLASS_MANUFACTURING
;
2297 InsertDefaultValue (BlockData
, &DefaultData
);
2302 // 2. Set as the default value when this is the first option.
2303 // The first oneof option value will be used as default value when no default value is specified.
2305 if (FirstOneOfOption
) {
2306 // This flag is used to specify whether this option is the first. Set it to FALSE for the following options.
2307 FirstOneOfOption
= FALSE
;
2310 // Prepare new DefaultValue
2312 DefaultData
.Type
= DefaultValueFromDefault
;
2313 CopyMem (&DefaultData
.Value
, &IfrOneOfOption
->Value
, IfrOneOfOption
->Header
.Length
- OFFSET_OF (EFI_IFR_ONE_OF_OPTION
, Value
));
2314 for (LinkData
= DefaultIdArray
->Entry
.ForwardLink
; LinkData
!= &DefaultIdArray
->Entry
; LinkData
= LinkData
->ForwardLink
) {
2315 DefaultDataPtr
= BASE_CR (LinkData
, IFR_DEFAULT_DATA
, Entry
);
2316 DefaultData
.DefaultId
= DefaultDataPtr
->DefaultId
;
2317 InsertDefaultValue (BlockData
, &DefaultData
);
2322 case EFI_IFR_DEFAULT_OP
:
2324 // Update Current BlockData to the default value.
2326 if (BlockData
== NULL
|| BlockData
->Scope
== 0) {
2328 // No matched block data is ignored.
2334 // Get the DefaultId
2336 IfrDefault
= (EFI_IFR_DEFAULT
*) IfrOpHdr
;
2337 VarDefaultId
= IfrDefault
->DefaultId
;
2339 // Prepare new DefaultValue
2341 DefaultData
.Type
= DefaultValueFromOpcode
;
2342 DefaultData
.DefaultId
= VarDefaultId
;
2343 CopyMem (&DefaultData
.Value
, &IfrDefault
->Value
, IfrDefault
->Header
.Length
- OFFSET_OF (EFI_IFR_DEFAULT
, Value
));
2345 // If the value field is expression, set the cleaned flag.
2346 if (IfrDefault
->Type
== EFI_IFR_TYPE_OTHER
) {
2347 DefaultData
.Cleaned
= TRUE
;
2350 // Add DefaultValue into current BlockData
2352 InsertDefaultValue (BlockData
, &DefaultData
);
2355 // After insert the default value, reset the cleaned value for next
2356 // time used. If not set here, need to set the value before everytime
2359 DefaultData
.Cleaned
= FALSE
;
2362 case EFI_IFR_END_OP
:
2364 // End Opcode is for Var question.
2366 if (BlockData
!= NULL
) {
2367 if (BlockData
->Scope
> 0) {
2370 if (BlockData
->Scope
== 0) {
2378 if (BlockData
!= NULL
) {
2379 if (BlockData
->Scope
> 0) {
2380 BlockData
->Scope
= (UINT8
) (BlockData
->Scope
+ IfrOpHdr
->Scope
);
2383 if (BlockData
->Scope
== 0) {
2390 IfrOffset
+= IfrOpHdr
->Length
;
2391 PackageOffset
+= IfrOpHdr
->Length
;
2395 //if Status == EFI_NOT_FOUND, just means the opcode is not required,not contain any error,
2396 //so set the Status to EFI_SUCCESS.
2398 if (Status
== EFI_NOT_FOUND
){
2399 Status
= EFI_SUCCESS
;
2403 for (LinkData
= VarStorageData
->BlockEntry
.ForwardLink
; LinkData
!= &VarStorageData
->BlockEntry
; LinkData
= LinkData
->ForwardLink
) {
2404 BlockData
= BASE_CR (LinkData
, IFR_BLOCK_DATA
, Entry
);
2405 for (LinkDefault
= BlockData
->DefaultValueEntry
.ForwardLink
; LinkDefault
!= &BlockData
->DefaultValueEntry
; ) {
2406 DefaultDataPtr
= BASE_CR (LinkDefault
, IFR_DEFAULT_DATA
, Entry
);
2407 LinkDefault
= LinkDefault
->ForwardLink
;
2408 if (DefaultDataPtr
->Cleaned
== TRUE
) {
2409 RemoveEntryList (&DefaultDataPtr
->Entry
);
2410 FreePool (DefaultDataPtr
);
2419 parse the configrequest string, get the elements.
2421 @param ConfigRequest The input configrequest string.
2422 @param Progress Return the progress data.
2424 @retval Block data pointer.
2428 IN EFI_STRING ConfigRequest
,
2429 OUT EFI_STRING
*Progress
2432 EFI_STRING StringPtr
;
2433 IFR_BLOCK_DATA
*BlockData
;
2434 IFR_BLOCK_DATA
*RequestBlockArray
;
2440 IFR_BLOCK_DATA
*NextBlockData
;
2446 // Init RequestBlockArray
2448 RequestBlockArray
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
2449 if (RequestBlockArray
== NULL
) {
2452 InitializeListHead (&RequestBlockArray
->Entry
);
2455 // Get the request Block array from the request string
2460 // Parse each <RequestElement> if exists
2461 // Only <BlockName> format is supported by this help function.
2462 // <BlockName> ::= &'OFFSET='<Number>&'WIDTH='<Number>
2464 StringPtr
= ConfigRequest
;
2465 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) == 0) {
2467 // Skip the OFFSET string
2469 *Progress
= StringPtr
;
2470 StringPtr
+= StrLen (L
"&OFFSET=");
2474 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
2475 if (EFI_ERROR (Status
)) {
2482 (((Length
+ 1) / 2) < sizeof (UINT16
)) ? ((Length
+ 1) / 2) : sizeof (UINT16
)
2484 FreePool (TmpBuffer
);
2486 StringPtr
+= Length
;
2487 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
2490 StringPtr
+= StrLen (L
"&WIDTH=");
2495 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
2496 if (EFI_ERROR (Status
)) {
2503 (((Length
+ 1) / 2) < sizeof (UINT16
)) ? ((Length
+ 1) / 2) : sizeof (UINT16
)
2505 FreePool (TmpBuffer
);
2507 StringPtr
+= Length
;
2508 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
2515 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
2516 if (BlockData
== NULL
) {
2519 BlockData
->Offset
= Offset
;
2520 BlockData
->Width
= Width
;
2521 InsertBlockData (&RequestBlockArray
->Entry
, &BlockData
);
2524 // Skip &VALUE string if &VALUE does exists.
2526 if (StrnCmp (StringPtr
, L
"&VALUE=", StrLen (L
"&VALUE=")) == 0) {
2527 StringPtr
+= StrLen (L
"&VALUE=");
2532 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
2533 if (EFI_ERROR (Status
)) {
2537 StringPtr
+= Length
;
2538 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
2543 // If '\0', parsing is finished.
2545 if (*StringPtr
== 0) {
2551 // Merge the requested block data.
2553 Link
= RequestBlockArray
->Entry
.ForwardLink
;
2554 while ((Link
!= &RequestBlockArray
->Entry
) && (Link
->ForwardLink
!= &RequestBlockArray
->Entry
)) {
2555 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
2556 NextBlockData
= BASE_CR (Link
->ForwardLink
, IFR_BLOCK_DATA
, Entry
);
2557 if ((NextBlockData
->Offset
>= BlockData
->Offset
) && (NextBlockData
->Offset
<= (BlockData
->Offset
+ BlockData
->Width
))) {
2558 if ((NextBlockData
->Offset
+ NextBlockData
->Width
) > (BlockData
->Offset
+ BlockData
->Width
)) {
2559 BlockData
->Width
= (UINT16
) (NextBlockData
->Offset
+ NextBlockData
->Width
- BlockData
->Offset
);
2561 RemoveEntryList (Link
->ForwardLink
);
2562 FreePool (NextBlockData
);
2565 Link
= Link
->ForwardLink
;
2568 return RequestBlockArray
;
2571 if (RequestBlockArray
!= NULL
) {
2573 // Free Link Array RequestBlockArray
2575 while (!IsListEmpty (&RequestBlockArray
->Entry
)) {
2576 BlockData
= BASE_CR (RequestBlockArray
->Entry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
2577 RemoveEntryList (&BlockData
->Entry
);
2578 FreePool (BlockData
);
2581 FreePool (RequestBlockArray
);
2588 parse the configrequest string, get the elements.
2590 @param ConfigRequest The input config request string.
2591 @param Progress Return the progress data.
2593 @retval return data block array.
2597 IN EFI_STRING ConfigRequest
,
2598 OUT EFI_STRING
*Progress
2601 EFI_STRING StringPtr
;
2603 IFR_BLOCK_DATA
*BlockData
;
2604 IFR_BLOCK_DATA
*RequestBlockArray
;
2607 StringPtr
= ConfigRequest
;
2610 // Init RequestBlockArray
2612 RequestBlockArray
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
2613 if (RequestBlockArray
== NULL
) {
2616 InitializeListHead (&RequestBlockArray
->Entry
);
2619 // Get the request Block array from the request string
2623 // Parse each <RequestElement> if exists
2624 // Only <BlockName> format is supported by this help function.
2625 // <BlockName> ::= &'Name***=***
2627 while (StringPtr
!= NULL
&& *StringPtr
== L
'&') {
2629 *Progress
= StringPtr
;
2631 // Skip the L"&" string
2636 if ((NextTag
= StrStr (StringPtr
, L
"=")) != NULL
) {
2639 } else if ((NextTag
= StrStr (StringPtr
, L
"&")) != NULL
) {
2646 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
2647 if (BlockData
== NULL
) {
2654 BlockData
->Name
= AllocateCopyPool(StrSize (StringPtr
), StringPtr
);
2655 InsertBlockData (&RequestBlockArray
->Entry
, &BlockData
);
2659 // If has value, skip the value.
2661 StringPtr
= NextTag
+ 1;
2663 StringPtr
= StrStr (StringPtr
, L
"&");
2664 } else if (NextTag
!= NULL
) {
2666 // restore the '&' text.
2668 StringPtr
= NextTag
;
2673 return RequestBlockArray
;
2676 if (RequestBlockArray
!= NULL
) {
2678 // Free Link Array RequestBlockArray
2680 while (!IsListEmpty (&RequestBlockArray
->Entry
)) {
2681 BlockData
= BASE_CR (RequestBlockArray
->Entry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
2682 RemoveEntryList (&BlockData
->Entry
);
2683 if (BlockData
->Name
!= NULL
) {
2684 FreePool (BlockData
->Name
);
2686 FreePool (BlockData
);
2689 FreePool (RequestBlockArray
);
2696 Generate ConfigRequest string base on the varstore info.
2698 @param ConfigHdr The config header for this varstore.
2699 @param VarStorageData The varstore info.
2700 @param Status Return Status.
2701 @param ConfigRequest The ConfigRequest info may be return.
2703 @retval TRUE Need to continue
2704 @retval Others NO need to continue or error occur.
2707 GenerateConfigRequest (
2708 IN CHAR16
*ConfigHdr
,
2709 IN IFR_VARSTORAGE_DATA
*VarStorageData
,
2710 OUT EFI_STATUS
*Status
,
2711 IN OUT EFI_STRING
*ConfigRequest
2717 CHAR16
*FullConfigRequest
;
2719 IFR_BLOCK_DATA
*BlockData
;
2722 // Append VarStorageData BlockEntry into *Request string
2723 // Now support only one varstore in a form package.
2727 // Go through all VarStorageData Entry and get BlockEntry for each one for the multiple varstore in a single form package
2728 // Then construct them all to return MultiRequest string : ConfigHdr BlockConfig
2732 // Compute the length of the entire request starting with <ConfigHdr> and a
2736 Length
= StrLen (ConfigHdr
) + 1;
2738 for (Link
= VarStorageData
->BlockEntry
.ForwardLink
; Link
!= &VarStorageData
->BlockEntry
; Link
= Link
->ForwardLink
) {
2740 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
2741 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2743 // Add <BlockName> length for each Name
2745 // <BlockName> ::= &Name1&Name2&...
2746 // |1| StrLen(Name1)
2748 Length
= Length
+ (1 + StrLen (BlockData
->Name
));
2751 // Add <BlockName> length for each Offset/Width pair
2753 // <BlockName> ::= &OFFSET=1234&WIDTH=1234
2754 // | 8 | 4 | 7 | 4 |
2756 Length
= Length
+ (8 + 4 + 7 + 4);
2760 // No any request block data is found. The request string can't be constructed.
2763 *Status
= EFI_SUCCESS
;
2768 // Allocate buffer for the entire <ConfigRequest>
2770 FullConfigRequest
= AllocateZeroPool (Length
* sizeof (CHAR16
));
2771 if (FullConfigRequest
== NULL
) {
2772 *Status
= EFI_OUT_OF_RESOURCES
;
2775 StringPtr
= FullConfigRequest
;
2778 // Start with <ConfigHdr>
2780 StrCpyS (StringPtr
, Length
, ConfigHdr
);
2781 StringPtr
+= StrLen (StringPtr
);
2784 // Loop through all the Offset/Width pairs and append them to ConfigRequest
2786 for (Link
= VarStorageData
->BlockEntry
.ForwardLink
; Link
!= &VarStorageData
->BlockEntry
; Link
= Link
->ForwardLink
) {
2787 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
2788 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2794 (1 + StrLen (BlockData
->Name
) + 1) * sizeof (CHAR16
),
2800 // Append &OFFSET=XXXX&WIDTH=YYYY\0
2804 (8 + 4 + 7 + 4 + 1) * sizeof (CHAR16
),
2805 L
"&OFFSET=%04X&WIDTH=%04X",
2810 StringPtr
+= StrLen (StringPtr
);
2813 // Set to the got full request string.
2815 HiiToLower (FullConfigRequest
);
2817 if (*ConfigRequest
!= NULL
) {
2818 FreePool (*ConfigRequest
);
2820 *ConfigRequest
= FullConfigRequest
;
2826 Generate ConfigRequest Header base on the varstore info.
2828 @param VarStorageData The varstore info.
2829 @param DevicePath Device path for this varstore.
2830 @param ConfigHdr The config header for this varstore.
2832 @retval EFI_SUCCESS Generate the header success.
2833 @retval EFI_OUT_OF_RESOURCES Allocate buffer fail.
2837 IN IFR_VARSTORAGE_DATA
*VarStorageData
,
2838 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
2839 OUT EFI_STRING
*ConfigHdr
2848 Status
= EFI_SUCCESS
;
2854 // Construct <ConfigHdr> : "GUID=...&NAME=...&PATH=..." by VarStorageData Guid, Name and DriverHandle
2856 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*) &VarStorageData
->Guid
, 1, &GuidStr
);
2857 if (VarStorageData
->Name
!= NULL
) {
2858 GenerateSubStr (L
"NAME=", StrLen (VarStorageData
->Name
) * sizeof (CHAR16
), (VOID
*) VarStorageData
->Name
, 2, &NameStr
);
2860 GenerateSubStr (L
"NAME=", 0, NULL
, 2, &NameStr
);
2864 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) DevicePath
),
2865 (VOID
*) DevicePath
,
2869 Length
= StrLen (GuidStr
) + StrLen (NameStr
) + StrLen (PathStr
) + 1;
2870 if (VarStorageData
->Name
== NULL
) {
2874 *ConfigHdr
= AllocateZeroPool (Length
* sizeof (CHAR16
));
2875 if (*ConfigHdr
== NULL
) {
2876 Status
= EFI_OUT_OF_RESOURCES
;
2879 StrCpyS (*ConfigHdr
, Length
, GuidStr
);
2880 StrCatS (*ConfigHdr
, Length
, NameStr
);
2881 if (VarStorageData
->Name
== NULL
) {
2882 StrCatS (*ConfigHdr
, Length
, L
"&");
2884 StrCatS (*ConfigHdr
, Length
, PathStr
);
2887 // Remove the last character L'&'
2889 *(*ConfigHdr
+ StrLen (*ConfigHdr
) - 1) = L
'\0';
2892 if (GuidStr
!= NULL
) {
2896 if (NameStr
!= NULL
) {
2900 if (PathStr
!= NULL
) {
2908 Get Data buffer size based on data type.
2910 @param ValueType The input data type.
2912 @retval The data buffer size for the input type.
2919 UINT16 StorageWidth
;
2921 switch (ValueType
) {
2922 case EFI_IFR_NUMERIC_SIZE_1
:
2923 case EFI_IFR_TYPE_BOOLEAN
:
2924 StorageWidth
= (UINT16
) sizeof (UINT8
);
2927 case EFI_IFR_NUMERIC_SIZE_2
:
2928 StorageWidth
= (UINT16
) sizeof (UINT16
);
2931 case EFI_IFR_NUMERIC_SIZE_4
:
2932 StorageWidth
= (UINT16
) sizeof (UINT32
);
2935 case EFI_IFR_NUMERIC_SIZE_8
:
2936 StorageWidth
= (UINT16
) sizeof (UINT64
);
2939 case EFI_IFR_TYPE_TIME
:
2940 StorageWidth
= (UINT16
) sizeof (EFI_IFR_TIME
);
2943 case EFI_IFR_TYPE_DATE
:
2944 StorageWidth
= (UINT16
) sizeof (EFI_IFR_DATE
);
2952 return StorageWidth
;
2956 Generate ConfigAltResp string base on the varstore info.
2958 @param HiiHandle Hii Handle for this hii package.
2959 @param ConfigHdr The config header for this varstore.
2960 @param VarStorageData The varstore info.
2961 @param DefaultIdArray The Default id array.
2962 @param DefaultAltCfgResp The DefaultAltCfgResp info may be return.
2964 @retval TRUE Need to continue
2965 @retval Others NO need to continue or error occur.
2968 GenerateAltConfigResp (
2969 IN EFI_HII_HANDLE HiiHandle
,
2970 IN CHAR16
*ConfigHdr
,
2971 IN IFR_VARSTORAGE_DATA
*VarStorageData
,
2972 IN IFR_DEFAULT_DATA
*DefaultIdArray
,
2973 IN OUT EFI_STRING
*DefaultAltCfgResp
2979 LIST_ENTRY
*LinkData
;
2980 LIST_ENTRY
*LinkDefault
;
2981 LIST_ENTRY
*ListEntry
;
2983 IFR_BLOCK_DATA
*BlockData
;
2984 IFR_DEFAULT_DATA
*DefaultId
;
2985 IFR_DEFAULT_DATA
*DefaultValueData
;
2988 CHAR16
*DefaultString
;
2992 DefaultString
= NULL
;
2994 // Add length for <ConfigHdr> + '\0'
2996 Length
= StrLen (ConfigHdr
) + 1;
2998 for (Link
= DefaultIdArray
->Entry
.ForwardLink
; Link
!= &DefaultIdArray
->Entry
; Link
= Link
->ForwardLink
) {
2999 DefaultId
= BASE_CR (Link
, IFR_DEFAULT_DATA
, Entry
);
3001 // Add length for "&<ConfigHdr>&ALTCFG=XXXX"
3002 // |1| StrLen (ConfigHdr) | 8 | 4 |
3004 Length
+= (1 + StrLen (ConfigHdr
) + 8 + 4);
3006 for (LinkData
= VarStorageData
->BlockEntry
.ForwardLink
; LinkData
!= &VarStorageData
->BlockEntry
; LinkData
= LinkData
->ForwardLink
) {
3007 BlockData
= BASE_CR (LinkData
, IFR_BLOCK_DATA
, Entry
);
3008 ListEntry
= &BlockData
->DefaultValueEntry
;
3009 for (LinkDefault
= ListEntry
->ForwardLink
; LinkDefault
!= ListEntry
; LinkDefault
= LinkDefault
->ForwardLink
) {
3010 DefaultValueData
= BASE_CR (LinkDefault
, IFR_DEFAULT_DATA
, Entry
);
3011 if (DefaultValueData
->DefaultId
!= DefaultId
->DefaultId
) {
3014 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3016 // Add length for "&Name1=zzzzzzzzzzzz"
3019 Length
+= (1 + StrLen (BlockData
->Name
) + 1 + BlockData
->Width
* 2);
3022 // Add length for "&OFFSET=XXXX&WIDTH=YYYY&VALUE=zzzzzzzzzzzz"
3023 // | 8 | 4 | 7 | 4 | 7 | Width * 2 |
3025 Length
+= (8 + 4 + 7 + 4 + 7 + BlockData
->Width
* 2);
3033 // No default value is found. The default string doesn't exist.
3040 // Allocate buffer for the entire <DefaultAltCfgResp>
3042 *DefaultAltCfgResp
= AllocateZeroPool (Length
* sizeof (CHAR16
));
3043 if (*DefaultAltCfgResp
== NULL
) {
3044 return EFI_OUT_OF_RESOURCES
;
3046 StringPtr
= *DefaultAltCfgResp
;
3049 // Start with <ConfigHdr>
3051 StrCpyS (StringPtr
, Length
, ConfigHdr
);
3052 StringPtr
+= StrLen (StringPtr
);
3054 for (Link
= DefaultIdArray
->Entry
.ForwardLink
; Link
!= &DefaultIdArray
->Entry
; Link
= Link
->ForwardLink
) {
3055 DefaultId
= BASE_CR (Link
, IFR_DEFAULT_DATA
, Entry
);
3057 // Add <AltConfigHdr> of the form "&<ConfigHdr>&ALTCFG=XXXX\0"
3058 // |1| StrLen (ConfigHdr) | 8 | 4 |
3062 (1 + StrLen (ConfigHdr
) + 8 + 4 + 1) * sizeof (CHAR16
),
3065 DefaultId
->DefaultId
3067 StringPtr
+= StrLen (StringPtr
);
3069 for (LinkData
= VarStorageData
->BlockEntry
.ForwardLink
; LinkData
!= &VarStorageData
->BlockEntry
; LinkData
= LinkData
->ForwardLink
) {
3070 BlockData
= BASE_CR (LinkData
, IFR_BLOCK_DATA
, Entry
);
3071 ListEntry
= &BlockData
->DefaultValueEntry
;
3072 for (LinkDefault
= ListEntry
->ForwardLink
; LinkDefault
!= ListEntry
; LinkDefault
= LinkDefault
->ForwardLink
) {
3073 DefaultValueData
= BASE_CR (LinkDefault
, IFR_DEFAULT_DATA
, Entry
);
3074 if (DefaultValueData
->DefaultId
!= DefaultId
->DefaultId
) {
3077 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3080 (1 + StrLen (ConfigHdr
) + 1) * sizeof (CHAR16
),
3084 StringPtr
+= StrLen (StringPtr
);
3087 // Add <BlockConfig>
3088 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>
3092 (8 + 4 + 7 + 4 + 7 + 1) * sizeof (CHAR16
),
3093 L
"&OFFSET=%04X&WIDTH=%04X&VALUE=",
3097 StringPtr
+= StrLen (StringPtr
);
3099 Width
= BlockData
->Width
;
3101 // Convert Value to a hex string in "%x" format
3102 // NOTE: This is in the opposite byte that GUID and PATH use
3104 if (BlockData
->OpCode
== EFI_IFR_STRING_OP
){
3105 DefaultString
= InternalGetString(HiiHandle
, DefaultValueData
->Value
.string
);
3106 TmpBuffer
= (UINT8
*) DefaultString
;
3108 TmpBuffer
= (UINT8
*) &(DefaultValueData
->Value
);
3110 for (; Width
> 0 && (TmpBuffer
!= NULL
); Width
--) {
3111 StringPtr
+= UnicodeValueToString (StringPtr
, PREFIX_ZERO
| RADIX_HEX
, TmpBuffer
[Width
- 1], 2);
3113 if (DefaultString
!= NULL
){
3114 FreePool(DefaultString
);
3115 DefaultString
= NULL
;
3121 HiiToLower (*DefaultAltCfgResp
);
3127 This function gets the full request string and full default value string by
3128 parsing IFR data in HII form packages.
3130 When Request points to NULL string, the request string and default value string
3131 for each varstore in form package will return.
3133 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
3134 @param DevicePath Device Path which Hii Config Access Protocol is registered.
3135 @param Request Pointer to a null-terminated Unicode string in
3136 <ConfigRequest> format. When it doesn't contain
3137 any RequestElement, it will be updated to return
3138 the full RequestElement retrieved from IFR data.
3139 If it points to NULL, the request string for the first
3140 varstore in form package will be merged into a
3141 <MultiConfigRequest> format string and return.
3142 @param AltCfgResp Pointer to a null-terminated Unicode string in
3143 <ConfigAltResp> format. When the pointer is to NULL,
3144 the full default value string retrieved from IFR data
3145 will return. When the pinter is to a string, the
3146 full default value string retrieved from IFR data
3147 will be merged into the input string and return.
3148 When Request points to NULL, the default value string
3149 for each varstore in form package will be merged into
3150 a <MultiConfigAltResp> format string and return.
3151 @param PointerProgress Optional parameter, it can be be NULL.
3152 When it is not NULL, if Request is NULL, it returns NULL.
3153 On return, points to a character in the Request
3154 string. Points to the string's null terminator if
3155 request was successful. Points to the most recent
3156 & before the first failing name / value pair (or
3157 the beginning of the string if the failure is in
3158 the first name / value pair) if the request was
3160 @retval EFI_SUCCESS The Results string is set to the full request string.
3161 And AltCfgResp contains all default value string.
3162 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
3163 @retval EFI_NOT_FOUND The varstore (Guid and Name) in Request string
3164 can't be found in Form package.
3165 @retval EFI_NOT_FOUND HiiPackage can't be got on the input HiiHandle.
3166 @retval EFI_INVALID_PARAMETER Request points to NULL.
3171 GetFullStringFromHiiFormPackages (
3172 IN HII_DATABASE_RECORD
*DataBaseRecord
,
3173 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
3174 IN OUT EFI_STRING
*Request
,
3175 IN OUT EFI_STRING
*AltCfgResp
,
3176 OUT EFI_STRING
*PointerProgress OPTIONAL
3180 UINT8
*HiiFormPackage
;
3182 IFR_BLOCK_DATA
*RequestBlockArray
;
3183 IFR_BLOCK_DATA
*BlockData
;
3184 IFR_DEFAULT_DATA
*DefaultValueData
;
3185 IFR_DEFAULT_DATA
*DefaultId
;
3186 IFR_DEFAULT_DATA
*DefaultIdArray
;
3187 IFR_VARSTORAGE_DATA
*VarStorageData
;
3188 EFI_STRING DefaultAltCfgResp
;
3189 EFI_STRING ConfigHdr
;
3190 EFI_STRING StringPtr
;
3191 EFI_STRING Progress
;
3193 if (DataBaseRecord
== NULL
|| DevicePath
== NULL
|| Request
== NULL
|| AltCfgResp
== NULL
) {
3194 return EFI_INVALID_PARAMETER
;
3198 // Initialize the local variables.
3200 RequestBlockArray
= NULL
;
3201 DefaultIdArray
= NULL
;
3202 VarStorageData
= NULL
;
3203 DefaultAltCfgResp
= NULL
;
3205 HiiFormPackage
= NULL
;
3207 Progress
= *Request
;
3209 Status
= GetFormPackageData (DataBaseRecord
, &HiiFormPackage
, &PackageSize
);
3210 if (EFI_ERROR (Status
)) {
3215 // 1. Get the request block array by Request String when Request string containts the block array.
3218 if (*Request
!= NULL
) {
3219 StringPtr
= *Request
;
3223 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
3224 Status
= EFI_INVALID_PARAMETER
;
3227 StringPtr
+= StrLen (L
"GUID=");
3228 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&NAME=", StrLen (L
"&NAME=")) != 0) {
3231 if (*StringPtr
== L
'\0') {
3232 Status
= EFI_INVALID_PARAMETER
;
3235 StringPtr
+= StrLen (L
"&NAME=");
3236 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&PATH=", StrLen (L
"&PATH=")) != 0) {
3239 if (*StringPtr
== L
'\0') {
3240 Status
= EFI_INVALID_PARAMETER
;
3243 StringPtr
+= StrLen (L
"&PATH=");
3244 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
3248 if (*StringPtr
== L
'\0') {
3250 // No request block is found.
3257 // If StringPtr != NULL, get the request elements.
3259 if (StringPtr
!= NULL
) {
3260 if (StrStr (StringPtr
, L
"&OFFSET=") != NULL
) {
3261 RequestBlockArray
= GetBlockElement(StringPtr
, &Progress
);
3263 RequestBlockArray
= GetNameElement(StringPtr
, &Progress
);
3266 if (RequestBlockArray
== NULL
) {
3267 Status
= EFI_INVALID_PARAMETER
;
3273 // Initialize DefaultIdArray to store the map between DeaultId and DefaultName
3275 DefaultIdArray
= (IFR_DEFAULT_DATA
*) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
3276 if (DefaultIdArray
== NULL
) {
3277 Status
= EFI_OUT_OF_RESOURCES
;
3280 InitializeListHead (&DefaultIdArray
->Entry
);
3283 // Initialize VarStorageData to store the var store Block and Default value information.
3285 VarStorageData
= (IFR_VARSTORAGE_DATA
*) AllocateZeroPool (sizeof (IFR_VARSTORAGE_DATA
));
3286 if (VarStorageData
== NULL
) {
3287 Status
= EFI_OUT_OF_RESOURCES
;
3290 InitializeListHead (&VarStorageData
->Entry
);
3291 InitializeListHead (&VarStorageData
->BlockEntry
);
3294 // 2. Parse FormPackage to get BlockArray and DefaultId Array for the request BlockArray.
3298 // Parse the opcode in form pacakge to get the default setting.
3300 Status
= ParseIfrData (DataBaseRecord
->Handle
,
3302 (UINT32
) PackageSize
,
3307 if (EFI_ERROR (Status
)) {
3312 // No requested varstore in IFR data and directly return
3314 if (VarStorageData
->Type
== 0 && VarStorageData
->Name
== NULL
) {
3315 Status
= EFI_SUCCESS
;
3320 // 3. Construct Request Element (Block Name) for 2.1 and 2.2 case.
3322 Status
= GenerateHdr (VarStorageData
, DevicePath
, &ConfigHdr
);
3323 if (EFI_ERROR (Status
)) {
3327 if (RequestBlockArray
== NULL
) {
3328 if (!GenerateConfigRequest(ConfigHdr
, VarStorageData
, &Status
, Request
)) {
3334 // 4. Construct Default Value string in AltResp according to request element.
3335 // Go through all VarStorageData Entry and get the DefaultId array for each one
3336 // Then construct them all to : ConfigHdr AltConfigHdr ConfigBody AltConfigHdr ConfigBody
3338 Status
= GenerateAltConfigResp (DataBaseRecord
->Handle
,ConfigHdr
, VarStorageData
, DefaultIdArray
, &DefaultAltCfgResp
);
3339 if (EFI_ERROR (Status
)) {
3344 // 5. Merge string into the input AltCfgResp if the iput *AltCfgResp is not NULL.
3346 if (*AltCfgResp
!= NULL
&& DefaultAltCfgResp
!= NULL
) {
3347 Status
= MergeDefaultString (AltCfgResp
, DefaultAltCfgResp
);
3348 FreePool (DefaultAltCfgResp
);
3349 } else if (*AltCfgResp
== NULL
) {
3350 *AltCfgResp
= DefaultAltCfgResp
;
3354 if (RequestBlockArray
!= NULL
) {
3356 // Free Link Array RequestBlockArray
3358 while (!IsListEmpty (&RequestBlockArray
->Entry
)) {
3359 BlockData
= BASE_CR (RequestBlockArray
->Entry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
3360 RemoveEntryList (&BlockData
->Entry
);
3361 if (BlockData
->Name
!= NULL
) {
3362 FreePool (BlockData
->Name
);
3364 FreePool (BlockData
);
3367 FreePool (RequestBlockArray
);
3370 if (VarStorageData
!= NULL
) {
3372 // Free link array VarStorageData
3374 while (!IsListEmpty (&VarStorageData
->BlockEntry
)) {
3375 BlockData
= BASE_CR (VarStorageData
->BlockEntry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
3376 RemoveEntryList (&BlockData
->Entry
);
3377 if (BlockData
->Name
!= NULL
) {
3378 FreePool (BlockData
->Name
);
3381 // Free default value link array
3383 while (!IsListEmpty (&BlockData
->DefaultValueEntry
)) {
3384 DefaultValueData
= BASE_CR (BlockData
->DefaultValueEntry
.ForwardLink
, IFR_DEFAULT_DATA
, Entry
);
3385 RemoveEntryList (&DefaultValueData
->Entry
);
3386 FreePool (DefaultValueData
);
3388 FreePool (BlockData
);
3390 FreePool (VarStorageData
);
3393 if (DefaultIdArray
!= NULL
) {
3395 // Free DefaultId Array
3397 while (!IsListEmpty (&DefaultIdArray
->Entry
)) {
3398 DefaultId
= BASE_CR (DefaultIdArray
->Entry
.ForwardLink
, IFR_DEFAULT_DATA
, Entry
);
3399 RemoveEntryList (&DefaultId
->Entry
);
3400 FreePool (DefaultId
);
3402 FreePool (DefaultIdArray
);
3406 // Free the allocated string
3408 if (ConfigHdr
!= NULL
) {
3409 FreePool (ConfigHdr
);
3413 // Free Pacakge data
3415 if (HiiFormPackage
!= NULL
) {
3416 FreePool (HiiFormPackage
);
3419 if (PointerProgress
!= NULL
) {
3420 if (*Request
== NULL
) {
3421 *PointerProgress
= NULL
;
3422 } else if (EFI_ERROR (Status
)) {
3423 *PointerProgress
= *Request
;
3425 *PointerProgress
= *Request
+ StrLen (*Request
);
3433 This function gets the full request resp string by
3434 parsing IFR data in HII form packages.
3436 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
3438 @param EfiVarStoreInfo The efi varstore info which is save in the EFI
3439 varstore data structure.
3440 @param Request Pointer to a null-terminated Unicode string in
3441 <ConfigRequest> format.
3442 @param RequestResp Pointer to a null-terminated Unicode string in
3443 <ConfigResp> format.
3444 @param AccessProgress On return, points to a character in the Request
3445 string. Points to the string's null terminator if
3446 request was successful. Points to the most recent
3447 & before the first failing name / value pair (or
3448 the beginning of the string if the failure is in
3449 the first name / value pair) if the request was
3452 @retval EFI_SUCCESS The Results string is set to the full request string.
3453 And AltCfgResp contains all default value string.
3454 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
3455 @retval EFI_INVALID_PARAMETER Request points to NULL.
3459 GetConfigRespFromEfiVarStore (
3460 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
3461 IN EFI_IFR_VARSTORE_EFI
*EfiVarStoreInfo
,
3462 IN EFI_STRING Request
,
3463 OUT EFI_STRING
*RequestResp
,
3464 OUT EFI_STRING
*AccessProgress
3468 EFI_STRING VarStoreName
;
3472 Status
= EFI_SUCCESS
;
3475 VarStoreName
= NULL
;
3476 *AccessProgress
= Request
;
3478 VarStoreName
= AllocateZeroPool (AsciiStrSize ((CHAR8
*)EfiVarStoreInfo
->Name
) * sizeof (CHAR16
));
3479 if (VarStoreName
== NULL
) {
3480 Status
= EFI_OUT_OF_RESOURCES
;
3483 AsciiStrToUnicodeStr ((CHAR8
*) EfiVarStoreInfo
->Name
, VarStoreName
);
3486 Status
= gRT
->GetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, NULL
, &BufferSize
, NULL
);
3487 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
3491 VarStore
= AllocateZeroPool (BufferSize
);
3492 ASSERT (VarStore
!= NULL
);
3493 Status
= gRT
->GetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, NULL
, &BufferSize
, VarStore
);
3494 if (EFI_ERROR (Status
)) {
3498 Status
= HiiBlockToConfig(This
, Request
, VarStore
, BufferSize
, RequestResp
, AccessProgress
);
3499 if (EFI_ERROR (Status
)) {
3504 if (VarStoreName
!= NULL
) {
3505 FreePool (VarStoreName
);
3508 if (VarStore
!= NULL
) {
3509 FreePool (VarStore
);
3517 This function route the full request resp string for efi varstore.
3519 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
3521 @param EfiVarStoreInfo The efi varstore info which is save in the EFI
3522 varstore data structure.
3523 @param RequestResp Pointer to a null-terminated Unicode string in
3524 <ConfigResp> format.
3525 @param Result Pointer to a null-terminated Unicode string in
3526 <ConfigResp> format.
3528 @retval EFI_SUCCESS The Results string is set to the full request string.
3529 And AltCfgResp contains all default value string.
3530 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
3531 @retval EFI_INVALID_PARAMETER Request points to NULL.
3535 RouteConfigRespForEfiVarStore (
3536 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
3537 IN EFI_IFR_VARSTORE_EFI
*EfiVarStoreInfo
,
3538 IN EFI_STRING RequestResp
,
3539 OUT EFI_STRING
*Result
3543 EFI_STRING VarStoreName
;
3548 Status
= EFI_SUCCESS
;
3551 VarStoreName
= NULL
;
3553 VarStoreName
= AllocateZeroPool (AsciiStrSize ((CHAR8
*)EfiVarStoreInfo
->Name
) * sizeof (CHAR16
));
3554 if (VarStoreName
== NULL
) {
3555 Status
= EFI_OUT_OF_RESOURCES
;
3558 AsciiStrToUnicodeStr ((CHAR8
*) EfiVarStoreInfo
->Name
, VarStoreName
);
3560 Status
= gRT
->GetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, NULL
, &BufferSize
, NULL
);
3561 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
3565 BlockSize
= BufferSize
;
3566 VarStore
= AllocateZeroPool (BufferSize
);
3567 ASSERT (VarStore
!= NULL
);
3568 Status
= gRT
->GetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, NULL
, &BufferSize
, VarStore
);
3569 if (EFI_ERROR (Status
)) {
3573 Status
= HiiConfigToBlock(This
, RequestResp
, VarStore
, &BlockSize
, Result
);
3574 if (EFI_ERROR (Status
)) {
3578 Status
= gRT
->SetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, EfiVarStoreInfo
->Attributes
, BufferSize
, VarStore
);
3579 if (EFI_ERROR (Status
)) {
3584 if (VarStoreName
!= NULL
) {
3585 FreePool (VarStoreName
);
3588 if (VarStore
!= NULL
) {
3589 FreePool (VarStore
);
3596 Validate the config request elements.
3598 @param ConfigElements A null-terminated Unicode string in <ConfigRequest> format,
3599 without configHdr field.
3601 @retval CHAR16 * THE first Name/value pair not correct.
3602 @retval NULL Success parse the name/value pair
3605 OffsetWidthValidate (
3606 CHAR16
*ConfigElements
3612 StringPtr
= ConfigElements
;
3616 if (StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) != 0) {
3620 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
3623 if (*StringPtr
== L
'\0') {
3627 StringPtr
+= StrLen (L
"&WIDTH=");
3628 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) != 0) {
3632 if (*StringPtr
== L
'\0') {
3639 Validate the config request elements.
3641 @param ConfigElements A null-terminated Unicode string in <ConfigRequest> format,
3642 without configHdr field.
3644 @retval CHAR16 * THE first Name/value pair not correct.
3645 @retval NULL Success parse the name/value pair
3650 CHAR16
*ConfigElements
3656 StringPtr
= ConfigElements
;
3660 if (*StringPtr
!= L
'&') {
3665 StringPtr
= StrStr (StringPtr
, L
"&");
3667 if (StringPtr
== NULL
) {
3674 Validate the config request string.
3676 @param ConfigRequest A null-terminated Unicode string in <ConfigRequest> format.
3678 @retval CHAR16 * THE first element not correct.
3679 @retval NULL Success parse the name/value pair
3683 ConfigRequestValidate (
3684 CHAR16
*ConfigRequest
3687 BOOLEAN HasNameField
;
3690 HasNameField
= TRUE
;
3691 StringPtr
= ConfigRequest
;
3694 // Check <ConfigHdr>
3696 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
3697 return ConfigRequest
;
3699 StringPtr
+= StrLen (L
"GUID=");
3700 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&NAME=", StrLen (L
"&NAME=")) != 0) {
3703 if (*StringPtr
== L
'\0') {
3704 return ConfigRequest
;
3706 StringPtr
+= StrLen (L
"&NAME=");
3707 if (*StringPtr
== L
'&') {
3708 HasNameField
= FALSE
;
3710 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&PATH=", StrLen (L
"&PATH=")) != 0) {
3713 if (*StringPtr
== L
'\0') {
3714 return ConfigRequest
;
3716 StringPtr
+= StrLen (L
"&PATH=");
3717 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
3721 if (*StringPtr
== L
'\0') {
3727 // Should be Buffer varstore, config request should be "OFFSET/Width" pairs.
3729 return OffsetWidthValidate(StringPtr
);
3732 // Should be Name/Value varstore, config request should be "&name1&name2..." pairs.
3734 return NameValueValidate(StringPtr
);
3739 This function allows a caller to extract the current configuration
3740 for one or more named elements from one or more drivers.
3742 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
3744 @param Request A null-terminated Unicode string in
3745 <MultiConfigRequest> format.
3746 @param Progress On return, points to a character in the Request
3747 string. Points to the string's null terminator if
3748 request was successful. Points to the most recent
3749 & before the first failing name / value pair (or
3750 the beginning of the string if the failure is in
3751 the first name / value pair) if the request was
3753 @param Results Null-terminated Unicode string in
3754 <MultiConfigAltResp> format which has all values
3755 filled in for the names in the Request string.
3756 String to be allocated by the called function.
3758 @retval EFI_SUCCESS The Results string is filled with the values
3759 corresponding to all requested names.
3760 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
3761 results that must be stored awaiting possible
3763 @retval EFI_NOT_FOUND Routing data doesn't match any known driver.
3764 Progress set to the "G" in "GUID" of the routing
3765 header that doesn't match. Note: There is no
3766 requirement that all routing data be validated
3767 before any configuration extraction.
3768 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Request
3769 parameter would result in this type of error. The
3770 Progress parameter is set to NULL.
3771 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set to most recent &
3772 before the error or the beginning of the string.
3773 @retval EFI_INVALID_PARAMETER The ExtractConfig function of the underlying HII
3774 Configuration Access Protocol returned
3775 EFI_INVALID_PARAMETER. Progress set to most recent
3776 & before the error or the beginning of the string.
3781 HiiConfigRoutingExtractConfig (
3782 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
3783 IN CONST EFI_STRING Request
,
3784 OUT EFI_STRING
*Progress
,
3785 OUT EFI_STRING
*Results
3788 HII_DATABASE_PRIVATE_DATA
*Private
;
3789 EFI_STRING StringPtr
;
3790 EFI_STRING ConfigRequest
;
3792 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
3793 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
3796 HII_DATABASE_RECORD
*Database
;
3797 UINT8
*DevicePathPkg
;
3798 UINT8
*CurrentDevicePath
;
3799 EFI_HANDLE DriverHandle
;
3800 EFI_HII_HANDLE HiiHandle
;
3801 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
3802 EFI_STRING AccessProgress
;
3803 EFI_STRING AccessResults
;
3804 EFI_STRING DefaultResults
;
3805 BOOLEAN FirstElement
;
3806 BOOLEAN IfrDataParsedFlag
;
3807 BOOLEAN IsEfiVarStore
;
3808 EFI_IFR_VARSTORE_EFI
*EfiVarStoreInfo
;
3809 EFI_STRING ErrorPtr
;
3810 UINTN DevicePathSize
;
3812 if (This
== NULL
|| Progress
== NULL
|| Results
== NULL
) {
3813 return EFI_INVALID_PARAMETER
;
3816 if (Request
== NULL
) {
3818 return EFI_INVALID_PARAMETER
;
3821 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
3822 StringPtr
= Request
;
3823 *Progress
= StringPtr
;
3824 DefaultResults
= NULL
;
3825 ConfigRequest
= NULL
;
3826 Status
= EFI_SUCCESS
;
3827 AccessResults
= NULL
;
3828 AccessProgress
= NULL
;
3830 IfrDataParsedFlag
= FALSE
;
3831 IsEfiVarStore
= FALSE
;
3832 EfiVarStoreInfo
= NULL
;
3835 // The first element of <MultiConfigRequest> should be
3836 // <GuidHdr>, which is in 'GUID='<Guid> syntax.
3838 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
3839 return EFI_INVALID_PARAMETER
;
3842 FirstElement
= TRUE
;
3845 // Allocate a fix length of memory to store Results. Reallocate memory for
3846 // Results if this fix length is insufficient.
3848 *Results
= (EFI_STRING
) AllocateZeroPool (MAX_STRING_LENGTH
);
3849 if (*Results
== NULL
) {
3850 return EFI_OUT_OF_RESOURCES
;
3853 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) == 0) {
3855 // If parsing error, set Progress to the beginning of the <MultiConfigRequest>
3856 // or most recent & before the error.
3858 if (StringPtr
== Request
) {
3859 *Progress
= StringPtr
;
3861 *Progress
= StringPtr
- 1;
3865 // Process each <ConfigRequest> of <MultiConfigRequest>
3867 Length
= CalculateConfigStringLen (StringPtr
);
3868 ConfigRequest
= AllocateCopyPool ((Length
+ 1) * sizeof (CHAR16
), StringPtr
);
3869 if (ConfigRequest
== NULL
) {
3870 Status
= EFI_OUT_OF_RESOURCES
;
3873 *(ConfigRequest
+ Length
) = 0;
3876 // Get the UEFI device path
3878 Status
= GetDevicePath (ConfigRequest
, (UINT8
**) &DevicePath
);
3879 if (EFI_ERROR (Status
)) {
3884 // Find driver which matches the routing data.
3886 DriverHandle
= NULL
;
3889 for (Link
= Private
->DatabaseList
.ForwardLink
;
3890 Link
!= &Private
->DatabaseList
;
3891 Link
= Link
->ForwardLink
3893 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
3894 if ((DevicePathPkg
= Database
->PackageList
->DevicePathPkg
) != NULL
) {
3895 CurrentDevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
3896 DevicePathSize
= GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) CurrentDevicePath
);
3897 if ((CompareMem (DevicePath
,CurrentDevicePath
,DevicePathSize
) == 0) && IsThisPackageList(Database
, ConfigRequest
)) {
3898 DriverHandle
= Database
->DriverHandle
;
3899 HiiHandle
= Database
->Handle
;
3906 // Try to find driver handle by device path.
3908 if (DriverHandle
== NULL
) {
3909 TempDevicePath
= DevicePath
;
3910 Status
= gBS
->LocateDevicePath (
3911 &gEfiDevicePathProtocolGuid
,
3915 if (EFI_ERROR (Status
) || (DriverHandle
== NULL
)) {
3917 // Routing data does not match any known driver.
3918 // Set Progress to the 'G' in "GUID" of the routing header.
3920 *Progress
= StringPtr
;
3921 Status
= EFI_NOT_FOUND
;
3927 // Validate ConfigRequest String.
3929 ErrorPtr
= ConfigRequestValidate(ConfigRequest
);
3930 if (ErrorPtr
!= NULL
) {
3931 *Progress
= StrStr (StringPtr
, ErrorPtr
);
3932 Status
= EFI_INVALID_PARAMETER
;
3937 // Check whether ConfigRequest contains request string.
3939 IfrDataParsedFlag
= FALSE
;
3940 if ((HiiHandle
!= NULL
) && !GetElementsFromRequest(ConfigRequest
)) {
3942 // Get the full request string from IFR when HiiPackage is registered to HiiHandle
3944 IfrDataParsedFlag
= TRUE
;
3945 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &ConfigRequest
, &DefaultResults
, &AccessProgress
);
3946 if (EFI_ERROR (Status
)) {
3948 // AccessProgress indicates the parsing progress on <ConfigRequest>.
3949 // Map it to the progress on <MultiConfigRequest> then return it.
3951 ASSERT (AccessProgress
!= NULL
);
3952 *Progress
= StrStr (StringPtr
, AccessProgress
);
3956 // Not any request block is found.
3958 if (!GetElementsFromRequest(ConfigRequest
)) {
3959 AccessResults
= AllocateCopyPool (StrSize (ConfigRequest
), ConfigRequest
);
3960 goto NextConfigString
;
3965 // Check whether this ConfigRequest is search from Efi varstore type storage.
3967 Status
= GetVarStoreType(Database
, ConfigRequest
, &IsEfiVarStore
, &EfiVarStoreInfo
);
3968 if (EFI_ERROR (Status
)) {
3972 if (IsEfiVarStore
) {
3974 // Call the GetVariable function to extract settings.
3976 Status
= GetConfigRespFromEfiVarStore(This
, EfiVarStoreInfo
, ConfigRequest
, &AccessResults
, &AccessProgress
);
3977 FreePool (EfiVarStoreInfo
);
3980 // Call corresponding ConfigAccess protocol to extract settings
3982 Status
= gBS
->HandleProtocol (
3984 &gEfiHiiConfigAccessProtocolGuid
,
3985 (VOID
**) &ConfigAccess
3987 if (EFI_ERROR (Status
)) {
3991 Status
= ConfigAccess
->ExtractConfig (
3998 if (EFI_ERROR (Status
)) {
4000 // AccessProgress indicates the parsing progress on <ConfigRequest>.
4001 // Map it to the progress on <MultiConfigRequest> then return it.
4003 *Progress
= StrStr (StringPtr
, AccessProgress
);
4008 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'
4009 // which seperates the first <ConfigAltResp> and the following ones.
4011 ASSERT (*AccessProgress
== 0);
4014 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
4016 if (!IfrDataParsedFlag
&& HiiHandle
!= NULL
) {
4017 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &ConfigRequest
, &DefaultResults
, NULL
);
4018 ASSERT_EFI_ERROR (Status
);
4021 FreePool (DevicePath
);
4024 if (DefaultResults
!= NULL
) {
4025 Status
= MergeDefaultString (&AccessResults
, DefaultResults
);
4026 ASSERT_EFI_ERROR (Status
);
4027 FreePool (DefaultResults
);
4028 DefaultResults
= NULL
;
4032 if (!FirstElement
) {
4033 Status
= AppendToMultiString (Results
, L
"&");
4034 ASSERT_EFI_ERROR (Status
);
4037 Status
= AppendToMultiString (Results
, AccessResults
);
4038 ASSERT_EFI_ERROR (Status
);
4040 FirstElement
= FALSE
;
4042 FreePool (AccessResults
);
4043 AccessResults
= NULL
;
4044 FreePool (ConfigRequest
);
4045 ConfigRequest
= NULL
;
4048 // Go to next <ConfigRequest> (skip '&').
4050 StringPtr
+= Length
;
4051 if (*StringPtr
== 0) {
4052 *Progress
= StringPtr
;
4060 if (EFI_ERROR (Status
)) {
4061 FreePool (*Results
);
4065 if (ConfigRequest
!= NULL
) {
4066 FreePool (ConfigRequest
);
4069 if (AccessResults
!= NULL
) {
4070 FreePool (AccessResults
);
4073 if (DefaultResults
!= NULL
) {
4074 FreePool (DefaultResults
);
4077 if (DevicePath
!= NULL
) {
4078 FreePool (DevicePath
);
4086 This function allows the caller to request the current configuration for the
4087 entirety of the current HII database and returns the data in a
4088 null-terminated Unicode string.
4090 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
4092 @param Results Null-terminated Unicode string in
4093 <MultiConfigAltResp> format which has all values
4094 filled in for the entirety of the current HII
4095 database. String to be allocated by the called
4096 function. De-allocation is up to the caller.
4098 @retval EFI_SUCCESS The Results string is filled with the values
4099 corresponding to all requested names.
4100 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
4101 results that must be stored awaiting possible
4103 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Results
4104 parameter would result in this type of error.
4109 HiiConfigRoutingExportConfig (
4110 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
4111 OUT EFI_STRING
*Results
4115 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
4116 EFI_STRING AccessResults
;
4117 EFI_STRING Progress
;
4118 EFI_STRING StringPtr
;
4119 EFI_STRING ConfigRequest
;
4121 EFI_HANDLE
*ConfigAccessHandles
;
4122 UINTN NumberConfigAccessHandles
;
4123 BOOLEAN FirstElement
;
4124 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
4125 EFI_HII_HANDLE HiiHandle
;
4126 EFI_STRING DefaultResults
;
4127 HII_DATABASE_PRIVATE_DATA
*Private
;
4129 HII_DATABASE_RECORD
*Database
;
4130 UINT8
*DevicePathPkg
;
4131 UINT8
*CurrentDevicePath
;
4132 BOOLEAN IfrDataParsedFlag
;
4134 if (This
== NULL
|| Results
== NULL
) {
4135 return EFI_INVALID_PARAMETER
;
4138 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
4141 // Allocate a fix length of memory to store Results. Reallocate memory for
4142 // Results if this fix length is insufficient.
4144 *Results
= (EFI_STRING
) AllocateZeroPool (MAX_STRING_LENGTH
);
4145 if (*Results
== NULL
) {
4146 return EFI_OUT_OF_RESOURCES
;
4149 NumberConfigAccessHandles
= 0;
4150 Status
= gBS
->LocateHandleBuffer (
4152 &gEfiHiiConfigAccessProtocolGuid
,
4154 &NumberConfigAccessHandles
,
4155 &ConfigAccessHandles
4157 if (EFI_ERROR (Status
)) {
4161 FirstElement
= TRUE
;
4163 for (Index
= 0; Index
< NumberConfigAccessHandles
; Index
++) {
4164 Status
= gBS
->HandleProtocol (
4165 ConfigAccessHandles
[Index
],
4166 &gEfiHiiConfigAccessProtocolGuid
,
4167 (VOID
**) &ConfigAccess
4169 if (EFI_ERROR (Status
)) {
4174 // Get DevicePath and HiiHandle for this ConfigAccess driver handle
4176 IfrDataParsedFlag
= FALSE
;
4179 DefaultResults
= NULL
;
4181 ConfigRequest
= NULL
;
4182 DevicePath
= DevicePathFromHandle (ConfigAccessHandles
[Index
]);
4183 if (DevicePath
!= NULL
) {
4184 for (Link
= Private
->DatabaseList
.ForwardLink
;
4185 Link
!= &Private
->DatabaseList
;
4186 Link
= Link
->ForwardLink
4188 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
4189 if ((DevicePathPkg
= Database
->PackageList
->DevicePathPkg
) != NULL
) {
4190 CurrentDevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
4194 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) CurrentDevicePath
)
4196 HiiHandle
= Database
->Handle
;
4203 Status
= ConfigAccess
->ExtractConfig (
4209 if (EFI_ERROR (Status
)) {
4211 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
4213 if (HiiHandle
!= NULL
&& DevicePath
!= NULL
) {
4214 IfrDataParsedFlag
= TRUE
;
4215 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &ConfigRequest
, &DefaultResults
, NULL
);
4217 // Get the full request string to get the Current setting again.
4219 if (!EFI_ERROR (Status
) && ConfigRequest
!= NULL
) {
4220 Status
= ConfigAccess
->ExtractConfig (
4226 FreePool (ConfigRequest
);
4228 Status
= EFI_NOT_FOUND
;
4233 if (!EFI_ERROR (Status
)) {
4235 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
4237 if (!IfrDataParsedFlag
&& HiiHandle
!= NULL
&& DevicePath
!= NULL
) {
4238 StringPtr
= StrStr (AccessResults
, L
"&GUID=");
4239 if (StringPtr
!= NULL
) {
4242 if (GetElementsFromRequest (AccessResults
)) {
4243 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &AccessResults
, &DefaultResults
, NULL
);
4244 ASSERT_EFI_ERROR (Status
);
4246 if (StringPtr
!= NULL
) {
4251 // Merge the default sting from IFR code into the got setting from driver.
4253 if (DefaultResults
!= NULL
) {
4254 Status
= MergeDefaultString (&AccessResults
, DefaultResults
);
4255 ASSERT_EFI_ERROR (Status
);
4256 FreePool (DefaultResults
);
4257 DefaultResults
= NULL
;
4261 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'
4262 // which seperates the first <ConfigAltResp> and the following ones.
4264 if (!FirstElement
) {
4265 Status
= AppendToMultiString (Results
, L
"&");
4266 ASSERT_EFI_ERROR (Status
);
4269 Status
= AppendToMultiString (Results
, AccessResults
);
4270 ASSERT_EFI_ERROR (Status
);
4272 FirstElement
= FALSE
;
4274 FreePool (AccessResults
);
4275 AccessResults
= NULL
;
4278 FreePool (ConfigAccessHandles
);
4285 This function processes the results of processing forms and routes it to the
4286 appropriate handlers or storage.
4288 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
4290 @param Configuration A null-terminated Unicode string in
4291 <MulltiConfigResp> format.
4292 @param Progress A pointer to a string filled in with the offset of
4293 the most recent & before the first failing name /
4294 value pair (or the beginning of the string if the
4295 failure is in the first name / value pair) or the
4296 terminating NULL if all was successful.
4298 @retval EFI_SUCCESS The results have been distributed or are awaiting
4300 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
4301 results that must be stored awaiting possible
4303 @retval EFI_INVALID_PARAMETER Passing in a NULL for the Configuration parameter
4304 would result in this type of error.
4305 @retval EFI_NOT_FOUND Target for the specified routing data was not
4311 HiiConfigRoutingRouteConfig (
4312 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
4313 IN CONST EFI_STRING Configuration
,
4314 OUT EFI_STRING
*Progress
4317 HII_DATABASE_PRIVATE_DATA
*Private
;
4318 EFI_STRING StringPtr
;
4319 EFI_STRING ConfigResp
;
4322 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
4323 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
4325 HII_DATABASE_RECORD
*Database
;
4326 UINT8
*DevicePathPkg
;
4327 UINT8
*CurrentDevicePath
;
4328 EFI_HANDLE DriverHandle
;
4329 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
4330 EFI_STRING AccessProgress
;
4331 EFI_IFR_VARSTORE_EFI
*EfiVarStoreInfo
;
4332 BOOLEAN IsEfiVarstore
;
4333 UINTN DevicePathSize
;
4335 if (This
== NULL
|| Progress
== NULL
) {
4336 return EFI_INVALID_PARAMETER
;
4339 if (Configuration
== NULL
) {
4341 return EFI_INVALID_PARAMETER
;
4344 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
4345 StringPtr
= Configuration
;
4346 *Progress
= StringPtr
;
4348 AccessProgress
= NULL
;
4349 EfiVarStoreInfo
= NULL
;
4350 IsEfiVarstore
= FALSE
;
4353 // The first element of <MultiConfigResp> should be
4354 // <GuidHdr>, which is in 'GUID='<Guid> syntax.
4356 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
4357 return EFI_INVALID_PARAMETER
;
4360 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) == 0) {
4362 // If parsing error, set Progress to the beginning of the <MultiConfigResp>
4363 // or most recent & before the error.
4365 if (StringPtr
== Configuration
) {
4366 *Progress
= StringPtr
;
4368 *Progress
= StringPtr
- 1;
4372 // Process each <ConfigResp> of <MultiConfigResp>
4374 Length
= CalculateConfigStringLen (StringPtr
);
4375 ConfigResp
= AllocateCopyPool ((Length
+ 1) * sizeof (CHAR16
), StringPtr
);
4376 if (ConfigResp
== NULL
) {
4377 return EFI_OUT_OF_RESOURCES
;
4380 // Append '\0' to the end of ConfigRequest
4382 *(ConfigResp
+ Length
) = 0;
4385 // Get the UEFI device path
4387 Status
= GetDevicePath (ConfigResp
, (UINT8
**) &DevicePath
);
4388 if (EFI_ERROR (Status
)) {
4389 FreePool (ConfigResp
);
4394 // Find driver which matches the routing data.
4396 DriverHandle
= NULL
;
4397 for (Link
= Private
->DatabaseList
.ForwardLink
;
4398 Link
!= &Private
->DatabaseList
;
4399 Link
= Link
->ForwardLink
4401 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
4403 if ((DevicePathPkg
= Database
->PackageList
->DevicePathPkg
) != NULL
) {
4404 CurrentDevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
4405 DevicePathSize
= GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) CurrentDevicePath
);
4406 if ((CompareMem (DevicePath
,CurrentDevicePath
,DevicePathSize
) == 0) && IsThisPackageList(Database
, ConfigResp
)) {
4407 DriverHandle
= Database
->DriverHandle
;
4414 // Try to find driver handle by device path.
4416 if (DriverHandle
== NULL
) {
4417 TempDevicePath
= DevicePath
;
4418 Status
= gBS
->LocateDevicePath (
4419 &gEfiDevicePathProtocolGuid
,
4423 if (EFI_ERROR (Status
) || (DriverHandle
== NULL
)) {
4425 // Routing data does not match any known driver.
4426 // Set Progress to the 'G' in "GUID" of the routing header.
4428 FreePool (DevicePath
);
4429 *Progress
= StringPtr
;
4430 FreePool (ConfigResp
);
4431 return EFI_NOT_FOUND
;
4435 FreePool (DevicePath
);
4438 // Check whether this ConfigRequest is search from Efi varstore type storage.
4440 Status
= GetVarStoreType(Database
, ConfigResp
, &IsEfiVarstore
, &EfiVarStoreInfo
);
4441 if (EFI_ERROR (Status
)) {
4445 if (IsEfiVarstore
) {
4447 // Call the SetVariable function to route settings.
4449 Status
= RouteConfigRespForEfiVarStore(This
, EfiVarStoreInfo
, ConfigResp
, &AccessProgress
);
4450 FreePool (EfiVarStoreInfo
);
4453 // Call corresponding ConfigAccess protocol to route settings
4455 Status
= gBS
->HandleProtocol (
4457 &gEfiHiiConfigAccessProtocolGuid
,
4458 (VOID
**) &ConfigAccess
4460 if (EFI_ERROR (Status
)) {
4461 *Progress
= StringPtr
;
4462 FreePool (ConfigResp
);
4463 return EFI_NOT_FOUND
;
4466 Status
= ConfigAccess
->RouteConfig (
4472 if (EFI_ERROR (Status
)) {
4473 ASSERT (AccessProgress
!= NULL
);
4475 // AccessProgress indicates the parsing progress on <ConfigResp>.
4476 // Map it to the progress on <MultiConfigResp> then return it.
4478 *Progress
= StrStr (StringPtr
, AccessProgress
);
4480 FreePool (ConfigResp
);
4484 FreePool (ConfigResp
);
4488 // Go to next <ConfigResp> (skip '&').
4490 StringPtr
+= Length
;
4491 if (*StringPtr
== 0) {
4492 *Progress
= StringPtr
;
4505 This helper function is to be called by drivers to map configuration data
4506 stored in byte array ("block") formats such as UEFI Variables into current
4507 configuration strings.
4509 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
4511 @param ConfigRequest A null-terminated Unicode string in
4512 <ConfigRequest> format.
4513 @param Block Array of bytes defining the block's configuration.
4514 @param BlockSize Length in bytes of Block.
4515 @param Config Filled-in configuration string. String allocated
4516 by the function. Returned only if call is
4517 successful. It is <ConfigResp> string format.
4518 @param Progress A pointer to a string filled in with the offset of
4519 the most recent & before the first failing
4520 name/value pair (or the beginning of the string if
4521 the failure is in the first name / value pair) or
4522 the terminating NULL if all was successful.
4524 @retval EFI_SUCCESS The request succeeded. Progress points to the null
4525 terminator at the end of the ConfigRequest
4527 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress
4528 points to the first character of ConfigRequest.
4529 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigRequest or
4530 Block parameter would result in this type of
4531 error. Progress points to the first character of
4533 @retval EFI_DEVICE_ERROR Block not large enough. Progress undefined.
4534 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted string.
4535 Block is left updated and Progress points at
4536 the "&" preceding the first non-<BlockName>.
4542 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
4543 IN CONST EFI_STRING ConfigRequest
,
4544 IN CONST UINT8
*Block
,
4545 IN CONST UINTN BlockSize
,
4546 OUT EFI_STRING
*Config
,
4547 OUT EFI_STRING
*Progress
4550 HII_DATABASE_PRIVATE_DATA
*Private
;
4551 EFI_STRING StringPtr
;
4559 EFI_STRING ValueStr
;
4560 EFI_STRING ConfigElement
;
4568 if (This
== NULL
|| Progress
== NULL
|| Config
== NULL
) {
4569 return EFI_INVALID_PARAMETER
;
4572 if (Block
== NULL
|| ConfigRequest
== NULL
) {
4573 *Progress
= ConfigRequest
;
4574 return EFI_INVALID_PARAMETER
;
4578 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
4579 ASSERT (Private
!= NULL
);
4581 StringPtr
= ConfigRequest
;
4584 ConfigElement
= NULL
;
4587 // Allocate a fix length of memory to store Results. Reallocate memory for
4588 // Results if this fix length is insufficient.
4590 *Config
= (EFI_STRING
) AllocateZeroPool (MAX_STRING_LENGTH
);
4591 if (*Config
== NULL
) {
4592 return EFI_OUT_OF_RESOURCES
;
4598 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
4599 *Progress
= StringPtr
;
4600 Status
= EFI_INVALID_PARAMETER
;
4603 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"PATH=", StrLen (L
"PATH=")) != 0) {
4606 if (*StringPtr
== 0) {
4607 *Progress
= StringPtr
- 1;
4608 Status
= EFI_INVALID_PARAMETER
;
4612 while (*StringPtr
!= L
'&' && *StringPtr
!= 0) {
4615 if (*StringPtr
== 0) {
4616 *Progress
= StringPtr
;
4618 AppendToMultiString(Config
, ConfigRequest
);
4619 HiiToLower (*Config
);
4629 // Copy <ConfigHdr> and an additional '&' to <ConfigResp>
4631 TemChar
= *StringPtr
;
4633 AppendToMultiString(Config
, ConfigRequest
);
4634 *StringPtr
= TemChar
;
4637 // Parse each <RequestElement> if exists
4638 // Only <BlockName> format is supported by this help function.
4639 // <BlockName> ::= 'OFFSET='<Number>&'WIDTH='<Number>
4641 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"OFFSET=", StrLen (L
"OFFSET=")) == 0) {
4643 // Back up the header of one <BlockName>
4647 StringPtr
+= StrLen (L
"OFFSET=");
4651 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
4652 if (EFI_ERROR (Status
)) {
4653 *Progress
= TmpPtr
- 1;
4660 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
4662 FreePool (TmpBuffer
);
4664 StringPtr
+= Length
;
4665 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
4666 *Progress
= TmpPtr
- 1;
4667 Status
= EFI_INVALID_PARAMETER
;
4670 StringPtr
+= StrLen (L
"&WIDTH=");
4675 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
4676 if (EFI_ERROR (Status
)) {
4677 *Progress
= TmpPtr
- 1;
4684 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
4686 FreePool (TmpBuffer
);
4688 StringPtr
+= Length
;
4689 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
4690 *Progress
= TmpPtr
- 1;
4691 Status
= EFI_INVALID_PARAMETER
;
4696 // Calculate Value and convert it to hex string.
4698 if (Offset
+ Width
> BlockSize
) {
4699 *Progress
= StringPtr
;
4700 Status
= EFI_DEVICE_ERROR
;
4704 Value
= (UINT8
*) AllocateZeroPool (Width
);
4705 if (Value
== NULL
) {
4706 *Progress
= ConfigRequest
;
4707 Status
= EFI_OUT_OF_RESOURCES
;
4711 CopyMem (Value
, (UINT8
*) Block
+ Offset
, Width
);
4713 Length
= Width
* 2 + 1;
4714 ValueStr
= (EFI_STRING
) AllocateZeroPool (Length
* sizeof (CHAR16
));
4715 if (ValueStr
== NULL
) {
4716 *Progress
= ConfigRequest
;
4717 Status
= EFI_OUT_OF_RESOURCES
;
4721 TemString
= ValueStr
;
4722 TemBuffer
= Value
+ Width
- 1;
4723 for (Index
= 0; Index
< Width
; Index
++, TemBuffer
--) {
4724 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
4731 // Build a ConfigElement
4733 Length
+= StringPtr
- TmpPtr
+ 1 + StrLen (L
"VALUE=");
4734 ConfigElement
= (EFI_STRING
) AllocateZeroPool (Length
* sizeof (CHAR16
));
4735 if (ConfigElement
== NULL
) {
4736 Status
= EFI_OUT_OF_RESOURCES
;
4739 CopyMem (ConfigElement
, TmpPtr
, (StringPtr
- TmpPtr
+ 1) * sizeof (CHAR16
));
4740 if (*StringPtr
== 0) {
4741 *(ConfigElement
+ (StringPtr
- TmpPtr
)) = L
'&';
4743 *(ConfigElement
+ (StringPtr
- TmpPtr
) + 1) = 0;
4744 StrCatS (ConfigElement
, Length
, L
"VALUE=");
4745 StrCatS (ConfigElement
, Length
, ValueStr
);
4747 AppendToMultiString (Config
, ConfigElement
);
4749 FreePool (ConfigElement
);
4750 FreePool (ValueStr
);
4751 ConfigElement
= NULL
;
4755 // If '\0', parsing is finished. Otherwise skip '&' to continue
4757 if (*StringPtr
== 0) {
4760 AppendToMultiString (Config
, L
"&");
4765 if (*StringPtr
!= 0) {
4766 *Progress
= StringPtr
- 1;
4767 Status
= EFI_INVALID_PARAMETER
;
4771 HiiToLower (*Config
);
4772 *Progress
= StringPtr
;
4776 if (*Config
!= NULL
) {
4780 if (ValueStr
!= NULL
) {
4781 FreePool (ValueStr
);
4783 if (Value
!= NULL
) {
4786 if (ConfigElement
!= NULL
) {
4787 FreePool (ConfigElement
);
4796 This helper function is to be called by drivers to map configuration strings
4797 to configurations stored in byte array ("block") formats such as UEFI Variables.
4799 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
4801 @param ConfigResp A null-terminated Unicode string in <ConfigResp>
4803 @param Block A possibly null array of bytes representing the
4804 current block. Only bytes referenced in the
4805 ConfigResp string in the block are modified. If
4806 this parameter is null or if the *BlockSize
4807 parameter is (on input) shorter than required by
4808 the Configuration string, only the BlockSize
4809 parameter is updated and an appropriate status
4810 (see below) is returned.
4811 @param BlockSize The length of the Block in units of UINT8. On
4812 input, this is the size of the Block. On output,
4813 if successful, contains the largest index of the
4814 modified byte in the Block, or the required buffer
4815 size if the Block is not large enough.
4816 @param Progress On return, points to an element of the ConfigResp
4817 string filled in with the offset of the most
4818 recent '&' before the first failing name / value
4819 pair (or the beginning of the string if the
4820 failure is in the first name / value pair) or the
4821 terminating NULL if all was successful.
4823 @retval EFI_SUCCESS The request succeeded. Progress points to the null
4824 terminator at the end of the ConfigResp string.
4825 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress
4826 points to the first character of ConfigResp.
4827 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigResp or
4828 Block parameter would result in this type of
4829 error. Progress points to the first character of
4831 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted name /
4832 value pair. Block is left updated and
4833 Progress points at the '&' preceding the first
4835 @retval EFI_BUFFER_TOO_SMALL Block not large enough. Progress undefined.
4836 BlockSize is updated with the required buffer size.
4837 @retval EFI_NOT_FOUND Target for the specified routing data was not found.
4838 Progress points to the "G" in "GUID" of the errant
4845 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
4846 IN CONST EFI_STRING ConfigResp
,
4847 IN OUT UINT8
*Block
,
4848 IN OUT UINTN
*BlockSize
,
4849 OUT EFI_STRING
*Progress
4852 HII_DATABASE_PRIVATE_DATA
*Private
;
4853 EFI_STRING StringPtr
;
4866 if (This
== NULL
|| BlockSize
== NULL
|| Progress
== NULL
) {
4867 return EFI_INVALID_PARAMETER
;
4870 *Progress
= ConfigResp
;
4871 if (ConfigResp
== NULL
) {
4872 return EFI_INVALID_PARAMETER
;
4875 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
4876 ASSERT (Private
!= NULL
);
4878 StringPtr
= ConfigResp
;
4879 BufferSize
= *BlockSize
;
4886 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
4887 *Progress
= StringPtr
;
4888 Status
= EFI_INVALID_PARAMETER
;
4891 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"PATH=", StrLen (L
"PATH=")) != 0) {
4894 if (*StringPtr
== 0) {
4895 *Progress
= StringPtr
;
4896 Status
= EFI_INVALID_PARAMETER
;
4900 while (*StringPtr
!= L
'&' && *StringPtr
!= 0) {
4903 if (*StringPtr
== 0) {
4904 *Progress
= StringPtr
;
4905 Status
= EFI_INVALID_PARAMETER
;
4910 // Parse each <ConfigElement> if exists
4911 // Only '&'<BlockConfig> format is supported by this help function.
4912 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE='<Number>
4914 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) == 0) {
4916 StringPtr
+= StrLen (L
"&OFFSET=");
4920 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
4921 if (EFI_ERROR (Status
)) {
4929 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
4931 FreePool (TmpBuffer
);
4933 StringPtr
+= Length
;
4934 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
4936 Status
= EFI_INVALID_PARAMETER
;
4939 StringPtr
+= StrLen (L
"&WIDTH=");
4944 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
4945 if (EFI_ERROR (Status
)) {
4953 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
4955 FreePool (TmpBuffer
);
4957 StringPtr
+= Length
;
4958 if (StrnCmp (StringPtr
, L
"&VALUE=", StrLen (L
"&VALUE=")) != 0) {
4960 Status
= EFI_INVALID_PARAMETER
;
4963 StringPtr
+= StrLen (L
"&VALUE=");
4968 Status
= GetValueOfNumber (StringPtr
, &Value
, &Length
);
4969 if (EFI_ERROR (Status
)) {
4974 StringPtr
+= Length
;
4975 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
4977 Status
= EFI_INVALID_PARAMETER
;
4982 // Update the Block with configuration info
4984 if ((Block
!= NULL
) && (Offset
+ Width
<= BufferSize
)) {
4985 CopyMem (Block
+ Offset
, Value
, Width
);
4987 if (Offset
+ Width
> MaxBlockSize
) {
4988 MaxBlockSize
= Offset
+ Width
;
4995 // If '\0', parsing is finished.
4997 if (*StringPtr
== 0) {
5003 // The input string is not ConfigResp format, return error.
5005 if (*StringPtr
!= 0) {
5006 *Progress
= StringPtr
;
5007 Status
= EFI_INVALID_PARAMETER
;
5011 *Progress
= StringPtr
+ StrLen (StringPtr
);
5012 *BlockSize
= MaxBlockSize
- 1;
5014 if (MaxBlockSize
> BufferSize
) {
5015 *BlockSize
= MaxBlockSize
;
5016 if (Block
!= NULL
) {
5017 return EFI_BUFFER_TOO_SMALL
;
5021 if (Block
== NULL
) {
5022 *Progress
= ConfigResp
;
5023 return EFI_INVALID_PARAMETER
;
5030 if (Value
!= NULL
) {
5038 This helper function is to be called by drivers to extract portions of
5039 a larger configuration string.
5041 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
5043 @param Configuration A null-terminated Unicode string in
5044 <MultiConfigAltResp> format.
5045 @param Guid A pointer to the GUID value to search for in the
5046 routing portion of the ConfigResp string when
5047 retrieving the requested data. If Guid is NULL,
5048 then all GUID values will be searched for.
5049 @param Name A pointer to the NAME value to search for in the
5050 routing portion of the ConfigResp string when
5051 retrieving the requested data. If Name is NULL,
5052 then all Name values will be searched for.
5053 @param DevicePath A pointer to the PATH value to search for in the
5054 routing portion of the ConfigResp string when
5055 retrieving the requested data. If DevicePath is
5056 NULL, then all DevicePath values will be searched
5058 @param AltCfgId A pointer to the ALTCFG value to search for in the
5059 routing portion of the ConfigResp string when
5060 retrieving the requested data. If this parameter
5061 is NULL, then the current setting will be
5063 @param AltCfgResp A pointer to a buffer which will be allocated by
5064 the function which contains the retrieved string
5065 as requested. This buffer is only allocated if
5066 the call was successful. It is <ConfigResp> format.
5068 @retval EFI_SUCCESS The request succeeded. The requested data was
5069 extracted and placed in the newly allocated
5071 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate AltCfgResp.
5072 @retval EFI_INVALID_PARAMETER Any parameter is invalid.
5073 @retval EFI_NOT_FOUND Target for the specified routing data was not
5080 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
5081 IN CONST EFI_STRING Configuration
,
5082 IN CONST EFI_GUID
*Guid
,
5083 IN CONST EFI_STRING Name
,
5084 IN CONST EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
5085 IN CONST UINT16
*AltCfgId
,
5086 OUT EFI_STRING
*AltCfgResp
5090 EFI_STRING StringPtr
;
5091 EFI_STRING HdrStart
;
5098 EFI_STRING AltIdStr
;
5115 if (This
== NULL
|| Configuration
== NULL
|| AltCfgResp
== NULL
) {
5116 return EFI_INVALID_PARAMETER
;
5119 StringPtr
= Configuration
;
5120 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
5121 return EFI_INVALID_PARAMETER
;
5125 // Generate the sub string for later matching.
5127 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*) Guid
, 1, &GuidStr
);
5130 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) DevicePath
),
5131 (VOID
*) DevicePath
,
5135 if (AltCfgId
!= NULL
) {
5136 GenerateSubStr (L
"ALTCFG=", sizeof (UINT16
), (VOID
*) AltCfgId
, 3, &AltIdStr
);
5139 GenerateSubStr (L
"NAME=", StrLen (Name
) * sizeof (CHAR16
), (VOID
*) Name
, 2, &NameStr
);
5141 GenerateSubStr (L
"NAME=", 0, NULL
, 2, &NameStr
);
5144 while (*StringPtr
!= 0) {
5146 // Try to match the GUID
5149 TmpPtr
= StrStr (StringPtr
, GuidStr
);
5150 if (TmpPtr
== NULL
) {
5151 Status
= EFI_NOT_FOUND
;
5157 // Jump to <NameHdr>
5160 StringPtr
= TmpPtr
+ StrLen (GuidStr
);
5162 StringPtr
= StrStr (TmpPtr
, L
"NAME=");
5163 if (StringPtr
== NULL
) {
5164 Status
= EFI_NOT_FOUND
;
5172 // Try to match the NAME
5174 if (GuidFlag
&& !NameFlag
) {
5175 if (StrnCmp (StringPtr
, NameStr
, StrLen (NameStr
)) != 0) {
5179 // Jump to <PathHdr>
5182 StringPtr
+= StrLen (NameStr
);
5184 StringPtr
= StrStr (StringPtr
, L
"PATH=");
5185 if (StringPtr
== NULL
) {
5186 Status
= EFI_NOT_FOUND
;
5195 // Try to match the DevicePath
5197 if (GuidFlag
&& NameFlag
&& !PathFlag
) {
5198 if (StrnCmp (StringPtr
, PathStr
, StrLen (PathStr
)) != 0) {
5203 // Jump to '&' before <DescHdr> or <ConfigBody>
5205 if (DevicePath
!= NULL
) {
5206 StringPtr
+= StrLen (PathStr
);
5208 StringPtr
= StrStr (StringPtr
, L
"&");
5209 if (StringPtr
== NULL
) {
5210 Status
= EFI_NOT_FOUND
;
5221 // Try to match the AltCfgId
5223 if (GuidFlag
&& NameFlag
&& PathFlag
) {
5224 if (AltCfgId
== NULL
) {
5226 // Return Current Setting when AltCfgId is NULL.
5228 Status
= OutputConfigBody (StringPtr
, &Result
);
5232 // Search the <ConfigAltResp> to get the <AltResp> with AltCfgId.
5234 if (StrnCmp (StringPtr
, AltIdStr
, StrLen (AltIdStr
)) != 0) {
5240 // Skip AltIdStr and &
5242 StringPtr
= StringPtr
+ StrLen (AltIdStr
);
5243 Status
= OutputConfigBody (StringPtr
, &Result
);
5249 Status
= EFI_NOT_FOUND
;
5253 if (!EFI_ERROR (Status
) && (Result
!= NULL
)) {
5255 // Copy the <ConfigHdr> and <ConfigBody>
5257 Length
= HdrEnd
- HdrStart
+ StrLen (Result
) + 1;
5258 *AltCfgResp
= AllocateZeroPool (Length
* sizeof (CHAR16
));
5259 if (*AltCfgResp
== NULL
) {
5260 Status
= EFI_OUT_OF_RESOURCES
;
5262 StrnCpyS (*AltCfgResp
, Length
, HdrStart
, HdrEnd
- HdrStart
);
5263 StrCatS (*AltCfgResp
, Length
, Result
);
5264 Status
= EFI_SUCCESS
;
5268 if (GuidStr
!= NULL
) {
5271 if (NameStr
!= NULL
) {
5274 if (PathStr
!= NULL
) {
5277 if (AltIdStr
!= NULL
) {
5278 FreePool (AltIdStr
);
5280 if (Result
!= NULL
) {