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 if (StringPtrEnd
== NULL
) {
605 // No more default string is found.
607 TotalSize
= SizeAltCfgResp
+ StrSize (StringPtrDefault
);
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 TotalSize
= SizeAltCfgResp
+ StrSize (StringPtrDefault
);
623 *AltCfgResp
= (EFI_STRING
) ReallocatePool (
626 (VOID
*) (*AltCfgResp
)
628 if (*AltCfgResp
== NULL
) {
629 FreePool (AltConfigHdr
);
630 return EFI_OUT_OF_RESOURCES
;
632 StrCatS (*AltCfgResp
, TotalSize
/ sizeof (CHAR16
), StringPtrDefault
);
633 *StringPtrEnd
= TempChar
;
638 // Find next AltCfg String
640 *(AltConfigHdr
+ HeaderLength
) = L
'\0';
641 StringPtrDefault
= StrStr (StringPtrDefault
+ 1, AltConfigHdr
);
644 FreePool (AltConfigHdr
);
649 This function inserts new DefaultValueData into the BlockData DefaultValue array.
651 @param BlockData The BlockData is updated to add new default value.
652 @param DefaultValueData The DefaultValue is added.
657 IN IFR_BLOCK_DATA
*BlockData
,
658 IN IFR_DEFAULT_DATA
*DefaultValueData
662 IFR_DEFAULT_DATA
*DefaultValueArray
;
663 LIST_ENTRY
*DefaultLink
;
665 DefaultLink
= &BlockData
->DefaultValueEntry
;
667 for (Link
= DefaultLink
->ForwardLink
; Link
!= DefaultLink
; Link
= Link
->ForwardLink
) {
668 DefaultValueArray
= BASE_CR (Link
, IFR_DEFAULT_DATA
, Entry
);
669 if (DefaultValueArray
->DefaultId
== DefaultValueData
->DefaultId
) {
671 // DEFAULT_VALUE_FROM_OPCODE has high priority, DEFAULT_VALUE_FROM_DEFAULT has low priority.
673 if (DefaultValueData
->Type
> DefaultValueArray
->Type
) {
675 // Update the default value array in BlockData.
677 CopyMem (&DefaultValueArray
->Value
, &DefaultValueData
->Value
, sizeof (EFI_IFR_TYPE_VALUE
));
678 DefaultValueArray
->Type
= DefaultValueData
->Type
;
679 DefaultValueArray
->Cleaned
= DefaultValueData
->Cleaned
;
686 // Insert new default value data in tail.
688 DefaultValueArray
= AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
689 ASSERT (DefaultValueArray
!= NULL
);
690 CopyMem (DefaultValueArray
, DefaultValueData
, sizeof (IFR_DEFAULT_DATA
));
691 InsertTailList (Link
, &DefaultValueArray
->Entry
);
695 This function inserts new BlockData into the block link
697 @param BlockLink The list entry points to block array.
698 @param BlockData The point to BlockData is added.
703 IN LIST_ENTRY
*BlockLink
,
704 IN IFR_BLOCK_DATA
**BlockData
708 IFR_BLOCK_DATA
*BlockArray
;
709 IFR_BLOCK_DATA
*BlockSingleData
;
711 BlockSingleData
= *BlockData
;
713 if (BlockSingleData
->Name
!= NULL
) {
714 InsertTailList (BlockLink
, &BlockSingleData
->Entry
);
719 // Insert block data in its Offset and Width order.
721 for (Link
= BlockLink
->ForwardLink
; Link
!= BlockLink
; Link
= Link
->ForwardLink
) {
722 BlockArray
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
723 if (BlockArray
->Offset
== BlockSingleData
->Offset
) {
724 if (BlockArray
->Width
> BlockSingleData
->Width
) {
726 // Insert this block data in the front of block array
728 InsertTailList (Link
, &BlockSingleData
->Entry
);
732 if (BlockArray
->Width
== BlockSingleData
->Width
) {
734 // The same block array has been added.
736 if (BlockSingleData
!= BlockArray
) {
737 FreePool (BlockSingleData
);
738 *BlockData
= BlockArray
;
742 } else if (BlockArray
->Offset
> BlockSingleData
->Offset
) {
744 // Insert new block data in the front of block array
746 InsertTailList (Link
, &BlockSingleData
->Entry
);
752 // Add new block data into the tail.
754 InsertTailList (Link
, &BlockSingleData
->Entry
);
758 Retrieves a pointer to the a Null-terminated ASCII string containing the list
759 of languages that an HII handle in the HII Database supports. The returned
760 string is allocated using AllocatePool(). The caller is responsible for freeing
761 the returned string using FreePool(). The format of the returned string follows
762 the language format assumed the HII Database.
764 If HiiHandle is NULL, then ASSERT().
766 @param[in] HiiHandle A handle that was previously registered in the HII Database.
768 @retval NULL HiiHandle is not registered in the HII database
769 @retval NULL There are not enough resources available to retrieve the suported
771 @retval NULL The list of suported languages could not be retrieved.
772 @retval Other A pointer to the Null-terminated ASCII string of supported languages.
776 GetSupportedLanguages (
777 IN EFI_HII_HANDLE HiiHandle
782 CHAR8 TempSupportedLanguages
;
783 CHAR8
*SupportedLanguages
;
785 ASSERT (HiiHandle
!= NULL
);
788 // Retrieve the size required for the supported languages buffer.
791 Status
= mPrivate
.HiiString
.GetLanguages (&mPrivate
.HiiString
, HiiHandle
, &TempSupportedLanguages
, &LanguageSize
);
794 // If GetLanguages() returns EFI_SUCCESS for a zero size,
795 // then there are no supported languages registered for HiiHandle. If GetLanguages()
796 // returns an error other than EFI_BUFFER_TOO_SMALL, then HiiHandle is not present
797 // in the HII Database
799 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
801 // Return NULL if the size can not be retrieved, or if HiiHandle is not in the HII Database
807 // Allocate the supported languages buffer.
809 SupportedLanguages
= AllocateZeroPool (LanguageSize
);
810 if (SupportedLanguages
== NULL
) {
812 // Return NULL if allocation fails.
818 // Retrieve the supported languages string
820 Status
= mPrivate
.HiiString
.GetLanguages (&mPrivate
.HiiString
, HiiHandle
, SupportedLanguages
, &LanguageSize
);
821 if (EFI_ERROR (Status
)) {
823 // Free the buffer and return NULL if the supported languages can not be retrieved.
825 FreePool (SupportedLanguages
);
830 // Return the Null-terminated ASCII string of supported languages
832 return SupportedLanguages
;
836 Retrieves a string from a string package.
838 If HiiHandle is NULL, then ASSERT().
839 If StringId is 0, then ASSET.
841 @param[in] HiiHandle A handle that was previously registered in the HII Database.
842 @param[in] StringId The identifier of the string to retrieved from the string
843 package associated with HiiHandle.
845 @retval NULL The string specified by StringId is not present in the string package.
846 @retval Other The string was returned.
851 IN EFI_HII_HANDLE HiiHandle
,
852 IN EFI_STRING_ID StringId
859 CHAR8
*SupportedLanguages
;
860 CHAR8
*PlatformLanguage
;
864 ASSERT (HiiHandle
!= NULL
);
865 ASSERT (StringId
!= 0);
868 // Initialize all allocated buffers to NULL
870 SupportedLanguages
= NULL
;
871 PlatformLanguage
= NULL
;
877 // Get the languages that the package specified by HiiHandle supports
879 SupportedLanguages
= GetSupportedLanguages (HiiHandle
);
880 if (SupportedLanguages
== NULL
) {
885 // Get the current platform language setting
887 GetEfiGlobalVariable2 (L
"PlatformLang", (VOID
**)&PlatformLanguage
, NULL
);
890 // Get the best matching language from SupportedLanguages
892 BestLanguage
= GetBestLanguage (
894 FALSE
, // RFC 4646 mode
895 Language
, // Highest priority
896 PlatformLanguage
!= NULL
? PlatformLanguage
: "", // Next highest priority
897 SupportedLanguages
, // Lowest priority
900 if (BestLanguage
== NULL
) {
905 // Retrieve the size of the string in the string package for the BestLanguage
908 Status
= mPrivate
.HiiString
.GetString (
918 // If GetString() returns EFI_SUCCESS for a zero size,
919 // then there are no supported languages registered for HiiHandle. If GetString()
920 // returns an error other than EFI_BUFFER_TOO_SMALL, then HiiHandle is not present
921 // in the HII Database
923 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
928 // Allocate a buffer for the return string
930 String
= AllocateZeroPool (StringSize
);
931 if (String
== NULL
) {
936 // Retrieve the string from the string package
938 Status
= mPrivate
.HiiString
.GetString (
947 if (EFI_ERROR (Status
)) {
949 // Free the buffer and return NULL if the supported languages can not be retrieved.
957 // Free allocated buffers
959 if (SupportedLanguages
!= NULL
) {
960 FreePool (SupportedLanguages
);
962 if (PlatformLanguage
!= NULL
) {
963 FreePool (PlatformLanguage
);
965 if (BestLanguage
!= NULL
) {
966 FreePool (BestLanguage
);
970 // Return the Null-terminated Unicode string
976 This function checks VarOffset and VarWidth is in the block range.
978 @param RequestBlockArray The block array is to be checked.
979 @param VarOffset Offset of var to the structure
980 @param VarWidth Width of var.
981 @param IsNameValueType Whether this varstore is name/value varstore or not.
982 @param HiiHandle Hii handle for this hii package.
984 @retval TRUE This Var is in the block range.
985 @retval FALSE This Var is not in the block range.
989 IN IFR_BLOCK_DATA
*RequestBlockArray
,
992 IN BOOLEAN IsNameValueType
,
993 IN EFI_HII_HANDLE HiiHandle
997 IFR_BLOCK_DATA
*BlockData
;
1001 // No Request Block array, all vars are got.
1003 if (RequestBlockArray
== NULL
) {
1008 // Check the input var is in the request block range.
1010 for (Link
= RequestBlockArray
->Entry
.ForwardLink
; Link
!= &RequestBlockArray
->Entry
; Link
= Link
->ForwardLink
) {
1011 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
1013 if (IsNameValueType
) {
1014 Name
= InternalGetString (HiiHandle
, VarOffset
);
1015 ASSERT (Name
!= NULL
);
1017 if (StrnCmp (BlockData
->Name
, Name
, StrLen (Name
)) == 0) {
1023 if ((VarOffset
>= BlockData
->Offset
) && ((VarOffset
+ VarWidth
) <= (BlockData
->Offset
+ BlockData
->Width
))) {
1033 Get form package data from data base.
1035 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
1036 @param HiiFormPackage The buffer saves the package data.
1037 @param PackageSize The buffer size of the package data.
1041 GetFormPackageData (
1042 IN HII_DATABASE_RECORD
*DataBaseRecord
,
1043 IN OUT UINT8
**HiiFormPackage
,
1044 OUT UINTN
*PackageSize
1051 if (DataBaseRecord
== NULL
|| HiiFormPackage
== NULL
|| PackageSize
== NULL
) {
1052 return EFI_INVALID_PARAMETER
;
1058 // 0. Get Hii Form Package by HiiHandle
1060 Status
= ExportFormPackages (
1062 DataBaseRecord
->Handle
,
1063 DataBaseRecord
->PackageList
,
1069 if (EFI_ERROR (Status
)) {
1073 (*HiiFormPackage
) = AllocatePool (ResultSize
);
1074 if (*HiiFormPackage
== NULL
) {
1075 Status
= EFI_OUT_OF_RESOURCES
;
1080 // Get HiiFormPackage by HiiHandle
1084 Status
= ExportFormPackages (
1086 DataBaseRecord
->Handle
,
1087 DataBaseRecord
->PackageList
,
1093 if (EFI_ERROR (Status
)) {
1094 FreePool (*HiiFormPackage
);
1097 *PackageSize
= Size
;
1104 This function parses Form Package to get the efi varstore info according to the request ConfigHdr.
1106 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
1107 @param ConfigHdr Request string ConfigHdr. If it is NULL,
1108 the first found varstore will be as ConfigHdr.
1109 @param IsEfiVarstore Whether the request storage type is efi varstore type.
1110 @param EfiVarStore The efi varstore info which will return.
1114 IN HII_DATABASE_RECORD
*DataBaseRecord
,
1115 IN EFI_STRING ConfigHdr
,
1116 OUT BOOLEAN
*IsEfiVarstore
,
1117 OUT EFI_IFR_VARSTORE_EFI
**EfiVarStore
1122 UINTN PackageOffset
;
1123 EFI_IFR_OP_HEADER
*IfrOpHdr
;
1124 CHAR16
*VarStoreName
;
1129 UINT8
*HiiFormPackage
;
1131 EFI_IFR_VARSTORE_EFI
*IfrEfiVarStore
;
1132 EFI_HII_PACKAGE_HEADER
*PackageHeader
;
1134 HiiFormPackage
= NULL
;
1136 Status
= EFI_SUCCESS
;
1140 *IsEfiVarstore
= FALSE
;
1142 Status
= GetFormPackageData(DataBaseRecord
, &HiiFormPackage
, &PackageSize
);
1143 if (EFI_ERROR (Status
)) {
1147 IfrOffset
= sizeof (EFI_HII_PACKAGE_HEADER
);
1148 PackageOffset
= IfrOffset
;
1149 PackageHeader
= (EFI_HII_PACKAGE_HEADER
*) HiiFormPackage
;
1151 while (IfrOffset
< PackageSize
) {
1153 // More than one form packages exist.
1155 if (PackageOffset
>= PackageHeader
->Length
) {
1157 // Process the new form package.
1159 PackageOffset
= sizeof (EFI_HII_PACKAGE_HEADER
);
1160 IfrOffset
+= PackageOffset
;
1161 PackageHeader
= (EFI_HII_PACKAGE_HEADER
*) (HiiFormPackage
+ IfrOffset
);
1164 IfrOpHdr
= (EFI_IFR_OP_HEADER
*) (HiiFormPackage
+ IfrOffset
);
1165 IfrOffset
+= IfrOpHdr
->Length
;
1166 PackageOffset
+= IfrOpHdr
->Length
;
1168 if (IfrOpHdr
->OpCode
== EFI_IFR_VARSTORE_EFI_OP
) {
1169 IfrEfiVarStore
= (EFI_IFR_VARSTORE_EFI
*) IfrOpHdr
;
1171 // If the length is small than the structure, this is from old efi
1172 // varstore definition. Old efi varstore get config directly from
1173 // GetVariable function.
1175 if (IfrOpHdr
->Length
< sizeof (EFI_IFR_VARSTORE_EFI
)) {
1179 VarStoreName
= AllocateZeroPool (AsciiStrSize ((CHAR8
*)IfrEfiVarStore
->Name
) * sizeof (CHAR16
));
1180 if (VarStoreName
== NULL
) {
1181 Status
= EFI_OUT_OF_RESOURCES
;
1184 AsciiStrToUnicodeStr ((CHAR8
*) IfrEfiVarStore
->Name
, VarStoreName
);
1186 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*) &IfrEfiVarStore
->Guid
, 1, &GuidStr
);
1187 GenerateSubStr (L
"NAME=", StrLen (VarStoreName
) * sizeof (CHAR16
), (VOID
*) VarStoreName
, 2, &NameStr
);
1188 LengthString
= StrLen (GuidStr
);
1189 LengthString
= LengthString
+ StrLen (NameStr
) + 1;
1190 TempStr
= AllocateZeroPool (LengthString
* sizeof (CHAR16
));
1191 if (TempStr
== NULL
) {
1194 FreePool (VarStoreName
);
1195 Status
= EFI_OUT_OF_RESOURCES
;
1198 StrCpyS (TempStr
, LengthString
, GuidStr
);
1199 StrCatS (TempStr
, LengthString
, NameStr
);
1200 if (ConfigHdr
== NULL
|| StrnCmp (ConfigHdr
, TempStr
, StrLen (TempStr
)) == 0) {
1201 *EfiVarStore
= (EFI_IFR_VARSTORE_EFI
*) AllocateZeroPool (IfrOpHdr
->Length
);
1202 if (*EfiVarStore
== NULL
) {
1203 FreePool (VarStoreName
);
1207 Status
= EFI_OUT_OF_RESOURCES
;
1210 *IsEfiVarstore
= TRUE
;
1211 CopyMem (*EfiVarStore
, IfrEfiVarStore
, IfrOpHdr
->Length
);
1215 // Free alllocated temp string.
1217 FreePool (VarStoreName
);
1223 // Already found the varstore, break;
1225 if (*IsEfiVarstore
) {
1231 if (HiiFormPackage
!= NULL
) {
1232 FreePool (HiiFormPackage
);
1239 Check whether the ConfigRequest string has the request elements.
1240 For EFI_HII_VARSTORE_BUFFER type, the request has "&OFFSET=****&WIDTH=****..." format.
1241 For EFI_HII_VARSTORE_NAME_VALUE type, the request has "&NAME1**&NAME2..." format.
1243 @param ConfigRequest The input config request string.
1245 @retval TRUE The input include config request elements.
1246 @retval FALSE The input string not includes.
1250 GetElementsFromRequest (
1251 IN EFI_STRING ConfigRequest
1254 EFI_STRING TmpRequest
;
1256 TmpRequest
= StrStr (ConfigRequest
, L
"PATH=");
1257 ASSERT (TmpRequest
!= NULL
);
1259 if ((StrStr (TmpRequest
, L
"&OFFSET=") != NULL
) || (StrStr (TmpRequest
, L
"&") != NULL
)) {
1267 Check whether the this varstore is the request varstore.
1269 @param VarstoreGuid Varstore guid.
1270 @param Name Varstore name.
1271 @param ConfigHdr Current configRequest info.
1273 @retval TRUE This varstore is the requst one.
1274 @retval FALSE This varstore is not the requst one.
1279 IN EFI_GUID
*VarstoreGuid
,
1281 IN CHAR16
*ConfigHdr
1295 // If ConfigHdr has name field and varstore not has name, return FALSE.
1297 if (Name
== NULL
&& ConfigHdr
!= NULL
&& StrStr (ConfigHdr
, L
"NAME=&") == NULL
) {
1301 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*)VarstoreGuid
, 1, &GuidStr
);
1303 GenerateSubStr (L
"NAME=", StrLen (Name
) * sizeof (CHAR16
), (VOID
*) Name
, 2, &NameStr
);
1305 GenerateSubStr (L
"NAME=", 0, NULL
, 2, &NameStr
);
1307 LengthString
= StrLen (GuidStr
);
1308 LengthString
= LengthString
+ StrLen (NameStr
) + 1;
1309 TempStr
= AllocateZeroPool (LengthString
* sizeof (CHAR16
));
1310 if (TempStr
== NULL
) {
1314 StrCpyS (TempStr
, LengthString
, GuidStr
);
1315 StrCatS (TempStr
, LengthString
, NameStr
);
1317 if (ConfigHdr
== NULL
|| StrnCmp (ConfigHdr
, TempStr
, StrLen (TempStr
)) == 0) {
1322 if (GuidStr
!= NULL
) {
1326 if (NameStr
!= NULL
) {
1330 if (TempStr
!= NULL
) {
1338 This function parses Form Package to get the efi varstore info according to the request ConfigHdr.
1340 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
1341 @param ConfigHdr Request string ConfigHdr. If it is NULL,
1342 the first found varstore will be as ConfigHdr.
1343 @retval TRUE This hii package is the reqeust one.
1344 @retval FALSE This hii package is not the reqeust one.
1348 IN HII_DATABASE_RECORD
*DataBaseRecord
,
1349 IN EFI_STRING ConfigHdr
1354 UINTN PackageOffset
;
1355 EFI_IFR_OP_HEADER
*IfrOpHdr
;
1356 CHAR16
*VarStoreName
;
1357 UINT8
*HiiFormPackage
;
1359 EFI_IFR_VARSTORE_EFI
*IfrEfiVarStore
;
1360 EFI_HII_PACKAGE_HEADER
*PackageHeader
;
1361 EFI_IFR_VARSTORE
*IfrVarStore
;
1362 EFI_IFR_VARSTORE_NAME_VALUE
*IfrNameValueVarStore
;
1363 BOOLEAN FindVarstore
;
1365 HiiFormPackage
= NULL
;
1366 VarStoreName
= NULL
;
1367 Status
= EFI_SUCCESS
;
1368 FindVarstore
= FALSE
;
1370 Status
= GetFormPackageData(DataBaseRecord
, &HiiFormPackage
, &PackageSize
);
1371 if (EFI_ERROR (Status
)) {
1375 IfrOffset
= sizeof (EFI_HII_PACKAGE_HEADER
);
1376 PackageOffset
= IfrOffset
;
1377 PackageHeader
= (EFI_HII_PACKAGE_HEADER
*) HiiFormPackage
;
1379 while (IfrOffset
< PackageSize
) {
1381 // More than one form packages exist.
1383 if (PackageOffset
>= PackageHeader
->Length
) {
1385 // Process the new form package.
1387 PackageOffset
= sizeof (EFI_HII_PACKAGE_HEADER
);
1388 IfrOffset
+= PackageOffset
;
1389 PackageHeader
= (EFI_HII_PACKAGE_HEADER
*) (HiiFormPackage
+ IfrOffset
);
1392 IfrOpHdr
= (EFI_IFR_OP_HEADER
*) (HiiFormPackage
+ IfrOffset
);
1393 IfrOffset
+= IfrOpHdr
->Length
;
1394 PackageOffset
+= IfrOpHdr
->Length
;
1396 switch (IfrOpHdr
->OpCode
) {
1398 case EFI_IFR_VARSTORE_OP
:
1399 IfrVarStore
= (EFI_IFR_VARSTORE
*) IfrOpHdr
;
1401 VarStoreName
= AllocateZeroPool (AsciiStrSize ((CHAR8
*)IfrVarStore
->Name
) * sizeof (CHAR16
));
1402 if (VarStoreName
== NULL
) {
1405 AsciiStrToUnicodeStr ((CHAR8
*)IfrVarStore
->Name
, VarStoreName
);
1407 if (IsThisVarstore((VOID
*)&IfrVarStore
->Guid
, VarStoreName
, ConfigHdr
)) {
1408 FindVarstore
= TRUE
;
1413 case EFI_IFR_VARSTORE_EFI_OP
:
1414 IfrEfiVarStore
= (EFI_IFR_VARSTORE_EFI
*) IfrOpHdr
;
1415 VarStoreName
= AllocateZeroPool (AsciiStrSize ((CHAR8
*)IfrEfiVarStore
->Name
) * sizeof (CHAR16
));
1416 if (VarStoreName
== NULL
) {
1419 AsciiStrToUnicodeStr ((CHAR8
*)IfrEfiVarStore
->Name
, VarStoreName
);
1421 if (IsThisVarstore (&IfrEfiVarStore
->Guid
, VarStoreName
, ConfigHdr
)) {
1422 FindVarstore
= TRUE
;
1427 case EFI_IFR_VARSTORE_NAME_VALUE_OP
:
1428 IfrNameValueVarStore
= (EFI_IFR_VARSTORE_NAME_VALUE
*) IfrOpHdr
;
1430 if (IsThisVarstore (&IfrNameValueVarStore
->Guid
, NULL
, ConfigHdr
)) {
1431 FindVarstore
= TRUE
;
1436 case EFI_IFR_FORM_OP
:
1437 case EFI_IFR_FORM_MAP_OP
:
1439 // No matched varstore is found and directly return.
1448 if (HiiFormPackage
!= NULL
) {
1449 FreePool (HiiFormPackage
);
1452 if (VarStoreName
!= NULL
) {
1453 FreePool (VarStoreName
);
1456 return FindVarstore
;
1460 Check whether the this op code is required.
1462 @param RequestBlockArray The array includes all the request info or NULL.
1463 @param HiiHandle The hii handle for this form package.
1464 @param VarStorageData The varstore data strucure.
1465 @param IfrOpHdr Ifr opcode header for this opcode.
1466 @param VarWidth The buffer width for this opcode.
1467 @param ReturnData The data block added for this opcode.
1469 @retval EFI_SUCCESS This opcode is required.
1470 @retval EFI_NOT_FOUND This opcode is not required.
1471 @retval Others Contain some error.
1475 IsThisOpcodeRequired (
1476 IN IFR_BLOCK_DATA
*RequestBlockArray
,
1477 IN EFI_HII_HANDLE HiiHandle
,
1478 IN OUT IFR_VARSTORAGE_DATA
*VarStorageData
,
1479 IN EFI_IFR_OP_HEADER
*IfrOpHdr
,
1481 OUT IFR_BLOCK_DATA
**ReturnData
1484 IFR_BLOCK_DATA
*BlockData
;
1486 EFI_STRING_ID NameId
;
1487 EFI_IFR_QUESTION_HEADER
*IfrQuestionHdr
;
1491 IfrQuestionHdr
= (EFI_IFR_QUESTION_HEADER
*)((CHAR8
*) IfrOpHdr
+ sizeof (EFI_IFR_OP_HEADER
));
1493 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
1494 NameId
= IfrQuestionHdr
->VarStoreInfo
.VarName
;
1497 // Check whether this question is in requested block array.
1499 if (!BlockArrayCheck (RequestBlockArray
, NameId
, 0, TRUE
, HiiHandle
)) {
1501 // This question is not in the requested string. Skip it.
1503 return EFI_NOT_FOUND
;
1506 VarOffset
= IfrQuestionHdr
->VarStoreInfo
.VarOffset
;
1509 // Check whether this question is in requested block array.
1511 if (!BlockArrayCheck (RequestBlockArray
, VarOffset
, VarWidth
, FALSE
, HiiHandle
)) {
1513 // This question is not in the requested string. Skip it.
1515 return EFI_NOT_FOUND
;
1519 // Check this var question is in the var storage
1521 if (((VarOffset
+ VarWidth
) > VarStorageData
->Size
)) {
1522 return EFI_INVALID_PARAMETER
;
1526 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
1527 if (BlockData
== NULL
) {
1528 return EFI_OUT_OF_RESOURCES
;
1531 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
1532 BlockData
->Name
= InternalGetString(HiiHandle
, NameId
);
1534 BlockData
->Offset
= VarOffset
;
1537 BlockData
->Width
= VarWidth
;
1538 BlockData
->QuestionId
= IfrQuestionHdr
->QuestionId
;
1539 BlockData
->OpCode
= IfrOpHdr
->OpCode
;
1540 BlockData
->Scope
= IfrOpHdr
->Scope
;
1541 InitializeListHead (&BlockData
->DefaultValueEntry
);
1543 // Add Block Data into VarStorageData BlockEntry
1545 InsertBlockData (&VarStorageData
->BlockEntry
, &BlockData
);
1546 *ReturnData
= BlockData
;
1552 This function parses Form Package to get the block array and the default
1553 value array according to the request ConfigHdr.
1555 @param HiiHandle Hii Handle for this hii package.
1556 @param Package Pointer to the form package data.
1557 @param PackageLength Length of the pacakge.
1558 @param ConfigHdr Request string ConfigHdr. If it is NULL,
1559 the first found varstore will be as ConfigHdr.
1560 @param RequestBlockArray The block array is retrieved from the request string.
1561 @param VarStorageData VarStorage structure contains the got block and default value.
1562 @param DefaultIdArray Point to the got default id and default name array.
1564 @retval EFI_SUCCESS The block array and the default value array are got.
1565 @retval EFI_INVALID_PARAMETER The varstore defintion in the differnt form pacakges
1567 @retval EFI_OUT_OF_RESOURCES No enough memory.
1572 IN EFI_HII_HANDLE HiiHandle
,
1574 IN UINT32 PackageLength
,
1575 IN EFI_STRING ConfigHdr
,
1576 IN IFR_BLOCK_DATA
*RequestBlockArray
,
1577 IN OUT IFR_VARSTORAGE_DATA
*VarStorageData
,
1578 OUT IFR_DEFAULT_DATA
*DefaultIdArray
1583 UINTN PackageOffset
;
1584 EFI_IFR_VARSTORE
*IfrVarStore
;
1585 EFI_IFR_VARSTORE_EFI
*IfrEfiVarStore
;
1586 EFI_IFR_OP_HEADER
*IfrOpHdr
;
1587 EFI_IFR_ONE_OF
*IfrOneOf
;
1588 EFI_IFR_REF4
*IfrRef
;
1589 EFI_IFR_ONE_OF_OPTION
*IfrOneOfOption
;
1590 EFI_IFR_DEFAULT
*IfrDefault
;
1591 EFI_IFR_ORDERED_LIST
*IfrOrderedList
;
1592 EFI_IFR_CHECKBOX
*IfrCheckBox
;
1593 EFI_IFR_PASSWORD
*IfrPassword
;
1594 EFI_IFR_STRING
*IfrString
;
1595 EFI_IFR_DATE
*IfrDate
;
1596 EFI_IFR_TIME
*IfrTime
;
1597 IFR_DEFAULT_DATA DefaultData
;
1598 IFR_DEFAULT_DATA
*DefaultDataPtr
;
1599 IFR_BLOCK_DATA
*BlockData
;
1600 CHAR16
*VarStoreName
;
1602 UINT16 VarDefaultId
;
1603 BOOLEAN FirstOneOfOption
;
1604 BOOLEAN FirstOrderedList
;
1605 LIST_ENTRY
*LinkData
;
1606 LIST_ENTRY
*LinkDefault
;
1607 EFI_IFR_VARSTORE_NAME_VALUE
*IfrNameValueVarStore
;
1608 EFI_HII_PACKAGE_HEADER
*PackageHeader
;
1609 EFI_VARSTORE_ID VarStoreId
;
1611 Status
= EFI_SUCCESS
;
1613 DefaultDataPtr
= NULL
;
1614 FirstOneOfOption
= FALSE
;
1616 FirstOrderedList
= FALSE
;
1617 ZeroMem (&DefaultData
, sizeof (IFR_DEFAULT_DATA
));
1620 // Go through the form package to parse OpCode one by one.
1622 PackageOffset
= sizeof (EFI_HII_PACKAGE_HEADER
);
1623 PackageHeader
= (EFI_HII_PACKAGE_HEADER
*) Package
;
1624 IfrOffset
= PackageOffset
;
1625 while (IfrOffset
< PackageLength
) {
1628 // More than one form package found.
1630 if (PackageOffset
>= PackageHeader
->Length
) {
1632 // Already found varstore for this request, break;
1634 if (VarStoreId
!= 0) {
1639 // Get next package header info.
1641 IfrOffset
+= sizeof (EFI_HII_PACKAGE_HEADER
);
1642 PackageOffset
= sizeof (EFI_HII_PACKAGE_HEADER
);
1643 PackageHeader
= (EFI_HII_PACKAGE_HEADER
*) (Package
+ IfrOffset
);
1646 IfrOpHdr
= (EFI_IFR_OP_HEADER
*) (Package
+ IfrOffset
);
1647 switch (IfrOpHdr
->OpCode
) {
1648 case EFI_IFR_VARSTORE_OP
:
1650 // VarStore is found. Don't need to search any more.
1652 if (VarStoreId
!= 0) {
1656 IfrVarStore
= (EFI_IFR_VARSTORE
*) IfrOpHdr
;
1658 VarStoreName
= AllocateZeroPool (AsciiStrSize ((CHAR8
*)IfrVarStore
->Name
) * sizeof (CHAR16
));
1659 if (VarStoreName
== NULL
) {
1660 Status
= EFI_OUT_OF_RESOURCES
;
1663 AsciiStrToUnicodeStr ((CHAR8
*)IfrVarStore
->Name
, VarStoreName
);
1665 if (IsThisVarstore((VOID
*)&IfrVarStore
->Guid
, VarStoreName
, ConfigHdr
)) {
1667 // Find the matched VarStore
1669 CopyGuid (&VarStorageData
->Guid
, (EFI_GUID
*) (VOID
*) &IfrVarStore
->Guid
);
1670 VarStorageData
->Size
= IfrVarStore
->Size
;
1671 VarStorageData
->Name
= VarStoreName
;
1672 VarStorageData
->Type
= EFI_HII_VARSTORE_BUFFER
;
1673 VarStoreId
= IfrVarStore
->VarStoreId
;
1677 case EFI_IFR_VARSTORE_EFI_OP
:
1679 // VarStore is found. Don't need to search any more.
1681 if (VarStoreId
!= 0) {
1685 IfrEfiVarStore
= (EFI_IFR_VARSTORE_EFI
*) IfrOpHdr
;
1688 // If the length is small than the structure, this is from old efi
1689 // varstore definition. Old efi varstore get config directly from
1690 // GetVariable function.
1692 if (IfrOpHdr
->Length
< sizeof (EFI_IFR_VARSTORE_EFI
)) {
1696 VarStoreName
= AllocateZeroPool (AsciiStrSize ((CHAR8
*)IfrEfiVarStore
->Name
) * sizeof (CHAR16
));
1697 if (VarStoreName
== NULL
) {
1698 Status
= EFI_OUT_OF_RESOURCES
;
1701 AsciiStrToUnicodeStr ((CHAR8
*)IfrEfiVarStore
->Name
, VarStoreName
);
1703 if (IsThisVarstore (&IfrEfiVarStore
->Guid
, VarStoreName
, ConfigHdr
)) {
1705 // Find the matched VarStore
1707 CopyGuid (&VarStorageData
->Guid
, (EFI_GUID
*) (VOID
*) &IfrEfiVarStore
->Guid
);
1708 VarStorageData
->Size
= IfrEfiVarStore
->Size
;
1709 VarStorageData
->Name
= VarStoreName
;
1710 VarStorageData
->Type
= EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
;
1711 VarStoreId
= IfrEfiVarStore
->VarStoreId
;
1715 case EFI_IFR_VARSTORE_NAME_VALUE_OP
:
1717 // VarStore is found. Don't need to search any more.
1719 if (VarStoreId
!= 0) {
1723 IfrNameValueVarStore
= (EFI_IFR_VARSTORE_NAME_VALUE
*) IfrOpHdr
;
1725 if (IsThisVarstore (&IfrNameValueVarStore
->Guid
, NULL
, ConfigHdr
)) {
1727 // Find the matched VarStore
1729 CopyGuid (&VarStorageData
->Guid
, (EFI_GUID
*) (VOID
*) &IfrNameValueVarStore
->Guid
);
1730 VarStorageData
->Type
= EFI_HII_VARSTORE_NAME_VALUE
;
1731 VarStoreId
= IfrNameValueVarStore
->VarStoreId
;
1735 case EFI_IFR_DEFAULTSTORE_OP
:
1737 // Add new the map between default id and default name.
1739 DefaultDataPtr
= (IFR_DEFAULT_DATA
*) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
1740 if (DefaultDataPtr
== NULL
) {
1741 Status
= EFI_OUT_OF_RESOURCES
;
1744 DefaultDataPtr
->DefaultId
= ((EFI_IFR_DEFAULTSTORE
*) IfrOpHdr
)->DefaultId
;
1745 InsertTailList (&DefaultIdArray
->Entry
, &DefaultDataPtr
->Entry
);
1746 DefaultDataPtr
= NULL
;
1749 case EFI_IFR_FORM_OP
:
1750 case EFI_IFR_FORM_MAP_OP
:
1752 // No matched varstore is found and directly return.
1754 if ( VarStoreId
== 0) {
1755 Status
= EFI_SUCCESS
;
1760 case EFI_IFR_REF_OP
:
1762 // Ref question is not in IFR Form. This IFR form is not valid.
1764 if ( VarStoreId
== 0) {
1765 Status
= EFI_INVALID_PARAMETER
;
1769 // Check whether this question is for the requested varstore.
1771 IfrRef
= (EFI_IFR_REF4
*) IfrOpHdr
;
1772 if (IfrRef
->Question
.VarStoreId
!= VarStoreId
) {
1775 VarWidth
= (UINT16
) (sizeof (EFI_HII_REF
));
1778 // The BlockData may allocate by other opcode,need to clean.
1780 if (BlockData
!= NULL
){
1784 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
1785 if (EFI_ERROR (Status
)) {
1786 if (Status
== EFI_NOT_FOUND
){
1788 //The opcode is not required,exit and parse other opcode.
1796 case EFI_IFR_ONE_OF_OP
:
1797 case EFI_IFR_NUMERIC_OP
:
1799 // Numeric and OneOf has the same opcode structure.
1803 // Numeric and OneOf question is not in IFR Form. This IFR form is not valid.
1805 if (VarStoreId
== 0) {
1806 Status
= EFI_INVALID_PARAMETER
;
1810 // Check whether this question is for the requested varstore.
1812 IfrOneOf
= (EFI_IFR_ONE_OF
*) IfrOpHdr
;
1813 if (IfrOneOf
->Question
.VarStoreId
!= VarStoreId
) {
1816 VarWidth
= (UINT16
) (1 << (IfrOneOf
->Flags
& EFI_IFR_NUMERIC_SIZE
));
1819 // The BlockData may allocate by other opcode,need to clean.
1821 if (BlockData
!= NULL
){
1825 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
1826 if (EFI_ERROR (Status
)) {
1827 if (Status
== EFI_NOT_FOUND
){
1829 //The opcode is not required,exit and parse other opcode.
1837 //when go to there,BlockData can't be NULLL.
1839 ASSERT (BlockData
!= NULL
);
1841 if (IfrOpHdr
->OpCode
== EFI_IFR_ONE_OF_OP
) {
1843 // Set this flag to TRUE for the first oneof option.
1845 FirstOneOfOption
= TRUE
;
1846 } else if (IfrOpHdr
->OpCode
== EFI_IFR_NUMERIC_OP
) {
1848 // Numeric minimum value will be used as default value when no default is specified.
1850 DefaultData
.Type
= DefaultValueFromDefault
;
1851 switch (IfrOneOf
->Flags
& EFI_IFR_NUMERIC_SIZE
) {
1852 case EFI_IFR_NUMERIC_SIZE_1
:
1853 DefaultData
.Value
.u8
= IfrOneOf
->data
.u8
.MinValue
;
1856 case EFI_IFR_NUMERIC_SIZE_2
:
1857 CopyMem (&DefaultData
.Value
.u16
, &IfrOneOf
->data
.u16
.MinValue
, sizeof (UINT16
));
1860 case EFI_IFR_NUMERIC_SIZE_4
:
1861 CopyMem (&DefaultData
.Value
.u32
, &IfrOneOf
->data
.u32
.MinValue
, sizeof (UINT32
));
1864 case EFI_IFR_NUMERIC_SIZE_8
:
1865 CopyMem (&DefaultData
.Value
.u64
, &IfrOneOf
->data
.u64
.MinValue
, sizeof (UINT64
));
1869 Status
= EFI_INVALID_PARAMETER
;
1873 // Set default value base on the DefaultId list get from IFR data.
1875 for (LinkData
= DefaultIdArray
->Entry
.ForwardLink
; LinkData
!= &DefaultIdArray
->Entry
; LinkData
= LinkData
->ForwardLink
) {
1876 DefaultDataPtr
= BASE_CR (LinkData
, IFR_DEFAULT_DATA
, Entry
);
1877 DefaultData
.DefaultId
= DefaultDataPtr
->DefaultId
;
1878 InsertDefaultValue (BlockData
, &DefaultData
);
1883 case EFI_IFR_ORDERED_LIST_OP
:
1885 // offset by question header
1886 // width by EFI_IFR_ORDERED_LIST MaxContainers * OneofOption Type
1889 FirstOrderedList
= TRUE
;
1891 // OrderedList question is not in IFR Form. This IFR form is not valid.
1893 if (VarStoreId
== 0) {
1894 Status
= EFI_INVALID_PARAMETER
;
1898 // Check whether this question is for the requested varstore.
1900 IfrOrderedList
= (EFI_IFR_ORDERED_LIST
*) IfrOpHdr
;
1901 if (IfrOrderedList
->Question
.VarStoreId
!= VarStoreId
) {
1905 VarWidth
= IfrOrderedList
->MaxContainers
;
1908 // The BlockData may allocate by other opcode,need to clean.
1910 if (BlockData
!= NULL
){
1914 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
1915 if (EFI_ERROR (Status
)) {
1916 if (Status
== EFI_NOT_FOUND
){
1918 //The opcode is not required,exit and parse other opcode.
1926 case EFI_IFR_CHECKBOX_OP
:
1928 // EFI_IFR_DEFAULT_OP
1929 // offset by question header
1930 // width is 1 sizeof (BOOLEAN)
1931 // default id by CheckBox Flags if CheckBox flags (Default or Mau) is set, the default value is 1 to be set.
1932 // value by DefaultOption
1933 // default id by DeaultOption DefaultId can override CheckBox Flags and Default value.
1937 // CheckBox question is not in IFR Form. This IFR form is not valid.
1939 if (VarStoreId
== 0) {
1940 Status
= EFI_INVALID_PARAMETER
;
1944 // Check whether this question is for the requested varstore.
1946 IfrCheckBox
= (EFI_IFR_CHECKBOX
*) IfrOpHdr
;
1947 if (IfrCheckBox
->Question
.VarStoreId
!= VarStoreId
) {
1950 VarWidth
= (UINT16
) sizeof (BOOLEAN
);
1953 // The BlockData may allocate by other opcode,need to clean.
1955 if (BlockData
!= NULL
){
1959 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
1960 if (EFI_ERROR (Status
)) {
1961 if (Status
== EFI_NOT_FOUND
){
1963 //The opcode is not required,exit and parse other opcode.
1971 //when go to there,BlockData can't be NULLL.
1973 ASSERT (BlockData
!= NULL
);
1976 // Add default value for standard ID by CheckBox Flag
1978 VarDefaultId
= EFI_HII_DEFAULT_CLASS_STANDARD
;
1980 // Prepare new DefaultValue
1982 DefaultData
.DefaultId
= VarDefaultId
;
1983 if ((IfrCheckBox
->Flags
& EFI_IFR_CHECKBOX_DEFAULT
) == EFI_IFR_CHECKBOX_DEFAULT
) {
1985 // When flag is set, defautl value is TRUE.
1987 DefaultData
.Type
= DefaultValueFromFlag
;
1988 DefaultData
.Value
.b
= TRUE
;
1991 // When flag is not set, defautl value is FASLE.
1993 DefaultData
.Type
= DefaultValueFromDefault
;
1994 DefaultData
.Value
.b
= FALSE
;
1997 // Add DefaultValue into current BlockData
1999 InsertDefaultValue (BlockData
, &DefaultData
);
2002 // Add default value for Manufacture ID by CheckBox Flag
2004 VarDefaultId
= EFI_HII_DEFAULT_CLASS_MANUFACTURING
;
2006 // Prepare new DefaultValue
2008 DefaultData
.DefaultId
= VarDefaultId
;
2009 if ((IfrCheckBox
->Flags
& EFI_IFR_CHECKBOX_DEFAULT_MFG
) == EFI_IFR_CHECKBOX_DEFAULT_MFG
) {
2011 // When flag is set, defautl value is TRUE.
2013 DefaultData
.Type
= DefaultValueFromFlag
;
2014 DefaultData
.Value
.b
= TRUE
;
2017 // When flag is not set, defautl value is FASLE.
2019 DefaultData
.Type
= DefaultValueFromDefault
;
2020 DefaultData
.Value
.b
= FALSE
;
2023 // Add DefaultValue into current BlockData
2025 InsertDefaultValue (BlockData
, &DefaultData
);
2028 case EFI_IFR_DATE_OP
:
2030 // offset by question header
2031 // width MaxSize * sizeof (CHAR16)
2032 // no default value, only block array
2036 // Date question is not in IFR Form. This IFR form is not valid.
2038 if (VarStoreId
== 0) {
2039 Status
= EFI_INVALID_PARAMETER
;
2043 // Check whether this question is for the requested varstore.
2045 IfrDate
= (EFI_IFR_DATE
*) IfrOpHdr
;
2046 if (IfrDate
->Question
.VarStoreId
!= VarStoreId
) {
2051 // The BlockData may allocate by other opcode,need to clean.
2053 if (BlockData
!= NULL
){
2057 VarWidth
= (UINT16
) sizeof (EFI_HII_DATE
);
2058 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
2059 if (EFI_ERROR (Status
)) {
2060 if (Status
== EFI_NOT_FOUND
){
2062 //The opcode is not required,exit and parse other opcode.
2070 case EFI_IFR_TIME_OP
:
2072 // offset by question header
2073 // width MaxSize * sizeof (CHAR16)
2074 // no default value, only block array
2078 // Time question is not in IFR Form. This IFR form is not valid.
2080 if (VarStoreId
== 0) {
2081 Status
= EFI_INVALID_PARAMETER
;
2085 // Check whether this question is for the requested varstore.
2087 IfrTime
= (EFI_IFR_TIME
*) IfrOpHdr
;
2088 if (IfrTime
->Question
.VarStoreId
!= VarStoreId
) {
2093 // The BlockData may allocate by other opcode,need to clean.
2095 if (BlockData
!= NULL
){
2099 VarWidth
= (UINT16
) sizeof (EFI_HII_TIME
);
2100 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
2101 if (EFI_ERROR (Status
)) {
2102 if (Status
== EFI_NOT_FOUND
){
2104 //The opcode is not required,exit and parse other opcode.
2112 case EFI_IFR_STRING_OP
:
2114 // offset by question header
2115 // width MaxSize * sizeof (CHAR16)
2116 // no default value, only block array
2120 // String question is not in IFR Form. This IFR form is not valid.
2122 if (VarStoreId
== 0) {
2123 Status
= EFI_INVALID_PARAMETER
;
2127 // Check whether this question is for the requested varstore.
2129 IfrString
= (EFI_IFR_STRING
*) IfrOpHdr
;
2130 if (IfrString
->Question
.VarStoreId
!= VarStoreId
) {
2135 // The BlockData may allocate by other opcode,need to clean.
2137 if (BlockData
!= NULL
){
2141 VarWidth
= (UINT16
) (IfrString
->MaxSize
* sizeof (UINT16
));
2142 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
2143 if (EFI_ERROR (Status
)) {
2144 if (Status
== EFI_NOT_FOUND
){
2146 //The opcode is not required,exit and parse other opcode.
2154 case EFI_IFR_PASSWORD_OP
:
2156 // offset by question header
2157 // width MaxSize * sizeof (CHAR16)
2158 // no default value, only block array
2162 // Password question is not in IFR Form. This IFR form is not valid.
2164 if (VarStoreId
== 0) {
2165 Status
= EFI_INVALID_PARAMETER
;
2169 // Check whether this question is for the requested varstore.
2171 IfrPassword
= (EFI_IFR_PASSWORD
*) IfrOpHdr
;
2172 if (IfrPassword
->Question
.VarStoreId
!= VarStoreId
) {
2177 // The BlockData may allocate by other opcode,need to clean.
2179 if (BlockData
!= NULL
){
2183 VarWidth
= (UINT16
) (IfrPassword
->MaxSize
* sizeof (UINT16
));
2184 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
2185 if (EFI_ERROR (Status
)) {
2186 if (Status
== EFI_NOT_FOUND
){
2188 //The opcode is not required,exit and parse other opcode.
2196 // No default value for string.
2201 case EFI_IFR_ONE_OF_OPTION_OP
:
2203 // No matched block data is ignored.
2205 if (BlockData
== NULL
|| BlockData
->Scope
== 0) {
2209 IfrOneOfOption
= (EFI_IFR_ONE_OF_OPTION
*) IfrOpHdr
;
2210 if (BlockData
->OpCode
== EFI_IFR_ORDERED_LIST_OP
) {
2212 if (!FirstOrderedList
){
2216 // Get ordered list option data type.
2218 if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_8
|| IfrOneOfOption
->Type
== EFI_IFR_TYPE_BOOLEAN
) {
2220 } else if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_16
) {
2222 } else if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_32
) {
2224 } else if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_64
) {
2228 // Invalid ordered list option data type.
2230 Status
= EFI_INVALID_PARAMETER
;
2231 if (BlockData
->Name
!= NULL
) {
2232 FreePool (BlockData
->Name
);
2234 FreePool (BlockData
);
2239 // Calculate Ordered list QuestionId width.
2241 BlockData
->Width
= (UINT16
) (BlockData
->Width
* VarWidth
);
2243 // Check whether this question is in requested block array.
2245 if (!BlockArrayCheck (RequestBlockArray
, BlockData
->Offset
, BlockData
->Width
, (BOOLEAN
)(BlockData
->Name
!= NULL
), HiiHandle
)) {
2247 // This question is not in the requested string. Skip it.
2249 if (BlockData
->Name
!= NULL
) {
2250 FreePool (BlockData
->Name
);
2252 FreePool (BlockData
);
2257 // Check this var question is in the var storage
2259 if ((BlockData
->Name
== NULL
) && ((BlockData
->Offset
+ BlockData
->Width
) > VarStorageData
->Size
)) {
2260 Status
= EFI_INVALID_PARAMETER
;
2261 if (BlockData
->Name
!= NULL
) {
2262 FreePool (BlockData
->Name
);
2264 FreePool (BlockData
);
2268 // Add Block Data into VarStorageData BlockEntry
2270 InsertBlockData (&VarStorageData
->BlockEntry
, &BlockData
);
2272 FirstOrderedList
= FALSE
;
2278 // 1. Set default value for OneOf option when flag field has default attribute.
2280 if (((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT
) == EFI_IFR_OPTION_DEFAULT
) ||
2281 ((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT_MFG
) == EFI_IFR_OPTION_DEFAULT_MFG
)) {
2283 // This flag is used to specify whether this option is the first. Set it to FALSE for the following options.
2284 // The first oneof option value will be used as default value when no default value is specified.
2286 FirstOneOfOption
= FALSE
;
2288 // Prepare new DefaultValue
2290 DefaultData
.Type
= DefaultValueFromFlag
;
2291 CopyMem (&DefaultData
.Value
, &IfrOneOfOption
->Value
, IfrOneOfOption
->Header
.Length
- OFFSET_OF (EFI_IFR_ONE_OF_OPTION
, Value
));
2292 if ((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT
) == EFI_IFR_OPTION_DEFAULT
) {
2293 DefaultData
.DefaultId
= EFI_HII_DEFAULT_CLASS_STANDARD
;
2294 InsertDefaultValue (BlockData
, &DefaultData
);
2296 if ((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT_MFG
) == EFI_IFR_OPTION_DEFAULT_MFG
) {
2297 DefaultData
.DefaultId
= EFI_HII_DEFAULT_CLASS_MANUFACTURING
;
2298 InsertDefaultValue (BlockData
, &DefaultData
);
2303 // 2. Set as the default value when this is the first option.
2304 // The first oneof option value will be used as default value when no default value is specified.
2306 if (FirstOneOfOption
) {
2307 // This flag is used to specify whether this option is the first. Set it to FALSE for the following options.
2308 FirstOneOfOption
= FALSE
;
2311 // Prepare new DefaultValue
2313 DefaultData
.Type
= DefaultValueFromDefault
;
2314 CopyMem (&DefaultData
.Value
, &IfrOneOfOption
->Value
, IfrOneOfOption
->Header
.Length
- OFFSET_OF (EFI_IFR_ONE_OF_OPTION
, Value
));
2315 for (LinkData
= DefaultIdArray
->Entry
.ForwardLink
; LinkData
!= &DefaultIdArray
->Entry
; LinkData
= LinkData
->ForwardLink
) {
2316 DefaultDataPtr
= BASE_CR (LinkData
, IFR_DEFAULT_DATA
, Entry
);
2317 DefaultData
.DefaultId
= DefaultDataPtr
->DefaultId
;
2318 InsertDefaultValue (BlockData
, &DefaultData
);
2323 case EFI_IFR_DEFAULT_OP
:
2325 // Update Current BlockData to the default value.
2327 if (BlockData
== NULL
|| BlockData
->Scope
== 0) {
2329 // No matched block data is ignored.
2335 // Get the DefaultId
2337 IfrDefault
= (EFI_IFR_DEFAULT
*) IfrOpHdr
;
2338 VarDefaultId
= IfrDefault
->DefaultId
;
2340 // Prepare new DefaultValue
2342 DefaultData
.Type
= DefaultValueFromOpcode
;
2343 DefaultData
.DefaultId
= VarDefaultId
;
2344 CopyMem (&DefaultData
.Value
, &IfrDefault
->Value
, IfrDefault
->Header
.Length
- OFFSET_OF (EFI_IFR_DEFAULT
, Value
));
2346 // If the value field is expression, set the cleaned flag.
2347 if (IfrDefault
->Type
== EFI_IFR_TYPE_OTHER
) {
2348 DefaultData
.Cleaned
= TRUE
;
2351 // Add DefaultValue into current BlockData
2353 InsertDefaultValue (BlockData
, &DefaultData
);
2356 // After insert the default value, reset the cleaned value for next
2357 // time used. If not set here, need to set the value before everytime
2360 DefaultData
.Cleaned
= FALSE
;
2363 case EFI_IFR_END_OP
:
2365 // End Opcode is for Var question.
2367 if (BlockData
!= NULL
) {
2368 if (BlockData
->Scope
> 0) {
2371 if (BlockData
->Scope
== 0) {
2379 if (BlockData
!= NULL
) {
2380 if (BlockData
->Scope
> 0) {
2381 BlockData
->Scope
= (UINT8
) (BlockData
->Scope
+ IfrOpHdr
->Scope
);
2384 if (BlockData
->Scope
== 0) {
2391 IfrOffset
+= IfrOpHdr
->Length
;
2392 PackageOffset
+= IfrOpHdr
->Length
;
2396 //if Status == EFI_NOT_FOUND, just means the opcode is not required,not contain any error,
2397 //so set the Status to EFI_SUCCESS.
2399 if (Status
== EFI_NOT_FOUND
){
2400 Status
= EFI_SUCCESS
;
2404 for (LinkData
= VarStorageData
->BlockEntry
.ForwardLink
; LinkData
!= &VarStorageData
->BlockEntry
; LinkData
= LinkData
->ForwardLink
) {
2405 BlockData
= BASE_CR (LinkData
, IFR_BLOCK_DATA
, Entry
);
2406 for (LinkDefault
= BlockData
->DefaultValueEntry
.ForwardLink
; LinkDefault
!= &BlockData
->DefaultValueEntry
; ) {
2407 DefaultDataPtr
= BASE_CR (LinkDefault
, IFR_DEFAULT_DATA
, Entry
);
2408 LinkDefault
= LinkDefault
->ForwardLink
;
2409 if (DefaultDataPtr
->Cleaned
== TRUE
) {
2410 RemoveEntryList (&DefaultDataPtr
->Entry
);
2411 FreePool (DefaultDataPtr
);
2420 parse the configrequest string, get the elements.
2422 @param ConfigRequest The input configrequest string.
2423 @param Progress Return the progress data.
2425 @retval Block data pointer.
2429 IN EFI_STRING ConfigRequest
,
2430 OUT EFI_STRING
*Progress
2433 EFI_STRING StringPtr
;
2434 IFR_BLOCK_DATA
*BlockData
;
2435 IFR_BLOCK_DATA
*RequestBlockArray
;
2441 IFR_BLOCK_DATA
*NextBlockData
;
2447 // Init RequestBlockArray
2449 RequestBlockArray
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
2450 if (RequestBlockArray
== NULL
) {
2453 InitializeListHead (&RequestBlockArray
->Entry
);
2456 // Get the request Block array from the request string
2461 // Parse each <RequestElement> if exists
2462 // Only <BlockName> format is supported by this help function.
2463 // <BlockName> ::= &'OFFSET='<Number>&'WIDTH='<Number>
2465 StringPtr
= ConfigRequest
;
2466 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) == 0) {
2468 // Skip the OFFSET string
2470 *Progress
= StringPtr
;
2471 StringPtr
+= StrLen (L
"&OFFSET=");
2475 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
2476 if (EFI_ERROR (Status
)) {
2483 (((Length
+ 1) / 2) < sizeof (UINT16
)) ? ((Length
+ 1) / 2) : sizeof (UINT16
)
2485 FreePool (TmpBuffer
);
2487 StringPtr
+= Length
;
2488 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
2491 StringPtr
+= StrLen (L
"&WIDTH=");
2496 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
2497 if (EFI_ERROR (Status
)) {
2504 (((Length
+ 1) / 2) < sizeof (UINT16
)) ? ((Length
+ 1) / 2) : sizeof (UINT16
)
2506 FreePool (TmpBuffer
);
2508 StringPtr
+= Length
;
2509 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
2516 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
2517 if (BlockData
== NULL
) {
2520 BlockData
->Offset
= Offset
;
2521 BlockData
->Width
= Width
;
2522 InsertBlockData (&RequestBlockArray
->Entry
, &BlockData
);
2525 // Skip &VALUE string if &VALUE does exists.
2527 if (StrnCmp (StringPtr
, L
"&VALUE=", StrLen (L
"&VALUE=")) == 0) {
2528 StringPtr
+= StrLen (L
"&VALUE=");
2533 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
2534 if (EFI_ERROR (Status
)) {
2538 StringPtr
+= Length
;
2539 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
2544 // If '\0', parsing is finished.
2546 if (*StringPtr
== 0) {
2552 // Merge the requested block data.
2554 Link
= RequestBlockArray
->Entry
.ForwardLink
;
2555 while ((Link
!= &RequestBlockArray
->Entry
) && (Link
->ForwardLink
!= &RequestBlockArray
->Entry
)) {
2556 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
2557 NextBlockData
= BASE_CR (Link
->ForwardLink
, IFR_BLOCK_DATA
, Entry
);
2558 if ((NextBlockData
->Offset
>= BlockData
->Offset
) && (NextBlockData
->Offset
<= (BlockData
->Offset
+ BlockData
->Width
))) {
2559 if ((NextBlockData
->Offset
+ NextBlockData
->Width
) > (BlockData
->Offset
+ BlockData
->Width
)) {
2560 BlockData
->Width
= (UINT16
) (NextBlockData
->Offset
+ NextBlockData
->Width
- BlockData
->Offset
);
2562 RemoveEntryList (Link
->ForwardLink
);
2563 FreePool (NextBlockData
);
2566 Link
= Link
->ForwardLink
;
2569 return RequestBlockArray
;
2572 if (RequestBlockArray
!= NULL
) {
2574 // Free Link Array RequestBlockArray
2576 while (!IsListEmpty (&RequestBlockArray
->Entry
)) {
2577 BlockData
= BASE_CR (RequestBlockArray
->Entry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
2578 RemoveEntryList (&BlockData
->Entry
);
2579 FreePool (BlockData
);
2582 FreePool (RequestBlockArray
);
2589 parse the configrequest string, get the elements.
2591 @param ConfigRequest The input config request string.
2592 @param Progress Return the progress data.
2594 @retval return data block array.
2598 IN EFI_STRING ConfigRequest
,
2599 OUT EFI_STRING
*Progress
2602 EFI_STRING StringPtr
;
2604 IFR_BLOCK_DATA
*BlockData
;
2605 IFR_BLOCK_DATA
*RequestBlockArray
;
2608 StringPtr
= ConfigRequest
;
2611 // Init RequestBlockArray
2613 RequestBlockArray
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
2614 if (RequestBlockArray
== NULL
) {
2617 InitializeListHead (&RequestBlockArray
->Entry
);
2620 // Get the request Block array from the request string
2624 // Parse each <RequestElement> if exists
2625 // Only <BlockName> format is supported by this help function.
2626 // <BlockName> ::= &'Name***=***
2628 while (StringPtr
!= NULL
&& *StringPtr
== L
'&') {
2630 *Progress
= StringPtr
;
2632 // Skip the L"&" string
2637 if ((NextTag
= StrStr (StringPtr
, L
"=")) != NULL
) {
2640 } else if ((NextTag
= StrStr (StringPtr
, L
"&")) != NULL
) {
2647 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
2648 if (BlockData
== NULL
) {
2655 BlockData
->Name
= AllocateCopyPool(StrSize (StringPtr
), StringPtr
);
2656 InsertBlockData (&RequestBlockArray
->Entry
, &BlockData
);
2660 // If has value, skip the value.
2662 StringPtr
= NextTag
+ 1;
2664 StringPtr
= StrStr (StringPtr
, L
"&");
2665 } else if (NextTag
!= NULL
) {
2667 // restore the '&' text.
2669 StringPtr
= NextTag
;
2674 return RequestBlockArray
;
2677 if (RequestBlockArray
!= NULL
) {
2679 // Free Link Array RequestBlockArray
2681 while (!IsListEmpty (&RequestBlockArray
->Entry
)) {
2682 BlockData
= BASE_CR (RequestBlockArray
->Entry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
2683 RemoveEntryList (&BlockData
->Entry
);
2684 if (BlockData
->Name
!= NULL
) {
2685 FreePool (BlockData
->Name
);
2687 FreePool (BlockData
);
2690 FreePool (RequestBlockArray
);
2697 Generate ConfigRequest string base on the varstore info.
2699 @param ConfigHdr The config header for this varstore.
2700 @param VarStorageData The varstore info.
2701 @param Status Return Status.
2702 @param ConfigRequest The ConfigRequest info may be return.
2704 @retval TRUE Need to continue
2705 @retval Others NO need to continue or error occur.
2708 GenerateConfigRequest (
2709 IN CHAR16
*ConfigHdr
,
2710 IN IFR_VARSTORAGE_DATA
*VarStorageData
,
2711 OUT EFI_STATUS
*Status
,
2712 IN OUT EFI_STRING
*ConfigRequest
2718 CHAR16
*FullConfigRequest
;
2720 IFR_BLOCK_DATA
*BlockData
;
2723 // Append VarStorageData BlockEntry into *Request string
2724 // Now support only one varstore in a form package.
2728 // Go through all VarStorageData Entry and get BlockEntry for each one for the multiple varstore in a single form package
2729 // Then construct them all to return MultiRequest string : ConfigHdr BlockConfig
2733 // Compute the length of the entire request starting with <ConfigHdr> and a
2737 Length
= StrLen (ConfigHdr
) + 1;
2739 for (Link
= VarStorageData
->BlockEntry
.ForwardLink
; Link
!= &VarStorageData
->BlockEntry
; Link
= Link
->ForwardLink
) {
2741 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
2742 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2744 // Add <BlockName> length for each Name
2746 // <BlockName> ::= &Name1&Name2&...
2747 // |1| StrLen(Name1)
2749 Length
= Length
+ (1 + StrLen (BlockData
->Name
));
2752 // Add <BlockName> length for each Offset/Width pair
2754 // <BlockName> ::= &OFFSET=1234&WIDTH=1234
2755 // | 8 | 4 | 7 | 4 |
2757 Length
= Length
+ (8 + 4 + 7 + 4);
2761 // No any request block data is found. The request string can't be constructed.
2764 *Status
= EFI_SUCCESS
;
2769 // Allocate buffer for the entire <ConfigRequest>
2771 FullConfigRequest
= AllocateZeroPool (Length
* sizeof (CHAR16
));
2772 if (FullConfigRequest
== NULL
) {
2773 *Status
= EFI_OUT_OF_RESOURCES
;
2776 StringPtr
= FullConfigRequest
;
2779 // Start with <ConfigHdr>
2781 StrCpyS (StringPtr
, Length
, ConfigHdr
);
2782 StringPtr
+= StrLen (StringPtr
);
2785 // Loop through all the Offset/Width pairs and append them to ConfigRequest
2787 for (Link
= VarStorageData
->BlockEntry
.ForwardLink
; Link
!= &VarStorageData
->BlockEntry
; Link
= Link
->ForwardLink
) {
2788 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
2789 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2795 (1 + StrLen (BlockData
->Name
) + 1) * sizeof (CHAR16
),
2801 // Append &OFFSET=XXXX&WIDTH=YYYY\0
2805 (8 + 4 + 7 + 4 + 1) * sizeof (CHAR16
),
2806 L
"&OFFSET=%04X&WIDTH=%04X",
2811 StringPtr
+= StrLen (StringPtr
);
2814 // Set to the got full request string.
2816 HiiToLower (FullConfigRequest
);
2818 if (*ConfigRequest
!= NULL
) {
2819 FreePool (*ConfigRequest
);
2821 *ConfigRequest
= FullConfigRequest
;
2827 Generate ConfigRequest Header base on the varstore info.
2829 @param VarStorageData The varstore info.
2830 @param DevicePath Device path for this varstore.
2831 @param ConfigHdr The config header for this varstore.
2833 @retval EFI_SUCCESS Generate the header success.
2834 @retval EFI_OUT_OF_RESOURCES Allocate buffer fail.
2838 IN IFR_VARSTORAGE_DATA
*VarStorageData
,
2839 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
2840 OUT EFI_STRING
*ConfigHdr
2849 Status
= EFI_SUCCESS
;
2855 // Construct <ConfigHdr> : "GUID=...&NAME=...&PATH=..." by VarStorageData Guid, Name and DriverHandle
2857 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*) &VarStorageData
->Guid
, 1, &GuidStr
);
2858 if (VarStorageData
->Name
!= NULL
) {
2859 GenerateSubStr (L
"NAME=", StrLen (VarStorageData
->Name
) * sizeof (CHAR16
), (VOID
*) VarStorageData
->Name
, 2, &NameStr
);
2861 GenerateSubStr (L
"NAME=", 0, NULL
, 2, &NameStr
);
2865 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) DevicePath
),
2866 (VOID
*) DevicePath
,
2870 Length
= StrLen (GuidStr
) + StrLen (NameStr
) + StrLen (PathStr
) + 1;
2871 if (VarStorageData
->Name
== NULL
) {
2875 *ConfigHdr
= AllocateZeroPool (Length
* sizeof (CHAR16
));
2876 if (*ConfigHdr
== NULL
) {
2877 Status
= EFI_OUT_OF_RESOURCES
;
2880 StrCpyS (*ConfigHdr
, Length
, GuidStr
);
2881 StrCatS (*ConfigHdr
, Length
, NameStr
);
2882 if (VarStorageData
->Name
== NULL
) {
2883 StrCatS (*ConfigHdr
, Length
, L
"&");
2885 StrCatS (*ConfigHdr
, Length
, PathStr
);
2888 // Remove the last character L'&'
2890 *(*ConfigHdr
+ StrLen (*ConfigHdr
) - 1) = L
'\0';
2893 if (GuidStr
!= NULL
) {
2897 if (NameStr
!= NULL
) {
2901 if (PathStr
!= NULL
) {
2909 Get Data buffer size based on data type.
2911 @param ValueType The input data type.
2913 @retval The data buffer size for the input type.
2920 UINT16 StorageWidth
;
2922 switch (ValueType
) {
2923 case EFI_IFR_NUMERIC_SIZE_1
:
2924 case EFI_IFR_TYPE_BOOLEAN
:
2925 StorageWidth
= (UINT16
) sizeof (UINT8
);
2928 case EFI_IFR_NUMERIC_SIZE_2
:
2929 StorageWidth
= (UINT16
) sizeof (UINT16
);
2932 case EFI_IFR_NUMERIC_SIZE_4
:
2933 StorageWidth
= (UINT16
) sizeof (UINT32
);
2936 case EFI_IFR_NUMERIC_SIZE_8
:
2937 StorageWidth
= (UINT16
) sizeof (UINT64
);
2940 case EFI_IFR_TYPE_TIME
:
2941 StorageWidth
= (UINT16
) sizeof (EFI_IFR_TIME
);
2944 case EFI_IFR_TYPE_DATE
:
2945 StorageWidth
= (UINT16
) sizeof (EFI_IFR_DATE
);
2953 return StorageWidth
;
2957 Generate ConfigAltResp string base on the varstore info.
2959 @param HiiHandle Hii Handle for this hii package.
2960 @param ConfigHdr The config header for this varstore.
2961 @param VarStorageData The varstore info.
2962 @param DefaultIdArray The Default id array.
2963 @param DefaultAltCfgResp The DefaultAltCfgResp info may be return.
2965 @retval TRUE Need to continue
2966 @retval Others NO need to continue or error occur.
2969 GenerateAltConfigResp (
2970 IN EFI_HII_HANDLE HiiHandle
,
2971 IN CHAR16
*ConfigHdr
,
2972 IN IFR_VARSTORAGE_DATA
*VarStorageData
,
2973 IN IFR_DEFAULT_DATA
*DefaultIdArray
,
2974 IN OUT EFI_STRING
*DefaultAltCfgResp
2980 LIST_ENTRY
*LinkData
;
2981 LIST_ENTRY
*LinkDefault
;
2982 LIST_ENTRY
*ListEntry
;
2984 IFR_BLOCK_DATA
*BlockData
;
2985 IFR_DEFAULT_DATA
*DefaultId
;
2986 IFR_DEFAULT_DATA
*DefaultValueData
;
2989 CHAR16
*DefaultString
;
2993 DefaultString
= NULL
;
2995 // Add length for <ConfigHdr> + '\0'
2997 Length
= StrLen (ConfigHdr
) + 1;
2999 for (Link
= DefaultIdArray
->Entry
.ForwardLink
; Link
!= &DefaultIdArray
->Entry
; Link
= Link
->ForwardLink
) {
3000 DefaultId
= BASE_CR (Link
, IFR_DEFAULT_DATA
, Entry
);
3002 // Add length for "&<ConfigHdr>&ALTCFG=XXXX"
3003 // |1| StrLen (ConfigHdr) | 8 | 4 |
3005 Length
+= (1 + StrLen (ConfigHdr
) + 8 + 4);
3007 for (LinkData
= VarStorageData
->BlockEntry
.ForwardLink
; LinkData
!= &VarStorageData
->BlockEntry
; LinkData
= LinkData
->ForwardLink
) {
3008 BlockData
= BASE_CR (LinkData
, IFR_BLOCK_DATA
, Entry
);
3009 ListEntry
= &BlockData
->DefaultValueEntry
;
3010 for (LinkDefault
= ListEntry
->ForwardLink
; LinkDefault
!= ListEntry
; LinkDefault
= LinkDefault
->ForwardLink
) {
3011 DefaultValueData
= BASE_CR (LinkDefault
, IFR_DEFAULT_DATA
, Entry
);
3012 if (DefaultValueData
->DefaultId
!= DefaultId
->DefaultId
) {
3015 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3017 // Add length for "&Name1=zzzzzzzzzzzz"
3020 Length
+= (1 + StrLen (BlockData
->Name
) + 1 + BlockData
->Width
* 2);
3023 // Add length for "&OFFSET=XXXX&WIDTH=YYYY&VALUE=zzzzzzzzzzzz"
3024 // | 8 | 4 | 7 | 4 | 7 | Width * 2 |
3026 Length
+= (8 + 4 + 7 + 4 + 7 + BlockData
->Width
* 2);
3034 // No default value is found. The default string doesn't exist.
3041 // Allocate buffer for the entire <DefaultAltCfgResp>
3043 *DefaultAltCfgResp
= AllocateZeroPool (Length
* sizeof (CHAR16
));
3044 if (*DefaultAltCfgResp
== NULL
) {
3045 return EFI_OUT_OF_RESOURCES
;
3047 StringPtr
= *DefaultAltCfgResp
;
3050 // Start with <ConfigHdr>
3052 StrCpyS (StringPtr
, Length
, ConfigHdr
);
3053 StringPtr
+= StrLen (StringPtr
);
3055 for (Link
= DefaultIdArray
->Entry
.ForwardLink
; Link
!= &DefaultIdArray
->Entry
; Link
= Link
->ForwardLink
) {
3056 DefaultId
= BASE_CR (Link
, IFR_DEFAULT_DATA
, Entry
);
3058 // Add <AltConfigHdr> of the form "&<ConfigHdr>&ALTCFG=XXXX\0"
3059 // |1| StrLen (ConfigHdr) | 8 | 4 |
3063 (1 + StrLen (ConfigHdr
) + 8 + 4 + 1) * sizeof (CHAR16
),
3066 DefaultId
->DefaultId
3068 StringPtr
+= StrLen (StringPtr
);
3070 for (LinkData
= VarStorageData
->BlockEntry
.ForwardLink
; LinkData
!= &VarStorageData
->BlockEntry
; LinkData
= LinkData
->ForwardLink
) {
3071 BlockData
= BASE_CR (LinkData
, IFR_BLOCK_DATA
, Entry
);
3072 ListEntry
= &BlockData
->DefaultValueEntry
;
3073 for (LinkDefault
= ListEntry
->ForwardLink
; LinkDefault
!= ListEntry
; LinkDefault
= LinkDefault
->ForwardLink
) {
3074 DefaultValueData
= BASE_CR (LinkDefault
, IFR_DEFAULT_DATA
, Entry
);
3075 if (DefaultValueData
->DefaultId
!= DefaultId
->DefaultId
) {
3078 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
3081 (1 + StrLen (ConfigHdr
) + 1) * sizeof (CHAR16
),
3085 StringPtr
+= StrLen (StringPtr
);
3088 // Add <BlockConfig>
3089 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>
3093 (8 + 4 + 7 + 4 + 7 + 1) * sizeof (CHAR16
),
3094 L
"&OFFSET=%04X&WIDTH=%04X&VALUE=",
3098 StringPtr
+= StrLen (StringPtr
);
3100 Width
= BlockData
->Width
;
3102 // Convert Value to a hex string in "%x" format
3103 // NOTE: This is in the opposite byte that GUID and PATH use
3105 if (BlockData
->OpCode
== EFI_IFR_STRING_OP
){
3106 DefaultString
= InternalGetString(HiiHandle
, DefaultValueData
->Value
.string
);
3107 TmpBuffer
= (UINT8
*) DefaultString
;
3109 TmpBuffer
= (UINT8
*) &(DefaultValueData
->Value
);
3111 for (; Width
> 0 && (TmpBuffer
!= NULL
); Width
--) {
3112 StringPtr
+= UnicodeValueToString (StringPtr
, PREFIX_ZERO
| RADIX_HEX
, TmpBuffer
[Width
- 1], 2);
3114 if (DefaultString
!= NULL
){
3115 FreePool(DefaultString
);
3116 DefaultString
= NULL
;
3122 HiiToLower (*DefaultAltCfgResp
);
3128 This function gets the full request string and full default value string by
3129 parsing IFR data in HII form packages.
3131 When Request points to NULL string, the request string and default value string
3132 for each varstore in form package will return.
3134 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
3135 @param DevicePath Device Path which Hii Config Access Protocol is registered.
3136 @param Request Pointer to a null-terminated Unicode string in
3137 <ConfigRequest> format. When it doesn't contain
3138 any RequestElement, it will be updated to return
3139 the full RequestElement retrieved from IFR data.
3140 If it points to NULL, the request string for the first
3141 varstore in form package will be merged into a
3142 <MultiConfigRequest> format string and return.
3143 @param AltCfgResp Pointer to a null-terminated Unicode string in
3144 <ConfigAltResp> format. When the pointer is to NULL,
3145 the full default value string retrieved from IFR data
3146 will return. When the pinter is to a string, the
3147 full default value string retrieved from IFR data
3148 will be merged into the input string and return.
3149 When Request points to NULL, the default value string
3150 for each varstore in form package will be merged into
3151 a <MultiConfigAltResp> format string and return.
3152 @param PointerProgress Optional parameter, it can be be NULL.
3153 When it is not NULL, if Request is NULL, it returns NULL.
3154 On return, points to a character in the Request
3155 string. Points to the string's null terminator if
3156 request was successful. Points to the most recent
3157 & before the first failing name / value pair (or
3158 the beginning of the string if the failure is in
3159 the first name / value pair) if the request was
3161 @retval EFI_SUCCESS The Results string is set to the full request string.
3162 And AltCfgResp contains all default value string.
3163 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
3164 @retval EFI_NOT_FOUND The varstore (Guid and Name) in Request string
3165 can't be found in Form package.
3166 @retval EFI_NOT_FOUND HiiPackage can't be got on the input HiiHandle.
3167 @retval EFI_INVALID_PARAMETER Request points to NULL.
3172 GetFullStringFromHiiFormPackages (
3173 IN HII_DATABASE_RECORD
*DataBaseRecord
,
3174 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
3175 IN OUT EFI_STRING
*Request
,
3176 IN OUT EFI_STRING
*AltCfgResp
,
3177 OUT EFI_STRING
*PointerProgress OPTIONAL
3181 UINT8
*HiiFormPackage
;
3183 IFR_BLOCK_DATA
*RequestBlockArray
;
3184 IFR_BLOCK_DATA
*BlockData
;
3185 IFR_DEFAULT_DATA
*DefaultValueData
;
3186 IFR_DEFAULT_DATA
*DefaultId
;
3187 IFR_DEFAULT_DATA
*DefaultIdArray
;
3188 IFR_VARSTORAGE_DATA
*VarStorageData
;
3189 EFI_STRING DefaultAltCfgResp
;
3190 EFI_STRING ConfigHdr
;
3191 EFI_STRING StringPtr
;
3192 EFI_STRING Progress
;
3194 if (DataBaseRecord
== NULL
|| DevicePath
== NULL
|| Request
== NULL
|| AltCfgResp
== NULL
) {
3195 return EFI_INVALID_PARAMETER
;
3199 // Initialize the local variables.
3201 RequestBlockArray
= NULL
;
3202 DefaultIdArray
= NULL
;
3203 VarStorageData
= NULL
;
3204 DefaultAltCfgResp
= NULL
;
3206 HiiFormPackage
= NULL
;
3208 Progress
= *Request
;
3210 Status
= GetFormPackageData (DataBaseRecord
, &HiiFormPackage
, &PackageSize
);
3211 if (EFI_ERROR (Status
)) {
3216 // 1. Get the request block array by Request String when Request string containts the block array.
3219 if (*Request
!= NULL
) {
3220 StringPtr
= *Request
;
3224 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
3225 Status
= EFI_INVALID_PARAMETER
;
3228 StringPtr
+= StrLen (L
"GUID=");
3229 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&NAME=", StrLen (L
"&NAME=")) != 0) {
3232 if (*StringPtr
== L
'\0') {
3233 Status
= EFI_INVALID_PARAMETER
;
3236 StringPtr
+= StrLen (L
"&NAME=");
3237 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&PATH=", StrLen (L
"&PATH=")) != 0) {
3240 if (*StringPtr
== L
'\0') {
3241 Status
= EFI_INVALID_PARAMETER
;
3244 StringPtr
+= StrLen (L
"&PATH=");
3245 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
3249 if (*StringPtr
== L
'\0') {
3251 // No request block is found.
3258 // If StringPtr != NULL, get the request elements.
3260 if (StringPtr
!= NULL
) {
3261 if (StrStr (StringPtr
, L
"&OFFSET=") != NULL
) {
3262 RequestBlockArray
= GetBlockElement(StringPtr
, &Progress
);
3264 RequestBlockArray
= GetNameElement(StringPtr
, &Progress
);
3267 if (RequestBlockArray
== NULL
) {
3268 Status
= EFI_INVALID_PARAMETER
;
3274 // Initialize DefaultIdArray to store the map between DeaultId and DefaultName
3276 DefaultIdArray
= (IFR_DEFAULT_DATA
*) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
3277 if (DefaultIdArray
== NULL
) {
3278 Status
= EFI_OUT_OF_RESOURCES
;
3281 InitializeListHead (&DefaultIdArray
->Entry
);
3284 // Initialize VarStorageData to store the var store Block and Default value information.
3286 VarStorageData
= (IFR_VARSTORAGE_DATA
*) AllocateZeroPool (sizeof (IFR_VARSTORAGE_DATA
));
3287 if (VarStorageData
== NULL
) {
3288 Status
= EFI_OUT_OF_RESOURCES
;
3291 InitializeListHead (&VarStorageData
->Entry
);
3292 InitializeListHead (&VarStorageData
->BlockEntry
);
3295 // 2. Parse FormPackage to get BlockArray and DefaultId Array for the request BlockArray.
3299 // Parse the opcode in form pacakge to get the default setting.
3301 Status
= ParseIfrData (DataBaseRecord
->Handle
,
3303 (UINT32
) PackageSize
,
3308 if (EFI_ERROR (Status
)) {
3313 // No requested varstore in IFR data and directly return
3315 if (VarStorageData
->Type
== 0 && VarStorageData
->Name
== NULL
) {
3316 Status
= EFI_SUCCESS
;
3321 // 3. Construct Request Element (Block Name) for 2.1 and 2.2 case.
3323 Status
= GenerateHdr (VarStorageData
, DevicePath
, &ConfigHdr
);
3324 if (EFI_ERROR (Status
)) {
3328 if (RequestBlockArray
== NULL
) {
3329 if (!GenerateConfigRequest(ConfigHdr
, VarStorageData
, &Status
, Request
)) {
3335 // 4. Construct Default Value string in AltResp according to request element.
3336 // Go through all VarStorageData Entry and get the DefaultId array for each one
3337 // Then construct them all to : ConfigHdr AltConfigHdr ConfigBody AltConfigHdr ConfigBody
3339 Status
= GenerateAltConfigResp (DataBaseRecord
->Handle
,ConfigHdr
, VarStorageData
, DefaultIdArray
, &DefaultAltCfgResp
);
3340 if (EFI_ERROR (Status
)) {
3345 // 5. Merge string into the input AltCfgResp if the iput *AltCfgResp is not NULL.
3347 if (*AltCfgResp
!= NULL
&& DefaultAltCfgResp
!= NULL
) {
3348 Status
= MergeDefaultString (AltCfgResp
, DefaultAltCfgResp
);
3349 FreePool (DefaultAltCfgResp
);
3350 } else if (*AltCfgResp
== NULL
) {
3351 *AltCfgResp
= DefaultAltCfgResp
;
3355 if (RequestBlockArray
!= NULL
) {
3357 // Free Link Array RequestBlockArray
3359 while (!IsListEmpty (&RequestBlockArray
->Entry
)) {
3360 BlockData
= BASE_CR (RequestBlockArray
->Entry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
3361 RemoveEntryList (&BlockData
->Entry
);
3362 if (BlockData
->Name
!= NULL
) {
3363 FreePool (BlockData
->Name
);
3365 FreePool (BlockData
);
3368 FreePool (RequestBlockArray
);
3371 if (VarStorageData
!= NULL
) {
3373 // Free link array VarStorageData
3375 while (!IsListEmpty (&VarStorageData
->BlockEntry
)) {
3376 BlockData
= BASE_CR (VarStorageData
->BlockEntry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
3377 RemoveEntryList (&BlockData
->Entry
);
3378 if (BlockData
->Name
!= NULL
) {
3379 FreePool (BlockData
->Name
);
3382 // Free default value link array
3384 while (!IsListEmpty (&BlockData
->DefaultValueEntry
)) {
3385 DefaultValueData
= BASE_CR (BlockData
->DefaultValueEntry
.ForwardLink
, IFR_DEFAULT_DATA
, Entry
);
3386 RemoveEntryList (&DefaultValueData
->Entry
);
3387 FreePool (DefaultValueData
);
3389 FreePool (BlockData
);
3391 FreePool (VarStorageData
);
3394 if (DefaultIdArray
!= NULL
) {
3396 // Free DefaultId Array
3398 while (!IsListEmpty (&DefaultIdArray
->Entry
)) {
3399 DefaultId
= BASE_CR (DefaultIdArray
->Entry
.ForwardLink
, IFR_DEFAULT_DATA
, Entry
);
3400 RemoveEntryList (&DefaultId
->Entry
);
3401 FreePool (DefaultId
);
3403 FreePool (DefaultIdArray
);
3407 // Free the allocated string
3409 if (ConfigHdr
!= NULL
) {
3410 FreePool (ConfigHdr
);
3414 // Free Pacakge data
3416 if (HiiFormPackage
!= NULL
) {
3417 FreePool (HiiFormPackage
);
3420 if (PointerProgress
!= NULL
) {
3421 if (*Request
== NULL
) {
3422 *PointerProgress
= NULL
;
3423 } else if (EFI_ERROR (Status
)) {
3424 *PointerProgress
= *Request
;
3426 *PointerProgress
= *Request
+ StrLen (*Request
);
3434 This function gets the full request resp string by
3435 parsing IFR data in HII form packages.
3437 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
3439 @param EfiVarStoreInfo The efi varstore info which is save in the EFI
3440 varstore data structure.
3441 @param Request Pointer to a null-terminated Unicode string in
3442 <ConfigRequest> format.
3443 @param RequestResp Pointer to a null-terminated Unicode string in
3444 <ConfigResp> format.
3445 @param AccessProgress On return, points to a character in the Request
3446 string. Points to the string's null terminator if
3447 request was successful. Points to the most recent
3448 & before the first failing name / value pair (or
3449 the beginning of the string if the failure is in
3450 the first name / value pair) if the request was
3453 @retval EFI_SUCCESS The Results string is set to the full request string.
3454 And AltCfgResp contains all default value string.
3455 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
3456 @retval EFI_INVALID_PARAMETER Request points to NULL.
3460 GetConfigRespFromEfiVarStore (
3461 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
3462 IN EFI_IFR_VARSTORE_EFI
*EfiVarStoreInfo
,
3463 IN EFI_STRING Request
,
3464 OUT EFI_STRING
*RequestResp
,
3465 OUT EFI_STRING
*AccessProgress
3469 EFI_STRING VarStoreName
;
3473 Status
= EFI_SUCCESS
;
3476 VarStoreName
= NULL
;
3477 *AccessProgress
= Request
;
3479 VarStoreName
= AllocateZeroPool (AsciiStrSize ((CHAR8
*)EfiVarStoreInfo
->Name
) * sizeof (CHAR16
));
3480 if (VarStoreName
== NULL
) {
3481 Status
= EFI_OUT_OF_RESOURCES
;
3484 AsciiStrToUnicodeStr ((CHAR8
*) EfiVarStoreInfo
->Name
, VarStoreName
);
3487 Status
= gRT
->GetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, NULL
, &BufferSize
, NULL
);
3488 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
3492 VarStore
= AllocateZeroPool (BufferSize
);
3493 ASSERT (VarStore
!= NULL
);
3494 Status
= gRT
->GetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, NULL
, &BufferSize
, VarStore
);
3495 if (EFI_ERROR (Status
)) {
3499 Status
= HiiBlockToConfig(This
, Request
, VarStore
, BufferSize
, RequestResp
, AccessProgress
);
3500 if (EFI_ERROR (Status
)) {
3505 if (VarStoreName
!= NULL
) {
3506 FreePool (VarStoreName
);
3509 if (VarStore
!= NULL
) {
3510 FreePool (VarStore
);
3518 This function route the full request resp string for efi varstore.
3520 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
3522 @param EfiVarStoreInfo The efi varstore info which is save in the EFI
3523 varstore data structure.
3524 @param RequestResp Pointer to a null-terminated Unicode string in
3525 <ConfigResp> format.
3526 @param Result Pointer to a null-terminated Unicode string in
3527 <ConfigResp> format.
3529 @retval EFI_SUCCESS The Results string is set to the full request string.
3530 And AltCfgResp contains all default value string.
3531 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
3532 @retval EFI_INVALID_PARAMETER Request points to NULL.
3536 RouteConfigRespForEfiVarStore (
3537 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
3538 IN EFI_IFR_VARSTORE_EFI
*EfiVarStoreInfo
,
3539 IN EFI_STRING RequestResp
,
3540 OUT EFI_STRING
*Result
3544 EFI_STRING VarStoreName
;
3549 Status
= EFI_SUCCESS
;
3552 VarStoreName
= NULL
;
3554 VarStoreName
= AllocateZeroPool (AsciiStrSize ((CHAR8
*)EfiVarStoreInfo
->Name
) * sizeof (CHAR16
));
3555 if (VarStoreName
== NULL
) {
3556 Status
= EFI_OUT_OF_RESOURCES
;
3559 AsciiStrToUnicodeStr ((CHAR8
*) EfiVarStoreInfo
->Name
, VarStoreName
);
3561 Status
= gRT
->GetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, NULL
, &BufferSize
, NULL
);
3562 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
3566 BlockSize
= BufferSize
;
3567 VarStore
= AllocateZeroPool (BufferSize
);
3568 ASSERT (VarStore
!= NULL
);
3569 Status
= gRT
->GetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, NULL
, &BufferSize
, VarStore
);
3570 if (EFI_ERROR (Status
)) {
3574 Status
= HiiConfigToBlock(This
, RequestResp
, VarStore
, &BlockSize
, Result
);
3575 if (EFI_ERROR (Status
)) {
3579 Status
= gRT
->SetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, EfiVarStoreInfo
->Attributes
, BufferSize
, VarStore
);
3580 if (EFI_ERROR (Status
)) {
3585 if (VarStoreName
!= NULL
) {
3586 FreePool (VarStoreName
);
3589 if (VarStore
!= NULL
) {
3590 FreePool (VarStore
);
3597 Validate the config request elements.
3599 @param ConfigElements A null-terminated Unicode string in <ConfigRequest> format,
3600 without configHdr field.
3602 @retval CHAR16 * THE first Name/value pair not correct.
3603 @retval NULL Success parse the name/value pair
3606 OffsetWidthValidate (
3607 CHAR16
*ConfigElements
3613 StringPtr
= ConfigElements
;
3617 if (StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) != 0) {
3621 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
3624 if (*StringPtr
== L
'\0') {
3628 StringPtr
+= StrLen (L
"&WIDTH=");
3629 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) != 0) {
3633 if (*StringPtr
== L
'\0') {
3640 Validate the config request elements.
3642 @param ConfigElements A null-terminated Unicode string in <ConfigRequest> format,
3643 without configHdr field.
3645 @retval CHAR16 * THE first Name/value pair not correct.
3646 @retval NULL Success parse the name/value pair
3651 CHAR16
*ConfigElements
3657 StringPtr
= ConfigElements
;
3661 if (*StringPtr
!= L
'&') {
3666 StringPtr
= StrStr (StringPtr
, L
"&");
3668 if (StringPtr
== NULL
) {
3675 Validate the config request string.
3677 @param ConfigRequest A null-terminated Unicode string in <ConfigRequest> format.
3679 @retval CHAR16 * THE first element not correct.
3680 @retval NULL Success parse the name/value pair
3684 ConfigRequestValidate (
3685 CHAR16
*ConfigRequest
3688 BOOLEAN HasNameField
;
3691 HasNameField
= TRUE
;
3692 StringPtr
= ConfigRequest
;
3695 // Check <ConfigHdr>
3697 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
3698 return ConfigRequest
;
3700 StringPtr
+= StrLen (L
"GUID=");
3701 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&NAME=", StrLen (L
"&NAME=")) != 0) {
3704 if (*StringPtr
== L
'\0') {
3705 return ConfigRequest
;
3707 StringPtr
+= StrLen (L
"&NAME=");
3708 if (*StringPtr
== L
'&') {
3709 HasNameField
= FALSE
;
3711 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&PATH=", StrLen (L
"&PATH=")) != 0) {
3714 if (*StringPtr
== L
'\0') {
3715 return ConfigRequest
;
3717 StringPtr
+= StrLen (L
"&PATH=");
3718 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
3722 if (*StringPtr
== L
'\0') {
3728 // Should be Buffer varstore, config request should be "OFFSET/Width" pairs.
3730 return OffsetWidthValidate(StringPtr
);
3733 // Should be Name/Value varstore, config request should be "&name1&name2..." pairs.
3735 return NameValueValidate(StringPtr
);
3740 This function allows a caller to extract the current configuration
3741 for one or more named elements from one or more drivers.
3743 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
3745 @param Request A null-terminated Unicode string in
3746 <MultiConfigRequest> format.
3747 @param Progress On return, points to a character in the Request
3748 string. Points to the string's null terminator if
3749 request was successful. Points to the most recent
3750 & before the first failing name / value pair (or
3751 the beginning of the string if the failure is in
3752 the first name / value pair) if the request was
3754 @param Results Null-terminated Unicode string in
3755 <MultiConfigAltResp> format which has all values
3756 filled in for the names in the Request string.
3757 String to be allocated by the called function.
3759 @retval EFI_SUCCESS The Results string is filled with the values
3760 corresponding to all requested names.
3761 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
3762 results that must be stored awaiting possible
3764 @retval EFI_NOT_FOUND Routing data doesn't match any known driver.
3765 Progress set to the "G" in "GUID" of the routing
3766 header that doesn't match. Note: There is no
3767 requirement that all routing data be validated
3768 before any configuration extraction.
3769 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Request
3770 parameter would result in this type of error. The
3771 Progress parameter is set to NULL.
3772 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set to most recent &
3773 before the error or the beginning of the string.
3774 @retval EFI_INVALID_PARAMETER The ExtractConfig function of the underlying HII
3775 Configuration Access Protocol returned
3776 EFI_INVALID_PARAMETER. Progress set to most recent
3777 & before the error or the beginning of the string.
3782 HiiConfigRoutingExtractConfig (
3783 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
3784 IN CONST EFI_STRING Request
,
3785 OUT EFI_STRING
*Progress
,
3786 OUT EFI_STRING
*Results
3789 HII_DATABASE_PRIVATE_DATA
*Private
;
3790 EFI_STRING StringPtr
;
3791 EFI_STRING ConfigRequest
;
3793 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
3794 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
3797 HII_DATABASE_RECORD
*Database
;
3798 UINT8
*DevicePathPkg
;
3799 UINT8
*CurrentDevicePath
;
3800 EFI_HANDLE DriverHandle
;
3801 EFI_HII_HANDLE HiiHandle
;
3802 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
3803 EFI_STRING AccessProgress
;
3804 EFI_STRING AccessResults
;
3805 EFI_STRING DefaultResults
;
3806 BOOLEAN FirstElement
;
3807 BOOLEAN IfrDataParsedFlag
;
3808 BOOLEAN IsEfiVarStore
;
3809 EFI_IFR_VARSTORE_EFI
*EfiVarStoreInfo
;
3810 EFI_STRING ErrorPtr
;
3811 UINTN DevicePathSize
;
3813 if (This
== NULL
|| Progress
== NULL
|| Results
== NULL
) {
3814 return EFI_INVALID_PARAMETER
;
3817 if (Request
== NULL
) {
3819 return EFI_INVALID_PARAMETER
;
3822 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
3823 StringPtr
= Request
;
3824 *Progress
= StringPtr
;
3825 DefaultResults
= NULL
;
3826 ConfigRequest
= NULL
;
3827 Status
= EFI_SUCCESS
;
3828 AccessResults
= NULL
;
3829 AccessProgress
= NULL
;
3831 IfrDataParsedFlag
= FALSE
;
3832 IsEfiVarStore
= FALSE
;
3833 EfiVarStoreInfo
= NULL
;
3836 // The first element of <MultiConfigRequest> should be
3837 // <GuidHdr>, which is in 'GUID='<Guid> syntax.
3839 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
3840 return EFI_INVALID_PARAMETER
;
3843 FirstElement
= TRUE
;
3846 // Allocate a fix length of memory to store Results. Reallocate memory for
3847 // Results if this fix length is insufficient.
3849 *Results
= (EFI_STRING
) AllocateZeroPool (MAX_STRING_LENGTH
);
3850 if (*Results
== NULL
) {
3851 return EFI_OUT_OF_RESOURCES
;
3854 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) == 0) {
3856 // If parsing error, set Progress to the beginning of the <MultiConfigRequest>
3857 // or most recent & before the error.
3859 if (StringPtr
== Request
) {
3860 *Progress
= StringPtr
;
3862 *Progress
= StringPtr
- 1;
3866 // Process each <ConfigRequest> of <MultiConfigRequest>
3868 Length
= CalculateConfigStringLen (StringPtr
);
3869 ConfigRequest
= AllocateCopyPool ((Length
+ 1) * sizeof (CHAR16
), StringPtr
);
3870 if (ConfigRequest
== NULL
) {
3871 Status
= EFI_OUT_OF_RESOURCES
;
3874 *(ConfigRequest
+ Length
) = 0;
3877 // Get the UEFI device path
3879 Status
= GetDevicePath (ConfigRequest
, (UINT8
**) &DevicePath
);
3880 if (EFI_ERROR (Status
)) {
3885 // Find driver which matches the routing data.
3887 DriverHandle
= NULL
;
3890 for (Link
= Private
->DatabaseList
.ForwardLink
;
3891 Link
!= &Private
->DatabaseList
;
3892 Link
= Link
->ForwardLink
3894 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
3895 if ((DevicePathPkg
= Database
->PackageList
->DevicePathPkg
) != NULL
) {
3896 CurrentDevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
3897 DevicePathSize
= GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) CurrentDevicePath
);
3898 if ((CompareMem (DevicePath
,CurrentDevicePath
,DevicePathSize
) == 0) && IsThisPackageList(Database
, ConfigRequest
)) {
3899 DriverHandle
= Database
->DriverHandle
;
3900 HiiHandle
= Database
->Handle
;
3907 // Try to find driver handle by device path.
3909 if (DriverHandle
== NULL
) {
3910 TempDevicePath
= DevicePath
;
3911 Status
= gBS
->LocateDevicePath (
3912 &gEfiDevicePathProtocolGuid
,
3916 if (EFI_ERROR (Status
) || (DriverHandle
== NULL
)) {
3918 // Routing data does not match any known driver.
3919 // Set Progress to the 'G' in "GUID" of the routing header.
3921 *Progress
= StringPtr
;
3922 Status
= EFI_NOT_FOUND
;
3928 // Validate ConfigRequest String.
3930 ErrorPtr
= ConfigRequestValidate(ConfigRequest
);
3931 if (ErrorPtr
!= NULL
) {
3932 *Progress
= StrStr (StringPtr
, ErrorPtr
);
3933 Status
= EFI_INVALID_PARAMETER
;
3938 // Check whether ConfigRequest contains request string.
3940 IfrDataParsedFlag
= FALSE
;
3941 if ((HiiHandle
!= NULL
) && !GetElementsFromRequest(ConfigRequest
)) {
3943 // Get the full request string from IFR when HiiPackage is registered to HiiHandle
3945 IfrDataParsedFlag
= TRUE
;
3946 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &ConfigRequest
, &DefaultResults
, &AccessProgress
);
3947 if (EFI_ERROR (Status
)) {
3949 // AccessProgress indicates the parsing progress on <ConfigRequest>.
3950 // Map it to the progress on <MultiConfigRequest> then return it.
3952 ASSERT (AccessProgress
!= NULL
);
3953 *Progress
= StrStr (StringPtr
, AccessProgress
);
3957 // Not any request block is found.
3959 if (!GetElementsFromRequest(ConfigRequest
)) {
3960 AccessResults
= AllocateCopyPool (StrSize (ConfigRequest
), ConfigRequest
);
3961 goto NextConfigString
;
3966 // Check whether this ConfigRequest is search from Efi varstore type storage.
3968 Status
= GetVarStoreType(Database
, ConfigRequest
, &IsEfiVarStore
, &EfiVarStoreInfo
);
3969 if (EFI_ERROR (Status
)) {
3973 if (IsEfiVarStore
) {
3975 // Call the GetVariable function to extract settings.
3977 Status
= GetConfigRespFromEfiVarStore(This
, EfiVarStoreInfo
, ConfigRequest
, &AccessResults
, &AccessProgress
);
3978 FreePool (EfiVarStoreInfo
);
3981 // Call corresponding ConfigAccess protocol to extract settings
3983 Status
= gBS
->HandleProtocol (
3985 &gEfiHiiConfigAccessProtocolGuid
,
3986 (VOID
**) &ConfigAccess
3988 if (EFI_ERROR (Status
)) {
3992 Status
= ConfigAccess
->ExtractConfig (
3999 if (EFI_ERROR (Status
)) {
4001 // AccessProgress indicates the parsing progress on <ConfigRequest>.
4002 // Map it to the progress on <MultiConfigRequest> then return it.
4004 *Progress
= StrStr (StringPtr
, AccessProgress
);
4009 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'
4010 // which seperates the first <ConfigAltResp> and the following ones.
4012 ASSERT (*AccessProgress
== 0);
4015 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
4017 if (!IfrDataParsedFlag
&& HiiHandle
!= NULL
) {
4018 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &ConfigRequest
, &DefaultResults
, NULL
);
4019 ASSERT_EFI_ERROR (Status
);
4022 FreePool (DevicePath
);
4025 if (DefaultResults
!= NULL
) {
4026 Status
= MergeDefaultString (&AccessResults
, DefaultResults
);
4027 ASSERT_EFI_ERROR (Status
);
4028 FreePool (DefaultResults
);
4029 DefaultResults
= NULL
;
4033 if (!FirstElement
) {
4034 Status
= AppendToMultiString (Results
, L
"&");
4035 ASSERT_EFI_ERROR (Status
);
4038 Status
= AppendToMultiString (Results
, AccessResults
);
4039 ASSERT_EFI_ERROR (Status
);
4041 FirstElement
= FALSE
;
4043 FreePool (AccessResults
);
4044 AccessResults
= NULL
;
4045 FreePool (ConfigRequest
);
4046 ConfigRequest
= NULL
;
4049 // Go to next <ConfigRequest> (skip '&').
4051 StringPtr
+= Length
;
4052 if (*StringPtr
== 0) {
4053 *Progress
= StringPtr
;
4061 if (EFI_ERROR (Status
)) {
4062 FreePool (*Results
);
4066 if (ConfigRequest
!= NULL
) {
4067 FreePool (ConfigRequest
);
4070 if (AccessResults
!= NULL
) {
4071 FreePool (AccessResults
);
4074 if (DefaultResults
!= NULL
) {
4075 FreePool (DefaultResults
);
4078 if (DevicePath
!= NULL
) {
4079 FreePool (DevicePath
);
4087 This function allows the caller to request the current configuration for the
4088 entirety of the current HII database and returns the data in a
4089 null-terminated Unicode string.
4091 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
4093 @param Results Null-terminated Unicode string in
4094 <MultiConfigAltResp> format which has all values
4095 filled in for the entirety of the current HII
4096 database. String to be allocated by the called
4097 function. De-allocation is up to the caller.
4099 @retval EFI_SUCCESS The Results string is filled with the values
4100 corresponding to all requested names.
4101 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
4102 results that must be stored awaiting possible
4104 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Results
4105 parameter would result in this type of error.
4110 HiiConfigRoutingExportConfig (
4111 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
4112 OUT EFI_STRING
*Results
4116 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
4117 EFI_STRING AccessResults
;
4118 EFI_STRING Progress
;
4119 EFI_STRING StringPtr
;
4120 EFI_STRING ConfigRequest
;
4122 EFI_HANDLE
*ConfigAccessHandles
;
4123 UINTN NumberConfigAccessHandles
;
4124 BOOLEAN FirstElement
;
4125 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
4126 EFI_HII_HANDLE HiiHandle
;
4127 EFI_STRING DefaultResults
;
4128 HII_DATABASE_PRIVATE_DATA
*Private
;
4130 HII_DATABASE_RECORD
*Database
;
4131 UINT8
*DevicePathPkg
;
4132 UINT8
*CurrentDevicePath
;
4133 BOOLEAN IfrDataParsedFlag
;
4135 if (This
== NULL
|| Results
== NULL
) {
4136 return EFI_INVALID_PARAMETER
;
4139 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
4142 // Allocate a fix length of memory to store Results. Reallocate memory for
4143 // Results if this fix length is insufficient.
4145 *Results
= (EFI_STRING
) AllocateZeroPool (MAX_STRING_LENGTH
);
4146 if (*Results
== NULL
) {
4147 return EFI_OUT_OF_RESOURCES
;
4150 NumberConfigAccessHandles
= 0;
4151 Status
= gBS
->LocateHandleBuffer (
4153 &gEfiHiiConfigAccessProtocolGuid
,
4155 &NumberConfigAccessHandles
,
4156 &ConfigAccessHandles
4158 if (EFI_ERROR (Status
)) {
4162 FirstElement
= TRUE
;
4164 for (Index
= 0; Index
< NumberConfigAccessHandles
; Index
++) {
4165 Status
= gBS
->HandleProtocol (
4166 ConfigAccessHandles
[Index
],
4167 &gEfiHiiConfigAccessProtocolGuid
,
4168 (VOID
**) &ConfigAccess
4170 if (EFI_ERROR (Status
)) {
4175 // Get DevicePath and HiiHandle for this ConfigAccess driver handle
4177 IfrDataParsedFlag
= FALSE
;
4180 DefaultResults
= NULL
;
4182 ConfigRequest
= NULL
;
4183 DevicePath
= DevicePathFromHandle (ConfigAccessHandles
[Index
]);
4184 if (DevicePath
!= NULL
) {
4185 for (Link
= Private
->DatabaseList
.ForwardLink
;
4186 Link
!= &Private
->DatabaseList
;
4187 Link
= Link
->ForwardLink
4189 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
4190 if ((DevicePathPkg
= Database
->PackageList
->DevicePathPkg
) != NULL
) {
4191 CurrentDevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
4195 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) CurrentDevicePath
)
4197 HiiHandle
= Database
->Handle
;
4204 Status
= ConfigAccess
->ExtractConfig (
4210 if (EFI_ERROR (Status
)) {
4212 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
4214 if (HiiHandle
!= NULL
&& DevicePath
!= NULL
) {
4215 IfrDataParsedFlag
= TRUE
;
4216 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &ConfigRequest
, &DefaultResults
, NULL
);
4218 // Get the full request string to get the Current setting again.
4220 if (!EFI_ERROR (Status
) && ConfigRequest
!= NULL
) {
4221 Status
= ConfigAccess
->ExtractConfig (
4227 FreePool (ConfigRequest
);
4229 Status
= EFI_NOT_FOUND
;
4234 if (!EFI_ERROR (Status
)) {
4236 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
4238 if (!IfrDataParsedFlag
&& HiiHandle
!= NULL
&& DevicePath
!= NULL
) {
4239 StringPtr
= StrStr (AccessResults
, L
"&GUID=");
4240 if (StringPtr
!= NULL
) {
4243 if (GetElementsFromRequest (AccessResults
)) {
4244 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &AccessResults
, &DefaultResults
, NULL
);
4245 ASSERT_EFI_ERROR (Status
);
4247 if (StringPtr
!= NULL
) {
4252 // Merge the default sting from IFR code into the got setting from driver.
4254 if (DefaultResults
!= NULL
) {
4255 Status
= MergeDefaultString (&AccessResults
, DefaultResults
);
4256 ASSERT_EFI_ERROR (Status
);
4257 FreePool (DefaultResults
);
4258 DefaultResults
= NULL
;
4262 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'
4263 // which seperates the first <ConfigAltResp> and the following ones.
4265 if (!FirstElement
) {
4266 Status
= AppendToMultiString (Results
, L
"&");
4267 ASSERT_EFI_ERROR (Status
);
4270 Status
= AppendToMultiString (Results
, AccessResults
);
4271 ASSERT_EFI_ERROR (Status
);
4273 FirstElement
= FALSE
;
4275 FreePool (AccessResults
);
4276 AccessResults
= NULL
;
4279 FreePool (ConfigAccessHandles
);
4286 This function processes the results of processing forms and routes it to the
4287 appropriate handlers or storage.
4289 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
4291 @param Configuration A null-terminated Unicode string in
4292 <MulltiConfigResp> format.
4293 @param Progress A pointer to a string filled in with the offset of
4294 the most recent & before the first failing name /
4295 value pair (or the beginning of the string if the
4296 failure is in the first name / value pair) or the
4297 terminating NULL if all was successful.
4299 @retval EFI_SUCCESS The results have been distributed or are awaiting
4301 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
4302 results that must be stored awaiting possible
4304 @retval EFI_INVALID_PARAMETER Passing in a NULL for the Configuration parameter
4305 would result in this type of error.
4306 @retval EFI_NOT_FOUND Target for the specified routing data was not
4312 HiiConfigRoutingRouteConfig (
4313 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
4314 IN CONST EFI_STRING Configuration
,
4315 OUT EFI_STRING
*Progress
4318 HII_DATABASE_PRIVATE_DATA
*Private
;
4319 EFI_STRING StringPtr
;
4320 EFI_STRING ConfigResp
;
4323 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
4324 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
4326 HII_DATABASE_RECORD
*Database
;
4327 UINT8
*DevicePathPkg
;
4328 UINT8
*CurrentDevicePath
;
4329 EFI_HANDLE DriverHandle
;
4330 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
4331 EFI_STRING AccessProgress
;
4332 EFI_IFR_VARSTORE_EFI
*EfiVarStoreInfo
;
4333 BOOLEAN IsEfiVarstore
;
4334 UINTN DevicePathSize
;
4336 if (This
== NULL
|| Progress
== NULL
) {
4337 return EFI_INVALID_PARAMETER
;
4340 if (Configuration
== NULL
) {
4342 return EFI_INVALID_PARAMETER
;
4345 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
4346 StringPtr
= Configuration
;
4347 *Progress
= StringPtr
;
4349 AccessProgress
= NULL
;
4350 EfiVarStoreInfo
= NULL
;
4351 IsEfiVarstore
= FALSE
;
4354 // The first element of <MultiConfigResp> should be
4355 // <GuidHdr>, which is in 'GUID='<Guid> syntax.
4357 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
4358 return EFI_INVALID_PARAMETER
;
4361 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) == 0) {
4363 // If parsing error, set Progress to the beginning of the <MultiConfigResp>
4364 // or most recent & before the error.
4366 if (StringPtr
== Configuration
) {
4367 *Progress
= StringPtr
;
4369 *Progress
= StringPtr
- 1;
4373 // Process each <ConfigResp> of <MultiConfigResp>
4375 Length
= CalculateConfigStringLen (StringPtr
);
4376 ConfigResp
= AllocateCopyPool ((Length
+ 1) * sizeof (CHAR16
), StringPtr
);
4377 if (ConfigResp
== NULL
) {
4378 return EFI_OUT_OF_RESOURCES
;
4381 // Append '\0' to the end of ConfigRequest
4383 *(ConfigResp
+ Length
) = 0;
4386 // Get the UEFI device path
4388 Status
= GetDevicePath (ConfigResp
, (UINT8
**) &DevicePath
);
4389 if (EFI_ERROR (Status
)) {
4390 FreePool (ConfigResp
);
4395 // Find driver which matches the routing data.
4397 DriverHandle
= NULL
;
4398 for (Link
= Private
->DatabaseList
.ForwardLink
;
4399 Link
!= &Private
->DatabaseList
;
4400 Link
= Link
->ForwardLink
4402 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
4404 if ((DevicePathPkg
= Database
->PackageList
->DevicePathPkg
) != NULL
) {
4405 CurrentDevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
4406 DevicePathSize
= GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) CurrentDevicePath
);
4407 if ((CompareMem (DevicePath
,CurrentDevicePath
,DevicePathSize
) == 0) && IsThisPackageList(Database
, ConfigResp
)) {
4408 DriverHandle
= Database
->DriverHandle
;
4415 // Try to find driver handle by device path.
4417 if (DriverHandle
== NULL
) {
4418 TempDevicePath
= DevicePath
;
4419 Status
= gBS
->LocateDevicePath (
4420 &gEfiDevicePathProtocolGuid
,
4424 if (EFI_ERROR (Status
) || (DriverHandle
== NULL
)) {
4426 // Routing data does not match any known driver.
4427 // Set Progress to the 'G' in "GUID" of the routing header.
4429 FreePool (DevicePath
);
4430 *Progress
= StringPtr
;
4431 FreePool (ConfigResp
);
4432 return EFI_NOT_FOUND
;
4436 FreePool (DevicePath
);
4439 // Check whether this ConfigRequest is search from Efi varstore type storage.
4441 Status
= GetVarStoreType(Database
, ConfigResp
, &IsEfiVarstore
, &EfiVarStoreInfo
);
4442 if (EFI_ERROR (Status
)) {
4446 if (IsEfiVarstore
) {
4448 // Call the SetVariable function to route settings.
4450 Status
= RouteConfigRespForEfiVarStore(This
, EfiVarStoreInfo
, ConfigResp
, &AccessProgress
);
4451 FreePool (EfiVarStoreInfo
);
4454 // Call corresponding ConfigAccess protocol to route settings
4456 Status
= gBS
->HandleProtocol (
4458 &gEfiHiiConfigAccessProtocolGuid
,
4459 (VOID
**) &ConfigAccess
4461 if (EFI_ERROR (Status
)) {
4462 *Progress
= StringPtr
;
4463 FreePool (ConfigResp
);
4464 return EFI_NOT_FOUND
;
4467 Status
= ConfigAccess
->RouteConfig (
4473 if (EFI_ERROR (Status
)) {
4474 ASSERT (AccessProgress
!= NULL
);
4476 // AccessProgress indicates the parsing progress on <ConfigResp>.
4477 // Map it to the progress on <MultiConfigResp> then return it.
4479 *Progress
= StrStr (StringPtr
, AccessProgress
);
4481 FreePool (ConfigResp
);
4485 FreePool (ConfigResp
);
4489 // Go to next <ConfigResp> (skip '&').
4491 StringPtr
+= Length
;
4492 if (*StringPtr
== 0) {
4493 *Progress
= StringPtr
;
4506 This helper function is to be called by drivers to map configuration data
4507 stored in byte array ("block") formats such as UEFI Variables into current
4508 configuration strings.
4510 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
4512 @param ConfigRequest A null-terminated Unicode string in
4513 <ConfigRequest> format.
4514 @param Block Array of bytes defining the block's configuration.
4515 @param BlockSize Length in bytes of Block.
4516 @param Config Filled-in configuration string. String allocated
4517 by the function. Returned only if call is
4518 successful. It is <ConfigResp> string format.
4519 @param Progress A pointer to a string filled in with the offset of
4520 the most recent & before the first failing
4521 name/value pair (or the beginning of the string if
4522 the failure is in the first name / value pair) or
4523 the terminating NULL if all was successful.
4525 @retval EFI_SUCCESS The request succeeded. Progress points to the null
4526 terminator at the end of the ConfigRequest
4528 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress
4529 points to the first character of ConfigRequest.
4530 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigRequest or
4531 Block parameter would result in this type of
4532 error. Progress points to the first character of
4534 @retval EFI_DEVICE_ERROR Block not large enough. Progress undefined.
4535 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted string.
4536 Block is left updated and Progress points at
4537 the "&" preceding the first non-<BlockName>.
4543 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
4544 IN CONST EFI_STRING ConfigRequest
,
4545 IN CONST UINT8
*Block
,
4546 IN CONST UINTN BlockSize
,
4547 OUT EFI_STRING
*Config
,
4548 OUT EFI_STRING
*Progress
4551 HII_DATABASE_PRIVATE_DATA
*Private
;
4552 EFI_STRING StringPtr
;
4560 EFI_STRING ValueStr
;
4561 EFI_STRING ConfigElement
;
4569 if (This
== NULL
|| Progress
== NULL
|| Config
== NULL
) {
4570 return EFI_INVALID_PARAMETER
;
4573 if (Block
== NULL
|| ConfigRequest
== NULL
) {
4574 *Progress
= ConfigRequest
;
4575 return EFI_INVALID_PARAMETER
;
4579 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
4580 ASSERT (Private
!= NULL
);
4582 StringPtr
= ConfigRequest
;
4585 ConfigElement
= NULL
;
4588 // Allocate a fix length of memory to store Results. Reallocate memory for
4589 // Results if this fix length is insufficient.
4591 *Config
= (EFI_STRING
) AllocateZeroPool (MAX_STRING_LENGTH
);
4592 if (*Config
== NULL
) {
4593 return EFI_OUT_OF_RESOURCES
;
4599 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
4600 *Progress
= StringPtr
;
4601 Status
= EFI_INVALID_PARAMETER
;
4604 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"PATH=", StrLen (L
"PATH=")) != 0) {
4607 if (*StringPtr
== 0) {
4608 *Progress
= StringPtr
- 1;
4609 Status
= EFI_INVALID_PARAMETER
;
4613 while (*StringPtr
!= L
'&' && *StringPtr
!= 0) {
4616 if (*StringPtr
== 0) {
4617 *Progress
= StringPtr
;
4619 AppendToMultiString(Config
, ConfigRequest
);
4620 HiiToLower (*Config
);
4630 // Copy <ConfigHdr> and an additional '&' to <ConfigResp>
4632 TemChar
= *StringPtr
;
4634 AppendToMultiString(Config
, ConfigRequest
);
4635 *StringPtr
= TemChar
;
4638 // Parse each <RequestElement> if exists
4639 // Only <BlockName> format is supported by this help function.
4640 // <BlockName> ::= 'OFFSET='<Number>&'WIDTH='<Number>
4642 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"OFFSET=", StrLen (L
"OFFSET=")) == 0) {
4644 // Back up the header of one <BlockName>
4648 StringPtr
+= StrLen (L
"OFFSET=");
4652 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
4653 if (EFI_ERROR (Status
)) {
4654 *Progress
= TmpPtr
- 1;
4661 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
4663 FreePool (TmpBuffer
);
4665 StringPtr
+= Length
;
4666 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
4667 *Progress
= TmpPtr
- 1;
4668 Status
= EFI_INVALID_PARAMETER
;
4671 StringPtr
+= StrLen (L
"&WIDTH=");
4676 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
4677 if (EFI_ERROR (Status
)) {
4678 *Progress
= TmpPtr
- 1;
4685 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
4687 FreePool (TmpBuffer
);
4689 StringPtr
+= Length
;
4690 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
4691 *Progress
= TmpPtr
- 1;
4692 Status
= EFI_INVALID_PARAMETER
;
4697 // Calculate Value and convert it to hex string.
4699 if (Offset
+ Width
> BlockSize
) {
4700 *Progress
= StringPtr
;
4701 Status
= EFI_DEVICE_ERROR
;
4705 Value
= (UINT8
*) AllocateZeroPool (Width
);
4706 if (Value
== NULL
) {
4707 *Progress
= ConfigRequest
;
4708 Status
= EFI_OUT_OF_RESOURCES
;
4712 CopyMem (Value
, (UINT8
*) Block
+ Offset
, Width
);
4714 Length
= Width
* 2 + 1;
4715 ValueStr
= (EFI_STRING
) AllocateZeroPool (Length
* sizeof (CHAR16
));
4716 if (ValueStr
== NULL
) {
4717 *Progress
= ConfigRequest
;
4718 Status
= EFI_OUT_OF_RESOURCES
;
4722 TemString
= ValueStr
;
4723 TemBuffer
= Value
+ Width
- 1;
4724 for (Index
= 0; Index
< Width
; Index
++, TemBuffer
--) {
4725 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
4732 // Build a ConfigElement
4734 Length
+= StringPtr
- TmpPtr
+ 1 + StrLen (L
"VALUE=");
4735 ConfigElement
= (EFI_STRING
) AllocateZeroPool (Length
* sizeof (CHAR16
));
4736 if (ConfigElement
== NULL
) {
4737 Status
= EFI_OUT_OF_RESOURCES
;
4740 CopyMem (ConfigElement
, TmpPtr
, (StringPtr
- TmpPtr
+ 1) * sizeof (CHAR16
));
4741 if (*StringPtr
== 0) {
4742 *(ConfigElement
+ (StringPtr
- TmpPtr
)) = L
'&';
4744 *(ConfigElement
+ (StringPtr
- TmpPtr
) + 1) = 0;
4745 StrCatS (ConfigElement
, Length
, L
"VALUE=");
4746 StrCatS (ConfigElement
, Length
, ValueStr
);
4748 AppendToMultiString (Config
, ConfigElement
);
4750 FreePool (ConfigElement
);
4751 FreePool (ValueStr
);
4752 ConfigElement
= NULL
;
4756 // If '\0', parsing is finished. Otherwise skip '&' to continue
4758 if (*StringPtr
== 0) {
4761 AppendToMultiString (Config
, L
"&");
4766 if (*StringPtr
!= 0) {
4767 *Progress
= StringPtr
- 1;
4768 Status
= EFI_INVALID_PARAMETER
;
4772 HiiToLower (*Config
);
4773 *Progress
= StringPtr
;
4777 if (*Config
!= NULL
) {
4781 if (ValueStr
!= NULL
) {
4782 FreePool (ValueStr
);
4784 if (Value
!= NULL
) {
4787 if (ConfigElement
!= NULL
) {
4788 FreePool (ConfigElement
);
4797 This helper function is to be called by drivers to map configuration strings
4798 to configurations stored in byte array ("block") formats such as UEFI Variables.
4800 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
4802 @param ConfigResp A null-terminated Unicode string in <ConfigResp>
4804 @param Block A possibly null array of bytes representing the
4805 current block. Only bytes referenced in the
4806 ConfigResp string in the block are modified. If
4807 this parameter is null or if the *BlockSize
4808 parameter is (on input) shorter than required by
4809 the Configuration string, only the BlockSize
4810 parameter is updated and an appropriate status
4811 (see below) is returned.
4812 @param BlockSize The length of the Block in units of UINT8. On
4813 input, this is the size of the Block. On output,
4814 if successful, contains the largest index of the
4815 modified byte in the Block, or the required buffer
4816 size if the Block is not large enough.
4817 @param Progress On return, points to an element of the ConfigResp
4818 string filled in with the offset of the most
4819 recent '&' before the first failing name / value
4820 pair (or the beginning of the string if the
4821 failure is in the first name / value pair) or the
4822 terminating NULL if all was successful.
4824 @retval EFI_SUCCESS The request succeeded. Progress points to the null
4825 terminator at the end of the ConfigResp string.
4826 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress
4827 points to the first character of ConfigResp.
4828 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigResp or
4829 Block parameter would result in this type of
4830 error. Progress points to the first character of
4832 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted name /
4833 value pair. Block is left updated and
4834 Progress points at the '&' preceding the first
4836 @retval EFI_BUFFER_TOO_SMALL Block not large enough. Progress undefined.
4837 BlockSize is updated with the required buffer size.
4838 @retval EFI_NOT_FOUND Target for the specified routing data was not found.
4839 Progress points to the "G" in "GUID" of the errant
4846 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
4847 IN CONST EFI_STRING ConfigResp
,
4848 IN OUT UINT8
*Block
,
4849 IN OUT UINTN
*BlockSize
,
4850 OUT EFI_STRING
*Progress
4853 HII_DATABASE_PRIVATE_DATA
*Private
;
4854 EFI_STRING StringPtr
;
4867 if (This
== NULL
|| BlockSize
== NULL
|| Progress
== NULL
) {
4868 return EFI_INVALID_PARAMETER
;
4871 *Progress
= ConfigResp
;
4872 if (ConfigResp
== NULL
) {
4873 return EFI_INVALID_PARAMETER
;
4876 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
4877 ASSERT (Private
!= NULL
);
4879 StringPtr
= ConfigResp
;
4880 BufferSize
= *BlockSize
;
4887 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
4888 *Progress
= StringPtr
;
4889 Status
= EFI_INVALID_PARAMETER
;
4892 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"PATH=", StrLen (L
"PATH=")) != 0) {
4895 if (*StringPtr
== 0) {
4896 *Progress
= StringPtr
;
4897 Status
= EFI_INVALID_PARAMETER
;
4901 while (*StringPtr
!= L
'&' && *StringPtr
!= 0) {
4904 if (*StringPtr
== 0) {
4905 *Progress
= StringPtr
;
4906 Status
= EFI_INVALID_PARAMETER
;
4911 // Parse each <ConfigElement> if exists
4912 // Only '&'<BlockConfig> format is supported by this help function.
4913 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE='<Number>
4915 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) == 0) {
4917 StringPtr
+= StrLen (L
"&OFFSET=");
4921 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
4922 if (EFI_ERROR (Status
)) {
4930 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
4932 FreePool (TmpBuffer
);
4934 StringPtr
+= Length
;
4935 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
4937 Status
= EFI_INVALID_PARAMETER
;
4940 StringPtr
+= StrLen (L
"&WIDTH=");
4945 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
4946 if (EFI_ERROR (Status
)) {
4954 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
4956 FreePool (TmpBuffer
);
4958 StringPtr
+= Length
;
4959 if (StrnCmp (StringPtr
, L
"&VALUE=", StrLen (L
"&VALUE=")) != 0) {
4961 Status
= EFI_INVALID_PARAMETER
;
4964 StringPtr
+= StrLen (L
"&VALUE=");
4969 Status
= GetValueOfNumber (StringPtr
, &Value
, &Length
);
4970 if (EFI_ERROR (Status
)) {
4975 StringPtr
+= Length
;
4976 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
4978 Status
= EFI_INVALID_PARAMETER
;
4983 // Update the Block with configuration info
4985 if ((Block
!= NULL
) && (Offset
+ Width
<= BufferSize
)) {
4986 CopyMem (Block
+ Offset
, Value
, Width
);
4988 if (Offset
+ Width
> MaxBlockSize
) {
4989 MaxBlockSize
= Offset
+ Width
;
4996 // If '\0', parsing is finished.
4998 if (*StringPtr
== 0) {
5004 // The input string is not ConfigResp format, return error.
5006 if (*StringPtr
!= 0) {
5007 *Progress
= StringPtr
;
5008 Status
= EFI_INVALID_PARAMETER
;
5012 *Progress
= StringPtr
+ StrLen (StringPtr
);
5013 *BlockSize
= MaxBlockSize
- 1;
5015 if (MaxBlockSize
> BufferSize
) {
5016 *BlockSize
= MaxBlockSize
;
5017 if (Block
!= NULL
) {
5018 return EFI_BUFFER_TOO_SMALL
;
5022 if (Block
== NULL
) {
5023 *Progress
= ConfigResp
;
5024 return EFI_INVALID_PARAMETER
;
5031 if (Value
!= NULL
) {
5039 This helper function is to be called by drivers to extract portions of
5040 a larger configuration string.
5042 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
5044 @param Configuration A null-terminated Unicode string in
5045 <MultiConfigAltResp> format.
5046 @param Guid A pointer to the GUID value to search for in the
5047 routing portion of the ConfigResp string when
5048 retrieving the requested data. If Guid is NULL,
5049 then all GUID values will be searched for.
5050 @param Name A pointer to the NAME value to search for in the
5051 routing portion of the ConfigResp string when
5052 retrieving the requested data. If Name is NULL,
5053 then all Name values will be searched for.
5054 @param DevicePath A pointer to the PATH value to search for in the
5055 routing portion of the ConfigResp string when
5056 retrieving the requested data. If DevicePath is
5057 NULL, then all DevicePath values will be searched
5059 @param AltCfgId A pointer to the ALTCFG value to search for in the
5060 routing portion of the ConfigResp string when
5061 retrieving the requested data. If this parameter
5062 is NULL, then the current setting will be
5064 @param AltCfgResp A pointer to a buffer which will be allocated by
5065 the function which contains the retrieved string
5066 as requested. This buffer is only allocated if
5067 the call was successful. It is <ConfigResp> format.
5069 @retval EFI_SUCCESS The request succeeded. The requested data was
5070 extracted and placed in the newly allocated
5072 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate AltCfgResp.
5073 @retval EFI_INVALID_PARAMETER Any parameter is invalid.
5074 @retval EFI_NOT_FOUND Target for the specified routing data was not
5081 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
5082 IN CONST EFI_STRING Configuration
,
5083 IN CONST EFI_GUID
*Guid
,
5084 IN CONST EFI_STRING Name
,
5085 IN CONST EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
5086 IN CONST UINT16
*AltCfgId
,
5087 OUT EFI_STRING
*AltCfgResp
5091 EFI_STRING StringPtr
;
5092 EFI_STRING HdrStart
;
5099 EFI_STRING AltIdStr
;
5116 if (This
== NULL
|| Configuration
== NULL
|| AltCfgResp
== NULL
) {
5117 return EFI_INVALID_PARAMETER
;
5120 StringPtr
= Configuration
;
5121 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
5122 return EFI_INVALID_PARAMETER
;
5126 // Generate the sub string for later matching.
5128 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*) Guid
, 1, &GuidStr
);
5131 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) DevicePath
),
5132 (VOID
*) DevicePath
,
5136 if (AltCfgId
!= NULL
) {
5137 GenerateSubStr (L
"ALTCFG=", sizeof (UINT16
), (VOID
*) AltCfgId
, 3, &AltIdStr
);
5140 GenerateSubStr (L
"NAME=", StrLen (Name
) * sizeof (CHAR16
), (VOID
*) Name
, 2, &NameStr
);
5142 GenerateSubStr (L
"NAME=", 0, NULL
, 2, &NameStr
);
5145 while (*StringPtr
!= 0) {
5147 // Try to match the GUID
5150 TmpPtr
= StrStr (StringPtr
, GuidStr
);
5151 if (TmpPtr
== NULL
) {
5152 Status
= EFI_NOT_FOUND
;
5158 // Jump to <NameHdr>
5161 StringPtr
= TmpPtr
+ StrLen (GuidStr
);
5163 StringPtr
= StrStr (TmpPtr
, L
"NAME=");
5164 if (StringPtr
== NULL
) {
5165 Status
= EFI_NOT_FOUND
;
5173 // Try to match the NAME
5175 if (GuidFlag
&& !NameFlag
) {
5176 if (StrnCmp (StringPtr
, NameStr
, StrLen (NameStr
)) != 0) {
5180 // Jump to <PathHdr>
5183 StringPtr
+= StrLen (NameStr
);
5185 StringPtr
= StrStr (StringPtr
, L
"PATH=");
5186 if (StringPtr
== NULL
) {
5187 Status
= EFI_NOT_FOUND
;
5196 // Try to match the DevicePath
5198 if (GuidFlag
&& NameFlag
&& !PathFlag
) {
5199 if (StrnCmp (StringPtr
, PathStr
, StrLen (PathStr
)) != 0) {
5204 // Jump to '&' before <DescHdr> or <ConfigBody>
5206 if (DevicePath
!= NULL
) {
5207 StringPtr
+= StrLen (PathStr
);
5209 StringPtr
= StrStr (StringPtr
, L
"&");
5210 if (StringPtr
== NULL
) {
5211 Status
= EFI_NOT_FOUND
;
5222 // Try to match the AltCfgId
5224 if (GuidFlag
&& NameFlag
&& PathFlag
) {
5225 if (AltCfgId
== NULL
) {
5227 // Return Current Setting when AltCfgId is NULL.
5229 Status
= OutputConfigBody (StringPtr
, &Result
);
5233 // Search the <ConfigAltResp> to get the <AltResp> with AltCfgId.
5235 if (StrnCmp (StringPtr
, AltIdStr
, StrLen (AltIdStr
)) != 0) {
5241 // Skip AltIdStr and &
5243 StringPtr
= StringPtr
+ StrLen (AltIdStr
);
5244 Status
= OutputConfigBody (StringPtr
, &Result
);
5250 Status
= EFI_NOT_FOUND
;
5254 if (!EFI_ERROR (Status
) && (Result
!= NULL
)) {
5256 // Copy the <ConfigHdr> and <ConfigBody>
5258 Length
= HdrEnd
- HdrStart
+ StrLen (Result
) + 1;
5259 *AltCfgResp
= AllocateZeroPool (Length
* sizeof (CHAR16
));
5260 if (*AltCfgResp
== NULL
) {
5261 Status
= EFI_OUT_OF_RESOURCES
;
5263 StrnCpyS (*AltCfgResp
, Length
, HdrStart
, HdrEnd
- HdrStart
);
5264 StrCatS (*AltCfgResp
, Length
, Result
);
5265 Status
= EFI_SUCCESS
;
5269 if (GuidStr
!= NULL
) {
5272 if (NameStr
!= NULL
) {
5275 if (PathStr
!= NULL
) {
5278 if (AltIdStr
!= NULL
) {
5279 FreePool (AltIdStr
);
5281 if (Result
!= NULL
) {