2 Implementation of interfaces function for EFI_HII_CONFIG_ROUTING_PROTOCOL.
4 Copyright (c) 2007 - 2015, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 #include "HiiDatabase.h"
17 extern HII_DATABASE_PRIVATE_DATA mPrivate
;
20 Calculate the number of Unicode characters of the incoming Configuration string,
21 not including NULL terminator.
23 This is a internal function.
25 @param String String in <MultiConfigRequest> or
26 <MultiConfigResp> format.
28 @return The number of Unicode characters.
32 CalculateConfigStringLen (
39 // "GUID=" should be the first element of incoming string.
41 ASSERT (String
!= NULL
);
42 ASSERT (StrnCmp (String
, L
"GUID=", StrLen (L
"GUID=")) == 0);
45 // The beginning of next <ConfigRequest>/<ConfigResp> should be "&GUID=".
46 // Will meet '\0' if there is only one <ConfigRequest>/<ConfigResp>.
48 TmpPtr
= StrStr (String
, L
"&GUID=");
50 return StrLen (String
);
53 return (TmpPtr
- String
);
58 Convert the hex UNICODE %02x encoding of a UEFI device path to binary
59 from <PathHdr> of <ConfigHdr>.
61 This is a internal function.
63 @param String UEFI configuration string
64 @param DevicePathData Binary of a UEFI device path.
66 @retval EFI_NOT_FOUND The device path is not invalid.
67 @retval EFI_INVALID_PARAMETER Any incoming parameter is invalid.
68 @retval EFI_OUT_OF_RESOURCES Lake of resources to store neccesary structures.
69 @retval EFI_SUCCESS The device path is retrieved and translated to
76 OUT UINT8
**DevicePathData
81 UINT8
*DevicePathBuffer
;
85 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
88 if (String
== NULL
|| DevicePathData
== NULL
) {
89 return EFI_INVALID_PARAMETER
;
93 // Find the 'PATH=' of <PathHdr> and skip it.
95 for (; (*String
!= 0 && StrnCmp (String
, L
"PATH=", StrLen (L
"PATH=")) != 0); String
++);
97 return EFI_INVALID_PARAMETER
;
100 // Check whether path data does exist.
102 String
+= StrLen (L
"PATH=");
104 return EFI_INVALID_PARAMETER
;
109 // The content between 'PATH=' of <ConfigHdr> and '&' of next element
110 // or '\0' (end of configuration string) is the UNICODE %02x bytes encoding
111 // of UEFI device path.
113 for (Length
= 0; *String
!= 0 && *String
!= L
'&'; String
++, Length
++);
115 // Check DevicePath Length
117 if (((Length
+ 1) / 2) < sizeof (EFI_DEVICE_PATH_PROTOCOL
)) {
118 return EFI_NOT_FOUND
;
122 // The data in <PathHdr> is encoded as hex UNICODE %02x bytes in the same order
123 // as the device path resides in RAM memory.
124 // Translate the data into binary.
126 DevicePathBuffer
= (UINT8
*) AllocateZeroPool ((Length
+ 1) / 2);
127 if (DevicePathBuffer
== NULL
) {
128 return EFI_OUT_OF_RESOURCES
;
132 // Convert DevicePath
134 ZeroMem (TemStr
, sizeof (TemStr
));
135 for (Index
= 0; Index
< Length
; Index
++) {
136 TemStr
[0] = PathHdr
[Index
];
137 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
138 if ((Index
& 1) == 0) {
139 DevicePathBuffer
[Index
/2] = DigitUint8
;
141 DevicePathBuffer
[Index
/2] = (UINT8
) ((DevicePathBuffer
[Index
/2] << 4) + DigitUint8
);
146 // Validate DevicePath
148 DevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) DevicePathBuffer
;
149 while (!IsDevicePathEnd (DevicePath
)) {
150 if ((DevicePath
->Type
== 0) || (DevicePath
->SubType
== 0) || (DevicePathNodeLength (DevicePath
) < sizeof (EFI_DEVICE_PATH_PROTOCOL
))) {
152 // Invalid device path
154 FreePool (DevicePathBuffer
);
155 return EFI_NOT_FOUND
;
157 DevicePath
= NextDevicePathNode (DevicePath
);
161 // return the device path
163 *DevicePathData
= DevicePathBuffer
;
168 Converts the unicode character of the string from uppercase to lowercase.
169 This is a internal function.
171 @param ConfigString String to be converted
177 IN EFI_STRING ConfigString
183 ASSERT (ConfigString
!= NULL
);
186 // Convert all hex digits in range [A-F] in the configuration header to [a-f]
188 for (String
= ConfigString
, Lower
= FALSE
; *String
!= L
'\0'; String
++) {
189 if (*String
== L
'=') {
191 } else if (*String
== L
'&') {
193 } else if (Lower
&& *String
>= L
'A' && *String
<= L
'F') {
194 *String
= (CHAR16
) (*String
- L
'A' + L
'a');
202 Generate a sub string then output it.
204 This is a internal function.
206 @param String A constant string which is the prefix of the to be
207 generated string, e.g. GUID=
209 @param BufferLen The length of the Buffer in bytes.
211 @param Buffer Points to a buffer which will be converted to be the
212 content of the generated string.
214 @param Flag If 1, the buffer contains data for the value of GUID or PATH stored in
215 UINT8 *; if 2, the buffer contains unicode string for the value of NAME;
216 if 3, the buffer contains other data.
218 @param SubStr Points to the output string. It's caller's
219 responsibility to free this buffer.
225 IN CONST EFI_STRING String
,
229 OUT EFI_STRING
*SubStr
234 EFI_STRING StringHeader
;
240 ASSERT (String
!= NULL
&& SubStr
!= NULL
);
242 if (Buffer
== NULL
) {
243 *SubStr
= AllocateCopyPool (StrSize (String
), String
);
244 ASSERT (*SubStr
!= NULL
);
249 // Header + Data + '&' + '\0'
251 Length
= StrLen (String
) + BufferLen
* 2 + 1 + 1;
252 Str
= AllocateZeroPool (Length
* sizeof (CHAR16
));
253 ASSERT (Str
!= NULL
);
255 StrCpyS (Str
, Length
, String
);
257 StringHeader
= Str
+ StrLen (String
);
258 TemString
= (CHAR16
*) StringHeader
;
263 // Convert Buffer to Hex String in reverse order
265 TemBuffer
= ((UINT8
*) Buffer
);
266 for (Index
= 0; Index
< BufferLen
; Index
++, TemBuffer
++) {
267 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
272 // Check buffer is enough
274 TemName
= (CHAR16
*) Buffer
;
275 ASSERT ((BufferLen
* 2 + 1) >= (StrLen (TemName
) * 4 + 1));
277 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
279 for (; *TemName
!= L
'\0'; TemName
++) {
280 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemName
, 4);
285 // Convert Buffer to Hex String
287 TemBuffer
= ((UINT8
*) Buffer
) + BufferLen
- 1;
288 for (Index
= 0; Index
< BufferLen
; Index
++, TemBuffer
--) {
289 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
297 // Convert the uppercase to lowercase since <HexAf> is defined in lowercase format.
299 StrCatS (Str
, Length
, L
"&");
307 Retrieve the <ConfigBody> from String then output it.
309 This is a internal function.
311 @param String A sub string of a configuration string in
312 <MultiConfigAltResp> format.
313 @param ConfigBody Points to the output string. It's caller's
314 responsibility to free this buffer.
316 @retval EFI_INVALID_PARAMETER There is no form package in current hii database.
317 @retval EFI_OUT_OF_RESOURCES Not enough memory to finish this operation.
318 @retval EFI_SUCCESS All existing storage is exported.
323 IN EFI_STRING String
,
324 OUT EFI_STRING
*ConfigBody
331 if (String
== NULL
|| ConfigBody
== NULL
) {
332 return EFI_INVALID_PARAMETER
;
336 // The setting information should start OFFSET, not ALTCFG.
338 if (StrnCmp (String
, L
"&ALTCFG=", StrLen (L
"&ALTCFG=")) == 0) {
339 return EFI_INVALID_PARAMETER
;
342 TmpPtr
= StrStr (String
, L
"GUID=");
343 if (TmpPtr
== NULL
) {
345 // It is the last <ConfigResp> of the incoming configuration string.
347 Result
= AllocateCopyPool (StrSize (String
), String
);
348 if (Result
== NULL
) {
349 return EFI_OUT_OF_RESOURCES
;
351 *ConfigBody
= Result
;
356 Length
= TmpPtr
- String
;
358 return EFI_NOT_FOUND
;
360 Result
= AllocateCopyPool (Length
* sizeof (CHAR16
), String
);
361 if (Result
== NULL
) {
362 return EFI_OUT_OF_RESOURCES
;
365 *(Result
+ Length
- 1) = 0;
366 *ConfigBody
= Result
;
371 Append a string to a multi-string format.
373 This is a internal function.
375 @param MultiString String in <MultiConfigRequest>,
376 <MultiConfigAltResp>, or <MultiConfigResp>. On
377 input, the buffer length of this string is
378 MAX_STRING_LENGTH. On output, the buffer length
380 @param AppendString NULL-terminated Unicode string.
382 @retval EFI_INVALID_PARAMETER Any incoming parameter is invalid.
383 @retval EFI_SUCCESS AppendString is append to the end of MultiString
387 AppendToMultiString (
388 IN OUT EFI_STRING
*MultiString
,
389 IN EFI_STRING AppendString
392 UINTN AppendStringSize
;
393 UINTN MultiStringSize
;
396 if (MultiString
== NULL
|| *MultiString
== NULL
|| AppendString
== NULL
) {
397 return EFI_INVALID_PARAMETER
;
400 AppendStringSize
= StrSize (AppendString
);
401 MultiStringSize
= StrSize (*MultiString
);
402 MaxLen
= MAX_STRING_LENGTH
/ sizeof (CHAR16
);
405 // Enlarge the buffer each time when length exceeds MAX_STRING_LENGTH.
407 if (MultiStringSize
+ AppendStringSize
> MAX_STRING_LENGTH
||
408 MultiStringSize
> MAX_STRING_LENGTH
) {
409 *MultiString
= (EFI_STRING
) ReallocatePool (
411 MultiStringSize
+ AppendStringSize
,
412 (VOID
*) (*MultiString
)
414 MaxLen
= (MultiStringSize
+ AppendStringSize
) / sizeof (CHAR16
);
415 ASSERT (*MultiString
!= NULL
);
418 // Append the incoming string
420 StrCatS (*MultiString
, MaxLen
, AppendString
);
427 Get the value of <Number> in <BlockConfig> format, i.e. the value of OFFSET
429 <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>
431 This is a internal function.
433 @param StringPtr String in <BlockConfig> format and points to the
434 first character of <Number>.
435 @param Number The output value. Caller takes the responsibility
437 @param Len Length of the <Number>, in characters.
439 @retval EFI_OUT_OF_RESOURCES Insufficient resources to store neccessary
441 @retval EFI_SUCCESS Value of <Number> is outputted in Number
447 IN EFI_STRING StringPtr
,
461 if (StringPtr
== NULL
|| *StringPtr
== L
'\0' || Number
== NULL
|| Len
== NULL
) {
462 return EFI_INVALID_PARAMETER
;
468 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
471 *Len
= StringPtr
- TmpPtr
;
474 Str
= (EFI_STRING
) AllocateZeroPool (Length
* sizeof (CHAR16
));
476 Status
= EFI_OUT_OF_RESOURCES
;
479 CopyMem (Str
, TmpPtr
, *Len
* sizeof (CHAR16
));
480 *(Str
+ *Len
) = L
'\0';
482 Length
= (Length
+ 1) / 2;
483 Buf
= (UINT8
*) AllocateZeroPool (Length
);
485 Status
= EFI_OUT_OF_RESOURCES
;
490 ZeroMem (TemStr
, sizeof (TemStr
));
491 for (Index
= 0; Index
< Length
; Index
++) {
492 TemStr
[0] = Str
[Length
- Index
- 1];
493 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
494 if ((Index
& 1) == 0) {
495 Buf
[Index
/2] = DigitUint8
;
497 Buf
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Buf
[Index
/2]);
502 Status
= EFI_SUCCESS
;
513 This function merges DefaultAltCfgResp string into AltCfgResp string for
514 the missing AltCfgId in AltCfgResq.
516 @param AltCfgResp Pointer to a null-terminated Unicode string in
517 <ConfigAltResp> format. The default value string
518 will be merged into it.
519 @param DefaultAltCfgResp Pointer to a null-terminated Unicode string in
520 <MultiConfigAltResp> format. The default value
521 string may contain more than one ConfigAltResp
522 string for the different varstore buffer.
524 @retval EFI_SUCCESS The merged string returns.
525 @retval EFI_INVALID_PARAMETER *AltCfgResp is to NULL.
530 IN OUT EFI_STRING
*AltCfgResp
,
531 IN EFI_STRING DefaultAltCfgResp
534 EFI_STRING StringPtrDefault
;
535 EFI_STRING StringPtrEnd
;
537 EFI_STRING StringPtr
;
538 EFI_STRING AltConfigHdr
;
540 UINTN SizeAltCfgResp
;
544 if (*AltCfgResp
== NULL
) {
545 return EFI_INVALID_PARAMETER
;
549 // Get the requestr ConfigHdr
552 StringPtr
= *AltCfgResp
;
555 // Find <ConfigHdr> GUID=...&NAME=...&PATH=...
557 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
558 return EFI_INVALID_PARAMETER
;
560 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&NAME=", StrLen (L
"&NAME=")) != 0) {
563 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&PATH=", StrLen (L
"&PATH=")) != 0) {
566 if (*StringPtr
== L
'\0') {
567 return EFI_INVALID_PARAMETER
;
569 StringPtr
+= StrLen (L
"&PATH=");
570 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
573 HeaderLength
= StringPtr
- *AltCfgResp
;
576 // Construct AltConfigHdr string "&<ConfigHdr>&ALTCFG=XXXX\0"
577 // |1| StrLen (ConfigHdr) | 8 | 4 | 1 |
579 MaxLen
= 1 + HeaderLength
+ 8 + 4 + 1;
580 AltConfigHdr
= AllocateZeroPool (MaxLen
* sizeof (CHAR16
));
581 if (AltConfigHdr
== NULL
) {
582 return EFI_OUT_OF_RESOURCES
;
584 StrCpyS (AltConfigHdr
, MaxLen
, L
"&");
585 StrnCatS (AltConfigHdr
, MaxLen
, *AltCfgResp
, HeaderLength
);
586 StrCatS (AltConfigHdr
, MaxLen
, L
"&ALTCFG=");
587 HeaderLength
= StrLen (AltConfigHdr
);
589 StringPtrDefault
= StrStr (DefaultAltCfgResp
, AltConfigHdr
);
590 while (StringPtrDefault
!= NULL
) {
594 StrnCatS (AltConfigHdr
, MaxLen
, StringPtrDefault
+ HeaderLength
, 4);
595 StringPtr
= StrStr (*AltCfgResp
, AltConfigHdr
);
598 // Append the found default value string to the input AltCfgResp
600 if (StringPtr
== NULL
) {
601 StringPtrEnd
= StrStr (StringPtrDefault
+ 1, L
"&GUID");
602 SizeAltCfgResp
= StrSize (*AltCfgResp
);
603 TotalSize
= SizeAltCfgResp
+ StrSize (StringPtrDefault
);
604 if (StringPtrEnd
== NULL
) {
606 // No more default string is found.
608 *AltCfgResp
= (EFI_STRING
) ReallocatePool (
611 (VOID
*) (*AltCfgResp
)
613 if (*AltCfgResp
== NULL
) {
614 FreePool (AltConfigHdr
);
615 return EFI_OUT_OF_RESOURCES
;
617 StrCatS (*AltCfgResp
, TotalSize
/ sizeof (CHAR16
), StringPtrDefault
);
620 TempChar
= *StringPtrEnd
;
621 *StringPtrEnd
= L
'\0';
622 *AltCfgResp
= (EFI_STRING
) ReallocatePool (
625 (VOID
*) (*AltCfgResp
)
627 if (*AltCfgResp
== NULL
) {
628 FreePool (AltConfigHdr
);
629 return EFI_OUT_OF_RESOURCES
;
631 StrCatS (*AltCfgResp
, TotalSize
/ sizeof (CHAR16
), StringPtrDefault
);
632 *StringPtrEnd
= TempChar
;
637 // Find next AltCfg String
639 *(AltConfigHdr
+ HeaderLength
) = L
'\0';
640 StringPtrDefault
= StrStr (StringPtrDefault
+ 1, AltConfigHdr
);
643 FreePool (AltConfigHdr
);
648 This function inserts new DefaultValueData into the BlockData DefaultValue array.
650 @param BlockData The BlockData is updated to add new default value.
651 @param DefaultValueData The DefaultValue is added.
656 IN IFR_BLOCK_DATA
*BlockData
,
657 IN IFR_DEFAULT_DATA
*DefaultValueData
661 IFR_DEFAULT_DATA
*DefaultValueArray
;
662 LIST_ENTRY
*DefaultLink
;
664 DefaultLink
= &BlockData
->DefaultValueEntry
;
666 for (Link
= DefaultLink
->ForwardLink
; Link
!= DefaultLink
; Link
= Link
->ForwardLink
) {
667 DefaultValueArray
= BASE_CR (Link
, IFR_DEFAULT_DATA
, Entry
);
668 if (DefaultValueArray
->DefaultId
== DefaultValueData
->DefaultId
) {
670 // DEFAULT_VALUE_FROM_OPCODE has high priority, DEFAULT_VALUE_FROM_DEFAULT has low priority.
672 if (DefaultValueData
->Type
> DefaultValueArray
->Type
) {
674 // Update the default value array in BlockData.
676 CopyMem (&DefaultValueArray
->Value
, &DefaultValueData
->Value
, sizeof (EFI_IFR_TYPE_VALUE
));
677 DefaultValueArray
->Type
= DefaultValueData
->Type
;
678 DefaultValueArray
->Cleaned
= DefaultValueData
->Cleaned
;
685 // Insert new default value data in tail.
687 DefaultValueArray
= AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
688 ASSERT (DefaultValueArray
!= NULL
);
689 CopyMem (DefaultValueArray
, DefaultValueData
, sizeof (IFR_DEFAULT_DATA
));
690 InsertTailList (Link
, &DefaultValueArray
->Entry
);
694 This function inserts new BlockData into the block link
696 @param BlockLink The list entry points to block array.
697 @param BlockData The point to BlockData is added.
702 IN LIST_ENTRY
*BlockLink
,
703 IN IFR_BLOCK_DATA
**BlockData
707 IFR_BLOCK_DATA
*BlockArray
;
708 IFR_BLOCK_DATA
*BlockSingleData
;
710 BlockSingleData
= *BlockData
;
712 if (BlockSingleData
->Name
!= NULL
) {
713 InsertTailList (BlockLink
, &BlockSingleData
->Entry
);
718 // Insert block data in its Offset and Width order.
720 for (Link
= BlockLink
->ForwardLink
; Link
!= BlockLink
; Link
= Link
->ForwardLink
) {
721 BlockArray
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
722 if (BlockArray
->Offset
== BlockSingleData
->Offset
) {
723 if (BlockArray
->Width
> BlockSingleData
->Width
) {
725 // Insert this block data in the front of block array
727 InsertTailList (Link
, &BlockSingleData
->Entry
);
731 if (BlockArray
->Width
== BlockSingleData
->Width
) {
733 // The same block array has been added.
735 if (BlockSingleData
!= BlockArray
) {
736 FreePool (BlockSingleData
);
737 *BlockData
= BlockArray
;
741 } else if (BlockArray
->Offset
> BlockSingleData
->Offset
) {
743 // Insert new block data in the front of block array
745 InsertTailList (Link
, &BlockSingleData
->Entry
);
751 // Add new block data into the tail.
753 InsertTailList (Link
, &BlockSingleData
->Entry
);
757 Retrieves a pointer to the a Null-terminated ASCII string containing the list
758 of languages that an HII handle in the HII Database supports. The returned
759 string is allocated using AllocatePool(). The caller is responsible for freeing
760 the returned string using FreePool(). The format of the returned string follows
761 the language format assumed the HII Database.
763 If HiiHandle is NULL, then ASSERT().
765 @param[in] HiiHandle A handle that was previously registered in the HII Database.
767 @retval NULL HiiHandle is not registered in the HII database
768 @retval NULL There are not enough resources available to retrieve the suported
770 @retval NULL The list of suported languages could not be retrieved.
771 @retval Other A pointer to the Null-terminated ASCII string of supported languages.
775 GetSupportedLanguages (
776 IN EFI_HII_HANDLE HiiHandle
781 CHAR8 TempSupportedLanguages
;
782 CHAR8
*SupportedLanguages
;
784 ASSERT (HiiHandle
!= NULL
);
787 // Retrieve the size required for the supported languages buffer.
790 Status
= mPrivate
.HiiString
.GetLanguages (&mPrivate
.HiiString
, HiiHandle
, &TempSupportedLanguages
, &LanguageSize
);
793 // If GetLanguages() returns EFI_SUCCESS for a zero size,
794 // then there are no supported languages registered for HiiHandle. If GetLanguages()
795 // returns an error other than EFI_BUFFER_TOO_SMALL, then HiiHandle is not present
796 // in the HII Database
798 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
800 // Return NULL if the size can not be retrieved, or if HiiHandle is not in the HII Database
806 // Allocate the supported languages buffer.
808 SupportedLanguages
= AllocateZeroPool (LanguageSize
);
809 if (SupportedLanguages
== NULL
) {
811 // Return NULL if allocation fails.
817 // Retrieve the supported languages string
819 Status
= mPrivate
.HiiString
.GetLanguages (&mPrivate
.HiiString
, HiiHandle
, SupportedLanguages
, &LanguageSize
);
820 if (EFI_ERROR (Status
)) {
822 // Free the buffer and return NULL if the supported languages can not be retrieved.
824 FreePool (SupportedLanguages
);
829 // Return the Null-terminated ASCII string of supported languages
831 return SupportedLanguages
;
835 Retrieves a string from a string package.
837 If HiiHandle is NULL, then ASSERT().
838 If StringId is 0, then ASSET.
840 @param[in] HiiHandle A handle that was previously registered in the HII Database.
841 @param[in] StringId The identifier of the string to retrieved from the string
842 package associated with HiiHandle.
844 @retval NULL The string specified by StringId is not present in the string package.
845 @retval Other The string was returned.
850 IN EFI_HII_HANDLE HiiHandle
,
851 IN EFI_STRING_ID StringId
858 CHAR8
*SupportedLanguages
;
859 CHAR8
*PlatformLanguage
;
863 ASSERT (HiiHandle
!= NULL
);
864 ASSERT (StringId
!= 0);
867 // Initialize all allocated buffers to NULL
869 SupportedLanguages
= NULL
;
870 PlatformLanguage
= NULL
;
876 // Get the languages that the package specified by HiiHandle supports
878 SupportedLanguages
= GetSupportedLanguages (HiiHandle
);
879 if (SupportedLanguages
== NULL
) {
884 // Get the current platform language setting
886 GetEfiGlobalVariable2 (L
"PlatformLang", (VOID
**)&PlatformLanguage
, NULL
);
889 // Get the best matching language from SupportedLanguages
891 BestLanguage
= GetBestLanguage (
893 FALSE
, // RFC 4646 mode
894 Language
, // Highest priority
895 PlatformLanguage
!= NULL
? PlatformLanguage
: "", // Next highest priority
896 SupportedLanguages
, // Lowest priority
899 if (BestLanguage
== NULL
) {
904 // Retrieve the size of the string in the string package for the BestLanguage
907 Status
= mPrivate
.HiiString
.GetString (
917 // If GetString() returns EFI_SUCCESS for a zero size,
918 // then there are no supported languages registered for HiiHandle. If GetString()
919 // returns an error other than EFI_BUFFER_TOO_SMALL, then HiiHandle is not present
920 // in the HII Database
922 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
927 // Allocate a buffer for the return string
929 String
= AllocateZeroPool (StringSize
);
930 if (String
== NULL
) {
935 // Retrieve the string from the string package
937 Status
= mPrivate
.HiiString
.GetString (
946 if (EFI_ERROR (Status
)) {
948 // Free the buffer and return NULL if the supported languages can not be retrieved.
956 // Free allocated buffers
958 if (SupportedLanguages
!= NULL
) {
959 FreePool (SupportedLanguages
);
961 if (PlatformLanguage
!= NULL
) {
962 FreePool (PlatformLanguage
);
964 if (BestLanguage
!= NULL
) {
965 FreePool (BestLanguage
);
969 // Return the Null-terminated Unicode string
975 This function checks VarOffset and VarWidth is in the block range.
977 @param RequestBlockArray The block array is to be checked.
978 @param VarOffset Offset of var to the structure
979 @param VarWidth Width of var.
980 @param IsNameValueType Whether this varstore is name/value varstore or not.
981 @param HiiHandle Hii handle for this hii package.
983 @retval TRUE This Var is in the block range.
984 @retval FALSE This Var is not in the block range.
988 IN IFR_BLOCK_DATA
*RequestBlockArray
,
991 IN BOOLEAN IsNameValueType
,
992 IN EFI_HII_HANDLE HiiHandle
996 IFR_BLOCK_DATA
*BlockData
;
1000 // No Request Block array, all vars are got.
1002 if (RequestBlockArray
== NULL
) {
1007 // Check the input var is in the request block range.
1009 for (Link
= RequestBlockArray
->Entry
.ForwardLink
; Link
!= &RequestBlockArray
->Entry
; Link
= Link
->ForwardLink
) {
1010 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
1012 if (IsNameValueType
) {
1013 Name
= InternalGetString (HiiHandle
, VarOffset
);
1014 ASSERT (Name
!= NULL
);
1016 if (StrnCmp (BlockData
->Name
, Name
, StrLen (Name
)) == 0) {
1022 if ((VarOffset
>= BlockData
->Offset
) && ((VarOffset
+ VarWidth
) <= (BlockData
->Offset
+ BlockData
->Width
))) {
1032 Get form package data from data base.
1034 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
1035 @param HiiFormPackage The buffer saves the package data.
1036 @param PackageSize The buffer size of the package data.
1040 GetFormPackageData (
1041 IN HII_DATABASE_RECORD
*DataBaseRecord
,
1042 IN OUT UINT8
**HiiFormPackage
,
1043 OUT UINTN
*PackageSize
1050 if (DataBaseRecord
== NULL
|| HiiFormPackage
== NULL
|| PackageSize
== NULL
) {
1051 return EFI_INVALID_PARAMETER
;
1057 // 0. Get Hii Form Package by HiiHandle
1059 Status
= ExportFormPackages (
1061 DataBaseRecord
->Handle
,
1062 DataBaseRecord
->PackageList
,
1068 if (EFI_ERROR (Status
)) {
1072 (*HiiFormPackage
) = AllocatePool (ResultSize
);
1073 if (*HiiFormPackage
== NULL
) {
1074 Status
= EFI_OUT_OF_RESOURCES
;
1079 // Get HiiFormPackage by HiiHandle
1083 Status
= ExportFormPackages (
1085 DataBaseRecord
->Handle
,
1086 DataBaseRecord
->PackageList
,
1092 if (EFI_ERROR (Status
)) {
1093 FreePool (*HiiFormPackage
);
1096 *PackageSize
= Size
;
1103 This function parses Form Package to get the efi varstore info according to the request ConfigHdr.
1105 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
1106 @param ConfigHdr Request string ConfigHdr. If it is NULL,
1107 the first found varstore will be as ConfigHdr.
1108 @param IsEfiVarstore Whether the request storage type is efi varstore type.
1109 @param EfiVarStore The efi varstore info which will return.
1113 IN HII_DATABASE_RECORD
*DataBaseRecord
,
1114 IN EFI_STRING ConfigHdr
,
1115 OUT BOOLEAN
*IsEfiVarstore
,
1116 OUT EFI_IFR_VARSTORE_EFI
**EfiVarStore
1121 UINTN PackageOffset
;
1122 EFI_IFR_OP_HEADER
*IfrOpHdr
;
1123 CHAR16
*VarStoreName
;
1128 UINT8
*HiiFormPackage
;
1130 EFI_IFR_VARSTORE_EFI
*IfrEfiVarStore
;
1131 EFI_HII_PACKAGE_HEADER
*PackageHeader
;
1133 HiiFormPackage
= NULL
;
1135 Status
= EFI_SUCCESS
;
1139 *IsEfiVarstore
= FALSE
;
1141 Status
= GetFormPackageData(DataBaseRecord
, &HiiFormPackage
, &PackageSize
);
1142 if (EFI_ERROR (Status
)) {
1146 IfrOffset
= sizeof (EFI_HII_PACKAGE_HEADER
);
1147 PackageOffset
= IfrOffset
;
1148 PackageHeader
= (EFI_HII_PACKAGE_HEADER
*) HiiFormPackage
;
1150 while (IfrOffset
< PackageSize
) {
1152 // More than one form packages exist.
1154 if (PackageOffset
>= PackageHeader
->Length
) {
1156 // Process the new form package.
1158 PackageOffset
= sizeof (EFI_HII_PACKAGE_HEADER
);
1159 IfrOffset
+= PackageOffset
;
1160 PackageHeader
= (EFI_HII_PACKAGE_HEADER
*) (HiiFormPackage
+ IfrOffset
);
1163 IfrOpHdr
= (EFI_IFR_OP_HEADER
*) (HiiFormPackage
+ IfrOffset
);
1164 IfrOffset
+= IfrOpHdr
->Length
;
1165 PackageOffset
+= IfrOpHdr
->Length
;
1167 if (IfrOpHdr
->OpCode
== EFI_IFR_VARSTORE_EFI_OP
) {
1168 IfrEfiVarStore
= (EFI_IFR_VARSTORE_EFI
*) IfrOpHdr
;
1170 // If the length is small than the structure, this is from old efi
1171 // varstore definition. Old efi varstore get config directly from
1172 // GetVariable function.
1174 if (IfrOpHdr
->Length
< sizeof (EFI_IFR_VARSTORE_EFI
)) {
1178 VarStoreName
= AllocateZeroPool (AsciiStrSize ((CHAR8
*)IfrEfiVarStore
->Name
) * sizeof (CHAR16
));
1179 if (VarStoreName
== NULL
) {
1180 Status
= EFI_OUT_OF_RESOURCES
;
1183 AsciiStrToUnicodeStr ((CHAR8
*) IfrEfiVarStore
->Name
, VarStoreName
);
1185 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*) &IfrEfiVarStore
->Guid
, 1, &GuidStr
);
1186 GenerateSubStr (L
"NAME=", StrLen (VarStoreName
) * sizeof (CHAR16
), (VOID
*) VarStoreName
, 2, &NameStr
);
1187 LengthString
= StrLen (GuidStr
);
1188 LengthString
= LengthString
+ StrLen (NameStr
) + 1;
1189 TempStr
= AllocateZeroPool (LengthString
* sizeof (CHAR16
));
1190 if (TempStr
== NULL
) {
1193 FreePool (VarStoreName
);
1194 Status
= EFI_OUT_OF_RESOURCES
;
1197 StrCpyS (TempStr
, LengthString
, GuidStr
);
1198 StrCatS (TempStr
, LengthString
, NameStr
);
1199 if (ConfigHdr
== NULL
|| StrnCmp (ConfigHdr
, TempStr
, StrLen (TempStr
)) == 0) {
1200 *EfiVarStore
= (EFI_IFR_VARSTORE_EFI
*) AllocateZeroPool (IfrOpHdr
->Length
);
1201 if (*EfiVarStore
== NULL
) {
1202 FreePool (VarStoreName
);
1206 Status
= EFI_OUT_OF_RESOURCES
;
1209 *IsEfiVarstore
= TRUE
;
1210 CopyMem (*EfiVarStore
, IfrEfiVarStore
, IfrOpHdr
->Length
);
1214 // Free alllocated temp string.
1216 FreePool (VarStoreName
);
1222 // Already found the varstore, break;
1224 if (*IsEfiVarstore
) {
1230 if (HiiFormPackage
!= NULL
) {
1231 FreePool (HiiFormPackage
);
1238 Check whether the ConfigRequest string has the request elements.
1239 For EFI_HII_VARSTORE_BUFFER type, the request has "&OFFSET=****&WIDTH=****..." format.
1240 For EFI_HII_VARSTORE_NAME_VALUE type, the request has "&NAME1**&NAME2..." format.
1242 @param ConfigRequest The input config request string.
1244 @retval TRUE The input include config request elements.
1245 @retval FALSE The input string not includes.
1249 GetElementsFromRequest (
1250 IN EFI_STRING ConfigRequest
1253 EFI_STRING TmpRequest
;
1255 TmpRequest
= StrStr (ConfigRequest
, L
"PATH=");
1256 ASSERT (TmpRequest
!= NULL
);
1258 if ((StrStr (TmpRequest
, L
"&OFFSET=") != NULL
) || (StrStr (TmpRequest
, L
"&") != NULL
)) {
1266 Check whether the this varstore is the request varstore.
1268 @param VarstoreGuid Varstore guid.
1269 @param Name Varstore name.
1270 @param ConfigHdr Current configRequest info.
1272 @retval TRUE This varstore is the requst one.
1273 @retval FALSE This varstore is not the requst one.
1278 IN EFI_GUID
*VarstoreGuid
,
1280 IN CHAR16
*ConfigHdr
1294 // If ConfigHdr has name field and varstore not has name, return FALSE.
1296 if (Name
== NULL
&& ConfigHdr
!= NULL
&& StrStr (ConfigHdr
, L
"NAME=&") == NULL
) {
1300 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*)VarstoreGuid
, 1, &GuidStr
);
1302 GenerateSubStr (L
"NAME=", StrLen (Name
) * sizeof (CHAR16
), (VOID
*) Name
, 2, &NameStr
);
1304 GenerateSubStr (L
"NAME=", 0, NULL
, 2, &NameStr
);
1306 LengthString
= StrLen (GuidStr
);
1307 LengthString
= LengthString
+ StrLen (NameStr
) + 1;
1308 TempStr
= AllocateZeroPool (LengthString
* sizeof (CHAR16
));
1309 if (TempStr
== NULL
) {
1313 StrCpyS (TempStr
, LengthString
, GuidStr
);
1314 StrCatS (TempStr
, LengthString
, NameStr
);
1316 if (ConfigHdr
== NULL
|| StrnCmp (ConfigHdr
, TempStr
, StrLen (TempStr
)) == 0) {
1321 if (GuidStr
!= NULL
) {
1325 if (NameStr
!= NULL
) {
1329 if (TempStr
!= NULL
) {
1337 This function parses Form Package to get the efi varstore info according to the request ConfigHdr.
1339 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
1340 @param ConfigHdr Request string ConfigHdr. If it is NULL,
1341 the first found varstore will be as ConfigHdr.
1342 @retval TRUE This hii package is the reqeust one.
1343 @retval FALSE This hii package is not the reqeust one.
1347 IN HII_DATABASE_RECORD
*DataBaseRecord
,
1348 IN EFI_STRING ConfigHdr
1353 UINTN PackageOffset
;
1354 EFI_IFR_OP_HEADER
*IfrOpHdr
;
1355 CHAR16
*VarStoreName
;
1356 UINT8
*HiiFormPackage
;
1358 EFI_IFR_VARSTORE_EFI
*IfrEfiVarStore
;
1359 EFI_HII_PACKAGE_HEADER
*PackageHeader
;
1360 EFI_IFR_VARSTORE
*IfrVarStore
;
1361 EFI_IFR_VARSTORE_NAME_VALUE
*IfrNameValueVarStore
;
1362 BOOLEAN FindVarstore
;
1364 HiiFormPackage
= NULL
;
1365 VarStoreName
= NULL
;
1366 Status
= EFI_SUCCESS
;
1367 FindVarstore
= FALSE
;
1369 Status
= GetFormPackageData(DataBaseRecord
, &HiiFormPackage
, &PackageSize
);
1370 if (EFI_ERROR (Status
)) {
1374 IfrOffset
= sizeof (EFI_HII_PACKAGE_HEADER
);
1375 PackageOffset
= IfrOffset
;
1376 PackageHeader
= (EFI_HII_PACKAGE_HEADER
*) HiiFormPackage
;
1378 while (IfrOffset
< PackageSize
) {
1380 // More than one form packages exist.
1382 if (PackageOffset
>= PackageHeader
->Length
) {
1384 // Process the new form package.
1386 PackageOffset
= sizeof (EFI_HII_PACKAGE_HEADER
);
1387 IfrOffset
+= PackageOffset
;
1388 PackageHeader
= (EFI_HII_PACKAGE_HEADER
*) (HiiFormPackage
+ IfrOffset
);
1391 IfrOpHdr
= (EFI_IFR_OP_HEADER
*) (HiiFormPackage
+ IfrOffset
);
1392 IfrOffset
+= IfrOpHdr
->Length
;
1393 PackageOffset
+= IfrOpHdr
->Length
;
1395 switch (IfrOpHdr
->OpCode
) {
1397 case EFI_IFR_VARSTORE_OP
:
1398 IfrVarStore
= (EFI_IFR_VARSTORE
*) IfrOpHdr
;
1400 VarStoreName
= AllocateZeroPool (AsciiStrSize ((CHAR8
*)IfrVarStore
->Name
) * sizeof (CHAR16
));
1401 if (VarStoreName
== NULL
) {
1404 AsciiStrToUnicodeStr ((CHAR8
*)IfrVarStore
->Name
, VarStoreName
);
1406 if (IsThisVarstore((VOID
*)&IfrVarStore
->Guid
, VarStoreName
, ConfigHdr
)) {
1407 FindVarstore
= TRUE
;
1412 case EFI_IFR_VARSTORE_EFI_OP
:
1413 IfrEfiVarStore
= (EFI_IFR_VARSTORE_EFI
*) IfrOpHdr
;
1414 VarStoreName
= AllocateZeroPool (AsciiStrSize ((CHAR8
*)IfrEfiVarStore
->Name
) * sizeof (CHAR16
));
1415 if (VarStoreName
== NULL
) {
1418 AsciiStrToUnicodeStr ((CHAR8
*)IfrEfiVarStore
->Name
, VarStoreName
);
1420 if (IsThisVarstore (&IfrEfiVarStore
->Guid
, VarStoreName
, ConfigHdr
)) {
1421 FindVarstore
= TRUE
;
1426 case EFI_IFR_VARSTORE_NAME_VALUE_OP
:
1427 IfrNameValueVarStore
= (EFI_IFR_VARSTORE_NAME_VALUE
*) IfrOpHdr
;
1429 if (IsThisVarstore (&IfrNameValueVarStore
->Guid
, NULL
, ConfigHdr
)) {
1430 FindVarstore
= TRUE
;
1435 case EFI_IFR_FORM_OP
:
1436 case EFI_IFR_FORM_MAP_OP
:
1438 // No matched varstore is found and directly return.
1447 if (HiiFormPackage
!= NULL
) {
1448 FreePool (HiiFormPackage
);
1451 if (VarStoreName
!= NULL
) {
1452 FreePool (VarStoreName
);
1455 return FindVarstore
;
1459 Check whether the this op code is required.
1461 @param RequestBlockArray The array includes all the request info or NULL.
1462 @param HiiHandle The hii handle for this form package.
1463 @param VarStorageData The varstore data strucure.
1464 @param IfrOpHdr Ifr opcode header for this opcode.
1465 @param VarWidth The buffer width for this opcode.
1466 @param ReturnData The data block added for this opcode.
1468 @retval EFI_SUCCESS This opcode is required.
1469 @retval Others This opcode is not required or error occur.
1473 IsThisOpcodeRequired (
1474 IN IFR_BLOCK_DATA
*RequestBlockArray
,
1475 IN EFI_HII_HANDLE HiiHandle
,
1476 IN OUT IFR_VARSTORAGE_DATA
*VarStorageData
,
1477 IN EFI_IFR_OP_HEADER
*IfrOpHdr
,
1479 OUT IFR_BLOCK_DATA
**ReturnData
1482 IFR_BLOCK_DATA
*BlockData
;
1484 EFI_STRING_ID NameId
;
1485 EFI_IFR_QUESTION_HEADER
*IfrQuestionHdr
;
1489 IfrQuestionHdr
= (EFI_IFR_QUESTION_HEADER
*)((CHAR8
*) IfrOpHdr
+ sizeof (EFI_IFR_OP_HEADER
));
1491 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
1492 NameId
= IfrQuestionHdr
->VarStoreInfo
.VarName
;
1495 // Check whether this question is in requested block array.
1497 if (!BlockArrayCheck (RequestBlockArray
, NameId
, 0, TRUE
, HiiHandle
)) {
1499 // This question is not in the requested string. Skip it.
1504 VarOffset
= IfrQuestionHdr
->VarStoreInfo
.VarOffset
;
1507 // Check whether this question is in requested block array.
1509 if (!BlockArrayCheck (RequestBlockArray
, VarOffset
, VarWidth
, FALSE
, HiiHandle
)) {
1511 // This question is not in the requested string. Skip it.
1517 // Check this var question is in the var storage
1519 if (((VarOffset
+ VarWidth
) > VarStorageData
->Size
)) {
1520 return EFI_INVALID_PARAMETER
;
1524 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
1525 if (BlockData
== NULL
) {
1526 return EFI_OUT_OF_RESOURCES
;
1529 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
1530 BlockData
->Name
= InternalGetString(HiiHandle
, NameId
);
1532 BlockData
->Offset
= VarOffset
;
1535 BlockData
->Width
= VarWidth
;
1536 BlockData
->QuestionId
= IfrQuestionHdr
->QuestionId
;
1537 BlockData
->OpCode
= IfrOpHdr
->OpCode
;
1538 BlockData
->Scope
= IfrOpHdr
->Scope
;
1539 InitializeListHead (&BlockData
->DefaultValueEntry
);
1541 // Add Block Data into VarStorageData BlockEntry
1543 InsertBlockData (&VarStorageData
->BlockEntry
, &BlockData
);
1544 *ReturnData
= BlockData
;
1550 This function parses Form Package to get the block array and the default
1551 value array according to the request ConfigHdr.
1553 @param HiiHandle Hii Handle for this hii package.
1554 @param Package Pointer to the form package data.
1555 @param PackageLength Length of the pacakge.
1556 @param ConfigHdr Request string ConfigHdr. If it is NULL,
1557 the first found varstore will be as ConfigHdr.
1558 @param RequestBlockArray The block array is retrieved from the request string.
1559 @param VarStorageData VarStorage structure contains the got block and default value.
1560 @param DefaultIdArray Point to the got default id and default name array.
1562 @retval EFI_SUCCESS The block array and the default value array are got.
1563 @retval EFI_INVALID_PARAMETER The varstore defintion in the differnt form pacakges
1565 @retval EFI_OUT_OF_RESOURCES No enough memory.
1570 IN EFI_HII_HANDLE HiiHandle
,
1572 IN UINT32 PackageLength
,
1573 IN EFI_STRING ConfigHdr
,
1574 IN IFR_BLOCK_DATA
*RequestBlockArray
,
1575 IN OUT IFR_VARSTORAGE_DATA
*VarStorageData
,
1576 OUT IFR_DEFAULT_DATA
*DefaultIdArray
1581 UINTN PackageOffset
;
1582 EFI_IFR_VARSTORE
*IfrVarStore
;
1583 EFI_IFR_VARSTORE_EFI
*IfrEfiVarStore
;
1584 EFI_IFR_OP_HEADER
*IfrOpHdr
;
1585 EFI_IFR_ONE_OF
*IfrOneOf
;
1586 EFI_IFR_REF4
*IfrRef
;
1587 EFI_IFR_ONE_OF_OPTION
*IfrOneOfOption
;
1588 EFI_IFR_DEFAULT
*IfrDefault
;
1589 EFI_IFR_ORDERED_LIST
*IfrOrderedList
;
1590 EFI_IFR_CHECKBOX
*IfrCheckBox
;
1591 EFI_IFR_PASSWORD
*IfrPassword
;
1592 EFI_IFR_STRING
*IfrString
;
1593 EFI_IFR_DATE
*IfrDate
;
1594 EFI_IFR_TIME
*IfrTime
;
1595 IFR_DEFAULT_DATA DefaultData
;
1596 IFR_DEFAULT_DATA
*DefaultDataPtr
;
1597 IFR_BLOCK_DATA
*BlockData
;
1598 CHAR16
*VarStoreName
;
1600 UINT16 VarDefaultId
;
1601 BOOLEAN FirstOneOfOption
;
1602 LIST_ENTRY
*LinkData
;
1603 LIST_ENTRY
*LinkDefault
;
1604 EFI_IFR_VARSTORE_NAME_VALUE
*IfrNameValueVarStore
;
1605 EFI_HII_PACKAGE_HEADER
*PackageHeader
;
1606 EFI_VARSTORE_ID VarStoreId
;
1608 Status
= EFI_SUCCESS
;
1610 DefaultDataPtr
= NULL
;
1611 FirstOneOfOption
= FALSE
;
1613 ZeroMem (&DefaultData
, sizeof (IFR_DEFAULT_DATA
));
1616 // Go through the form package to parse OpCode one by one.
1618 PackageOffset
= sizeof (EFI_HII_PACKAGE_HEADER
);
1619 PackageHeader
= (EFI_HII_PACKAGE_HEADER
*) Package
;
1620 IfrOffset
= PackageOffset
;
1621 while (IfrOffset
< PackageLength
) {
1624 // More than one form package found.
1626 if (PackageOffset
>= PackageHeader
->Length
) {
1628 // Already found varstore for this request, break;
1630 if (VarStoreId
!= 0) {
1635 // Get next package header info.
1637 IfrOffset
+= sizeof (EFI_HII_PACKAGE_HEADER
);
1638 PackageOffset
= sizeof (EFI_HII_PACKAGE_HEADER
);
1639 PackageHeader
= (EFI_HII_PACKAGE_HEADER
*) (Package
+ IfrOffset
);
1642 IfrOpHdr
= (EFI_IFR_OP_HEADER
*) (Package
+ IfrOffset
);
1643 switch (IfrOpHdr
->OpCode
) {
1644 case EFI_IFR_VARSTORE_OP
:
1646 // VarStore is found. Don't need to search any more.
1648 if (VarStoreId
!= 0) {
1652 IfrVarStore
= (EFI_IFR_VARSTORE
*) IfrOpHdr
;
1654 VarStoreName
= AllocateZeroPool (AsciiStrSize ((CHAR8
*)IfrVarStore
->Name
) * sizeof (CHAR16
));
1655 if (VarStoreName
== NULL
) {
1656 Status
= EFI_OUT_OF_RESOURCES
;
1659 AsciiStrToUnicodeStr ((CHAR8
*)IfrVarStore
->Name
, VarStoreName
);
1661 if (IsThisVarstore((VOID
*)&IfrVarStore
->Guid
, VarStoreName
, ConfigHdr
)) {
1663 // Find the matched VarStore
1665 CopyGuid (&VarStorageData
->Guid
, (EFI_GUID
*) (VOID
*) &IfrVarStore
->Guid
);
1666 VarStorageData
->Size
= IfrVarStore
->Size
;
1667 VarStorageData
->Name
= VarStoreName
;
1668 VarStorageData
->Type
= EFI_HII_VARSTORE_BUFFER
;
1669 VarStoreId
= IfrVarStore
->VarStoreId
;
1673 case EFI_IFR_VARSTORE_EFI_OP
:
1675 // VarStore is found. Don't need to search any more.
1677 if (VarStoreId
!= 0) {
1681 IfrEfiVarStore
= (EFI_IFR_VARSTORE_EFI
*) IfrOpHdr
;
1684 // If the length is small than the structure, this is from old efi
1685 // varstore definition. Old efi varstore get config directly from
1686 // GetVariable function.
1688 if (IfrOpHdr
->Length
< sizeof (EFI_IFR_VARSTORE_EFI
)) {
1692 VarStoreName
= AllocateZeroPool (AsciiStrSize ((CHAR8
*)IfrEfiVarStore
->Name
) * sizeof (CHAR16
));
1693 if (VarStoreName
== NULL
) {
1694 Status
= EFI_OUT_OF_RESOURCES
;
1697 AsciiStrToUnicodeStr ((CHAR8
*)IfrEfiVarStore
->Name
, VarStoreName
);
1699 if (IsThisVarstore (&IfrEfiVarStore
->Guid
, VarStoreName
, ConfigHdr
)) {
1701 // Find the matched VarStore
1703 CopyGuid (&VarStorageData
->Guid
, (EFI_GUID
*) (VOID
*) &IfrEfiVarStore
->Guid
);
1704 VarStorageData
->Size
= IfrEfiVarStore
->Size
;
1705 VarStorageData
->Name
= VarStoreName
;
1706 VarStorageData
->Type
= EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
;
1707 VarStoreId
= IfrEfiVarStore
->VarStoreId
;
1711 case EFI_IFR_VARSTORE_NAME_VALUE_OP
:
1713 // VarStore is found. Don't need to search any more.
1715 if (VarStoreId
!= 0) {
1719 IfrNameValueVarStore
= (EFI_IFR_VARSTORE_NAME_VALUE
*) IfrOpHdr
;
1721 if (IsThisVarstore (&IfrNameValueVarStore
->Guid
, NULL
, ConfigHdr
)) {
1723 // Find the matched VarStore
1725 CopyGuid (&VarStorageData
->Guid
, (EFI_GUID
*) (VOID
*) &IfrNameValueVarStore
->Guid
);
1726 VarStorageData
->Type
= EFI_HII_VARSTORE_NAME_VALUE
;
1727 VarStoreId
= IfrNameValueVarStore
->VarStoreId
;
1731 case EFI_IFR_DEFAULTSTORE_OP
:
1733 // Add new the map between default id and default name.
1735 DefaultDataPtr
= (IFR_DEFAULT_DATA
*) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
1736 if (DefaultDataPtr
== NULL
) {
1737 Status
= EFI_OUT_OF_RESOURCES
;
1740 DefaultDataPtr
->DefaultId
= ((EFI_IFR_DEFAULTSTORE
*) IfrOpHdr
)->DefaultId
;
1741 InsertTailList (&DefaultIdArray
->Entry
, &DefaultDataPtr
->Entry
);
1742 DefaultDataPtr
= NULL
;
1745 case EFI_IFR_FORM_OP
:
1746 case EFI_IFR_FORM_MAP_OP
:
1748 // No matched varstore is found and directly return.
1750 if ( VarStoreId
== 0) {
1751 Status
= EFI_SUCCESS
;
1756 case EFI_IFR_REF_OP
:
1758 // Ref question is not in IFR Form. This IFR form is not valid.
1760 if ( VarStoreId
== 0) {
1761 Status
= EFI_INVALID_PARAMETER
;
1765 // Check whether this question is for the requested varstore.
1767 IfrRef
= (EFI_IFR_REF4
*) IfrOpHdr
;
1768 if (IfrRef
->Question
.VarStoreId
!= VarStoreId
) {
1771 VarWidth
= (UINT16
) (sizeof (EFI_HII_REF
));
1773 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
1774 if (EFI_ERROR (Status
)) {
1779 case EFI_IFR_ONE_OF_OP
:
1780 case EFI_IFR_NUMERIC_OP
:
1782 // Numeric and OneOf has the same opcode structure.
1786 // Numeric and OneOf question is not in IFR Form. This IFR form is not valid.
1788 if (VarStoreId
== 0) {
1789 Status
= EFI_INVALID_PARAMETER
;
1793 // Check whether this question is for the requested varstore.
1795 IfrOneOf
= (EFI_IFR_ONE_OF
*) IfrOpHdr
;
1796 if (IfrOneOf
->Question
.VarStoreId
!= VarStoreId
) {
1799 VarWidth
= (UINT16
) (1 << (IfrOneOf
->Flags
& EFI_IFR_NUMERIC_SIZE
));
1801 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
1802 if (EFI_ERROR (Status
)) {
1806 if (BlockData
== NULL
) {
1808 // BlockData == NULL means this opcode is not in the requst array.
1813 if (IfrOpHdr
->OpCode
== EFI_IFR_ONE_OF_OP
) {
1815 // Set this flag to TRUE for the first oneof option.
1817 FirstOneOfOption
= TRUE
;
1818 } else if (IfrOpHdr
->OpCode
== EFI_IFR_NUMERIC_OP
) {
1820 // Numeric minimum value will be used as default value when no default is specified.
1822 DefaultData
.Type
= DefaultValueFromDefault
;
1823 switch (IfrOneOf
->Flags
& EFI_IFR_NUMERIC_SIZE
) {
1824 case EFI_IFR_NUMERIC_SIZE_1
:
1825 DefaultData
.Value
.u8
= IfrOneOf
->data
.u8
.MinValue
;
1828 case EFI_IFR_NUMERIC_SIZE_2
:
1829 CopyMem (&DefaultData
.Value
.u16
, &IfrOneOf
->data
.u16
.MinValue
, sizeof (UINT16
));
1832 case EFI_IFR_NUMERIC_SIZE_4
:
1833 CopyMem (&DefaultData
.Value
.u32
, &IfrOneOf
->data
.u32
.MinValue
, sizeof (UINT32
));
1836 case EFI_IFR_NUMERIC_SIZE_8
:
1837 CopyMem (&DefaultData
.Value
.u64
, &IfrOneOf
->data
.u64
.MinValue
, sizeof (UINT64
));
1841 Status
= EFI_INVALID_PARAMETER
;
1845 // Set default value base on the DefaultId list get from IFR data.
1847 for (LinkData
= DefaultIdArray
->Entry
.ForwardLink
; LinkData
!= &DefaultIdArray
->Entry
; LinkData
= LinkData
->ForwardLink
) {
1848 DefaultDataPtr
= BASE_CR (LinkData
, IFR_DEFAULT_DATA
, Entry
);
1849 DefaultData
.DefaultId
= DefaultDataPtr
->DefaultId
;
1850 InsertDefaultValue (BlockData
, &DefaultData
);
1855 case EFI_IFR_ORDERED_LIST_OP
:
1857 // offset by question header
1858 // width by EFI_IFR_ORDERED_LIST MaxContainers * OneofOption Type
1859 // no default value and default id, how to define its default value?
1863 // OrderedList question is not in IFR Form. This IFR form is not valid.
1865 if (VarStoreId
== 0) {
1866 Status
= EFI_INVALID_PARAMETER
;
1870 // Check whether this question is for the requested varstore.
1872 IfrOrderedList
= (EFI_IFR_ORDERED_LIST
*) IfrOpHdr
;
1873 if (IfrOrderedList
->Question
.VarStoreId
!= VarStoreId
) {
1877 VarWidth
= IfrOrderedList
->MaxContainers
;
1878 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
1879 if (EFI_ERROR (Status
)) {
1884 case EFI_IFR_CHECKBOX_OP
:
1886 // EFI_IFR_DEFAULT_OP
1887 // offset by question header
1888 // width is 1 sizeof (BOOLEAN)
1889 // default id by CheckBox Flags if CheckBox flags (Default or Mau) is set, the default value is 1 to be set.
1890 // value by DefaultOption
1891 // default id by DeaultOption DefaultId can override CheckBox Flags and Default value.
1895 // CheckBox question is not in IFR Form. This IFR form is not valid.
1897 if (VarStoreId
== 0) {
1898 Status
= EFI_INVALID_PARAMETER
;
1902 // Check whether this question is for the requested varstore.
1904 IfrCheckBox
= (EFI_IFR_CHECKBOX
*) IfrOpHdr
;
1905 if (IfrCheckBox
->Question
.VarStoreId
!= VarStoreId
) {
1908 VarWidth
= (UINT16
) sizeof (BOOLEAN
);
1909 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
1910 if (EFI_ERROR (Status
)) {
1914 if (BlockData
== NULL
) {
1916 // BlockData == NULL means this opcode is not in the requst array.
1922 // Add default value for standard ID by CheckBox Flag
1924 VarDefaultId
= EFI_HII_DEFAULT_CLASS_STANDARD
;
1926 // Prepare new DefaultValue
1928 DefaultData
.DefaultId
= VarDefaultId
;
1929 if ((IfrCheckBox
->Flags
& EFI_IFR_CHECKBOX_DEFAULT
) == EFI_IFR_CHECKBOX_DEFAULT
) {
1931 // When flag is set, defautl value is TRUE.
1933 DefaultData
.Type
= DefaultValueFromFlag
;
1934 DefaultData
.Value
.b
= TRUE
;
1937 // When flag is not set, defautl value is FASLE.
1939 DefaultData
.Type
= DefaultValueFromDefault
;
1940 DefaultData
.Value
.b
= FALSE
;
1943 // Add DefaultValue into current BlockData
1945 InsertDefaultValue (BlockData
, &DefaultData
);
1948 // Add default value for Manufacture ID by CheckBox Flag
1950 VarDefaultId
= EFI_HII_DEFAULT_CLASS_MANUFACTURING
;
1952 // Prepare new DefaultValue
1954 DefaultData
.DefaultId
= VarDefaultId
;
1955 if ((IfrCheckBox
->Flags
& EFI_IFR_CHECKBOX_DEFAULT_MFG
) == EFI_IFR_CHECKBOX_DEFAULT_MFG
) {
1957 // When flag is set, defautl value is TRUE.
1959 DefaultData
.Type
= DefaultValueFromFlag
;
1960 DefaultData
.Value
.b
= TRUE
;
1963 // When flag is not set, defautl value is FASLE.
1965 DefaultData
.Type
= DefaultValueFromDefault
;
1966 DefaultData
.Value
.b
= FALSE
;
1969 // Add DefaultValue into current BlockData
1971 InsertDefaultValue (BlockData
, &DefaultData
);
1974 case EFI_IFR_DATE_OP
:
1976 // offset by question header
1977 // width MaxSize * sizeof (CHAR16)
1978 // no default value, only block array
1982 // Date question is not in IFR Form. This IFR form is not valid.
1984 if (VarStoreId
== 0) {
1985 Status
= EFI_INVALID_PARAMETER
;
1989 // Check whether this question is for the requested varstore.
1991 IfrDate
= (EFI_IFR_DATE
*) IfrOpHdr
;
1992 if (IfrDate
->Question
.VarStoreId
!= VarStoreId
) {
1996 VarWidth
= (UINT16
) sizeof (EFI_HII_DATE
);
1997 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
1998 if (EFI_ERROR (Status
)) {
2003 case EFI_IFR_TIME_OP
:
2005 // offset by question header
2006 // width MaxSize * sizeof (CHAR16)
2007 // no default value, only block array
2011 // Time question is not in IFR Form. This IFR form is not valid.
2013 if (VarStoreId
== 0) {
2014 Status
= EFI_INVALID_PARAMETER
;
2018 // Check whether this question is for the requested varstore.
2020 IfrTime
= (EFI_IFR_TIME
*) IfrOpHdr
;
2021 if (IfrTime
->Question
.VarStoreId
!= VarStoreId
) {
2025 VarWidth
= (UINT16
) sizeof (EFI_HII_TIME
);
2026 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
2027 if (EFI_ERROR (Status
)) {
2032 case EFI_IFR_STRING_OP
:
2034 // offset by question header
2035 // width MaxSize * sizeof (CHAR16)
2036 // no default value, only block array
2040 // String question is not in IFR Form. This IFR form is not valid.
2042 if (VarStoreId
== 0) {
2043 Status
= EFI_INVALID_PARAMETER
;
2047 // Check whether this question is for the requested varstore.
2049 IfrString
= (EFI_IFR_STRING
*) IfrOpHdr
;
2050 if (IfrString
->Question
.VarStoreId
!= VarStoreId
) {
2054 VarWidth
= (UINT16
) (IfrString
->MaxSize
* sizeof (UINT16
));
2055 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
2056 if (EFI_ERROR (Status
)) {
2061 case EFI_IFR_PASSWORD_OP
:
2063 // offset by question header
2064 // width MaxSize * sizeof (CHAR16)
2065 // no default value, only block array
2069 // Password question is not in IFR Form. This IFR form is not valid.
2071 if (VarStoreId
== 0) {
2072 Status
= EFI_INVALID_PARAMETER
;
2076 // Check whether this question is for the requested varstore.
2078 IfrPassword
= (EFI_IFR_PASSWORD
*) IfrOpHdr
;
2079 if (IfrPassword
->Question
.VarStoreId
!= VarStoreId
) {
2083 VarWidth
= (UINT16
) (IfrPassword
->MaxSize
* sizeof (UINT16
));
2084 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
2085 if (EFI_ERROR (Status
)) {
2090 // No default value for string.
2095 case EFI_IFR_ONE_OF_OPTION_OP
:
2097 // No matched block data is ignored.
2099 if (BlockData
== NULL
|| BlockData
->Scope
== 0) {
2103 IfrOneOfOption
= (EFI_IFR_ONE_OF_OPTION
*) IfrOpHdr
;
2104 if (BlockData
->OpCode
== EFI_IFR_ORDERED_LIST_OP
) {
2106 // Get ordered list option data type.
2108 if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_8
|| IfrOneOfOption
->Type
== EFI_IFR_TYPE_BOOLEAN
) {
2110 } else if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_16
) {
2112 } else if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_32
) {
2114 } else if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_64
) {
2118 // Invalid ordered list option data type.
2120 Status
= EFI_INVALID_PARAMETER
;
2121 if (BlockData
->Name
!= NULL
) {
2122 FreePool (BlockData
->Name
);
2124 FreePool (BlockData
);
2129 // Calculate Ordered list QuestionId width.
2131 BlockData
->Width
= (UINT16
) (BlockData
->Width
* VarWidth
);
2133 // Check whether this question is in requested block array.
2135 if (!BlockArrayCheck (RequestBlockArray
, BlockData
->Offset
, BlockData
->Width
, (BOOLEAN
)(BlockData
->Name
!= NULL
), HiiHandle
)) {
2137 // This question is not in the requested string. Skip it.
2139 if (BlockData
->Name
!= NULL
) {
2140 FreePool (BlockData
->Name
);
2142 FreePool (BlockData
);
2147 // Check this var question is in the var storage
2149 if ((BlockData
->Name
== NULL
) && ((BlockData
->Offset
+ BlockData
->Width
) > VarStorageData
->Size
)) {
2150 Status
= EFI_INVALID_PARAMETER
;
2151 if (BlockData
->Name
!= NULL
) {
2152 FreePool (BlockData
->Name
);
2154 FreePool (BlockData
);
2158 // Add Block Data into VarStorageData BlockEntry
2160 InsertBlockData (&VarStorageData
->BlockEntry
, &BlockData
);
2162 // No default data for OrderedList.
2169 // 1. Set default value for OneOf option when flag field has default attribute.
2171 if (((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT
) == EFI_IFR_OPTION_DEFAULT
) ||
2172 ((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT_MFG
) == EFI_IFR_OPTION_DEFAULT_MFG
)) {
2174 // This flag is used to specify whether this option is the first. Set it to FALSE for the following options.
2175 // The first oneof option value will be used as default value when no default value is specified.
2177 FirstOneOfOption
= FALSE
;
2179 // Prepare new DefaultValue
2181 DefaultData
.Type
= DefaultValueFromFlag
;
2182 CopyMem (&DefaultData
.Value
, &IfrOneOfOption
->Value
, IfrOneOfOption
->Header
.Length
- OFFSET_OF (EFI_IFR_ONE_OF_OPTION
, Value
));
2183 if ((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT
) == EFI_IFR_OPTION_DEFAULT
) {
2184 DefaultData
.DefaultId
= EFI_HII_DEFAULT_CLASS_STANDARD
;
2185 InsertDefaultValue (BlockData
, &DefaultData
);
2187 if ((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT_MFG
) == EFI_IFR_OPTION_DEFAULT_MFG
) {
2188 DefaultData
.DefaultId
= EFI_HII_DEFAULT_CLASS_MANUFACTURING
;
2189 InsertDefaultValue (BlockData
, &DefaultData
);
2194 // 2. Set as the default value when this is the first option.
2195 // The first oneof option value will be used as default value when no default value is specified.
2197 if (FirstOneOfOption
) {
2198 // This flag is used to specify whether this option is the first. Set it to FALSE for the following options.
2199 FirstOneOfOption
= FALSE
;
2202 // Prepare new DefaultValue
2204 DefaultData
.Type
= DefaultValueFromDefault
;
2205 CopyMem (&DefaultData
.Value
, &IfrOneOfOption
->Value
, IfrOneOfOption
->Header
.Length
- OFFSET_OF (EFI_IFR_ONE_OF_OPTION
, Value
));
2206 for (LinkData
= DefaultIdArray
->Entry
.ForwardLink
; LinkData
!= &DefaultIdArray
->Entry
; LinkData
= LinkData
->ForwardLink
) {
2207 DefaultDataPtr
= BASE_CR (LinkData
, IFR_DEFAULT_DATA
, Entry
);
2208 DefaultData
.DefaultId
= DefaultDataPtr
->DefaultId
;
2209 InsertDefaultValue (BlockData
, &DefaultData
);
2214 case EFI_IFR_DEFAULT_OP
:
2216 // Update Current BlockData to the default value.
2218 if (BlockData
== NULL
|| BlockData
->Scope
== 0) {
2220 // No matched block data is ignored.
2225 if (BlockData
->OpCode
== EFI_IFR_ORDERED_LIST_OP
) {
2227 // OrderedList Opcode is no default value.
2232 // Get the DefaultId
2234 IfrDefault
= (EFI_IFR_DEFAULT
*) IfrOpHdr
;
2235 VarDefaultId
= IfrDefault
->DefaultId
;
2237 // Prepare new DefaultValue
2239 DefaultData
.Type
= DefaultValueFromOpcode
;
2240 DefaultData
.DefaultId
= VarDefaultId
;
2241 CopyMem (&DefaultData
.Value
, &IfrDefault
->Value
, IfrDefault
->Header
.Length
- OFFSET_OF (EFI_IFR_DEFAULT
, Value
));
2243 // If the value field is expression, set the cleaned flag.
2244 if (IfrDefault
->Type
== EFI_IFR_TYPE_OTHER
) {
2245 DefaultData
.Cleaned
= TRUE
;
2248 // Add DefaultValue into current BlockData
2250 InsertDefaultValue (BlockData
, &DefaultData
);
2253 // After insert the default value, reset the cleaned value for next
2254 // time used. If not set here, need to set the value before everytime
2257 DefaultData
.Cleaned
= FALSE
;
2260 case EFI_IFR_END_OP
:
2262 // End Opcode is for Var question.
2264 if (BlockData
!= NULL
) {
2265 if (BlockData
->Scope
> 0) {
2268 if (BlockData
->Scope
== 0) {
2276 if (BlockData
!= NULL
) {
2277 if (BlockData
->Scope
> 0) {
2278 BlockData
->Scope
= (UINT8
) (BlockData
->Scope
+ IfrOpHdr
->Scope
);
2281 if (BlockData
->Scope
== 0) {
2288 IfrOffset
+= IfrOpHdr
->Length
;
2289 PackageOffset
+= IfrOpHdr
->Length
;
2293 for (LinkData
= VarStorageData
->BlockEntry
.ForwardLink
; LinkData
!= &VarStorageData
->BlockEntry
; LinkData
= LinkData
->ForwardLink
) {
2294 BlockData
= BASE_CR (LinkData
, IFR_BLOCK_DATA
, Entry
);
2295 for (LinkDefault
= BlockData
->DefaultValueEntry
.ForwardLink
; LinkDefault
!= &BlockData
->DefaultValueEntry
; ) {
2296 DefaultDataPtr
= BASE_CR (LinkDefault
, IFR_DEFAULT_DATA
, Entry
);
2297 LinkDefault
= LinkDefault
->ForwardLink
;
2298 if (DefaultDataPtr
->Cleaned
== TRUE
) {
2299 RemoveEntryList (&DefaultDataPtr
->Entry
);
2300 FreePool (DefaultDataPtr
);
2309 parse the configrequest string, get the elements.
2311 @param ConfigRequest The input configrequest string.
2312 @param Progress Return the progress data.
2314 @retval Block data pointer.
2318 IN EFI_STRING ConfigRequest
,
2319 OUT EFI_STRING
*Progress
2322 EFI_STRING StringPtr
;
2323 IFR_BLOCK_DATA
*BlockData
;
2324 IFR_BLOCK_DATA
*RequestBlockArray
;
2330 IFR_BLOCK_DATA
*NextBlockData
;
2336 // Init RequestBlockArray
2338 RequestBlockArray
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
2339 if (RequestBlockArray
== NULL
) {
2342 InitializeListHead (&RequestBlockArray
->Entry
);
2345 // Get the request Block array from the request string
2350 // Parse each <RequestElement> if exists
2351 // Only <BlockName> format is supported by this help function.
2352 // <BlockName> ::= &'OFFSET='<Number>&'WIDTH='<Number>
2354 StringPtr
= ConfigRequest
;
2355 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) == 0) {
2357 // Skip the OFFSET string
2359 *Progress
= StringPtr
;
2360 StringPtr
+= StrLen (L
"&OFFSET=");
2364 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
2365 if (EFI_ERROR (Status
)) {
2372 (((Length
+ 1) / 2) < sizeof (UINT16
)) ? ((Length
+ 1) / 2) : sizeof (UINT16
)
2374 FreePool (TmpBuffer
);
2376 StringPtr
+= Length
;
2377 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
2380 StringPtr
+= StrLen (L
"&WIDTH=");
2385 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
2386 if (EFI_ERROR (Status
)) {
2393 (((Length
+ 1) / 2) < sizeof (UINT16
)) ? ((Length
+ 1) / 2) : sizeof (UINT16
)
2395 FreePool (TmpBuffer
);
2397 StringPtr
+= Length
;
2398 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
2405 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
2406 if (BlockData
== NULL
) {
2409 BlockData
->Offset
= Offset
;
2410 BlockData
->Width
= Width
;
2411 InsertBlockData (&RequestBlockArray
->Entry
, &BlockData
);
2414 // Skip &VALUE string if &VALUE does exists.
2416 if (StrnCmp (StringPtr
, L
"&VALUE=", StrLen (L
"&VALUE=")) == 0) {
2417 StringPtr
+= StrLen (L
"&VALUE=");
2422 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
2423 if (EFI_ERROR (Status
)) {
2427 StringPtr
+= Length
;
2428 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
2433 // If '\0', parsing is finished.
2435 if (*StringPtr
== 0) {
2441 // Merge the requested block data.
2443 Link
= RequestBlockArray
->Entry
.ForwardLink
;
2444 while ((Link
!= &RequestBlockArray
->Entry
) && (Link
->ForwardLink
!= &RequestBlockArray
->Entry
)) {
2445 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
2446 NextBlockData
= BASE_CR (Link
->ForwardLink
, IFR_BLOCK_DATA
, Entry
);
2447 if ((NextBlockData
->Offset
>= BlockData
->Offset
) && (NextBlockData
->Offset
<= (BlockData
->Offset
+ BlockData
->Width
))) {
2448 if ((NextBlockData
->Offset
+ NextBlockData
->Width
) > (BlockData
->Offset
+ BlockData
->Width
)) {
2449 BlockData
->Width
= (UINT16
) (NextBlockData
->Offset
+ NextBlockData
->Width
- BlockData
->Offset
);
2451 RemoveEntryList (Link
->ForwardLink
);
2452 FreePool (NextBlockData
);
2455 Link
= Link
->ForwardLink
;
2458 return RequestBlockArray
;
2461 if (RequestBlockArray
!= NULL
) {
2463 // Free Link Array RequestBlockArray
2465 while (!IsListEmpty (&RequestBlockArray
->Entry
)) {
2466 BlockData
= BASE_CR (RequestBlockArray
->Entry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
2467 RemoveEntryList (&BlockData
->Entry
);
2468 FreePool (BlockData
);
2471 FreePool (RequestBlockArray
);
2478 parse the configrequest string, get the elements.
2480 @param ConfigRequest The input config request string.
2481 @param Progress Return the progress data.
2483 @retval return data block array.
2487 IN EFI_STRING ConfigRequest
,
2488 OUT EFI_STRING
*Progress
2491 EFI_STRING StringPtr
;
2493 IFR_BLOCK_DATA
*BlockData
;
2494 IFR_BLOCK_DATA
*RequestBlockArray
;
2497 StringPtr
= ConfigRequest
;
2500 // Init RequestBlockArray
2502 RequestBlockArray
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
2503 if (RequestBlockArray
== NULL
) {
2506 InitializeListHead (&RequestBlockArray
->Entry
);
2509 // Get the request Block array from the request string
2513 // Parse each <RequestElement> if exists
2514 // Only <BlockName> format is supported by this help function.
2515 // <BlockName> ::= &'Name***=***
2517 while (StringPtr
!= NULL
&& *StringPtr
== L
'&') {
2519 *Progress
= StringPtr
;
2521 // Skip the L"&" string
2526 if ((NextTag
= StrStr (StringPtr
, L
"=")) != NULL
) {
2529 } else if ((NextTag
= StrStr (StringPtr
, L
"&")) != NULL
) {
2536 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
2537 if (BlockData
== NULL
) {
2544 BlockData
->Name
= AllocateCopyPool(StrSize (StringPtr
), StringPtr
);
2545 InsertBlockData (&RequestBlockArray
->Entry
, &BlockData
);
2549 // If has value, skip the value.
2551 StringPtr
= NextTag
+ 1;
2553 StringPtr
= StrStr (StringPtr
, L
"&");
2554 } else if (NextTag
!= NULL
) {
2556 // restore the '&' text.
2558 StringPtr
= NextTag
;
2563 return RequestBlockArray
;
2566 if (RequestBlockArray
!= NULL
) {
2568 // Free Link Array RequestBlockArray
2570 while (!IsListEmpty (&RequestBlockArray
->Entry
)) {
2571 BlockData
= BASE_CR (RequestBlockArray
->Entry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
2572 RemoveEntryList (&BlockData
->Entry
);
2573 if (BlockData
->Name
!= NULL
) {
2574 FreePool (BlockData
->Name
);
2576 FreePool (BlockData
);
2579 FreePool (RequestBlockArray
);
2586 Generate ConfigRequest string base on the varstore info.
2588 @param ConfigHdr The config header for this varstore.
2589 @param VarStorageData The varstore info.
2590 @param Status Return Status.
2591 @param ConfigRequest The ConfigRequest info may be return.
2593 @retval TRUE Need to continue
2594 @retval Others NO need to continue or error occur.
2597 GenerateConfigRequest (
2598 IN CHAR16
*ConfigHdr
,
2599 IN IFR_VARSTORAGE_DATA
*VarStorageData
,
2600 OUT EFI_STATUS
*Status
,
2601 IN OUT EFI_STRING
*ConfigRequest
2607 CHAR16
*FullConfigRequest
;
2609 IFR_BLOCK_DATA
*BlockData
;
2612 // Append VarStorageData BlockEntry into *Request string
2613 // Now support only one varstore in a form package.
2617 // Go through all VarStorageData Entry and get BlockEntry for each one for the multiple varstore in a single form package
2618 // Then construct them all to return MultiRequest string : ConfigHdr BlockConfig
2622 // Compute the length of the entire request starting with <ConfigHdr> and a
2626 Length
= StrLen (ConfigHdr
) + 1;
2628 for (Link
= VarStorageData
->BlockEntry
.ForwardLink
; Link
!= &VarStorageData
->BlockEntry
; Link
= Link
->ForwardLink
) {
2630 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
2631 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2633 // Add <BlockName> length for each Name
2635 // <BlockName> ::= &Name1&Name2&...
2636 // |1| StrLen(Name1)
2638 Length
= Length
+ (1 + StrLen (BlockData
->Name
));
2641 // Add <BlockName> length for each Offset/Width pair
2643 // <BlockName> ::= &OFFSET=1234&WIDTH=1234
2644 // | 8 | 4 | 7 | 4 |
2646 Length
= Length
+ (8 + 4 + 7 + 4);
2650 // No any request block data is found. The request string can't be constructed.
2653 *Status
= EFI_SUCCESS
;
2658 // Allocate buffer for the entire <ConfigRequest>
2660 FullConfigRequest
= AllocateZeroPool (Length
* sizeof (CHAR16
));
2661 if (FullConfigRequest
== NULL
) {
2662 *Status
= EFI_OUT_OF_RESOURCES
;
2665 StringPtr
= FullConfigRequest
;
2668 // Start with <ConfigHdr>
2670 StrCpyS (StringPtr
, Length
, ConfigHdr
);
2671 StringPtr
+= StrLen (StringPtr
);
2674 // Loop through all the Offset/Width pairs and append them to ConfigRequest
2676 for (Link
= VarStorageData
->BlockEntry
.ForwardLink
; Link
!= &VarStorageData
->BlockEntry
; Link
= Link
->ForwardLink
) {
2677 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
2678 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2684 (1 + StrLen (BlockData
->Name
) + 1) * sizeof (CHAR16
),
2690 // Append &OFFSET=XXXX&WIDTH=YYYY\0
2694 (8 + 4 + 7 + 4 + 1) * sizeof (CHAR16
),
2695 L
"&OFFSET=%04X&WIDTH=%04X",
2700 StringPtr
+= StrLen (StringPtr
);
2703 // Set to the got full request string.
2705 HiiToLower (FullConfigRequest
);
2707 if (*ConfigRequest
!= NULL
) {
2708 FreePool (*ConfigRequest
);
2710 *ConfigRequest
= FullConfigRequest
;
2716 Generate ConfigRequest Header base on the varstore info.
2718 @param VarStorageData The varstore info.
2719 @param DevicePath Device path for this varstore.
2720 @param ConfigHdr The config header for this varstore.
2722 @retval EFI_SUCCESS Generate the header success.
2723 @retval EFI_OUT_OF_RESOURCES Allocate buffer fail.
2727 IN IFR_VARSTORAGE_DATA
*VarStorageData
,
2728 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
2729 OUT EFI_STRING
*ConfigHdr
2738 Status
= EFI_SUCCESS
;
2744 // Construct <ConfigHdr> : "GUID=...&NAME=...&PATH=..." by VarStorageData Guid, Name and DriverHandle
2746 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*) &VarStorageData
->Guid
, 1, &GuidStr
);
2747 if (VarStorageData
->Name
!= NULL
) {
2748 GenerateSubStr (L
"NAME=", StrLen (VarStorageData
->Name
) * sizeof (CHAR16
), (VOID
*) VarStorageData
->Name
, 2, &NameStr
);
2750 GenerateSubStr (L
"NAME=", 0, NULL
, 2, &NameStr
);
2754 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) DevicePath
),
2755 (VOID
*) DevicePath
,
2759 Length
= StrLen (GuidStr
) + StrLen (NameStr
) + StrLen (PathStr
) + 1;
2760 if (VarStorageData
->Name
== NULL
) {
2764 *ConfigHdr
= AllocateZeroPool (Length
* sizeof (CHAR16
));
2765 if (*ConfigHdr
== NULL
) {
2766 Status
= EFI_OUT_OF_RESOURCES
;
2769 StrCpyS (*ConfigHdr
, Length
, GuidStr
);
2770 StrCatS (*ConfigHdr
, Length
, NameStr
);
2771 if (VarStorageData
->Name
== NULL
) {
2772 StrCatS (*ConfigHdr
, Length
, L
"&");
2774 StrCatS (*ConfigHdr
, Length
, PathStr
);
2777 // Remove the last character L'&'
2779 *(*ConfigHdr
+ StrLen (*ConfigHdr
) - 1) = L
'\0';
2782 if (GuidStr
!= NULL
) {
2786 if (NameStr
!= NULL
) {
2790 if (PathStr
!= NULL
) {
2798 Get Data buffer size based on data type.
2800 @param ValueType The input data type.
2802 @retval The data buffer size for the input type.
2809 UINT16 StorageWidth
;
2811 switch (ValueType
) {
2812 case EFI_IFR_NUMERIC_SIZE_1
:
2813 case EFI_IFR_TYPE_BOOLEAN
:
2814 StorageWidth
= (UINT16
) sizeof (UINT8
);
2817 case EFI_IFR_NUMERIC_SIZE_2
:
2818 StorageWidth
= (UINT16
) sizeof (UINT16
);
2821 case EFI_IFR_NUMERIC_SIZE_4
:
2822 StorageWidth
= (UINT16
) sizeof (UINT32
);
2825 case EFI_IFR_NUMERIC_SIZE_8
:
2826 StorageWidth
= (UINT16
) sizeof (UINT64
);
2829 case EFI_IFR_TYPE_TIME
:
2830 StorageWidth
= (UINT16
) sizeof (EFI_IFR_TIME
);
2833 case EFI_IFR_TYPE_DATE
:
2834 StorageWidth
= (UINT16
) sizeof (EFI_IFR_DATE
);
2842 return StorageWidth
;
2846 Generate ConfigAltResp string base on the varstore info.
2848 @param HiiHandle Hii Handle for this hii package.
2849 @param ConfigHdr The config header for this varstore.
2850 @param VarStorageData The varstore info.
2851 @param DefaultIdArray The Default id array.
2852 @param DefaultAltCfgResp The DefaultAltCfgResp info may be return.
2854 @retval TRUE Need to continue
2855 @retval Others NO need to continue or error occur.
2858 GenerateAltConfigResp (
2859 IN EFI_HII_HANDLE HiiHandle
,
2860 IN CHAR16
*ConfigHdr
,
2861 IN IFR_VARSTORAGE_DATA
*VarStorageData
,
2862 IN IFR_DEFAULT_DATA
*DefaultIdArray
,
2863 IN OUT EFI_STRING
*DefaultAltCfgResp
2869 LIST_ENTRY
*LinkData
;
2870 LIST_ENTRY
*LinkDefault
;
2871 LIST_ENTRY
*ListEntry
;
2873 IFR_BLOCK_DATA
*BlockData
;
2874 IFR_DEFAULT_DATA
*DefaultId
;
2875 IFR_DEFAULT_DATA
*DefaultValueData
;
2878 CHAR16
*DefaultString
;
2882 DefaultString
= NULL
;
2884 // Add length for <ConfigHdr> + '\0'
2886 Length
= StrLen (ConfigHdr
) + 1;
2888 for (Link
= DefaultIdArray
->Entry
.ForwardLink
; Link
!= &DefaultIdArray
->Entry
; Link
= Link
->ForwardLink
) {
2889 DefaultId
= BASE_CR (Link
, IFR_DEFAULT_DATA
, Entry
);
2891 // Add length for "&<ConfigHdr>&ALTCFG=XXXX"
2892 // |1| StrLen (ConfigHdr) | 8 | 4 |
2894 Length
+= (1 + StrLen (ConfigHdr
) + 8 + 4);
2896 for (LinkData
= VarStorageData
->BlockEntry
.ForwardLink
; LinkData
!= &VarStorageData
->BlockEntry
; LinkData
= LinkData
->ForwardLink
) {
2897 BlockData
= BASE_CR (LinkData
, IFR_BLOCK_DATA
, Entry
);
2898 ListEntry
= &BlockData
->DefaultValueEntry
;
2899 for (LinkDefault
= ListEntry
->ForwardLink
; LinkDefault
!= ListEntry
; LinkDefault
= LinkDefault
->ForwardLink
) {
2900 DefaultValueData
= BASE_CR (LinkDefault
, IFR_DEFAULT_DATA
, Entry
);
2901 if (DefaultValueData
->DefaultId
!= DefaultId
->DefaultId
) {
2904 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2906 // Add length for "&Name1=zzzzzzzzzzzz"
2909 Length
+= (1 + StrLen (BlockData
->Name
) + 1 + BlockData
->Width
* 2);
2912 // Add length for "&OFFSET=XXXX&WIDTH=YYYY&VALUE=zzzzzzzzzzzz"
2913 // | 8 | 4 | 7 | 4 | 7 | Width * 2 |
2915 Length
+= (8 + 4 + 7 + 4 + 7 + BlockData
->Width
* 2);
2923 // No default value is found. The default string doesn't exist.
2930 // Allocate buffer for the entire <DefaultAltCfgResp>
2932 *DefaultAltCfgResp
= AllocateZeroPool (Length
* sizeof (CHAR16
));
2933 if (*DefaultAltCfgResp
== NULL
) {
2934 return EFI_OUT_OF_RESOURCES
;
2936 StringPtr
= *DefaultAltCfgResp
;
2939 // Start with <ConfigHdr>
2941 StrCpyS (StringPtr
, Length
, ConfigHdr
);
2942 StringPtr
+= StrLen (StringPtr
);
2944 for (Link
= DefaultIdArray
->Entry
.ForwardLink
; Link
!= &DefaultIdArray
->Entry
; Link
= Link
->ForwardLink
) {
2945 DefaultId
= BASE_CR (Link
, IFR_DEFAULT_DATA
, Entry
);
2947 // Add <AltConfigHdr> of the form "&<ConfigHdr>&ALTCFG=XXXX\0"
2948 // |1| StrLen (ConfigHdr) | 8 | 4 |
2952 (1 + StrLen (ConfigHdr
) + 8 + 4 + 1) * sizeof (CHAR16
),
2955 DefaultId
->DefaultId
2957 StringPtr
+= StrLen (StringPtr
);
2959 for (LinkData
= VarStorageData
->BlockEntry
.ForwardLink
; LinkData
!= &VarStorageData
->BlockEntry
; LinkData
= LinkData
->ForwardLink
) {
2960 BlockData
= BASE_CR (LinkData
, IFR_BLOCK_DATA
, Entry
);
2961 ListEntry
= &BlockData
->DefaultValueEntry
;
2962 for (LinkDefault
= ListEntry
->ForwardLink
; LinkDefault
!= ListEntry
; LinkDefault
= LinkDefault
->ForwardLink
) {
2963 DefaultValueData
= BASE_CR (LinkDefault
, IFR_DEFAULT_DATA
, Entry
);
2964 if (DefaultValueData
->DefaultId
!= DefaultId
->DefaultId
) {
2967 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2970 (1 + StrLen (ConfigHdr
) + 1) * sizeof (CHAR16
),
2974 StringPtr
+= StrLen (StringPtr
);
2977 // Add <BlockConfig>
2978 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>
2982 (8 + 4 + 7 + 4 + 7 + 1) * sizeof (CHAR16
),
2983 L
"&OFFSET=%04X&WIDTH=%04X&VALUE=",
2987 StringPtr
+= StrLen (StringPtr
);
2989 Width
= BlockData
->Width
;
2991 // Convert Value to a hex string in "%x" format
2992 // NOTE: This is in the opposite byte that GUID and PATH use
2994 if (BlockData
->OpCode
== EFI_IFR_STRING_OP
){
2995 DefaultString
= InternalGetString(HiiHandle
, DefaultValueData
->Value
.string
);
2996 TmpBuffer
= (UINT8
*) DefaultString
;
2998 TmpBuffer
= (UINT8
*) &(DefaultValueData
->Value
);
3000 for (; Width
> 0 && (TmpBuffer
!= NULL
); Width
--) {
3001 StringPtr
+= UnicodeValueToString (StringPtr
, PREFIX_ZERO
| RADIX_HEX
, TmpBuffer
[Width
- 1], 2);
3003 if (DefaultString
!= NULL
){
3004 FreePool(DefaultString
);
3005 DefaultString
= NULL
;
3011 HiiToLower (*DefaultAltCfgResp
);
3017 This function gets the full request string and full default value string by
3018 parsing IFR data in HII form packages.
3020 When Request points to NULL string, the request string and default value string
3021 for each varstore in form package will return.
3023 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
3024 @param DevicePath Device Path which Hii Config Access Protocol is registered.
3025 @param Request Pointer to a null-terminated Unicode string in
3026 <ConfigRequest> format. When it doesn't contain
3027 any RequestElement, it will be updated to return
3028 the full RequestElement retrieved from IFR data.
3029 If it points to NULL, the request string for the first
3030 varstore in form package will be merged into a
3031 <MultiConfigRequest> format string and return.
3032 @param AltCfgResp Pointer to a null-terminated Unicode string in
3033 <ConfigAltResp> format. When the pointer is to NULL,
3034 the full default value string retrieved from IFR data
3035 will return. When the pinter is to a string, the
3036 full default value string retrieved from IFR data
3037 will be merged into the input string and return.
3038 When Request points to NULL, the default value string
3039 for each varstore in form package will be merged into
3040 a <MultiConfigAltResp> format string and return.
3041 @param PointerProgress Optional parameter, it can be be NULL.
3042 When it is not NULL, if Request is NULL, it returns NULL.
3043 On return, points to a character in the Request
3044 string. Points to the string's null terminator if
3045 request was successful. Points to the most recent
3046 & before the first failing name / value pair (or
3047 the beginning of the string if the failure is in
3048 the first name / value pair) if the request was
3050 @retval EFI_SUCCESS The Results string is set to the full request string.
3051 And AltCfgResp contains all default value string.
3052 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
3053 @retval EFI_NOT_FOUND The varstore (Guid and Name) in Request string
3054 can't be found in Form package.
3055 @retval EFI_NOT_FOUND HiiPackage can't be got on the input HiiHandle.
3056 @retval EFI_INVALID_PARAMETER Request points to NULL.
3061 GetFullStringFromHiiFormPackages (
3062 IN HII_DATABASE_RECORD
*DataBaseRecord
,
3063 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
3064 IN OUT EFI_STRING
*Request
,
3065 IN OUT EFI_STRING
*AltCfgResp
,
3066 OUT EFI_STRING
*PointerProgress OPTIONAL
3070 UINT8
*HiiFormPackage
;
3072 IFR_BLOCK_DATA
*RequestBlockArray
;
3073 IFR_BLOCK_DATA
*BlockData
;
3074 IFR_DEFAULT_DATA
*DefaultValueData
;
3075 IFR_DEFAULT_DATA
*DefaultId
;
3076 IFR_DEFAULT_DATA
*DefaultIdArray
;
3077 IFR_VARSTORAGE_DATA
*VarStorageData
;
3078 EFI_STRING DefaultAltCfgResp
;
3079 EFI_STRING ConfigHdr
;
3080 EFI_STRING StringPtr
;
3081 EFI_STRING Progress
;
3083 if (DataBaseRecord
== NULL
|| DevicePath
== NULL
|| Request
== NULL
|| AltCfgResp
== NULL
) {
3084 return EFI_INVALID_PARAMETER
;
3088 // Initialize the local variables.
3090 RequestBlockArray
= NULL
;
3091 DefaultIdArray
= NULL
;
3092 VarStorageData
= NULL
;
3093 DefaultAltCfgResp
= NULL
;
3095 HiiFormPackage
= NULL
;
3097 Progress
= *Request
;
3099 Status
= GetFormPackageData (DataBaseRecord
, &HiiFormPackage
, &PackageSize
);
3100 if (EFI_ERROR (Status
)) {
3105 // 1. Get the request block array by Request String when Request string containts the block array.
3108 if (*Request
!= NULL
) {
3109 StringPtr
= *Request
;
3113 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
3114 Status
= EFI_INVALID_PARAMETER
;
3117 StringPtr
+= StrLen (L
"GUID=");
3118 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&NAME=", StrLen (L
"&NAME=")) != 0) {
3121 if (*StringPtr
== L
'\0') {
3122 Status
= EFI_INVALID_PARAMETER
;
3125 StringPtr
+= StrLen (L
"&NAME=");
3126 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&PATH=", StrLen (L
"&PATH=")) != 0) {
3129 if (*StringPtr
== L
'\0') {
3130 Status
= EFI_INVALID_PARAMETER
;
3133 StringPtr
+= StrLen (L
"&PATH=");
3134 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
3138 if (*StringPtr
== L
'\0') {
3140 // No request block is found.
3147 // If StringPtr != NULL, get the request elements.
3149 if (StringPtr
!= NULL
) {
3150 if (StrStr (StringPtr
, L
"&OFFSET=") != NULL
) {
3151 RequestBlockArray
= GetBlockElement(StringPtr
, &Progress
);
3153 RequestBlockArray
= GetNameElement(StringPtr
, &Progress
);
3156 if (RequestBlockArray
== NULL
) {
3157 Status
= EFI_INVALID_PARAMETER
;
3163 // Initialize DefaultIdArray to store the map between DeaultId and DefaultName
3165 DefaultIdArray
= (IFR_DEFAULT_DATA
*) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
3166 if (DefaultIdArray
== NULL
) {
3167 Status
= EFI_OUT_OF_RESOURCES
;
3170 InitializeListHead (&DefaultIdArray
->Entry
);
3173 // Initialize VarStorageData to store the var store Block and Default value information.
3175 VarStorageData
= (IFR_VARSTORAGE_DATA
*) AllocateZeroPool (sizeof (IFR_VARSTORAGE_DATA
));
3176 if (VarStorageData
== NULL
) {
3177 Status
= EFI_OUT_OF_RESOURCES
;
3180 InitializeListHead (&VarStorageData
->Entry
);
3181 InitializeListHead (&VarStorageData
->BlockEntry
);
3184 // 2. Parse FormPackage to get BlockArray and DefaultId Array for the request BlockArray.
3188 // Parse the opcode in form pacakge to get the default setting.
3190 Status
= ParseIfrData (DataBaseRecord
->Handle
,
3192 (UINT32
) PackageSize
,
3197 if (EFI_ERROR (Status
)) {
3202 // No requested varstore in IFR data and directly return
3204 if (VarStorageData
->Type
== 0 && VarStorageData
->Name
== NULL
) {
3205 Status
= EFI_SUCCESS
;
3210 // 3. Construct Request Element (Block Name) for 2.1 and 2.2 case.
3212 Status
= GenerateHdr (VarStorageData
, DevicePath
, &ConfigHdr
);
3213 if (EFI_ERROR (Status
)) {
3217 if (RequestBlockArray
== NULL
) {
3218 if (!GenerateConfigRequest(ConfigHdr
, VarStorageData
, &Status
, Request
)) {
3224 // 4. Construct Default Value string in AltResp according to request element.
3225 // Go through all VarStorageData Entry and get the DefaultId array for each one
3226 // Then construct them all to : ConfigHdr AltConfigHdr ConfigBody AltConfigHdr ConfigBody
3228 Status
= GenerateAltConfigResp (DataBaseRecord
->Handle
,ConfigHdr
, VarStorageData
, DefaultIdArray
, &DefaultAltCfgResp
);
3229 if (EFI_ERROR (Status
)) {
3234 // 5. Merge string into the input AltCfgResp if the iput *AltCfgResp is not NULL.
3236 if (*AltCfgResp
!= NULL
&& DefaultAltCfgResp
!= NULL
) {
3237 Status
= MergeDefaultString (AltCfgResp
, DefaultAltCfgResp
);
3238 FreePool (DefaultAltCfgResp
);
3239 } else if (*AltCfgResp
== NULL
) {
3240 *AltCfgResp
= DefaultAltCfgResp
;
3244 if (RequestBlockArray
!= NULL
) {
3246 // Free Link Array RequestBlockArray
3248 while (!IsListEmpty (&RequestBlockArray
->Entry
)) {
3249 BlockData
= BASE_CR (RequestBlockArray
->Entry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
3250 RemoveEntryList (&BlockData
->Entry
);
3251 if (BlockData
->Name
!= NULL
) {
3252 FreePool (BlockData
->Name
);
3254 FreePool (BlockData
);
3257 FreePool (RequestBlockArray
);
3260 if (VarStorageData
!= NULL
) {
3262 // Free link array VarStorageData
3264 while (!IsListEmpty (&VarStorageData
->BlockEntry
)) {
3265 BlockData
= BASE_CR (VarStorageData
->BlockEntry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
3266 RemoveEntryList (&BlockData
->Entry
);
3267 if (BlockData
->Name
!= NULL
) {
3268 FreePool (BlockData
->Name
);
3271 // Free default value link array
3273 while (!IsListEmpty (&BlockData
->DefaultValueEntry
)) {
3274 DefaultValueData
= BASE_CR (BlockData
->DefaultValueEntry
.ForwardLink
, IFR_DEFAULT_DATA
, Entry
);
3275 RemoveEntryList (&DefaultValueData
->Entry
);
3276 FreePool (DefaultValueData
);
3278 FreePool (BlockData
);
3280 FreePool (VarStorageData
);
3283 if (DefaultIdArray
!= NULL
) {
3285 // Free DefaultId Array
3287 while (!IsListEmpty (&DefaultIdArray
->Entry
)) {
3288 DefaultId
= BASE_CR (DefaultIdArray
->Entry
.ForwardLink
, IFR_DEFAULT_DATA
, Entry
);
3289 RemoveEntryList (&DefaultId
->Entry
);
3290 FreePool (DefaultId
);
3292 FreePool (DefaultIdArray
);
3296 // Free the allocated string
3298 if (ConfigHdr
!= NULL
) {
3299 FreePool (ConfigHdr
);
3303 // Free Pacakge data
3305 if (HiiFormPackage
!= NULL
) {
3306 FreePool (HiiFormPackage
);
3309 if (PointerProgress
!= NULL
) {
3310 if (*Request
== NULL
) {
3311 *PointerProgress
= NULL
;
3312 } else if (EFI_ERROR (Status
)) {
3313 *PointerProgress
= *Request
;
3315 *PointerProgress
= *Request
+ StrLen (*Request
);
3323 This function gets the full request resp string by
3324 parsing IFR data in HII form packages.
3326 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
3328 @param EfiVarStoreInfo The efi varstore info which is save in the EFI
3329 varstore data structure.
3330 @param Request Pointer to a null-terminated Unicode string in
3331 <ConfigRequest> format.
3332 @param RequestResp Pointer to a null-terminated Unicode string in
3333 <ConfigResp> format.
3334 @param AccessProgress On return, points to a character in the Request
3335 string. Points to the string's null terminator if
3336 request was successful. Points to the most recent
3337 & before the first failing name / value pair (or
3338 the beginning of the string if the failure is in
3339 the first name / value pair) if the request was
3342 @retval EFI_SUCCESS The Results string is set to the full request string.
3343 And AltCfgResp contains all default value string.
3344 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
3345 @retval EFI_INVALID_PARAMETER Request points to NULL.
3349 GetConfigRespFromEfiVarStore (
3350 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
3351 IN EFI_IFR_VARSTORE_EFI
*EfiVarStoreInfo
,
3352 IN EFI_STRING Request
,
3353 OUT EFI_STRING
*RequestResp
,
3354 OUT EFI_STRING
*AccessProgress
3358 EFI_STRING VarStoreName
;
3362 Status
= EFI_SUCCESS
;
3365 VarStoreName
= NULL
;
3366 *AccessProgress
= Request
;
3368 VarStoreName
= AllocateZeroPool (AsciiStrSize ((CHAR8
*)EfiVarStoreInfo
->Name
) * sizeof (CHAR16
));
3369 if (VarStoreName
== NULL
) {
3370 Status
= EFI_OUT_OF_RESOURCES
;
3373 AsciiStrToUnicodeStr ((CHAR8
*) EfiVarStoreInfo
->Name
, VarStoreName
);
3376 Status
= gRT
->GetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, NULL
, &BufferSize
, NULL
);
3377 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
3381 VarStore
= AllocateZeroPool (BufferSize
);
3382 ASSERT (VarStore
!= NULL
);
3383 Status
= gRT
->GetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, NULL
, &BufferSize
, VarStore
);
3384 if (EFI_ERROR (Status
)) {
3388 Status
= HiiBlockToConfig(This
, Request
, VarStore
, BufferSize
, RequestResp
, AccessProgress
);
3389 if (EFI_ERROR (Status
)) {
3394 if (VarStoreName
!= NULL
) {
3395 FreePool (VarStoreName
);
3398 if (VarStore
!= NULL
) {
3399 FreePool (VarStore
);
3407 This function route the full request resp string for efi varstore.
3409 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
3411 @param EfiVarStoreInfo The efi varstore info which is save in the EFI
3412 varstore data structure.
3413 @param RequestResp Pointer to a null-terminated Unicode string in
3414 <ConfigResp> format.
3415 @param Result Pointer to a null-terminated Unicode string in
3416 <ConfigResp> format.
3418 @retval EFI_SUCCESS The Results string is set to the full request string.
3419 And AltCfgResp contains all default value string.
3420 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
3421 @retval EFI_INVALID_PARAMETER Request points to NULL.
3425 RouteConfigRespForEfiVarStore (
3426 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
3427 IN EFI_IFR_VARSTORE_EFI
*EfiVarStoreInfo
,
3428 IN EFI_STRING RequestResp
,
3429 OUT EFI_STRING
*Result
3433 EFI_STRING VarStoreName
;
3438 Status
= EFI_SUCCESS
;
3441 VarStoreName
= NULL
;
3443 VarStoreName
= AllocateZeroPool (AsciiStrSize ((CHAR8
*)EfiVarStoreInfo
->Name
) * sizeof (CHAR16
));
3444 if (VarStoreName
== NULL
) {
3445 Status
= EFI_OUT_OF_RESOURCES
;
3448 AsciiStrToUnicodeStr ((CHAR8
*) EfiVarStoreInfo
->Name
, VarStoreName
);
3450 Status
= gRT
->GetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, NULL
, &BufferSize
, NULL
);
3451 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
3455 BlockSize
= BufferSize
;
3456 VarStore
= AllocateZeroPool (BufferSize
);
3457 ASSERT (VarStore
!= NULL
);
3458 Status
= gRT
->GetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, NULL
, &BufferSize
, VarStore
);
3459 if (EFI_ERROR (Status
)) {
3463 Status
= HiiConfigToBlock(This
, RequestResp
, VarStore
, &BlockSize
, Result
);
3464 if (EFI_ERROR (Status
)) {
3468 Status
= gRT
->SetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, EfiVarStoreInfo
->Attributes
, BufferSize
, VarStore
);
3469 if (EFI_ERROR (Status
)) {
3474 if (VarStoreName
!= NULL
) {
3475 FreePool (VarStoreName
);
3478 if (VarStore
!= NULL
) {
3479 FreePool (VarStore
);
3486 Validate the config request elements.
3488 @param ConfigElements A null-terminated Unicode string in <ConfigRequest> format,
3489 without configHdr field.
3491 @retval CHAR16 * THE first Name/value pair not correct.
3492 @retval NULL Success parse the name/value pair
3495 OffsetWidthValidate (
3496 CHAR16
*ConfigElements
3502 StringPtr
= ConfigElements
;
3506 if (StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) != 0) {
3510 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
3513 if (*StringPtr
== L
'\0') {
3517 StringPtr
+= StrLen (L
"&WIDTH=");
3518 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) != 0) {
3522 if (*StringPtr
== L
'\0') {
3529 Validate the config request elements.
3531 @param ConfigElements A null-terminated Unicode string in <ConfigRequest> format,
3532 without configHdr field.
3534 @retval CHAR16 * THE first Name/value pair not correct.
3535 @retval NULL Success parse the name/value pair
3540 CHAR16
*ConfigElements
3546 StringPtr
= ConfigElements
;
3550 if (*StringPtr
!= L
'&') {
3555 StringPtr
= StrStr (StringPtr
, L
"&");
3557 if (StringPtr
== NULL
) {
3564 Validate the config request string.
3566 @param ConfigRequest A null-terminated Unicode string in <ConfigRequest> format.
3568 @retval CHAR16 * THE first element not correct.
3569 @retval NULL Success parse the name/value pair
3573 ConfigRequestValidate (
3574 CHAR16
*ConfigRequest
3577 BOOLEAN HasNameField
;
3580 HasNameField
= TRUE
;
3581 StringPtr
= ConfigRequest
;
3584 // Check <ConfigHdr>
3586 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
3587 return ConfigRequest
;
3589 StringPtr
+= StrLen (L
"GUID=");
3590 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&NAME=", StrLen (L
"&NAME=")) != 0) {
3593 if (*StringPtr
== L
'\0') {
3594 return ConfigRequest
;
3596 StringPtr
+= StrLen (L
"&NAME=");
3597 if (*StringPtr
== L
'&') {
3598 HasNameField
= FALSE
;
3600 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&PATH=", StrLen (L
"&PATH=")) != 0) {
3603 if (*StringPtr
== L
'\0') {
3604 return ConfigRequest
;
3606 StringPtr
+= StrLen (L
"&PATH=");
3607 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
3611 if (*StringPtr
== L
'\0') {
3617 // Should be Buffer varstore, config request should be "OFFSET/Width" pairs.
3619 return OffsetWidthValidate(StringPtr
);
3622 // Should be Name/Value varstore, config request should be "&name1&name2..." pairs.
3624 return NameValueValidate(StringPtr
);
3629 This function allows a caller to extract the current configuration
3630 for one or more named elements from one or more drivers.
3632 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
3634 @param Request A null-terminated Unicode string in
3635 <MultiConfigRequest> format.
3636 @param Progress On return, points to a character in the Request
3637 string. Points to the string's null terminator if
3638 request was successful. Points to the most recent
3639 & before the first failing name / value pair (or
3640 the beginning of the string if the failure is in
3641 the first name / value pair) if the request was
3643 @param Results Null-terminated Unicode string in
3644 <MultiConfigAltResp> format which has all values
3645 filled in for the names in the Request string.
3646 String to be allocated by the called function.
3648 @retval EFI_SUCCESS The Results string is filled with the values
3649 corresponding to all requested names.
3650 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
3651 results that must be stored awaiting possible
3653 @retval EFI_NOT_FOUND Routing data doesn't match any known driver.
3654 Progress set to the "G" in "GUID" of the routing
3655 header that doesn't match. Note: There is no
3656 requirement that all routing data be validated
3657 before any configuration extraction.
3658 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Request
3659 parameter would result in this type of error. The
3660 Progress parameter is set to NULL.
3661 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set to most recent &
3662 before the error or the beginning of the string.
3663 @retval EFI_INVALID_PARAMETER The ExtractConfig function of the underlying HII
3664 Configuration Access Protocol returned
3665 EFI_INVALID_PARAMETER. Progress set to most recent
3666 & before the error or the beginning of the string.
3671 HiiConfigRoutingExtractConfig (
3672 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
3673 IN CONST EFI_STRING Request
,
3674 OUT EFI_STRING
*Progress
,
3675 OUT EFI_STRING
*Results
3678 HII_DATABASE_PRIVATE_DATA
*Private
;
3679 EFI_STRING StringPtr
;
3680 EFI_STRING ConfigRequest
;
3682 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
3683 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
3686 HII_DATABASE_RECORD
*Database
;
3687 UINT8
*DevicePathPkg
;
3688 UINT8
*CurrentDevicePath
;
3689 EFI_HANDLE DriverHandle
;
3690 EFI_HII_HANDLE HiiHandle
;
3691 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
3692 EFI_STRING AccessProgress
;
3693 EFI_STRING AccessResults
;
3694 EFI_STRING DefaultResults
;
3695 BOOLEAN FirstElement
;
3696 BOOLEAN IfrDataParsedFlag
;
3697 BOOLEAN IsEfiVarStore
;
3698 EFI_IFR_VARSTORE_EFI
*EfiVarStoreInfo
;
3699 EFI_STRING ErrorPtr
;
3700 UINTN DevicePathSize
;
3702 if (This
== NULL
|| Progress
== NULL
|| Results
== NULL
) {
3703 return EFI_INVALID_PARAMETER
;
3706 if (Request
== NULL
) {
3708 return EFI_INVALID_PARAMETER
;
3711 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
3712 StringPtr
= Request
;
3713 *Progress
= StringPtr
;
3714 DefaultResults
= NULL
;
3715 ConfigRequest
= NULL
;
3716 Status
= EFI_SUCCESS
;
3717 AccessResults
= NULL
;
3718 AccessProgress
= NULL
;
3720 IfrDataParsedFlag
= FALSE
;
3721 IsEfiVarStore
= FALSE
;
3722 EfiVarStoreInfo
= NULL
;
3725 // The first element of <MultiConfigRequest> should be
3726 // <GuidHdr>, which is in 'GUID='<Guid> syntax.
3728 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
3729 return EFI_INVALID_PARAMETER
;
3732 FirstElement
= TRUE
;
3735 // Allocate a fix length of memory to store Results. Reallocate memory for
3736 // Results if this fix length is insufficient.
3738 *Results
= (EFI_STRING
) AllocateZeroPool (MAX_STRING_LENGTH
);
3739 if (*Results
== NULL
) {
3740 return EFI_OUT_OF_RESOURCES
;
3743 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) == 0) {
3745 // If parsing error, set Progress to the beginning of the <MultiConfigRequest>
3746 // or most recent & before the error.
3748 if (StringPtr
== Request
) {
3749 *Progress
= StringPtr
;
3751 *Progress
= StringPtr
- 1;
3755 // Process each <ConfigRequest> of <MultiConfigRequest>
3757 Length
= CalculateConfigStringLen (StringPtr
);
3758 ConfigRequest
= AllocateCopyPool ((Length
+ 1) * sizeof (CHAR16
), StringPtr
);
3759 if (ConfigRequest
== NULL
) {
3760 Status
= EFI_OUT_OF_RESOURCES
;
3763 *(ConfigRequest
+ Length
) = 0;
3766 // Get the UEFI device path
3768 Status
= GetDevicePath (ConfigRequest
, (UINT8
**) &DevicePath
);
3769 if (EFI_ERROR (Status
)) {
3774 // Find driver which matches the routing data.
3776 DriverHandle
= NULL
;
3779 for (Link
= Private
->DatabaseList
.ForwardLink
;
3780 Link
!= &Private
->DatabaseList
;
3781 Link
= Link
->ForwardLink
3783 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
3784 if ((DevicePathPkg
= Database
->PackageList
->DevicePathPkg
) != NULL
) {
3785 CurrentDevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
3786 DevicePathSize
= GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) CurrentDevicePath
);
3787 if ((CompareMem (DevicePath
,CurrentDevicePath
,DevicePathSize
) == 0) && IsThisPackageList(Database
, ConfigRequest
)) {
3788 DriverHandle
= Database
->DriverHandle
;
3789 HiiHandle
= Database
->Handle
;
3796 // Try to find driver handle by device path.
3798 if (DriverHandle
== NULL
) {
3799 TempDevicePath
= DevicePath
;
3800 Status
= gBS
->LocateDevicePath (
3801 &gEfiDevicePathProtocolGuid
,
3805 if (EFI_ERROR (Status
) || (DriverHandle
== NULL
)) {
3807 // Routing data does not match any known driver.
3808 // Set Progress to the 'G' in "GUID" of the routing header.
3810 *Progress
= StringPtr
;
3811 Status
= EFI_NOT_FOUND
;
3817 // Validate ConfigRequest String.
3819 ErrorPtr
= ConfigRequestValidate(ConfigRequest
);
3820 if (ErrorPtr
!= NULL
) {
3821 *Progress
= StrStr (StringPtr
, ErrorPtr
);
3822 Status
= EFI_INVALID_PARAMETER
;
3827 // Check whether ConfigRequest contains request string.
3829 IfrDataParsedFlag
= FALSE
;
3830 if ((HiiHandle
!= NULL
) && !GetElementsFromRequest(ConfigRequest
)) {
3832 // Get the full request string from IFR when HiiPackage is registered to HiiHandle
3834 IfrDataParsedFlag
= TRUE
;
3835 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &ConfigRequest
, &DefaultResults
, &AccessProgress
);
3836 if (EFI_ERROR (Status
)) {
3838 // AccessProgress indicates the parsing progress on <ConfigRequest>.
3839 // Map it to the progress on <MultiConfigRequest> then return it.
3841 ASSERT (AccessProgress
!= NULL
);
3842 *Progress
= StrStr (StringPtr
, AccessProgress
);
3846 // Not any request block is found.
3848 if (!GetElementsFromRequest(ConfigRequest
)) {
3849 AccessResults
= AllocateCopyPool (StrSize (ConfigRequest
), ConfigRequest
);
3850 goto NextConfigString
;
3855 // Check whether this ConfigRequest is search from Efi varstore type storage.
3857 Status
= GetVarStoreType(Database
, ConfigRequest
, &IsEfiVarStore
, &EfiVarStoreInfo
);
3858 if (EFI_ERROR (Status
)) {
3862 if (IsEfiVarStore
) {
3864 // Call the GetVariable function to extract settings.
3866 Status
= GetConfigRespFromEfiVarStore(This
, EfiVarStoreInfo
, ConfigRequest
, &AccessResults
, &AccessProgress
);
3867 FreePool (EfiVarStoreInfo
);
3870 // Call corresponding ConfigAccess protocol to extract settings
3872 Status
= gBS
->HandleProtocol (
3874 &gEfiHiiConfigAccessProtocolGuid
,
3875 (VOID
**) &ConfigAccess
3877 ASSERT_EFI_ERROR (Status
);
3879 Status
= ConfigAccess
->ExtractConfig (
3886 if (EFI_ERROR (Status
)) {
3888 // AccessProgress indicates the parsing progress on <ConfigRequest>.
3889 // Map it to the progress on <MultiConfigRequest> then return it.
3891 *Progress
= StrStr (StringPtr
, AccessProgress
);
3896 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'
3897 // which seperates the first <ConfigAltResp> and the following ones.
3899 ASSERT (*AccessProgress
== 0);
3902 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
3904 if (!IfrDataParsedFlag
&& HiiHandle
!= NULL
) {
3905 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &ConfigRequest
, &DefaultResults
, NULL
);
3906 ASSERT_EFI_ERROR (Status
);
3909 FreePool (DevicePath
);
3912 if (DefaultResults
!= NULL
) {
3913 Status
= MergeDefaultString (&AccessResults
, DefaultResults
);
3914 ASSERT_EFI_ERROR (Status
);
3915 FreePool (DefaultResults
);
3916 DefaultResults
= NULL
;
3920 if (!FirstElement
) {
3921 Status
= AppendToMultiString (Results
, L
"&");
3922 ASSERT_EFI_ERROR (Status
);
3925 Status
= AppendToMultiString (Results
, AccessResults
);
3926 ASSERT_EFI_ERROR (Status
);
3928 FirstElement
= FALSE
;
3930 FreePool (AccessResults
);
3931 AccessResults
= NULL
;
3932 FreePool (ConfigRequest
);
3933 ConfigRequest
= NULL
;
3936 // Go to next <ConfigRequest> (skip '&').
3938 StringPtr
+= Length
;
3939 if (*StringPtr
== 0) {
3940 *Progress
= StringPtr
;
3948 if (EFI_ERROR (Status
)) {
3949 FreePool (*Results
);
3953 if (ConfigRequest
!= NULL
) {
3954 FreePool (ConfigRequest
);
3957 if (AccessResults
!= NULL
) {
3958 FreePool (AccessResults
);
3961 if (DefaultResults
!= NULL
) {
3962 FreePool (DefaultResults
);
3965 if (DevicePath
!= NULL
) {
3966 FreePool (DevicePath
);
3974 This function allows the caller to request the current configuration for the
3975 entirety of the current HII database and returns the data in a
3976 null-terminated Unicode string.
3978 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
3980 @param Results Null-terminated Unicode string in
3981 <MultiConfigAltResp> format which has all values
3982 filled in for the entirety of the current HII
3983 database. String to be allocated by the called
3984 function. De-allocation is up to the caller.
3986 @retval EFI_SUCCESS The Results string is filled with the values
3987 corresponding to all requested names.
3988 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
3989 results that must be stored awaiting possible
3991 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Results
3992 parameter would result in this type of error.
3997 HiiConfigRoutingExportConfig (
3998 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
3999 OUT EFI_STRING
*Results
4003 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
4004 EFI_STRING AccessResults
;
4005 EFI_STRING Progress
;
4006 EFI_STRING StringPtr
;
4007 EFI_STRING ConfigRequest
;
4009 EFI_HANDLE
*ConfigAccessHandles
;
4010 UINTN NumberConfigAccessHandles
;
4011 BOOLEAN FirstElement
;
4012 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
4013 EFI_HII_HANDLE HiiHandle
;
4014 EFI_STRING DefaultResults
;
4015 HII_DATABASE_PRIVATE_DATA
*Private
;
4017 HII_DATABASE_RECORD
*Database
;
4018 UINT8
*DevicePathPkg
;
4019 UINT8
*CurrentDevicePath
;
4020 BOOLEAN IfrDataParsedFlag
;
4022 if (This
== NULL
|| Results
== NULL
) {
4023 return EFI_INVALID_PARAMETER
;
4026 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
4029 // Allocate a fix length of memory to store Results. Reallocate memory for
4030 // Results if this fix length is insufficient.
4032 *Results
= (EFI_STRING
) AllocateZeroPool (MAX_STRING_LENGTH
);
4033 if (*Results
== NULL
) {
4034 return EFI_OUT_OF_RESOURCES
;
4037 NumberConfigAccessHandles
= 0;
4038 Status
= gBS
->LocateHandleBuffer (
4040 &gEfiHiiConfigAccessProtocolGuid
,
4042 &NumberConfigAccessHandles
,
4043 &ConfigAccessHandles
4045 if (EFI_ERROR (Status
)) {
4049 FirstElement
= TRUE
;
4051 for (Index
= 0; Index
< NumberConfigAccessHandles
; Index
++) {
4052 Status
= gBS
->HandleProtocol (
4053 ConfigAccessHandles
[Index
],
4054 &gEfiHiiConfigAccessProtocolGuid
,
4055 (VOID
**) &ConfigAccess
4057 if (EFI_ERROR (Status
)) {
4062 // Get DevicePath and HiiHandle for this ConfigAccess driver handle
4064 IfrDataParsedFlag
= FALSE
;
4067 DefaultResults
= NULL
;
4069 ConfigRequest
= NULL
;
4070 DevicePath
= DevicePathFromHandle (ConfigAccessHandles
[Index
]);
4071 if (DevicePath
!= NULL
) {
4072 for (Link
= Private
->DatabaseList
.ForwardLink
;
4073 Link
!= &Private
->DatabaseList
;
4074 Link
= Link
->ForwardLink
4076 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
4077 if ((DevicePathPkg
= Database
->PackageList
->DevicePathPkg
) != NULL
) {
4078 CurrentDevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
4082 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) CurrentDevicePath
)
4084 HiiHandle
= Database
->Handle
;
4091 Status
= ConfigAccess
->ExtractConfig (
4097 if (EFI_ERROR (Status
)) {
4099 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
4101 if (HiiHandle
!= NULL
&& DevicePath
!= NULL
) {
4102 IfrDataParsedFlag
= TRUE
;
4103 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &ConfigRequest
, &DefaultResults
, NULL
);
4105 // Get the full request string to get the Current setting again.
4107 if (!EFI_ERROR (Status
) && ConfigRequest
!= NULL
) {
4108 Status
= ConfigAccess
->ExtractConfig (
4114 FreePool (ConfigRequest
);
4116 Status
= EFI_NOT_FOUND
;
4121 if (!EFI_ERROR (Status
)) {
4123 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
4125 if (!IfrDataParsedFlag
&& HiiHandle
!= NULL
&& DevicePath
!= NULL
) {
4126 StringPtr
= StrStr (AccessResults
, L
"&GUID=");
4127 if (StringPtr
!= NULL
) {
4130 if (GetElementsFromRequest (AccessResults
)) {
4131 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &AccessResults
, &DefaultResults
, NULL
);
4132 ASSERT_EFI_ERROR (Status
);
4134 if (StringPtr
!= NULL
) {
4139 // Merge the default sting from IFR code into the got setting from driver.
4141 if (DefaultResults
!= NULL
) {
4142 Status
= MergeDefaultString (&AccessResults
, DefaultResults
);
4143 ASSERT_EFI_ERROR (Status
);
4144 FreePool (DefaultResults
);
4145 DefaultResults
= NULL
;
4149 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'
4150 // which seperates the first <ConfigAltResp> and the following ones.
4152 if (!FirstElement
) {
4153 Status
= AppendToMultiString (Results
, L
"&");
4154 ASSERT_EFI_ERROR (Status
);
4157 Status
= AppendToMultiString (Results
, AccessResults
);
4158 ASSERT_EFI_ERROR (Status
);
4160 FirstElement
= FALSE
;
4162 FreePool (AccessResults
);
4163 AccessResults
= NULL
;
4166 FreePool (ConfigAccessHandles
);
4173 This function processes the results of processing forms and routes it to the
4174 appropriate handlers or storage.
4176 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
4178 @param Configuration A null-terminated Unicode string in
4179 <MulltiConfigResp> format.
4180 @param Progress A pointer to a string filled in with the offset of
4181 the most recent & before the first failing name /
4182 value pair (or the beginning of the string if the
4183 failure is in the first name / value pair) or the
4184 terminating NULL if all was successful.
4186 @retval EFI_SUCCESS The results have been distributed or are awaiting
4188 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
4189 results that must be stored awaiting possible
4191 @retval EFI_INVALID_PARAMETER Passing in a NULL for the Configuration parameter
4192 would result in this type of error.
4193 @retval EFI_NOT_FOUND Target for the specified routing data was not
4199 HiiConfigRoutingRouteConfig (
4200 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
4201 IN CONST EFI_STRING Configuration
,
4202 OUT EFI_STRING
*Progress
4205 HII_DATABASE_PRIVATE_DATA
*Private
;
4206 EFI_STRING StringPtr
;
4207 EFI_STRING ConfigResp
;
4210 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
4211 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
4213 HII_DATABASE_RECORD
*Database
;
4214 UINT8
*DevicePathPkg
;
4215 UINT8
*CurrentDevicePath
;
4216 EFI_HANDLE DriverHandle
;
4217 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
4218 EFI_STRING AccessProgress
;
4219 EFI_IFR_VARSTORE_EFI
*EfiVarStoreInfo
;
4220 BOOLEAN IsEfiVarstore
;
4221 UINTN DevicePathSize
;
4223 if (This
== NULL
|| Progress
== NULL
) {
4224 return EFI_INVALID_PARAMETER
;
4227 if (Configuration
== NULL
) {
4229 return EFI_INVALID_PARAMETER
;
4232 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
4233 StringPtr
= Configuration
;
4234 *Progress
= StringPtr
;
4236 AccessProgress
= NULL
;
4237 EfiVarStoreInfo
= NULL
;
4238 IsEfiVarstore
= FALSE
;
4241 // The first element of <MultiConfigResp> should be
4242 // <GuidHdr>, which is in 'GUID='<Guid> syntax.
4244 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
4245 return EFI_INVALID_PARAMETER
;
4248 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) == 0) {
4250 // If parsing error, set Progress to the beginning of the <MultiConfigResp>
4251 // or most recent & before the error.
4253 if (StringPtr
== Configuration
) {
4254 *Progress
= StringPtr
;
4256 *Progress
= StringPtr
- 1;
4260 // Process each <ConfigResp> of <MultiConfigResp>
4262 Length
= CalculateConfigStringLen (StringPtr
);
4263 ConfigResp
= AllocateCopyPool ((Length
+ 1) * sizeof (CHAR16
), StringPtr
);
4264 if (ConfigResp
== NULL
) {
4265 return EFI_OUT_OF_RESOURCES
;
4268 // Append '\0' to the end of ConfigRequest
4270 *(ConfigResp
+ Length
) = 0;
4273 // Get the UEFI device path
4275 Status
= GetDevicePath (ConfigResp
, (UINT8
**) &DevicePath
);
4276 if (EFI_ERROR (Status
)) {
4277 FreePool (ConfigResp
);
4282 // Find driver which matches the routing data.
4284 DriverHandle
= NULL
;
4285 for (Link
= Private
->DatabaseList
.ForwardLink
;
4286 Link
!= &Private
->DatabaseList
;
4287 Link
= Link
->ForwardLink
4289 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
4291 if ((DevicePathPkg
= Database
->PackageList
->DevicePathPkg
) != NULL
) {
4292 CurrentDevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
4293 DevicePathSize
= GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) CurrentDevicePath
);
4294 if ((CompareMem (DevicePath
,CurrentDevicePath
,DevicePathSize
) == 0) && IsThisPackageList(Database
, ConfigResp
)) {
4295 DriverHandle
= Database
->DriverHandle
;
4302 // Try to find driver handle by device path.
4304 if (DriverHandle
== NULL
) {
4305 TempDevicePath
= DevicePath
;
4306 Status
= gBS
->LocateDevicePath (
4307 &gEfiDevicePathProtocolGuid
,
4311 if (EFI_ERROR (Status
) || (DriverHandle
== NULL
)) {
4313 // Routing data does not match any known driver.
4314 // Set Progress to the 'G' in "GUID" of the routing header.
4316 FreePool (DevicePath
);
4317 *Progress
= StringPtr
;
4318 FreePool (ConfigResp
);
4319 return EFI_NOT_FOUND
;
4323 FreePool (DevicePath
);
4326 // Check whether this ConfigRequest is search from Efi varstore type storage.
4328 Status
= GetVarStoreType(Database
, ConfigResp
, &IsEfiVarstore
, &EfiVarStoreInfo
);
4329 if (EFI_ERROR (Status
)) {
4333 if (IsEfiVarstore
) {
4335 // Call the SetVariable function to route settings.
4337 Status
= RouteConfigRespForEfiVarStore(This
, EfiVarStoreInfo
, ConfigResp
, &AccessProgress
);
4338 FreePool (EfiVarStoreInfo
);
4341 // Call corresponding ConfigAccess protocol to route settings
4343 Status
= gBS
->HandleProtocol (
4345 &gEfiHiiConfigAccessProtocolGuid
,
4346 (VOID
**) &ConfigAccess
4348 ASSERT_EFI_ERROR (Status
);
4350 Status
= ConfigAccess
->RouteConfig (
4356 if (EFI_ERROR (Status
)) {
4357 ASSERT (AccessProgress
!= NULL
);
4359 // AccessProgress indicates the parsing progress on <ConfigResp>.
4360 // Map it to the progress on <MultiConfigResp> then return it.
4362 *Progress
= StrStr (StringPtr
, AccessProgress
);
4364 FreePool (ConfigResp
);
4368 FreePool (ConfigResp
);
4372 // Go to next <ConfigResp> (skip '&').
4374 StringPtr
+= Length
;
4375 if (*StringPtr
== 0) {
4376 *Progress
= StringPtr
;
4389 This helper function is to be called by drivers to map configuration data
4390 stored in byte array ("block") formats such as UEFI Variables into current
4391 configuration strings.
4393 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
4395 @param ConfigRequest A null-terminated Unicode string in
4396 <ConfigRequest> format.
4397 @param Block Array of bytes defining the block's configuration.
4398 @param BlockSize Length in bytes of Block.
4399 @param Config Filled-in configuration string. String allocated
4400 by the function. Returned only if call is
4401 successful. It is <ConfigResp> string format.
4402 @param Progress A pointer to a string filled in with the offset of
4403 the most recent & before the first failing
4404 name/value pair (or the beginning of the string if
4405 the failure is in the first name / value pair) or
4406 the terminating NULL if all was successful.
4408 @retval EFI_SUCCESS The request succeeded. Progress points to the null
4409 terminator at the end of the ConfigRequest
4411 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress
4412 points to the first character of ConfigRequest.
4413 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigRequest or
4414 Block parameter would result in this type of
4415 error. Progress points to the first character of
4417 @retval EFI_DEVICE_ERROR Block not large enough. Progress undefined.
4418 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted string.
4419 Block is left updated and Progress points at
4420 the "&" preceding the first non-<BlockName>.
4426 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
4427 IN CONST EFI_STRING ConfigRequest
,
4428 IN CONST UINT8
*Block
,
4429 IN CONST UINTN BlockSize
,
4430 OUT EFI_STRING
*Config
,
4431 OUT EFI_STRING
*Progress
4434 HII_DATABASE_PRIVATE_DATA
*Private
;
4435 EFI_STRING StringPtr
;
4443 EFI_STRING ValueStr
;
4444 EFI_STRING ConfigElement
;
4452 if (This
== NULL
|| Progress
== NULL
|| Config
== NULL
) {
4453 return EFI_INVALID_PARAMETER
;
4456 if (Block
== NULL
|| ConfigRequest
== NULL
) {
4457 *Progress
= ConfigRequest
;
4458 return EFI_INVALID_PARAMETER
;
4462 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
4463 ASSERT (Private
!= NULL
);
4465 StringPtr
= ConfigRequest
;
4468 ConfigElement
= NULL
;
4471 // Allocate a fix length of memory to store Results. Reallocate memory for
4472 // Results if this fix length is insufficient.
4474 *Config
= (EFI_STRING
) AllocateZeroPool (MAX_STRING_LENGTH
);
4475 if (*Config
== NULL
) {
4476 return EFI_OUT_OF_RESOURCES
;
4482 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
4483 *Progress
= StringPtr
;
4484 Status
= EFI_INVALID_PARAMETER
;
4487 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"PATH=", StrLen (L
"PATH=")) != 0) {
4490 if (*StringPtr
== 0) {
4491 *Progress
= StringPtr
- 1;
4492 Status
= EFI_INVALID_PARAMETER
;
4496 while (*StringPtr
!= L
'&' && *StringPtr
!= 0) {
4499 if (*StringPtr
== 0) {
4500 *Progress
= StringPtr
;
4502 AppendToMultiString(Config
, ConfigRequest
);
4503 HiiToLower (*Config
);
4513 // Copy <ConfigHdr> and an additional '&' to <ConfigResp>
4515 TemChar
= *StringPtr
;
4517 AppendToMultiString(Config
, ConfigRequest
);
4518 *StringPtr
= TemChar
;
4521 // Parse each <RequestElement> if exists
4522 // Only <BlockName> format is supported by this help function.
4523 // <BlockName> ::= 'OFFSET='<Number>&'WIDTH='<Number>
4525 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"OFFSET=", StrLen (L
"OFFSET=")) == 0) {
4527 // Back up the header of one <BlockName>
4531 StringPtr
+= StrLen (L
"OFFSET=");
4535 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
4536 if (EFI_ERROR (Status
)) {
4537 *Progress
= TmpPtr
- 1;
4544 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
4546 FreePool (TmpBuffer
);
4548 StringPtr
+= Length
;
4549 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
4550 *Progress
= TmpPtr
- 1;
4551 Status
= EFI_INVALID_PARAMETER
;
4554 StringPtr
+= StrLen (L
"&WIDTH=");
4559 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
4560 if (EFI_ERROR (Status
)) {
4561 *Progress
= TmpPtr
- 1;
4568 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
4570 FreePool (TmpBuffer
);
4572 StringPtr
+= Length
;
4573 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
4574 *Progress
= TmpPtr
- 1;
4575 Status
= EFI_INVALID_PARAMETER
;
4580 // Calculate Value and convert it to hex string.
4582 if (Offset
+ Width
> BlockSize
) {
4583 *Progress
= StringPtr
;
4584 Status
= EFI_DEVICE_ERROR
;
4588 Value
= (UINT8
*) AllocateZeroPool (Width
);
4589 if (Value
== NULL
) {
4590 *Progress
= ConfigRequest
;
4591 Status
= EFI_OUT_OF_RESOURCES
;
4595 CopyMem (Value
, (UINT8
*) Block
+ Offset
, Width
);
4597 Length
= Width
* 2 + 1;
4598 ValueStr
= (EFI_STRING
) AllocateZeroPool (Length
* sizeof (CHAR16
));
4599 if (ValueStr
== NULL
) {
4600 *Progress
= ConfigRequest
;
4601 Status
= EFI_OUT_OF_RESOURCES
;
4605 TemString
= ValueStr
;
4606 TemBuffer
= Value
+ Width
- 1;
4607 for (Index
= 0; Index
< Width
; Index
++, TemBuffer
--) {
4608 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
4615 // Build a ConfigElement
4617 Length
+= StringPtr
- TmpPtr
+ 1 + StrLen (L
"VALUE=");
4618 ConfigElement
= (EFI_STRING
) AllocateZeroPool (Length
* sizeof (CHAR16
));
4619 if (ConfigElement
== NULL
) {
4620 Status
= EFI_OUT_OF_RESOURCES
;
4623 CopyMem (ConfigElement
, TmpPtr
, (StringPtr
- TmpPtr
+ 1) * sizeof (CHAR16
));
4624 if (*StringPtr
== 0) {
4625 *(ConfigElement
+ (StringPtr
- TmpPtr
)) = L
'&';
4627 *(ConfigElement
+ (StringPtr
- TmpPtr
) + 1) = 0;
4628 StrCatS (ConfigElement
, Length
, L
"VALUE=");
4629 StrCatS (ConfigElement
, Length
, ValueStr
);
4631 AppendToMultiString (Config
, ConfigElement
);
4633 FreePool (ConfigElement
);
4634 FreePool (ValueStr
);
4635 ConfigElement
= NULL
;
4639 // If '\0', parsing is finished. Otherwise skip '&' to continue
4641 if (*StringPtr
== 0) {
4644 AppendToMultiString (Config
, L
"&");
4649 if (*StringPtr
!= 0) {
4650 *Progress
= StringPtr
- 1;
4651 Status
= EFI_INVALID_PARAMETER
;
4655 HiiToLower (*Config
);
4656 *Progress
= StringPtr
;
4660 if (*Config
!= NULL
) {
4664 if (ValueStr
!= NULL
) {
4665 FreePool (ValueStr
);
4667 if (Value
!= NULL
) {
4670 if (ConfigElement
!= NULL
) {
4671 FreePool (ConfigElement
);
4680 This helper function is to be called by drivers to map configuration strings
4681 to configurations stored in byte array ("block") formats such as UEFI Variables.
4683 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
4685 @param ConfigResp A null-terminated Unicode string in <ConfigResp>
4687 @param Block A possibly null array of bytes representing the
4688 current block. Only bytes referenced in the
4689 ConfigResp string in the block are modified. If
4690 this parameter is null or if the *BlockSize
4691 parameter is (on input) shorter than required by
4692 the Configuration string, only the BlockSize
4693 parameter is updated and an appropriate status
4694 (see below) is returned.
4695 @param BlockSize The length of the Block in units of UINT8. On
4696 input, this is the size of the Block. On output,
4697 if successful, contains the largest index of the
4698 modified byte in the Block, or the required buffer
4699 size if the Block is not large enough.
4700 @param Progress On return, points to an element of the ConfigResp
4701 string filled in with the offset of the most
4702 recent '&' before the first failing name / value
4703 pair (or the beginning of the string if the
4704 failure is in the first name / value pair) or the
4705 terminating NULL if all was successful.
4707 @retval EFI_SUCCESS The request succeeded. Progress points to the null
4708 terminator at the end of the ConfigResp string.
4709 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress
4710 points to the first character of ConfigResp.
4711 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigResp or
4712 Block parameter would result in this type of
4713 error. Progress points to the first character of
4715 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted name /
4716 value pair. Block is left updated and
4717 Progress points at the '&' preceding the first
4719 @retval EFI_BUFFER_TOO_SMALL Block not large enough. Progress undefined.
4720 BlockSize is updated with the required buffer size.
4721 @retval EFI_NOT_FOUND Target for the specified routing data was not found.
4722 Progress points to the "G" in "GUID" of the errant
4729 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
4730 IN CONST EFI_STRING ConfigResp
,
4731 IN OUT UINT8
*Block
,
4732 IN OUT UINTN
*BlockSize
,
4733 OUT EFI_STRING
*Progress
4736 HII_DATABASE_PRIVATE_DATA
*Private
;
4737 EFI_STRING StringPtr
;
4750 if (This
== NULL
|| BlockSize
== NULL
|| Progress
== NULL
) {
4751 return EFI_INVALID_PARAMETER
;
4754 *Progress
= ConfigResp
;
4755 if (ConfigResp
== NULL
) {
4756 return EFI_INVALID_PARAMETER
;
4759 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
4760 ASSERT (Private
!= NULL
);
4762 StringPtr
= ConfigResp
;
4763 BufferSize
= *BlockSize
;
4770 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
4771 *Progress
= StringPtr
;
4772 Status
= EFI_INVALID_PARAMETER
;
4775 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"PATH=", StrLen (L
"PATH=")) != 0) {
4778 if (*StringPtr
== 0) {
4779 *Progress
= StringPtr
;
4780 Status
= EFI_INVALID_PARAMETER
;
4784 while (*StringPtr
!= L
'&' && *StringPtr
!= 0) {
4787 if (*StringPtr
== 0) {
4788 *Progress
= StringPtr
;
4789 Status
= EFI_INVALID_PARAMETER
;
4794 // Parse each <ConfigElement> if exists
4795 // Only '&'<BlockConfig> format is supported by this help function.
4796 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE='<Number>
4798 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) == 0) {
4800 StringPtr
+= StrLen (L
"&OFFSET=");
4804 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
4805 if (EFI_ERROR (Status
)) {
4813 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
4815 FreePool (TmpBuffer
);
4817 StringPtr
+= Length
;
4818 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
4820 Status
= EFI_INVALID_PARAMETER
;
4823 StringPtr
+= StrLen (L
"&WIDTH=");
4828 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
4829 if (EFI_ERROR (Status
)) {
4837 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
4839 FreePool (TmpBuffer
);
4841 StringPtr
+= Length
;
4842 if (StrnCmp (StringPtr
, L
"&VALUE=", StrLen (L
"&VALUE=")) != 0) {
4844 Status
= EFI_INVALID_PARAMETER
;
4847 StringPtr
+= StrLen (L
"&VALUE=");
4852 Status
= GetValueOfNumber (StringPtr
, &Value
, &Length
);
4853 if (EFI_ERROR (Status
)) {
4858 StringPtr
+= Length
;
4859 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
4861 Status
= EFI_INVALID_PARAMETER
;
4866 // Update the Block with configuration info
4868 if ((Block
!= NULL
) && (Offset
+ Width
<= BufferSize
)) {
4869 CopyMem (Block
+ Offset
, Value
, Width
);
4871 if (Offset
+ Width
> MaxBlockSize
) {
4872 MaxBlockSize
= Offset
+ Width
;
4879 // If '\0', parsing is finished.
4881 if (*StringPtr
== 0) {
4887 // The input string is not ConfigResp format, return error.
4889 if (*StringPtr
!= 0) {
4890 *Progress
= StringPtr
;
4891 Status
= EFI_INVALID_PARAMETER
;
4895 *Progress
= StringPtr
+ StrLen (StringPtr
);
4896 *BlockSize
= MaxBlockSize
- 1;
4898 if (MaxBlockSize
> BufferSize
) {
4899 *BlockSize
= MaxBlockSize
;
4900 if (Block
!= NULL
) {
4901 return EFI_BUFFER_TOO_SMALL
;
4905 if (Block
== NULL
) {
4906 *Progress
= ConfigResp
;
4907 return EFI_INVALID_PARAMETER
;
4914 if (Value
!= NULL
) {
4922 This helper function is to be called by drivers to extract portions of
4923 a larger configuration string.
4925 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
4927 @param Configuration A null-terminated Unicode string in
4928 <MultiConfigAltResp> format.
4929 @param Guid A pointer to the GUID value to search for in the
4930 routing portion of the ConfigResp string when
4931 retrieving the requested data. If Guid is NULL,
4932 then all GUID values will be searched for.
4933 @param Name A pointer to the NAME value to search for in the
4934 routing portion of the ConfigResp string when
4935 retrieving the requested data. If Name is NULL,
4936 then all Name values will be searched for.
4937 @param DevicePath A pointer to the PATH value to search for in the
4938 routing portion of the ConfigResp string when
4939 retrieving the requested data. If DevicePath is
4940 NULL, then all DevicePath values will be searched
4942 @param AltCfgId A pointer to the ALTCFG value to search for in the
4943 routing portion of the ConfigResp string when
4944 retrieving the requested data. If this parameter
4945 is NULL, then the current setting will be
4947 @param AltCfgResp A pointer to a buffer which will be allocated by
4948 the function which contains the retrieved string
4949 as requested. This buffer is only allocated if
4950 the call was successful. It is <ConfigResp> format.
4952 @retval EFI_SUCCESS The request succeeded. The requested data was
4953 extracted and placed in the newly allocated
4955 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate AltCfgResp.
4956 @retval EFI_INVALID_PARAMETER Any parameter is invalid.
4957 @retval EFI_NOT_FOUND Target for the specified routing data was not
4964 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
4965 IN CONST EFI_STRING Configuration
,
4966 IN CONST EFI_GUID
*Guid
,
4967 IN CONST EFI_STRING Name
,
4968 IN CONST EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
4969 IN CONST UINT16
*AltCfgId
,
4970 OUT EFI_STRING
*AltCfgResp
4974 EFI_STRING StringPtr
;
4975 EFI_STRING HdrStart
;
4982 EFI_STRING AltIdStr
;
4999 if (This
== NULL
|| Configuration
== NULL
|| AltCfgResp
== NULL
) {
5000 return EFI_INVALID_PARAMETER
;
5003 StringPtr
= Configuration
;
5004 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
5005 return EFI_INVALID_PARAMETER
;
5009 // Generate the sub string for later matching.
5011 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*) Guid
, 1, &GuidStr
);
5014 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) DevicePath
),
5015 (VOID
*) DevicePath
,
5019 if (AltCfgId
!= NULL
) {
5020 GenerateSubStr (L
"ALTCFG=", sizeof (UINT16
), (VOID
*) AltCfgId
, 3, &AltIdStr
);
5023 GenerateSubStr (L
"NAME=", StrLen (Name
) * sizeof (CHAR16
), (VOID
*) Name
, 2, &NameStr
);
5025 GenerateSubStr (L
"NAME=", 0, NULL
, 2, &NameStr
);
5028 while (*StringPtr
!= 0) {
5030 // Try to match the GUID
5033 TmpPtr
= StrStr (StringPtr
, GuidStr
);
5034 if (TmpPtr
== NULL
) {
5035 Status
= EFI_NOT_FOUND
;
5041 // Jump to <NameHdr>
5044 StringPtr
= TmpPtr
+ StrLen (GuidStr
);
5046 StringPtr
= StrStr (TmpPtr
, L
"NAME=");
5047 if (StringPtr
== NULL
) {
5048 Status
= EFI_NOT_FOUND
;
5056 // Try to match the NAME
5058 if (GuidFlag
&& !NameFlag
) {
5059 if (StrnCmp (StringPtr
, NameStr
, StrLen (NameStr
)) != 0) {
5063 // Jump to <PathHdr>
5066 StringPtr
+= StrLen (NameStr
);
5068 StringPtr
= StrStr (StringPtr
, L
"PATH=");
5069 if (StringPtr
== NULL
) {
5070 Status
= EFI_NOT_FOUND
;
5079 // Try to match the DevicePath
5081 if (GuidFlag
&& NameFlag
&& !PathFlag
) {
5082 if (StrnCmp (StringPtr
, PathStr
, StrLen (PathStr
)) != 0) {
5087 // Jump to '&' before <DescHdr> or <ConfigBody>
5089 if (DevicePath
!= NULL
) {
5090 StringPtr
+= StrLen (PathStr
);
5092 StringPtr
= StrStr (StringPtr
, L
"&");
5093 if (StringPtr
== NULL
) {
5094 Status
= EFI_NOT_FOUND
;
5105 // Try to match the AltCfgId
5107 if (GuidFlag
&& NameFlag
&& PathFlag
) {
5108 if (AltCfgId
== NULL
) {
5110 // Return Current Setting when AltCfgId is NULL.
5112 Status
= OutputConfigBody (StringPtr
, &Result
);
5116 // Search the <ConfigAltResp> to get the <AltResp> with AltCfgId.
5118 if (StrnCmp (StringPtr
, AltIdStr
, StrLen (AltIdStr
)) != 0) {
5124 // Skip AltIdStr and &
5126 StringPtr
= StringPtr
+ StrLen (AltIdStr
);
5127 Status
= OutputConfigBody (StringPtr
, &Result
);
5133 Status
= EFI_NOT_FOUND
;
5137 if (!EFI_ERROR (Status
) && (Result
!= NULL
)) {
5139 // Copy the <ConfigHdr> and <ConfigBody>
5141 Length
= HdrEnd
- HdrStart
+ StrLen (Result
) + 1;
5142 *AltCfgResp
= AllocateZeroPool (Length
* sizeof (CHAR16
));
5143 if (*AltCfgResp
== NULL
) {
5144 Status
= EFI_OUT_OF_RESOURCES
;
5146 StrnCpyS (*AltCfgResp
, Length
, HdrStart
, HdrEnd
- HdrStart
);
5147 StrCatS (*AltCfgResp
, Length
, Result
);
5148 Status
= EFI_SUCCESS
;
5152 if (GuidStr
!= NULL
) {
5155 if (NameStr
!= NULL
) {
5158 if (PathStr
!= NULL
) {
5161 if (AltIdStr
!= NULL
) {
5162 FreePool (AltIdStr
);
5164 if (Result
!= NULL
) {