2 Implementation of interfaces function for EFI_HII_CONFIG_ROUTING_PROTOCOL.
4 Copyright (c) 2007 - 2013, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 #include "HiiDatabase.h"
17 extern HII_DATABASE_PRIVATE_DATA mPrivate
;
20 Calculate the number of Unicode characters of the incoming Configuration string,
21 not including NULL terminator.
23 This is a internal function.
25 @param String String in <MultiConfigRequest> or
26 <MultiConfigResp> format.
28 @return The number of Unicode characters.
32 CalculateConfigStringLen (
39 // "GUID=" should be the first element of incoming string.
41 ASSERT (String
!= NULL
);
42 ASSERT (StrnCmp (String
, L
"GUID=", StrLen (L
"GUID=")) == 0);
45 // The beginning of next <ConfigRequest>/<ConfigResp> should be "&GUID=".
46 // Will meet '\0' if there is only one <ConfigRequest>/<ConfigResp>.
48 TmpPtr
= StrStr (String
, L
"&GUID=");
50 return StrLen (String
);
53 return (TmpPtr
- String
);
58 Convert the hex UNICODE %02x encoding of a UEFI device path to binary
59 from <PathHdr> of <ConfigHdr>.
61 This is a internal function.
63 @param String UEFI configuration string
64 @param DevicePathData Binary of a UEFI device path.
66 @retval EFI_NOT_FOUND The device path is not invalid.
67 @retval EFI_INVALID_PARAMETER Any incoming parameter is invalid.
68 @retval EFI_OUT_OF_RESOURCES Lake of resources to store neccesary structures.
69 @retval EFI_SUCCESS The device path is retrieved and translated to
76 OUT UINT8
**DevicePathData
81 UINT8
*DevicePathBuffer
;
85 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
88 if (String
== NULL
|| DevicePathData
== NULL
) {
89 return EFI_INVALID_PARAMETER
;
93 // Find the 'PATH=' of <PathHdr> and skip it.
95 for (; (*String
!= 0 && StrnCmp (String
, L
"PATH=", StrLen (L
"PATH=")) != 0); String
++);
97 return EFI_INVALID_PARAMETER
;
100 // Check whether path data does exist.
102 String
+= StrLen (L
"PATH=");
104 return EFI_INVALID_PARAMETER
;
109 // The content between 'PATH=' of <ConfigHdr> and '&' of next element
110 // or '\0' (end of configuration string) is the UNICODE %02x bytes encoding
111 // of UEFI device path.
113 for (Length
= 0; *String
!= 0 && *String
!= L
'&'; String
++, Length
++);
115 // Check DevicePath Length
117 if (((Length
+ 1) / 2) < sizeof (EFI_DEVICE_PATH_PROTOCOL
)) {
118 return EFI_NOT_FOUND
;
122 // The data in <PathHdr> is encoded as hex UNICODE %02x bytes in the same order
123 // as the device path resides in RAM memory.
124 // Translate the data into binary.
126 DevicePathBuffer
= (UINT8
*) AllocateZeroPool ((Length
+ 1) / 2);
127 if (DevicePathBuffer
== NULL
) {
128 return EFI_OUT_OF_RESOURCES
;
132 // Convert DevicePath
134 ZeroMem (TemStr
, sizeof (TemStr
));
135 for (Index
= 0; Index
< Length
; Index
++) {
136 TemStr
[0] = PathHdr
[Index
];
137 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
138 if ((Index
& 1) == 0) {
139 DevicePathBuffer
[Index
/2] = DigitUint8
;
141 DevicePathBuffer
[Index
/2] = (UINT8
) ((DevicePathBuffer
[Index
/2] << 4) + DigitUint8
);
146 // Validate DevicePath
148 DevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) DevicePathBuffer
;
149 while (!IsDevicePathEnd (DevicePath
)) {
150 if ((DevicePath
->Type
== 0) || (DevicePath
->SubType
== 0) || (DevicePathNodeLength (DevicePath
) < sizeof (EFI_DEVICE_PATH_PROTOCOL
))) {
152 // Invalid device path
154 FreePool (DevicePathBuffer
);
155 return EFI_NOT_FOUND
;
157 DevicePath
= NextDevicePathNode (DevicePath
);
161 // return the device path
163 *DevicePathData
= DevicePathBuffer
;
168 Converts the unicode character of the string from uppercase to lowercase.
169 This is a internal function.
171 @param ConfigString String to be converted
177 IN EFI_STRING ConfigString
183 ASSERT (ConfigString
!= NULL
);
186 // Convert all hex digits in range [A-F] in the configuration header to [a-f]
188 for (String
= ConfigString
, Lower
= FALSE
; *String
!= L
'\0'; String
++) {
189 if (*String
== L
'=') {
191 } else if (*String
== L
'&') {
193 } else if (Lower
&& *String
>= L
'A' && *String
<= L
'F') {
194 *String
= (CHAR16
) (*String
- L
'A' + L
'a');
202 Generate a sub string then output it.
204 This is a internal function.
206 @param String A constant string which is the prefix of the to be
207 generated string, e.g. GUID=
209 @param BufferLen The length of the Buffer in bytes.
211 @param Buffer Points to a buffer which will be converted to be the
212 content of the generated string.
214 @param Flag If 1, the buffer contains data for the value of GUID or PATH stored in
215 UINT8 *; if 2, the buffer contains unicode string for the value of NAME;
216 if 3, the buffer contains other data.
218 @param SubStr Points to the output string. It's caller's
219 responsibility to free this buffer.
225 IN CONST EFI_STRING String
,
229 OUT EFI_STRING
*SubStr
234 EFI_STRING StringHeader
;
240 ASSERT (String
!= NULL
&& SubStr
!= NULL
);
242 if (Buffer
== NULL
) {
243 *SubStr
= AllocateCopyPool (StrSize (String
), String
);
244 ASSERT (*SubStr
!= NULL
);
249 // Header + Data + '&' + '\0'
251 Length
= StrLen (String
) + BufferLen
* 2 + 1 + 1;
252 Str
= AllocateZeroPool (Length
* sizeof (CHAR16
));
253 ASSERT (Str
!= NULL
);
255 StrCpy (Str
, String
);
256 Length
= (BufferLen
* 2 + 1) * sizeof (CHAR16
);
258 StringHeader
= Str
+ StrLen (String
);
259 TemString
= (CHAR16
*) StringHeader
;
264 // Convert Buffer to Hex String in reverse order
266 TemBuffer
= ((UINT8
*) Buffer
);
267 for (Index
= 0; Index
< BufferLen
; Index
++, TemBuffer
++) {
268 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
273 // Check buffer is enough
275 TemName
= (CHAR16
*) Buffer
;
276 ASSERT ((BufferLen
* 2 + 1) >= (StrLen (TemName
) * 4 + 1));
278 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
280 for (; *TemName
!= L
'\0'; TemName
++) {
281 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemName
, 4);
286 // Convert Buffer to Hex String
288 TemBuffer
= ((UINT8
*) Buffer
) + BufferLen
- 1;
289 for (Index
= 0; Index
< BufferLen
; Index
++, TemBuffer
--) {
290 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
298 // Convert the uppercase to lowercase since <HexAf> is defined in lowercase format.
308 Retrieve the <ConfigBody> from String then output it.
310 This is a internal function.
312 @param String A sub string of a configuration string in
313 <MultiConfigAltResp> format.
314 @param ConfigBody Points to the output string. It's caller's
315 responsibility to free this buffer.
317 @retval EFI_INVALID_PARAMETER There is no form package in current hii database.
318 @retval EFI_OUT_OF_RESOURCES Not enough memory to finish this operation.
319 @retval EFI_SUCCESS All existing storage is exported.
324 IN EFI_STRING String
,
325 OUT EFI_STRING
*ConfigBody
332 if (String
== NULL
|| ConfigBody
== NULL
) {
333 return EFI_INVALID_PARAMETER
;
337 // The setting information should start OFFSET, not ALTCFG.
339 if (StrnCmp (String
, L
"&ALTCFG=", StrLen (L
"&ALTCFG=")) == 0) {
340 return EFI_INVALID_PARAMETER
;
343 TmpPtr
= StrStr (String
, L
"GUID=");
344 if (TmpPtr
== NULL
) {
346 // It is the last <ConfigResp> of the incoming configuration string.
348 Result
= AllocateCopyPool (StrSize (String
), String
);
349 if (Result
== NULL
) {
350 return EFI_OUT_OF_RESOURCES
;
352 *ConfigBody
= Result
;
357 Length
= TmpPtr
- String
;
358 Result
= AllocateCopyPool (Length
* sizeof (CHAR16
), String
);
359 if (Result
== NULL
) {
360 return EFI_OUT_OF_RESOURCES
;
363 *(Result
+ Length
- 1) = 0;
364 *ConfigBody
= Result
;
369 Append a string to a multi-string format.
371 This is a internal function.
373 @param MultiString String in <MultiConfigRequest>,
374 <MultiConfigAltResp>, or <MultiConfigResp>. On
375 input, the buffer length of this string is
376 MAX_STRING_LENGTH. On output, the buffer length
378 @param AppendString NULL-terminated Unicode string.
380 @retval EFI_INVALID_PARAMETER Any incoming parameter is invalid.
381 @retval EFI_SUCCESS AppendString is append to the end of MultiString
385 AppendToMultiString (
386 IN OUT EFI_STRING
*MultiString
,
387 IN EFI_STRING AppendString
390 UINTN AppendStringSize
;
391 UINTN MultiStringSize
;
393 if (MultiString
== NULL
|| *MultiString
== NULL
|| AppendString
== NULL
) {
394 return EFI_INVALID_PARAMETER
;
397 AppendStringSize
= StrSize (AppendString
);
398 MultiStringSize
= StrSize (*MultiString
);
401 // Enlarge the buffer each time when length exceeds MAX_STRING_LENGTH.
403 if (MultiStringSize
+ AppendStringSize
> MAX_STRING_LENGTH
||
404 MultiStringSize
> MAX_STRING_LENGTH
) {
405 *MultiString
= (EFI_STRING
) ReallocatePool (
407 MultiStringSize
+ AppendStringSize
,
408 (VOID
*) (*MultiString
)
410 ASSERT (*MultiString
!= NULL
);
413 // Append the incoming string
415 StrCat (*MultiString
, AppendString
);
422 Get the value of <Number> in <BlockConfig> format, i.e. the value of OFFSET
424 <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>
426 This is a internal function.
428 @param StringPtr String in <BlockConfig> format and points to the
429 first character of <Number>.
430 @param Number The output value. Caller takes the responsibility
432 @param Len Length of the <Number>, in characters.
434 @retval EFI_OUT_OF_RESOURCES Insufficient resources to store neccessary
436 @retval EFI_SUCCESS Value of <Number> is outputted in Number
442 IN EFI_STRING StringPtr
,
456 if (StringPtr
== NULL
|| *StringPtr
== L
'\0' || Number
== NULL
|| Len
== NULL
) {
457 return EFI_INVALID_PARAMETER
;
463 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
466 *Len
= StringPtr
- TmpPtr
;
469 Str
= (EFI_STRING
) AllocateZeroPool (Length
* sizeof (CHAR16
));
471 Status
= EFI_OUT_OF_RESOURCES
;
474 CopyMem (Str
, TmpPtr
, *Len
* sizeof (CHAR16
));
475 *(Str
+ *Len
) = L
'\0';
477 Length
= (Length
+ 1) / 2;
478 Buf
= (UINT8
*) AllocateZeroPool (Length
);
480 Status
= EFI_OUT_OF_RESOURCES
;
485 ZeroMem (TemStr
, sizeof (TemStr
));
486 for (Index
= 0; Index
< Length
; Index
++) {
487 TemStr
[0] = Str
[Length
- Index
- 1];
488 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
489 if ((Index
& 1) == 0) {
490 Buf
[Index
/2] = DigitUint8
;
492 Buf
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Buf
[Index
/2]);
497 Status
= EFI_SUCCESS
;
508 This function merges DefaultAltCfgResp string into AltCfgResp string for
509 the missing AltCfgId in AltCfgResq.
511 @param AltCfgResp Pointer to a null-terminated Unicode string in
512 <ConfigAltResp> format. The default value string
513 will be merged into it.
514 @param DefaultAltCfgResp Pointer to a null-terminated Unicode string in
515 <MultiConfigAltResp> format. The default value
516 string may contain more than one ConfigAltResp
517 string for the different varstore buffer.
519 @retval EFI_SUCCESS The merged string returns.
520 @retval EFI_INVALID_PARAMETER *AltCfgResp is to NULL.
525 IN OUT EFI_STRING
*AltCfgResp
,
526 IN EFI_STRING DefaultAltCfgResp
529 EFI_STRING StringPtrDefault
;
530 EFI_STRING StringPtrEnd
;
532 EFI_STRING StringPtr
;
533 EFI_STRING AltConfigHdr
;
535 UINTN SizeAltCfgResp
;
537 if (*AltCfgResp
== NULL
) {
538 return EFI_INVALID_PARAMETER
;
542 // Get the requestr ConfigHdr
545 StringPtr
= *AltCfgResp
;
548 // Find <ConfigHdr> GUID=...&NAME=...&PATH=...
550 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
551 return EFI_INVALID_PARAMETER
;
553 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&NAME=", StrLen (L
"&NAME=")) != 0) {
556 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&PATH=", StrLen (L
"&PATH=")) != 0) {
559 if (*StringPtr
== L
'\0') {
560 return EFI_INVALID_PARAMETER
;
562 StringPtr
+= StrLen (L
"&PATH=");
563 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
566 HeaderLength
= StringPtr
- *AltCfgResp
;
569 // Construct AltConfigHdr string "&<ConfigHdr>&ALTCFG=XXXX\0"
570 // |1| StrLen (ConfigHdr) | 8 | 4 | 1 |
572 AltConfigHdr
= AllocateZeroPool ((1 + HeaderLength
+ 8 + 4 + 1) * sizeof (CHAR16
));
573 if (AltConfigHdr
== NULL
) {
574 return EFI_OUT_OF_RESOURCES
;
576 StrCpy (AltConfigHdr
, L
"&");
577 StrnCat (AltConfigHdr
, *AltCfgResp
, HeaderLength
);
578 StrCat (AltConfigHdr
, L
"&ALTCFG=");
579 HeaderLength
= StrLen (AltConfigHdr
);
581 StringPtrDefault
= StrStr (DefaultAltCfgResp
, AltConfigHdr
);
582 while (StringPtrDefault
!= NULL
) {
586 StrnCat (AltConfigHdr
, StringPtrDefault
+ HeaderLength
, 4);
587 StringPtr
= StrStr (*AltCfgResp
, AltConfigHdr
);
590 // Append the found default value string to the input AltCfgResp
592 if (StringPtr
== NULL
) {
593 StringPtrEnd
= StrStr (StringPtrDefault
+ 1, L
"&GUID");
594 SizeAltCfgResp
= StrSize (*AltCfgResp
);
595 if (StringPtrEnd
== NULL
) {
597 // No more default string is found.
599 *AltCfgResp
= (EFI_STRING
) ReallocatePool (
601 SizeAltCfgResp
+ StrSize (StringPtrDefault
),
602 (VOID
*) (*AltCfgResp
)
604 if (*AltCfgResp
== NULL
) {
605 FreePool (AltConfigHdr
);
606 return EFI_OUT_OF_RESOURCES
;
608 StrCat (*AltCfgResp
, StringPtrDefault
);
611 TempChar
= *StringPtrEnd
;
612 *StringPtrEnd
= L
'\0';
613 *AltCfgResp
= (EFI_STRING
) ReallocatePool (
615 SizeAltCfgResp
+ StrSize (StringPtrDefault
),
616 (VOID
*) (*AltCfgResp
)
618 if (*AltCfgResp
== NULL
) {
619 FreePool (AltConfigHdr
);
620 return EFI_OUT_OF_RESOURCES
;
622 StrCat (*AltCfgResp
, StringPtrDefault
);
623 *StringPtrEnd
= TempChar
;
628 // Find next AltCfg String
630 *(AltConfigHdr
+ HeaderLength
) = L
'\0';
631 StringPtrDefault
= StrStr (StringPtrDefault
+ 1, AltConfigHdr
);
634 FreePool (AltConfigHdr
);
639 This function inserts new DefaultValueData into the BlockData DefaultValue array.
641 @param BlockData The BlockData is updated to add new default value.
642 @param DefaultValueData The DefaultValue is added.
647 IN IFR_BLOCK_DATA
*BlockData
,
648 IN IFR_DEFAULT_DATA
*DefaultValueData
652 IFR_DEFAULT_DATA
*DefaultValueArray
;
653 LIST_ENTRY
*DefaultLink
;
655 DefaultLink
= &BlockData
->DefaultValueEntry
;
657 for (Link
= DefaultLink
->ForwardLink
; Link
!= DefaultLink
; Link
= Link
->ForwardLink
) {
658 DefaultValueArray
= BASE_CR (Link
, IFR_DEFAULT_DATA
, Entry
);
659 if (DefaultValueArray
->DefaultId
== DefaultValueData
->DefaultId
) {
661 // DEFAULT_VALUE_FROM_OPCODE has high priority, DEFAULT_VALUE_FROM_DEFAULT has low priority.
663 if (DefaultValueData
->Type
> DefaultValueArray
->Type
) {
665 // Update the default value array in BlockData.
667 CopyMem (&DefaultValueArray
->Value
, &DefaultValueData
->Value
, sizeof (EFI_IFR_TYPE_VALUE
));
668 DefaultValueArray
->Type
= DefaultValueData
->Type
;
669 DefaultValueArray
->Cleaned
= DefaultValueData
->Cleaned
;
676 // Insert new default value data in tail.
678 DefaultValueArray
= AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
679 ASSERT (DefaultValueArray
!= NULL
);
680 CopyMem (DefaultValueArray
, DefaultValueData
, sizeof (IFR_DEFAULT_DATA
));
681 InsertTailList (Link
, &DefaultValueArray
->Entry
);
685 This function inserts new BlockData into the block link
687 @param BlockLink The list entry points to block array.
688 @param BlockData The point to BlockData is added.
693 IN LIST_ENTRY
*BlockLink
,
694 IN IFR_BLOCK_DATA
**BlockData
698 IFR_BLOCK_DATA
*BlockArray
;
699 IFR_BLOCK_DATA
*BlockSingleData
;
701 BlockSingleData
= *BlockData
;
703 if (BlockSingleData
->Name
!= NULL
) {
704 InsertTailList (BlockLink
, &BlockSingleData
->Entry
);
709 // Insert block data in its Offset and Width order.
711 for (Link
= BlockLink
->ForwardLink
; Link
!= BlockLink
; Link
= Link
->ForwardLink
) {
712 BlockArray
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
713 if (BlockArray
->Offset
== BlockSingleData
->Offset
) {
714 if (BlockArray
->Width
> BlockSingleData
->Width
) {
716 // Insert this block data in the front of block array
718 InsertTailList (Link
, &BlockSingleData
->Entry
);
722 if (BlockArray
->Width
== BlockSingleData
->Width
) {
724 // The same block array has been added.
726 if (BlockSingleData
!= BlockArray
) {
727 FreePool (BlockSingleData
);
728 *BlockData
= BlockArray
;
732 } else if (BlockArray
->Offset
> BlockSingleData
->Offset
) {
734 // Insert new block data in the front of block array
736 InsertTailList (Link
, &BlockSingleData
->Entry
);
742 // Add new block data into the tail.
744 InsertTailList (Link
, &BlockSingleData
->Entry
);
748 Retrieves a pointer to the a Null-terminated ASCII string containing the list
749 of languages that an HII handle in the HII Database supports. The returned
750 string is allocated using AllocatePool(). The caller is responsible for freeing
751 the returned string using FreePool(). The format of the returned string follows
752 the language format assumed the HII Database.
754 If HiiHandle is NULL, then ASSERT().
756 @param[in] HiiHandle A handle that was previously registered in the HII Database.
758 @retval NULL HiiHandle is not registered in the HII database
759 @retval NULL There are not enough resources available to retrieve the suported
761 @retval NULL The list of suported languages could not be retrieved.
762 @retval Other A pointer to the Null-terminated ASCII string of supported languages.
766 GetSupportedLanguages (
767 IN EFI_HII_HANDLE HiiHandle
772 CHAR8 TempSupportedLanguages
;
773 CHAR8
*SupportedLanguages
;
775 ASSERT (HiiHandle
!= NULL
);
778 // Retrieve the size required for the supported languages buffer.
781 Status
= mPrivate
.HiiString
.GetLanguages (&mPrivate
.HiiString
, HiiHandle
, &TempSupportedLanguages
, &LanguageSize
);
784 // If GetLanguages() returns EFI_SUCCESS for a zero size,
785 // then there are no supported languages registered for HiiHandle. If GetLanguages()
786 // returns an error other than EFI_BUFFER_TOO_SMALL, then HiiHandle is not present
787 // in the HII Database
789 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
791 // Return NULL if the size can not be retrieved, or if HiiHandle is not in the HII Database
797 // Allocate the supported languages buffer.
799 SupportedLanguages
= AllocateZeroPool (LanguageSize
);
800 if (SupportedLanguages
== NULL
) {
802 // Return NULL if allocation fails.
808 // Retrieve the supported languages string
810 Status
= mPrivate
.HiiString
.GetLanguages (&mPrivate
.HiiString
, HiiHandle
, SupportedLanguages
, &LanguageSize
);
811 if (EFI_ERROR (Status
)) {
813 // Free the buffer and return NULL if the supported languages can not be retrieved.
815 FreePool (SupportedLanguages
);
820 // Return the Null-terminated ASCII string of supported languages
822 return SupportedLanguages
;
826 Retrieves a string from a string package.
828 If HiiHandle is NULL, then ASSERT().
829 If StringId is 0, then ASSET.
831 @param[in] HiiHandle A handle that was previously registered in the HII Database.
832 @param[in] StringId The identifier of the string to retrieved from the string
833 package associated with HiiHandle.
835 @retval NULL The string specified by StringId is not present in the string package.
836 @retval Other The string was returned.
841 IN EFI_HII_HANDLE HiiHandle
,
842 IN EFI_STRING_ID StringId
849 CHAR8
*SupportedLanguages
;
850 CHAR8
*PlatformLanguage
;
854 ASSERT (HiiHandle
!= NULL
);
855 ASSERT (StringId
!= 0);
858 // Initialize all allocated buffers to NULL
860 SupportedLanguages
= NULL
;
861 PlatformLanguage
= NULL
;
867 // Get the languages that the package specified by HiiHandle supports
869 SupportedLanguages
= GetSupportedLanguages (HiiHandle
);
870 if (SupportedLanguages
== NULL
) {
875 // Get the current platform language setting
877 GetEfiGlobalVariable2 (L
"PlatformLang", (VOID
**)&PlatformLanguage
, NULL
);
880 // Get the best matching language from SupportedLanguages
882 BestLanguage
= GetBestLanguage (
884 FALSE
, // RFC 4646 mode
885 Language
, // Highest priority
886 PlatformLanguage
!= NULL
? PlatformLanguage
: "", // Next highest priority
887 SupportedLanguages
, // Lowest priority
890 if (BestLanguage
== NULL
) {
895 // Retrieve the size of the string in the string package for the BestLanguage
898 Status
= mPrivate
.HiiString
.GetString (
908 // If GetString() returns EFI_SUCCESS for a zero size,
909 // then there are no supported languages registered for HiiHandle. If GetString()
910 // returns an error other than EFI_BUFFER_TOO_SMALL, then HiiHandle is not present
911 // in the HII Database
913 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
918 // Allocate a buffer for the return string
920 String
= AllocateZeroPool (StringSize
);
921 if (String
== NULL
) {
926 // Retrieve the string from the string package
928 Status
= mPrivate
.HiiString
.GetString (
937 if (EFI_ERROR (Status
)) {
939 // Free the buffer and return NULL if the supported languages can not be retrieved.
947 // Free allocated buffers
949 if (SupportedLanguages
!= NULL
) {
950 FreePool (SupportedLanguages
);
952 if (PlatformLanguage
!= NULL
) {
953 FreePool (PlatformLanguage
);
955 if (BestLanguage
!= NULL
) {
956 FreePool (BestLanguage
);
960 // Return the Null-terminated Unicode string
966 This function checks VarOffset and VarWidth is in the block range.
968 @param RequestBlockArray The block array is to be checked.
969 @param VarOffset Offset of var to the structure
970 @param VarWidth Width of var.
971 @param IsNameValueType Whether this varstore is name/value varstore or not.
972 @param HiiHandle Hii handle for this hii package.
974 @retval TRUE This Var is in the block range.
975 @retval FALSE This Var is not in the block range.
979 IN IFR_BLOCK_DATA
*RequestBlockArray
,
982 IN BOOLEAN IsNameValueType
,
983 IN EFI_HII_HANDLE HiiHandle
987 IFR_BLOCK_DATA
*BlockData
;
991 // No Request Block array, all vars are got.
993 if (RequestBlockArray
== NULL
) {
998 // Check the input var is in the request block range.
1000 for (Link
= RequestBlockArray
->Entry
.ForwardLink
; Link
!= &RequestBlockArray
->Entry
; Link
= Link
->ForwardLink
) {
1001 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
1003 if (IsNameValueType
) {
1004 Name
= InternalGetString (HiiHandle
, VarOffset
);
1005 ASSERT (Name
!= NULL
);
1007 if (StrnCmp (BlockData
->Name
, Name
, StrLen (Name
)) == 0) {
1013 if ((VarOffset
>= BlockData
->Offset
) && ((VarOffset
+ VarWidth
) <= (BlockData
->Offset
+ BlockData
->Width
))) {
1023 Get form package data from data base.
1025 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
1026 @param HiiFormPackage The buffer saves the package data.
1027 @param PackageSize The buffer size of the package data.
1031 GetFormPackageData (
1032 IN HII_DATABASE_RECORD
*DataBaseRecord
,
1033 IN OUT UINT8
**HiiFormPackage
,
1034 OUT UINTN
*PackageSize
1041 if (DataBaseRecord
== NULL
|| HiiFormPackage
== NULL
|| PackageSize
== NULL
) {
1042 return EFI_INVALID_PARAMETER
;
1048 // 0. Get Hii Form Package by HiiHandle
1050 Status
= ExportFormPackages (
1052 DataBaseRecord
->Handle
,
1053 DataBaseRecord
->PackageList
,
1059 if (EFI_ERROR (Status
)) {
1063 (*HiiFormPackage
) = AllocatePool (ResultSize
);
1064 if (*HiiFormPackage
== NULL
) {
1065 Status
= EFI_OUT_OF_RESOURCES
;
1070 // Get HiiFormPackage by HiiHandle
1074 Status
= ExportFormPackages (
1076 DataBaseRecord
->Handle
,
1077 DataBaseRecord
->PackageList
,
1083 if (EFI_ERROR (Status
)) {
1084 FreePool (*HiiFormPackage
);
1087 *PackageSize
= Size
;
1094 This function parses Form Package to get the efi varstore info according to the request ConfigHdr.
1096 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
1097 @param ConfigHdr Request string ConfigHdr. If it is NULL,
1098 the first found varstore will be as ConfigHdr.
1099 @param IsEfiVarstore Whether the request storage type is efi varstore type.
1100 @param EfiVarStore The efi varstore info which will return.
1104 IN HII_DATABASE_RECORD
*DataBaseRecord
,
1105 IN EFI_STRING ConfigHdr
,
1106 OUT BOOLEAN
*IsEfiVarstore
,
1107 OUT EFI_IFR_VARSTORE_EFI
**EfiVarStore
1112 UINTN PackageOffset
;
1113 EFI_IFR_OP_HEADER
*IfrOpHdr
;
1114 CHAR16
*VarStoreName
;
1119 UINT8
*HiiFormPackage
;
1121 EFI_IFR_VARSTORE_EFI
*IfrEfiVarStore
;
1122 EFI_HII_PACKAGE_HEADER
*PackageHeader
;
1124 HiiFormPackage
= NULL
;
1126 Status
= EFI_SUCCESS
;
1130 *IsEfiVarstore
= FALSE
;
1132 Status
= GetFormPackageData(DataBaseRecord
, &HiiFormPackage
, &PackageSize
);
1133 if (EFI_ERROR (Status
)) {
1137 IfrOffset
= sizeof (EFI_HII_PACKAGE_HEADER
);
1138 PackageOffset
= IfrOffset
;
1139 PackageHeader
= (EFI_HII_PACKAGE_HEADER
*) HiiFormPackage
;
1141 while (IfrOffset
< PackageSize
) {
1143 // More than one form packages exist.
1145 if (PackageOffset
>= PackageHeader
->Length
) {
1147 // Process the new form package.
1149 PackageOffset
= sizeof (EFI_HII_PACKAGE_HEADER
);
1150 IfrOffset
+= PackageOffset
;
1151 PackageHeader
= (EFI_HII_PACKAGE_HEADER
*) (HiiFormPackage
+ IfrOffset
);
1154 IfrOpHdr
= (EFI_IFR_OP_HEADER
*) (HiiFormPackage
+ IfrOffset
);
1155 IfrOffset
+= IfrOpHdr
->Length
;
1156 PackageOffset
+= IfrOpHdr
->Length
;
1158 if (IfrOpHdr
->OpCode
== EFI_IFR_VARSTORE_EFI_OP
) {
1159 IfrEfiVarStore
= (EFI_IFR_VARSTORE_EFI
*) IfrOpHdr
;
1161 // If the length is small than the structure, this is from old efi
1162 // varstore definition. Old efi varstore get config directly from
1163 // GetVariable function.
1165 if (IfrOpHdr
->Length
< sizeof (EFI_IFR_VARSTORE_EFI
)) {
1169 VarStoreName
= AllocateZeroPool (AsciiStrSize ((CHAR8
*)IfrEfiVarStore
->Name
) * sizeof (CHAR16
));
1170 if (VarStoreName
== NULL
) {
1171 Status
= EFI_OUT_OF_RESOURCES
;
1174 AsciiStrToUnicodeStr ((CHAR8
*) IfrEfiVarStore
->Name
, VarStoreName
);
1176 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*) &IfrEfiVarStore
->Guid
, 1, &GuidStr
);
1177 GenerateSubStr (L
"NAME=", StrLen (VarStoreName
) * sizeof (CHAR16
), (VOID
*) VarStoreName
, 2, &NameStr
);
1178 LengthString
= StrLen (GuidStr
);
1179 LengthString
= LengthString
+ StrLen (NameStr
) + 1;
1180 TempStr
= AllocateZeroPool (LengthString
* sizeof (CHAR16
));
1181 if (TempStr
== NULL
) {
1184 FreePool (VarStoreName
);
1185 Status
= EFI_OUT_OF_RESOURCES
;
1188 StrCpy (TempStr
, GuidStr
);
1189 StrCat (TempStr
, NameStr
);
1190 if (ConfigHdr
== NULL
|| StrnCmp (ConfigHdr
, TempStr
, StrLen (TempStr
)) == 0) {
1191 *EfiVarStore
= (EFI_IFR_VARSTORE_EFI
*) AllocateZeroPool (IfrOpHdr
->Length
);
1192 if (*EfiVarStore
== NULL
) {
1193 FreePool (VarStoreName
);
1197 Status
= EFI_OUT_OF_RESOURCES
;
1200 *IsEfiVarstore
= TRUE
;
1201 CopyMem (*EfiVarStore
, IfrEfiVarStore
, IfrOpHdr
->Length
);
1205 // Free alllocated temp string.
1207 FreePool (VarStoreName
);
1213 // Already found the varstore, break;
1215 if (*IsEfiVarstore
) {
1221 if (HiiFormPackage
!= NULL
) {
1222 FreePool (HiiFormPackage
);
1229 Check whether the ConfigRequest string has the request elements.
1230 For EFI_HII_VARSTORE_BUFFER type, the request has "&OFFSET=****&WIDTH=****..." format.
1231 For EFI_HII_VARSTORE_NAME_VALUE type, the request has "&NAME1**&NAME2..." format.
1233 @param ConfigRequest The input config request string.
1235 @retval TRUE The input include config request elements.
1236 @retval FALSE The input string not includes.
1240 GetElementsFromRequest (
1241 IN EFI_STRING ConfigRequest
1244 EFI_STRING TmpRequest
;
1246 TmpRequest
= StrStr (ConfigRequest
, L
"PATH=");
1247 ASSERT (TmpRequest
!= NULL
);
1249 if ((StrStr (TmpRequest
, L
"&OFFSET=") != NULL
) || (StrStr (TmpRequest
, L
"&") != NULL
)) {
1257 Check whether the this varstore is the request varstore.
1259 @param VarstoreGuid Varstore guid.
1260 @param Name Varstore name.
1261 @param ConfigHdr Current configRequest info.
1263 @retval TRUE This varstore is the requst one.
1264 @retval FALSE This varstore is not the requst one.
1269 IN EFI_GUID
*VarstoreGuid
,
1271 IN CHAR16
*ConfigHdr
1284 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*)VarstoreGuid
, 1, &GuidStr
);
1286 GenerateSubStr (L
"NAME=", StrLen (Name
) * sizeof (CHAR16
), (VOID
*) Name
, 2, &NameStr
);
1288 GenerateSubStr (L
"NAME=", 0, NULL
, 2, &NameStr
);
1290 LengthString
= StrLen (GuidStr
);
1291 LengthString
= LengthString
+ StrLen (NameStr
) + 1;
1292 TempStr
= AllocateZeroPool (LengthString
* sizeof (CHAR16
));
1293 if (TempStr
== NULL
) {
1297 StrCpy (TempStr
, GuidStr
);
1298 StrCat (TempStr
, NameStr
);
1300 if (ConfigHdr
== NULL
|| StrnCmp (ConfigHdr
, TempStr
, StrLen (TempStr
)) == 0) {
1305 if (GuidStr
!= NULL
) {
1309 if (NameStr
!= NULL
) {
1313 if (TempStr
!= NULL
) {
1321 Check whether the this op code is required.
1323 @param RequestBlockArray The array includes all the request info or NULL.
1324 @param HiiHandle The hii handle for this form package.
1325 @param VarStorageData The varstore data strucure.
1326 @param IfrOpHdr Ifr opcode header for this opcode.
1327 @param VarWidth The buffer width for this opcode.
1328 @param ReturnData The data block added for this opcode.
1330 @retval EFI_SUCCESS This opcode is required.
1331 @retval Others This opcode is not required or error occur.
1335 IsThisOpcodeRequired (
1336 IN IFR_BLOCK_DATA
*RequestBlockArray
,
1337 IN EFI_HII_HANDLE HiiHandle
,
1338 IN OUT IFR_VARSTORAGE_DATA
*VarStorageData
,
1339 IN EFI_IFR_OP_HEADER
*IfrOpHdr
,
1341 OUT IFR_BLOCK_DATA
**ReturnData
1344 IFR_BLOCK_DATA
*BlockData
;
1346 EFI_STRING_ID NameId
;
1347 EFI_IFR_QUESTION_HEADER
*IfrQuestionHdr
;
1351 IfrQuestionHdr
= (EFI_IFR_QUESTION_HEADER
*)((CHAR8
*) IfrOpHdr
+ sizeof (EFI_IFR_OP_HEADER
));
1353 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
1354 NameId
= IfrQuestionHdr
->VarStoreInfo
.VarName
;
1357 // Check whether this question is in requested block array.
1359 if (!BlockArrayCheck (RequestBlockArray
, NameId
, 0, TRUE
, HiiHandle
)) {
1361 // This question is not in the requested string. Skip it.
1366 VarOffset
= IfrQuestionHdr
->VarStoreInfo
.VarOffset
;
1369 // Check whether this question is in requested block array.
1371 if (!BlockArrayCheck (RequestBlockArray
, VarOffset
, VarWidth
, FALSE
, HiiHandle
)) {
1373 // This question is not in the requested string. Skip it.
1379 // Check this var question is in the var storage
1381 if (((VarOffset
+ VarWidth
) > VarStorageData
->Size
)) {
1382 return EFI_INVALID_PARAMETER
;
1386 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
1387 if (BlockData
== NULL
) {
1388 return EFI_OUT_OF_RESOURCES
;
1391 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
1392 BlockData
->Name
= InternalGetString(HiiHandle
, NameId
);
1394 BlockData
->Offset
= VarOffset
;
1397 BlockData
->Width
= VarWidth
;
1398 BlockData
->QuestionId
= IfrQuestionHdr
->QuestionId
;
1399 BlockData
->OpCode
= IfrOpHdr
->OpCode
;
1400 BlockData
->Scope
= IfrOpHdr
->Scope
;
1401 InitializeListHead (&BlockData
->DefaultValueEntry
);
1403 // Add Block Data into VarStorageData BlockEntry
1405 InsertBlockData (&VarStorageData
->BlockEntry
, &BlockData
);
1406 *ReturnData
= BlockData
;
1412 This function parses Form Package to get the block array and the default
1413 value array according to the request ConfigHdr.
1415 @param HiiHandle Hii Handle for this hii package.
1416 @param Package Pointer to the form package data.
1417 @param PackageLength Length of the pacakge.
1418 @param ConfigHdr Request string ConfigHdr. If it is NULL,
1419 the first found varstore will be as ConfigHdr.
1420 @param RequestBlockArray The block array is retrieved from the request string.
1421 @param VarStorageData VarStorage structure contains the got block and default value.
1422 @param DefaultIdArray Point to the got default id and default name array.
1424 @retval EFI_SUCCESS The block array and the default value array are got.
1425 @retval EFI_INVALID_PARAMETER The varstore defintion in the differnt form pacakges
1427 @retval EFI_OUT_OF_RESOURCES No enough memory.
1432 IN EFI_HII_HANDLE HiiHandle
,
1434 IN UINT32 PackageLength
,
1435 IN EFI_STRING ConfigHdr
,
1436 IN IFR_BLOCK_DATA
*RequestBlockArray
,
1437 IN OUT IFR_VARSTORAGE_DATA
*VarStorageData
,
1438 OUT IFR_DEFAULT_DATA
*DefaultIdArray
1443 UINTN PackageOffset
;
1444 EFI_IFR_VARSTORE
*IfrVarStore
;
1445 EFI_IFR_VARSTORE_EFI
*IfrEfiVarStore
;
1446 EFI_IFR_OP_HEADER
*IfrOpHdr
;
1447 EFI_IFR_ONE_OF
*IfrOneOf
;
1448 EFI_IFR_REF4
*IfrRef
;
1449 EFI_IFR_ONE_OF_OPTION
*IfrOneOfOption
;
1450 EFI_IFR_DEFAULT
*IfrDefault
;
1451 EFI_IFR_ORDERED_LIST
*IfrOrderedList
;
1452 EFI_IFR_CHECKBOX
*IfrCheckBox
;
1453 EFI_IFR_PASSWORD
*IfrPassword
;
1454 EFI_IFR_STRING
*IfrString
;
1455 EFI_IFR_DATE
*IfrDate
;
1456 EFI_IFR_TIME
*IfrTime
;
1457 IFR_DEFAULT_DATA DefaultData
;
1458 IFR_DEFAULT_DATA
*DefaultDataPtr
;
1459 IFR_BLOCK_DATA
*BlockData
;
1460 CHAR16
*VarStoreName
;
1462 UINT16 VarDefaultId
;
1463 BOOLEAN FirstOneOfOption
;
1464 LIST_ENTRY
*LinkData
;
1465 LIST_ENTRY
*LinkDefault
;
1466 EFI_IFR_VARSTORE_NAME_VALUE
*IfrNameValueVarStore
;
1467 EFI_HII_PACKAGE_HEADER
*PackageHeader
;
1468 EFI_VARSTORE_ID VarStoreId
;
1470 Status
= EFI_SUCCESS
;
1472 DefaultDataPtr
= NULL
;
1473 FirstOneOfOption
= FALSE
;
1475 ZeroMem (&DefaultData
, sizeof (IFR_DEFAULT_DATA
));
1478 // Go through the form package to parse OpCode one by one.
1480 PackageOffset
= sizeof (EFI_HII_PACKAGE_HEADER
);
1481 PackageHeader
= (EFI_HII_PACKAGE_HEADER
*) Package
;
1482 IfrOffset
= PackageOffset
;
1483 while (IfrOffset
< PackageLength
) {
1486 // More than one form package found.
1488 if (PackageOffset
>= PackageHeader
->Length
) {
1490 // Already found varstore for this request, break;
1492 if (VarStoreId
!= 0) {
1497 // Get next package header info.
1499 IfrOffset
+= sizeof (EFI_HII_PACKAGE_HEADER
);
1500 PackageOffset
= sizeof (EFI_HII_PACKAGE_HEADER
);
1501 PackageHeader
= (EFI_HII_PACKAGE_HEADER
*) (Package
+ IfrOffset
);
1504 IfrOpHdr
= (EFI_IFR_OP_HEADER
*) (Package
+ IfrOffset
);
1505 switch (IfrOpHdr
->OpCode
) {
1506 case EFI_IFR_VARSTORE_OP
:
1508 // VarStore is found. Don't need to search any more.
1510 if (VarStoreId
!= 0) {
1514 IfrVarStore
= (EFI_IFR_VARSTORE
*) IfrOpHdr
;
1516 VarStoreName
= AllocateZeroPool (AsciiStrSize ((CHAR8
*)IfrVarStore
->Name
) * sizeof (CHAR16
));
1517 if (VarStoreName
== NULL
) {
1518 Status
= EFI_OUT_OF_RESOURCES
;
1521 AsciiStrToUnicodeStr ((CHAR8
*)IfrVarStore
->Name
, VarStoreName
);
1523 if (IsThisVarstore((VOID
*)&IfrVarStore
->Guid
, VarStoreName
, ConfigHdr
)) {
1525 // Find the matched VarStore
1527 CopyGuid (&VarStorageData
->Guid
, (EFI_GUID
*) (VOID
*) &IfrVarStore
->Guid
);
1528 VarStorageData
->Size
= IfrVarStore
->Size
;
1529 VarStorageData
->Name
= VarStoreName
;
1530 VarStorageData
->Type
= EFI_HII_VARSTORE_BUFFER
;
1531 VarStoreId
= IfrVarStore
->VarStoreId
;
1535 case EFI_IFR_VARSTORE_EFI_OP
:
1537 // VarStore is found. Don't need to search any more.
1539 if (VarStoreId
!= 0) {
1543 IfrEfiVarStore
= (EFI_IFR_VARSTORE_EFI
*) IfrOpHdr
;
1546 // If the length is small than the structure, this is from old efi
1547 // varstore definition. Old efi varstore get config directly from
1548 // GetVariable function.
1550 if (IfrOpHdr
->Length
< sizeof (EFI_IFR_VARSTORE_EFI
)) {
1554 VarStoreName
= AllocateZeroPool (AsciiStrSize ((CHAR8
*)IfrEfiVarStore
->Name
) * sizeof (CHAR16
));
1555 if (VarStoreName
== NULL
) {
1556 Status
= EFI_OUT_OF_RESOURCES
;
1559 AsciiStrToUnicodeStr ((CHAR8
*)IfrEfiVarStore
->Name
, VarStoreName
);
1561 if (IsThisVarstore (&IfrEfiVarStore
->Guid
, VarStoreName
, ConfigHdr
)) {
1563 // Find the matched VarStore
1565 CopyGuid (&VarStorageData
->Guid
, (EFI_GUID
*) (VOID
*) &IfrEfiVarStore
->Guid
);
1566 VarStorageData
->Size
= IfrEfiVarStore
->Size
;
1567 VarStorageData
->Name
= VarStoreName
;
1568 VarStorageData
->Type
= EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
;
1569 VarStoreId
= IfrEfiVarStore
->VarStoreId
;
1573 case EFI_IFR_VARSTORE_NAME_VALUE_OP
:
1575 // VarStore is found. Don't need to search any more.
1577 if (VarStoreId
!= 0) {
1581 IfrNameValueVarStore
= (EFI_IFR_VARSTORE_NAME_VALUE
*) IfrOpHdr
;
1583 if (IsThisVarstore (&IfrNameValueVarStore
->Guid
, NULL
, ConfigHdr
)) {
1585 // Find the matched VarStore
1587 CopyGuid (&VarStorageData
->Guid
, (EFI_GUID
*) (VOID
*) &IfrNameValueVarStore
->Guid
);
1588 VarStorageData
->Type
= EFI_HII_VARSTORE_NAME_VALUE
;
1589 VarStoreId
= IfrNameValueVarStore
->VarStoreId
;
1593 case EFI_IFR_DEFAULTSTORE_OP
:
1595 // Add new the map between default id and default name.
1597 DefaultDataPtr
= (IFR_DEFAULT_DATA
*) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
1598 if (DefaultDataPtr
== NULL
) {
1599 Status
= EFI_OUT_OF_RESOURCES
;
1602 DefaultDataPtr
->DefaultId
= ((EFI_IFR_DEFAULTSTORE
*) IfrOpHdr
)->DefaultId
;
1603 InsertTailList (&DefaultIdArray
->Entry
, &DefaultDataPtr
->Entry
);
1604 DefaultDataPtr
= NULL
;
1607 case EFI_IFR_FORM_OP
:
1608 case EFI_IFR_FORM_MAP_OP
:
1610 // No matched varstore is found and directly return.
1612 if ( VarStoreId
== 0) {
1613 Status
= EFI_SUCCESS
;
1618 case EFI_IFR_REF_OP
:
1620 // Ref question is not in IFR Form. This IFR form is not valid.
1622 if ( VarStoreId
== 0) {
1623 Status
= EFI_INVALID_PARAMETER
;
1627 // Check whether this question is for the requested varstore.
1629 IfrRef
= (EFI_IFR_REF4
*) IfrOpHdr
;
1630 if (IfrRef
->Question
.VarStoreId
!= VarStoreId
) {
1633 VarWidth
= (UINT16
) (sizeof (EFI_HII_REF
));
1635 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
1636 if (EFI_ERROR (Status
)) {
1641 case EFI_IFR_ONE_OF_OP
:
1642 case EFI_IFR_NUMERIC_OP
:
1644 // Numeric and OneOf has the same opcode structure.
1648 // Numeric and OneOf question is not in IFR Form. This IFR form is not valid.
1650 if (VarStoreId
== 0) {
1651 Status
= EFI_INVALID_PARAMETER
;
1655 // Check whether this question is for the requested varstore.
1657 IfrOneOf
= (EFI_IFR_ONE_OF
*) IfrOpHdr
;
1658 if (IfrOneOf
->Question
.VarStoreId
!= VarStoreId
) {
1661 VarWidth
= (UINT16
) (1 << (IfrOneOf
->Flags
& EFI_IFR_NUMERIC_SIZE
));
1663 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
1664 if (EFI_ERROR (Status
)) {
1668 if (BlockData
== NULL
) {
1670 // BlockData == NULL means this opcode is not in the requst array.
1675 if (IfrOpHdr
->OpCode
== EFI_IFR_ONE_OF_OP
) {
1677 // Set this flag to TRUE for the first oneof option.
1679 FirstOneOfOption
= TRUE
;
1680 } else if (IfrOpHdr
->OpCode
== EFI_IFR_NUMERIC_OP
) {
1682 // Numeric minimum value will be used as default value when no default is specified.
1684 DefaultData
.Type
= DefaultValueFromDefault
;
1685 switch (IfrOneOf
->Flags
& EFI_IFR_NUMERIC_SIZE
) {
1686 case EFI_IFR_NUMERIC_SIZE_1
:
1687 DefaultData
.Value
.u8
= IfrOneOf
->data
.u8
.MinValue
;
1690 case EFI_IFR_NUMERIC_SIZE_2
:
1691 CopyMem (&DefaultData
.Value
.u16
, &IfrOneOf
->data
.u16
.MinValue
, sizeof (UINT16
));
1694 case EFI_IFR_NUMERIC_SIZE_4
:
1695 CopyMem (&DefaultData
.Value
.u32
, &IfrOneOf
->data
.u32
.MinValue
, sizeof (UINT32
));
1698 case EFI_IFR_NUMERIC_SIZE_8
:
1699 CopyMem (&DefaultData
.Value
.u64
, &IfrOneOf
->data
.u64
.MinValue
, sizeof (UINT64
));
1703 Status
= EFI_INVALID_PARAMETER
;
1707 // Set default value base on the DefaultId list get from IFR data.
1709 for (LinkData
= DefaultIdArray
->Entry
.ForwardLink
; LinkData
!= &DefaultIdArray
->Entry
; LinkData
= LinkData
->ForwardLink
) {
1710 DefaultDataPtr
= BASE_CR (LinkData
, IFR_DEFAULT_DATA
, Entry
);
1711 DefaultData
.DefaultId
= DefaultDataPtr
->DefaultId
;
1712 InsertDefaultValue (BlockData
, &DefaultData
);
1717 case EFI_IFR_ORDERED_LIST_OP
:
1719 // offset by question header
1720 // width by EFI_IFR_ORDERED_LIST MaxContainers * OneofOption Type
1721 // no default value and default id, how to define its default value?
1725 // OrderedList question is not in IFR Form. This IFR form is not valid.
1727 if (VarStoreId
== 0) {
1728 Status
= EFI_INVALID_PARAMETER
;
1732 // Check whether this question is for the requested varstore.
1734 IfrOrderedList
= (EFI_IFR_ORDERED_LIST
*) IfrOpHdr
;
1735 if (IfrOrderedList
->Question
.VarStoreId
!= VarStoreId
) {
1739 VarWidth
= IfrOrderedList
->MaxContainers
;
1740 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
1741 if (EFI_ERROR (Status
)) {
1746 case EFI_IFR_CHECKBOX_OP
:
1748 // EFI_IFR_DEFAULT_OP
1749 // offset by question header
1750 // width is 1 sizeof (BOOLEAN)
1751 // default id by CheckBox Flags if CheckBox flags (Default or Mau) is set, the default value is 1 to be set.
1752 // value by DefaultOption
1753 // default id by DeaultOption DefaultId can override CheckBox Flags and Default value.
1757 // CheckBox question is not in IFR Form. This IFR form is not valid.
1759 if (VarStoreId
== 0) {
1760 Status
= EFI_INVALID_PARAMETER
;
1764 // Check whether this question is for the requested varstore.
1766 IfrCheckBox
= (EFI_IFR_CHECKBOX
*) IfrOpHdr
;
1767 if (IfrCheckBox
->Question
.VarStoreId
!= VarStoreId
) {
1770 VarWidth
= (UINT16
) sizeof (BOOLEAN
);
1771 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
1772 if (EFI_ERROR (Status
)) {
1776 if (BlockData
== NULL
) {
1778 // BlockData == NULL means this opcode is not in the requst array.
1784 // Add default value for standard ID by CheckBox Flag
1786 VarDefaultId
= EFI_HII_DEFAULT_CLASS_STANDARD
;
1788 // Prepare new DefaultValue
1790 DefaultData
.DefaultId
= VarDefaultId
;
1791 if ((IfrCheckBox
->Flags
& EFI_IFR_CHECKBOX_DEFAULT
) == EFI_IFR_CHECKBOX_DEFAULT
) {
1793 // When flag is set, defautl value is TRUE.
1795 DefaultData
.Type
= DefaultValueFromFlag
;
1796 DefaultData
.Value
.b
= TRUE
;
1799 // When flag is not set, defautl value is FASLE.
1801 DefaultData
.Type
= DefaultValueFromDefault
;
1802 DefaultData
.Value
.b
= FALSE
;
1805 // Add DefaultValue into current BlockData
1807 InsertDefaultValue (BlockData
, &DefaultData
);
1810 // Add default value for Manufacture ID by CheckBox Flag
1812 VarDefaultId
= EFI_HII_DEFAULT_CLASS_MANUFACTURING
;
1814 // Prepare new DefaultValue
1816 DefaultData
.DefaultId
= VarDefaultId
;
1817 if ((IfrCheckBox
->Flags
& EFI_IFR_CHECKBOX_DEFAULT_MFG
) == EFI_IFR_CHECKBOX_DEFAULT_MFG
) {
1819 // When flag is set, defautl value is TRUE.
1821 DefaultData
.Type
= DefaultValueFromFlag
;
1822 DefaultData
.Value
.b
= TRUE
;
1825 // When flag is not set, defautl value is FASLE.
1827 DefaultData
.Type
= DefaultValueFromDefault
;
1828 DefaultData
.Value
.b
= FALSE
;
1831 // Add DefaultValue into current BlockData
1833 InsertDefaultValue (BlockData
, &DefaultData
);
1836 case EFI_IFR_DATE_OP
:
1838 // offset by question header
1839 // width MaxSize * sizeof (CHAR16)
1840 // no default value, only block array
1844 // Date question is not in IFR Form. This IFR form is not valid.
1846 if (VarStoreId
== 0) {
1847 Status
= EFI_INVALID_PARAMETER
;
1851 // Check whether this question is for the requested varstore.
1853 IfrDate
= (EFI_IFR_DATE
*) IfrOpHdr
;
1854 if (IfrDate
->Question
.VarStoreId
!= VarStoreId
) {
1858 VarWidth
= (UINT16
) sizeof (EFI_HII_DATE
);
1859 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
1860 if (EFI_ERROR (Status
)) {
1865 case EFI_IFR_TIME_OP
:
1867 // offset by question header
1868 // width MaxSize * sizeof (CHAR16)
1869 // no default value, only block array
1873 // Time question is not in IFR Form. This IFR form is not valid.
1875 if (VarStoreId
== 0) {
1876 Status
= EFI_INVALID_PARAMETER
;
1880 // Check whether this question is for the requested varstore.
1882 IfrTime
= (EFI_IFR_TIME
*) IfrOpHdr
;
1883 if (IfrTime
->Question
.VarStoreId
!= VarStoreId
) {
1887 VarWidth
= (UINT16
) sizeof (EFI_HII_TIME
);
1888 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
1889 if (EFI_ERROR (Status
)) {
1894 case EFI_IFR_STRING_OP
:
1896 // offset by question header
1897 // width MaxSize * sizeof (CHAR16)
1898 // no default value, only block array
1902 // String question is not in IFR Form. This IFR form is not valid.
1904 if (VarStoreId
== 0) {
1905 Status
= EFI_INVALID_PARAMETER
;
1909 // Check whether this question is for the requested varstore.
1911 IfrString
= (EFI_IFR_STRING
*) IfrOpHdr
;
1912 if (IfrString
->Question
.VarStoreId
!= VarStoreId
) {
1916 VarWidth
= (UINT16
) (IfrString
->MaxSize
* sizeof (UINT16
));
1917 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
1918 if (EFI_ERROR (Status
)) {
1923 // No default value for string.
1928 case EFI_IFR_PASSWORD_OP
:
1930 // offset by question header
1931 // width MaxSize * sizeof (CHAR16)
1932 // no default value, only block array
1936 // Password question is not in IFR Form. This IFR form is not valid.
1938 if (VarStoreId
== 0) {
1939 Status
= EFI_INVALID_PARAMETER
;
1943 // Check whether this question is for the requested varstore.
1945 IfrPassword
= (EFI_IFR_PASSWORD
*) IfrOpHdr
;
1946 if (IfrPassword
->Question
.VarStoreId
!= VarStoreId
) {
1950 VarWidth
= (UINT16
) (IfrPassword
->MaxSize
* sizeof (UINT16
));
1951 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
1952 if (EFI_ERROR (Status
)) {
1957 // No default value for string.
1962 case EFI_IFR_ONE_OF_OPTION_OP
:
1964 // No matched block data is ignored.
1966 if (BlockData
== NULL
|| BlockData
->Scope
== 0) {
1970 IfrOneOfOption
= (EFI_IFR_ONE_OF_OPTION
*) IfrOpHdr
;
1971 if (BlockData
->OpCode
== EFI_IFR_ORDERED_LIST_OP
) {
1973 // Get ordered list option data type.
1975 if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_8
|| IfrOneOfOption
->Type
== EFI_IFR_TYPE_BOOLEAN
) {
1977 } else if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_16
) {
1979 } else if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_32
) {
1981 } else if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_64
) {
1985 // Invalid ordered list option data type.
1987 Status
= EFI_INVALID_PARAMETER
;
1988 if (BlockData
->Name
!= NULL
) {
1989 FreePool (BlockData
->Name
);
1991 FreePool (BlockData
);
1996 // Calculate Ordered list QuestionId width.
1998 BlockData
->Width
= (UINT16
) (BlockData
->Width
* VarWidth
);
2000 // Check whether this question is in requested block array.
2002 if (!BlockArrayCheck (RequestBlockArray
, BlockData
->Offset
, BlockData
->Width
, (BOOLEAN
)(BlockData
->Name
!= NULL
), HiiHandle
)) {
2004 // This question is not in the requested string. Skip it.
2006 if (BlockData
->Name
!= NULL
) {
2007 FreePool (BlockData
->Name
);
2009 FreePool (BlockData
);
2014 // Check this var question is in the var storage
2016 if ((BlockData
->Name
== NULL
) && ((BlockData
->Offset
+ BlockData
->Width
) > VarStorageData
->Size
)) {
2017 Status
= EFI_INVALID_PARAMETER
;
2018 if (BlockData
->Name
!= NULL
) {
2019 FreePool (BlockData
->Name
);
2021 FreePool (BlockData
);
2025 // Add Block Data into VarStorageData BlockEntry
2027 InsertBlockData (&VarStorageData
->BlockEntry
, &BlockData
);
2029 // No default data for OrderedList.
2036 // 1. Set default value for OneOf option when flag field has default attribute.
2038 if (((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT
) == EFI_IFR_OPTION_DEFAULT
) ||
2039 ((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT_MFG
) == EFI_IFR_OPTION_DEFAULT_MFG
)) {
2041 // This flag is used to specify whether this option is the first. Set it to FALSE for the following options.
2042 // The first oneof option value will be used as default value when no default value is specified.
2044 FirstOneOfOption
= FALSE
;
2046 // Prepare new DefaultValue
2048 DefaultData
.Type
= DefaultValueFromFlag
;
2049 CopyMem (&DefaultData
.Value
, &IfrOneOfOption
->Value
, IfrOneOfOption
->Header
.Length
- OFFSET_OF (EFI_IFR_ONE_OF_OPTION
, Value
));
2050 if ((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT
) == EFI_IFR_OPTION_DEFAULT
) {
2051 DefaultData
.DefaultId
= EFI_HII_DEFAULT_CLASS_STANDARD
;
2052 InsertDefaultValue (BlockData
, &DefaultData
);
2054 if ((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT_MFG
) == EFI_IFR_OPTION_DEFAULT_MFG
) {
2055 DefaultData
.DefaultId
= EFI_HII_DEFAULT_CLASS_MANUFACTURING
;
2056 InsertDefaultValue (BlockData
, &DefaultData
);
2061 // 2. Set as the default value when this is the first option.
2062 // The first oneof option value will be used as default value when no default value is specified.
2064 if (FirstOneOfOption
) {
2065 // This flag is used to specify whether this option is the first. Set it to FALSE for the following options.
2066 FirstOneOfOption
= FALSE
;
2069 // Prepare new DefaultValue
2071 DefaultData
.Type
= DefaultValueFromDefault
;
2072 CopyMem (&DefaultData
.Value
, &IfrOneOfOption
->Value
, IfrOneOfOption
->Header
.Length
- OFFSET_OF (EFI_IFR_ONE_OF_OPTION
, Value
));
2073 for (LinkData
= DefaultIdArray
->Entry
.ForwardLink
; LinkData
!= &DefaultIdArray
->Entry
; LinkData
= LinkData
->ForwardLink
) {
2074 DefaultDataPtr
= BASE_CR (LinkData
, IFR_DEFAULT_DATA
, Entry
);
2075 DefaultData
.DefaultId
= DefaultDataPtr
->DefaultId
;
2076 InsertDefaultValue (BlockData
, &DefaultData
);
2081 case EFI_IFR_DEFAULT_OP
:
2083 // Update Current BlockData to the default value.
2085 if (BlockData
== NULL
|| BlockData
->Scope
== 0) {
2087 // No matched block data is ignored.
2092 if (BlockData
->OpCode
== EFI_IFR_ORDERED_LIST_OP
) {
2094 // OrderedList Opcode is no default value.
2099 // Get the DefaultId
2101 IfrDefault
= (EFI_IFR_DEFAULT
*) IfrOpHdr
;
2102 VarDefaultId
= IfrDefault
->DefaultId
;
2104 // Prepare new DefaultValue
2106 DefaultData
.Type
= DefaultValueFromOpcode
;
2107 DefaultData
.DefaultId
= VarDefaultId
;
2108 CopyMem (&DefaultData
.Value
, &IfrDefault
->Value
, IfrDefault
->Header
.Length
- OFFSET_OF (EFI_IFR_DEFAULT
, Value
));
2110 // If the value field is expression, set the cleaned flag.
2111 if (IfrDefault
->Type
== EFI_IFR_TYPE_OTHER
) {
2112 DefaultData
.Cleaned
= TRUE
;
2115 // Add DefaultValue into current BlockData
2117 InsertDefaultValue (BlockData
, &DefaultData
);
2120 // After insert the default value, reset the cleaned value for next
2121 // time used. If not set here, need to set the value before everytime
2124 DefaultData
.Cleaned
= FALSE
;
2127 case EFI_IFR_END_OP
:
2129 // End Opcode is for Var question.
2131 if (BlockData
!= NULL
&& BlockData
->Scope
> 0) {
2137 if (BlockData
!= NULL
&& BlockData
->Scope
> 0) {
2138 BlockData
->Scope
= (UINT8
) (BlockData
->Scope
+ IfrOpHdr
->Scope
);
2143 IfrOffset
+= IfrOpHdr
->Length
;
2144 PackageOffset
+= IfrOpHdr
->Length
;
2148 for (LinkData
= VarStorageData
->BlockEntry
.ForwardLink
; LinkData
!= &VarStorageData
->BlockEntry
; LinkData
= LinkData
->ForwardLink
) {
2149 BlockData
= BASE_CR (LinkData
, IFR_BLOCK_DATA
, Entry
);
2150 for (LinkDefault
= BlockData
->DefaultValueEntry
.ForwardLink
; LinkDefault
!= &BlockData
->DefaultValueEntry
; ) {
2151 DefaultDataPtr
= BASE_CR (LinkDefault
, IFR_DEFAULT_DATA
, Entry
);
2152 LinkDefault
= LinkDefault
->ForwardLink
;
2153 if (DefaultDataPtr
->Cleaned
== TRUE
) {
2154 RemoveEntryList (&DefaultDataPtr
->Entry
);
2155 FreePool (DefaultDataPtr
);
2164 parse the configrequest string, get the elements.
2166 @param ConfigRequest The input configrequest string.
2167 @param Progress Return the progress data.
2169 @retval Block data pointer.
2173 IN EFI_STRING ConfigRequest
,
2174 OUT EFI_STRING
*Progress
2177 EFI_STRING StringPtr
;
2178 IFR_BLOCK_DATA
*BlockData
;
2179 IFR_BLOCK_DATA
*RequestBlockArray
;
2185 IFR_BLOCK_DATA
*NextBlockData
;
2189 // Init RequestBlockArray
2191 RequestBlockArray
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
2192 if (RequestBlockArray
== NULL
) {
2195 InitializeListHead (&RequestBlockArray
->Entry
);
2198 // Get the request Block array from the request string
2203 // Parse each <RequestElement> if exists
2204 // Only <BlockName> format is supported by this help function.
2205 // <BlockName> ::= &'OFFSET='<Number>&'WIDTH='<Number>
2207 StringPtr
= ConfigRequest
;
2208 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) == 0) {
2210 // Skip the OFFSET string
2212 *Progress
= StringPtr
;
2213 StringPtr
+= StrLen (L
"&OFFSET=");
2217 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
2218 if (EFI_ERROR (Status
)) {
2225 (((Length
+ 1) / 2) < sizeof (UINT16
)) ? ((Length
+ 1) / 2) : sizeof (UINT16
)
2227 FreePool (TmpBuffer
);
2229 StringPtr
+= Length
;
2230 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
2233 StringPtr
+= StrLen (L
"&WIDTH=");
2238 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
2239 if (EFI_ERROR (Status
)) {
2246 (((Length
+ 1) / 2) < sizeof (UINT16
)) ? ((Length
+ 1) / 2) : sizeof (UINT16
)
2248 FreePool (TmpBuffer
);
2250 StringPtr
+= Length
;
2251 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
2258 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
2259 if (BlockData
== NULL
) {
2262 BlockData
->Offset
= Offset
;
2263 BlockData
->Width
= Width
;
2264 InsertBlockData (&RequestBlockArray
->Entry
, &BlockData
);
2267 // Skip &VALUE string if &VALUE does exists.
2269 if (StrnCmp (StringPtr
, L
"&VALUE=", StrLen (L
"&VALUE=")) == 0) {
2270 StringPtr
+= StrLen (L
"&VALUE=");
2275 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
2276 if (EFI_ERROR (Status
)) {
2280 StringPtr
+= Length
;
2281 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
2286 // If '\0', parsing is finished.
2288 if (*StringPtr
== 0) {
2294 // Merge the requested block data.
2296 Link
= RequestBlockArray
->Entry
.ForwardLink
;
2297 while ((Link
!= &RequestBlockArray
->Entry
) && (Link
->ForwardLink
!= &RequestBlockArray
->Entry
)) {
2298 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
2299 NextBlockData
= BASE_CR (Link
->ForwardLink
, IFR_BLOCK_DATA
, Entry
);
2300 if ((NextBlockData
->Offset
>= BlockData
->Offset
) && (NextBlockData
->Offset
<= (BlockData
->Offset
+ BlockData
->Width
))) {
2301 if ((NextBlockData
->Offset
+ NextBlockData
->Width
) > (BlockData
->Offset
+ BlockData
->Width
)) {
2302 BlockData
->Width
= (UINT16
) (NextBlockData
->Offset
+ NextBlockData
->Width
- BlockData
->Offset
);
2304 RemoveEntryList (Link
->ForwardLink
);
2305 FreePool (NextBlockData
);
2308 Link
= Link
->ForwardLink
;
2311 return RequestBlockArray
;
2314 if (RequestBlockArray
!= NULL
) {
2316 // Free Link Array RequestBlockArray
2318 while (!IsListEmpty (&RequestBlockArray
->Entry
)) {
2319 BlockData
= BASE_CR (RequestBlockArray
->Entry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
2320 RemoveEntryList (&BlockData
->Entry
);
2321 FreePool (BlockData
);
2324 FreePool (RequestBlockArray
);
2331 parse the configrequest string, get the elements.
2333 @param ConfigRequest The input config request string.
2334 @param Progress Return the progress data.
2336 @retval return data block array.
2340 IN EFI_STRING ConfigRequest
,
2341 OUT EFI_STRING
*Progress
2344 EFI_STRING StringPtr
;
2346 IFR_BLOCK_DATA
*BlockData
;
2347 IFR_BLOCK_DATA
*RequestBlockArray
;
2350 StringPtr
= ConfigRequest
;
2353 // Init RequestBlockArray
2355 RequestBlockArray
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
2356 if (RequestBlockArray
== NULL
) {
2359 InitializeListHead (&RequestBlockArray
->Entry
);
2362 // Get the request Block array from the request string
2366 // Parse each <RequestElement> if exists
2367 // Only <BlockName> format is supported by this help function.
2368 // <BlockName> ::= &'Name***=***
2370 while (StringPtr
!= NULL
&& *StringPtr
== L
'&') {
2372 *Progress
= StringPtr
;
2374 // Skip the L"&" string
2379 if ((NextTag
= StrStr (StringPtr
, L
"=")) != NULL
) {
2382 } else if ((NextTag
= StrStr (StringPtr
, L
"&")) != NULL
) {
2389 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
2390 if (BlockData
== NULL
) {
2397 BlockData
->Name
= AllocateCopyPool(StrSize (StringPtr
), StringPtr
);
2398 InsertBlockData (&RequestBlockArray
->Entry
, &BlockData
);
2402 // If has value, skip the value.
2404 StringPtr
= NextTag
+ 1;
2406 StringPtr
= StrStr (StringPtr
, L
"&");
2407 } else if (NextTag
!= NULL
) {
2409 // restore the '&' text.
2411 StringPtr
= NextTag
;
2416 return RequestBlockArray
;
2419 if (RequestBlockArray
!= NULL
) {
2421 // Free Link Array RequestBlockArray
2423 while (!IsListEmpty (&RequestBlockArray
->Entry
)) {
2424 BlockData
= BASE_CR (RequestBlockArray
->Entry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
2425 RemoveEntryList (&BlockData
->Entry
);
2426 if (BlockData
->Name
!= NULL
) {
2427 FreePool (BlockData
->Name
);
2429 FreePool (BlockData
);
2432 FreePool (RequestBlockArray
);
2439 Generate ConfigRequest string base on the varstore info.
2441 @param ConfigHdr The config header for this varstore.
2442 @param VarStorageData The varstore info.
2443 @param Status Return Status.
2444 @param ConfigRequest The ConfigRequest info may be return.
2446 @retval TRUE Need to continue
2447 @retval Others NO need to continue or error occur.
2450 GenerateConfigRequest (
2451 IN CHAR16
*ConfigHdr
,
2452 IN IFR_VARSTORAGE_DATA
*VarStorageData
,
2453 OUT EFI_STATUS
*Status
,
2454 IN OUT EFI_STRING
*ConfigRequest
2460 CHAR16
*FullConfigRequest
;
2462 IFR_BLOCK_DATA
*BlockData
;
2465 // Append VarStorageData BlockEntry into *Request string
2466 // Now support only one varstore in a form package.
2470 // Go through all VarStorageData Entry and get BlockEntry for each one for the multiple varstore in a single form package
2471 // Then construct them all to return MultiRequest string : ConfigHdr BlockConfig
2475 // Compute the length of the entire request starting with <ConfigHdr> and a
2479 Length
= StrLen (ConfigHdr
) + 1;
2481 for (Link
= VarStorageData
->BlockEntry
.ForwardLink
; Link
!= &VarStorageData
->BlockEntry
; Link
= Link
->ForwardLink
) {
2483 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
2484 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2486 // Add <BlockName> length for each Name
2488 // <BlockName> ::= &Name1&Name2&...
2489 // |1| StrLen(Name1)
2491 Length
= Length
+ (1 + StrLen (BlockData
->Name
));
2494 // Add <BlockName> length for each Offset/Width pair
2496 // <BlockName> ::= &OFFSET=1234&WIDTH=1234
2497 // | 8 | 4 | 7 | 4 |
2499 Length
= Length
+ (8 + 4 + 7 + 4);
2503 // No any request block data is found. The request string can't be constructed.
2506 *Status
= EFI_SUCCESS
;
2511 // Allocate buffer for the entire <ConfigRequest>
2513 FullConfigRequest
= AllocateZeroPool (Length
* sizeof (CHAR16
));
2514 if (FullConfigRequest
== NULL
) {
2515 *Status
= EFI_OUT_OF_RESOURCES
;
2518 StringPtr
= FullConfigRequest
;
2521 // Start with <ConfigHdr>
2523 StrCpy (StringPtr
, ConfigHdr
);
2524 StringPtr
+= StrLen (StringPtr
);
2527 // Loop through all the Offset/Width pairs and append them to ConfigRequest
2529 for (Link
= VarStorageData
->BlockEntry
.ForwardLink
; Link
!= &VarStorageData
->BlockEntry
; Link
= Link
->ForwardLink
) {
2530 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
2531 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2537 (1 + StrLen (BlockData
->Name
) + 1) * sizeof (CHAR16
),
2543 // Append &OFFSET=XXXX&WIDTH=YYYY\0
2547 (8 + 4 + 7 + 4 + 1) * sizeof (CHAR16
),
2548 L
"&OFFSET=%04X&WIDTH=%04X",
2553 StringPtr
+= StrLen (StringPtr
);
2556 // Set to the got full request string.
2558 HiiToLower (FullConfigRequest
);
2560 if (*ConfigRequest
!= NULL
) {
2561 FreePool (*ConfigRequest
);
2563 *ConfigRequest
= FullConfigRequest
;
2569 Generate ConfigRequest Header base on the varstore info.
2571 @param VarStorageData The varstore info.
2572 @param DevicePath Device path for this varstore.
2573 @param ConfigHdr The config header for this varstore.
2575 @retval EFI_SUCCESS Generate the header success.
2576 @retval EFI_OUT_OF_RESOURCES Allocate buffer fail.
2580 IN IFR_VARSTORAGE_DATA
*VarStorageData
,
2581 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
2582 OUT EFI_STRING
*ConfigHdr
2591 Status
= EFI_SUCCESS
;
2597 // Construct <ConfigHdr> : "GUID=...&NAME=...&PATH=..." by VarStorageData Guid, Name and DriverHandle
2599 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*) &VarStorageData
->Guid
, 1, &GuidStr
);
2600 if (VarStorageData
->Name
!= NULL
) {
2601 GenerateSubStr (L
"NAME=", StrLen (VarStorageData
->Name
) * sizeof (CHAR16
), (VOID
*) VarStorageData
->Name
, 2, &NameStr
);
2603 GenerateSubStr (L
"NAME=", 0, NULL
, 2, &NameStr
);
2607 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) DevicePath
),
2608 (VOID
*) DevicePath
,
2612 Length
= StrLen (GuidStr
) + StrLen (NameStr
) + StrLen (PathStr
) + 1;
2613 if (VarStorageData
->Name
== NULL
) {
2617 *ConfigHdr
= AllocateZeroPool (Length
* sizeof (CHAR16
));
2618 if (*ConfigHdr
== NULL
) {
2619 Status
= EFI_OUT_OF_RESOURCES
;
2622 StrCpy (*ConfigHdr
, GuidStr
);
2623 StrCat (*ConfigHdr
, NameStr
);
2624 if (VarStorageData
->Name
== NULL
) {
2625 StrCat (*ConfigHdr
, L
"&");
2627 StrCat (*ConfigHdr
, PathStr
);
2630 // Remove the last character L'&'
2632 *(*ConfigHdr
+ StrLen (*ConfigHdr
) - 1) = L
'\0';
2635 if (GuidStr
!= NULL
) {
2639 if (NameStr
!= NULL
) {
2643 if (PathStr
!= NULL
) {
2651 Get Data buffer size based on data type.
2653 @param ValueType The input data type.
2655 @retval The data buffer size for the input type.
2662 UINT16 StorageWidth
;
2664 switch (ValueType
) {
2665 case EFI_IFR_NUMERIC_SIZE_1
:
2666 case EFI_IFR_TYPE_BOOLEAN
:
2667 StorageWidth
= (UINT16
) sizeof (UINT8
);
2670 case EFI_IFR_NUMERIC_SIZE_2
:
2671 StorageWidth
= (UINT16
) sizeof (UINT16
);
2674 case EFI_IFR_NUMERIC_SIZE_4
:
2675 StorageWidth
= (UINT16
) sizeof (UINT32
);
2678 case EFI_IFR_NUMERIC_SIZE_8
:
2679 StorageWidth
= (UINT16
) sizeof (UINT64
);
2682 case EFI_IFR_TYPE_TIME
:
2683 StorageWidth
= (UINT16
) sizeof (EFI_IFR_TIME
);
2686 case EFI_IFR_TYPE_DATE
:
2687 StorageWidth
= (UINT16
) sizeof (EFI_IFR_DATE
);
2695 return StorageWidth
;
2699 Generate ConfigAltResp string base on the varstore info.
2701 @param ConfigHdr The config header for this varstore.
2702 @param VarStorageData The varstore info.
2703 @param DefaultIdArray The Default id array.
2704 @param DefaultAltCfgResp The DefaultAltCfgResp info may be return.
2706 @retval TRUE Need to continue
2707 @retval Others NO need to continue or error occur.
2710 GenerateAltConfigResp (
2711 IN CHAR16
*ConfigHdr
,
2712 IN IFR_VARSTORAGE_DATA
*VarStorageData
,
2713 IN IFR_DEFAULT_DATA
*DefaultIdArray
,
2714 IN OUT EFI_STRING
*DefaultAltCfgResp
2720 LIST_ENTRY
*LinkData
;
2721 LIST_ENTRY
*LinkDefault
;
2722 LIST_ENTRY
*ListEntry
;
2724 IFR_BLOCK_DATA
*BlockData
;
2725 IFR_DEFAULT_DATA
*DefaultId
;
2726 IFR_DEFAULT_DATA
*DefaultValueData
;
2734 // Add length for <ConfigHdr> + '\0'
2736 Length
= StrLen (ConfigHdr
) + 1;
2738 for (Link
= DefaultIdArray
->Entry
.ForwardLink
; Link
!= &DefaultIdArray
->Entry
; Link
= Link
->ForwardLink
) {
2739 DefaultId
= BASE_CR (Link
, IFR_DEFAULT_DATA
, Entry
);
2741 // Add length for "&<ConfigHdr>&ALTCFG=XXXX"
2742 // |1| StrLen (ConfigHdr) | 8 | 4 |
2744 Length
+= (1 + StrLen (ConfigHdr
) + 8 + 4);
2746 for (LinkData
= VarStorageData
->BlockEntry
.ForwardLink
; LinkData
!= &VarStorageData
->BlockEntry
; LinkData
= LinkData
->ForwardLink
) {
2747 BlockData
= BASE_CR (LinkData
, IFR_BLOCK_DATA
, Entry
);
2748 ListEntry
= &BlockData
->DefaultValueEntry
;
2749 for (LinkDefault
= ListEntry
->ForwardLink
; LinkDefault
!= ListEntry
; LinkDefault
= LinkDefault
->ForwardLink
) {
2750 DefaultValueData
= BASE_CR (LinkDefault
, IFR_DEFAULT_DATA
, Entry
);
2751 if (DefaultValueData
->DefaultId
!= DefaultId
->DefaultId
) {
2754 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2756 // Add length for "&Name1=zzzzzzzzzzzz"
2759 Length
+= (1 + StrLen (BlockData
->Name
) + 1 + BlockData
->Width
* 2);
2762 // Add length for "&OFFSET=XXXX&WIDTH=YYYY&VALUE=zzzzzzzzzzzz"
2763 // | 8 | 4 | 7 | 4 | 7 | Width * 2 |
2765 Length
+= (8 + 4 + 7 + 4 + 7 + BlockData
->Width
* 2);
2773 // No default value is found. The default string doesn't exist.
2780 // Allocate buffer for the entire <DefaultAltCfgResp>
2782 *DefaultAltCfgResp
= AllocateZeroPool (Length
* sizeof (CHAR16
));
2783 if (*DefaultAltCfgResp
== NULL
) {
2784 return EFI_OUT_OF_RESOURCES
;
2786 StringPtr
= *DefaultAltCfgResp
;
2789 // Start with <ConfigHdr>
2791 StrCpy (StringPtr
, ConfigHdr
);
2792 StringPtr
+= StrLen (StringPtr
);
2794 for (Link
= DefaultIdArray
->Entry
.ForwardLink
; Link
!= &DefaultIdArray
->Entry
; Link
= Link
->ForwardLink
) {
2795 DefaultId
= BASE_CR (Link
, IFR_DEFAULT_DATA
, Entry
);
2797 // Add <AltConfigHdr> of the form "&<ConfigHdr>&ALTCFG=XXXX\0"
2798 // |1| StrLen (ConfigHdr) | 8 | 4 |
2802 (1 + StrLen (ConfigHdr
) + 8 + 4 + 1) * sizeof (CHAR16
),
2805 DefaultId
->DefaultId
2807 StringPtr
+= StrLen (StringPtr
);
2809 for (LinkData
= VarStorageData
->BlockEntry
.ForwardLink
; LinkData
!= &VarStorageData
->BlockEntry
; LinkData
= LinkData
->ForwardLink
) {
2810 BlockData
= BASE_CR (LinkData
, IFR_BLOCK_DATA
, Entry
);
2811 ListEntry
= &BlockData
->DefaultValueEntry
;
2812 for (LinkDefault
= ListEntry
->ForwardLink
; LinkDefault
!= ListEntry
; LinkDefault
= LinkDefault
->ForwardLink
) {
2813 DefaultValueData
= BASE_CR (LinkDefault
, IFR_DEFAULT_DATA
, Entry
);
2814 if (DefaultValueData
->DefaultId
!= DefaultId
->DefaultId
) {
2817 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2820 (1 + StrLen (ConfigHdr
) + 1) * sizeof (CHAR16
),
2824 StringPtr
+= StrLen (StringPtr
);
2827 // Add <BlockConfig>
2828 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>
2832 (8 + 4 + 7 + 4 + 7 + 1) * sizeof (CHAR16
),
2833 L
"&OFFSET=%04X&WIDTH=%04X&VALUE=",
2837 StringPtr
+= StrLen (StringPtr
);
2839 Width
= BlockData
->Width
;
2841 // Convert Value to a hex string in "%x" format
2842 // NOTE: This is in the opposite byte that GUID and PATH use
2844 TmpBuffer
= (UINT8
*) &(DefaultValueData
->Value
);
2845 for (; Width
> 0; Width
--) {
2846 StringPtr
+= UnicodeValueToString (StringPtr
, PREFIX_ZERO
| RADIX_HEX
, TmpBuffer
[Width
- 1], 2);
2852 HiiToLower (*DefaultAltCfgResp
);
2858 This function gets the full request string and full default value string by
2859 parsing IFR data in HII form packages.
2861 When Request points to NULL string, the request string and default value string
2862 for each varstore in form package will return.
2864 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
2865 @param DevicePath Device Path which Hii Config Access Protocol is registered.
2866 @param Request Pointer to a null-terminated Unicode string in
2867 <ConfigRequest> format. When it doesn't contain
2868 any RequestElement, it will be updated to return
2869 the full RequestElement retrieved from IFR data.
2870 If it points to NULL, the request string for the first
2871 varstore in form package will be merged into a
2872 <MultiConfigRequest> format string and return.
2873 @param AltCfgResp Pointer to a null-terminated Unicode string in
2874 <ConfigAltResp> format. When the pointer is to NULL,
2875 the full default value string retrieved from IFR data
2876 will return. When the pinter is to a string, the
2877 full default value string retrieved from IFR data
2878 will be merged into the input string and return.
2879 When Request points to NULL, the default value string
2880 for each varstore in form package will be merged into
2881 a <MultiConfigAltResp> format string and return.
2882 @param PointerProgress Optional parameter, it can be be NULL.
2883 When it is not NULL, if Request is NULL, it returns NULL.
2884 On return, points to a character in the Request
2885 string. Points to the string's null terminator if
2886 request was successful. Points to the most recent
2887 & before the first failing name / value pair (or
2888 the beginning of the string if the failure is in
2889 the first name / value pair) if the request was
2891 @retval EFI_SUCCESS The Results string is set to the full request string.
2892 And AltCfgResp contains all default value string.
2893 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
2894 @retval EFI_NOT_FOUND The varstore (Guid and Name) in Request string
2895 can't be found in Form package.
2896 @retval EFI_NOT_FOUND HiiPackage can't be got on the input HiiHandle.
2897 @retval EFI_INVALID_PARAMETER Request points to NULL.
2902 GetFullStringFromHiiFormPackages (
2903 IN HII_DATABASE_RECORD
*DataBaseRecord
,
2904 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
2905 IN OUT EFI_STRING
*Request
,
2906 IN OUT EFI_STRING
*AltCfgResp
,
2907 OUT EFI_STRING
*PointerProgress OPTIONAL
2911 UINT8
*HiiFormPackage
;
2913 IFR_BLOCK_DATA
*RequestBlockArray
;
2914 IFR_BLOCK_DATA
*BlockData
;
2915 IFR_DEFAULT_DATA
*DefaultValueData
;
2916 IFR_DEFAULT_DATA
*DefaultId
;
2917 IFR_DEFAULT_DATA
*DefaultIdArray
;
2918 IFR_VARSTORAGE_DATA
*VarStorageData
;
2919 EFI_STRING DefaultAltCfgResp
;
2920 EFI_STRING ConfigHdr
;
2921 EFI_STRING StringPtr
;
2922 EFI_STRING Progress
;
2924 if (DataBaseRecord
== NULL
|| DevicePath
== NULL
|| Request
== NULL
|| AltCfgResp
== NULL
) {
2925 return EFI_INVALID_PARAMETER
;
2929 // Initialize the local variables.
2931 RequestBlockArray
= NULL
;
2932 DefaultIdArray
= NULL
;
2933 VarStorageData
= NULL
;
2934 DefaultAltCfgResp
= NULL
;
2936 HiiFormPackage
= NULL
;
2938 Progress
= *Request
;
2940 Status
= GetFormPackageData (DataBaseRecord
, &HiiFormPackage
, &PackageSize
);
2941 if (EFI_ERROR (Status
)) {
2946 // 1. Get the request block array by Request String when Request string containts the block array.
2949 if (*Request
!= NULL
) {
2950 StringPtr
= *Request
;
2954 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
2955 Status
= EFI_INVALID_PARAMETER
;
2958 StringPtr
+= StrLen (L
"GUID=");
2959 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&NAME=", StrLen (L
"&NAME=")) != 0) {
2962 if (*StringPtr
== L
'\0') {
2963 Status
= EFI_INVALID_PARAMETER
;
2966 StringPtr
+= StrLen (L
"&NAME=");
2967 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&PATH=", StrLen (L
"&PATH=")) != 0) {
2970 if (*StringPtr
== L
'\0') {
2971 Status
= EFI_INVALID_PARAMETER
;
2974 StringPtr
+= StrLen (L
"&PATH=");
2975 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
2979 if (*StringPtr
== L
'\0') {
2981 // No request block is found.
2988 // If StringPtr != NULL, get the request elements.
2990 if (StringPtr
!= NULL
) {
2991 if (StrStr (StringPtr
, L
"&OFFSET=") != NULL
) {
2992 RequestBlockArray
= GetBlockElement(StringPtr
, &Progress
);
2994 RequestBlockArray
= GetNameElement(StringPtr
, &Progress
);
2997 if (RequestBlockArray
== NULL
) {
2998 Status
= EFI_INVALID_PARAMETER
;
3004 // Initialize DefaultIdArray to store the map between DeaultId and DefaultName
3006 DefaultIdArray
= (IFR_DEFAULT_DATA
*) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
3007 if (DefaultIdArray
== NULL
) {
3008 Status
= EFI_OUT_OF_RESOURCES
;
3011 InitializeListHead (&DefaultIdArray
->Entry
);
3014 // Initialize VarStorageData to store the var store Block and Default value information.
3016 VarStorageData
= (IFR_VARSTORAGE_DATA
*) AllocateZeroPool (sizeof (IFR_VARSTORAGE_DATA
));
3017 if (VarStorageData
== NULL
) {
3018 Status
= EFI_OUT_OF_RESOURCES
;
3021 InitializeListHead (&VarStorageData
->Entry
);
3022 InitializeListHead (&VarStorageData
->BlockEntry
);
3025 // 2. Parse FormPackage to get BlockArray and DefaultId Array for the request BlockArray.
3029 // Parse the opcode in form pacakge to get the default setting.
3031 Status
= ParseIfrData (DataBaseRecord
->Handle
,
3033 (UINT32
) PackageSize
,
3038 if (EFI_ERROR (Status
)) {
3043 // No requested varstore in IFR data and directly return
3045 if (VarStorageData
->Type
== 0 && VarStorageData
->Name
== NULL
) {
3046 Status
= EFI_SUCCESS
;
3051 // 3. Construct Request Element (Block Name) for 2.1 and 2.2 case.
3053 Status
= GenerateHdr (VarStorageData
, DevicePath
, &ConfigHdr
);
3054 if (EFI_ERROR (Status
)) {
3058 if (RequestBlockArray
== NULL
) {
3059 if (!GenerateConfigRequest(ConfigHdr
, VarStorageData
, &Status
, Request
)) {
3065 // 4. Construct Default Value string in AltResp according to request element.
3066 // Go through all VarStorageData Entry and get the DefaultId array for each one
3067 // Then construct them all to : ConfigHdr AltConfigHdr ConfigBody AltConfigHdr ConfigBody
3069 Status
= GenerateAltConfigResp (ConfigHdr
, VarStorageData
, DefaultIdArray
, &DefaultAltCfgResp
);
3070 if (EFI_ERROR (Status
)) {
3075 // 5. Merge string into the input AltCfgResp if the iput *AltCfgResp is not NULL.
3077 if (*AltCfgResp
!= NULL
&& DefaultAltCfgResp
!= NULL
) {
3078 Status
= MergeDefaultString (AltCfgResp
, DefaultAltCfgResp
);
3079 FreePool (DefaultAltCfgResp
);
3080 } else if (*AltCfgResp
== NULL
) {
3081 *AltCfgResp
= DefaultAltCfgResp
;
3085 if (RequestBlockArray
!= NULL
) {
3087 // Free Link Array RequestBlockArray
3089 while (!IsListEmpty (&RequestBlockArray
->Entry
)) {
3090 BlockData
= BASE_CR (RequestBlockArray
->Entry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
3091 RemoveEntryList (&BlockData
->Entry
);
3092 if (BlockData
->Name
!= NULL
) {
3093 FreePool (BlockData
->Name
);
3095 FreePool (BlockData
);
3098 FreePool (RequestBlockArray
);
3101 if (VarStorageData
!= NULL
) {
3103 // Free link array VarStorageData
3105 while (!IsListEmpty (&VarStorageData
->BlockEntry
)) {
3106 BlockData
= BASE_CR (VarStorageData
->BlockEntry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
3107 RemoveEntryList (&BlockData
->Entry
);
3108 if (BlockData
->Name
!= NULL
) {
3109 FreePool (BlockData
->Name
);
3112 // Free default value link array
3114 while (!IsListEmpty (&BlockData
->DefaultValueEntry
)) {
3115 DefaultValueData
= BASE_CR (BlockData
->DefaultValueEntry
.ForwardLink
, IFR_DEFAULT_DATA
, Entry
);
3116 RemoveEntryList (&DefaultValueData
->Entry
);
3117 FreePool (DefaultValueData
);
3119 FreePool (BlockData
);
3121 FreePool (VarStorageData
);
3124 if (DefaultIdArray
!= NULL
) {
3126 // Free DefaultId Array
3128 while (!IsListEmpty (&DefaultIdArray
->Entry
)) {
3129 DefaultId
= BASE_CR (DefaultIdArray
->Entry
.ForwardLink
, IFR_DEFAULT_DATA
, Entry
);
3130 RemoveEntryList (&DefaultId
->Entry
);
3131 FreePool (DefaultId
);
3133 FreePool (DefaultIdArray
);
3137 // Free the allocated string
3139 if (ConfigHdr
!= NULL
) {
3140 FreePool (ConfigHdr
);
3144 // Free Pacakge data
3146 if (HiiFormPackage
!= NULL
) {
3147 FreePool (HiiFormPackage
);
3150 if (PointerProgress
!= NULL
) {
3151 if (*Request
== NULL
) {
3152 *PointerProgress
= NULL
;
3153 } else if (EFI_ERROR (Status
)) {
3154 *PointerProgress
= *Request
;
3156 *PointerProgress
= *Request
+ StrLen (*Request
);
3164 This function gets the full request resp string by
3165 parsing IFR data in HII form packages.
3167 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
3169 @param EfiVarStoreInfo The efi varstore info which is save in the EFI
3170 varstore data structure.
3171 @param Request Pointer to a null-terminated Unicode string in
3172 <ConfigRequest> format.
3173 @param RequestResp Pointer to a null-terminated Unicode string in
3174 <ConfigResp> format.
3175 @param AccessProgress On return, points to a character in the Request
3176 string. Points to the string's null terminator if
3177 request was successful. Points to the most recent
3178 & before the first failing name / value pair (or
3179 the beginning of the string if the failure is in
3180 the first name / value pair) if the request was
3183 @retval EFI_SUCCESS The Results string is set to the full request string.
3184 And AltCfgResp contains all default value string.
3185 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
3186 @retval EFI_INVALID_PARAMETER Request points to NULL.
3190 GetConfigRespFromEfiVarStore (
3191 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
3192 IN EFI_IFR_VARSTORE_EFI
*EfiVarStoreInfo
,
3193 IN EFI_STRING Request
,
3194 OUT EFI_STRING
*RequestResp
,
3195 OUT EFI_STRING
*AccessProgress
3199 EFI_STRING VarStoreName
;
3203 Status
= EFI_SUCCESS
;
3206 VarStoreName
= NULL
;
3208 VarStoreName
= AllocateZeroPool (AsciiStrSize ((CHAR8
*)EfiVarStoreInfo
->Name
) * sizeof (CHAR16
));
3209 if (VarStoreName
== NULL
) {
3210 Status
= EFI_OUT_OF_RESOURCES
;
3213 AsciiStrToUnicodeStr ((CHAR8
*) EfiVarStoreInfo
->Name
, VarStoreName
);
3216 Status
= gRT
->GetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, NULL
, &BufferSize
, NULL
);
3217 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
3221 VarStore
= AllocateZeroPool (BufferSize
);
3222 ASSERT (VarStore
!= NULL
);
3223 Status
= gRT
->GetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, NULL
, &BufferSize
, VarStore
);
3224 if (EFI_ERROR (Status
)) {
3228 Status
= HiiBlockToConfig(This
, Request
, VarStore
, BufferSize
, RequestResp
, AccessProgress
);
3229 if (EFI_ERROR (Status
)) {
3234 if (VarStoreName
!= NULL
) {
3235 FreePool (VarStoreName
);
3238 if (VarStore
!= NULL
) {
3239 FreePool (VarStore
);
3247 This function route the full request resp string for efi varstore.
3249 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
3251 @param EfiVarStoreInfo The efi varstore info which is save in the EFI
3252 varstore data structure.
3253 @param RequestResp Pointer to a null-terminated Unicode string in
3254 <ConfigResp> format.
3255 @param Result Pointer to a null-terminated Unicode string in
3256 <ConfigResp> format.
3258 @retval EFI_SUCCESS The Results string is set to the full request string.
3259 And AltCfgResp contains all default value string.
3260 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
3261 @retval EFI_INVALID_PARAMETER Request points to NULL.
3265 RouteConfigRespForEfiVarStore (
3266 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
3267 IN EFI_IFR_VARSTORE_EFI
*EfiVarStoreInfo
,
3268 IN EFI_STRING RequestResp
,
3269 OUT EFI_STRING
*Result
3273 EFI_STRING VarStoreName
;
3278 Status
= EFI_SUCCESS
;
3281 VarStoreName
= NULL
;
3283 VarStoreName
= AllocateZeroPool (AsciiStrSize ((CHAR8
*)EfiVarStoreInfo
->Name
) * sizeof (CHAR16
));
3284 if (VarStoreName
== NULL
) {
3285 Status
= EFI_OUT_OF_RESOURCES
;
3288 AsciiStrToUnicodeStr ((CHAR8
*) EfiVarStoreInfo
->Name
, VarStoreName
);
3290 Status
= gRT
->GetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, NULL
, &BufferSize
, NULL
);
3291 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
3295 BlockSize
= BufferSize
;
3296 VarStore
= AllocateZeroPool (BufferSize
);
3297 ASSERT (VarStore
!= NULL
);
3298 Status
= gRT
->GetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, NULL
, &BufferSize
, VarStore
);
3299 if (EFI_ERROR (Status
)) {
3303 Status
= HiiConfigToBlock(This
, RequestResp
, VarStore
, &BlockSize
, Result
);
3304 if (EFI_ERROR (Status
)) {
3308 Status
= gRT
->SetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, EfiVarStoreInfo
->Attributes
, BufferSize
, VarStore
);
3309 if (EFI_ERROR (Status
)) {
3314 if (VarStoreName
!= NULL
) {
3315 FreePool (VarStoreName
);
3318 if (VarStore
!= NULL
) {
3319 FreePool (VarStore
);
3326 Validate the config request elements.
3328 @param ConfigElements A null-terminated Unicode string in <ConfigRequest> format,
3329 without configHdr field.
3331 @retval CHAR16 * THE first Name/value pair not correct.
3332 @retval NULL Success parse the name/value pair
3335 OffsetWidthValidate (
3336 CHAR16
*ConfigElements
3342 StringPtr
= ConfigElements
;
3346 if (StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) != 0) {
3350 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
3353 if (*StringPtr
== L
'\0') {
3357 StringPtr
+= StrLen (L
"&WIDTH=");
3358 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) != 0) {
3362 if (*StringPtr
== L
'\0') {
3369 Validate the config request elements.
3371 @param ConfigElements A null-terminated Unicode string in <ConfigRequest> format,
3372 without configHdr field.
3374 @retval CHAR16 * THE first Name/value pair not correct.
3375 @retval NULL Success parse the name/value pair
3380 CHAR16
*ConfigElements
3386 StringPtr
= ConfigElements
;
3390 if (*StringPtr
!= L
'&') {
3395 StringPtr
= StrStr (StringPtr
, L
"&");
3397 if (StringPtr
== NULL
) {
3404 Validate the config request string.
3406 @param ConfigRequest A null-terminated Unicode string in <ConfigRequest> format.
3408 @retval CHAR16 * THE first element not correct.
3409 @retval NULL Success parse the name/value pair
3413 ConfigRequestValidate (
3414 CHAR16
*ConfigRequest
3417 BOOLEAN HasNameField
;
3420 HasNameField
= TRUE
;
3421 StringPtr
= ConfigRequest
;
3424 // Check <ConfigHdr>
3426 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
3427 return ConfigRequest
;
3429 StringPtr
+= StrLen (L
"GUID=");
3430 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&NAME=", StrLen (L
"&NAME=")) != 0) {
3433 if (*StringPtr
== L
'\0') {
3434 return ConfigRequest
;
3436 StringPtr
+= StrLen (L
"&NAME=");
3437 if (*StringPtr
== L
'&') {
3438 HasNameField
= FALSE
;
3440 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&PATH=", StrLen (L
"&PATH=")) != 0) {
3443 if (*StringPtr
== L
'\0') {
3444 return ConfigRequest
;
3446 StringPtr
+= StrLen (L
"&PATH=");
3447 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
3451 if (*StringPtr
== L
'\0') {
3457 // Should be Buffer varstore, config request should be "OFFSET/Width" pairs.
3459 return OffsetWidthValidate(StringPtr
);
3462 // Should be Name/Value varstore, config request should be "&name1&name2..." pairs.
3464 return NameValueValidate(StringPtr
);
3469 This function allows a caller to extract the current configuration
3470 for one or more named elements from one or more drivers.
3472 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
3474 @param Request A null-terminated Unicode string in
3475 <MultiConfigRequest> format.
3476 @param Progress On return, points to a character in the Request
3477 string. Points to the string's null terminator if
3478 request was successful. Points to the most recent
3479 & before the first failing name / value pair (or
3480 the beginning of the string if the failure is in
3481 the first name / value pair) if the request was
3483 @param Results Null-terminated Unicode string in
3484 <MultiConfigAltResp> format which has all values
3485 filled in for the names in the Request string.
3486 String to be allocated by the called function.
3488 @retval EFI_SUCCESS The Results string is filled with the values
3489 corresponding to all requested names.
3490 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
3491 results that must be stored awaiting possible
3493 @retval EFI_NOT_FOUND Routing data doesn't match any known driver.
3494 Progress set to the "G" in "GUID" of the routing
3495 header that doesn't match. Note: There is no
3496 requirement that all routing data be validated
3497 before any configuration extraction.
3498 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Request
3499 parameter would result in this type of error. The
3500 Progress parameter is set to NULL.
3501 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set to most recent &
3502 before the error or the beginning of the string.
3503 @retval EFI_INVALID_PARAMETER The ExtractConfig function of the underlying HII
3504 Configuration Access Protocol returned
3505 EFI_INVALID_PARAMETER. Progress set to most recent
3506 & before the error or the beginning of the string.
3511 HiiConfigRoutingExtractConfig (
3512 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
3513 IN CONST EFI_STRING Request
,
3514 OUT EFI_STRING
*Progress
,
3515 OUT EFI_STRING
*Results
3518 HII_DATABASE_PRIVATE_DATA
*Private
;
3519 EFI_STRING StringPtr
;
3520 EFI_STRING ConfigRequest
;
3522 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
3523 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
3526 HII_DATABASE_RECORD
*Database
;
3527 UINT8
*DevicePathPkg
;
3528 UINT8
*CurrentDevicePath
;
3529 EFI_HANDLE DriverHandle
;
3530 EFI_HII_HANDLE HiiHandle
;
3531 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
3532 EFI_STRING AccessProgress
;
3533 EFI_STRING AccessResults
;
3534 EFI_STRING DefaultResults
;
3535 BOOLEAN FirstElement
;
3536 BOOLEAN IfrDataParsedFlag
;
3537 BOOLEAN IsEfiVarStore
;
3538 EFI_IFR_VARSTORE_EFI
*EfiVarStoreInfo
;
3539 EFI_STRING ErrorPtr
;
3541 if (This
== NULL
|| Progress
== NULL
|| Results
== NULL
) {
3542 return EFI_INVALID_PARAMETER
;
3545 if (Request
== NULL
) {
3547 return EFI_INVALID_PARAMETER
;
3550 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
3551 StringPtr
= Request
;
3552 *Progress
= StringPtr
;
3553 DefaultResults
= NULL
;
3554 ConfigRequest
= NULL
;
3555 Status
= EFI_SUCCESS
;
3556 AccessResults
= NULL
;
3557 AccessProgress
= NULL
;
3559 IfrDataParsedFlag
= FALSE
;
3560 IsEfiVarStore
= FALSE
;
3561 EfiVarStoreInfo
= NULL
;
3564 // The first element of <MultiConfigRequest> should be
3565 // <GuidHdr>, which is in 'GUID='<Guid> syntax.
3567 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
3568 return EFI_INVALID_PARAMETER
;
3571 FirstElement
= TRUE
;
3574 // Allocate a fix length of memory to store Results. Reallocate memory for
3575 // Results if this fix length is insufficient.
3577 *Results
= (EFI_STRING
) AllocateZeroPool (MAX_STRING_LENGTH
);
3578 if (*Results
== NULL
) {
3579 return EFI_OUT_OF_RESOURCES
;
3582 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) == 0) {
3584 // If parsing error, set Progress to the beginning of the <MultiConfigRequest>
3585 // or most recent & before the error.
3587 if (StringPtr
== Request
) {
3588 *Progress
= StringPtr
;
3590 *Progress
= StringPtr
- 1;
3594 // Process each <ConfigRequest> of <MultiConfigRequest>
3596 Length
= CalculateConfigStringLen (StringPtr
);
3597 ConfigRequest
= AllocateCopyPool ((Length
+ 1) * sizeof (CHAR16
), StringPtr
);
3598 if (ConfigRequest
== NULL
) {
3599 Status
= EFI_OUT_OF_RESOURCES
;
3602 *(ConfigRequest
+ Length
) = 0;
3605 // Get the UEFI device path
3607 Status
= GetDevicePath (ConfigRequest
, (UINT8
**) &DevicePath
);
3608 if (EFI_ERROR (Status
)) {
3613 // Find driver which matches the routing data.
3615 DriverHandle
= NULL
;
3618 for (Link
= Private
->DatabaseList
.ForwardLink
;
3619 Link
!= &Private
->DatabaseList
;
3620 Link
= Link
->ForwardLink
3622 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
3623 if ((DevicePathPkg
= Database
->PackageList
->DevicePathPkg
) != NULL
) {
3624 CurrentDevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
3628 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) CurrentDevicePath
)
3630 DriverHandle
= Database
->DriverHandle
;
3631 HiiHandle
= Database
->Handle
;
3638 // Try to find driver handle by device path.
3640 if (DriverHandle
== NULL
) {
3641 TempDevicePath
= DevicePath
;
3642 Status
= gBS
->LocateDevicePath (
3643 &gEfiDevicePathProtocolGuid
,
3647 if (EFI_ERROR (Status
) || (DriverHandle
== NULL
)) {
3649 // Routing data does not match any known driver.
3650 // Set Progress to the 'G' in "GUID" of the routing header.
3652 *Progress
= StringPtr
;
3653 Status
= EFI_NOT_FOUND
;
3659 // Validate ConfigRequest String.
3661 ErrorPtr
= ConfigRequestValidate(ConfigRequest
);
3662 if (ErrorPtr
!= NULL
) {
3663 *Progress
= StrStr (StringPtr
, ErrorPtr
);
3664 Status
= EFI_INVALID_PARAMETER
;
3669 // Check whether ConfigRequest contains request string.
3671 IfrDataParsedFlag
= FALSE
;
3672 if ((HiiHandle
!= NULL
) && !GetElementsFromRequest(ConfigRequest
)) {
3674 // Get the full request string from IFR when HiiPackage is registered to HiiHandle
3676 IfrDataParsedFlag
= TRUE
;
3677 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &ConfigRequest
, &DefaultResults
, &AccessProgress
);
3678 if (EFI_ERROR (Status
)) {
3680 // AccessProgress indicates the parsing progress on <ConfigRequest>.
3681 // Map it to the progress on <MultiConfigRequest> then return it.
3683 ASSERT (AccessProgress
!= NULL
);
3684 *Progress
= StrStr (StringPtr
, AccessProgress
);
3688 // Not any request block is found.
3690 if (!GetElementsFromRequest(ConfigRequest
)) {
3691 AccessResults
= AllocateCopyPool (StrSize (ConfigRequest
), ConfigRequest
);
3692 goto NextConfigString
;
3697 // Check whether this ConfigRequest is search from Efi varstore type storage.
3699 Status
= GetVarStoreType(Database
, ConfigRequest
, &IsEfiVarStore
, &EfiVarStoreInfo
);
3700 if (EFI_ERROR (Status
)) {
3704 if (IsEfiVarStore
) {
3706 // Call the GetVariable function to extract settings.
3708 Status
= GetConfigRespFromEfiVarStore(This
, EfiVarStoreInfo
, ConfigRequest
, &AccessResults
, &AccessProgress
);
3709 FreePool (EfiVarStoreInfo
);
3712 // Call corresponding ConfigAccess protocol to extract settings
3714 Status
= gBS
->HandleProtocol (
3716 &gEfiHiiConfigAccessProtocolGuid
,
3717 (VOID
**) &ConfigAccess
3719 ASSERT_EFI_ERROR (Status
);
3721 Status
= ConfigAccess
->ExtractConfig (
3728 if (EFI_ERROR (Status
)) {
3730 // AccessProgress indicates the parsing progress on <ConfigRequest>.
3731 // Map it to the progress on <MultiConfigRequest> then return it.
3733 *Progress
= StrStr (StringPtr
, AccessProgress
);
3738 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'
3739 // which seperates the first <ConfigAltResp> and the following ones.
3741 ASSERT (*AccessProgress
== 0);
3744 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
3746 if (!IfrDataParsedFlag
&& HiiHandle
!= NULL
) {
3747 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &ConfigRequest
, &DefaultResults
, NULL
);
3748 ASSERT_EFI_ERROR (Status
);
3751 FreePool (DevicePath
);
3754 if (DefaultResults
!= NULL
) {
3755 Status
= MergeDefaultString (&AccessResults
, DefaultResults
);
3756 ASSERT_EFI_ERROR (Status
);
3757 FreePool (DefaultResults
);
3758 DefaultResults
= NULL
;
3762 if (!FirstElement
) {
3763 Status
= AppendToMultiString (Results
, L
"&");
3764 ASSERT_EFI_ERROR (Status
);
3767 Status
= AppendToMultiString (Results
, AccessResults
);
3768 ASSERT_EFI_ERROR (Status
);
3770 FirstElement
= FALSE
;
3772 FreePool (AccessResults
);
3773 AccessResults
= NULL
;
3774 FreePool (ConfigRequest
);
3775 ConfigRequest
= NULL
;
3778 // Go to next <ConfigRequest> (skip '&').
3780 StringPtr
+= Length
;
3781 if (*StringPtr
== 0) {
3782 *Progress
= StringPtr
;
3790 if (EFI_ERROR (Status
)) {
3791 FreePool (*Results
);
3795 if (ConfigRequest
!= NULL
) {
3796 FreePool (ConfigRequest
);
3799 if (AccessResults
!= NULL
) {
3800 FreePool (AccessResults
);
3803 if (DefaultResults
!= NULL
) {
3804 FreePool (DefaultResults
);
3807 if (DevicePath
!= NULL
) {
3808 FreePool (DevicePath
);
3816 This function allows the caller to request the current configuration for the
3817 entirety of the current HII database and returns the data in a
3818 null-terminated Unicode string.
3820 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
3822 @param Results Null-terminated Unicode string in
3823 <MultiConfigAltResp> format which has all values
3824 filled in for the entirety of the current HII
3825 database. String to be allocated by the called
3826 function. De-allocation is up to the caller.
3828 @retval EFI_SUCCESS The Results string is filled with the values
3829 corresponding to all requested names.
3830 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
3831 results that must be stored awaiting possible
3833 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Results
3834 parameter would result in this type of error.
3839 HiiConfigRoutingExportConfig (
3840 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
3841 OUT EFI_STRING
*Results
3845 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
3846 EFI_STRING AccessResults
;
3847 EFI_STRING Progress
;
3848 EFI_STRING StringPtr
;
3849 EFI_STRING ConfigRequest
;
3851 EFI_HANDLE
*ConfigAccessHandles
;
3852 UINTN NumberConfigAccessHandles
;
3853 BOOLEAN FirstElement
;
3854 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
3855 EFI_HII_HANDLE HiiHandle
;
3856 EFI_STRING DefaultResults
;
3857 HII_DATABASE_PRIVATE_DATA
*Private
;
3859 HII_DATABASE_RECORD
*Database
;
3860 UINT8
*DevicePathPkg
;
3861 UINT8
*CurrentDevicePath
;
3862 BOOLEAN IfrDataParsedFlag
;
3864 if (This
== NULL
|| Results
== NULL
) {
3865 return EFI_INVALID_PARAMETER
;
3868 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
3871 // Allocate a fix length of memory to store Results. Reallocate memory for
3872 // Results if this fix length is insufficient.
3874 *Results
= (EFI_STRING
) AllocateZeroPool (MAX_STRING_LENGTH
);
3875 if (*Results
== NULL
) {
3876 return EFI_OUT_OF_RESOURCES
;
3879 NumberConfigAccessHandles
= 0;
3880 Status
= gBS
->LocateHandleBuffer (
3882 &gEfiHiiConfigAccessProtocolGuid
,
3884 &NumberConfigAccessHandles
,
3885 &ConfigAccessHandles
3887 if (EFI_ERROR (Status
)) {
3891 FirstElement
= TRUE
;
3893 for (Index
= 0; Index
< NumberConfigAccessHandles
; Index
++) {
3894 Status
= gBS
->HandleProtocol (
3895 ConfigAccessHandles
[Index
],
3896 &gEfiHiiConfigAccessProtocolGuid
,
3897 (VOID
**) &ConfigAccess
3899 if (EFI_ERROR (Status
)) {
3904 // Get DevicePath and HiiHandle for this ConfigAccess driver handle
3906 IfrDataParsedFlag
= FALSE
;
3909 DefaultResults
= NULL
;
3911 ConfigRequest
= NULL
;
3912 DevicePath
= DevicePathFromHandle (ConfigAccessHandles
[Index
]);
3913 if (DevicePath
!= NULL
) {
3914 for (Link
= Private
->DatabaseList
.ForwardLink
;
3915 Link
!= &Private
->DatabaseList
;
3916 Link
= Link
->ForwardLink
3918 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
3919 if ((DevicePathPkg
= Database
->PackageList
->DevicePathPkg
) != NULL
) {
3920 CurrentDevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
3924 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) CurrentDevicePath
)
3926 HiiHandle
= Database
->Handle
;
3933 Status
= ConfigAccess
->ExtractConfig (
3939 if (EFI_ERROR (Status
)) {
3941 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
3943 if (HiiHandle
!= NULL
&& DevicePath
!= NULL
) {
3944 IfrDataParsedFlag
= TRUE
;
3945 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &ConfigRequest
, &DefaultResults
, NULL
);
3947 // Get the full request string to get the Current setting again.
3949 if (!EFI_ERROR (Status
) && ConfigRequest
!= NULL
) {
3950 Status
= ConfigAccess
->ExtractConfig (
3956 FreePool (ConfigRequest
);
3958 Status
= EFI_NOT_FOUND
;
3963 if (!EFI_ERROR (Status
)) {
3965 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
3967 if (!IfrDataParsedFlag
&& HiiHandle
!= NULL
&& DevicePath
!= NULL
) {
3968 StringPtr
= StrStr (AccessResults
, L
"&GUID=");
3969 if (StringPtr
!= NULL
) {
3972 if (GetElementsFromRequest (AccessResults
)) {
3973 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &AccessResults
, &DefaultResults
, NULL
);
3974 ASSERT_EFI_ERROR (Status
);
3976 if (StringPtr
!= NULL
) {
3981 // Merge the default sting from IFR code into the got setting from driver.
3983 if (DefaultResults
!= NULL
) {
3984 Status
= MergeDefaultString (&AccessResults
, DefaultResults
);
3985 ASSERT_EFI_ERROR (Status
);
3986 FreePool (DefaultResults
);
3987 DefaultResults
= NULL
;
3991 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'
3992 // which seperates the first <ConfigAltResp> and the following ones.
3994 if (!FirstElement
) {
3995 Status
= AppendToMultiString (Results
, L
"&");
3996 ASSERT_EFI_ERROR (Status
);
3999 Status
= AppendToMultiString (Results
, AccessResults
);
4000 ASSERT_EFI_ERROR (Status
);
4002 FirstElement
= FALSE
;
4004 FreePool (AccessResults
);
4005 AccessResults
= NULL
;
4008 FreePool (ConfigAccessHandles
);
4015 This function processes the results of processing forms and routes it to the
4016 appropriate handlers or storage.
4018 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
4020 @param Configuration A null-terminated Unicode string in
4021 <MulltiConfigResp> format.
4022 @param Progress A pointer to a string filled in with the offset of
4023 the most recent & before the first failing name /
4024 value pair (or the beginning of the string if the
4025 failure is in the first name / value pair) or the
4026 terminating NULL if all was successful.
4028 @retval EFI_SUCCESS The results have been distributed or are awaiting
4030 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
4031 results that must be stored awaiting possible
4033 @retval EFI_INVALID_PARAMETER Passing in a NULL for the Configuration parameter
4034 would result in this type of error.
4035 @retval EFI_NOT_FOUND Target for the specified routing data was not
4041 HiiConfigRoutingRouteConfig (
4042 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
4043 IN CONST EFI_STRING Configuration
,
4044 OUT EFI_STRING
*Progress
4047 HII_DATABASE_PRIVATE_DATA
*Private
;
4048 EFI_STRING StringPtr
;
4049 EFI_STRING ConfigResp
;
4052 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
4053 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
4055 HII_DATABASE_RECORD
*Database
;
4056 UINT8
*DevicePathPkg
;
4057 UINT8
*CurrentDevicePath
;
4058 EFI_HANDLE DriverHandle
;
4059 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
4060 EFI_STRING AccessProgress
;
4061 EFI_IFR_VARSTORE_EFI
*EfiVarStoreInfo
;
4062 BOOLEAN IsEfiVarstore
;
4064 if (This
== NULL
|| Progress
== NULL
) {
4065 return EFI_INVALID_PARAMETER
;
4068 if (Configuration
== NULL
) {
4070 return EFI_INVALID_PARAMETER
;
4073 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
4074 StringPtr
= Configuration
;
4075 *Progress
= StringPtr
;
4077 AccessProgress
= NULL
;
4078 EfiVarStoreInfo
= NULL
;
4079 IsEfiVarstore
= FALSE
;
4082 // The first element of <MultiConfigResp> should be
4083 // <GuidHdr>, which is in 'GUID='<Guid> syntax.
4085 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
4086 return EFI_INVALID_PARAMETER
;
4089 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) == 0) {
4091 // If parsing error, set Progress to the beginning of the <MultiConfigResp>
4092 // or most recent & before the error.
4094 if (StringPtr
== Configuration
) {
4095 *Progress
= StringPtr
;
4097 *Progress
= StringPtr
- 1;
4101 // Process each <ConfigResp> of <MultiConfigResp>
4103 Length
= CalculateConfigStringLen (StringPtr
);
4104 ConfigResp
= AllocateCopyPool ((Length
+ 1) * sizeof (CHAR16
), StringPtr
);
4105 if (ConfigResp
== NULL
) {
4106 return EFI_OUT_OF_RESOURCES
;
4109 // Append '\0' to the end of ConfigRequest
4111 *(ConfigResp
+ Length
) = 0;
4114 // Get the UEFI device path
4116 Status
= GetDevicePath (ConfigResp
, (UINT8
**) &DevicePath
);
4117 if (EFI_ERROR (Status
)) {
4118 FreePool (ConfigResp
);
4123 // Find driver which matches the routing data.
4125 DriverHandle
= NULL
;
4126 for (Link
= Private
->DatabaseList
.ForwardLink
;
4127 Link
!= &Private
->DatabaseList
;
4128 Link
= Link
->ForwardLink
4130 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
4132 if ((DevicePathPkg
= Database
->PackageList
->DevicePathPkg
) != NULL
) {
4133 CurrentDevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
4137 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) CurrentDevicePath
)
4139 DriverHandle
= Database
->DriverHandle
;
4146 // Try to find driver handle by device path.
4148 if (DriverHandle
== NULL
) {
4149 TempDevicePath
= DevicePath
;
4150 Status
= gBS
->LocateDevicePath (
4151 &gEfiDevicePathProtocolGuid
,
4155 if (EFI_ERROR (Status
) || (DriverHandle
== NULL
)) {
4157 // Routing data does not match any known driver.
4158 // Set Progress to the 'G' in "GUID" of the routing header.
4160 FreePool (DevicePath
);
4161 *Progress
= StringPtr
;
4162 FreePool (ConfigResp
);
4163 return EFI_NOT_FOUND
;
4167 FreePool (DevicePath
);
4170 // Check whether this ConfigRequest is search from Efi varstore type storage.
4172 Status
= GetVarStoreType(Database
, ConfigResp
, &IsEfiVarstore
, &EfiVarStoreInfo
);
4173 if (EFI_ERROR (Status
)) {
4177 if (IsEfiVarstore
) {
4179 // Call the SetVariable function to route settings.
4181 Status
= RouteConfigRespForEfiVarStore(This
, EfiVarStoreInfo
, ConfigResp
, &AccessProgress
);
4182 FreePool (EfiVarStoreInfo
);
4185 // Call corresponding ConfigAccess protocol to route settings
4187 Status
= gBS
->HandleProtocol (
4189 &gEfiHiiConfigAccessProtocolGuid
,
4190 (VOID
**) &ConfigAccess
4192 ASSERT_EFI_ERROR (Status
);
4194 Status
= ConfigAccess
->RouteConfig (
4200 if (EFI_ERROR (Status
)) {
4202 // AccessProgress indicates the parsing progress on <ConfigResp>.
4203 // Map it to the progress on <MultiConfigResp> then return it.
4205 *Progress
= StrStr (StringPtr
, AccessProgress
);
4207 FreePool (ConfigResp
);
4211 FreePool (ConfigResp
);
4215 // Go to next <ConfigResp> (skip '&').
4217 StringPtr
+= Length
;
4218 if (*StringPtr
== 0) {
4219 *Progress
= StringPtr
;
4232 This helper function is to be called by drivers to map configuration data
4233 stored in byte array ("block") formats such as UEFI Variables into current
4234 configuration strings.
4236 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
4238 @param ConfigRequest A null-terminated Unicode string in
4239 <ConfigRequest> format.
4240 @param Block Array of bytes defining the block's configuration.
4241 @param BlockSize Length in bytes of Block.
4242 @param Config Filled-in configuration string. String allocated
4243 by the function. Returned only if call is
4244 successful. It is <ConfigResp> string format.
4245 @param Progress A pointer to a string filled in with the offset of
4246 the most recent & before the first failing
4247 name/value pair (or the beginning of the string if
4248 the failure is in the first name / value pair) or
4249 the terminating NULL if all was successful.
4251 @retval EFI_SUCCESS The request succeeded. Progress points to the null
4252 terminator at the end of the ConfigRequest
4254 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress
4255 points to the first character of ConfigRequest.
4256 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigRequest or
4257 Block parameter would result in this type of
4258 error. Progress points to the first character of
4260 @retval EFI_DEVICE_ERROR Block not large enough. Progress undefined.
4261 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted string.
4262 Block is left updated and Progress points at
4263 the "&" preceding the first non-<BlockName>.
4269 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
4270 IN CONST EFI_STRING ConfigRequest
,
4271 IN CONST UINT8
*Block
,
4272 IN CONST UINTN BlockSize
,
4273 OUT EFI_STRING
*Config
,
4274 OUT EFI_STRING
*Progress
4277 HII_DATABASE_PRIVATE_DATA
*Private
;
4278 EFI_STRING StringPtr
;
4286 EFI_STRING ValueStr
;
4287 EFI_STRING ConfigElement
;
4293 if (This
== NULL
|| Progress
== NULL
|| Config
== NULL
) {
4294 return EFI_INVALID_PARAMETER
;
4297 if (Block
== NULL
|| ConfigRequest
== NULL
) {
4298 *Progress
= ConfigRequest
;
4299 return EFI_INVALID_PARAMETER
;
4303 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
4304 ASSERT (Private
!= NULL
);
4306 StringPtr
= ConfigRequest
;
4309 ConfigElement
= NULL
;
4312 // Allocate a fix length of memory to store Results. Reallocate memory for
4313 // Results if this fix length is insufficient.
4315 *Config
= (EFI_STRING
) AllocateZeroPool (MAX_STRING_LENGTH
);
4316 if (*Config
== NULL
) {
4317 return EFI_OUT_OF_RESOURCES
;
4323 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
4324 *Progress
= StringPtr
;
4325 Status
= EFI_INVALID_PARAMETER
;
4328 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"PATH=", StrLen (L
"PATH=")) != 0) {
4331 if (*StringPtr
== 0) {
4332 *Progress
= StringPtr
- 1;
4333 Status
= EFI_INVALID_PARAMETER
;
4337 while (*StringPtr
!= L
'&' && *StringPtr
!= 0) {
4340 if (*StringPtr
== 0) {
4341 *Progress
= StringPtr
;
4342 Status
= EFI_SUCCESS
;
4344 AppendToMultiString(Config
, ConfigRequest
);
4345 HiiToLower (*Config
);
4355 // Copy <ConfigHdr> and an additional '&' to <ConfigResp>
4357 TemChar
= *StringPtr
;
4359 AppendToMultiString(Config
, ConfigRequest
);
4360 *StringPtr
= TemChar
;
4363 // Parse each <RequestElement> if exists
4364 // Only <BlockName> format is supported by this help function.
4365 // <BlockName> ::= 'OFFSET='<Number>&'WIDTH='<Number>
4367 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"OFFSET=", StrLen (L
"OFFSET=")) == 0) {
4369 // Back up the header of one <BlockName>
4373 StringPtr
+= StrLen (L
"OFFSET=");
4377 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
4378 if (EFI_ERROR (Status
)) {
4379 *Progress
= TmpPtr
- 1;
4386 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
4388 FreePool (TmpBuffer
);
4390 StringPtr
+= Length
;
4391 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
4392 *Progress
= TmpPtr
- 1;
4393 Status
= EFI_INVALID_PARAMETER
;
4396 StringPtr
+= StrLen (L
"&WIDTH=");
4401 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
4402 if (EFI_ERROR (Status
)) {
4403 *Progress
= TmpPtr
- 1;
4410 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
4412 FreePool (TmpBuffer
);
4414 StringPtr
+= Length
;
4415 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
4416 *Progress
= TmpPtr
- 1;
4417 Status
= EFI_INVALID_PARAMETER
;
4422 // Calculate Value and convert it to hex string.
4424 if (Offset
+ Width
> BlockSize
) {
4425 *Progress
= StringPtr
;
4426 Status
= EFI_DEVICE_ERROR
;
4430 Value
= (UINT8
*) AllocateZeroPool (Width
);
4431 if (Value
== NULL
) {
4432 *Progress
= ConfigRequest
;
4433 Status
= EFI_OUT_OF_RESOURCES
;
4437 CopyMem (Value
, (UINT8
*) Block
+ Offset
, Width
);
4439 Length
= Width
* 2 + 1;
4440 ValueStr
= (EFI_STRING
) AllocateZeroPool (Length
* sizeof (CHAR16
));
4441 if (ValueStr
== NULL
) {
4442 *Progress
= ConfigRequest
;
4443 Status
= EFI_OUT_OF_RESOURCES
;
4447 TemString
= ValueStr
;
4448 TemBuffer
= Value
+ Width
- 1;
4449 for (Index
= 0; Index
< Width
; Index
++, TemBuffer
--) {
4450 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
4457 // Build a ConfigElement
4459 Length
+= StringPtr
- TmpPtr
+ 1 + StrLen (L
"VALUE=");
4460 ConfigElement
= (EFI_STRING
) AllocateZeroPool (Length
* sizeof (CHAR16
));
4461 if (ConfigElement
== NULL
) {
4462 Status
= EFI_OUT_OF_RESOURCES
;
4465 CopyMem (ConfigElement
, TmpPtr
, (StringPtr
- TmpPtr
+ 1) * sizeof (CHAR16
));
4466 if (*StringPtr
== 0) {
4467 *(ConfigElement
+ (StringPtr
- TmpPtr
)) = L
'&';
4469 *(ConfigElement
+ (StringPtr
- TmpPtr
) + 1) = 0;
4470 StrCat (ConfigElement
, L
"VALUE=");
4471 StrCat (ConfigElement
, ValueStr
);
4473 AppendToMultiString (Config
, ConfigElement
);
4475 FreePool (ConfigElement
);
4476 FreePool (ValueStr
);
4477 ConfigElement
= NULL
;
4481 // If '\0', parsing is finished. Otherwise skip '&' to continue
4483 if (*StringPtr
== 0) {
4486 AppendToMultiString (Config
, L
"&");
4491 if (*StringPtr
!= 0) {
4492 *Progress
= StringPtr
- 1;
4493 Status
= EFI_INVALID_PARAMETER
;
4497 HiiToLower (*Config
);
4498 *Progress
= StringPtr
;
4502 if (*Config
!= NULL
) {
4506 if (ValueStr
!= NULL
) {
4507 FreePool (ValueStr
);
4509 if (Value
!= NULL
) {
4512 if (ConfigElement
!= NULL
) {
4513 FreePool (ConfigElement
);
4522 This helper function is to be called by drivers to map configuration strings
4523 to configurations stored in byte array ("block") formats such as UEFI Variables.
4525 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
4527 @param ConfigResp A null-terminated Unicode string in <ConfigResp>
4529 @param Block A possibly null array of bytes representing the
4530 current block. Only bytes referenced in the
4531 ConfigResp string in the block are modified. If
4532 this parameter is null or if the *BlockSize
4533 parameter is (on input) shorter than required by
4534 the Configuration string, only the BlockSize
4535 parameter is updated and an appropriate status
4536 (see below) is returned.
4537 @param BlockSize The length of the Block in units of UINT8. On
4538 input, this is the size of the Block. On output,
4539 if successful, contains the largest index of the
4540 modified byte in the Block, or the required buffer
4541 size if the Block is not large enough.
4542 @param Progress On return, points to an element of the ConfigResp
4543 string filled in with the offset of the most
4544 recent '&' before the first failing name / value
4545 pair (or the beginning of the string if the
4546 failure is in the first name / value pair) or the
4547 terminating NULL if all was successful.
4549 @retval EFI_SUCCESS The request succeeded. Progress points to the null
4550 terminator at the end of the ConfigResp string.
4551 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress
4552 points to the first character of ConfigResp.
4553 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigResp or
4554 Block parameter would result in this type of
4555 error. Progress points to the first character of
4557 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted name /
4558 value pair. Block is left updated and
4559 Progress points at the '&' preceding the first
4561 @retval EFI_BUFFER_TOO_SMALL Block not large enough. Progress undefined.
4562 BlockSize is updated with the required buffer size.
4563 @retval EFI_NOT_FOUND Target for the specified routing data was not found.
4564 Progress points to the "G" in "GUID" of the errant
4571 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
4572 IN CONST EFI_STRING ConfigResp
,
4573 IN OUT UINT8
*Block
,
4574 IN OUT UINTN
*BlockSize
,
4575 OUT EFI_STRING
*Progress
4578 HII_DATABASE_PRIVATE_DATA
*Private
;
4579 EFI_STRING StringPtr
;
4590 if (This
== NULL
|| BlockSize
== NULL
|| Progress
== NULL
) {
4591 return EFI_INVALID_PARAMETER
;
4594 *Progress
= ConfigResp
;
4595 if (ConfigResp
== NULL
) {
4596 return EFI_INVALID_PARAMETER
;
4599 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
4600 ASSERT (Private
!= NULL
);
4602 StringPtr
= ConfigResp
;
4603 BufferSize
= *BlockSize
;
4610 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
4611 *Progress
= StringPtr
;
4612 Status
= EFI_INVALID_PARAMETER
;
4615 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"PATH=", StrLen (L
"PATH=")) != 0) {
4618 if (*StringPtr
== 0) {
4619 *Progress
= StringPtr
;
4620 Status
= EFI_INVALID_PARAMETER
;
4624 while (*StringPtr
!= L
'&' && *StringPtr
!= 0) {
4627 if (*StringPtr
== 0) {
4628 *Progress
= StringPtr
;
4629 Status
= EFI_INVALID_PARAMETER
;
4634 // Parse each <ConfigElement> if exists
4635 // Only '&'<BlockConfig> format is supported by this help function.
4636 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE='<Number>
4638 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) == 0) {
4640 StringPtr
+= StrLen (L
"&OFFSET=");
4644 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
4645 if (EFI_ERROR (Status
)) {
4653 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
4655 FreePool (TmpBuffer
);
4657 StringPtr
+= Length
;
4658 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
4660 Status
= EFI_INVALID_PARAMETER
;
4663 StringPtr
+= StrLen (L
"&WIDTH=");
4668 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
4669 if (EFI_ERROR (Status
)) {
4677 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
4679 FreePool (TmpBuffer
);
4681 StringPtr
+= Length
;
4682 if (StrnCmp (StringPtr
, L
"&VALUE=", StrLen (L
"&VALUE=")) != 0) {
4684 Status
= EFI_INVALID_PARAMETER
;
4687 StringPtr
+= StrLen (L
"&VALUE=");
4692 Status
= GetValueOfNumber (StringPtr
, &Value
, &Length
);
4693 if (EFI_ERROR (Status
)) {
4698 StringPtr
+= Length
;
4699 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
4701 Status
= EFI_INVALID_PARAMETER
;
4706 // Update the Block with configuration info
4708 if ((Block
!= NULL
) && (Offset
+ Width
<= BufferSize
)) {
4709 CopyMem (Block
+ Offset
, Value
, Width
);
4711 if (Offset
+ Width
> MaxBlockSize
) {
4712 MaxBlockSize
= Offset
+ Width
;
4719 // If '\0', parsing is finished.
4721 if (*StringPtr
== 0) {
4727 // The input string is not ConfigResp format, return error.
4729 if (*StringPtr
!= 0) {
4730 *Progress
= StringPtr
;
4731 Status
= EFI_INVALID_PARAMETER
;
4735 *Progress
= StringPtr
+ StrLen (StringPtr
);
4736 *BlockSize
= MaxBlockSize
- 1;
4738 if (MaxBlockSize
> BufferSize
) {
4739 *BlockSize
= MaxBlockSize
;
4740 if (Block
!= NULL
) {
4741 return EFI_BUFFER_TOO_SMALL
;
4745 if (Block
== NULL
) {
4746 *Progress
= ConfigResp
;
4747 return EFI_INVALID_PARAMETER
;
4754 if (Value
!= NULL
) {
4762 This helper function is to be called by drivers to extract portions of
4763 a larger configuration string.
4765 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
4767 @param Configuration A null-terminated Unicode string in
4768 <MultiConfigAltResp> format.
4769 @param Guid A pointer to the GUID value to search for in the
4770 routing portion of the ConfigResp string when
4771 retrieving the requested data. If Guid is NULL,
4772 then all GUID values will be searched for.
4773 @param Name A pointer to the NAME value to search for in the
4774 routing portion of the ConfigResp string when
4775 retrieving the requested data. If Name is NULL,
4776 then all Name values will be searched for.
4777 @param DevicePath A pointer to the PATH value to search for in the
4778 routing portion of the ConfigResp string when
4779 retrieving the requested data. If DevicePath is
4780 NULL, then all DevicePath values will be searched
4782 @param AltCfgId A pointer to the ALTCFG value to search for in the
4783 routing portion of the ConfigResp string when
4784 retrieving the requested data. If this parameter
4785 is NULL, then the current setting will be
4787 @param AltCfgResp A pointer to a buffer which will be allocated by
4788 the function which contains the retrieved string
4789 as requested. This buffer is only allocated if
4790 the call was successful. It is <ConfigResp> format.
4792 @retval EFI_SUCCESS The request succeeded. The requested data was
4793 extracted and placed in the newly allocated
4795 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate AltCfgResp.
4796 @retval EFI_INVALID_PARAMETER Any parameter is invalid.
4797 @retval EFI_NOT_FOUND Target for the specified routing data was not
4804 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
4805 IN CONST EFI_STRING Configuration
,
4806 IN CONST EFI_GUID
*Guid
,
4807 IN CONST EFI_STRING Name
,
4808 IN CONST EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
4809 IN CONST UINT16
*AltCfgId
,
4810 OUT EFI_STRING
*AltCfgResp
4814 EFI_STRING StringPtr
;
4815 EFI_STRING HdrStart
;
4822 EFI_STRING AltIdStr
;
4839 if (This
== NULL
|| Configuration
== NULL
|| AltCfgResp
== NULL
) {
4840 return EFI_INVALID_PARAMETER
;
4843 StringPtr
= Configuration
;
4844 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
4845 return EFI_INVALID_PARAMETER
;
4849 // Generate the sub string for later matching.
4851 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*) Guid
, 1, &GuidStr
);
4854 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) DevicePath
),
4855 (VOID
*) DevicePath
,
4859 if (AltCfgId
!= NULL
) {
4860 GenerateSubStr (L
"ALTCFG=", sizeof (UINT16
), (VOID
*) AltCfgId
, 3, &AltIdStr
);
4863 GenerateSubStr (L
"NAME=", StrLen (Name
) * sizeof (CHAR16
), (VOID
*) Name
, 2, &NameStr
);
4865 GenerateSubStr (L
"NAME=", 0, NULL
, 2, &NameStr
);
4868 while (*StringPtr
!= 0) {
4870 // Try to match the GUID
4873 TmpPtr
= StrStr (StringPtr
, GuidStr
);
4874 if (TmpPtr
== NULL
) {
4875 Status
= EFI_NOT_FOUND
;
4881 // Jump to <NameHdr>
4884 StringPtr
= TmpPtr
+ StrLen (GuidStr
);
4886 StringPtr
= StrStr (TmpPtr
, L
"NAME=");
4887 if (StringPtr
== NULL
) {
4888 Status
= EFI_NOT_FOUND
;
4896 // Try to match the NAME
4898 if (GuidFlag
&& !NameFlag
) {
4899 if (StrnCmp (StringPtr
, NameStr
, StrLen (NameStr
)) != 0) {
4903 // Jump to <PathHdr>
4906 StringPtr
+= StrLen (NameStr
);
4908 StringPtr
= StrStr (StringPtr
, L
"PATH=");
4909 if (StringPtr
== NULL
) {
4910 Status
= EFI_NOT_FOUND
;
4919 // Try to match the DevicePath
4921 if (GuidFlag
&& NameFlag
&& !PathFlag
) {
4922 if (StrnCmp (StringPtr
, PathStr
, StrLen (PathStr
)) != 0) {
4927 // Jump to '&' before <DescHdr> or <ConfigBody>
4929 if (DevicePath
!= NULL
) {
4930 StringPtr
+= StrLen (PathStr
);
4932 StringPtr
= StrStr (StringPtr
, L
"&");
4933 if (StringPtr
== NULL
) {
4934 Status
= EFI_NOT_FOUND
;
4945 // Try to match the AltCfgId
4947 if (GuidFlag
&& NameFlag
&& PathFlag
) {
4948 if (AltCfgId
== NULL
) {
4950 // Return Current Setting when AltCfgId is NULL.
4952 Status
= OutputConfigBody (StringPtr
, &Result
);
4956 // Search the <ConfigAltResp> to get the <AltResp> with AltCfgId.
4958 if (StrnCmp (StringPtr
, AltIdStr
, StrLen (AltIdStr
)) != 0) {
4964 // Skip AltIdStr and &
4966 StringPtr
= StringPtr
+ StrLen (AltIdStr
);
4967 Status
= OutputConfigBody (StringPtr
, &Result
);
4973 Status
= EFI_NOT_FOUND
;
4977 if (!EFI_ERROR (Status
) && (Result
!= NULL
)) {
4979 // Copy the <ConfigHdr> and <ConfigBody>
4981 Length
= HdrEnd
- HdrStart
+ StrLen (Result
) + 1;
4982 *AltCfgResp
= AllocateZeroPool (Length
* sizeof (CHAR16
));
4983 if (*AltCfgResp
== NULL
) {
4984 Status
= EFI_OUT_OF_RESOURCES
;
4986 StrnCpy (*AltCfgResp
, HdrStart
, HdrEnd
- HdrStart
);
4987 StrCat (*AltCfgResp
, Result
);
4988 Status
= EFI_SUCCESS
;
4992 if (GuidStr
!= NULL
) {
4995 if (NameStr
!= NULL
) {
4998 if (PathStr
!= NULL
) {
5001 if (AltIdStr
!= NULL
) {
5002 FreePool (AltIdStr
);
5004 if (Result
!= NULL
) {