2 Implementation of interfaces function for EFI_HII_CONFIG_ROUTING_PROTOCOL.
4 Copyright (c) 2007 - 2014, 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
&& ConfigHdr
!= 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.
1441 if (HiiFormPackage
!= NULL
) {
1442 FreePool (HiiFormPackage
);
1445 if (VarStoreName
!= NULL
) {
1446 FreePool (VarStoreName
);
1449 return FindVarstore
;
1453 Check whether the this op code is required.
1455 @param RequestBlockArray The array includes all the request info or NULL.
1456 @param HiiHandle The hii handle for this form package.
1457 @param VarStorageData The varstore data strucure.
1458 @param IfrOpHdr Ifr opcode header for this opcode.
1459 @param VarWidth The buffer width for this opcode.
1460 @param ReturnData The data block added for this opcode.
1462 @retval EFI_SUCCESS This opcode is required.
1463 @retval Others This opcode is not required or error occur.
1467 IsThisOpcodeRequired (
1468 IN IFR_BLOCK_DATA
*RequestBlockArray
,
1469 IN EFI_HII_HANDLE HiiHandle
,
1470 IN OUT IFR_VARSTORAGE_DATA
*VarStorageData
,
1471 IN EFI_IFR_OP_HEADER
*IfrOpHdr
,
1473 OUT IFR_BLOCK_DATA
**ReturnData
1476 IFR_BLOCK_DATA
*BlockData
;
1478 EFI_STRING_ID NameId
;
1479 EFI_IFR_QUESTION_HEADER
*IfrQuestionHdr
;
1483 IfrQuestionHdr
= (EFI_IFR_QUESTION_HEADER
*)((CHAR8
*) IfrOpHdr
+ sizeof (EFI_IFR_OP_HEADER
));
1485 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
1486 NameId
= IfrQuestionHdr
->VarStoreInfo
.VarName
;
1489 // Check whether this question is in requested block array.
1491 if (!BlockArrayCheck (RequestBlockArray
, NameId
, 0, TRUE
, HiiHandle
)) {
1493 // This question is not in the requested string. Skip it.
1498 VarOffset
= IfrQuestionHdr
->VarStoreInfo
.VarOffset
;
1501 // Check whether this question is in requested block array.
1503 if (!BlockArrayCheck (RequestBlockArray
, VarOffset
, VarWidth
, FALSE
, HiiHandle
)) {
1505 // This question is not in the requested string. Skip it.
1511 // Check this var question is in the var storage
1513 if (((VarOffset
+ VarWidth
) > VarStorageData
->Size
)) {
1514 return EFI_INVALID_PARAMETER
;
1518 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
1519 if (BlockData
== NULL
) {
1520 return EFI_OUT_OF_RESOURCES
;
1523 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
1524 BlockData
->Name
= InternalGetString(HiiHandle
, NameId
);
1526 BlockData
->Offset
= VarOffset
;
1529 BlockData
->Width
= VarWidth
;
1530 BlockData
->QuestionId
= IfrQuestionHdr
->QuestionId
;
1531 BlockData
->OpCode
= IfrOpHdr
->OpCode
;
1532 BlockData
->Scope
= IfrOpHdr
->Scope
;
1533 InitializeListHead (&BlockData
->DefaultValueEntry
);
1535 // Add Block Data into VarStorageData BlockEntry
1537 InsertBlockData (&VarStorageData
->BlockEntry
, &BlockData
);
1538 *ReturnData
= BlockData
;
1544 This function parses Form Package to get the block array and the default
1545 value array according to the request ConfigHdr.
1547 @param HiiHandle Hii Handle for this hii package.
1548 @param Package Pointer to the form package data.
1549 @param PackageLength Length of the pacakge.
1550 @param ConfigHdr Request string ConfigHdr. If it is NULL,
1551 the first found varstore will be as ConfigHdr.
1552 @param RequestBlockArray The block array is retrieved from the request string.
1553 @param VarStorageData VarStorage structure contains the got block and default value.
1554 @param DefaultIdArray Point to the got default id and default name array.
1556 @retval EFI_SUCCESS The block array and the default value array are got.
1557 @retval EFI_INVALID_PARAMETER The varstore defintion in the differnt form pacakges
1559 @retval EFI_OUT_OF_RESOURCES No enough memory.
1564 IN EFI_HII_HANDLE HiiHandle
,
1566 IN UINT32 PackageLength
,
1567 IN EFI_STRING ConfigHdr
,
1568 IN IFR_BLOCK_DATA
*RequestBlockArray
,
1569 IN OUT IFR_VARSTORAGE_DATA
*VarStorageData
,
1570 OUT IFR_DEFAULT_DATA
*DefaultIdArray
1575 UINTN PackageOffset
;
1576 EFI_IFR_VARSTORE
*IfrVarStore
;
1577 EFI_IFR_VARSTORE_EFI
*IfrEfiVarStore
;
1578 EFI_IFR_OP_HEADER
*IfrOpHdr
;
1579 EFI_IFR_ONE_OF
*IfrOneOf
;
1580 EFI_IFR_REF4
*IfrRef
;
1581 EFI_IFR_ONE_OF_OPTION
*IfrOneOfOption
;
1582 EFI_IFR_DEFAULT
*IfrDefault
;
1583 EFI_IFR_ORDERED_LIST
*IfrOrderedList
;
1584 EFI_IFR_CHECKBOX
*IfrCheckBox
;
1585 EFI_IFR_PASSWORD
*IfrPassword
;
1586 EFI_IFR_STRING
*IfrString
;
1587 EFI_IFR_DATE
*IfrDate
;
1588 EFI_IFR_TIME
*IfrTime
;
1589 IFR_DEFAULT_DATA DefaultData
;
1590 IFR_DEFAULT_DATA
*DefaultDataPtr
;
1591 IFR_BLOCK_DATA
*BlockData
;
1592 CHAR16
*VarStoreName
;
1594 UINT16 VarDefaultId
;
1595 BOOLEAN FirstOneOfOption
;
1596 LIST_ENTRY
*LinkData
;
1597 LIST_ENTRY
*LinkDefault
;
1598 EFI_IFR_VARSTORE_NAME_VALUE
*IfrNameValueVarStore
;
1599 EFI_HII_PACKAGE_HEADER
*PackageHeader
;
1600 EFI_VARSTORE_ID VarStoreId
;
1602 Status
= EFI_SUCCESS
;
1604 DefaultDataPtr
= NULL
;
1605 FirstOneOfOption
= FALSE
;
1607 ZeroMem (&DefaultData
, sizeof (IFR_DEFAULT_DATA
));
1610 // Go through the form package to parse OpCode one by one.
1612 PackageOffset
= sizeof (EFI_HII_PACKAGE_HEADER
);
1613 PackageHeader
= (EFI_HII_PACKAGE_HEADER
*) Package
;
1614 IfrOffset
= PackageOffset
;
1615 while (IfrOffset
< PackageLength
) {
1618 // More than one form package found.
1620 if (PackageOffset
>= PackageHeader
->Length
) {
1622 // Already found varstore for this request, break;
1624 if (VarStoreId
!= 0) {
1629 // Get next package header info.
1631 IfrOffset
+= sizeof (EFI_HII_PACKAGE_HEADER
);
1632 PackageOffset
= sizeof (EFI_HII_PACKAGE_HEADER
);
1633 PackageHeader
= (EFI_HII_PACKAGE_HEADER
*) (Package
+ IfrOffset
);
1636 IfrOpHdr
= (EFI_IFR_OP_HEADER
*) (Package
+ IfrOffset
);
1637 switch (IfrOpHdr
->OpCode
) {
1638 case EFI_IFR_VARSTORE_OP
:
1640 // VarStore is found. Don't need to search any more.
1642 if (VarStoreId
!= 0) {
1646 IfrVarStore
= (EFI_IFR_VARSTORE
*) IfrOpHdr
;
1648 VarStoreName
= AllocateZeroPool (AsciiStrSize ((CHAR8
*)IfrVarStore
->Name
) * sizeof (CHAR16
));
1649 if (VarStoreName
== NULL
) {
1650 Status
= EFI_OUT_OF_RESOURCES
;
1653 AsciiStrToUnicodeStr ((CHAR8
*)IfrVarStore
->Name
, VarStoreName
);
1655 if (IsThisVarstore((VOID
*)&IfrVarStore
->Guid
, VarStoreName
, ConfigHdr
)) {
1657 // Find the matched VarStore
1659 CopyGuid (&VarStorageData
->Guid
, (EFI_GUID
*) (VOID
*) &IfrVarStore
->Guid
);
1660 VarStorageData
->Size
= IfrVarStore
->Size
;
1661 VarStorageData
->Name
= VarStoreName
;
1662 VarStorageData
->Type
= EFI_HII_VARSTORE_BUFFER
;
1663 VarStoreId
= IfrVarStore
->VarStoreId
;
1667 case EFI_IFR_VARSTORE_EFI_OP
:
1669 // VarStore is found. Don't need to search any more.
1671 if (VarStoreId
!= 0) {
1675 IfrEfiVarStore
= (EFI_IFR_VARSTORE_EFI
*) IfrOpHdr
;
1678 // If the length is small than the structure, this is from old efi
1679 // varstore definition. Old efi varstore get config directly from
1680 // GetVariable function.
1682 if (IfrOpHdr
->Length
< sizeof (EFI_IFR_VARSTORE_EFI
)) {
1686 VarStoreName
= AllocateZeroPool (AsciiStrSize ((CHAR8
*)IfrEfiVarStore
->Name
) * sizeof (CHAR16
));
1687 if (VarStoreName
== NULL
) {
1688 Status
= EFI_OUT_OF_RESOURCES
;
1691 AsciiStrToUnicodeStr ((CHAR8
*)IfrEfiVarStore
->Name
, VarStoreName
);
1693 if (IsThisVarstore (&IfrEfiVarStore
->Guid
, VarStoreName
, ConfigHdr
)) {
1695 // Find the matched VarStore
1697 CopyGuid (&VarStorageData
->Guid
, (EFI_GUID
*) (VOID
*) &IfrEfiVarStore
->Guid
);
1698 VarStorageData
->Size
= IfrEfiVarStore
->Size
;
1699 VarStorageData
->Name
= VarStoreName
;
1700 VarStorageData
->Type
= EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
;
1701 VarStoreId
= IfrEfiVarStore
->VarStoreId
;
1705 case EFI_IFR_VARSTORE_NAME_VALUE_OP
:
1707 // VarStore is found. Don't need to search any more.
1709 if (VarStoreId
!= 0) {
1713 IfrNameValueVarStore
= (EFI_IFR_VARSTORE_NAME_VALUE
*) IfrOpHdr
;
1715 if (IsThisVarstore (&IfrNameValueVarStore
->Guid
, NULL
, ConfigHdr
)) {
1717 // Find the matched VarStore
1719 CopyGuid (&VarStorageData
->Guid
, (EFI_GUID
*) (VOID
*) &IfrNameValueVarStore
->Guid
);
1720 VarStorageData
->Type
= EFI_HII_VARSTORE_NAME_VALUE
;
1721 VarStoreId
= IfrNameValueVarStore
->VarStoreId
;
1725 case EFI_IFR_DEFAULTSTORE_OP
:
1727 // Add new the map between default id and default name.
1729 DefaultDataPtr
= (IFR_DEFAULT_DATA
*) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
1730 if (DefaultDataPtr
== NULL
) {
1731 Status
= EFI_OUT_OF_RESOURCES
;
1734 DefaultDataPtr
->DefaultId
= ((EFI_IFR_DEFAULTSTORE
*) IfrOpHdr
)->DefaultId
;
1735 InsertTailList (&DefaultIdArray
->Entry
, &DefaultDataPtr
->Entry
);
1736 DefaultDataPtr
= NULL
;
1739 case EFI_IFR_FORM_OP
:
1740 case EFI_IFR_FORM_MAP_OP
:
1742 // No matched varstore is found and directly return.
1744 if ( VarStoreId
== 0) {
1745 Status
= EFI_SUCCESS
;
1750 case EFI_IFR_REF_OP
:
1752 // Ref question is not in IFR Form. This IFR form is not valid.
1754 if ( VarStoreId
== 0) {
1755 Status
= EFI_INVALID_PARAMETER
;
1759 // Check whether this question is for the requested varstore.
1761 IfrRef
= (EFI_IFR_REF4
*) IfrOpHdr
;
1762 if (IfrRef
->Question
.VarStoreId
!= VarStoreId
) {
1765 VarWidth
= (UINT16
) (sizeof (EFI_HII_REF
));
1767 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
1768 if (EFI_ERROR (Status
)) {
1773 case EFI_IFR_ONE_OF_OP
:
1774 case EFI_IFR_NUMERIC_OP
:
1776 // Numeric and OneOf has the same opcode structure.
1780 // Numeric and OneOf question is not in IFR Form. This IFR form is not valid.
1782 if (VarStoreId
== 0) {
1783 Status
= EFI_INVALID_PARAMETER
;
1787 // Check whether this question is for the requested varstore.
1789 IfrOneOf
= (EFI_IFR_ONE_OF
*) IfrOpHdr
;
1790 if (IfrOneOf
->Question
.VarStoreId
!= VarStoreId
) {
1793 VarWidth
= (UINT16
) (1 << (IfrOneOf
->Flags
& EFI_IFR_NUMERIC_SIZE
));
1795 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
1796 if (EFI_ERROR (Status
)) {
1800 if (BlockData
== NULL
) {
1802 // BlockData == NULL means this opcode is not in the requst array.
1807 if (IfrOpHdr
->OpCode
== EFI_IFR_ONE_OF_OP
) {
1809 // Set this flag to TRUE for the first oneof option.
1811 FirstOneOfOption
= TRUE
;
1812 } else if (IfrOpHdr
->OpCode
== EFI_IFR_NUMERIC_OP
) {
1814 // Numeric minimum value will be used as default value when no default is specified.
1816 DefaultData
.Type
= DefaultValueFromDefault
;
1817 switch (IfrOneOf
->Flags
& EFI_IFR_NUMERIC_SIZE
) {
1818 case EFI_IFR_NUMERIC_SIZE_1
:
1819 DefaultData
.Value
.u8
= IfrOneOf
->data
.u8
.MinValue
;
1822 case EFI_IFR_NUMERIC_SIZE_2
:
1823 CopyMem (&DefaultData
.Value
.u16
, &IfrOneOf
->data
.u16
.MinValue
, sizeof (UINT16
));
1826 case EFI_IFR_NUMERIC_SIZE_4
:
1827 CopyMem (&DefaultData
.Value
.u32
, &IfrOneOf
->data
.u32
.MinValue
, sizeof (UINT32
));
1830 case EFI_IFR_NUMERIC_SIZE_8
:
1831 CopyMem (&DefaultData
.Value
.u64
, &IfrOneOf
->data
.u64
.MinValue
, sizeof (UINT64
));
1835 Status
= EFI_INVALID_PARAMETER
;
1839 // Set default value base on the DefaultId list get from IFR data.
1841 for (LinkData
= DefaultIdArray
->Entry
.ForwardLink
; LinkData
!= &DefaultIdArray
->Entry
; LinkData
= LinkData
->ForwardLink
) {
1842 DefaultDataPtr
= BASE_CR (LinkData
, IFR_DEFAULT_DATA
, Entry
);
1843 DefaultData
.DefaultId
= DefaultDataPtr
->DefaultId
;
1844 InsertDefaultValue (BlockData
, &DefaultData
);
1849 case EFI_IFR_ORDERED_LIST_OP
:
1851 // offset by question header
1852 // width by EFI_IFR_ORDERED_LIST MaxContainers * OneofOption Type
1853 // no default value and default id, how to define its default value?
1857 // OrderedList question is not in IFR Form. This IFR form is not valid.
1859 if (VarStoreId
== 0) {
1860 Status
= EFI_INVALID_PARAMETER
;
1864 // Check whether this question is for the requested varstore.
1866 IfrOrderedList
= (EFI_IFR_ORDERED_LIST
*) IfrOpHdr
;
1867 if (IfrOrderedList
->Question
.VarStoreId
!= VarStoreId
) {
1871 VarWidth
= IfrOrderedList
->MaxContainers
;
1872 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
1873 if (EFI_ERROR (Status
)) {
1878 case EFI_IFR_CHECKBOX_OP
:
1880 // EFI_IFR_DEFAULT_OP
1881 // offset by question header
1882 // width is 1 sizeof (BOOLEAN)
1883 // default id by CheckBox Flags if CheckBox flags (Default or Mau) is set, the default value is 1 to be set.
1884 // value by DefaultOption
1885 // default id by DeaultOption DefaultId can override CheckBox Flags and Default value.
1889 // CheckBox question is not in IFR Form. This IFR form is not valid.
1891 if (VarStoreId
== 0) {
1892 Status
= EFI_INVALID_PARAMETER
;
1896 // Check whether this question is for the requested varstore.
1898 IfrCheckBox
= (EFI_IFR_CHECKBOX
*) IfrOpHdr
;
1899 if (IfrCheckBox
->Question
.VarStoreId
!= VarStoreId
) {
1902 VarWidth
= (UINT16
) sizeof (BOOLEAN
);
1903 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
1904 if (EFI_ERROR (Status
)) {
1908 if (BlockData
== NULL
) {
1910 // BlockData == NULL means this opcode is not in the requst array.
1916 // Add default value for standard ID by CheckBox Flag
1918 VarDefaultId
= EFI_HII_DEFAULT_CLASS_STANDARD
;
1920 // Prepare new DefaultValue
1922 DefaultData
.DefaultId
= VarDefaultId
;
1923 if ((IfrCheckBox
->Flags
& EFI_IFR_CHECKBOX_DEFAULT
) == EFI_IFR_CHECKBOX_DEFAULT
) {
1925 // When flag is set, defautl value is TRUE.
1927 DefaultData
.Type
= DefaultValueFromFlag
;
1928 DefaultData
.Value
.b
= TRUE
;
1931 // When flag is not set, defautl value is FASLE.
1933 DefaultData
.Type
= DefaultValueFromDefault
;
1934 DefaultData
.Value
.b
= FALSE
;
1937 // Add DefaultValue into current BlockData
1939 InsertDefaultValue (BlockData
, &DefaultData
);
1942 // Add default value for Manufacture ID by CheckBox Flag
1944 VarDefaultId
= EFI_HII_DEFAULT_CLASS_MANUFACTURING
;
1946 // Prepare new DefaultValue
1948 DefaultData
.DefaultId
= VarDefaultId
;
1949 if ((IfrCheckBox
->Flags
& EFI_IFR_CHECKBOX_DEFAULT_MFG
) == EFI_IFR_CHECKBOX_DEFAULT_MFG
) {
1951 // When flag is set, defautl value is TRUE.
1953 DefaultData
.Type
= DefaultValueFromFlag
;
1954 DefaultData
.Value
.b
= TRUE
;
1957 // When flag is not set, defautl value is FASLE.
1959 DefaultData
.Type
= DefaultValueFromDefault
;
1960 DefaultData
.Value
.b
= FALSE
;
1963 // Add DefaultValue into current BlockData
1965 InsertDefaultValue (BlockData
, &DefaultData
);
1968 case EFI_IFR_DATE_OP
:
1970 // offset by question header
1971 // width MaxSize * sizeof (CHAR16)
1972 // no default value, only block array
1976 // Date question is not in IFR Form. This IFR form is not valid.
1978 if (VarStoreId
== 0) {
1979 Status
= EFI_INVALID_PARAMETER
;
1983 // Check whether this question is for the requested varstore.
1985 IfrDate
= (EFI_IFR_DATE
*) IfrOpHdr
;
1986 if (IfrDate
->Question
.VarStoreId
!= VarStoreId
) {
1990 VarWidth
= (UINT16
) sizeof (EFI_HII_DATE
);
1991 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
1992 if (EFI_ERROR (Status
)) {
1997 case EFI_IFR_TIME_OP
:
1999 // offset by question header
2000 // width MaxSize * sizeof (CHAR16)
2001 // no default value, only block array
2005 // Time question is not in IFR Form. This IFR form is not valid.
2007 if (VarStoreId
== 0) {
2008 Status
= EFI_INVALID_PARAMETER
;
2012 // Check whether this question is for the requested varstore.
2014 IfrTime
= (EFI_IFR_TIME
*) IfrOpHdr
;
2015 if (IfrTime
->Question
.VarStoreId
!= VarStoreId
) {
2019 VarWidth
= (UINT16
) sizeof (EFI_HII_TIME
);
2020 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
2021 if (EFI_ERROR (Status
)) {
2026 case EFI_IFR_STRING_OP
:
2028 // offset by question header
2029 // width MaxSize * sizeof (CHAR16)
2030 // no default value, only block array
2034 // String question is not in IFR Form. This IFR form is not valid.
2036 if (VarStoreId
== 0) {
2037 Status
= EFI_INVALID_PARAMETER
;
2041 // Check whether this question is for the requested varstore.
2043 IfrString
= (EFI_IFR_STRING
*) IfrOpHdr
;
2044 if (IfrString
->Question
.VarStoreId
!= VarStoreId
) {
2048 VarWidth
= (UINT16
) (IfrString
->MaxSize
* sizeof (UINT16
));
2049 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
2050 if (EFI_ERROR (Status
)) {
2055 // No default value for string.
2060 case EFI_IFR_PASSWORD_OP
:
2062 // offset by question header
2063 // width MaxSize * sizeof (CHAR16)
2064 // no default value, only block array
2068 // Password question is not in IFR Form. This IFR form is not valid.
2070 if (VarStoreId
== 0) {
2071 Status
= EFI_INVALID_PARAMETER
;
2075 // Check whether this question is for the requested varstore.
2077 IfrPassword
= (EFI_IFR_PASSWORD
*) IfrOpHdr
;
2078 if (IfrPassword
->Question
.VarStoreId
!= VarStoreId
) {
2082 VarWidth
= (UINT16
) (IfrPassword
->MaxSize
* sizeof (UINT16
));
2083 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
2084 if (EFI_ERROR (Status
)) {
2089 // No default value for string.
2094 case EFI_IFR_ONE_OF_OPTION_OP
:
2096 // No matched block data is ignored.
2098 if (BlockData
== NULL
|| BlockData
->Scope
== 0) {
2102 IfrOneOfOption
= (EFI_IFR_ONE_OF_OPTION
*) IfrOpHdr
;
2103 if (BlockData
->OpCode
== EFI_IFR_ORDERED_LIST_OP
) {
2105 // Get ordered list option data type.
2107 if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_8
|| IfrOneOfOption
->Type
== EFI_IFR_TYPE_BOOLEAN
) {
2109 } else if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_16
) {
2111 } else if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_32
) {
2113 } else if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_64
) {
2117 // Invalid ordered list option data type.
2119 Status
= EFI_INVALID_PARAMETER
;
2120 if (BlockData
->Name
!= NULL
) {
2121 FreePool (BlockData
->Name
);
2123 FreePool (BlockData
);
2128 // Calculate Ordered list QuestionId width.
2130 BlockData
->Width
= (UINT16
) (BlockData
->Width
* VarWidth
);
2132 // Check whether this question is in requested block array.
2134 if (!BlockArrayCheck (RequestBlockArray
, BlockData
->Offset
, BlockData
->Width
, (BOOLEAN
)(BlockData
->Name
!= NULL
), HiiHandle
)) {
2136 // This question is not in the requested string. Skip it.
2138 if (BlockData
->Name
!= NULL
) {
2139 FreePool (BlockData
->Name
);
2141 FreePool (BlockData
);
2146 // Check this var question is in the var storage
2148 if ((BlockData
->Name
== NULL
) && ((BlockData
->Offset
+ BlockData
->Width
) > VarStorageData
->Size
)) {
2149 Status
= EFI_INVALID_PARAMETER
;
2150 if (BlockData
->Name
!= NULL
) {
2151 FreePool (BlockData
->Name
);
2153 FreePool (BlockData
);
2157 // Add Block Data into VarStorageData BlockEntry
2159 InsertBlockData (&VarStorageData
->BlockEntry
, &BlockData
);
2161 // No default data for OrderedList.
2168 // 1. Set default value for OneOf option when flag field has default attribute.
2170 if (((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT
) == EFI_IFR_OPTION_DEFAULT
) ||
2171 ((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT_MFG
) == EFI_IFR_OPTION_DEFAULT_MFG
)) {
2173 // This flag is used to specify whether this option is the first. Set it to FALSE for the following options.
2174 // The first oneof option value will be used as default value when no default value is specified.
2176 FirstOneOfOption
= FALSE
;
2178 // Prepare new DefaultValue
2180 DefaultData
.Type
= DefaultValueFromFlag
;
2181 CopyMem (&DefaultData
.Value
, &IfrOneOfOption
->Value
, IfrOneOfOption
->Header
.Length
- OFFSET_OF (EFI_IFR_ONE_OF_OPTION
, Value
));
2182 if ((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT
) == EFI_IFR_OPTION_DEFAULT
) {
2183 DefaultData
.DefaultId
= EFI_HII_DEFAULT_CLASS_STANDARD
;
2184 InsertDefaultValue (BlockData
, &DefaultData
);
2186 if ((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT_MFG
) == EFI_IFR_OPTION_DEFAULT_MFG
) {
2187 DefaultData
.DefaultId
= EFI_HII_DEFAULT_CLASS_MANUFACTURING
;
2188 InsertDefaultValue (BlockData
, &DefaultData
);
2193 // 2. Set as the default value when this is the first option.
2194 // The first oneof option value will be used as default value when no default value is specified.
2196 if (FirstOneOfOption
) {
2197 // This flag is used to specify whether this option is the first. Set it to FALSE for the following options.
2198 FirstOneOfOption
= FALSE
;
2201 // Prepare new DefaultValue
2203 DefaultData
.Type
= DefaultValueFromDefault
;
2204 CopyMem (&DefaultData
.Value
, &IfrOneOfOption
->Value
, IfrOneOfOption
->Header
.Length
- OFFSET_OF (EFI_IFR_ONE_OF_OPTION
, Value
));
2205 for (LinkData
= DefaultIdArray
->Entry
.ForwardLink
; LinkData
!= &DefaultIdArray
->Entry
; LinkData
= LinkData
->ForwardLink
) {
2206 DefaultDataPtr
= BASE_CR (LinkData
, IFR_DEFAULT_DATA
, Entry
);
2207 DefaultData
.DefaultId
= DefaultDataPtr
->DefaultId
;
2208 InsertDefaultValue (BlockData
, &DefaultData
);
2213 case EFI_IFR_DEFAULT_OP
:
2215 // Update Current BlockData to the default value.
2217 if (BlockData
== NULL
|| BlockData
->Scope
== 0) {
2219 // No matched block data is ignored.
2224 if (BlockData
->OpCode
== EFI_IFR_ORDERED_LIST_OP
) {
2226 // OrderedList Opcode is no default value.
2231 // Get the DefaultId
2233 IfrDefault
= (EFI_IFR_DEFAULT
*) IfrOpHdr
;
2234 VarDefaultId
= IfrDefault
->DefaultId
;
2236 // Prepare new DefaultValue
2238 DefaultData
.Type
= DefaultValueFromOpcode
;
2239 DefaultData
.DefaultId
= VarDefaultId
;
2240 CopyMem (&DefaultData
.Value
, &IfrDefault
->Value
, IfrDefault
->Header
.Length
- OFFSET_OF (EFI_IFR_DEFAULT
, Value
));
2242 // If the value field is expression, set the cleaned flag.
2243 if (IfrDefault
->Type
== EFI_IFR_TYPE_OTHER
) {
2244 DefaultData
.Cleaned
= TRUE
;
2247 // Add DefaultValue into current BlockData
2249 InsertDefaultValue (BlockData
, &DefaultData
);
2252 // After insert the default value, reset the cleaned value for next
2253 // time used. If not set here, need to set the value before everytime
2256 DefaultData
.Cleaned
= FALSE
;
2259 case EFI_IFR_END_OP
:
2261 // End Opcode is for Var question.
2263 if (BlockData
!= NULL
) {
2264 if (BlockData
->Scope
> 0) {
2267 if (BlockData
->Scope
== 0) {
2275 if (BlockData
!= NULL
) {
2276 if (BlockData
->Scope
> 0) {
2277 BlockData
->Scope
= (UINT8
) (BlockData
->Scope
+ IfrOpHdr
->Scope
);
2280 if (BlockData
->Scope
== 0) {
2287 IfrOffset
+= IfrOpHdr
->Length
;
2288 PackageOffset
+= IfrOpHdr
->Length
;
2292 for (LinkData
= VarStorageData
->BlockEntry
.ForwardLink
; LinkData
!= &VarStorageData
->BlockEntry
; LinkData
= LinkData
->ForwardLink
) {
2293 BlockData
= BASE_CR (LinkData
, IFR_BLOCK_DATA
, Entry
);
2294 for (LinkDefault
= BlockData
->DefaultValueEntry
.ForwardLink
; LinkDefault
!= &BlockData
->DefaultValueEntry
; ) {
2295 DefaultDataPtr
= BASE_CR (LinkDefault
, IFR_DEFAULT_DATA
, Entry
);
2296 LinkDefault
= LinkDefault
->ForwardLink
;
2297 if (DefaultDataPtr
->Cleaned
== TRUE
) {
2298 RemoveEntryList (&DefaultDataPtr
->Entry
);
2299 FreePool (DefaultDataPtr
);
2308 parse the configrequest string, get the elements.
2310 @param ConfigRequest The input configrequest string.
2311 @param Progress Return the progress data.
2313 @retval Block data pointer.
2317 IN EFI_STRING ConfigRequest
,
2318 OUT EFI_STRING
*Progress
2321 EFI_STRING StringPtr
;
2322 IFR_BLOCK_DATA
*BlockData
;
2323 IFR_BLOCK_DATA
*RequestBlockArray
;
2329 IFR_BLOCK_DATA
*NextBlockData
;
2333 // Init RequestBlockArray
2335 RequestBlockArray
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
2336 if (RequestBlockArray
== NULL
) {
2339 InitializeListHead (&RequestBlockArray
->Entry
);
2342 // Get the request Block array from the request string
2347 // Parse each <RequestElement> if exists
2348 // Only <BlockName> format is supported by this help function.
2349 // <BlockName> ::= &'OFFSET='<Number>&'WIDTH='<Number>
2351 StringPtr
= ConfigRequest
;
2352 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) == 0) {
2354 // Skip the OFFSET string
2356 *Progress
= StringPtr
;
2357 StringPtr
+= StrLen (L
"&OFFSET=");
2361 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
2362 if (EFI_ERROR (Status
)) {
2369 (((Length
+ 1) / 2) < sizeof (UINT16
)) ? ((Length
+ 1) / 2) : sizeof (UINT16
)
2371 FreePool (TmpBuffer
);
2373 StringPtr
+= Length
;
2374 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
2377 StringPtr
+= StrLen (L
"&WIDTH=");
2382 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
2383 if (EFI_ERROR (Status
)) {
2390 (((Length
+ 1) / 2) < sizeof (UINT16
)) ? ((Length
+ 1) / 2) : sizeof (UINT16
)
2392 FreePool (TmpBuffer
);
2394 StringPtr
+= Length
;
2395 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
2402 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
2403 if (BlockData
== NULL
) {
2406 BlockData
->Offset
= Offset
;
2407 BlockData
->Width
= Width
;
2408 InsertBlockData (&RequestBlockArray
->Entry
, &BlockData
);
2411 // Skip &VALUE string if &VALUE does exists.
2413 if (StrnCmp (StringPtr
, L
"&VALUE=", StrLen (L
"&VALUE=")) == 0) {
2414 StringPtr
+= StrLen (L
"&VALUE=");
2419 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
2420 if (EFI_ERROR (Status
)) {
2424 StringPtr
+= Length
;
2425 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
2430 // If '\0', parsing is finished.
2432 if (*StringPtr
== 0) {
2438 // Merge the requested block data.
2440 Link
= RequestBlockArray
->Entry
.ForwardLink
;
2441 while ((Link
!= &RequestBlockArray
->Entry
) && (Link
->ForwardLink
!= &RequestBlockArray
->Entry
)) {
2442 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
2443 NextBlockData
= BASE_CR (Link
->ForwardLink
, IFR_BLOCK_DATA
, Entry
);
2444 if ((NextBlockData
->Offset
>= BlockData
->Offset
) && (NextBlockData
->Offset
<= (BlockData
->Offset
+ BlockData
->Width
))) {
2445 if ((NextBlockData
->Offset
+ NextBlockData
->Width
) > (BlockData
->Offset
+ BlockData
->Width
)) {
2446 BlockData
->Width
= (UINT16
) (NextBlockData
->Offset
+ NextBlockData
->Width
- BlockData
->Offset
);
2448 RemoveEntryList (Link
->ForwardLink
);
2449 FreePool (NextBlockData
);
2452 Link
= Link
->ForwardLink
;
2455 return RequestBlockArray
;
2458 if (RequestBlockArray
!= NULL
) {
2460 // Free Link Array RequestBlockArray
2462 while (!IsListEmpty (&RequestBlockArray
->Entry
)) {
2463 BlockData
= BASE_CR (RequestBlockArray
->Entry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
2464 RemoveEntryList (&BlockData
->Entry
);
2465 FreePool (BlockData
);
2468 FreePool (RequestBlockArray
);
2475 parse the configrequest string, get the elements.
2477 @param ConfigRequest The input config request string.
2478 @param Progress Return the progress data.
2480 @retval return data block array.
2484 IN EFI_STRING ConfigRequest
,
2485 OUT EFI_STRING
*Progress
2488 EFI_STRING StringPtr
;
2490 IFR_BLOCK_DATA
*BlockData
;
2491 IFR_BLOCK_DATA
*RequestBlockArray
;
2494 StringPtr
= ConfigRequest
;
2497 // Init RequestBlockArray
2499 RequestBlockArray
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
2500 if (RequestBlockArray
== NULL
) {
2503 InitializeListHead (&RequestBlockArray
->Entry
);
2506 // Get the request Block array from the request string
2510 // Parse each <RequestElement> if exists
2511 // Only <BlockName> format is supported by this help function.
2512 // <BlockName> ::= &'Name***=***
2514 while (StringPtr
!= NULL
&& *StringPtr
== L
'&') {
2516 *Progress
= StringPtr
;
2518 // Skip the L"&" string
2523 if ((NextTag
= StrStr (StringPtr
, L
"=")) != NULL
) {
2526 } else if ((NextTag
= StrStr (StringPtr
, L
"&")) != NULL
) {
2533 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
2534 if (BlockData
== NULL
) {
2541 BlockData
->Name
= AllocateCopyPool(StrSize (StringPtr
), StringPtr
);
2542 InsertBlockData (&RequestBlockArray
->Entry
, &BlockData
);
2546 // If has value, skip the value.
2548 StringPtr
= NextTag
+ 1;
2550 StringPtr
= StrStr (StringPtr
, L
"&");
2551 } else if (NextTag
!= NULL
) {
2553 // restore the '&' text.
2555 StringPtr
= NextTag
;
2560 return RequestBlockArray
;
2563 if (RequestBlockArray
!= NULL
) {
2565 // Free Link Array RequestBlockArray
2567 while (!IsListEmpty (&RequestBlockArray
->Entry
)) {
2568 BlockData
= BASE_CR (RequestBlockArray
->Entry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
2569 RemoveEntryList (&BlockData
->Entry
);
2570 if (BlockData
->Name
!= NULL
) {
2571 FreePool (BlockData
->Name
);
2573 FreePool (BlockData
);
2576 FreePool (RequestBlockArray
);
2583 Generate ConfigRequest string base on the varstore info.
2585 @param ConfigHdr The config header for this varstore.
2586 @param VarStorageData The varstore info.
2587 @param Status Return Status.
2588 @param ConfigRequest The ConfigRequest info may be return.
2590 @retval TRUE Need to continue
2591 @retval Others NO need to continue or error occur.
2594 GenerateConfigRequest (
2595 IN CHAR16
*ConfigHdr
,
2596 IN IFR_VARSTORAGE_DATA
*VarStorageData
,
2597 OUT EFI_STATUS
*Status
,
2598 IN OUT EFI_STRING
*ConfigRequest
2604 CHAR16
*FullConfigRequest
;
2606 IFR_BLOCK_DATA
*BlockData
;
2609 // Append VarStorageData BlockEntry into *Request string
2610 // Now support only one varstore in a form package.
2614 // Go through all VarStorageData Entry and get BlockEntry for each one for the multiple varstore in a single form package
2615 // Then construct them all to return MultiRequest string : ConfigHdr BlockConfig
2619 // Compute the length of the entire request starting with <ConfigHdr> and a
2623 Length
= StrLen (ConfigHdr
) + 1;
2625 for (Link
= VarStorageData
->BlockEntry
.ForwardLink
; Link
!= &VarStorageData
->BlockEntry
; Link
= Link
->ForwardLink
) {
2627 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
2628 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2630 // Add <BlockName> length for each Name
2632 // <BlockName> ::= &Name1&Name2&...
2633 // |1| StrLen(Name1)
2635 Length
= Length
+ (1 + StrLen (BlockData
->Name
));
2638 // Add <BlockName> length for each Offset/Width pair
2640 // <BlockName> ::= &OFFSET=1234&WIDTH=1234
2641 // | 8 | 4 | 7 | 4 |
2643 Length
= Length
+ (8 + 4 + 7 + 4);
2647 // No any request block data is found. The request string can't be constructed.
2650 *Status
= EFI_SUCCESS
;
2655 // Allocate buffer for the entire <ConfigRequest>
2657 FullConfigRequest
= AllocateZeroPool (Length
* sizeof (CHAR16
));
2658 if (FullConfigRequest
== NULL
) {
2659 *Status
= EFI_OUT_OF_RESOURCES
;
2662 StringPtr
= FullConfigRequest
;
2665 // Start with <ConfigHdr>
2667 StrCpy (StringPtr
, ConfigHdr
);
2668 StringPtr
+= StrLen (StringPtr
);
2671 // Loop through all the Offset/Width pairs and append them to ConfigRequest
2673 for (Link
= VarStorageData
->BlockEntry
.ForwardLink
; Link
!= &VarStorageData
->BlockEntry
; Link
= Link
->ForwardLink
) {
2674 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
2675 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2681 (1 + StrLen (BlockData
->Name
) + 1) * sizeof (CHAR16
),
2687 // Append &OFFSET=XXXX&WIDTH=YYYY\0
2691 (8 + 4 + 7 + 4 + 1) * sizeof (CHAR16
),
2692 L
"&OFFSET=%04X&WIDTH=%04X",
2697 StringPtr
+= StrLen (StringPtr
);
2700 // Set to the got full request string.
2702 HiiToLower (FullConfigRequest
);
2704 if (*ConfigRequest
!= NULL
) {
2705 FreePool (*ConfigRequest
);
2707 *ConfigRequest
= FullConfigRequest
;
2713 Generate ConfigRequest Header base on the varstore info.
2715 @param VarStorageData The varstore info.
2716 @param DevicePath Device path for this varstore.
2717 @param ConfigHdr The config header for this varstore.
2719 @retval EFI_SUCCESS Generate the header success.
2720 @retval EFI_OUT_OF_RESOURCES Allocate buffer fail.
2724 IN IFR_VARSTORAGE_DATA
*VarStorageData
,
2725 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
2726 OUT EFI_STRING
*ConfigHdr
2735 Status
= EFI_SUCCESS
;
2741 // Construct <ConfigHdr> : "GUID=...&NAME=...&PATH=..." by VarStorageData Guid, Name and DriverHandle
2743 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*) &VarStorageData
->Guid
, 1, &GuidStr
);
2744 if (VarStorageData
->Name
!= NULL
) {
2745 GenerateSubStr (L
"NAME=", StrLen (VarStorageData
->Name
) * sizeof (CHAR16
), (VOID
*) VarStorageData
->Name
, 2, &NameStr
);
2747 GenerateSubStr (L
"NAME=", 0, NULL
, 2, &NameStr
);
2751 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) DevicePath
),
2752 (VOID
*) DevicePath
,
2756 Length
= StrLen (GuidStr
) + StrLen (NameStr
) + StrLen (PathStr
) + 1;
2757 if (VarStorageData
->Name
== NULL
) {
2761 *ConfigHdr
= AllocateZeroPool (Length
* sizeof (CHAR16
));
2762 if (*ConfigHdr
== NULL
) {
2763 Status
= EFI_OUT_OF_RESOURCES
;
2766 StrCpy (*ConfigHdr
, GuidStr
);
2767 StrCat (*ConfigHdr
, NameStr
);
2768 if (VarStorageData
->Name
== NULL
) {
2769 StrCat (*ConfigHdr
, L
"&");
2771 StrCat (*ConfigHdr
, PathStr
);
2774 // Remove the last character L'&'
2776 *(*ConfigHdr
+ StrLen (*ConfigHdr
) - 1) = L
'\0';
2779 if (GuidStr
!= NULL
) {
2783 if (NameStr
!= NULL
) {
2787 if (PathStr
!= NULL
) {
2795 Get Data buffer size based on data type.
2797 @param ValueType The input data type.
2799 @retval The data buffer size for the input type.
2806 UINT16 StorageWidth
;
2808 switch (ValueType
) {
2809 case EFI_IFR_NUMERIC_SIZE_1
:
2810 case EFI_IFR_TYPE_BOOLEAN
:
2811 StorageWidth
= (UINT16
) sizeof (UINT8
);
2814 case EFI_IFR_NUMERIC_SIZE_2
:
2815 StorageWidth
= (UINT16
) sizeof (UINT16
);
2818 case EFI_IFR_NUMERIC_SIZE_4
:
2819 StorageWidth
= (UINT16
) sizeof (UINT32
);
2822 case EFI_IFR_NUMERIC_SIZE_8
:
2823 StorageWidth
= (UINT16
) sizeof (UINT64
);
2826 case EFI_IFR_TYPE_TIME
:
2827 StorageWidth
= (UINT16
) sizeof (EFI_IFR_TIME
);
2830 case EFI_IFR_TYPE_DATE
:
2831 StorageWidth
= (UINT16
) sizeof (EFI_IFR_DATE
);
2839 return StorageWidth
;
2843 Generate ConfigAltResp string base on the varstore info.
2845 @param ConfigHdr The config header for this varstore.
2846 @param VarStorageData The varstore info.
2847 @param DefaultIdArray The Default id array.
2848 @param DefaultAltCfgResp The DefaultAltCfgResp info may be return.
2850 @retval TRUE Need to continue
2851 @retval Others NO need to continue or error occur.
2854 GenerateAltConfigResp (
2855 IN CHAR16
*ConfigHdr
,
2856 IN IFR_VARSTORAGE_DATA
*VarStorageData
,
2857 IN IFR_DEFAULT_DATA
*DefaultIdArray
,
2858 IN OUT EFI_STRING
*DefaultAltCfgResp
2864 LIST_ENTRY
*LinkData
;
2865 LIST_ENTRY
*LinkDefault
;
2866 LIST_ENTRY
*ListEntry
;
2868 IFR_BLOCK_DATA
*BlockData
;
2869 IFR_DEFAULT_DATA
*DefaultId
;
2870 IFR_DEFAULT_DATA
*DefaultValueData
;
2878 // Add length for <ConfigHdr> + '\0'
2880 Length
= StrLen (ConfigHdr
) + 1;
2882 for (Link
= DefaultIdArray
->Entry
.ForwardLink
; Link
!= &DefaultIdArray
->Entry
; Link
= Link
->ForwardLink
) {
2883 DefaultId
= BASE_CR (Link
, IFR_DEFAULT_DATA
, Entry
);
2885 // Add length for "&<ConfigHdr>&ALTCFG=XXXX"
2886 // |1| StrLen (ConfigHdr) | 8 | 4 |
2888 Length
+= (1 + StrLen (ConfigHdr
) + 8 + 4);
2890 for (LinkData
= VarStorageData
->BlockEntry
.ForwardLink
; LinkData
!= &VarStorageData
->BlockEntry
; LinkData
= LinkData
->ForwardLink
) {
2891 BlockData
= BASE_CR (LinkData
, IFR_BLOCK_DATA
, Entry
);
2892 ListEntry
= &BlockData
->DefaultValueEntry
;
2893 for (LinkDefault
= ListEntry
->ForwardLink
; LinkDefault
!= ListEntry
; LinkDefault
= LinkDefault
->ForwardLink
) {
2894 DefaultValueData
= BASE_CR (LinkDefault
, IFR_DEFAULT_DATA
, Entry
);
2895 if (DefaultValueData
->DefaultId
!= DefaultId
->DefaultId
) {
2898 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2900 // Add length for "&Name1=zzzzzzzzzzzz"
2903 Length
+= (1 + StrLen (BlockData
->Name
) + 1 + BlockData
->Width
* 2);
2906 // Add length for "&OFFSET=XXXX&WIDTH=YYYY&VALUE=zzzzzzzzzzzz"
2907 // | 8 | 4 | 7 | 4 | 7 | Width * 2 |
2909 Length
+= (8 + 4 + 7 + 4 + 7 + BlockData
->Width
* 2);
2917 // No default value is found. The default string doesn't exist.
2924 // Allocate buffer for the entire <DefaultAltCfgResp>
2926 *DefaultAltCfgResp
= AllocateZeroPool (Length
* sizeof (CHAR16
));
2927 if (*DefaultAltCfgResp
== NULL
) {
2928 return EFI_OUT_OF_RESOURCES
;
2930 StringPtr
= *DefaultAltCfgResp
;
2933 // Start with <ConfigHdr>
2935 StrCpy (StringPtr
, ConfigHdr
);
2936 StringPtr
+= StrLen (StringPtr
);
2938 for (Link
= DefaultIdArray
->Entry
.ForwardLink
; Link
!= &DefaultIdArray
->Entry
; Link
= Link
->ForwardLink
) {
2939 DefaultId
= BASE_CR (Link
, IFR_DEFAULT_DATA
, Entry
);
2941 // Add <AltConfigHdr> of the form "&<ConfigHdr>&ALTCFG=XXXX\0"
2942 // |1| StrLen (ConfigHdr) | 8 | 4 |
2946 (1 + StrLen (ConfigHdr
) + 8 + 4 + 1) * sizeof (CHAR16
),
2949 DefaultId
->DefaultId
2951 StringPtr
+= StrLen (StringPtr
);
2953 for (LinkData
= VarStorageData
->BlockEntry
.ForwardLink
; LinkData
!= &VarStorageData
->BlockEntry
; LinkData
= LinkData
->ForwardLink
) {
2954 BlockData
= BASE_CR (LinkData
, IFR_BLOCK_DATA
, Entry
);
2955 ListEntry
= &BlockData
->DefaultValueEntry
;
2956 for (LinkDefault
= ListEntry
->ForwardLink
; LinkDefault
!= ListEntry
; LinkDefault
= LinkDefault
->ForwardLink
) {
2957 DefaultValueData
= BASE_CR (LinkDefault
, IFR_DEFAULT_DATA
, Entry
);
2958 if (DefaultValueData
->DefaultId
!= DefaultId
->DefaultId
) {
2961 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2964 (1 + StrLen (ConfigHdr
) + 1) * sizeof (CHAR16
),
2968 StringPtr
+= StrLen (StringPtr
);
2971 // Add <BlockConfig>
2972 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>
2976 (8 + 4 + 7 + 4 + 7 + 1) * sizeof (CHAR16
),
2977 L
"&OFFSET=%04X&WIDTH=%04X&VALUE=",
2981 StringPtr
+= StrLen (StringPtr
);
2983 Width
= BlockData
->Width
;
2985 // Convert Value to a hex string in "%x" format
2986 // NOTE: This is in the opposite byte that GUID and PATH use
2988 TmpBuffer
= (UINT8
*) &(DefaultValueData
->Value
);
2989 for (; Width
> 0; Width
--) {
2990 StringPtr
+= UnicodeValueToString (StringPtr
, PREFIX_ZERO
| RADIX_HEX
, TmpBuffer
[Width
- 1], 2);
2996 HiiToLower (*DefaultAltCfgResp
);
3002 This function gets the full request string and full default value string by
3003 parsing IFR data in HII form packages.
3005 When Request points to NULL string, the request string and default value string
3006 for each varstore in form package will return.
3008 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
3009 @param DevicePath Device Path which Hii Config Access Protocol is registered.
3010 @param Request Pointer to a null-terminated Unicode string in
3011 <ConfigRequest> format. When it doesn't contain
3012 any RequestElement, it will be updated to return
3013 the full RequestElement retrieved from IFR data.
3014 If it points to NULL, the request string for the first
3015 varstore in form package will be merged into a
3016 <MultiConfigRequest> format string and return.
3017 @param AltCfgResp Pointer to a null-terminated Unicode string in
3018 <ConfigAltResp> format. When the pointer is to NULL,
3019 the full default value string retrieved from IFR data
3020 will return. When the pinter is to a string, the
3021 full default value string retrieved from IFR data
3022 will be merged into the input string and return.
3023 When Request points to NULL, the default value string
3024 for each varstore in form package will be merged into
3025 a <MultiConfigAltResp> format string and return.
3026 @param PointerProgress Optional parameter, it can be be NULL.
3027 When it is not NULL, if Request is NULL, it returns NULL.
3028 On return, points to a character in the Request
3029 string. Points to the string's null terminator if
3030 request was successful. Points to the most recent
3031 & before the first failing name / value pair (or
3032 the beginning of the string if the failure is in
3033 the first name / value pair) if the request was
3035 @retval EFI_SUCCESS The Results string is set to the full request string.
3036 And AltCfgResp contains all default value string.
3037 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
3038 @retval EFI_NOT_FOUND The varstore (Guid and Name) in Request string
3039 can't be found in Form package.
3040 @retval EFI_NOT_FOUND HiiPackage can't be got on the input HiiHandle.
3041 @retval EFI_INVALID_PARAMETER Request points to NULL.
3046 GetFullStringFromHiiFormPackages (
3047 IN HII_DATABASE_RECORD
*DataBaseRecord
,
3048 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
3049 IN OUT EFI_STRING
*Request
,
3050 IN OUT EFI_STRING
*AltCfgResp
,
3051 OUT EFI_STRING
*PointerProgress OPTIONAL
3055 UINT8
*HiiFormPackage
;
3057 IFR_BLOCK_DATA
*RequestBlockArray
;
3058 IFR_BLOCK_DATA
*BlockData
;
3059 IFR_DEFAULT_DATA
*DefaultValueData
;
3060 IFR_DEFAULT_DATA
*DefaultId
;
3061 IFR_DEFAULT_DATA
*DefaultIdArray
;
3062 IFR_VARSTORAGE_DATA
*VarStorageData
;
3063 EFI_STRING DefaultAltCfgResp
;
3064 EFI_STRING ConfigHdr
;
3065 EFI_STRING StringPtr
;
3066 EFI_STRING Progress
;
3068 if (DataBaseRecord
== NULL
|| DevicePath
== NULL
|| Request
== NULL
|| AltCfgResp
== NULL
) {
3069 return EFI_INVALID_PARAMETER
;
3073 // Initialize the local variables.
3075 RequestBlockArray
= NULL
;
3076 DefaultIdArray
= NULL
;
3077 VarStorageData
= NULL
;
3078 DefaultAltCfgResp
= NULL
;
3080 HiiFormPackage
= NULL
;
3082 Progress
= *Request
;
3084 Status
= GetFormPackageData (DataBaseRecord
, &HiiFormPackage
, &PackageSize
);
3085 if (EFI_ERROR (Status
)) {
3090 // 1. Get the request block array by Request String when Request string containts the block array.
3093 if (*Request
!= NULL
) {
3094 StringPtr
= *Request
;
3098 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
3099 Status
= EFI_INVALID_PARAMETER
;
3102 StringPtr
+= StrLen (L
"GUID=");
3103 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&NAME=", StrLen (L
"&NAME=")) != 0) {
3106 if (*StringPtr
== L
'\0') {
3107 Status
= EFI_INVALID_PARAMETER
;
3110 StringPtr
+= StrLen (L
"&NAME=");
3111 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&PATH=", StrLen (L
"&PATH=")) != 0) {
3114 if (*StringPtr
== L
'\0') {
3115 Status
= EFI_INVALID_PARAMETER
;
3118 StringPtr
+= StrLen (L
"&PATH=");
3119 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
3123 if (*StringPtr
== L
'\0') {
3125 // No request block is found.
3132 // If StringPtr != NULL, get the request elements.
3134 if (StringPtr
!= NULL
) {
3135 if (StrStr (StringPtr
, L
"&OFFSET=") != NULL
) {
3136 RequestBlockArray
= GetBlockElement(StringPtr
, &Progress
);
3138 RequestBlockArray
= GetNameElement(StringPtr
, &Progress
);
3141 if (RequestBlockArray
== NULL
) {
3142 Status
= EFI_INVALID_PARAMETER
;
3148 // Initialize DefaultIdArray to store the map between DeaultId and DefaultName
3150 DefaultIdArray
= (IFR_DEFAULT_DATA
*) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
3151 if (DefaultIdArray
== NULL
) {
3152 Status
= EFI_OUT_OF_RESOURCES
;
3155 InitializeListHead (&DefaultIdArray
->Entry
);
3158 // Initialize VarStorageData to store the var store Block and Default value information.
3160 VarStorageData
= (IFR_VARSTORAGE_DATA
*) AllocateZeroPool (sizeof (IFR_VARSTORAGE_DATA
));
3161 if (VarStorageData
== NULL
) {
3162 Status
= EFI_OUT_OF_RESOURCES
;
3165 InitializeListHead (&VarStorageData
->Entry
);
3166 InitializeListHead (&VarStorageData
->BlockEntry
);
3169 // 2. Parse FormPackage to get BlockArray and DefaultId Array for the request BlockArray.
3173 // Parse the opcode in form pacakge to get the default setting.
3175 Status
= ParseIfrData (DataBaseRecord
->Handle
,
3177 (UINT32
) PackageSize
,
3182 if (EFI_ERROR (Status
)) {
3187 // No requested varstore in IFR data and directly return
3189 if (VarStorageData
->Type
== 0 && VarStorageData
->Name
== NULL
) {
3190 Status
= EFI_SUCCESS
;
3195 // 3. Construct Request Element (Block Name) for 2.1 and 2.2 case.
3197 Status
= GenerateHdr (VarStorageData
, DevicePath
, &ConfigHdr
);
3198 if (EFI_ERROR (Status
)) {
3202 if (RequestBlockArray
== NULL
) {
3203 if (!GenerateConfigRequest(ConfigHdr
, VarStorageData
, &Status
, Request
)) {
3209 // 4. Construct Default Value string in AltResp according to request element.
3210 // Go through all VarStorageData Entry and get the DefaultId array for each one
3211 // Then construct them all to : ConfigHdr AltConfigHdr ConfigBody AltConfigHdr ConfigBody
3213 Status
= GenerateAltConfigResp (ConfigHdr
, VarStorageData
, DefaultIdArray
, &DefaultAltCfgResp
);
3214 if (EFI_ERROR (Status
)) {
3219 // 5. Merge string into the input AltCfgResp if the iput *AltCfgResp is not NULL.
3221 if (*AltCfgResp
!= NULL
&& DefaultAltCfgResp
!= NULL
) {
3222 Status
= MergeDefaultString (AltCfgResp
, DefaultAltCfgResp
);
3223 FreePool (DefaultAltCfgResp
);
3224 } else if (*AltCfgResp
== NULL
) {
3225 *AltCfgResp
= DefaultAltCfgResp
;
3229 if (RequestBlockArray
!= NULL
) {
3231 // Free Link Array RequestBlockArray
3233 while (!IsListEmpty (&RequestBlockArray
->Entry
)) {
3234 BlockData
= BASE_CR (RequestBlockArray
->Entry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
3235 RemoveEntryList (&BlockData
->Entry
);
3236 if (BlockData
->Name
!= NULL
) {
3237 FreePool (BlockData
->Name
);
3239 FreePool (BlockData
);
3242 FreePool (RequestBlockArray
);
3245 if (VarStorageData
!= NULL
) {
3247 // Free link array VarStorageData
3249 while (!IsListEmpty (&VarStorageData
->BlockEntry
)) {
3250 BlockData
= BASE_CR (VarStorageData
->BlockEntry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
3251 RemoveEntryList (&BlockData
->Entry
);
3252 if (BlockData
->Name
!= NULL
) {
3253 FreePool (BlockData
->Name
);
3256 // Free default value link array
3258 while (!IsListEmpty (&BlockData
->DefaultValueEntry
)) {
3259 DefaultValueData
= BASE_CR (BlockData
->DefaultValueEntry
.ForwardLink
, IFR_DEFAULT_DATA
, Entry
);
3260 RemoveEntryList (&DefaultValueData
->Entry
);
3261 FreePool (DefaultValueData
);
3263 FreePool (BlockData
);
3265 FreePool (VarStorageData
);
3268 if (DefaultIdArray
!= NULL
) {
3270 // Free DefaultId Array
3272 while (!IsListEmpty (&DefaultIdArray
->Entry
)) {
3273 DefaultId
= BASE_CR (DefaultIdArray
->Entry
.ForwardLink
, IFR_DEFAULT_DATA
, Entry
);
3274 RemoveEntryList (&DefaultId
->Entry
);
3275 FreePool (DefaultId
);
3277 FreePool (DefaultIdArray
);
3281 // Free the allocated string
3283 if (ConfigHdr
!= NULL
) {
3284 FreePool (ConfigHdr
);
3288 // Free Pacakge data
3290 if (HiiFormPackage
!= NULL
) {
3291 FreePool (HiiFormPackage
);
3294 if (PointerProgress
!= NULL
) {
3295 if (*Request
== NULL
) {
3296 *PointerProgress
= NULL
;
3297 } else if (EFI_ERROR (Status
)) {
3298 *PointerProgress
= *Request
;
3300 *PointerProgress
= *Request
+ StrLen (*Request
);
3308 This function gets the full request resp string by
3309 parsing IFR data in HII form packages.
3311 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
3313 @param EfiVarStoreInfo The efi varstore info which is save in the EFI
3314 varstore data structure.
3315 @param Request Pointer to a null-terminated Unicode string in
3316 <ConfigRequest> format.
3317 @param RequestResp Pointer to a null-terminated Unicode string in
3318 <ConfigResp> format.
3319 @param AccessProgress On return, points to a character in the Request
3320 string. Points to the string's null terminator if
3321 request was successful. Points to the most recent
3322 & before the first failing name / value pair (or
3323 the beginning of the string if the failure is in
3324 the first name / value pair) if the request was
3327 @retval EFI_SUCCESS The Results string is set to the full request string.
3328 And AltCfgResp contains all default value string.
3329 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
3330 @retval EFI_INVALID_PARAMETER Request points to NULL.
3334 GetConfigRespFromEfiVarStore (
3335 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
3336 IN EFI_IFR_VARSTORE_EFI
*EfiVarStoreInfo
,
3337 IN EFI_STRING Request
,
3338 OUT EFI_STRING
*RequestResp
,
3339 OUT EFI_STRING
*AccessProgress
3343 EFI_STRING VarStoreName
;
3347 Status
= EFI_SUCCESS
;
3350 VarStoreName
= NULL
;
3351 *AccessProgress
= Request
;
3353 VarStoreName
= AllocateZeroPool (AsciiStrSize ((CHAR8
*)EfiVarStoreInfo
->Name
) * sizeof (CHAR16
));
3354 if (VarStoreName
== NULL
) {
3355 Status
= EFI_OUT_OF_RESOURCES
;
3358 AsciiStrToUnicodeStr ((CHAR8
*) EfiVarStoreInfo
->Name
, VarStoreName
);
3361 Status
= gRT
->GetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, NULL
, &BufferSize
, NULL
);
3362 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
3366 VarStore
= AllocateZeroPool (BufferSize
);
3367 ASSERT (VarStore
!= NULL
);
3368 Status
= gRT
->GetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, NULL
, &BufferSize
, VarStore
);
3369 if (EFI_ERROR (Status
)) {
3373 Status
= HiiBlockToConfig(This
, Request
, VarStore
, BufferSize
, RequestResp
, AccessProgress
);
3374 if (EFI_ERROR (Status
)) {
3379 if (VarStoreName
!= NULL
) {
3380 FreePool (VarStoreName
);
3383 if (VarStore
!= NULL
) {
3384 FreePool (VarStore
);
3392 This function route the full request resp string for efi varstore.
3394 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
3396 @param EfiVarStoreInfo The efi varstore info which is save in the EFI
3397 varstore data structure.
3398 @param RequestResp Pointer to a null-terminated Unicode string in
3399 <ConfigResp> format.
3400 @param Result Pointer to a null-terminated Unicode string in
3401 <ConfigResp> format.
3403 @retval EFI_SUCCESS The Results string is set to the full request string.
3404 And AltCfgResp contains all default value string.
3405 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
3406 @retval EFI_INVALID_PARAMETER Request points to NULL.
3410 RouteConfigRespForEfiVarStore (
3411 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
3412 IN EFI_IFR_VARSTORE_EFI
*EfiVarStoreInfo
,
3413 IN EFI_STRING RequestResp
,
3414 OUT EFI_STRING
*Result
3418 EFI_STRING VarStoreName
;
3423 Status
= EFI_SUCCESS
;
3426 VarStoreName
= NULL
;
3428 VarStoreName
= AllocateZeroPool (AsciiStrSize ((CHAR8
*)EfiVarStoreInfo
->Name
) * sizeof (CHAR16
));
3429 if (VarStoreName
== NULL
) {
3430 Status
= EFI_OUT_OF_RESOURCES
;
3433 AsciiStrToUnicodeStr ((CHAR8
*) EfiVarStoreInfo
->Name
, VarStoreName
);
3435 Status
= gRT
->GetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, NULL
, &BufferSize
, NULL
);
3436 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
3440 BlockSize
= BufferSize
;
3441 VarStore
= AllocateZeroPool (BufferSize
);
3442 ASSERT (VarStore
!= NULL
);
3443 Status
= gRT
->GetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, NULL
, &BufferSize
, VarStore
);
3444 if (EFI_ERROR (Status
)) {
3448 Status
= HiiConfigToBlock(This
, RequestResp
, VarStore
, &BlockSize
, Result
);
3449 if (EFI_ERROR (Status
)) {
3453 Status
= gRT
->SetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, EfiVarStoreInfo
->Attributes
, BufferSize
, VarStore
);
3454 if (EFI_ERROR (Status
)) {
3459 if (VarStoreName
!= NULL
) {
3460 FreePool (VarStoreName
);
3463 if (VarStore
!= NULL
) {
3464 FreePool (VarStore
);
3471 Validate the config request elements.
3473 @param ConfigElements A null-terminated Unicode string in <ConfigRequest> format,
3474 without configHdr field.
3476 @retval CHAR16 * THE first Name/value pair not correct.
3477 @retval NULL Success parse the name/value pair
3480 OffsetWidthValidate (
3481 CHAR16
*ConfigElements
3487 StringPtr
= ConfigElements
;
3491 if (StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) != 0) {
3495 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
3498 if (*StringPtr
== L
'\0') {
3502 StringPtr
+= StrLen (L
"&WIDTH=");
3503 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) != 0) {
3507 if (*StringPtr
== L
'\0') {
3514 Validate the config request elements.
3516 @param ConfigElements A null-terminated Unicode string in <ConfigRequest> format,
3517 without configHdr field.
3519 @retval CHAR16 * THE first Name/value pair not correct.
3520 @retval NULL Success parse the name/value pair
3525 CHAR16
*ConfigElements
3531 StringPtr
= ConfigElements
;
3535 if (*StringPtr
!= L
'&') {
3540 StringPtr
= StrStr (StringPtr
, L
"&");
3542 if (StringPtr
== NULL
) {
3549 Validate the config request string.
3551 @param ConfigRequest A null-terminated Unicode string in <ConfigRequest> format.
3553 @retval CHAR16 * THE first element not correct.
3554 @retval NULL Success parse the name/value pair
3558 ConfigRequestValidate (
3559 CHAR16
*ConfigRequest
3562 BOOLEAN HasNameField
;
3565 HasNameField
= TRUE
;
3566 StringPtr
= ConfigRequest
;
3569 // Check <ConfigHdr>
3571 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
3572 return ConfigRequest
;
3574 StringPtr
+= StrLen (L
"GUID=");
3575 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&NAME=", StrLen (L
"&NAME=")) != 0) {
3578 if (*StringPtr
== L
'\0') {
3579 return ConfigRequest
;
3581 StringPtr
+= StrLen (L
"&NAME=");
3582 if (*StringPtr
== L
'&') {
3583 HasNameField
= FALSE
;
3585 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&PATH=", StrLen (L
"&PATH=")) != 0) {
3588 if (*StringPtr
== L
'\0') {
3589 return ConfigRequest
;
3591 StringPtr
+= StrLen (L
"&PATH=");
3592 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
3596 if (*StringPtr
== L
'\0') {
3602 // Should be Buffer varstore, config request should be "OFFSET/Width" pairs.
3604 return OffsetWidthValidate(StringPtr
);
3607 // Should be Name/Value varstore, config request should be "&name1&name2..." pairs.
3609 return NameValueValidate(StringPtr
);
3614 This function allows a caller to extract the current configuration
3615 for one or more named elements from one or more drivers.
3617 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
3619 @param Request A null-terminated Unicode string in
3620 <MultiConfigRequest> format.
3621 @param Progress On return, points to a character in the Request
3622 string. Points to the string's null terminator if
3623 request was successful. Points to the most recent
3624 & before the first failing name / value pair (or
3625 the beginning of the string if the failure is in
3626 the first name / value pair) if the request was
3628 @param Results Null-terminated Unicode string in
3629 <MultiConfigAltResp> format which has all values
3630 filled in for the names in the Request string.
3631 String to be allocated by the called function.
3633 @retval EFI_SUCCESS The Results string is filled with the values
3634 corresponding to all requested names.
3635 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
3636 results that must be stored awaiting possible
3638 @retval EFI_NOT_FOUND Routing data doesn't match any known driver.
3639 Progress set to the "G" in "GUID" of the routing
3640 header that doesn't match. Note: There is no
3641 requirement that all routing data be validated
3642 before any configuration extraction.
3643 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Request
3644 parameter would result in this type of error. The
3645 Progress parameter is set to NULL.
3646 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set to most recent &
3647 before the error or the beginning of the string.
3648 @retval EFI_INVALID_PARAMETER The ExtractConfig function of the underlying HII
3649 Configuration Access Protocol returned
3650 EFI_INVALID_PARAMETER. Progress set to most recent
3651 & before the error or the beginning of the string.
3656 HiiConfigRoutingExtractConfig (
3657 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
3658 IN CONST EFI_STRING Request
,
3659 OUT EFI_STRING
*Progress
,
3660 OUT EFI_STRING
*Results
3663 HII_DATABASE_PRIVATE_DATA
*Private
;
3664 EFI_STRING StringPtr
;
3665 EFI_STRING ConfigRequest
;
3667 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
3668 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
3671 HII_DATABASE_RECORD
*Database
;
3672 UINT8
*DevicePathPkg
;
3673 UINT8
*CurrentDevicePath
;
3674 EFI_HANDLE DriverHandle
;
3675 EFI_HII_HANDLE HiiHandle
;
3676 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
3677 EFI_STRING AccessProgress
;
3678 EFI_STRING AccessResults
;
3679 EFI_STRING DefaultResults
;
3680 BOOLEAN FirstElement
;
3681 BOOLEAN IfrDataParsedFlag
;
3682 BOOLEAN IsEfiVarStore
;
3683 EFI_IFR_VARSTORE_EFI
*EfiVarStoreInfo
;
3684 EFI_STRING ErrorPtr
;
3685 UINTN DevicePathSize
;
3687 if (This
== NULL
|| Progress
== NULL
|| Results
== NULL
) {
3688 return EFI_INVALID_PARAMETER
;
3691 if (Request
== NULL
) {
3693 return EFI_INVALID_PARAMETER
;
3696 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
3697 StringPtr
= Request
;
3698 *Progress
= StringPtr
;
3699 DefaultResults
= NULL
;
3700 ConfigRequest
= NULL
;
3701 Status
= EFI_SUCCESS
;
3702 AccessResults
= NULL
;
3703 AccessProgress
= NULL
;
3705 IfrDataParsedFlag
= FALSE
;
3706 IsEfiVarStore
= FALSE
;
3707 EfiVarStoreInfo
= NULL
;
3710 // The first element of <MultiConfigRequest> should be
3711 // <GuidHdr>, which is in 'GUID='<Guid> syntax.
3713 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
3714 return EFI_INVALID_PARAMETER
;
3717 FirstElement
= TRUE
;
3720 // Allocate a fix length of memory to store Results. Reallocate memory for
3721 // Results if this fix length is insufficient.
3723 *Results
= (EFI_STRING
) AllocateZeroPool (MAX_STRING_LENGTH
);
3724 if (*Results
== NULL
) {
3725 return EFI_OUT_OF_RESOURCES
;
3728 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) == 0) {
3730 // If parsing error, set Progress to the beginning of the <MultiConfigRequest>
3731 // or most recent & before the error.
3733 if (StringPtr
== Request
) {
3734 *Progress
= StringPtr
;
3736 *Progress
= StringPtr
- 1;
3740 // Process each <ConfigRequest> of <MultiConfigRequest>
3742 Length
= CalculateConfigStringLen (StringPtr
);
3743 ConfigRequest
= AllocateCopyPool ((Length
+ 1) * sizeof (CHAR16
), StringPtr
);
3744 if (ConfigRequest
== NULL
) {
3745 Status
= EFI_OUT_OF_RESOURCES
;
3748 *(ConfigRequest
+ Length
) = 0;
3751 // Get the UEFI device path
3753 Status
= GetDevicePath (ConfigRequest
, (UINT8
**) &DevicePath
);
3754 if (EFI_ERROR (Status
)) {
3759 // Find driver which matches the routing data.
3761 DriverHandle
= NULL
;
3764 for (Link
= Private
->DatabaseList
.ForwardLink
;
3765 Link
!= &Private
->DatabaseList
;
3766 Link
= Link
->ForwardLink
3768 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
3769 if ((DevicePathPkg
= Database
->PackageList
->DevicePathPkg
) != NULL
) {
3770 CurrentDevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
3771 DevicePathSize
= GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) CurrentDevicePath
);
3772 if ((CompareMem (DevicePath
,CurrentDevicePath
,DevicePathSize
) == 0) && IsThisPackageList(Database
, ConfigRequest
)) {
3773 DriverHandle
= Database
->DriverHandle
;
3774 HiiHandle
= Database
->Handle
;
3781 // Try to find driver handle by device path.
3783 if (DriverHandle
== NULL
) {
3784 TempDevicePath
= DevicePath
;
3785 Status
= gBS
->LocateDevicePath (
3786 &gEfiDevicePathProtocolGuid
,
3790 if (EFI_ERROR (Status
) || (DriverHandle
== NULL
)) {
3792 // Routing data does not match any known driver.
3793 // Set Progress to the 'G' in "GUID" of the routing header.
3795 *Progress
= StringPtr
;
3796 Status
= EFI_NOT_FOUND
;
3802 // Validate ConfigRequest String.
3804 ErrorPtr
= ConfigRequestValidate(ConfigRequest
);
3805 if (ErrorPtr
!= NULL
) {
3806 *Progress
= StrStr (StringPtr
, ErrorPtr
);
3807 Status
= EFI_INVALID_PARAMETER
;
3812 // Check whether ConfigRequest contains request string.
3814 IfrDataParsedFlag
= FALSE
;
3815 if ((HiiHandle
!= NULL
) && !GetElementsFromRequest(ConfigRequest
)) {
3817 // Get the full request string from IFR when HiiPackage is registered to HiiHandle
3819 IfrDataParsedFlag
= TRUE
;
3820 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &ConfigRequest
, &DefaultResults
, &AccessProgress
);
3821 if (EFI_ERROR (Status
)) {
3823 // AccessProgress indicates the parsing progress on <ConfigRequest>.
3824 // Map it to the progress on <MultiConfigRequest> then return it.
3826 ASSERT (AccessProgress
!= NULL
);
3827 *Progress
= StrStr (StringPtr
, AccessProgress
);
3831 // Not any request block is found.
3833 if (!GetElementsFromRequest(ConfigRequest
)) {
3834 AccessResults
= AllocateCopyPool (StrSize (ConfigRequest
), ConfigRequest
);
3835 goto NextConfigString
;
3840 // Check whether this ConfigRequest is search from Efi varstore type storage.
3842 Status
= GetVarStoreType(Database
, ConfigRequest
, &IsEfiVarStore
, &EfiVarStoreInfo
);
3843 if (EFI_ERROR (Status
)) {
3847 if (IsEfiVarStore
) {
3849 // Call the GetVariable function to extract settings.
3851 Status
= GetConfigRespFromEfiVarStore(This
, EfiVarStoreInfo
, ConfigRequest
, &AccessResults
, &AccessProgress
);
3852 FreePool (EfiVarStoreInfo
);
3855 // Call corresponding ConfigAccess protocol to extract settings
3857 Status
= gBS
->HandleProtocol (
3859 &gEfiHiiConfigAccessProtocolGuid
,
3860 (VOID
**) &ConfigAccess
3862 ASSERT_EFI_ERROR (Status
);
3864 Status
= ConfigAccess
->ExtractConfig (
3871 if (EFI_ERROR (Status
)) {
3873 // AccessProgress indicates the parsing progress on <ConfigRequest>.
3874 // Map it to the progress on <MultiConfigRequest> then return it.
3876 *Progress
= StrStr (StringPtr
, AccessProgress
);
3881 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'
3882 // which seperates the first <ConfigAltResp> and the following ones.
3884 ASSERT (*AccessProgress
== 0);
3887 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
3889 if (!IfrDataParsedFlag
&& HiiHandle
!= NULL
) {
3890 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &ConfigRequest
, &DefaultResults
, NULL
);
3891 ASSERT_EFI_ERROR (Status
);
3894 FreePool (DevicePath
);
3897 if (DefaultResults
!= NULL
) {
3898 Status
= MergeDefaultString (&AccessResults
, DefaultResults
);
3899 ASSERT_EFI_ERROR (Status
);
3900 FreePool (DefaultResults
);
3901 DefaultResults
= NULL
;
3905 if (!FirstElement
) {
3906 Status
= AppendToMultiString (Results
, L
"&");
3907 ASSERT_EFI_ERROR (Status
);
3910 Status
= AppendToMultiString (Results
, AccessResults
);
3911 ASSERT_EFI_ERROR (Status
);
3913 FirstElement
= FALSE
;
3915 FreePool (AccessResults
);
3916 AccessResults
= NULL
;
3917 FreePool (ConfigRequest
);
3918 ConfigRequest
= NULL
;
3921 // Go to next <ConfigRequest> (skip '&').
3923 StringPtr
+= Length
;
3924 if (*StringPtr
== 0) {
3925 *Progress
= StringPtr
;
3933 if (EFI_ERROR (Status
)) {
3934 FreePool (*Results
);
3938 if (ConfigRequest
!= NULL
) {
3939 FreePool (ConfigRequest
);
3942 if (AccessResults
!= NULL
) {
3943 FreePool (AccessResults
);
3946 if (DefaultResults
!= NULL
) {
3947 FreePool (DefaultResults
);
3950 if (DevicePath
!= NULL
) {
3951 FreePool (DevicePath
);
3959 This function allows the caller to request the current configuration for the
3960 entirety of the current HII database and returns the data in a
3961 null-terminated Unicode string.
3963 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
3965 @param Results Null-terminated Unicode string in
3966 <MultiConfigAltResp> format which has all values
3967 filled in for the entirety of the current HII
3968 database. String to be allocated by the called
3969 function. De-allocation is up to the caller.
3971 @retval EFI_SUCCESS The Results string is filled with the values
3972 corresponding to all requested names.
3973 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
3974 results that must be stored awaiting possible
3976 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Results
3977 parameter would result in this type of error.
3982 HiiConfigRoutingExportConfig (
3983 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
3984 OUT EFI_STRING
*Results
3988 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
3989 EFI_STRING AccessResults
;
3990 EFI_STRING Progress
;
3991 EFI_STRING StringPtr
;
3992 EFI_STRING ConfigRequest
;
3994 EFI_HANDLE
*ConfigAccessHandles
;
3995 UINTN NumberConfigAccessHandles
;
3996 BOOLEAN FirstElement
;
3997 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
3998 EFI_HII_HANDLE HiiHandle
;
3999 EFI_STRING DefaultResults
;
4000 HII_DATABASE_PRIVATE_DATA
*Private
;
4002 HII_DATABASE_RECORD
*Database
;
4003 UINT8
*DevicePathPkg
;
4004 UINT8
*CurrentDevicePath
;
4005 BOOLEAN IfrDataParsedFlag
;
4007 if (This
== NULL
|| Results
== NULL
) {
4008 return EFI_INVALID_PARAMETER
;
4011 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
4014 // Allocate a fix length of memory to store Results. Reallocate memory for
4015 // Results if this fix length is insufficient.
4017 *Results
= (EFI_STRING
) AllocateZeroPool (MAX_STRING_LENGTH
);
4018 if (*Results
== NULL
) {
4019 return EFI_OUT_OF_RESOURCES
;
4022 NumberConfigAccessHandles
= 0;
4023 Status
= gBS
->LocateHandleBuffer (
4025 &gEfiHiiConfigAccessProtocolGuid
,
4027 &NumberConfigAccessHandles
,
4028 &ConfigAccessHandles
4030 if (EFI_ERROR (Status
)) {
4034 FirstElement
= TRUE
;
4036 for (Index
= 0; Index
< NumberConfigAccessHandles
; Index
++) {
4037 Status
= gBS
->HandleProtocol (
4038 ConfigAccessHandles
[Index
],
4039 &gEfiHiiConfigAccessProtocolGuid
,
4040 (VOID
**) &ConfigAccess
4042 if (EFI_ERROR (Status
)) {
4047 // Get DevicePath and HiiHandle for this ConfigAccess driver handle
4049 IfrDataParsedFlag
= FALSE
;
4052 DefaultResults
= NULL
;
4054 ConfigRequest
= NULL
;
4055 DevicePath
= DevicePathFromHandle (ConfigAccessHandles
[Index
]);
4056 if (DevicePath
!= NULL
) {
4057 for (Link
= Private
->DatabaseList
.ForwardLink
;
4058 Link
!= &Private
->DatabaseList
;
4059 Link
= Link
->ForwardLink
4061 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
4062 if ((DevicePathPkg
= Database
->PackageList
->DevicePathPkg
) != NULL
) {
4063 CurrentDevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
4067 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) CurrentDevicePath
)
4069 HiiHandle
= Database
->Handle
;
4076 Status
= ConfigAccess
->ExtractConfig (
4082 if (EFI_ERROR (Status
)) {
4084 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
4086 if (HiiHandle
!= NULL
&& DevicePath
!= NULL
) {
4087 IfrDataParsedFlag
= TRUE
;
4088 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &ConfigRequest
, &DefaultResults
, NULL
);
4090 // Get the full request string to get the Current setting again.
4092 if (!EFI_ERROR (Status
) && ConfigRequest
!= NULL
) {
4093 Status
= ConfigAccess
->ExtractConfig (
4099 FreePool (ConfigRequest
);
4101 Status
= EFI_NOT_FOUND
;
4106 if (!EFI_ERROR (Status
)) {
4108 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
4110 if (!IfrDataParsedFlag
&& HiiHandle
!= NULL
&& DevicePath
!= NULL
) {
4111 StringPtr
= StrStr (AccessResults
, L
"&GUID=");
4112 if (StringPtr
!= NULL
) {
4115 if (GetElementsFromRequest (AccessResults
)) {
4116 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &AccessResults
, &DefaultResults
, NULL
);
4117 ASSERT_EFI_ERROR (Status
);
4119 if (StringPtr
!= NULL
) {
4124 // Merge the default sting from IFR code into the got setting from driver.
4126 if (DefaultResults
!= NULL
) {
4127 Status
= MergeDefaultString (&AccessResults
, DefaultResults
);
4128 ASSERT_EFI_ERROR (Status
);
4129 FreePool (DefaultResults
);
4130 DefaultResults
= NULL
;
4134 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'
4135 // which seperates the first <ConfigAltResp> and the following ones.
4137 if (!FirstElement
) {
4138 Status
= AppendToMultiString (Results
, L
"&");
4139 ASSERT_EFI_ERROR (Status
);
4142 Status
= AppendToMultiString (Results
, AccessResults
);
4143 ASSERT_EFI_ERROR (Status
);
4145 FirstElement
= FALSE
;
4147 FreePool (AccessResults
);
4148 AccessResults
= NULL
;
4151 FreePool (ConfigAccessHandles
);
4158 This function processes the results of processing forms and routes it to the
4159 appropriate handlers or storage.
4161 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
4163 @param Configuration A null-terminated Unicode string in
4164 <MulltiConfigResp> format.
4165 @param Progress A pointer to a string filled in with the offset of
4166 the most recent & before the first failing name /
4167 value pair (or the beginning of the string if the
4168 failure is in the first name / value pair) or the
4169 terminating NULL if all was successful.
4171 @retval EFI_SUCCESS The results have been distributed or are awaiting
4173 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
4174 results that must be stored awaiting possible
4176 @retval EFI_INVALID_PARAMETER Passing in a NULL for the Configuration parameter
4177 would result in this type of error.
4178 @retval EFI_NOT_FOUND Target for the specified routing data was not
4184 HiiConfigRoutingRouteConfig (
4185 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
4186 IN CONST EFI_STRING Configuration
,
4187 OUT EFI_STRING
*Progress
4190 HII_DATABASE_PRIVATE_DATA
*Private
;
4191 EFI_STRING StringPtr
;
4192 EFI_STRING ConfigResp
;
4195 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
4196 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
4198 HII_DATABASE_RECORD
*Database
;
4199 UINT8
*DevicePathPkg
;
4200 UINT8
*CurrentDevicePath
;
4201 EFI_HANDLE DriverHandle
;
4202 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
4203 EFI_STRING AccessProgress
;
4204 EFI_IFR_VARSTORE_EFI
*EfiVarStoreInfo
;
4205 BOOLEAN IsEfiVarstore
;
4206 UINTN DevicePathSize
;
4208 if (This
== NULL
|| Progress
== NULL
) {
4209 return EFI_INVALID_PARAMETER
;
4212 if (Configuration
== NULL
) {
4214 return EFI_INVALID_PARAMETER
;
4217 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
4218 StringPtr
= Configuration
;
4219 *Progress
= StringPtr
;
4221 AccessProgress
= NULL
;
4222 EfiVarStoreInfo
= NULL
;
4223 IsEfiVarstore
= FALSE
;
4226 // The first element of <MultiConfigResp> should be
4227 // <GuidHdr>, which is in 'GUID='<Guid> syntax.
4229 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
4230 return EFI_INVALID_PARAMETER
;
4233 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) == 0) {
4235 // If parsing error, set Progress to the beginning of the <MultiConfigResp>
4236 // or most recent & before the error.
4238 if (StringPtr
== Configuration
) {
4239 *Progress
= StringPtr
;
4241 *Progress
= StringPtr
- 1;
4245 // Process each <ConfigResp> of <MultiConfigResp>
4247 Length
= CalculateConfigStringLen (StringPtr
);
4248 ConfigResp
= AllocateCopyPool ((Length
+ 1) * sizeof (CHAR16
), StringPtr
);
4249 if (ConfigResp
== NULL
) {
4250 return EFI_OUT_OF_RESOURCES
;
4253 // Append '\0' to the end of ConfigRequest
4255 *(ConfigResp
+ Length
) = 0;
4258 // Get the UEFI device path
4260 Status
= GetDevicePath (ConfigResp
, (UINT8
**) &DevicePath
);
4261 if (EFI_ERROR (Status
)) {
4262 FreePool (ConfigResp
);
4267 // Find driver which matches the routing data.
4269 DriverHandle
= NULL
;
4270 for (Link
= Private
->DatabaseList
.ForwardLink
;
4271 Link
!= &Private
->DatabaseList
;
4272 Link
= Link
->ForwardLink
4274 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
4276 if ((DevicePathPkg
= Database
->PackageList
->DevicePathPkg
) != NULL
) {
4277 CurrentDevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
4278 DevicePathSize
= GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) CurrentDevicePath
);
4279 if ((CompareMem (DevicePath
,CurrentDevicePath
,DevicePathSize
) == 0) && IsThisPackageList(Database
, ConfigResp
)) {
4280 DriverHandle
= Database
->DriverHandle
;
4287 // Try to find driver handle by device path.
4289 if (DriverHandle
== NULL
) {
4290 TempDevicePath
= DevicePath
;
4291 Status
= gBS
->LocateDevicePath (
4292 &gEfiDevicePathProtocolGuid
,
4296 if (EFI_ERROR (Status
) || (DriverHandle
== NULL
)) {
4298 // Routing data does not match any known driver.
4299 // Set Progress to the 'G' in "GUID" of the routing header.
4301 FreePool (DevicePath
);
4302 *Progress
= StringPtr
;
4303 FreePool (ConfigResp
);
4304 return EFI_NOT_FOUND
;
4308 FreePool (DevicePath
);
4311 // Check whether this ConfigRequest is search from Efi varstore type storage.
4313 Status
= GetVarStoreType(Database
, ConfigResp
, &IsEfiVarstore
, &EfiVarStoreInfo
);
4314 if (EFI_ERROR (Status
)) {
4318 if (IsEfiVarstore
) {
4320 // Call the SetVariable function to route settings.
4322 Status
= RouteConfigRespForEfiVarStore(This
, EfiVarStoreInfo
, ConfigResp
, &AccessProgress
);
4323 FreePool (EfiVarStoreInfo
);
4326 // Call corresponding ConfigAccess protocol to route settings
4328 Status
= gBS
->HandleProtocol (
4330 &gEfiHiiConfigAccessProtocolGuid
,
4331 (VOID
**) &ConfigAccess
4333 ASSERT_EFI_ERROR (Status
);
4335 Status
= ConfigAccess
->RouteConfig (
4341 if (EFI_ERROR (Status
)) {
4343 // AccessProgress indicates the parsing progress on <ConfigResp>.
4344 // Map it to the progress on <MultiConfigResp> then return it.
4346 *Progress
= StrStr (StringPtr
, AccessProgress
);
4348 FreePool (ConfigResp
);
4352 FreePool (ConfigResp
);
4356 // Go to next <ConfigResp> (skip '&').
4358 StringPtr
+= Length
;
4359 if (*StringPtr
== 0) {
4360 *Progress
= StringPtr
;
4373 This helper function is to be called by drivers to map configuration data
4374 stored in byte array ("block") formats such as UEFI Variables into current
4375 configuration strings.
4377 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
4379 @param ConfigRequest A null-terminated Unicode string in
4380 <ConfigRequest> format.
4381 @param Block Array of bytes defining the block's configuration.
4382 @param BlockSize Length in bytes of Block.
4383 @param Config Filled-in configuration string. String allocated
4384 by the function. Returned only if call is
4385 successful. It is <ConfigResp> string format.
4386 @param Progress A pointer to a string filled in with the offset of
4387 the most recent & before the first failing
4388 name/value pair (or the beginning of the string if
4389 the failure is in the first name / value pair) or
4390 the terminating NULL if all was successful.
4392 @retval EFI_SUCCESS The request succeeded. Progress points to the null
4393 terminator at the end of the ConfigRequest
4395 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress
4396 points to the first character of ConfigRequest.
4397 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigRequest or
4398 Block parameter would result in this type of
4399 error. Progress points to the first character of
4401 @retval EFI_DEVICE_ERROR Block not large enough. Progress undefined.
4402 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted string.
4403 Block is left updated and Progress points at
4404 the "&" preceding the first non-<BlockName>.
4410 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
4411 IN CONST EFI_STRING ConfigRequest
,
4412 IN CONST UINT8
*Block
,
4413 IN CONST UINTN BlockSize
,
4414 OUT EFI_STRING
*Config
,
4415 OUT EFI_STRING
*Progress
4418 HII_DATABASE_PRIVATE_DATA
*Private
;
4419 EFI_STRING StringPtr
;
4427 EFI_STRING ValueStr
;
4428 EFI_STRING ConfigElement
;
4434 if (This
== NULL
|| Progress
== NULL
|| Config
== NULL
) {
4435 return EFI_INVALID_PARAMETER
;
4438 if (Block
== NULL
|| ConfigRequest
== NULL
) {
4439 *Progress
= ConfigRequest
;
4440 return EFI_INVALID_PARAMETER
;
4444 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
4445 ASSERT (Private
!= NULL
);
4447 StringPtr
= ConfigRequest
;
4450 ConfigElement
= NULL
;
4453 // Allocate a fix length of memory to store Results. Reallocate memory for
4454 // Results if this fix length is insufficient.
4456 *Config
= (EFI_STRING
) AllocateZeroPool (MAX_STRING_LENGTH
);
4457 if (*Config
== NULL
) {
4458 return EFI_OUT_OF_RESOURCES
;
4464 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
4465 *Progress
= StringPtr
;
4466 Status
= EFI_INVALID_PARAMETER
;
4469 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"PATH=", StrLen (L
"PATH=")) != 0) {
4472 if (*StringPtr
== 0) {
4473 *Progress
= StringPtr
- 1;
4474 Status
= EFI_INVALID_PARAMETER
;
4478 while (*StringPtr
!= L
'&' && *StringPtr
!= 0) {
4481 if (*StringPtr
== 0) {
4482 *Progress
= StringPtr
;
4484 AppendToMultiString(Config
, ConfigRequest
);
4485 HiiToLower (*Config
);
4495 // Copy <ConfigHdr> and an additional '&' to <ConfigResp>
4497 TemChar
= *StringPtr
;
4499 AppendToMultiString(Config
, ConfigRequest
);
4500 *StringPtr
= TemChar
;
4503 // Parse each <RequestElement> if exists
4504 // Only <BlockName> format is supported by this help function.
4505 // <BlockName> ::= 'OFFSET='<Number>&'WIDTH='<Number>
4507 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"OFFSET=", StrLen (L
"OFFSET=")) == 0) {
4509 // Back up the header of one <BlockName>
4513 StringPtr
+= StrLen (L
"OFFSET=");
4517 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
4518 if (EFI_ERROR (Status
)) {
4519 *Progress
= TmpPtr
- 1;
4526 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
4528 FreePool (TmpBuffer
);
4530 StringPtr
+= Length
;
4531 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
4532 *Progress
= TmpPtr
- 1;
4533 Status
= EFI_INVALID_PARAMETER
;
4536 StringPtr
+= StrLen (L
"&WIDTH=");
4541 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
4542 if (EFI_ERROR (Status
)) {
4543 *Progress
= TmpPtr
- 1;
4550 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
4552 FreePool (TmpBuffer
);
4554 StringPtr
+= Length
;
4555 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
4556 *Progress
= TmpPtr
- 1;
4557 Status
= EFI_INVALID_PARAMETER
;
4562 // Calculate Value and convert it to hex string.
4564 if (Offset
+ Width
> BlockSize
) {
4565 *Progress
= StringPtr
;
4566 Status
= EFI_DEVICE_ERROR
;
4570 Value
= (UINT8
*) AllocateZeroPool (Width
);
4571 if (Value
== NULL
) {
4572 *Progress
= ConfigRequest
;
4573 Status
= EFI_OUT_OF_RESOURCES
;
4577 CopyMem (Value
, (UINT8
*) Block
+ Offset
, Width
);
4579 Length
= Width
* 2 + 1;
4580 ValueStr
= (EFI_STRING
) AllocateZeroPool (Length
* sizeof (CHAR16
));
4581 if (ValueStr
== NULL
) {
4582 *Progress
= ConfigRequest
;
4583 Status
= EFI_OUT_OF_RESOURCES
;
4587 TemString
= ValueStr
;
4588 TemBuffer
= Value
+ Width
- 1;
4589 for (Index
= 0; Index
< Width
; Index
++, TemBuffer
--) {
4590 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
4597 // Build a ConfigElement
4599 Length
+= StringPtr
- TmpPtr
+ 1 + StrLen (L
"VALUE=");
4600 ConfigElement
= (EFI_STRING
) AllocateZeroPool (Length
* sizeof (CHAR16
));
4601 if (ConfigElement
== NULL
) {
4602 Status
= EFI_OUT_OF_RESOURCES
;
4605 CopyMem (ConfigElement
, TmpPtr
, (StringPtr
- TmpPtr
+ 1) * sizeof (CHAR16
));
4606 if (*StringPtr
== 0) {
4607 *(ConfigElement
+ (StringPtr
- TmpPtr
)) = L
'&';
4609 *(ConfigElement
+ (StringPtr
- TmpPtr
) + 1) = 0;
4610 StrCat (ConfigElement
, L
"VALUE=");
4611 StrCat (ConfigElement
, ValueStr
);
4613 AppendToMultiString (Config
, ConfigElement
);
4615 FreePool (ConfigElement
);
4616 FreePool (ValueStr
);
4617 ConfigElement
= NULL
;
4621 // If '\0', parsing is finished. Otherwise skip '&' to continue
4623 if (*StringPtr
== 0) {
4626 AppendToMultiString (Config
, L
"&");
4631 if (*StringPtr
!= 0) {
4632 *Progress
= StringPtr
- 1;
4633 Status
= EFI_INVALID_PARAMETER
;
4637 HiiToLower (*Config
);
4638 *Progress
= StringPtr
;
4642 if (*Config
!= NULL
) {
4646 if (ValueStr
!= NULL
) {
4647 FreePool (ValueStr
);
4649 if (Value
!= NULL
) {
4652 if (ConfigElement
!= NULL
) {
4653 FreePool (ConfigElement
);
4662 This helper function is to be called by drivers to map configuration strings
4663 to configurations stored in byte array ("block") formats such as UEFI Variables.
4665 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
4667 @param ConfigResp A null-terminated Unicode string in <ConfigResp>
4669 @param Block A possibly null array of bytes representing the
4670 current block. Only bytes referenced in the
4671 ConfigResp string in the block are modified. If
4672 this parameter is null or if the *BlockSize
4673 parameter is (on input) shorter than required by
4674 the Configuration string, only the BlockSize
4675 parameter is updated and an appropriate status
4676 (see below) is returned.
4677 @param BlockSize The length of the Block in units of UINT8. On
4678 input, this is the size of the Block. On output,
4679 if successful, contains the largest index of the
4680 modified byte in the Block, or the required buffer
4681 size if the Block is not large enough.
4682 @param Progress On return, points to an element of the ConfigResp
4683 string filled in with the offset of the most
4684 recent '&' before the first failing name / value
4685 pair (or the beginning of the string if the
4686 failure is in the first name / value pair) or the
4687 terminating NULL if all was successful.
4689 @retval EFI_SUCCESS The request succeeded. Progress points to the null
4690 terminator at the end of the ConfigResp string.
4691 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress
4692 points to the first character of ConfigResp.
4693 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigResp or
4694 Block parameter would result in this type of
4695 error. Progress points to the first character of
4697 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted name /
4698 value pair. Block is left updated and
4699 Progress points at the '&' preceding the first
4701 @retval EFI_BUFFER_TOO_SMALL Block not large enough. Progress undefined.
4702 BlockSize is updated with the required buffer size.
4703 @retval EFI_NOT_FOUND Target for the specified routing data was not found.
4704 Progress points to the "G" in "GUID" of the errant
4711 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
4712 IN CONST EFI_STRING ConfigResp
,
4713 IN OUT UINT8
*Block
,
4714 IN OUT UINTN
*BlockSize
,
4715 OUT EFI_STRING
*Progress
4718 HII_DATABASE_PRIVATE_DATA
*Private
;
4719 EFI_STRING StringPtr
;
4730 if (This
== NULL
|| BlockSize
== NULL
|| Progress
== NULL
) {
4731 return EFI_INVALID_PARAMETER
;
4734 *Progress
= ConfigResp
;
4735 if (ConfigResp
== NULL
) {
4736 return EFI_INVALID_PARAMETER
;
4739 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
4740 ASSERT (Private
!= NULL
);
4742 StringPtr
= ConfigResp
;
4743 BufferSize
= *BlockSize
;
4750 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
4751 *Progress
= StringPtr
;
4752 Status
= EFI_INVALID_PARAMETER
;
4755 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"PATH=", StrLen (L
"PATH=")) != 0) {
4758 if (*StringPtr
== 0) {
4759 *Progress
= StringPtr
;
4760 Status
= EFI_INVALID_PARAMETER
;
4764 while (*StringPtr
!= L
'&' && *StringPtr
!= 0) {
4767 if (*StringPtr
== 0) {
4768 *Progress
= StringPtr
;
4769 Status
= EFI_INVALID_PARAMETER
;
4774 // Parse each <ConfigElement> if exists
4775 // Only '&'<BlockConfig> format is supported by this help function.
4776 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE='<Number>
4778 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) == 0) {
4780 StringPtr
+= StrLen (L
"&OFFSET=");
4784 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
4785 if (EFI_ERROR (Status
)) {
4793 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
4795 FreePool (TmpBuffer
);
4797 StringPtr
+= Length
;
4798 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
4800 Status
= EFI_INVALID_PARAMETER
;
4803 StringPtr
+= StrLen (L
"&WIDTH=");
4808 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
4809 if (EFI_ERROR (Status
)) {
4817 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
4819 FreePool (TmpBuffer
);
4821 StringPtr
+= Length
;
4822 if (StrnCmp (StringPtr
, L
"&VALUE=", StrLen (L
"&VALUE=")) != 0) {
4824 Status
= EFI_INVALID_PARAMETER
;
4827 StringPtr
+= StrLen (L
"&VALUE=");
4832 Status
= GetValueOfNumber (StringPtr
, &Value
, &Length
);
4833 if (EFI_ERROR (Status
)) {
4838 StringPtr
+= Length
;
4839 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
4841 Status
= EFI_INVALID_PARAMETER
;
4846 // Update the Block with configuration info
4848 if ((Block
!= NULL
) && (Offset
+ Width
<= BufferSize
)) {
4849 CopyMem (Block
+ Offset
, Value
, Width
);
4851 if (Offset
+ Width
> MaxBlockSize
) {
4852 MaxBlockSize
= Offset
+ Width
;
4859 // If '\0', parsing is finished.
4861 if (*StringPtr
== 0) {
4867 // The input string is not ConfigResp format, return error.
4869 if (*StringPtr
!= 0) {
4870 *Progress
= StringPtr
;
4871 Status
= EFI_INVALID_PARAMETER
;
4875 *Progress
= StringPtr
+ StrLen (StringPtr
);
4876 *BlockSize
= MaxBlockSize
- 1;
4878 if (MaxBlockSize
> BufferSize
) {
4879 *BlockSize
= MaxBlockSize
;
4880 if (Block
!= NULL
) {
4881 return EFI_BUFFER_TOO_SMALL
;
4885 if (Block
== NULL
) {
4886 *Progress
= ConfigResp
;
4887 return EFI_INVALID_PARAMETER
;
4894 if (Value
!= NULL
) {
4902 This helper function is to be called by drivers to extract portions of
4903 a larger configuration string.
4905 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
4907 @param Configuration A null-terminated Unicode string in
4908 <MultiConfigAltResp> format.
4909 @param Guid A pointer to the GUID value to search for in the
4910 routing portion of the ConfigResp string when
4911 retrieving the requested data. If Guid is NULL,
4912 then all GUID values will be searched for.
4913 @param Name A pointer to the NAME value to search for in the
4914 routing portion of the ConfigResp string when
4915 retrieving the requested data. If Name is NULL,
4916 then all Name values will be searched for.
4917 @param DevicePath A pointer to the PATH value to search for in the
4918 routing portion of the ConfigResp string when
4919 retrieving the requested data. If DevicePath is
4920 NULL, then all DevicePath values will be searched
4922 @param AltCfgId A pointer to the ALTCFG value to search for in the
4923 routing portion of the ConfigResp string when
4924 retrieving the requested data. If this parameter
4925 is NULL, then the current setting will be
4927 @param AltCfgResp A pointer to a buffer which will be allocated by
4928 the function which contains the retrieved string
4929 as requested. This buffer is only allocated if
4930 the call was successful. It is <ConfigResp> format.
4932 @retval EFI_SUCCESS The request succeeded. The requested data was
4933 extracted and placed in the newly allocated
4935 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate AltCfgResp.
4936 @retval EFI_INVALID_PARAMETER Any parameter is invalid.
4937 @retval EFI_NOT_FOUND Target for the specified routing data was not
4944 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
4945 IN CONST EFI_STRING Configuration
,
4946 IN CONST EFI_GUID
*Guid
,
4947 IN CONST EFI_STRING Name
,
4948 IN CONST EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
4949 IN CONST UINT16
*AltCfgId
,
4950 OUT EFI_STRING
*AltCfgResp
4954 EFI_STRING StringPtr
;
4955 EFI_STRING HdrStart
;
4962 EFI_STRING AltIdStr
;
4979 if (This
== NULL
|| Configuration
== NULL
|| AltCfgResp
== NULL
) {
4980 return EFI_INVALID_PARAMETER
;
4983 StringPtr
= Configuration
;
4984 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
4985 return EFI_INVALID_PARAMETER
;
4989 // Generate the sub string for later matching.
4991 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*) Guid
, 1, &GuidStr
);
4994 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) DevicePath
),
4995 (VOID
*) DevicePath
,
4999 if (AltCfgId
!= NULL
) {
5000 GenerateSubStr (L
"ALTCFG=", sizeof (UINT16
), (VOID
*) AltCfgId
, 3, &AltIdStr
);
5003 GenerateSubStr (L
"NAME=", StrLen (Name
) * sizeof (CHAR16
), (VOID
*) Name
, 2, &NameStr
);
5005 GenerateSubStr (L
"NAME=", 0, NULL
, 2, &NameStr
);
5008 while (*StringPtr
!= 0) {
5010 // Try to match the GUID
5013 TmpPtr
= StrStr (StringPtr
, GuidStr
);
5014 if (TmpPtr
== NULL
) {
5015 Status
= EFI_NOT_FOUND
;
5021 // Jump to <NameHdr>
5024 StringPtr
= TmpPtr
+ StrLen (GuidStr
);
5026 StringPtr
= StrStr (TmpPtr
, L
"NAME=");
5027 if (StringPtr
== NULL
) {
5028 Status
= EFI_NOT_FOUND
;
5036 // Try to match the NAME
5038 if (GuidFlag
&& !NameFlag
) {
5039 if (StrnCmp (StringPtr
, NameStr
, StrLen (NameStr
)) != 0) {
5043 // Jump to <PathHdr>
5046 StringPtr
+= StrLen (NameStr
);
5048 StringPtr
= StrStr (StringPtr
, L
"PATH=");
5049 if (StringPtr
== NULL
) {
5050 Status
= EFI_NOT_FOUND
;
5059 // Try to match the DevicePath
5061 if (GuidFlag
&& NameFlag
&& !PathFlag
) {
5062 if (StrnCmp (StringPtr
, PathStr
, StrLen (PathStr
)) != 0) {
5067 // Jump to '&' before <DescHdr> or <ConfigBody>
5069 if (DevicePath
!= NULL
) {
5070 StringPtr
+= StrLen (PathStr
);
5072 StringPtr
= StrStr (StringPtr
, L
"&");
5073 if (StringPtr
== NULL
) {
5074 Status
= EFI_NOT_FOUND
;
5085 // Try to match the AltCfgId
5087 if (GuidFlag
&& NameFlag
&& PathFlag
) {
5088 if (AltCfgId
== NULL
) {
5090 // Return Current Setting when AltCfgId is NULL.
5092 Status
= OutputConfigBody (StringPtr
, &Result
);
5096 // Search the <ConfigAltResp> to get the <AltResp> with AltCfgId.
5098 if (StrnCmp (StringPtr
, AltIdStr
, StrLen (AltIdStr
)) != 0) {
5104 // Skip AltIdStr and &
5106 StringPtr
= StringPtr
+ StrLen (AltIdStr
);
5107 Status
= OutputConfigBody (StringPtr
, &Result
);
5113 Status
= EFI_NOT_FOUND
;
5117 if (!EFI_ERROR (Status
) && (Result
!= NULL
)) {
5119 // Copy the <ConfigHdr> and <ConfigBody>
5121 Length
= HdrEnd
- HdrStart
+ StrLen (Result
) + 1;
5122 *AltCfgResp
= AllocateZeroPool (Length
* sizeof (CHAR16
));
5123 if (*AltCfgResp
== NULL
) {
5124 Status
= EFI_OUT_OF_RESOURCES
;
5126 StrnCpy (*AltCfgResp
, HdrStart
, HdrEnd
- HdrStart
);
5127 StrCat (*AltCfgResp
, Result
);
5128 Status
= EFI_SUCCESS
;
5132 if (GuidStr
!= NULL
) {
5135 if (NameStr
!= NULL
) {
5138 if (PathStr
!= NULL
) {
5141 if (AltIdStr
!= NULL
) {
5142 FreePool (AltIdStr
);
5144 if (Result
!= NULL
) {