2 Implementation of interfaces function for EFI_HII_CONFIG_ROUTING_PROTOCOL.
4 Copyright (c) 2007 - 2013, 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 StrCpy (Str
, String
);
256 Length
= (BufferLen
* 2 + 1) * sizeof (CHAR16
);
258 StringHeader
= Str
+ StrLen (String
);
259 TemString
= (CHAR16
*) StringHeader
;
264 // Convert Buffer to Hex String in reverse order
266 TemBuffer
= ((UINT8
*) Buffer
);
267 for (Index
= 0; Index
< BufferLen
; Index
++, TemBuffer
++) {
268 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
273 // Check buffer is enough
275 TemName
= (CHAR16
*) Buffer
;
276 ASSERT ((BufferLen
* 2 + 1) >= (StrLen (TemName
) * 4 + 1));
278 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
280 for (; *TemName
!= L
'\0'; TemName
++) {
281 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemName
, 4);
286 // Convert Buffer to Hex String
288 TemBuffer
= ((UINT8
*) Buffer
) + BufferLen
- 1;
289 for (Index
= 0; Index
< BufferLen
; Index
++, TemBuffer
--) {
290 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
298 // Convert the uppercase to lowercase since <HexAf> is defined in lowercase format.
308 Retrieve the <ConfigBody> from String then output it.
310 This is a internal function.
312 @param String A sub string of a configuration string in
313 <MultiConfigAltResp> format.
314 @param ConfigBody Points to the output string. It's caller's
315 responsibility to free this buffer.
317 @retval EFI_INVALID_PARAMETER There is no form package in current hii database.
318 @retval EFI_OUT_OF_RESOURCES Not enough memory to finish this operation.
319 @retval EFI_SUCCESS All existing storage is exported.
324 IN EFI_STRING String
,
325 OUT EFI_STRING
*ConfigBody
332 if (String
== NULL
|| ConfigBody
== NULL
) {
333 return EFI_INVALID_PARAMETER
;
337 // The setting information should start OFFSET, not ALTCFG.
339 if (StrnCmp (String
, L
"&ALTCFG=", StrLen (L
"&ALTCFG=")) == 0) {
340 return EFI_INVALID_PARAMETER
;
343 TmpPtr
= StrStr (String
, L
"GUID=");
344 if (TmpPtr
== NULL
) {
346 // It is the last <ConfigResp> of the incoming configuration string.
348 Result
= AllocateCopyPool (StrSize (String
), String
);
349 if (Result
== NULL
) {
350 return EFI_OUT_OF_RESOURCES
;
352 *ConfigBody
= Result
;
357 Length
= TmpPtr
- String
;
359 return EFI_NOT_FOUND
;
361 Result
= AllocateCopyPool (Length
* sizeof (CHAR16
), String
);
362 if (Result
== NULL
) {
363 return EFI_OUT_OF_RESOURCES
;
366 *(Result
+ Length
- 1) = 0;
367 *ConfigBody
= Result
;
372 Append a string to a multi-string format.
374 This is a internal function.
376 @param MultiString String in <MultiConfigRequest>,
377 <MultiConfigAltResp>, or <MultiConfigResp>. On
378 input, the buffer length of this string is
379 MAX_STRING_LENGTH. On output, the buffer length
381 @param AppendString NULL-terminated Unicode string.
383 @retval EFI_INVALID_PARAMETER Any incoming parameter is invalid.
384 @retval EFI_SUCCESS AppendString is append to the end of MultiString
388 AppendToMultiString (
389 IN OUT EFI_STRING
*MultiString
,
390 IN EFI_STRING AppendString
393 UINTN AppendStringSize
;
394 UINTN MultiStringSize
;
396 if (MultiString
== NULL
|| *MultiString
== NULL
|| AppendString
== NULL
) {
397 return EFI_INVALID_PARAMETER
;
400 AppendStringSize
= StrSize (AppendString
);
401 MultiStringSize
= StrSize (*MultiString
);
404 // Enlarge the buffer each time when length exceeds MAX_STRING_LENGTH.
406 if (MultiStringSize
+ AppendStringSize
> MAX_STRING_LENGTH
||
407 MultiStringSize
> MAX_STRING_LENGTH
) {
408 *MultiString
= (EFI_STRING
) ReallocatePool (
410 MultiStringSize
+ AppendStringSize
,
411 (VOID
*) (*MultiString
)
413 ASSERT (*MultiString
!= NULL
);
416 // Append the incoming string
418 StrCat (*MultiString
, AppendString
);
425 Get the value of <Number> in <BlockConfig> format, i.e. the value of OFFSET
427 <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>
429 This is a internal function.
431 @param StringPtr String in <BlockConfig> format and points to the
432 first character of <Number>.
433 @param Number The output value. Caller takes the responsibility
435 @param Len Length of the <Number>, in characters.
437 @retval EFI_OUT_OF_RESOURCES Insufficient resources to store neccessary
439 @retval EFI_SUCCESS Value of <Number> is outputted in Number
445 IN EFI_STRING StringPtr
,
459 if (StringPtr
== NULL
|| *StringPtr
== L
'\0' || Number
== NULL
|| Len
== NULL
) {
460 return EFI_INVALID_PARAMETER
;
466 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
469 *Len
= StringPtr
- TmpPtr
;
472 Str
= (EFI_STRING
) AllocateZeroPool (Length
* sizeof (CHAR16
));
474 Status
= EFI_OUT_OF_RESOURCES
;
477 CopyMem (Str
, TmpPtr
, *Len
* sizeof (CHAR16
));
478 *(Str
+ *Len
) = L
'\0';
480 Length
= (Length
+ 1) / 2;
481 Buf
= (UINT8
*) AllocateZeroPool (Length
);
483 Status
= EFI_OUT_OF_RESOURCES
;
488 ZeroMem (TemStr
, sizeof (TemStr
));
489 for (Index
= 0; Index
< Length
; Index
++) {
490 TemStr
[0] = Str
[Length
- Index
- 1];
491 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
492 if ((Index
& 1) == 0) {
493 Buf
[Index
/2] = DigitUint8
;
495 Buf
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Buf
[Index
/2]);
500 Status
= EFI_SUCCESS
;
511 This function merges DefaultAltCfgResp string into AltCfgResp string for
512 the missing AltCfgId in AltCfgResq.
514 @param AltCfgResp Pointer to a null-terminated Unicode string in
515 <ConfigAltResp> format. The default value string
516 will be merged into it.
517 @param DefaultAltCfgResp Pointer to a null-terminated Unicode string in
518 <MultiConfigAltResp> format. The default value
519 string may contain more than one ConfigAltResp
520 string for the different varstore buffer.
522 @retval EFI_SUCCESS The merged string returns.
523 @retval EFI_INVALID_PARAMETER *AltCfgResp is to NULL.
528 IN OUT EFI_STRING
*AltCfgResp
,
529 IN EFI_STRING DefaultAltCfgResp
532 EFI_STRING StringPtrDefault
;
533 EFI_STRING StringPtrEnd
;
535 EFI_STRING StringPtr
;
536 EFI_STRING AltConfigHdr
;
538 UINTN SizeAltCfgResp
;
540 if (*AltCfgResp
== NULL
) {
541 return EFI_INVALID_PARAMETER
;
545 // Get the requestr ConfigHdr
548 StringPtr
= *AltCfgResp
;
551 // Find <ConfigHdr> GUID=...&NAME=...&PATH=...
553 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
554 return EFI_INVALID_PARAMETER
;
556 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&NAME=", StrLen (L
"&NAME=")) != 0) {
559 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&PATH=", StrLen (L
"&PATH=")) != 0) {
562 if (*StringPtr
== L
'\0') {
563 return EFI_INVALID_PARAMETER
;
565 StringPtr
+= StrLen (L
"&PATH=");
566 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
569 HeaderLength
= StringPtr
- *AltCfgResp
;
572 // Construct AltConfigHdr string "&<ConfigHdr>&ALTCFG=XXXX\0"
573 // |1| StrLen (ConfigHdr) | 8 | 4 | 1 |
575 AltConfigHdr
= AllocateZeroPool ((1 + HeaderLength
+ 8 + 4 + 1) * sizeof (CHAR16
));
576 if (AltConfigHdr
== NULL
) {
577 return EFI_OUT_OF_RESOURCES
;
579 StrCpy (AltConfigHdr
, L
"&");
580 StrnCat (AltConfigHdr
, *AltCfgResp
, HeaderLength
);
581 StrCat (AltConfigHdr
, L
"&ALTCFG=");
582 HeaderLength
= StrLen (AltConfigHdr
);
584 StringPtrDefault
= StrStr (DefaultAltCfgResp
, AltConfigHdr
);
585 while (StringPtrDefault
!= NULL
) {
589 StrnCat (AltConfigHdr
, StringPtrDefault
+ HeaderLength
, 4);
590 StringPtr
= StrStr (*AltCfgResp
, AltConfigHdr
);
593 // Append the found default value string to the input AltCfgResp
595 if (StringPtr
== NULL
) {
596 StringPtrEnd
= StrStr (StringPtrDefault
+ 1, L
"&GUID");
597 SizeAltCfgResp
= StrSize (*AltCfgResp
);
598 if (StringPtrEnd
== NULL
) {
600 // No more default string is found.
602 *AltCfgResp
= (EFI_STRING
) ReallocatePool (
604 SizeAltCfgResp
+ StrSize (StringPtrDefault
),
605 (VOID
*) (*AltCfgResp
)
607 if (*AltCfgResp
== NULL
) {
608 FreePool (AltConfigHdr
);
609 return EFI_OUT_OF_RESOURCES
;
611 StrCat (*AltCfgResp
, StringPtrDefault
);
614 TempChar
= *StringPtrEnd
;
615 *StringPtrEnd
= L
'\0';
616 *AltCfgResp
= (EFI_STRING
) ReallocatePool (
618 SizeAltCfgResp
+ StrSize (StringPtrDefault
),
619 (VOID
*) (*AltCfgResp
)
621 if (*AltCfgResp
== NULL
) {
622 FreePool (AltConfigHdr
);
623 return EFI_OUT_OF_RESOURCES
;
625 StrCat (*AltCfgResp
, StringPtrDefault
);
626 *StringPtrEnd
= TempChar
;
631 // Find next AltCfg String
633 *(AltConfigHdr
+ HeaderLength
) = L
'\0';
634 StringPtrDefault
= StrStr (StringPtrDefault
+ 1, AltConfigHdr
);
637 FreePool (AltConfigHdr
);
642 This function inserts new DefaultValueData into the BlockData DefaultValue array.
644 @param BlockData The BlockData is updated to add new default value.
645 @param DefaultValueData The DefaultValue is added.
650 IN IFR_BLOCK_DATA
*BlockData
,
651 IN IFR_DEFAULT_DATA
*DefaultValueData
655 IFR_DEFAULT_DATA
*DefaultValueArray
;
656 LIST_ENTRY
*DefaultLink
;
658 DefaultLink
= &BlockData
->DefaultValueEntry
;
660 for (Link
= DefaultLink
->ForwardLink
; Link
!= DefaultLink
; Link
= Link
->ForwardLink
) {
661 DefaultValueArray
= BASE_CR (Link
, IFR_DEFAULT_DATA
, Entry
);
662 if (DefaultValueArray
->DefaultId
== DefaultValueData
->DefaultId
) {
664 // DEFAULT_VALUE_FROM_OPCODE has high priority, DEFAULT_VALUE_FROM_DEFAULT has low priority.
666 if (DefaultValueData
->Type
> DefaultValueArray
->Type
) {
668 // Update the default value array in BlockData.
670 CopyMem (&DefaultValueArray
->Value
, &DefaultValueData
->Value
, sizeof (EFI_IFR_TYPE_VALUE
));
671 DefaultValueArray
->Type
= DefaultValueData
->Type
;
672 DefaultValueArray
->Cleaned
= DefaultValueData
->Cleaned
;
679 // Insert new default value data in tail.
681 DefaultValueArray
= AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
682 ASSERT (DefaultValueArray
!= NULL
);
683 CopyMem (DefaultValueArray
, DefaultValueData
, sizeof (IFR_DEFAULT_DATA
));
684 InsertTailList (Link
, &DefaultValueArray
->Entry
);
688 This function inserts new BlockData into the block link
690 @param BlockLink The list entry points to block array.
691 @param BlockData The point to BlockData is added.
696 IN LIST_ENTRY
*BlockLink
,
697 IN IFR_BLOCK_DATA
**BlockData
701 IFR_BLOCK_DATA
*BlockArray
;
702 IFR_BLOCK_DATA
*BlockSingleData
;
704 BlockSingleData
= *BlockData
;
706 if (BlockSingleData
->Name
!= NULL
) {
707 InsertTailList (BlockLink
, &BlockSingleData
->Entry
);
712 // Insert block data in its Offset and Width order.
714 for (Link
= BlockLink
->ForwardLink
; Link
!= BlockLink
; Link
= Link
->ForwardLink
) {
715 BlockArray
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
716 if (BlockArray
->Offset
== BlockSingleData
->Offset
) {
717 if (BlockArray
->Width
> BlockSingleData
->Width
) {
719 // Insert this block data in the front of block array
721 InsertTailList (Link
, &BlockSingleData
->Entry
);
725 if (BlockArray
->Width
== BlockSingleData
->Width
) {
727 // The same block array has been added.
729 if (BlockSingleData
!= BlockArray
) {
730 FreePool (BlockSingleData
);
731 *BlockData
= BlockArray
;
735 } else if (BlockArray
->Offset
> BlockSingleData
->Offset
) {
737 // Insert new block data in the front of block array
739 InsertTailList (Link
, &BlockSingleData
->Entry
);
745 // Add new block data into the tail.
747 InsertTailList (Link
, &BlockSingleData
->Entry
);
751 Retrieves a pointer to the a Null-terminated ASCII string containing the list
752 of languages that an HII handle in the HII Database supports. The returned
753 string is allocated using AllocatePool(). The caller is responsible for freeing
754 the returned string using FreePool(). The format of the returned string follows
755 the language format assumed the HII Database.
757 If HiiHandle is NULL, then ASSERT().
759 @param[in] HiiHandle A handle that was previously registered in the HII Database.
761 @retval NULL HiiHandle is not registered in the HII database
762 @retval NULL There are not enough resources available to retrieve the suported
764 @retval NULL The list of suported languages could not be retrieved.
765 @retval Other A pointer to the Null-terminated ASCII string of supported languages.
769 GetSupportedLanguages (
770 IN EFI_HII_HANDLE HiiHandle
775 CHAR8 TempSupportedLanguages
;
776 CHAR8
*SupportedLanguages
;
778 ASSERT (HiiHandle
!= NULL
);
781 // Retrieve the size required for the supported languages buffer.
784 Status
= mPrivate
.HiiString
.GetLanguages (&mPrivate
.HiiString
, HiiHandle
, &TempSupportedLanguages
, &LanguageSize
);
787 // If GetLanguages() returns EFI_SUCCESS for a zero size,
788 // then there are no supported languages registered for HiiHandle. If GetLanguages()
789 // returns an error other than EFI_BUFFER_TOO_SMALL, then HiiHandle is not present
790 // in the HII Database
792 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
794 // Return NULL if the size can not be retrieved, or if HiiHandle is not in the HII Database
800 // Allocate the supported languages buffer.
802 SupportedLanguages
= AllocateZeroPool (LanguageSize
);
803 if (SupportedLanguages
== NULL
) {
805 // Return NULL if allocation fails.
811 // Retrieve the supported languages string
813 Status
= mPrivate
.HiiString
.GetLanguages (&mPrivate
.HiiString
, HiiHandle
, SupportedLanguages
, &LanguageSize
);
814 if (EFI_ERROR (Status
)) {
816 // Free the buffer and return NULL if the supported languages can not be retrieved.
818 FreePool (SupportedLanguages
);
823 // Return the Null-terminated ASCII string of supported languages
825 return SupportedLanguages
;
829 Retrieves a string from a string package.
831 If HiiHandle is NULL, then ASSERT().
832 If StringId is 0, then ASSET.
834 @param[in] HiiHandle A handle that was previously registered in the HII Database.
835 @param[in] StringId The identifier of the string to retrieved from the string
836 package associated with HiiHandle.
838 @retval NULL The string specified by StringId is not present in the string package.
839 @retval Other The string was returned.
844 IN EFI_HII_HANDLE HiiHandle
,
845 IN EFI_STRING_ID StringId
852 CHAR8
*SupportedLanguages
;
853 CHAR8
*PlatformLanguage
;
857 ASSERT (HiiHandle
!= NULL
);
858 ASSERT (StringId
!= 0);
861 // Initialize all allocated buffers to NULL
863 SupportedLanguages
= NULL
;
864 PlatformLanguage
= NULL
;
870 // Get the languages that the package specified by HiiHandle supports
872 SupportedLanguages
= GetSupportedLanguages (HiiHandle
);
873 if (SupportedLanguages
== NULL
) {
878 // Get the current platform language setting
880 GetEfiGlobalVariable2 (L
"PlatformLang", (VOID
**)&PlatformLanguage
, NULL
);
883 // Get the best matching language from SupportedLanguages
885 BestLanguage
= GetBestLanguage (
887 FALSE
, // RFC 4646 mode
888 Language
, // Highest priority
889 PlatformLanguage
!= NULL
? PlatformLanguage
: "", // Next highest priority
890 SupportedLanguages
, // Lowest priority
893 if (BestLanguage
== NULL
) {
898 // Retrieve the size of the string in the string package for the BestLanguage
901 Status
= mPrivate
.HiiString
.GetString (
911 // If GetString() returns EFI_SUCCESS for a zero size,
912 // then there are no supported languages registered for HiiHandle. If GetString()
913 // returns an error other than EFI_BUFFER_TOO_SMALL, then HiiHandle is not present
914 // in the HII Database
916 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
921 // Allocate a buffer for the return string
923 String
= AllocateZeroPool (StringSize
);
924 if (String
== NULL
) {
929 // Retrieve the string from the string package
931 Status
= mPrivate
.HiiString
.GetString (
940 if (EFI_ERROR (Status
)) {
942 // Free the buffer and return NULL if the supported languages can not be retrieved.
950 // Free allocated buffers
952 if (SupportedLanguages
!= NULL
) {
953 FreePool (SupportedLanguages
);
955 if (PlatformLanguage
!= NULL
) {
956 FreePool (PlatformLanguage
);
958 if (BestLanguage
!= NULL
) {
959 FreePool (BestLanguage
);
963 // Return the Null-terminated Unicode string
969 This function checks VarOffset and VarWidth is in the block range.
971 @param RequestBlockArray The block array is to be checked.
972 @param VarOffset Offset of var to the structure
973 @param VarWidth Width of var.
974 @param IsNameValueType Whether this varstore is name/value varstore or not.
975 @param HiiHandle Hii handle for this hii package.
977 @retval TRUE This Var is in the block range.
978 @retval FALSE This Var is not in the block range.
982 IN IFR_BLOCK_DATA
*RequestBlockArray
,
985 IN BOOLEAN IsNameValueType
,
986 IN EFI_HII_HANDLE HiiHandle
990 IFR_BLOCK_DATA
*BlockData
;
994 // No Request Block array, all vars are got.
996 if (RequestBlockArray
== NULL
) {
1001 // Check the input var is in the request block range.
1003 for (Link
= RequestBlockArray
->Entry
.ForwardLink
; Link
!= &RequestBlockArray
->Entry
; Link
= Link
->ForwardLink
) {
1004 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
1006 if (IsNameValueType
) {
1007 Name
= InternalGetString (HiiHandle
, VarOffset
);
1008 ASSERT (Name
!= NULL
);
1010 if (StrnCmp (BlockData
->Name
, Name
, StrLen (Name
)) == 0) {
1016 if ((VarOffset
>= BlockData
->Offset
) && ((VarOffset
+ VarWidth
) <= (BlockData
->Offset
+ BlockData
->Width
))) {
1026 Get form package data from data base.
1028 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
1029 @param HiiFormPackage The buffer saves the package data.
1030 @param PackageSize The buffer size of the package data.
1034 GetFormPackageData (
1035 IN HII_DATABASE_RECORD
*DataBaseRecord
,
1036 IN OUT UINT8
**HiiFormPackage
,
1037 OUT UINTN
*PackageSize
1044 if (DataBaseRecord
== NULL
|| HiiFormPackage
== NULL
|| PackageSize
== NULL
) {
1045 return EFI_INVALID_PARAMETER
;
1051 // 0. Get Hii Form Package by HiiHandle
1053 Status
= ExportFormPackages (
1055 DataBaseRecord
->Handle
,
1056 DataBaseRecord
->PackageList
,
1062 if (EFI_ERROR (Status
)) {
1066 (*HiiFormPackage
) = AllocatePool (ResultSize
);
1067 if (*HiiFormPackage
== NULL
) {
1068 Status
= EFI_OUT_OF_RESOURCES
;
1073 // Get HiiFormPackage by HiiHandle
1077 Status
= ExportFormPackages (
1079 DataBaseRecord
->Handle
,
1080 DataBaseRecord
->PackageList
,
1086 if (EFI_ERROR (Status
)) {
1087 FreePool (*HiiFormPackage
);
1090 *PackageSize
= Size
;
1097 This function parses Form Package to get the efi varstore info according to the request ConfigHdr.
1099 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
1100 @param ConfigHdr Request string ConfigHdr. If it is NULL,
1101 the first found varstore will be as ConfigHdr.
1102 @param IsEfiVarstore Whether the request storage type is efi varstore type.
1103 @param EfiVarStore The efi varstore info which will return.
1107 IN HII_DATABASE_RECORD
*DataBaseRecord
,
1108 IN EFI_STRING ConfigHdr
,
1109 OUT BOOLEAN
*IsEfiVarstore
,
1110 OUT EFI_IFR_VARSTORE_EFI
**EfiVarStore
1115 UINTN PackageOffset
;
1116 EFI_IFR_OP_HEADER
*IfrOpHdr
;
1117 CHAR16
*VarStoreName
;
1122 UINT8
*HiiFormPackage
;
1124 EFI_IFR_VARSTORE_EFI
*IfrEfiVarStore
;
1125 EFI_HII_PACKAGE_HEADER
*PackageHeader
;
1127 HiiFormPackage
= NULL
;
1129 Status
= EFI_SUCCESS
;
1133 *IsEfiVarstore
= FALSE
;
1135 Status
= GetFormPackageData(DataBaseRecord
, &HiiFormPackage
, &PackageSize
);
1136 if (EFI_ERROR (Status
)) {
1140 IfrOffset
= sizeof (EFI_HII_PACKAGE_HEADER
);
1141 PackageOffset
= IfrOffset
;
1142 PackageHeader
= (EFI_HII_PACKAGE_HEADER
*) HiiFormPackage
;
1144 while (IfrOffset
< PackageSize
) {
1146 // More than one form packages exist.
1148 if (PackageOffset
>= PackageHeader
->Length
) {
1150 // Process the new form package.
1152 PackageOffset
= sizeof (EFI_HII_PACKAGE_HEADER
);
1153 IfrOffset
+= PackageOffset
;
1154 PackageHeader
= (EFI_HII_PACKAGE_HEADER
*) (HiiFormPackage
+ IfrOffset
);
1157 IfrOpHdr
= (EFI_IFR_OP_HEADER
*) (HiiFormPackage
+ IfrOffset
);
1158 IfrOffset
+= IfrOpHdr
->Length
;
1159 PackageOffset
+= IfrOpHdr
->Length
;
1161 if (IfrOpHdr
->OpCode
== EFI_IFR_VARSTORE_EFI_OP
) {
1162 IfrEfiVarStore
= (EFI_IFR_VARSTORE_EFI
*) IfrOpHdr
;
1164 // If the length is small than the structure, this is from old efi
1165 // varstore definition. Old efi varstore get config directly from
1166 // GetVariable function.
1168 if (IfrOpHdr
->Length
< sizeof (EFI_IFR_VARSTORE_EFI
)) {
1172 VarStoreName
= AllocateZeroPool (AsciiStrSize ((CHAR8
*)IfrEfiVarStore
->Name
) * sizeof (CHAR16
));
1173 if (VarStoreName
== NULL
) {
1174 Status
= EFI_OUT_OF_RESOURCES
;
1177 AsciiStrToUnicodeStr ((CHAR8
*) IfrEfiVarStore
->Name
, VarStoreName
);
1179 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*) &IfrEfiVarStore
->Guid
, 1, &GuidStr
);
1180 GenerateSubStr (L
"NAME=", StrLen (VarStoreName
) * sizeof (CHAR16
), (VOID
*) VarStoreName
, 2, &NameStr
);
1181 LengthString
= StrLen (GuidStr
);
1182 LengthString
= LengthString
+ StrLen (NameStr
) + 1;
1183 TempStr
= AllocateZeroPool (LengthString
* sizeof (CHAR16
));
1184 if (TempStr
== NULL
) {
1187 FreePool (VarStoreName
);
1188 Status
= EFI_OUT_OF_RESOURCES
;
1191 StrCpy (TempStr
, GuidStr
);
1192 StrCat (TempStr
, NameStr
);
1193 if (ConfigHdr
== NULL
|| StrnCmp (ConfigHdr
, TempStr
, StrLen (TempStr
)) == 0) {
1194 *EfiVarStore
= (EFI_IFR_VARSTORE_EFI
*) AllocateZeroPool (IfrOpHdr
->Length
);
1195 if (*EfiVarStore
== NULL
) {
1196 FreePool (VarStoreName
);
1200 Status
= EFI_OUT_OF_RESOURCES
;
1203 *IsEfiVarstore
= TRUE
;
1204 CopyMem (*EfiVarStore
, IfrEfiVarStore
, IfrOpHdr
->Length
);
1208 // Free alllocated temp string.
1210 FreePool (VarStoreName
);
1216 // Already found the varstore, break;
1218 if (*IsEfiVarstore
) {
1224 if (HiiFormPackage
!= NULL
) {
1225 FreePool (HiiFormPackage
);
1232 Check whether the ConfigRequest string has the request elements.
1233 For EFI_HII_VARSTORE_BUFFER type, the request has "&OFFSET=****&WIDTH=****..." format.
1234 For EFI_HII_VARSTORE_NAME_VALUE type, the request has "&NAME1**&NAME2..." format.
1236 @param ConfigRequest The input config request string.
1238 @retval TRUE The input include config request elements.
1239 @retval FALSE The input string not includes.
1243 GetElementsFromRequest (
1244 IN EFI_STRING ConfigRequest
1247 EFI_STRING TmpRequest
;
1249 TmpRequest
= StrStr (ConfigRequest
, L
"PATH=");
1250 ASSERT (TmpRequest
!= NULL
);
1252 if ((StrStr (TmpRequest
, L
"&OFFSET=") != NULL
) || (StrStr (TmpRequest
, L
"&") != NULL
)) {
1260 Check whether the this varstore is the request varstore.
1262 @param VarstoreGuid Varstore guid.
1263 @param Name Varstore name.
1264 @param ConfigHdr Current configRequest info.
1266 @retval TRUE This varstore is the requst one.
1267 @retval FALSE This varstore is not the requst one.
1272 IN EFI_GUID
*VarstoreGuid
,
1274 IN CHAR16
*ConfigHdr
1288 // If ConfigHdr has name field and varstore not has name, return FALSE.
1290 if (Name
== NULL
&& StrStr (ConfigHdr
, L
"NAME=&") == NULL
) {
1294 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*)VarstoreGuid
, 1, &GuidStr
);
1296 GenerateSubStr (L
"NAME=", StrLen (Name
) * sizeof (CHAR16
), (VOID
*) Name
, 2, &NameStr
);
1298 GenerateSubStr (L
"NAME=", 0, NULL
, 2, &NameStr
);
1300 LengthString
= StrLen (GuidStr
);
1301 LengthString
= LengthString
+ StrLen (NameStr
) + 1;
1302 TempStr
= AllocateZeroPool (LengthString
* sizeof (CHAR16
));
1303 if (TempStr
== NULL
) {
1307 StrCpy (TempStr
, GuidStr
);
1308 StrCat (TempStr
, NameStr
);
1310 if (ConfigHdr
== NULL
|| StrnCmp (ConfigHdr
, TempStr
, StrLen (TempStr
)) == 0) {
1315 if (GuidStr
!= NULL
) {
1319 if (NameStr
!= NULL
) {
1323 if (TempStr
!= NULL
) {
1331 This function parses Form Package to get the efi varstore info according to the request ConfigHdr.
1333 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
1334 @param ConfigHdr Request string ConfigHdr. If it is NULL,
1335 the first found varstore will be as ConfigHdr.
1336 @retval TRUE This hii package is the reqeust one.
1337 @retval FALSE This hii package is not the reqeust one.
1341 IN HII_DATABASE_RECORD
*DataBaseRecord
,
1342 IN EFI_STRING ConfigHdr
1347 UINTN PackageOffset
;
1348 EFI_IFR_OP_HEADER
*IfrOpHdr
;
1349 CHAR16
*VarStoreName
;
1350 UINT8
*HiiFormPackage
;
1352 EFI_IFR_VARSTORE_EFI
*IfrEfiVarStore
;
1353 EFI_HII_PACKAGE_HEADER
*PackageHeader
;
1354 EFI_IFR_VARSTORE
*IfrVarStore
;
1355 EFI_IFR_VARSTORE_NAME_VALUE
*IfrNameValueVarStore
;
1356 BOOLEAN FindVarstore
;
1358 HiiFormPackage
= NULL
;
1359 VarStoreName
= NULL
;
1360 Status
= EFI_SUCCESS
;
1361 FindVarstore
= FALSE
;
1363 Status
= GetFormPackageData(DataBaseRecord
, &HiiFormPackage
, &PackageSize
);
1364 if (EFI_ERROR (Status
)) {
1368 IfrOffset
= sizeof (EFI_HII_PACKAGE_HEADER
);
1369 PackageOffset
= IfrOffset
;
1370 PackageHeader
= (EFI_HII_PACKAGE_HEADER
*) HiiFormPackage
;
1372 while (IfrOffset
< PackageSize
) {
1374 // More than one form packages exist.
1376 if (PackageOffset
>= PackageHeader
->Length
) {
1378 // Process the new form package.
1380 PackageOffset
= sizeof (EFI_HII_PACKAGE_HEADER
);
1381 IfrOffset
+= PackageOffset
;
1382 PackageHeader
= (EFI_HII_PACKAGE_HEADER
*) (HiiFormPackage
+ IfrOffset
);
1385 IfrOpHdr
= (EFI_IFR_OP_HEADER
*) (HiiFormPackage
+ IfrOffset
);
1386 IfrOffset
+= IfrOpHdr
->Length
;
1387 PackageOffset
+= IfrOpHdr
->Length
;
1389 switch (IfrOpHdr
->OpCode
) {
1391 case EFI_IFR_VARSTORE_OP
:
1392 IfrVarStore
= (EFI_IFR_VARSTORE
*) IfrOpHdr
;
1394 VarStoreName
= AllocateZeroPool (AsciiStrSize ((CHAR8
*)IfrVarStore
->Name
) * sizeof (CHAR16
));
1395 if (VarStoreName
== NULL
) {
1398 AsciiStrToUnicodeStr ((CHAR8
*)IfrVarStore
->Name
, VarStoreName
);
1400 if (IsThisVarstore((VOID
*)&IfrVarStore
->Guid
, VarStoreName
, ConfigHdr
)) {
1401 FindVarstore
= TRUE
;
1406 case EFI_IFR_VARSTORE_EFI_OP
:
1407 IfrEfiVarStore
= (EFI_IFR_VARSTORE_EFI
*) IfrOpHdr
;
1408 VarStoreName
= AllocateZeroPool (AsciiStrSize ((CHAR8
*)IfrEfiVarStore
->Name
) * sizeof (CHAR16
));
1409 if (VarStoreName
== NULL
) {
1412 AsciiStrToUnicodeStr ((CHAR8
*)IfrEfiVarStore
->Name
, VarStoreName
);
1414 if (IsThisVarstore (&IfrEfiVarStore
->Guid
, VarStoreName
, ConfigHdr
)) {
1415 FindVarstore
= TRUE
;
1420 case EFI_IFR_VARSTORE_NAME_VALUE_OP
:
1421 IfrNameValueVarStore
= (EFI_IFR_VARSTORE_NAME_VALUE
*) IfrOpHdr
;
1423 if (IsThisVarstore (&IfrNameValueVarStore
->Guid
, NULL
, ConfigHdr
)) {
1424 FindVarstore
= TRUE
;
1429 case EFI_IFR_FORM_OP
:
1430 case EFI_IFR_FORM_MAP_OP
:
1432 // No matched varstore is found and directly return.
1443 if (HiiFormPackage
!= NULL
) {
1444 FreePool (HiiFormPackage
);
1447 if (VarStoreName
!= NULL
) {
1448 FreePool (VarStoreName
);
1451 return FindVarstore
;
1455 Check whether the this op code is required.
1457 @param RequestBlockArray The array includes all the request info or NULL.
1458 @param HiiHandle The hii handle for this form package.
1459 @param VarStorageData The varstore data strucure.
1460 @param IfrOpHdr Ifr opcode header for this opcode.
1461 @param VarWidth The buffer width for this opcode.
1462 @param ReturnData The data block added for this opcode.
1464 @retval EFI_SUCCESS This opcode is required.
1465 @retval Others This opcode is not required or error occur.
1469 IsThisOpcodeRequired (
1470 IN IFR_BLOCK_DATA
*RequestBlockArray
,
1471 IN EFI_HII_HANDLE HiiHandle
,
1472 IN OUT IFR_VARSTORAGE_DATA
*VarStorageData
,
1473 IN EFI_IFR_OP_HEADER
*IfrOpHdr
,
1475 OUT IFR_BLOCK_DATA
**ReturnData
1478 IFR_BLOCK_DATA
*BlockData
;
1480 EFI_STRING_ID NameId
;
1481 EFI_IFR_QUESTION_HEADER
*IfrQuestionHdr
;
1485 IfrQuestionHdr
= (EFI_IFR_QUESTION_HEADER
*)((CHAR8
*) IfrOpHdr
+ sizeof (EFI_IFR_OP_HEADER
));
1487 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
1488 NameId
= IfrQuestionHdr
->VarStoreInfo
.VarName
;
1491 // Check whether this question is in requested block array.
1493 if (!BlockArrayCheck (RequestBlockArray
, NameId
, 0, TRUE
, HiiHandle
)) {
1495 // This question is not in the requested string. Skip it.
1500 VarOffset
= IfrQuestionHdr
->VarStoreInfo
.VarOffset
;
1503 // Check whether this question is in requested block array.
1505 if (!BlockArrayCheck (RequestBlockArray
, VarOffset
, VarWidth
, FALSE
, HiiHandle
)) {
1507 // This question is not in the requested string. Skip it.
1513 // Check this var question is in the var storage
1515 if (((VarOffset
+ VarWidth
) > VarStorageData
->Size
)) {
1516 return EFI_INVALID_PARAMETER
;
1520 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
1521 if (BlockData
== NULL
) {
1522 return EFI_OUT_OF_RESOURCES
;
1525 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
1526 BlockData
->Name
= InternalGetString(HiiHandle
, NameId
);
1528 BlockData
->Offset
= VarOffset
;
1531 BlockData
->Width
= VarWidth
;
1532 BlockData
->QuestionId
= IfrQuestionHdr
->QuestionId
;
1533 BlockData
->OpCode
= IfrOpHdr
->OpCode
;
1534 BlockData
->Scope
= IfrOpHdr
->Scope
;
1535 InitializeListHead (&BlockData
->DefaultValueEntry
);
1537 // Add Block Data into VarStorageData BlockEntry
1539 InsertBlockData (&VarStorageData
->BlockEntry
, &BlockData
);
1540 *ReturnData
= BlockData
;
1546 This function parses Form Package to get the block array and the default
1547 value array according to the request ConfigHdr.
1549 @param HiiHandle Hii Handle for this hii package.
1550 @param Package Pointer to the form package data.
1551 @param PackageLength Length of the pacakge.
1552 @param ConfigHdr Request string ConfigHdr. If it is NULL,
1553 the first found varstore will be as ConfigHdr.
1554 @param RequestBlockArray The block array is retrieved from the request string.
1555 @param VarStorageData VarStorage structure contains the got block and default value.
1556 @param DefaultIdArray Point to the got default id and default name array.
1558 @retval EFI_SUCCESS The block array and the default value array are got.
1559 @retval EFI_INVALID_PARAMETER The varstore defintion in the differnt form pacakges
1561 @retval EFI_OUT_OF_RESOURCES No enough memory.
1566 IN EFI_HII_HANDLE HiiHandle
,
1568 IN UINT32 PackageLength
,
1569 IN EFI_STRING ConfigHdr
,
1570 IN IFR_BLOCK_DATA
*RequestBlockArray
,
1571 IN OUT IFR_VARSTORAGE_DATA
*VarStorageData
,
1572 OUT IFR_DEFAULT_DATA
*DefaultIdArray
1577 UINTN PackageOffset
;
1578 EFI_IFR_VARSTORE
*IfrVarStore
;
1579 EFI_IFR_VARSTORE_EFI
*IfrEfiVarStore
;
1580 EFI_IFR_OP_HEADER
*IfrOpHdr
;
1581 EFI_IFR_ONE_OF
*IfrOneOf
;
1582 EFI_IFR_REF4
*IfrRef
;
1583 EFI_IFR_ONE_OF_OPTION
*IfrOneOfOption
;
1584 EFI_IFR_DEFAULT
*IfrDefault
;
1585 EFI_IFR_ORDERED_LIST
*IfrOrderedList
;
1586 EFI_IFR_CHECKBOX
*IfrCheckBox
;
1587 EFI_IFR_PASSWORD
*IfrPassword
;
1588 EFI_IFR_STRING
*IfrString
;
1589 EFI_IFR_DATE
*IfrDate
;
1590 EFI_IFR_TIME
*IfrTime
;
1591 IFR_DEFAULT_DATA DefaultData
;
1592 IFR_DEFAULT_DATA
*DefaultDataPtr
;
1593 IFR_BLOCK_DATA
*BlockData
;
1594 CHAR16
*VarStoreName
;
1596 UINT16 VarDefaultId
;
1597 BOOLEAN FirstOneOfOption
;
1598 LIST_ENTRY
*LinkData
;
1599 LIST_ENTRY
*LinkDefault
;
1600 EFI_IFR_VARSTORE_NAME_VALUE
*IfrNameValueVarStore
;
1601 EFI_HII_PACKAGE_HEADER
*PackageHeader
;
1602 EFI_VARSTORE_ID VarStoreId
;
1604 Status
= EFI_SUCCESS
;
1606 DefaultDataPtr
= NULL
;
1607 FirstOneOfOption
= FALSE
;
1609 ZeroMem (&DefaultData
, sizeof (IFR_DEFAULT_DATA
));
1612 // Go through the form package to parse OpCode one by one.
1614 PackageOffset
= sizeof (EFI_HII_PACKAGE_HEADER
);
1615 PackageHeader
= (EFI_HII_PACKAGE_HEADER
*) Package
;
1616 IfrOffset
= PackageOffset
;
1617 while (IfrOffset
< PackageLength
) {
1620 // More than one form package found.
1622 if (PackageOffset
>= PackageHeader
->Length
) {
1624 // Already found varstore for this request, break;
1626 if (VarStoreId
!= 0) {
1631 // Get next package header info.
1633 IfrOffset
+= sizeof (EFI_HII_PACKAGE_HEADER
);
1634 PackageOffset
= sizeof (EFI_HII_PACKAGE_HEADER
);
1635 PackageHeader
= (EFI_HII_PACKAGE_HEADER
*) (Package
+ IfrOffset
);
1638 IfrOpHdr
= (EFI_IFR_OP_HEADER
*) (Package
+ IfrOffset
);
1639 switch (IfrOpHdr
->OpCode
) {
1640 case EFI_IFR_VARSTORE_OP
:
1642 // VarStore is found. Don't need to search any more.
1644 if (VarStoreId
!= 0) {
1648 IfrVarStore
= (EFI_IFR_VARSTORE
*) IfrOpHdr
;
1650 VarStoreName
= AllocateZeroPool (AsciiStrSize ((CHAR8
*)IfrVarStore
->Name
) * sizeof (CHAR16
));
1651 if (VarStoreName
== NULL
) {
1652 Status
= EFI_OUT_OF_RESOURCES
;
1655 AsciiStrToUnicodeStr ((CHAR8
*)IfrVarStore
->Name
, VarStoreName
);
1657 if (IsThisVarstore((VOID
*)&IfrVarStore
->Guid
, VarStoreName
, ConfigHdr
)) {
1659 // Find the matched VarStore
1661 CopyGuid (&VarStorageData
->Guid
, (EFI_GUID
*) (VOID
*) &IfrVarStore
->Guid
);
1662 VarStorageData
->Size
= IfrVarStore
->Size
;
1663 VarStorageData
->Name
= VarStoreName
;
1664 VarStorageData
->Type
= EFI_HII_VARSTORE_BUFFER
;
1665 VarStoreId
= IfrVarStore
->VarStoreId
;
1669 case EFI_IFR_VARSTORE_EFI_OP
:
1671 // VarStore is found. Don't need to search any more.
1673 if (VarStoreId
!= 0) {
1677 IfrEfiVarStore
= (EFI_IFR_VARSTORE_EFI
*) IfrOpHdr
;
1680 // If the length is small than the structure, this is from old efi
1681 // varstore definition. Old efi varstore get config directly from
1682 // GetVariable function.
1684 if (IfrOpHdr
->Length
< sizeof (EFI_IFR_VARSTORE_EFI
)) {
1688 VarStoreName
= AllocateZeroPool (AsciiStrSize ((CHAR8
*)IfrEfiVarStore
->Name
) * sizeof (CHAR16
));
1689 if (VarStoreName
== NULL
) {
1690 Status
= EFI_OUT_OF_RESOURCES
;
1693 AsciiStrToUnicodeStr ((CHAR8
*)IfrEfiVarStore
->Name
, VarStoreName
);
1695 if (IsThisVarstore (&IfrEfiVarStore
->Guid
, VarStoreName
, ConfigHdr
)) {
1697 // Find the matched VarStore
1699 CopyGuid (&VarStorageData
->Guid
, (EFI_GUID
*) (VOID
*) &IfrEfiVarStore
->Guid
);
1700 VarStorageData
->Size
= IfrEfiVarStore
->Size
;
1701 VarStorageData
->Name
= VarStoreName
;
1702 VarStorageData
->Type
= EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
;
1703 VarStoreId
= IfrEfiVarStore
->VarStoreId
;
1707 case EFI_IFR_VARSTORE_NAME_VALUE_OP
:
1709 // VarStore is found. Don't need to search any more.
1711 if (VarStoreId
!= 0) {
1715 IfrNameValueVarStore
= (EFI_IFR_VARSTORE_NAME_VALUE
*) IfrOpHdr
;
1717 if (IsThisVarstore (&IfrNameValueVarStore
->Guid
, NULL
, ConfigHdr
)) {
1719 // Find the matched VarStore
1721 CopyGuid (&VarStorageData
->Guid
, (EFI_GUID
*) (VOID
*) &IfrNameValueVarStore
->Guid
);
1722 VarStorageData
->Type
= EFI_HII_VARSTORE_NAME_VALUE
;
1723 VarStoreId
= IfrNameValueVarStore
->VarStoreId
;
1727 case EFI_IFR_DEFAULTSTORE_OP
:
1729 // Add new the map between default id and default name.
1731 DefaultDataPtr
= (IFR_DEFAULT_DATA
*) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
1732 if (DefaultDataPtr
== NULL
) {
1733 Status
= EFI_OUT_OF_RESOURCES
;
1736 DefaultDataPtr
->DefaultId
= ((EFI_IFR_DEFAULTSTORE
*) IfrOpHdr
)->DefaultId
;
1737 InsertTailList (&DefaultIdArray
->Entry
, &DefaultDataPtr
->Entry
);
1738 DefaultDataPtr
= NULL
;
1741 case EFI_IFR_FORM_OP
:
1742 case EFI_IFR_FORM_MAP_OP
:
1744 // No matched varstore is found and directly return.
1746 if ( VarStoreId
== 0) {
1747 Status
= EFI_SUCCESS
;
1752 case EFI_IFR_REF_OP
:
1754 // Ref question is not in IFR Form. This IFR form is not valid.
1756 if ( VarStoreId
== 0) {
1757 Status
= EFI_INVALID_PARAMETER
;
1761 // Check whether this question is for the requested varstore.
1763 IfrRef
= (EFI_IFR_REF4
*) IfrOpHdr
;
1764 if (IfrRef
->Question
.VarStoreId
!= VarStoreId
) {
1767 VarWidth
= (UINT16
) (sizeof (EFI_HII_REF
));
1769 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
1770 if (EFI_ERROR (Status
)) {
1775 case EFI_IFR_ONE_OF_OP
:
1776 case EFI_IFR_NUMERIC_OP
:
1778 // Numeric and OneOf has the same opcode structure.
1782 // Numeric and OneOf question is not in IFR Form. This IFR form is not valid.
1784 if (VarStoreId
== 0) {
1785 Status
= EFI_INVALID_PARAMETER
;
1789 // Check whether this question is for the requested varstore.
1791 IfrOneOf
= (EFI_IFR_ONE_OF
*) IfrOpHdr
;
1792 if (IfrOneOf
->Question
.VarStoreId
!= VarStoreId
) {
1795 VarWidth
= (UINT16
) (1 << (IfrOneOf
->Flags
& EFI_IFR_NUMERIC_SIZE
));
1797 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
1798 if (EFI_ERROR (Status
)) {
1802 if (BlockData
== NULL
) {
1804 // BlockData == NULL means this opcode is not in the requst array.
1809 if (IfrOpHdr
->OpCode
== EFI_IFR_ONE_OF_OP
) {
1811 // Set this flag to TRUE for the first oneof option.
1813 FirstOneOfOption
= TRUE
;
1814 } else if (IfrOpHdr
->OpCode
== EFI_IFR_NUMERIC_OP
) {
1816 // Numeric minimum value will be used as default value when no default is specified.
1818 DefaultData
.Type
= DefaultValueFromDefault
;
1819 switch (IfrOneOf
->Flags
& EFI_IFR_NUMERIC_SIZE
) {
1820 case EFI_IFR_NUMERIC_SIZE_1
:
1821 DefaultData
.Value
.u8
= IfrOneOf
->data
.u8
.MinValue
;
1824 case EFI_IFR_NUMERIC_SIZE_2
:
1825 CopyMem (&DefaultData
.Value
.u16
, &IfrOneOf
->data
.u16
.MinValue
, sizeof (UINT16
));
1828 case EFI_IFR_NUMERIC_SIZE_4
:
1829 CopyMem (&DefaultData
.Value
.u32
, &IfrOneOf
->data
.u32
.MinValue
, sizeof (UINT32
));
1832 case EFI_IFR_NUMERIC_SIZE_8
:
1833 CopyMem (&DefaultData
.Value
.u64
, &IfrOneOf
->data
.u64
.MinValue
, sizeof (UINT64
));
1837 Status
= EFI_INVALID_PARAMETER
;
1841 // Set default value base on the DefaultId list get from IFR data.
1843 for (LinkData
= DefaultIdArray
->Entry
.ForwardLink
; LinkData
!= &DefaultIdArray
->Entry
; LinkData
= LinkData
->ForwardLink
) {
1844 DefaultDataPtr
= BASE_CR (LinkData
, IFR_DEFAULT_DATA
, Entry
);
1845 DefaultData
.DefaultId
= DefaultDataPtr
->DefaultId
;
1846 InsertDefaultValue (BlockData
, &DefaultData
);
1851 case EFI_IFR_ORDERED_LIST_OP
:
1853 // offset by question header
1854 // width by EFI_IFR_ORDERED_LIST MaxContainers * OneofOption Type
1855 // no default value and default id, how to define its default value?
1859 // OrderedList question is not in IFR Form. This IFR form is not valid.
1861 if (VarStoreId
== 0) {
1862 Status
= EFI_INVALID_PARAMETER
;
1866 // Check whether this question is for the requested varstore.
1868 IfrOrderedList
= (EFI_IFR_ORDERED_LIST
*) IfrOpHdr
;
1869 if (IfrOrderedList
->Question
.VarStoreId
!= VarStoreId
) {
1873 VarWidth
= IfrOrderedList
->MaxContainers
;
1874 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
1875 if (EFI_ERROR (Status
)) {
1880 case EFI_IFR_CHECKBOX_OP
:
1882 // EFI_IFR_DEFAULT_OP
1883 // offset by question header
1884 // width is 1 sizeof (BOOLEAN)
1885 // default id by CheckBox Flags if CheckBox flags (Default or Mau) is set, the default value is 1 to be set.
1886 // value by DefaultOption
1887 // default id by DeaultOption DefaultId can override CheckBox Flags and Default value.
1891 // CheckBox question is not in IFR Form. This IFR form is not valid.
1893 if (VarStoreId
== 0) {
1894 Status
= EFI_INVALID_PARAMETER
;
1898 // Check whether this question is for the requested varstore.
1900 IfrCheckBox
= (EFI_IFR_CHECKBOX
*) IfrOpHdr
;
1901 if (IfrCheckBox
->Question
.VarStoreId
!= VarStoreId
) {
1904 VarWidth
= (UINT16
) sizeof (BOOLEAN
);
1905 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
1906 if (EFI_ERROR (Status
)) {
1910 if (BlockData
== NULL
) {
1912 // BlockData == NULL means this opcode is not in the requst array.
1918 // Add default value for standard ID by CheckBox Flag
1920 VarDefaultId
= EFI_HII_DEFAULT_CLASS_STANDARD
;
1922 // Prepare new DefaultValue
1924 DefaultData
.DefaultId
= VarDefaultId
;
1925 if ((IfrCheckBox
->Flags
& EFI_IFR_CHECKBOX_DEFAULT
) == EFI_IFR_CHECKBOX_DEFAULT
) {
1927 // When flag is set, defautl value is TRUE.
1929 DefaultData
.Type
= DefaultValueFromFlag
;
1930 DefaultData
.Value
.b
= TRUE
;
1933 // When flag is not set, defautl value is FASLE.
1935 DefaultData
.Type
= DefaultValueFromDefault
;
1936 DefaultData
.Value
.b
= FALSE
;
1939 // Add DefaultValue into current BlockData
1941 InsertDefaultValue (BlockData
, &DefaultData
);
1944 // Add default value for Manufacture ID by CheckBox Flag
1946 VarDefaultId
= EFI_HII_DEFAULT_CLASS_MANUFACTURING
;
1948 // Prepare new DefaultValue
1950 DefaultData
.DefaultId
= VarDefaultId
;
1951 if ((IfrCheckBox
->Flags
& EFI_IFR_CHECKBOX_DEFAULT_MFG
) == EFI_IFR_CHECKBOX_DEFAULT_MFG
) {
1953 // When flag is set, defautl value is TRUE.
1955 DefaultData
.Type
= DefaultValueFromFlag
;
1956 DefaultData
.Value
.b
= TRUE
;
1959 // When flag is not set, defautl value is FASLE.
1961 DefaultData
.Type
= DefaultValueFromDefault
;
1962 DefaultData
.Value
.b
= FALSE
;
1965 // Add DefaultValue into current BlockData
1967 InsertDefaultValue (BlockData
, &DefaultData
);
1970 case EFI_IFR_DATE_OP
:
1972 // offset by question header
1973 // width MaxSize * sizeof (CHAR16)
1974 // no default value, only block array
1978 // Date question is not in IFR Form. This IFR form is not valid.
1980 if (VarStoreId
== 0) {
1981 Status
= EFI_INVALID_PARAMETER
;
1985 // Check whether this question is for the requested varstore.
1987 IfrDate
= (EFI_IFR_DATE
*) IfrOpHdr
;
1988 if (IfrDate
->Question
.VarStoreId
!= VarStoreId
) {
1992 VarWidth
= (UINT16
) sizeof (EFI_HII_DATE
);
1993 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
1994 if (EFI_ERROR (Status
)) {
1999 case EFI_IFR_TIME_OP
:
2001 // offset by question header
2002 // width MaxSize * sizeof (CHAR16)
2003 // no default value, only block array
2007 // Time question is not in IFR Form. This IFR form is not valid.
2009 if (VarStoreId
== 0) {
2010 Status
= EFI_INVALID_PARAMETER
;
2014 // Check whether this question is for the requested varstore.
2016 IfrTime
= (EFI_IFR_TIME
*) IfrOpHdr
;
2017 if (IfrTime
->Question
.VarStoreId
!= VarStoreId
) {
2021 VarWidth
= (UINT16
) sizeof (EFI_HII_TIME
);
2022 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
2023 if (EFI_ERROR (Status
)) {
2028 case EFI_IFR_STRING_OP
:
2030 // offset by question header
2031 // width MaxSize * sizeof (CHAR16)
2032 // no default value, only block array
2036 // String question is not in IFR Form. This IFR form is not valid.
2038 if (VarStoreId
== 0) {
2039 Status
= EFI_INVALID_PARAMETER
;
2043 // Check whether this question is for the requested varstore.
2045 IfrString
= (EFI_IFR_STRING
*) IfrOpHdr
;
2046 if (IfrString
->Question
.VarStoreId
!= VarStoreId
) {
2050 VarWidth
= (UINT16
) (IfrString
->MaxSize
* sizeof (UINT16
));
2051 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
2052 if (EFI_ERROR (Status
)) {
2057 // No default value for string.
2062 case EFI_IFR_PASSWORD_OP
:
2064 // offset by question header
2065 // width MaxSize * sizeof (CHAR16)
2066 // no default value, only block array
2070 // Password question is not in IFR Form. This IFR form is not valid.
2072 if (VarStoreId
== 0) {
2073 Status
= EFI_INVALID_PARAMETER
;
2077 // Check whether this question is for the requested varstore.
2079 IfrPassword
= (EFI_IFR_PASSWORD
*) IfrOpHdr
;
2080 if (IfrPassword
->Question
.VarStoreId
!= VarStoreId
) {
2084 VarWidth
= (UINT16
) (IfrPassword
->MaxSize
* sizeof (UINT16
));
2085 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
2086 if (EFI_ERROR (Status
)) {
2091 // No default value for string.
2096 case EFI_IFR_ONE_OF_OPTION_OP
:
2098 // No matched block data is ignored.
2100 if (BlockData
== NULL
|| BlockData
->Scope
== 0) {
2104 IfrOneOfOption
= (EFI_IFR_ONE_OF_OPTION
*) IfrOpHdr
;
2105 if (BlockData
->OpCode
== EFI_IFR_ORDERED_LIST_OP
) {
2107 // Get ordered list option data type.
2109 if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_8
|| IfrOneOfOption
->Type
== EFI_IFR_TYPE_BOOLEAN
) {
2111 } else if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_16
) {
2113 } else if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_32
) {
2115 } else if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_64
) {
2119 // Invalid ordered list option data type.
2121 Status
= EFI_INVALID_PARAMETER
;
2122 if (BlockData
->Name
!= NULL
) {
2123 FreePool (BlockData
->Name
);
2125 FreePool (BlockData
);
2130 // Calculate Ordered list QuestionId width.
2132 BlockData
->Width
= (UINT16
) (BlockData
->Width
* VarWidth
);
2134 // Check whether this question is in requested block array.
2136 if (!BlockArrayCheck (RequestBlockArray
, BlockData
->Offset
, BlockData
->Width
, (BOOLEAN
)(BlockData
->Name
!= NULL
), HiiHandle
)) {
2138 // This question is not in the requested string. Skip it.
2140 if (BlockData
->Name
!= NULL
) {
2141 FreePool (BlockData
->Name
);
2143 FreePool (BlockData
);
2148 // Check this var question is in the var storage
2150 if ((BlockData
->Name
== NULL
) && ((BlockData
->Offset
+ BlockData
->Width
) > VarStorageData
->Size
)) {
2151 Status
= EFI_INVALID_PARAMETER
;
2152 if (BlockData
->Name
!= NULL
) {
2153 FreePool (BlockData
->Name
);
2155 FreePool (BlockData
);
2159 // Add Block Data into VarStorageData BlockEntry
2161 InsertBlockData (&VarStorageData
->BlockEntry
, &BlockData
);
2163 // No default data for OrderedList.
2170 // 1. Set default value for OneOf option when flag field has default attribute.
2172 if (((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT
) == EFI_IFR_OPTION_DEFAULT
) ||
2173 ((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT_MFG
) == EFI_IFR_OPTION_DEFAULT_MFG
)) {
2175 // This flag is used to specify whether this option is the first. Set it to FALSE for the following options.
2176 // The first oneof option value will be used as default value when no default value is specified.
2178 FirstOneOfOption
= FALSE
;
2180 // Prepare new DefaultValue
2182 DefaultData
.Type
= DefaultValueFromFlag
;
2183 CopyMem (&DefaultData
.Value
, &IfrOneOfOption
->Value
, IfrOneOfOption
->Header
.Length
- OFFSET_OF (EFI_IFR_ONE_OF_OPTION
, Value
));
2184 if ((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT
) == EFI_IFR_OPTION_DEFAULT
) {
2185 DefaultData
.DefaultId
= EFI_HII_DEFAULT_CLASS_STANDARD
;
2186 InsertDefaultValue (BlockData
, &DefaultData
);
2188 if ((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT_MFG
) == EFI_IFR_OPTION_DEFAULT_MFG
) {
2189 DefaultData
.DefaultId
= EFI_HII_DEFAULT_CLASS_MANUFACTURING
;
2190 InsertDefaultValue (BlockData
, &DefaultData
);
2195 // 2. Set as the default value when this is the first option.
2196 // The first oneof option value will be used as default value when no default value is specified.
2198 if (FirstOneOfOption
) {
2199 // This flag is used to specify whether this option is the first. Set it to FALSE for the following options.
2200 FirstOneOfOption
= FALSE
;
2203 // Prepare new DefaultValue
2205 DefaultData
.Type
= DefaultValueFromDefault
;
2206 CopyMem (&DefaultData
.Value
, &IfrOneOfOption
->Value
, IfrOneOfOption
->Header
.Length
- OFFSET_OF (EFI_IFR_ONE_OF_OPTION
, Value
));
2207 for (LinkData
= DefaultIdArray
->Entry
.ForwardLink
; LinkData
!= &DefaultIdArray
->Entry
; LinkData
= LinkData
->ForwardLink
) {
2208 DefaultDataPtr
= BASE_CR (LinkData
, IFR_DEFAULT_DATA
, Entry
);
2209 DefaultData
.DefaultId
= DefaultDataPtr
->DefaultId
;
2210 InsertDefaultValue (BlockData
, &DefaultData
);
2215 case EFI_IFR_DEFAULT_OP
:
2217 // Update Current BlockData to the default value.
2219 if (BlockData
== NULL
|| BlockData
->Scope
== 0) {
2221 // No matched block data is ignored.
2226 if (BlockData
->OpCode
== EFI_IFR_ORDERED_LIST_OP
) {
2228 // OrderedList Opcode is no default value.
2233 // Get the DefaultId
2235 IfrDefault
= (EFI_IFR_DEFAULT
*) IfrOpHdr
;
2236 VarDefaultId
= IfrDefault
->DefaultId
;
2238 // Prepare new DefaultValue
2240 DefaultData
.Type
= DefaultValueFromOpcode
;
2241 DefaultData
.DefaultId
= VarDefaultId
;
2242 CopyMem (&DefaultData
.Value
, &IfrDefault
->Value
, IfrDefault
->Header
.Length
- OFFSET_OF (EFI_IFR_DEFAULT
, Value
));
2244 // If the value field is expression, set the cleaned flag.
2245 if (IfrDefault
->Type
== EFI_IFR_TYPE_OTHER
) {
2246 DefaultData
.Cleaned
= TRUE
;
2249 // Add DefaultValue into current BlockData
2251 InsertDefaultValue (BlockData
, &DefaultData
);
2254 // After insert the default value, reset the cleaned value for next
2255 // time used. If not set here, need to set the value before everytime
2258 DefaultData
.Cleaned
= FALSE
;
2261 case EFI_IFR_END_OP
:
2263 // End Opcode is for Var question.
2265 if (BlockData
!= NULL
) {
2266 if (BlockData
->Scope
> 0) {
2269 if (BlockData
->Scope
== 0) {
2277 if (BlockData
!= NULL
) {
2278 if (BlockData
->Scope
> 0) {
2279 BlockData
->Scope
= (UINT8
) (BlockData
->Scope
+ IfrOpHdr
->Scope
);
2282 if (BlockData
->Scope
== 0) {
2289 IfrOffset
+= IfrOpHdr
->Length
;
2290 PackageOffset
+= IfrOpHdr
->Length
;
2294 for (LinkData
= VarStorageData
->BlockEntry
.ForwardLink
; LinkData
!= &VarStorageData
->BlockEntry
; LinkData
= LinkData
->ForwardLink
) {
2295 BlockData
= BASE_CR (LinkData
, IFR_BLOCK_DATA
, Entry
);
2296 for (LinkDefault
= BlockData
->DefaultValueEntry
.ForwardLink
; LinkDefault
!= &BlockData
->DefaultValueEntry
; ) {
2297 DefaultDataPtr
= BASE_CR (LinkDefault
, IFR_DEFAULT_DATA
, Entry
);
2298 LinkDefault
= LinkDefault
->ForwardLink
;
2299 if (DefaultDataPtr
->Cleaned
== TRUE
) {
2300 RemoveEntryList (&DefaultDataPtr
->Entry
);
2301 FreePool (DefaultDataPtr
);
2310 parse the configrequest string, get the elements.
2312 @param ConfigRequest The input configrequest string.
2313 @param Progress Return the progress data.
2315 @retval Block data pointer.
2319 IN EFI_STRING ConfigRequest
,
2320 OUT EFI_STRING
*Progress
2323 EFI_STRING StringPtr
;
2324 IFR_BLOCK_DATA
*BlockData
;
2325 IFR_BLOCK_DATA
*RequestBlockArray
;
2331 IFR_BLOCK_DATA
*NextBlockData
;
2335 // Init RequestBlockArray
2337 RequestBlockArray
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
2338 if (RequestBlockArray
== NULL
) {
2341 InitializeListHead (&RequestBlockArray
->Entry
);
2344 // Get the request Block array from the request string
2349 // Parse each <RequestElement> if exists
2350 // Only <BlockName> format is supported by this help function.
2351 // <BlockName> ::= &'OFFSET='<Number>&'WIDTH='<Number>
2353 StringPtr
= ConfigRequest
;
2354 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) == 0) {
2356 // Skip the OFFSET string
2358 *Progress
= StringPtr
;
2359 StringPtr
+= StrLen (L
"&OFFSET=");
2363 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
2364 if (EFI_ERROR (Status
)) {
2371 (((Length
+ 1) / 2) < sizeof (UINT16
)) ? ((Length
+ 1) / 2) : sizeof (UINT16
)
2373 FreePool (TmpBuffer
);
2375 StringPtr
+= Length
;
2376 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
2379 StringPtr
+= StrLen (L
"&WIDTH=");
2384 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
2385 if (EFI_ERROR (Status
)) {
2392 (((Length
+ 1) / 2) < sizeof (UINT16
)) ? ((Length
+ 1) / 2) : sizeof (UINT16
)
2394 FreePool (TmpBuffer
);
2396 StringPtr
+= Length
;
2397 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
2404 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
2405 if (BlockData
== NULL
) {
2408 BlockData
->Offset
= Offset
;
2409 BlockData
->Width
= Width
;
2410 InsertBlockData (&RequestBlockArray
->Entry
, &BlockData
);
2413 // Skip &VALUE string if &VALUE does exists.
2415 if (StrnCmp (StringPtr
, L
"&VALUE=", StrLen (L
"&VALUE=")) == 0) {
2416 StringPtr
+= StrLen (L
"&VALUE=");
2421 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
2422 if (EFI_ERROR (Status
)) {
2426 StringPtr
+= Length
;
2427 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
2432 // If '\0', parsing is finished.
2434 if (*StringPtr
== 0) {
2440 // Merge the requested block data.
2442 Link
= RequestBlockArray
->Entry
.ForwardLink
;
2443 while ((Link
!= &RequestBlockArray
->Entry
) && (Link
->ForwardLink
!= &RequestBlockArray
->Entry
)) {
2444 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
2445 NextBlockData
= BASE_CR (Link
->ForwardLink
, IFR_BLOCK_DATA
, Entry
);
2446 if ((NextBlockData
->Offset
>= BlockData
->Offset
) && (NextBlockData
->Offset
<= (BlockData
->Offset
+ BlockData
->Width
))) {
2447 if ((NextBlockData
->Offset
+ NextBlockData
->Width
) > (BlockData
->Offset
+ BlockData
->Width
)) {
2448 BlockData
->Width
= (UINT16
) (NextBlockData
->Offset
+ NextBlockData
->Width
- BlockData
->Offset
);
2450 RemoveEntryList (Link
->ForwardLink
);
2451 FreePool (NextBlockData
);
2454 Link
= Link
->ForwardLink
;
2457 return RequestBlockArray
;
2460 if (RequestBlockArray
!= NULL
) {
2462 // Free Link Array RequestBlockArray
2464 while (!IsListEmpty (&RequestBlockArray
->Entry
)) {
2465 BlockData
= BASE_CR (RequestBlockArray
->Entry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
2466 RemoveEntryList (&BlockData
->Entry
);
2467 FreePool (BlockData
);
2470 FreePool (RequestBlockArray
);
2477 parse the configrequest string, get the elements.
2479 @param ConfigRequest The input config request string.
2480 @param Progress Return the progress data.
2482 @retval return data block array.
2486 IN EFI_STRING ConfigRequest
,
2487 OUT EFI_STRING
*Progress
2490 EFI_STRING StringPtr
;
2492 IFR_BLOCK_DATA
*BlockData
;
2493 IFR_BLOCK_DATA
*RequestBlockArray
;
2496 StringPtr
= ConfigRequest
;
2499 // Init RequestBlockArray
2501 RequestBlockArray
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
2502 if (RequestBlockArray
== NULL
) {
2505 InitializeListHead (&RequestBlockArray
->Entry
);
2508 // Get the request Block array from the request string
2512 // Parse each <RequestElement> if exists
2513 // Only <BlockName> format is supported by this help function.
2514 // <BlockName> ::= &'Name***=***
2516 while (StringPtr
!= NULL
&& *StringPtr
== L
'&') {
2518 *Progress
= StringPtr
;
2520 // Skip the L"&" string
2525 if ((NextTag
= StrStr (StringPtr
, L
"=")) != NULL
) {
2528 } else if ((NextTag
= StrStr (StringPtr
, L
"&")) != NULL
) {
2535 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
2536 if (BlockData
== NULL
) {
2543 BlockData
->Name
= AllocateCopyPool(StrSize (StringPtr
), StringPtr
);
2544 InsertBlockData (&RequestBlockArray
->Entry
, &BlockData
);
2548 // If has value, skip the value.
2550 StringPtr
= NextTag
+ 1;
2552 StringPtr
= StrStr (StringPtr
, L
"&");
2553 } else if (NextTag
!= NULL
) {
2555 // restore the '&' text.
2557 StringPtr
= NextTag
;
2562 return RequestBlockArray
;
2565 if (RequestBlockArray
!= NULL
) {
2567 // Free Link Array RequestBlockArray
2569 while (!IsListEmpty (&RequestBlockArray
->Entry
)) {
2570 BlockData
= BASE_CR (RequestBlockArray
->Entry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
2571 RemoveEntryList (&BlockData
->Entry
);
2572 if (BlockData
->Name
!= NULL
) {
2573 FreePool (BlockData
->Name
);
2575 FreePool (BlockData
);
2578 FreePool (RequestBlockArray
);
2585 Generate ConfigRequest string base on the varstore info.
2587 @param ConfigHdr The config header for this varstore.
2588 @param VarStorageData The varstore info.
2589 @param Status Return Status.
2590 @param ConfigRequest The ConfigRequest info may be return.
2592 @retval TRUE Need to continue
2593 @retval Others NO need to continue or error occur.
2596 GenerateConfigRequest (
2597 IN CHAR16
*ConfigHdr
,
2598 IN IFR_VARSTORAGE_DATA
*VarStorageData
,
2599 OUT EFI_STATUS
*Status
,
2600 IN OUT EFI_STRING
*ConfigRequest
2606 CHAR16
*FullConfigRequest
;
2608 IFR_BLOCK_DATA
*BlockData
;
2611 // Append VarStorageData BlockEntry into *Request string
2612 // Now support only one varstore in a form package.
2616 // Go through all VarStorageData Entry and get BlockEntry for each one for the multiple varstore in a single form package
2617 // Then construct them all to return MultiRequest string : ConfigHdr BlockConfig
2621 // Compute the length of the entire request starting with <ConfigHdr> and a
2625 Length
= StrLen (ConfigHdr
) + 1;
2627 for (Link
= VarStorageData
->BlockEntry
.ForwardLink
; Link
!= &VarStorageData
->BlockEntry
; Link
= Link
->ForwardLink
) {
2629 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
2630 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2632 // Add <BlockName> length for each Name
2634 // <BlockName> ::= &Name1&Name2&...
2635 // |1| StrLen(Name1)
2637 Length
= Length
+ (1 + StrLen (BlockData
->Name
));
2640 // Add <BlockName> length for each Offset/Width pair
2642 // <BlockName> ::= &OFFSET=1234&WIDTH=1234
2643 // | 8 | 4 | 7 | 4 |
2645 Length
= Length
+ (8 + 4 + 7 + 4);
2649 // No any request block data is found. The request string can't be constructed.
2652 *Status
= EFI_SUCCESS
;
2657 // Allocate buffer for the entire <ConfigRequest>
2659 FullConfigRequest
= AllocateZeroPool (Length
* sizeof (CHAR16
));
2660 if (FullConfigRequest
== NULL
) {
2661 *Status
= EFI_OUT_OF_RESOURCES
;
2664 StringPtr
= FullConfigRequest
;
2667 // Start with <ConfigHdr>
2669 StrCpy (StringPtr
, ConfigHdr
);
2670 StringPtr
+= StrLen (StringPtr
);
2673 // Loop through all the Offset/Width pairs and append them to ConfigRequest
2675 for (Link
= VarStorageData
->BlockEntry
.ForwardLink
; Link
!= &VarStorageData
->BlockEntry
; Link
= Link
->ForwardLink
) {
2676 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
2677 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2683 (1 + StrLen (BlockData
->Name
) + 1) * sizeof (CHAR16
),
2689 // Append &OFFSET=XXXX&WIDTH=YYYY\0
2693 (8 + 4 + 7 + 4 + 1) * sizeof (CHAR16
),
2694 L
"&OFFSET=%04X&WIDTH=%04X",
2699 StringPtr
+= StrLen (StringPtr
);
2702 // Set to the got full request string.
2704 HiiToLower (FullConfigRequest
);
2706 if (*ConfigRequest
!= NULL
) {
2707 FreePool (*ConfigRequest
);
2709 *ConfigRequest
= FullConfigRequest
;
2715 Generate ConfigRequest Header base on the varstore info.
2717 @param VarStorageData The varstore info.
2718 @param DevicePath Device path for this varstore.
2719 @param ConfigHdr The config header for this varstore.
2721 @retval EFI_SUCCESS Generate the header success.
2722 @retval EFI_OUT_OF_RESOURCES Allocate buffer fail.
2726 IN IFR_VARSTORAGE_DATA
*VarStorageData
,
2727 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
2728 OUT EFI_STRING
*ConfigHdr
2737 Status
= EFI_SUCCESS
;
2743 // Construct <ConfigHdr> : "GUID=...&NAME=...&PATH=..." by VarStorageData Guid, Name and DriverHandle
2745 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*) &VarStorageData
->Guid
, 1, &GuidStr
);
2746 if (VarStorageData
->Name
!= NULL
) {
2747 GenerateSubStr (L
"NAME=", StrLen (VarStorageData
->Name
) * sizeof (CHAR16
), (VOID
*) VarStorageData
->Name
, 2, &NameStr
);
2749 GenerateSubStr (L
"NAME=", 0, NULL
, 2, &NameStr
);
2753 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) DevicePath
),
2754 (VOID
*) DevicePath
,
2758 Length
= StrLen (GuidStr
) + StrLen (NameStr
) + StrLen (PathStr
) + 1;
2759 if (VarStorageData
->Name
== NULL
) {
2763 *ConfigHdr
= AllocateZeroPool (Length
* sizeof (CHAR16
));
2764 if (*ConfigHdr
== NULL
) {
2765 Status
= EFI_OUT_OF_RESOURCES
;
2768 StrCpy (*ConfigHdr
, GuidStr
);
2769 StrCat (*ConfigHdr
, NameStr
);
2770 if (VarStorageData
->Name
== NULL
) {
2771 StrCat (*ConfigHdr
, L
"&");
2773 StrCat (*ConfigHdr
, PathStr
);
2776 // Remove the last character L'&'
2778 *(*ConfigHdr
+ StrLen (*ConfigHdr
) - 1) = L
'\0';
2781 if (GuidStr
!= NULL
) {
2785 if (NameStr
!= NULL
) {
2789 if (PathStr
!= NULL
) {
2797 Get Data buffer size based on data type.
2799 @param ValueType The input data type.
2801 @retval The data buffer size for the input type.
2808 UINT16 StorageWidth
;
2810 switch (ValueType
) {
2811 case EFI_IFR_NUMERIC_SIZE_1
:
2812 case EFI_IFR_TYPE_BOOLEAN
:
2813 StorageWidth
= (UINT16
) sizeof (UINT8
);
2816 case EFI_IFR_NUMERIC_SIZE_2
:
2817 StorageWidth
= (UINT16
) sizeof (UINT16
);
2820 case EFI_IFR_NUMERIC_SIZE_4
:
2821 StorageWidth
= (UINT16
) sizeof (UINT32
);
2824 case EFI_IFR_NUMERIC_SIZE_8
:
2825 StorageWidth
= (UINT16
) sizeof (UINT64
);
2828 case EFI_IFR_TYPE_TIME
:
2829 StorageWidth
= (UINT16
) sizeof (EFI_IFR_TIME
);
2832 case EFI_IFR_TYPE_DATE
:
2833 StorageWidth
= (UINT16
) sizeof (EFI_IFR_DATE
);
2841 return StorageWidth
;
2845 Generate ConfigAltResp string base on the varstore info.
2847 @param ConfigHdr The config header for this varstore.
2848 @param VarStorageData The varstore info.
2849 @param DefaultIdArray The Default id array.
2850 @param DefaultAltCfgResp The DefaultAltCfgResp info may be return.
2852 @retval TRUE Need to continue
2853 @retval Others NO need to continue or error occur.
2856 GenerateAltConfigResp (
2857 IN CHAR16
*ConfigHdr
,
2858 IN IFR_VARSTORAGE_DATA
*VarStorageData
,
2859 IN IFR_DEFAULT_DATA
*DefaultIdArray
,
2860 IN OUT EFI_STRING
*DefaultAltCfgResp
2866 LIST_ENTRY
*LinkData
;
2867 LIST_ENTRY
*LinkDefault
;
2868 LIST_ENTRY
*ListEntry
;
2870 IFR_BLOCK_DATA
*BlockData
;
2871 IFR_DEFAULT_DATA
*DefaultId
;
2872 IFR_DEFAULT_DATA
*DefaultValueData
;
2880 // Add length for <ConfigHdr> + '\0'
2882 Length
= StrLen (ConfigHdr
) + 1;
2884 for (Link
= DefaultIdArray
->Entry
.ForwardLink
; Link
!= &DefaultIdArray
->Entry
; Link
= Link
->ForwardLink
) {
2885 DefaultId
= BASE_CR (Link
, IFR_DEFAULT_DATA
, Entry
);
2887 // Add length for "&<ConfigHdr>&ALTCFG=XXXX"
2888 // |1| StrLen (ConfigHdr) | 8 | 4 |
2890 Length
+= (1 + StrLen (ConfigHdr
) + 8 + 4);
2892 for (LinkData
= VarStorageData
->BlockEntry
.ForwardLink
; LinkData
!= &VarStorageData
->BlockEntry
; LinkData
= LinkData
->ForwardLink
) {
2893 BlockData
= BASE_CR (LinkData
, IFR_BLOCK_DATA
, Entry
);
2894 ListEntry
= &BlockData
->DefaultValueEntry
;
2895 for (LinkDefault
= ListEntry
->ForwardLink
; LinkDefault
!= ListEntry
; LinkDefault
= LinkDefault
->ForwardLink
) {
2896 DefaultValueData
= BASE_CR (LinkDefault
, IFR_DEFAULT_DATA
, Entry
);
2897 if (DefaultValueData
->DefaultId
!= DefaultId
->DefaultId
) {
2900 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2902 // Add length for "&Name1=zzzzzzzzzzzz"
2905 Length
+= (1 + StrLen (BlockData
->Name
) + 1 + BlockData
->Width
* 2);
2908 // Add length for "&OFFSET=XXXX&WIDTH=YYYY&VALUE=zzzzzzzzzzzz"
2909 // | 8 | 4 | 7 | 4 | 7 | Width * 2 |
2911 Length
+= (8 + 4 + 7 + 4 + 7 + BlockData
->Width
* 2);
2919 // No default value is found. The default string doesn't exist.
2926 // Allocate buffer for the entire <DefaultAltCfgResp>
2928 *DefaultAltCfgResp
= AllocateZeroPool (Length
* sizeof (CHAR16
));
2929 if (*DefaultAltCfgResp
== NULL
) {
2930 return EFI_OUT_OF_RESOURCES
;
2932 StringPtr
= *DefaultAltCfgResp
;
2935 // Start with <ConfigHdr>
2937 StrCpy (StringPtr
, ConfigHdr
);
2938 StringPtr
+= StrLen (StringPtr
);
2940 for (Link
= DefaultIdArray
->Entry
.ForwardLink
; Link
!= &DefaultIdArray
->Entry
; Link
= Link
->ForwardLink
) {
2941 DefaultId
= BASE_CR (Link
, IFR_DEFAULT_DATA
, Entry
);
2943 // Add <AltConfigHdr> of the form "&<ConfigHdr>&ALTCFG=XXXX\0"
2944 // |1| StrLen (ConfigHdr) | 8 | 4 |
2948 (1 + StrLen (ConfigHdr
) + 8 + 4 + 1) * sizeof (CHAR16
),
2951 DefaultId
->DefaultId
2953 StringPtr
+= StrLen (StringPtr
);
2955 for (LinkData
= VarStorageData
->BlockEntry
.ForwardLink
; LinkData
!= &VarStorageData
->BlockEntry
; LinkData
= LinkData
->ForwardLink
) {
2956 BlockData
= BASE_CR (LinkData
, IFR_BLOCK_DATA
, Entry
);
2957 ListEntry
= &BlockData
->DefaultValueEntry
;
2958 for (LinkDefault
= ListEntry
->ForwardLink
; LinkDefault
!= ListEntry
; LinkDefault
= LinkDefault
->ForwardLink
) {
2959 DefaultValueData
= BASE_CR (LinkDefault
, IFR_DEFAULT_DATA
, Entry
);
2960 if (DefaultValueData
->DefaultId
!= DefaultId
->DefaultId
) {
2963 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2966 (1 + StrLen (ConfigHdr
) + 1) * sizeof (CHAR16
),
2970 StringPtr
+= StrLen (StringPtr
);
2973 // Add <BlockConfig>
2974 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>
2978 (8 + 4 + 7 + 4 + 7 + 1) * sizeof (CHAR16
),
2979 L
"&OFFSET=%04X&WIDTH=%04X&VALUE=",
2983 StringPtr
+= StrLen (StringPtr
);
2985 Width
= BlockData
->Width
;
2987 // Convert Value to a hex string in "%x" format
2988 // NOTE: This is in the opposite byte that GUID and PATH use
2990 TmpBuffer
= (UINT8
*) &(DefaultValueData
->Value
);
2991 for (; Width
> 0; Width
--) {
2992 StringPtr
+= UnicodeValueToString (StringPtr
, PREFIX_ZERO
| RADIX_HEX
, TmpBuffer
[Width
- 1], 2);
2998 HiiToLower (*DefaultAltCfgResp
);
3004 This function gets the full request string and full default value string by
3005 parsing IFR data in HII form packages.
3007 When Request points to NULL string, the request string and default value string
3008 for each varstore in form package will return.
3010 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
3011 @param DevicePath Device Path which Hii Config Access Protocol is registered.
3012 @param Request Pointer to a null-terminated Unicode string in
3013 <ConfigRequest> format. When it doesn't contain
3014 any RequestElement, it will be updated to return
3015 the full RequestElement retrieved from IFR data.
3016 If it points to NULL, the request string for the first
3017 varstore in form package will be merged into a
3018 <MultiConfigRequest> format string and return.
3019 @param AltCfgResp Pointer to a null-terminated Unicode string in
3020 <ConfigAltResp> format. When the pointer is to NULL,
3021 the full default value string retrieved from IFR data
3022 will return. When the pinter is to a string, the
3023 full default value string retrieved from IFR data
3024 will be merged into the input string and return.
3025 When Request points to NULL, the default value string
3026 for each varstore in form package will be merged into
3027 a <MultiConfigAltResp> format string and return.
3028 @param PointerProgress Optional parameter, it can be be NULL.
3029 When it is not NULL, if Request is NULL, it returns NULL.
3030 On return, points to a character in the Request
3031 string. Points to the string's null terminator if
3032 request was successful. Points to the most recent
3033 & before the first failing name / value pair (or
3034 the beginning of the string if the failure is in
3035 the first name / value pair) if the request was
3037 @retval EFI_SUCCESS The Results string is set to the full request string.
3038 And AltCfgResp contains all default value string.
3039 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
3040 @retval EFI_NOT_FOUND The varstore (Guid and Name) in Request string
3041 can't be found in Form package.
3042 @retval EFI_NOT_FOUND HiiPackage can't be got on the input HiiHandle.
3043 @retval EFI_INVALID_PARAMETER Request points to NULL.
3048 GetFullStringFromHiiFormPackages (
3049 IN HII_DATABASE_RECORD
*DataBaseRecord
,
3050 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
3051 IN OUT EFI_STRING
*Request
,
3052 IN OUT EFI_STRING
*AltCfgResp
,
3053 OUT EFI_STRING
*PointerProgress OPTIONAL
3057 UINT8
*HiiFormPackage
;
3059 IFR_BLOCK_DATA
*RequestBlockArray
;
3060 IFR_BLOCK_DATA
*BlockData
;
3061 IFR_DEFAULT_DATA
*DefaultValueData
;
3062 IFR_DEFAULT_DATA
*DefaultId
;
3063 IFR_DEFAULT_DATA
*DefaultIdArray
;
3064 IFR_VARSTORAGE_DATA
*VarStorageData
;
3065 EFI_STRING DefaultAltCfgResp
;
3066 EFI_STRING ConfigHdr
;
3067 EFI_STRING StringPtr
;
3068 EFI_STRING Progress
;
3070 if (DataBaseRecord
== NULL
|| DevicePath
== NULL
|| Request
== NULL
|| AltCfgResp
== NULL
) {
3071 return EFI_INVALID_PARAMETER
;
3075 // Initialize the local variables.
3077 RequestBlockArray
= NULL
;
3078 DefaultIdArray
= NULL
;
3079 VarStorageData
= NULL
;
3080 DefaultAltCfgResp
= NULL
;
3082 HiiFormPackage
= NULL
;
3084 Progress
= *Request
;
3086 Status
= GetFormPackageData (DataBaseRecord
, &HiiFormPackage
, &PackageSize
);
3087 if (EFI_ERROR (Status
)) {
3092 // 1. Get the request block array by Request String when Request string containts the block array.
3095 if (*Request
!= NULL
) {
3096 StringPtr
= *Request
;
3100 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
3101 Status
= EFI_INVALID_PARAMETER
;
3104 StringPtr
+= StrLen (L
"GUID=");
3105 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&NAME=", StrLen (L
"&NAME=")) != 0) {
3108 if (*StringPtr
== L
'\0') {
3109 Status
= EFI_INVALID_PARAMETER
;
3112 StringPtr
+= StrLen (L
"&NAME=");
3113 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&PATH=", StrLen (L
"&PATH=")) != 0) {
3116 if (*StringPtr
== L
'\0') {
3117 Status
= EFI_INVALID_PARAMETER
;
3120 StringPtr
+= StrLen (L
"&PATH=");
3121 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
3125 if (*StringPtr
== L
'\0') {
3127 // No request block is found.
3134 // If StringPtr != NULL, get the request elements.
3136 if (StringPtr
!= NULL
) {
3137 if (StrStr (StringPtr
, L
"&OFFSET=") != NULL
) {
3138 RequestBlockArray
= GetBlockElement(StringPtr
, &Progress
);
3140 RequestBlockArray
= GetNameElement(StringPtr
, &Progress
);
3143 if (RequestBlockArray
== NULL
) {
3144 Status
= EFI_INVALID_PARAMETER
;
3150 // Initialize DefaultIdArray to store the map between DeaultId and DefaultName
3152 DefaultIdArray
= (IFR_DEFAULT_DATA
*) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
3153 if (DefaultIdArray
== NULL
) {
3154 Status
= EFI_OUT_OF_RESOURCES
;
3157 InitializeListHead (&DefaultIdArray
->Entry
);
3160 // Initialize VarStorageData to store the var store Block and Default value information.
3162 VarStorageData
= (IFR_VARSTORAGE_DATA
*) AllocateZeroPool (sizeof (IFR_VARSTORAGE_DATA
));
3163 if (VarStorageData
== NULL
) {
3164 Status
= EFI_OUT_OF_RESOURCES
;
3167 InitializeListHead (&VarStorageData
->Entry
);
3168 InitializeListHead (&VarStorageData
->BlockEntry
);
3171 // 2. Parse FormPackage to get BlockArray and DefaultId Array for the request BlockArray.
3175 // Parse the opcode in form pacakge to get the default setting.
3177 Status
= ParseIfrData (DataBaseRecord
->Handle
,
3179 (UINT32
) PackageSize
,
3184 if (EFI_ERROR (Status
)) {
3189 // No requested varstore in IFR data and directly return
3191 if (VarStorageData
->Type
== 0 && VarStorageData
->Name
== NULL
) {
3192 Status
= EFI_SUCCESS
;
3197 // 3. Construct Request Element (Block Name) for 2.1 and 2.2 case.
3199 Status
= GenerateHdr (VarStorageData
, DevicePath
, &ConfigHdr
);
3200 if (EFI_ERROR (Status
)) {
3204 if (RequestBlockArray
== NULL
) {
3205 if (!GenerateConfigRequest(ConfigHdr
, VarStorageData
, &Status
, Request
)) {
3211 // 4. Construct Default Value string in AltResp according to request element.
3212 // Go through all VarStorageData Entry and get the DefaultId array for each one
3213 // Then construct them all to : ConfigHdr AltConfigHdr ConfigBody AltConfigHdr ConfigBody
3215 Status
= GenerateAltConfigResp (ConfigHdr
, VarStorageData
, DefaultIdArray
, &DefaultAltCfgResp
);
3216 if (EFI_ERROR (Status
)) {
3221 // 5. Merge string into the input AltCfgResp if the iput *AltCfgResp is not NULL.
3223 if (*AltCfgResp
!= NULL
&& DefaultAltCfgResp
!= NULL
) {
3224 Status
= MergeDefaultString (AltCfgResp
, DefaultAltCfgResp
);
3225 FreePool (DefaultAltCfgResp
);
3226 } else if (*AltCfgResp
== NULL
) {
3227 *AltCfgResp
= DefaultAltCfgResp
;
3231 if (RequestBlockArray
!= NULL
) {
3233 // Free Link Array RequestBlockArray
3235 while (!IsListEmpty (&RequestBlockArray
->Entry
)) {
3236 BlockData
= BASE_CR (RequestBlockArray
->Entry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
3237 RemoveEntryList (&BlockData
->Entry
);
3238 if (BlockData
->Name
!= NULL
) {
3239 FreePool (BlockData
->Name
);
3241 FreePool (BlockData
);
3244 FreePool (RequestBlockArray
);
3247 if (VarStorageData
!= NULL
) {
3249 // Free link array VarStorageData
3251 while (!IsListEmpty (&VarStorageData
->BlockEntry
)) {
3252 BlockData
= BASE_CR (VarStorageData
->BlockEntry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
3253 RemoveEntryList (&BlockData
->Entry
);
3254 if (BlockData
->Name
!= NULL
) {
3255 FreePool (BlockData
->Name
);
3258 // Free default value link array
3260 while (!IsListEmpty (&BlockData
->DefaultValueEntry
)) {
3261 DefaultValueData
= BASE_CR (BlockData
->DefaultValueEntry
.ForwardLink
, IFR_DEFAULT_DATA
, Entry
);
3262 RemoveEntryList (&DefaultValueData
->Entry
);
3263 FreePool (DefaultValueData
);
3265 FreePool (BlockData
);
3267 FreePool (VarStorageData
);
3270 if (DefaultIdArray
!= NULL
) {
3272 // Free DefaultId Array
3274 while (!IsListEmpty (&DefaultIdArray
->Entry
)) {
3275 DefaultId
= BASE_CR (DefaultIdArray
->Entry
.ForwardLink
, IFR_DEFAULT_DATA
, Entry
);
3276 RemoveEntryList (&DefaultId
->Entry
);
3277 FreePool (DefaultId
);
3279 FreePool (DefaultIdArray
);
3283 // Free the allocated string
3285 if (ConfigHdr
!= NULL
) {
3286 FreePool (ConfigHdr
);
3290 // Free Pacakge data
3292 if (HiiFormPackage
!= NULL
) {
3293 FreePool (HiiFormPackage
);
3296 if (PointerProgress
!= NULL
) {
3297 if (*Request
== NULL
) {
3298 *PointerProgress
= NULL
;
3299 } else if (EFI_ERROR (Status
)) {
3300 *PointerProgress
= *Request
;
3302 *PointerProgress
= *Request
+ StrLen (*Request
);
3310 This function gets the full request resp string by
3311 parsing IFR data in HII form packages.
3313 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
3315 @param EfiVarStoreInfo The efi varstore info which is save in the EFI
3316 varstore data structure.
3317 @param Request Pointer to a null-terminated Unicode string in
3318 <ConfigRequest> format.
3319 @param RequestResp Pointer to a null-terminated Unicode string in
3320 <ConfigResp> format.
3321 @param AccessProgress On return, points to a character in the Request
3322 string. Points to the string's null terminator if
3323 request was successful. Points to the most recent
3324 & before the first failing name / value pair (or
3325 the beginning of the string if the failure is in
3326 the first name / value pair) if the request was
3329 @retval EFI_SUCCESS The Results string is set to the full request string.
3330 And AltCfgResp contains all default value string.
3331 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
3332 @retval EFI_INVALID_PARAMETER Request points to NULL.
3336 GetConfigRespFromEfiVarStore (
3337 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
3338 IN EFI_IFR_VARSTORE_EFI
*EfiVarStoreInfo
,
3339 IN EFI_STRING Request
,
3340 OUT EFI_STRING
*RequestResp
,
3341 OUT EFI_STRING
*AccessProgress
3345 EFI_STRING VarStoreName
;
3349 Status
= EFI_SUCCESS
;
3352 VarStoreName
= NULL
;
3353 *AccessProgress
= Request
;
3355 VarStoreName
= AllocateZeroPool (AsciiStrSize ((CHAR8
*)EfiVarStoreInfo
->Name
) * sizeof (CHAR16
));
3356 if (VarStoreName
== NULL
) {
3357 Status
= EFI_OUT_OF_RESOURCES
;
3360 AsciiStrToUnicodeStr ((CHAR8
*) EfiVarStoreInfo
->Name
, VarStoreName
);
3363 Status
= gRT
->GetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, NULL
, &BufferSize
, NULL
);
3364 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
3368 VarStore
= AllocateZeroPool (BufferSize
);
3369 ASSERT (VarStore
!= NULL
);
3370 Status
= gRT
->GetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, NULL
, &BufferSize
, VarStore
);
3371 if (EFI_ERROR (Status
)) {
3375 Status
= HiiBlockToConfig(This
, Request
, VarStore
, BufferSize
, RequestResp
, AccessProgress
);
3376 if (EFI_ERROR (Status
)) {
3381 if (VarStoreName
!= NULL
) {
3382 FreePool (VarStoreName
);
3385 if (VarStore
!= NULL
) {
3386 FreePool (VarStore
);
3394 This function route the full request resp string for efi varstore.
3396 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
3398 @param EfiVarStoreInfo The efi varstore info which is save in the EFI
3399 varstore data structure.
3400 @param RequestResp Pointer to a null-terminated Unicode string in
3401 <ConfigResp> format.
3402 @param Result Pointer to a null-terminated Unicode string in
3403 <ConfigResp> format.
3405 @retval EFI_SUCCESS The Results string is set to the full request string.
3406 And AltCfgResp contains all default value string.
3407 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
3408 @retval EFI_INVALID_PARAMETER Request points to NULL.
3412 RouteConfigRespForEfiVarStore (
3413 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
3414 IN EFI_IFR_VARSTORE_EFI
*EfiVarStoreInfo
,
3415 IN EFI_STRING RequestResp
,
3416 OUT EFI_STRING
*Result
3420 EFI_STRING VarStoreName
;
3425 Status
= EFI_SUCCESS
;
3428 VarStoreName
= NULL
;
3430 VarStoreName
= AllocateZeroPool (AsciiStrSize ((CHAR8
*)EfiVarStoreInfo
->Name
) * sizeof (CHAR16
));
3431 if (VarStoreName
== NULL
) {
3432 Status
= EFI_OUT_OF_RESOURCES
;
3435 AsciiStrToUnicodeStr ((CHAR8
*) EfiVarStoreInfo
->Name
, VarStoreName
);
3437 Status
= gRT
->GetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, NULL
, &BufferSize
, NULL
);
3438 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
3442 BlockSize
= BufferSize
;
3443 VarStore
= AllocateZeroPool (BufferSize
);
3444 ASSERT (VarStore
!= NULL
);
3445 Status
= gRT
->GetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, NULL
, &BufferSize
, VarStore
);
3446 if (EFI_ERROR (Status
)) {
3450 Status
= HiiConfigToBlock(This
, RequestResp
, VarStore
, &BlockSize
, Result
);
3451 if (EFI_ERROR (Status
)) {
3455 Status
= gRT
->SetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, EfiVarStoreInfo
->Attributes
, BufferSize
, VarStore
);
3456 if (EFI_ERROR (Status
)) {
3461 if (VarStoreName
!= NULL
) {
3462 FreePool (VarStoreName
);
3465 if (VarStore
!= NULL
) {
3466 FreePool (VarStore
);
3473 Validate the config request elements.
3475 @param ConfigElements A null-terminated Unicode string in <ConfigRequest> format,
3476 without configHdr field.
3478 @retval CHAR16 * THE first Name/value pair not correct.
3479 @retval NULL Success parse the name/value pair
3482 OffsetWidthValidate (
3483 CHAR16
*ConfigElements
3489 StringPtr
= ConfigElements
;
3493 if (StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) != 0) {
3497 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
3500 if (*StringPtr
== L
'\0') {
3504 StringPtr
+= StrLen (L
"&WIDTH=");
3505 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) != 0) {
3509 if (*StringPtr
== L
'\0') {
3516 Validate the config request elements.
3518 @param ConfigElements A null-terminated Unicode string in <ConfigRequest> format,
3519 without configHdr field.
3521 @retval CHAR16 * THE first Name/value pair not correct.
3522 @retval NULL Success parse the name/value pair
3527 CHAR16
*ConfigElements
3533 StringPtr
= ConfigElements
;
3537 if (*StringPtr
!= L
'&') {
3542 StringPtr
= StrStr (StringPtr
, L
"&");
3544 if (StringPtr
== NULL
) {
3551 Validate the config request string.
3553 @param ConfigRequest A null-terminated Unicode string in <ConfigRequest> format.
3555 @retval CHAR16 * THE first element not correct.
3556 @retval NULL Success parse the name/value pair
3560 ConfigRequestValidate (
3561 CHAR16
*ConfigRequest
3564 BOOLEAN HasNameField
;
3567 HasNameField
= TRUE
;
3568 StringPtr
= ConfigRequest
;
3571 // Check <ConfigHdr>
3573 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
3574 return ConfigRequest
;
3576 StringPtr
+= StrLen (L
"GUID=");
3577 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&NAME=", StrLen (L
"&NAME=")) != 0) {
3580 if (*StringPtr
== L
'\0') {
3581 return ConfigRequest
;
3583 StringPtr
+= StrLen (L
"&NAME=");
3584 if (*StringPtr
== L
'&') {
3585 HasNameField
= FALSE
;
3587 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&PATH=", StrLen (L
"&PATH=")) != 0) {
3590 if (*StringPtr
== L
'\0') {
3591 return ConfigRequest
;
3593 StringPtr
+= StrLen (L
"&PATH=");
3594 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
3598 if (*StringPtr
== L
'\0') {
3604 // Should be Buffer varstore, config request should be "OFFSET/Width" pairs.
3606 return OffsetWidthValidate(StringPtr
);
3609 // Should be Name/Value varstore, config request should be "&name1&name2..." pairs.
3611 return NameValueValidate(StringPtr
);
3616 This function allows a caller to extract the current configuration
3617 for one or more named elements from one or more drivers.
3619 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
3621 @param Request A null-terminated Unicode string in
3622 <MultiConfigRequest> format.
3623 @param Progress On return, points to a character in the Request
3624 string. Points to the string's null terminator if
3625 request was successful. Points to the most recent
3626 & before the first failing name / value pair (or
3627 the beginning of the string if the failure is in
3628 the first name / value pair) if the request was
3630 @param Results Null-terminated Unicode string in
3631 <MultiConfigAltResp> format which has all values
3632 filled in for the names in the Request string.
3633 String to be allocated by the called function.
3635 @retval EFI_SUCCESS The Results string is filled with the values
3636 corresponding to all requested names.
3637 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
3638 results that must be stored awaiting possible
3640 @retval EFI_NOT_FOUND Routing data doesn't match any known driver.
3641 Progress set to the "G" in "GUID" of the routing
3642 header that doesn't match. Note: There is no
3643 requirement that all routing data be validated
3644 before any configuration extraction.
3645 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Request
3646 parameter would result in this type of error. The
3647 Progress parameter is set to NULL.
3648 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set to most recent &
3649 before the error or the beginning of the string.
3650 @retval EFI_INVALID_PARAMETER The ExtractConfig function of the underlying HII
3651 Configuration Access Protocol returned
3652 EFI_INVALID_PARAMETER. Progress set to most recent
3653 & before the error or the beginning of the string.
3658 HiiConfigRoutingExtractConfig (
3659 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
3660 IN CONST EFI_STRING Request
,
3661 OUT EFI_STRING
*Progress
,
3662 OUT EFI_STRING
*Results
3665 HII_DATABASE_PRIVATE_DATA
*Private
;
3666 EFI_STRING StringPtr
;
3667 EFI_STRING ConfigRequest
;
3669 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
3670 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
3673 HII_DATABASE_RECORD
*Database
;
3674 UINT8
*DevicePathPkg
;
3675 UINT8
*CurrentDevicePath
;
3676 EFI_HANDLE DriverHandle
;
3677 EFI_HII_HANDLE HiiHandle
;
3678 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
3679 EFI_STRING AccessProgress
;
3680 EFI_STRING AccessResults
;
3681 EFI_STRING DefaultResults
;
3682 BOOLEAN FirstElement
;
3683 BOOLEAN IfrDataParsedFlag
;
3684 BOOLEAN IsEfiVarStore
;
3685 EFI_IFR_VARSTORE_EFI
*EfiVarStoreInfo
;
3686 EFI_STRING ErrorPtr
;
3687 UINTN DevicePathSize
;
3689 if (This
== NULL
|| Progress
== NULL
|| Results
== NULL
) {
3690 return EFI_INVALID_PARAMETER
;
3693 if (Request
== NULL
) {
3695 return EFI_INVALID_PARAMETER
;
3698 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
3699 StringPtr
= Request
;
3700 *Progress
= StringPtr
;
3701 DefaultResults
= NULL
;
3702 ConfigRequest
= NULL
;
3703 Status
= EFI_SUCCESS
;
3704 AccessResults
= NULL
;
3705 AccessProgress
= NULL
;
3707 IfrDataParsedFlag
= FALSE
;
3708 IsEfiVarStore
= FALSE
;
3709 EfiVarStoreInfo
= NULL
;
3712 // The first element of <MultiConfigRequest> should be
3713 // <GuidHdr>, which is in 'GUID='<Guid> syntax.
3715 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
3716 return EFI_INVALID_PARAMETER
;
3719 FirstElement
= TRUE
;
3722 // Allocate a fix length of memory to store Results. Reallocate memory for
3723 // Results if this fix length is insufficient.
3725 *Results
= (EFI_STRING
) AllocateZeroPool (MAX_STRING_LENGTH
);
3726 if (*Results
== NULL
) {
3727 return EFI_OUT_OF_RESOURCES
;
3730 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) == 0) {
3732 // If parsing error, set Progress to the beginning of the <MultiConfigRequest>
3733 // or most recent & before the error.
3735 if (StringPtr
== Request
) {
3736 *Progress
= StringPtr
;
3738 *Progress
= StringPtr
- 1;
3742 // Process each <ConfigRequest> of <MultiConfigRequest>
3744 Length
= CalculateConfigStringLen (StringPtr
);
3745 ConfigRequest
= AllocateCopyPool ((Length
+ 1) * sizeof (CHAR16
), StringPtr
);
3746 if (ConfigRequest
== NULL
) {
3747 Status
= EFI_OUT_OF_RESOURCES
;
3750 *(ConfigRequest
+ Length
) = 0;
3753 // Get the UEFI device path
3755 Status
= GetDevicePath (ConfigRequest
, (UINT8
**) &DevicePath
);
3756 if (EFI_ERROR (Status
)) {
3761 // Find driver which matches the routing data.
3763 DriverHandle
= NULL
;
3766 for (Link
= Private
->DatabaseList
.ForwardLink
;
3767 Link
!= &Private
->DatabaseList
;
3768 Link
= Link
->ForwardLink
3770 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
3771 if ((DevicePathPkg
= Database
->PackageList
->DevicePathPkg
) != NULL
) {
3772 CurrentDevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
3773 DevicePathSize
= GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) CurrentDevicePath
);
3774 if ((CompareMem (DevicePath
,CurrentDevicePath
,DevicePathSize
) == 0) && IsThisPackageList(Database
, Request
)) {
3775 DriverHandle
= Database
->DriverHandle
;
3776 HiiHandle
= Database
->Handle
;
3783 // Try to find driver handle by device path.
3785 if (DriverHandle
== NULL
) {
3786 TempDevicePath
= DevicePath
;
3787 Status
= gBS
->LocateDevicePath (
3788 &gEfiDevicePathProtocolGuid
,
3792 if (EFI_ERROR (Status
) || (DriverHandle
== NULL
)) {
3794 // Routing data does not match any known driver.
3795 // Set Progress to the 'G' in "GUID" of the routing header.
3797 *Progress
= StringPtr
;
3798 Status
= EFI_NOT_FOUND
;
3804 // Validate ConfigRequest String.
3806 ErrorPtr
= ConfigRequestValidate(ConfigRequest
);
3807 if (ErrorPtr
!= NULL
) {
3808 *Progress
= StrStr (StringPtr
, ErrorPtr
);
3809 Status
= EFI_INVALID_PARAMETER
;
3814 // Check whether ConfigRequest contains request string.
3816 IfrDataParsedFlag
= FALSE
;
3817 if ((HiiHandle
!= NULL
) && !GetElementsFromRequest(ConfigRequest
)) {
3819 // Get the full request string from IFR when HiiPackage is registered to HiiHandle
3821 IfrDataParsedFlag
= TRUE
;
3822 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &ConfigRequest
, &DefaultResults
, &AccessProgress
);
3823 if (EFI_ERROR (Status
)) {
3825 // AccessProgress indicates the parsing progress on <ConfigRequest>.
3826 // Map it to the progress on <MultiConfigRequest> then return it.
3828 ASSERT (AccessProgress
!= NULL
);
3829 *Progress
= StrStr (StringPtr
, AccessProgress
);
3833 // Not any request block is found.
3835 if (!GetElementsFromRequest(ConfigRequest
)) {
3836 AccessResults
= AllocateCopyPool (StrSize (ConfigRequest
), ConfigRequest
);
3837 goto NextConfigString
;
3842 // Check whether this ConfigRequest is search from Efi varstore type storage.
3844 Status
= GetVarStoreType(Database
, ConfigRequest
, &IsEfiVarStore
, &EfiVarStoreInfo
);
3845 if (EFI_ERROR (Status
)) {
3849 if (IsEfiVarStore
) {
3851 // Call the GetVariable function to extract settings.
3853 Status
= GetConfigRespFromEfiVarStore(This
, EfiVarStoreInfo
, ConfigRequest
, &AccessResults
, &AccessProgress
);
3854 FreePool (EfiVarStoreInfo
);
3857 // Call corresponding ConfigAccess protocol to extract settings
3859 Status
= gBS
->HandleProtocol (
3861 &gEfiHiiConfigAccessProtocolGuid
,
3862 (VOID
**) &ConfigAccess
3864 ASSERT_EFI_ERROR (Status
);
3866 Status
= ConfigAccess
->ExtractConfig (
3873 if (EFI_ERROR (Status
)) {
3875 // AccessProgress indicates the parsing progress on <ConfigRequest>.
3876 // Map it to the progress on <MultiConfigRequest> then return it.
3878 *Progress
= StrStr (StringPtr
, AccessProgress
);
3883 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'
3884 // which seperates the first <ConfigAltResp> and the following ones.
3886 ASSERT (*AccessProgress
== 0);
3889 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
3891 if (!IfrDataParsedFlag
&& HiiHandle
!= NULL
) {
3892 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &ConfigRequest
, &DefaultResults
, NULL
);
3893 ASSERT_EFI_ERROR (Status
);
3896 FreePool (DevicePath
);
3899 if (DefaultResults
!= NULL
) {
3900 Status
= MergeDefaultString (&AccessResults
, DefaultResults
);
3901 ASSERT_EFI_ERROR (Status
);
3902 FreePool (DefaultResults
);
3903 DefaultResults
= NULL
;
3907 if (!FirstElement
) {
3908 Status
= AppendToMultiString (Results
, L
"&");
3909 ASSERT_EFI_ERROR (Status
);
3912 Status
= AppendToMultiString (Results
, AccessResults
);
3913 ASSERT_EFI_ERROR (Status
);
3915 FirstElement
= FALSE
;
3917 FreePool (AccessResults
);
3918 AccessResults
= NULL
;
3919 FreePool (ConfigRequest
);
3920 ConfigRequest
= NULL
;
3923 // Go to next <ConfigRequest> (skip '&').
3925 StringPtr
+= Length
;
3926 if (*StringPtr
== 0) {
3927 *Progress
= StringPtr
;
3935 if (EFI_ERROR (Status
)) {
3936 FreePool (*Results
);
3940 if (ConfigRequest
!= NULL
) {
3941 FreePool (ConfigRequest
);
3944 if (AccessResults
!= NULL
) {
3945 FreePool (AccessResults
);
3948 if (DefaultResults
!= NULL
) {
3949 FreePool (DefaultResults
);
3952 if (DevicePath
!= NULL
) {
3953 FreePool (DevicePath
);
3961 This function allows the caller to request the current configuration for the
3962 entirety of the current HII database and returns the data in a
3963 null-terminated Unicode string.
3965 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
3967 @param Results Null-terminated Unicode string in
3968 <MultiConfigAltResp> format which has all values
3969 filled in for the entirety of the current HII
3970 database. String to be allocated by the called
3971 function. De-allocation is up to the caller.
3973 @retval EFI_SUCCESS The Results string is filled with the values
3974 corresponding to all requested names.
3975 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
3976 results that must be stored awaiting possible
3978 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Results
3979 parameter would result in this type of error.
3984 HiiConfigRoutingExportConfig (
3985 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
3986 OUT EFI_STRING
*Results
3990 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
3991 EFI_STRING AccessResults
;
3992 EFI_STRING Progress
;
3993 EFI_STRING StringPtr
;
3994 EFI_STRING ConfigRequest
;
3996 EFI_HANDLE
*ConfigAccessHandles
;
3997 UINTN NumberConfigAccessHandles
;
3998 BOOLEAN FirstElement
;
3999 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
4000 EFI_HII_HANDLE HiiHandle
;
4001 EFI_STRING DefaultResults
;
4002 HII_DATABASE_PRIVATE_DATA
*Private
;
4004 HII_DATABASE_RECORD
*Database
;
4005 UINT8
*DevicePathPkg
;
4006 UINT8
*CurrentDevicePath
;
4007 BOOLEAN IfrDataParsedFlag
;
4009 if (This
== NULL
|| Results
== NULL
) {
4010 return EFI_INVALID_PARAMETER
;
4013 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
4016 // Allocate a fix length of memory to store Results. Reallocate memory for
4017 // Results if this fix length is insufficient.
4019 *Results
= (EFI_STRING
) AllocateZeroPool (MAX_STRING_LENGTH
);
4020 if (*Results
== NULL
) {
4021 return EFI_OUT_OF_RESOURCES
;
4024 NumberConfigAccessHandles
= 0;
4025 Status
= gBS
->LocateHandleBuffer (
4027 &gEfiHiiConfigAccessProtocolGuid
,
4029 &NumberConfigAccessHandles
,
4030 &ConfigAccessHandles
4032 if (EFI_ERROR (Status
)) {
4036 FirstElement
= TRUE
;
4038 for (Index
= 0; Index
< NumberConfigAccessHandles
; Index
++) {
4039 Status
= gBS
->HandleProtocol (
4040 ConfigAccessHandles
[Index
],
4041 &gEfiHiiConfigAccessProtocolGuid
,
4042 (VOID
**) &ConfigAccess
4044 if (EFI_ERROR (Status
)) {
4049 // Get DevicePath and HiiHandle for this ConfigAccess driver handle
4051 IfrDataParsedFlag
= FALSE
;
4054 DefaultResults
= NULL
;
4056 ConfigRequest
= NULL
;
4057 DevicePath
= DevicePathFromHandle (ConfigAccessHandles
[Index
]);
4058 if (DevicePath
!= NULL
) {
4059 for (Link
= Private
->DatabaseList
.ForwardLink
;
4060 Link
!= &Private
->DatabaseList
;
4061 Link
= Link
->ForwardLink
4063 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
4064 if ((DevicePathPkg
= Database
->PackageList
->DevicePathPkg
) != NULL
) {
4065 CurrentDevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
4069 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) CurrentDevicePath
)
4071 HiiHandle
= Database
->Handle
;
4078 Status
= ConfigAccess
->ExtractConfig (
4084 if (EFI_ERROR (Status
)) {
4086 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
4088 if (HiiHandle
!= NULL
&& DevicePath
!= NULL
) {
4089 IfrDataParsedFlag
= TRUE
;
4090 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &ConfigRequest
, &DefaultResults
, NULL
);
4092 // Get the full request string to get the Current setting again.
4094 if (!EFI_ERROR (Status
) && ConfigRequest
!= NULL
) {
4095 Status
= ConfigAccess
->ExtractConfig (
4101 FreePool (ConfigRequest
);
4103 Status
= EFI_NOT_FOUND
;
4108 if (!EFI_ERROR (Status
)) {
4110 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
4112 if (!IfrDataParsedFlag
&& HiiHandle
!= NULL
&& DevicePath
!= NULL
) {
4113 StringPtr
= StrStr (AccessResults
, L
"&GUID=");
4114 if (StringPtr
!= NULL
) {
4117 if (GetElementsFromRequest (AccessResults
)) {
4118 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &AccessResults
, &DefaultResults
, NULL
);
4119 ASSERT_EFI_ERROR (Status
);
4121 if (StringPtr
!= NULL
) {
4126 // Merge the default sting from IFR code into the got setting from driver.
4128 if (DefaultResults
!= NULL
) {
4129 Status
= MergeDefaultString (&AccessResults
, DefaultResults
);
4130 ASSERT_EFI_ERROR (Status
);
4131 FreePool (DefaultResults
);
4132 DefaultResults
= NULL
;
4136 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'
4137 // which seperates the first <ConfigAltResp> and the following ones.
4139 if (!FirstElement
) {
4140 Status
= AppendToMultiString (Results
, L
"&");
4141 ASSERT_EFI_ERROR (Status
);
4144 Status
= AppendToMultiString (Results
, AccessResults
);
4145 ASSERT_EFI_ERROR (Status
);
4147 FirstElement
= FALSE
;
4149 FreePool (AccessResults
);
4150 AccessResults
= NULL
;
4153 FreePool (ConfigAccessHandles
);
4160 This function processes the results of processing forms and routes it to the
4161 appropriate handlers or storage.
4163 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
4165 @param Configuration A null-terminated Unicode string in
4166 <MulltiConfigResp> format.
4167 @param Progress A pointer to a string filled in with the offset of
4168 the most recent & before the first failing name /
4169 value pair (or the beginning of the string if the
4170 failure is in the first name / value pair) or the
4171 terminating NULL if all was successful.
4173 @retval EFI_SUCCESS The results have been distributed or are awaiting
4175 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
4176 results that must be stored awaiting possible
4178 @retval EFI_INVALID_PARAMETER Passing in a NULL for the Configuration parameter
4179 would result in this type of error.
4180 @retval EFI_NOT_FOUND Target for the specified routing data was not
4186 HiiConfigRoutingRouteConfig (
4187 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
4188 IN CONST EFI_STRING Configuration
,
4189 OUT EFI_STRING
*Progress
4192 HII_DATABASE_PRIVATE_DATA
*Private
;
4193 EFI_STRING StringPtr
;
4194 EFI_STRING ConfigResp
;
4197 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
4198 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
4200 HII_DATABASE_RECORD
*Database
;
4201 UINT8
*DevicePathPkg
;
4202 UINT8
*CurrentDevicePath
;
4203 EFI_HANDLE DriverHandle
;
4204 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
4205 EFI_STRING AccessProgress
;
4206 EFI_IFR_VARSTORE_EFI
*EfiVarStoreInfo
;
4207 BOOLEAN IsEfiVarstore
;
4208 UINTN DevicePathSize
;
4210 if (This
== NULL
|| Progress
== NULL
) {
4211 return EFI_INVALID_PARAMETER
;
4214 if (Configuration
== NULL
) {
4216 return EFI_INVALID_PARAMETER
;
4219 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
4220 StringPtr
= Configuration
;
4221 *Progress
= StringPtr
;
4223 AccessProgress
= NULL
;
4224 EfiVarStoreInfo
= NULL
;
4225 IsEfiVarstore
= FALSE
;
4228 // The first element of <MultiConfigResp> should be
4229 // <GuidHdr>, which is in 'GUID='<Guid> syntax.
4231 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
4232 return EFI_INVALID_PARAMETER
;
4235 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) == 0) {
4237 // If parsing error, set Progress to the beginning of the <MultiConfigResp>
4238 // or most recent & before the error.
4240 if (StringPtr
== Configuration
) {
4241 *Progress
= StringPtr
;
4243 *Progress
= StringPtr
- 1;
4247 // Process each <ConfigResp> of <MultiConfigResp>
4249 Length
= CalculateConfigStringLen (StringPtr
);
4250 ConfigResp
= AllocateCopyPool ((Length
+ 1) * sizeof (CHAR16
), StringPtr
);
4251 if (ConfigResp
== NULL
) {
4252 return EFI_OUT_OF_RESOURCES
;
4255 // Append '\0' to the end of ConfigRequest
4257 *(ConfigResp
+ Length
) = 0;
4260 // Get the UEFI device path
4262 Status
= GetDevicePath (ConfigResp
, (UINT8
**) &DevicePath
);
4263 if (EFI_ERROR (Status
)) {
4264 FreePool (ConfigResp
);
4269 // Find driver which matches the routing data.
4271 DriverHandle
= NULL
;
4272 for (Link
= Private
->DatabaseList
.ForwardLink
;
4273 Link
!= &Private
->DatabaseList
;
4274 Link
= Link
->ForwardLink
4276 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
4278 if ((DevicePathPkg
= Database
->PackageList
->DevicePathPkg
) != NULL
) {
4279 CurrentDevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
4280 DevicePathSize
= GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) CurrentDevicePath
);
4281 if ((CompareMem (DevicePath
,CurrentDevicePath
,DevicePathSize
) == 0) && IsThisPackageList(Database
, Configuration
)) {
4282 DriverHandle
= Database
->DriverHandle
;
4289 // Try to find driver handle by device path.
4291 if (DriverHandle
== NULL
) {
4292 TempDevicePath
= DevicePath
;
4293 Status
= gBS
->LocateDevicePath (
4294 &gEfiDevicePathProtocolGuid
,
4298 if (EFI_ERROR (Status
) || (DriverHandle
== NULL
)) {
4300 // Routing data does not match any known driver.
4301 // Set Progress to the 'G' in "GUID" of the routing header.
4303 FreePool (DevicePath
);
4304 *Progress
= StringPtr
;
4305 FreePool (ConfigResp
);
4306 return EFI_NOT_FOUND
;
4310 FreePool (DevicePath
);
4313 // Check whether this ConfigRequest is search from Efi varstore type storage.
4315 Status
= GetVarStoreType(Database
, ConfigResp
, &IsEfiVarstore
, &EfiVarStoreInfo
);
4316 if (EFI_ERROR (Status
)) {
4320 if (IsEfiVarstore
) {
4322 // Call the SetVariable function to route settings.
4324 Status
= RouteConfigRespForEfiVarStore(This
, EfiVarStoreInfo
, ConfigResp
, &AccessProgress
);
4325 FreePool (EfiVarStoreInfo
);
4328 // Call corresponding ConfigAccess protocol to route settings
4330 Status
= gBS
->HandleProtocol (
4332 &gEfiHiiConfigAccessProtocolGuid
,
4333 (VOID
**) &ConfigAccess
4335 ASSERT_EFI_ERROR (Status
);
4337 Status
= ConfigAccess
->RouteConfig (
4343 if (EFI_ERROR (Status
)) {
4345 // AccessProgress indicates the parsing progress on <ConfigResp>.
4346 // Map it to the progress on <MultiConfigResp> then return it.
4348 *Progress
= StrStr (StringPtr
, AccessProgress
);
4350 FreePool (ConfigResp
);
4354 FreePool (ConfigResp
);
4358 // Go to next <ConfigResp> (skip '&').
4360 StringPtr
+= Length
;
4361 if (*StringPtr
== 0) {
4362 *Progress
= StringPtr
;
4375 This helper function is to be called by drivers to map configuration data
4376 stored in byte array ("block") formats such as UEFI Variables into current
4377 configuration strings.
4379 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
4381 @param ConfigRequest A null-terminated Unicode string in
4382 <ConfigRequest> format.
4383 @param Block Array of bytes defining the block's configuration.
4384 @param BlockSize Length in bytes of Block.
4385 @param Config Filled-in configuration string. String allocated
4386 by the function. Returned only if call is
4387 successful. It is <ConfigResp> string format.
4388 @param Progress A pointer to a string filled in with the offset of
4389 the most recent & before the first failing
4390 name/value pair (or the beginning of the string if
4391 the failure is in the first name / value pair) or
4392 the terminating NULL if all was successful.
4394 @retval EFI_SUCCESS The request succeeded. Progress points to the null
4395 terminator at the end of the ConfigRequest
4397 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress
4398 points to the first character of ConfigRequest.
4399 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigRequest or
4400 Block parameter would result in this type of
4401 error. Progress points to the first character of
4403 @retval EFI_DEVICE_ERROR Block not large enough. Progress undefined.
4404 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted string.
4405 Block is left updated and Progress points at
4406 the "&" preceding the first non-<BlockName>.
4412 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
4413 IN CONST EFI_STRING ConfigRequest
,
4414 IN CONST UINT8
*Block
,
4415 IN CONST UINTN BlockSize
,
4416 OUT EFI_STRING
*Config
,
4417 OUT EFI_STRING
*Progress
4420 HII_DATABASE_PRIVATE_DATA
*Private
;
4421 EFI_STRING StringPtr
;
4429 EFI_STRING ValueStr
;
4430 EFI_STRING ConfigElement
;
4436 if (This
== NULL
|| Progress
== NULL
|| Config
== NULL
) {
4437 return EFI_INVALID_PARAMETER
;
4440 if (Block
== NULL
|| ConfigRequest
== NULL
) {
4441 *Progress
= ConfigRequest
;
4442 return EFI_INVALID_PARAMETER
;
4446 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
4447 ASSERT (Private
!= NULL
);
4449 StringPtr
= ConfigRequest
;
4452 ConfigElement
= NULL
;
4455 // Allocate a fix length of memory to store Results. Reallocate memory for
4456 // Results if this fix length is insufficient.
4458 *Config
= (EFI_STRING
) AllocateZeroPool (MAX_STRING_LENGTH
);
4459 if (*Config
== NULL
) {
4460 return EFI_OUT_OF_RESOURCES
;
4466 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
4467 *Progress
= StringPtr
;
4468 Status
= EFI_INVALID_PARAMETER
;
4471 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"PATH=", StrLen (L
"PATH=")) != 0) {
4474 if (*StringPtr
== 0) {
4475 *Progress
= StringPtr
- 1;
4476 Status
= EFI_INVALID_PARAMETER
;
4480 while (*StringPtr
!= L
'&' && *StringPtr
!= 0) {
4483 if (*StringPtr
== 0) {
4484 *Progress
= StringPtr
;
4485 Status
= EFI_SUCCESS
;
4487 AppendToMultiString(Config
, ConfigRequest
);
4488 HiiToLower (*Config
);
4498 // Copy <ConfigHdr> and an additional '&' to <ConfigResp>
4500 TemChar
= *StringPtr
;
4502 AppendToMultiString(Config
, ConfigRequest
);
4503 *StringPtr
= TemChar
;
4506 // Parse each <RequestElement> if exists
4507 // Only <BlockName> format is supported by this help function.
4508 // <BlockName> ::= 'OFFSET='<Number>&'WIDTH='<Number>
4510 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"OFFSET=", StrLen (L
"OFFSET=")) == 0) {
4512 // Back up the header of one <BlockName>
4516 StringPtr
+= StrLen (L
"OFFSET=");
4520 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
4521 if (EFI_ERROR (Status
)) {
4522 *Progress
= TmpPtr
- 1;
4529 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
4531 FreePool (TmpBuffer
);
4533 StringPtr
+= Length
;
4534 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
4535 *Progress
= TmpPtr
- 1;
4536 Status
= EFI_INVALID_PARAMETER
;
4539 StringPtr
+= StrLen (L
"&WIDTH=");
4544 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
4545 if (EFI_ERROR (Status
)) {
4546 *Progress
= TmpPtr
- 1;
4553 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
4555 FreePool (TmpBuffer
);
4557 StringPtr
+= Length
;
4558 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
4559 *Progress
= TmpPtr
- 1;
4560 Status
= EFI_INVALID_PARAMETER
;
4565 // Calculate Value and convert it to hex string.
4567 if (Offset
+ Width
> BlockSize
) {
4568 *Progress
= StringPtr
;
4569 Status
= EFI_DEVICE_ERROR
;
4573 Value
= (UINT8
*) AllocateZeroPool (Width
);
4574 if (Value
== NULL
) {
4575 *Progress
= ConfigRequest
;
4576 Status
= EFI_OUT_OF_RESOURCES
;
4580 CopyMem (Value
, (UINT8
*) Block
+ Offset
, Width
);
4582 Length
= Width
* 2 + 1;
4583 ValueStr
= (EFI_STRING
) AllocateZeroPool (Length
* sizeof (CHAR16
));
4584 if (ValueStr
== NULL
) {
4585 *Progress
= ConfigRequest
;
4586 Status
= EFI_OUT_OF_RESOURCES
;
4590 TemString
= ValueStr
;
4591 TemBuffer
= Value
+ Width
- 1;
4592 for (Index
= 0; Index
< Width
; Index
++, TemBuffer
--) {
4593 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
4600 // Build a ConfigElement
4602 Length
+= StringPtr
- TmpPtr
+ 1 + StrLen (L
"VALUE=");
4603 ConfigElement
= (EFI_STRING
) AllocateZeroPool (Length
* sizeof (CHAR16
));
4604 if (ConfigElement
== NULL
) {
4605 Status
= EFI_OUT_OF_RESOURCES
;
4608 CopyMem (ConfigElement
, TmpPtr
, (StringPtr
- TmpPtr
+ 1) * sizeof (CHAR16
));
4609 if (*StringPtr
== 0) {
4610 *(ConfigElement
+ (StringPtr
- TmpPtr
)) = L
'&';
4612 *(ConfigElement
+ (StringPtr
- TmpPtr
) + 1) = 0;
4613 StrCat (ConfigElement
, L
"VALUE=");
4614 StrCat (ConfigElement
, ValueStr
);
4616 AppendToMultiString (Config
, ConfigElement
);
4618 FreePool (ConfigElement
);
4619 FreePool (ValueStr
);
4620 ConfigElement
= NULL
;
4624 // If '\0', parsing is finished. Otherwise skip '&' to continue
4626 if (*StringPtr
== 0) {
4629 AppendToMultiString (Config
, L
"&");
4634 if (*StringPtr
!= 0) {
4635 *Progress
= StringPtr
- 1;
4636 Status
= EFI_INVALID_PARAMETER
;
4640 HiiToLower (*Config
);
4641 *Progress
= StringPtr
;
4645 if (*Config
!= NULL
) {
4649 if (ValueStr
!= NULL
) {
4650 FreePool (ValueStr
);
4652 if (Value
!= NULL
) {
4655 if (ConfigElement
!= NULL
) {
4656 FreePool (ConfigElement
);
4665 This helper function is to be called by drivers to map configuration strings
4666 to configurations stored in byte array ("block") formats such as UEFI Variables.
4668 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
4670 @param ConfigResp A null-terminated Unicode string in <ConfigResp>
4672 @param Block A possibly null array of bytes representing the
4673 current block. Only bytes referenced in the
4674 ConfigResp string in the block are modified. If
4675 this parameter is null or if the *BlockSize
4676 parameter is (on input) shorter than required by
4677 the Configuration string, only the BlockSize
4678 parameter is updated and an appropriate status
4679 (see below) is returned.
4680 @param BlockSize The length of the Block in units of UINT8. On
4681 input, this is the size of the Block. On output,
4682 if successful, contains the largest index of the
4683 modified byte in the Block, or the required buffer
4684 size if the Block is not large enough.
4685 @param Progress On return, points to an element of the ConfigResp
4686 string filled in with the offset of the most
4687 recent '&' before the first failing name / value
4688 pair (or the beginning of the string if the
4689 failure is in the first name / value pair) or the
4690 terminating NULL if all was successful.
4692 @retval EFI_SUCCESS The request succeeded. Progress points to the null
4693 terminator at the end of the ConfigResp string.
4694 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress
4695 points to the first character of ConfigResp.
4696 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigResp or
4697 Block parameter would result in this type of
4698 error. Progress points to the first character of
4700 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted name /
4701 value pair. Block is left updated and
4702 Progress points at the '&' preceding the first
4704 @retval EFI_BUFFER_TOO_SMALL Block not large enough. Progress undefined.
4705 BlockSize is updated with the required buffer size.
4706 @retval EFI_NOT_FOUND Target for the specified routing data was not found.
4707 Progress points to the "G" in "GUID" of the errant
4714 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
4715 IN CONST EFI_STRING ConfigResp
,
4716 IN OUT UINT8
*Block
,
4717 IN OUT UINTN
*BlockSize
,
4718 OUT EFI_STRING
*Progress
4721 HII_DATABASE_PRIVATE_DATA
*Private
;
4722 EFI_STRING StringPtr
;
4733 if (This
== NULL
|| BlockSize
== NULL
|| Progress
== NULL
) {
4734 return EFI_INVALID_PARAMETER
;
4737 *Progress
= ConfigResp
;
4738 if (ConfigResp
== NULL
) {
4739 return EFI_INVALID_PARAMETER
;
4742 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
4743 ASSERT (Private
!= NULL
);
4745 StringPtr
= ConfigResp
;
4746 BufferSize
= *BlockSize
;
4753 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
4754 *Progress
= StringPtr
;
4755 Status
= EFI_INVALID_PARAMETER
;
4758 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"PATH=", StrLen (L
"PATH=")) != 0) {
4761 if (*StringPtr
== 0) {
4762 *Progress
= StringPtr
;
4763 Status
= EFI_INVALID_PARAMETER
;
4767 while (*StringPtr
!= L
'&' && *StringPtr
!= 0) {
4770 if (*StringPtr
== 0) {
4771 *Progress
= StringPtr
;
4772 Status
= EFI_INVALID_PARAMETER
;
4777 // Parse each <ConfigElement> if exists
4778 // Only '&'<BlockConfig> format is supported by this help function.
4779 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE='<Number>
4781 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) == 0) {
4783 StringPtr
+= StrLen (L
"&OFFSET=");
4787 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
4788 if (EFI_ERROR (Status
)) {
4796 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
4798 FreePool (TmpBuffer
);
4800 StringPtr
+= Length
;
4801 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
4803 Status
= EFI_INVALID_PARAMETER
;
4806 StringPtr
+= StrLen (L
"&WIDTH=");
4811 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
4812 if (EFI_ERROR (Status
)) {
4820 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
4822 FreePool (TmpBuffer
);
4824 StringPtr
+= Length
;
4825 if (StrnCmp (StringPtr
, L
"&VALUE=", StrLen (L
"&VALUE=")) != 0) {
4827 Status
= EFI_INVALID_PARAMETER
;
4830 StringPtr
+= StrLen (L
"&VALUE=");
4835 Status
= GetValueOfNumber (StringPtr
, &Value
, &Length
);
4836 if (EFI_ERROR (Status
)) {
4841 StringPtr
+= Length
;
4842 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
4844 Status
= EFI_INVALID_PARAMETER
;
4849 // Update the Block with configuration info
4851 if ((Block
!= NULL
) && (Offset
+ Width
<= BufferSize
)) {
4852 CopyMem (Block
+ Offset
, Value
, Width
);
4854 if (Offset
+ Width
> MaxBlockSize
) {
4855 MaxBlockSize
= Offset
+ Width
;
4862 // If '\0', parsing is finished.
4864 if (*StringPtr
== 0) {
4870 // The input string is not ConfigResp format, return error.
4872 if (*StringPtr
!= 0) {
4873 *Progress
= StringPtr
;
4874 Status
= EFI_INVALID_PARAMETER
;
4878 *Progress
= StringPtr
+ StrLen (StringPtr
);
4879 *BlockSize
= MaxBlockSize
- 1;
4881 if (MaxBlockSize
> BufferSize
) {
4882 *BlockSize
= MaxBlockSize
;
4883 if (Block
!= NULL
) {
4884 return EFI_BUFFER_TOO_SMALL
;
4888 if (Block
== NULL
) {
4889 *Progress
= ConfigResp
;
4890 return EFI_INVALID_PARAMETER
;
4897 if (Value
!= NULL
) {
4905 This helper function is to be called by drivers to extract portions of
4906 a larger configuration string.
4908 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
4910 @param Configuration A null-terminated Unicode string in
4911 <MultiConfigAltResp> format.
4912 @param Guid A pointer to the GUID value to search for in the
4913 routing portion of the ConfigResp string when
4914 retrieving the requested data. If Guid is NULL,
4915 then all GUID values will be searched for.
4916 @param Name A pointer to the NAME value to search for in the
4917 routing portion of the ConfigResp string when
4918 retrieving the requested data. If Name is NULL,
4919 then all Name values will be searched for.
4920 @param DevicePath A pointer to the PATH value to search for in the
4921 routing portion of the ConfigResp string when
4922 retrieving the requested data. If DevicePath is
4923 NULL, then all DevicePath values will be searched
4925 @param AltCfgId A pointer to the ALTCFG value to search for in the
4926 routing portion of the ConfigResp string when
4927 retrieving the requested data. If this parameter
4928 is NULL, then the current setting will be
4930 @param AltCfgResp A pointer to a buffer which will be allocated by
4931 the function which contains the retrieved string
4932 as requested. This buffer is only allocated if
4933 the call was successful. It is <ConfigResp> format.
4935 @retval EFI_SUCCESS The request succeeded. The requested data was
4936 extracted and placed in the newly allocated
4938 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate AltCfgResp.
4939 @retval EFI_INVALID_PARAMETER Any parameter is invalid.
4940 @retval EFI_NOT_FOUND Target for the specified routing data was not
4947 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
4948 IN CONST EFI_STRING Configuration
,
4949 IN CONST EFI_GUID
*Guid
,
4950 IN CONST EFI_STRING Name
,
4951 IN CONST EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
4952 IN CONST UINT16
*AltCfgId
,
4953 OUT EFI_STRING
*AltCfgResp
4957 EFI_STRING StringPtr
;
4958 EFI_STRING HdrStart
;
4965 EFI_STRING AltIdStr
;
4982 if (This
== NULL
|| Configuration
== NULL
|| AltCfgResp
== NULL
) {
4983 return EFI_INVALID_PARAMETER
;
4986 StringPtr
= Configuration
;
4987 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
4988 return EFI_INVALID_PARAMETER
;
4992 // Generate the sub string for later matching.
4994 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*) Guid
, 1, &GuidStr
);
4997 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) DevicePath
),
4998 (VOID
*) DevicePath
,
5002 if (AltCfgId
!= NULL
) {
5003 GenerateSubStr (L
"ALTCFG=", sizeof (UINT16
), (VOID
*) AltCfgId
, 3, &AltIdStr
);
5006 GenerateSubStr (L
"NAME=", StrLen (Name
) * sizeof (CHAR16
), (VOID
*) Name
, 2, &NameStr
);
5008 GenerateSubStr (L
"NAME=", 0, NULL
, 2, &NameStr
);
5011 while (*StringPtr
!= 0) {
5013 // Try to match the GUID
5016 TmpPtr
= StrStr (StringPtr
, GuidStr
);
5017 if (TmpPtr
== NULL
) {
5018 Status
= EFI_NOT_FOUND
;
5024 // Jump to <NameHdr>
5027 StringPtr
= TmpPtr
+ StrLen (GuidStr
);
5029 StringPtr
= StrStr (TmpPtr
, L
"NAME=");
5030 if (StringPtr
== NULL
) {
5031 Status
= EFI_NOT_FOUND
;
5039 // Try to match the NAME
5041 if (GuidFlag
&& !NameFlag
) {
5042 if (StrnCmp (StringPtr
, NameStr
, StrLen (NameStr
)) != 0) {
5046 // Jump to <PathHdr>
5049 StringPtr
+= StrLen (NameStr
);
5051 StringPtr
= StrStr (StringPtr
, L
"PATH=");
5052 if (StringPtr
== NULL
) {
5053 Status
= EFI_NOT_FOUND
;
5062 // Try to match the DevicePath
5064 if (GuidFlag
&& NameFlag
&& !PathFlag
) {
5065 if (StrnCmp (StringPtr
, PathStr
, StrLen (PathStr
)) != 0) {
5070 // Jump to '&' before <DescHdr> or <ConfigBody>
5072 if (DevicePath
!= NULL
) {
5073 StringPtr
+= StrLen (PathStr
);
5075 StringPtr
= StrStr (StringPtr
, L
"&");
5076 if (StringPtr
== NULL
) {
5077 Status
= EFI_NOT_FOUND
;
5088 // Try to match the AltCfgId
5090 if (GuidFlag
&& NameFlag
&& PathFlag
) {
5091 if (AltCfgId
== NULL
) {
5093 // Return Current Setting when AltCfgId is NULL.
5095 Status
= OutputConfigBody (StringPtr
, &Result
);
5099 // Search the <ConfigAltResp> to get the <AltResp> with AltCfgId.
5101 if (StrnCmp (StringPtr
, AltIdStr
, StrLen (AltIdStr
)) != 0) {
5107 // Skip AltIdStr and &
5109 StringPtr
= StringPtr
+ StrLen (AltIdStr
);
5110 Status
= OutputConfigBody (StringPtr
, &Result
);
5116 Status
= EFI_NOT_FOUND
;
5120 if (!EFI_ERROR (Status
) && (Result
!= NULL
)) {
5122 // Copy the <ConfigHdr> and <ConfigBody>
5124 Length
= HdrEnd
- HdrStart
+ StrLen (Result
) + 1;
5125 *AltCfgResp
= AllocateZeroPool (Length
* sizeof (CHAR16
));
5126 if (*AltCfgResp
== NULL
) {
5127 Status
= EFI_OUT_OF_RESOURCES
;
5129 StrnCpy (*AltCfgResp
, HdrStart
, HdrEnd
- HdrStart
);
5130 StrCat (*AltCfgResp
, Result
);
5131 Status
= EFI_SUCCESS
;
5135 if (GuidStr
!= NULL
) {
5138 if (NameStr
!= NULL
) {
5141 if (PathStr
!= NULL
) {
5144 if (AltIdStr
!= NULL
) {
5145 FreePool (AltIdStr
);
5147 if (Result
!= NULL
) {