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 EFI_IFR_OP_HEADER
*IfrOpHdr
;
1113 CHAR16
*VarStoreName
;
1118 UINT8
*HiiFormPackage
;
1120 EFI_IFR_VARSTORE_EFI
*IfrEfiVarStore
;
1122 HiiFormPackage
= NULL
;
1124 Status
= EFI_SUCCESS
;
1129 Status
= GetFormPackageData(DataBaseRecord
, &HiiFormPackage
, &PackageSize
);
1130 if (EFI_ERROR (Status
)) {
1134 IfrOffset
= sizeof (EFI_HII_PACKAGE_HEADER
);
1135 while (IfrOffset
< PackageSize
) {
1136 IfrOpHdr
= (EFI_IFR_OP_HEADER
*) (HiiFormPackage
+ IfrOffset
);
1137 IfrOffset
+= IfrOpHdr
->Length
;
1139 if (IfrOpHdr
->OpCode
== EFI_IFR_VARSTORE_EFI_OP
) {
1140 IfrEfiVarStore
= (EFI_IFR_VARSTORE_EFI
*) IfrOpHdr
;
1142 // If the length is small than the structure, this is from old efi
1143 // varstore definition. Old efi varstore get config directly from
1144 // GetVariable function.
1146 if (IfrOpHdr
->Length
< sizeof (EFI_IFR_VARSTORE_EFI
)) {
1150 VarStoreName
= AllocateZeroPool (AsciiStrSize ((CHAR8
*)IfrEfiVarStore
->Name
) * sizeof (CHAR16
));
1151 if (VarStoreName
== NULL
) {
1152 Status
= EFI_OUT_OF_RESOURCES
;
1155 AsciiStrToUnicodeStr ((CHAR8
*) IfrEfiVarStore
->Name
, VarStoreName
);
1157 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*) &IfrEfiVarStore
->Guid
, 1, &GuidStr
);
1158 GenerateSubStr (L
"NAME=", StrLen (VarStoreName
) * sizeof (CHAR16
), (VOID
*) VarStoreName
, 2, &NameStr
);
1159 LengthString
= StrLen (GuidStr
);
1160 LengthString
= LengthString
+ StrLen (NameStr
) + 1;
1161 TempStr
= AllocateZeroPool (LengthString
* sizeof (CHAR16
));
1162 if (TempStr
== NULL
) {
1165 FreePool (VarStoreName
);
1166 Status
= EFI_OUT_OF_RESOURCES
;
1169 StrCpy (TempStr
, GuidStr
);
1170 StrCat (TempStr
, NameStr
);
1171 if (ConfigHdr
== NULL
|| StrnCmp (ConfigHdr
, TempStr
, StrLen (TempStr
)) == 0) {
1172 *EfiVarStore
= (EFI_IFR_VARSTORE_EFI
*) AllocateZeroPool (IfrOpHdr
->Length
);
1173 if (*EfiVarStore
== NULL
) {
1174 FreePool (VarStoreName
);
1178 Status
= EFI_OUT_OF_RESOURCES
;
1181 *IsEfiVarstore
= TRUE
;
1182 CopyMem (*EfiVarStore
, IfrEfiVarStore
, IfrOpHdr
->Length
);
1186 // Free alllocated temp string.
1188 FreePool (VarStoreName
);
1195 if (HiiFormPackage
!= NULL
) {
1196 FreePool (HiiFormPackage
);
1203 Check whether the ConfigRequest string has the request elements.
1204 For EFI_HII_VARSTORE_BUFFER type, the request has "&OFFSET=****&WIDTH=****..." format.
1205 For EFI_HII_VARSTORE_NAME_VALUE type, the request has "&NAME1**&NAME2..." format.
1207 @param ConfigRequest The input config request string.
1209 @retval TRUE The input include config request elements.
1210 @retval FALSE The input string not includes.
1214 GetElementsFromRequest (
1215 IN EFI_STRING ConfigRequest
1218 EFI_STRING TmpRequest
;
1220 TmpRequest
= StrStr (ConfigRequest
, L
"PATH=");
1221 ASSERT (TmpRequest
!= NULL
);
1223 if ((StrStr (TmpRequest
, L
"&OFFSET=") != NULL
) || (StrStr (TmpRequest
, L
"&") != NULL
)) {
1231 Check whether the this varstore is the request varstore.
1233 @param VarstoreGuid Varstore guid.
1234 @param Name Varstore name.
1235 @param ConfigHdr Current configRequest info.
1237 @retval TRUE This varstore is the requst one.
1238 @retval FALSE This varstore is not the requst one.
1243 IN EFI_GUID
*VarstoreGuid
,
1245 IN CHAR16
*ConfigHdr
1258 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*)VarstoreGuid
, 1, &GuidStr
);
1260 GenerateSubStr (L
"NAME=", StrLen (Name
) * sizeof (CHAR16
), (VOID
*) Name
, 2, &NameStr
);
1262 GenerateSubStr (L
"NAME=", 0, NULL
, 2, &NameStr
);
1264 LengthString
= StrLen (GuidStr
);
1265 LengthString
= LengthString
+ StrLen (NameStr
) + 1;
1266 TempStr
= AllocateZeroPool (LengthString
* sizeof (CHAR16
));
1267 if (TempStr
== NULL
) {
1271 StrCpy (TempStr
, GuidStr
);
1272 StrCat (TempStr
, NameStr
);
1274 if (ConfigHdr
== NULL
|| StrnCmp (ConfigHdr
, TempStr
, StrLen (TempStr
)) == 0) {
1279 if (GuidStr
!= NULL
) {
1283 if (NameStr
!= NULL
) {
1287 if (TempStr
!= NULL
) {
1295 Check whether the this op code is required.
1297 @param RequestBlockArray The array includes all the request info or NULL.
1298 @param HiiHandle The hii handle for this form package.
1299 @param VarStorageData The varstore data strucure.
1300 @param IfrOpHdr Ifr opcode header for this opcode.
1301 @param VarWidth The buffer width for this opcode.
1302 @param ReturnData The data block added for this opcode.
1304 @retval EFI_SUCCESS This opcode is required.
1305 @retval Others This opcode is not required or error occur.
1309 IsThisOpcodeRequired (
1310 IN IFR_BLOCK_DATA
*RequestBlockArray
,
1311 IN EFI_HII_HANDLE HiiHandle
,
1312 IN OUT IFR_VARSTORAGE_DATA
*VarStorageData
,
1313 IN EFI_IFR_OP_HEADER
*IfrOpHdr
,
1315 OUT IFR_BLOCK_DATA
**ReturnData
1318 IFR_BLOCK_DATA
*BlockData
;
1320 EFI_STRING_ID NameId
;
1321 EFI_IFR_QUESTION_HEADER
*IfrQuestionHdr
;
1325 IfrQuestionHdr
= (EFI_IFR_QUESTION_HEADER
*)((CHAR8
*) IfrOpHdr
+ sizeof (EFI_IFR_OP_HEADER
));
1327 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
1328 NameId
= IfrQuestionHdr
->VarStoreInfo
.VarName
;
1331 // Check whether this question is in requested block array.
1333 if (!BlockArrayCheck (RequestBlockArray
, NameId
, 0, TRUE
, HiiHandle
)) {
1335 // This question is not in the requested string. Skip it.
1340 VarOffset
= IfrQuestionHdr
->VarStoreInfo
.VarOffset
;
1343 // Check whether this question is in requested block array.
1345 if (!BlockArrayCheck (RequestBlockArray
, VarOffset
, VarWidth
, FALSE
, HiiHandle
)) {
1347 // This question is not in the requested string. Skip it.
1353 // Check this var question is in the var storage
1355 if (((VarOffset
+ VarWidth
) > VarStorageData
->Size
)) {
1356 return EFI_INVALID_PARAMETER
;
1360 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
1361 if (BlockData
== NULL
) {
1362 return EFI_OUT_OF_RESOURCES
;
1365 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
1366 BlockData
->Name
= InternalGetString(HiiHandle
, NameId
);
1368 BlockData
->Offset
= VarOffset
;
1371 BlockData
->Width
= VarWidth
;
1372 BlockData
->QuestionId
= IfrQuestionHdr
->QuestionId
;
1373 BlockData
->OpCode
= IfrOpHdr
->OpCode
;
1374 BlockData
->Scope
= IfrOpHdr
->Scope
;
1375 InitializeListHead (&BlockData
->DefaultValueEntry
);
1377 // Add Block Data into VarStorageData BlockEntry
1379 InsertBlockData (&VarStorageData
->BlockEntry
, &BlockData
);
1380 *ReturnData
= BlockData
;
1386 This function parses Form Package to get the block array and the default
1387 value array according to the request ConfigHdr.
1389 @param HiiHandle Hii Handle for this hii package.
1390 @param Package Pointer to the form package data.
1391 @param PackageLength Length of the pacakge.
1392 @param ConfigHdr Request string ConfigHdr. If it is NULL,
1393 the first found varstore will be as ConfigHdr.
1394 @param RequestBlockArray The block array is retrieved from the request string.
1395 @param VarStorageData VarStorage structure contains the got block and default value.
1396 @param DefaultIdArray Point to the got default id and default name array.
1398 @retval EFI_SUCCESS The block array and the default value array are got.
1399 @retval EFI_INVALID_PARAMETER The varstore defintion in the differnt form pacakges
1401 @retval EFI_OUT_OF_RESOURCES No enough memory.
1406 IN EFI_HII_HANDLE HiiHandle
,
1408 IN UINT32 PackageLength
,
1409 IN EFI_STRING ConfigHdr
,
1410 IN IFR_BLOCK_DATA
*RequestBlockArray
,
1411 IN OUT IFR_VARSTORAGE_DATA
*VarStorageData
,
1412 OUT IFR_DEFAULT_DATA
*DefaultIdArray
1417 EFI_IFR_VARSTORE
*IfrVarStore
;
1418 EFI_IFR_VARSTORE_EFI
*IfrEfiVarStore
;
1419 EFI_IFR_OP_HEADER
*IfrOpHdr
;
1420 EFI_IFR_ONE_OF
*IfrOneOf
;
1421 EFI_IFR_REF4
*IfrRef
;
1422 EFI_IFR_ONE_OF_OPTION
*IfrOneOfOption
;
1423 EFI_IFR_DEFAULT
*IfrDefault
;
1424 EFI_IFR_ORDERED_LIST
*IfrOrderedList
;
1425 EFI_IFR_CHECKBOX
*IfrCheckBox
;
1426 EFI_IFR_PASSWORD
*IfrPassword
;
1427 EFI_IFR_STRING
*IfrString
;
1428 EFI_IFR_DATE
*IfrDate
;
1429 EFI_IFR_TIME
*IfrTime
;
1430 IFR_DEFAULT_DATA DefaultData
;
1431 IFR_DEFAULT_DATA
*DefaultDataPtr
;
1432 IFR_BLOCK_DATA
*BlockData
;
1433 CHAR16
*VarStoreName
;
1435 UINT16 VarDefaultId
;
1436 BOOLEAN FirstOneOfOption
;
1437 LIST_ENTRY
*LinkData
;
1438 LIST_ENTRY
*LinkDefault
;
1439 EFI_IFR_VARSTORE_NAME_VALUE
*IfrNameValueVarStore
;
1441 Status
= EFI_SUCCESS
;
1443 DefaultDataPtr
= NULL
;
1444 FirstOneOfOption
= FALSE
;
1445 ZeroMem (&DefaultData
, sizeof (IFR_DEFAULT_DATA
));
1448 // Go through the form package to parse OpCode one by one.
1450 IfrOffset
= sizeof (EFI_HII_PACKAGE_HEADER
);
1451 while (IfrOffset
< PackageLength
) {
1452 IfrOpHdr
= (EFI_IFR_OP_HEADER
*) (Package
+ IfrOffset
);
1453 switch (IfrOpHdr
->OpCode
) {
1454 case EFI_IFR_VARSTORE_OP
:
1456 // VarStore is found. Don't need to search any more.
1458 if (VarStorageData
->VarStoreId
!= 0) {
1462 IfrVarStore
= (EFI_IFR_VARSTORE
*) IfrOpHdr
;
1464 VarStoreName
= AllocateZeroPool (AsciiStrSize ((CHAR8
*)IfrVarStore
->Name
) * sizeof (CHAR16
));
1465 if (VarStoreName
== NULL
) {
1466 Status
= EFI_OUT_OF_RESOURCES
;
1469 AsciiStrToUnicodeStr ((CHAR8
*)IfrVarStore
->Name
, VarStoreName
);
1471 if (IsThisVarstore((VOID
*)&IfrVarStore
->Guid
, VarStoreName
, ConfigHdr
)) {
1473 // Find the matched VarStore
1475 CopyGuid (&VarStorageData
->Guid
, (EFI_GUID
*) (VOID
*) &IfrVarStore
->Guid
);
1476 VarStorageData
->VarStoreId
= IfrVarStore
->VarStoreId
;
1477 VarStorageData
->Size
= IfrVarStore
->Size
;
1478 VarStorageData
->Name
= VarStoreName
;
1479 VarStorageData
->Type
= EFI_HII_VARSTORE_BUFFER
;
1483 case EFI_IFR_VARSTORE_EFI_OP
:
1485 // VarStore is found. Don't need to search any more.
1487 if (VarStorageData
->VarStoreId
!= 0) {
1491 IfrEfiVarStore
= (EFI_IFR_VARSTORE_EFI
*) IfrOpHdr
;
1494 // If the length is small than the structure, this is from old efi
1495 // varstore definition. Old efi varstore get config directly from
1496 // GetVariable function.
1498 if (IfrOpHdr
->Length
< sizeof (EFI_IFR_VARSTORE_EFI
)) {
1502 VarStoreName
= AllocateZeroPool (AsciiStrSize ((CHAR8
*)IfrEfiVarStore
->Name
) * sizeof (CHAR16
));
1503 if (VarStoreName
== NULL
) {
1504 Status
= EFI_OUT_OF_RESOURCES
;
1507 AsciiStrToUnicodeStr ((CHAR8
*)IfrEfiVarStore
->Name
, VarStoreName
);
1509 if (IsThisVarstore (&IfrEfiVarStore
->Guid
, VarStoreName
, ConfigHdr
)) {
1511 // Find the matched VarStore
1513 CopyGuid (&VarStorageData
->Guid
, (EFI_GUID
*) (VOID
*) &IfrEfiVarStore
->Guid
);
1514 VarStorageData
->VarStoreId
= IfrEfiVarStore
->VarStoreId
;
1515 VarStorageData
->Size
= IfrEfiVarStore
->Size
;
1516 VarStorageData
->Name
= VarStoreName
;
1517 VarStorageData
->Type
= EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
;
1521 case EFI_IFR_VARSTORE_NAME_VALUE_OP
:
1523 // VarStore is found. Don't need to search any more.
1525 if (VarStorageData
->VarStoreId
!= 0) {
1529 IfrNameValueVarStore
= (EFI_IFR_VARSTORE_NAME_VALUE
*) IfrOpHdr
;
1531 if (IsThisVarstore (&IfrNameValueVarStore
->Guid
, NULL
, ConfigHdr
)) {
1533 // Find the matched VarStore
1535 CopyGuid (&VarStorageData
->Guid
, (EFI_GUID
*) (VOID
*) &IfrNameValueVarStore
->Guid
);
1536 VarStorageData
->VarStoreId
= IfrNameValueVarStore
->VarStoreId
;
1537 VarStorageData
->Type
= EFI_HII_VARSTORE_NAME_VALUE
;
1541 case EFI_IFR_DEFAULTSTORE_OP
:
1543 // Add new the map between default id and default name.
1545 DefaultDataPtr
= (IFR_DEFAULT_DATA
*) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
1546 if (DefaultDataPtr
== NULL
) {
1547 Status
= EFI_OUT_OF_RESOURCES
;
1550 DefaultDataPtr
->DefaultId
= ((EFI_IFR_DEFAULTSTORE
*) IfrOpHdr
)->DefaultId
;
1551 InsertTailList (&DefaultIdArray
->Entry
, &DefaultDataPtr
->Entry
);
1552 DefaultDataPtr
= NULL
;
1555 case EFI_IFR_FORM_OP
:
1556 case EFI_IFR_FORM_MAP_OP
:
1558 // No matched varstore is found and directly return.
1560 if (VarStorageData
->VarStoreId
== 0) {
1561 Status
= EFI_SUCCESS
;
1566 case EFI_IFR_REF_OP
:
1568 // Ref question is not in IFR Form. This IFR form is not valid.
1570 if (VarStorageData
->VarStoreId
== 0) {
1571 Status
= EFI_INVALID_PARAMETER
;
1575 // Check whether this question is for the requested varstore.
1577 IfrRef
= (EFI_IFR_REF4
*) IfrOpHdr
;
1578 if (IfrRef
->Question
.VarStoreId
!= VarStorageData
->VarStoreId
) {
1581 VarWidth
= (UINT16
) (sizeof (EFI_HII_REF
));
1583 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
1584 if (EFI_ERROR (Status
)) {
1589 case EFI_IFR_ONE_OF_OP
:
1590 case EFI_IFR_NUMERIC_OP
:
1592 // Numeric and OneOf has the same opcode structure.
1596 // Numeric and OneOf question is not in IFR Form. This IFR form is not valid.
1598 if (VarStorageData
->VarStoreId
== 0) {
1599 Status
= EFI_INVALID_PARAMETER
;
1603 // Check whether this question is for the requested varstore.
1605 IfrOneOf
= (EFI_IFR_ONE_OF
*) IfrOpHdr
;
1606 if (IfrOneOf
->Question
.VarStoreId
!= VarStorageData
->VarStoreId
) {
1609 VarWidth
= (UINT16
) (1 << (IfrOneOf
->Flags
& EFI_IFR_NUMERIC_SIZE
));
1611 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
1612 if (EFI_ERROR (Status
)) {
1616 if (BlockData
== NULL
) {
1618 // BlockData == NULL means this opcode is not in the requst array.
1623 if (IfrOpHdr
->OpCode
== EFI_IFR_ONE_OF_OP
) {
1625 // Set this flag to TRUE for the first oneof option.
1627 FirstOneOfOption
= TRUE
;
1628 } else if (IfrOpHdr
->OpCode
== EFI_IFR_NUMERIC_OP
) {
1630 // Numeric minimum value will be used as default value when no default is specified.
1632 DefaultData
.Type
= DefaultValueFromDefault
;
1633 switch (IfrOneOf
->Flags
& EFI_IFR_NUMERIC_SIZE
) {
1634 case EFI_IFR_NUMERIC_SIZE_1
:
1635 DefaultData
.Value
.u8
= IfrOneOf
->data
.u8
.MinValue
;
1638 case EFI_IFR_NUMERIC_SIZE_2
:
1639 CopyMem (&DefaultData
.Value
.u16
, &IfrOneOf
->data
.u16
.MinValue
, sizeof (UINT16
));
1642 case EFI_IFR_NUMERIC_SIZE_4
:
1643 CopyMem (&DefaultData
.Value
.u32
, &IfrOneOf
->data
.u32
.MinValue
, sizeof (UINT32
));
1646 case EFI_IFR_NUMERIC_SIZE_8
:
1647 CopyMem (&DefaultData
.Value
.u64
, &IfrOneOf
->data
.u64
.MinValue
, sizeof (UINT64
));
1651 Status
= EFI_INVALID_PARAMETER
;
1655 // Set default value base on the DefaultId list get from IFR data.
1657 for (LinkData
= DefaultIdArray
->Entry
.ForwardLink
; LinkData
!= &DefaultIdArray
->Entry
; LinkData
= LinkData
->ForwardLink
) {
1658 DefaultDataPtr
= BASE_CR (LinkData
, IFR_DEFAULT_DATA
, Entry
);
1659 DefaultData
.DefaultId
= DefaultDataPtr
->DefaultId
;
1660 InsertDefaultValue (BlockData
, &DefaultData
);
1665 case EFI_IFR_ORDERED_LIST_OP
:
1667 // offset by question header
1668 // width by EFI_IFR_ORDERED_LIST MaxContainers * OneofOption Type
1669 // no default value and default id, how to define its default value?
1673 // OrderedList question is not in IFR Form. This IFR form is not valid.
1675 if (VarStorageData
->VarStoreId
== 0) {
1676 Status
= EFI_INVALID_PARAMETER
;
1680 // Check whether this question is for the requested varstore.
1682 IfrOrderedList
= (EFI_IFR_ORDERED_LIST
*) IfrOpHdr
;
1683 if (IfrOrderedList
->Question
.VarStoreId
!= VarStorageData
->VarStoreId
) {
1687 VarWidth
= IfrOrderedList
->MaxContainers
;
1688 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
1689 if (EFI_ERROR (Status
)) {
1694 case EFI_IFR_CHECKBOX_OP
:
1696 // EFI_IFR_DEFAULT_OP
1697 // offset by question header
1698 // width is 1 sizeof (BOOLEAN)
1699 // default id by CheckBox Flags if CheckBox flags (Default or Mau) is set, the default value is 1 to be set.
1700 // value by DefaultOption
1701 // default id by DeaultOption DefaultId can override CheckBox Flags and Default value.
1705 // CheckBox question is not in IFR Form. This IFR form is not valid.
1707 if (VarStorageData
->VarStoreId
== 0) {
1708 Status
= EFI_INVALID_PARAMETER
;
1712 // Check whether this question is for the requested varstore.
1714 IfrCheckBox
= (EFI_IFR_CHECKBOX
*) IfrOpHdr
;
1715 if (IfrCheckBox
->Question
.VarStoreId
!= VarStorageData
->VarStoreId
) {
1718 VarWidth
= (UINT16
) sizeof (BOOLEAN
);
1719 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
1720 if (EFI_ERROR (Status
)) {
1724 if (BlockData
== NULL
) {
1726 // BlockData == NULL means this opcode is not in the requst array.
1732 // Add default value for standard ID by CheckBox Flag
1734 VarDefaultId
= EFI_HII_DEFAULT_CLASS_STANDARD
;
1736 // Prepare new DefaultValue
1738 DefaultData
.DefaultId
= VarDefaultId
;
1739 if ((IfrCheckBox
->Flags
& EFI_IFR_CHECKBOX_DEFAULT
) == EFI_IFR_CHECKBOX_DEFAULT
) {
1741 // When flag is set, defautl value is TRUE.
1743 DefaultData
.Type
= DefaultValueFromFlag
;
1744 DefaultData
.Value
.b
= TRUE
;
1747 // When flag is not set, defautl value is FASLE.
1749 DefaultData
.Type
= DefaultValueFromDefault
;
1750 DefaultData
.Value
.b
= FALSE
;
1753 // Add DefaultValue into current BlockData
1755 InsertDefaultValue (BlockData
, &DefaultData
);
1758 // Add default value for Manufacture ID by CheckBox Flag
1760 VarDefaultId
= EFI_HII_DEFAULT_CLASS_MANUFACTURING
;
1762 // Prepare new DefaultValue
1764 DefaultData
.DefaultId
= VarDefaultId
;
1765 if ((IfrCheckBox
->Flags
& EFI_IFR_CHECKBOX_DEFAULT_MFG
) == EFI_IFR_CHECKBOX_DEFAULT_MFG
) {
1767 // When flag is set, defautl value is TRUE.
1769 DefaultData
.Type
= DefaultValueFromFlag
;
1770 DefaultData
.Value
.b
= TRUE
;
1773 // When flag is not set, defautl value is FASLE.
1775 DefaultData
.Type
= DefaultValueFromDefault
;
1776 DefaultData
.Value
.b
= FALSE
;
1779 // Add DefaultValue into current BlockData
1781 InsertDefaultValue (BlockData
, &DefaultData
);
1784 case EFI_IFR_DATE_OP
:
1786 // offset by question header
1787 // width MaxSize * sizeof (CHAR16)
1788 // no default value, only block array
1792 // Date question is not in IFR Form. This IFR form is not valid.
1794 if (VarStorageData
->VarStoreId
== 0) {
1795 Status
= EFI_INVALID_PARAMETER
;
1799 // Check whether this question is for the requested varstore.
1801 IfrDate
= (EFI_IFR_DATE
*) IfrOpHdr
;
1802 if (IfrDate
->Question
.VarStoreId
!= VarStorageData
->VarStoreId
) {
1806 VarWidth
= (UINT16
) sizeof (EFI_HII_DATE
);
1807 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
1808 if (EFI_ERROR (Status
)) {
1813 case EFI_IFR_TIME_OP
:
1815 // offset by question header
1816 // width MaxSize * sizeof (CHAR16)
1817 // no default value, only block array
1821 // Time question is not in IFR Form. This IFR form is not valid.
1823 if (VarStorageData
->VarStoreId
== 0) {
1824 Status
= EFI_INVALID_PARAMETER
;
1828 // Check whether this question is for the requested varstore.
1830 IfrTime
= (EFI_IFR_TIME
*) IfrOpHdr
;
1831 if (IfrTime
->Question
.VarStoreId
!= VarStorageData
->VarStoreId
) {
1835 VarWidth
= (UINT16
) sizeof (EFI_HII_TIME
);
1836 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
1837 if (EFI_ERROR (Status
)) {
1842 case EFI_IFR_STRING_OP
:
1844 // offset by question header
1845 // width MaxSize * sizeof (CHAR16)
1846 // no default value, only block array
1850 // String question is not in IFR Form. This IFR form is not valid.
1852 if (VarStorageData
->VarStoreId
== 0) {
1853 Status
= EFI_INVALID_PARAMETER
;
1857 // Check whether this question is for the requested varstore.
1859 IfrString
= (EFI_IFR_STRING
*) IfrOpHdr
;
1860 if (IfrString
->Question
.VarStoreId
!= VarStorageData
->VarStoreId
) {
1864 VarWidth
= (UINT16
) (IfrString
->MaxSize
* sizeof (UINT16
));
1865 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
1866 if (EFI_ERROR (Status
)) {
1871 // No default value for string.
1876 case EFI_IFR_PASSWORD_OP
:
1878 // offset by question header
1879 // width MaxSize * sizeof (CHAR16)
1880 // no default value, only block array
1884 // Password question is not in IFR Form. This IFR form is not valid.
1886 if (VarStorageData
->VarStoreId
== 0) {
1887 Status
= EFI_INVALID_PARAMETER
;
1891 // Check whether this question is for the requested varstore.
1893 IfrPassword
= (EFI_IFR_PASSWORD
*) IfrOpHdr
;
1894 if (IfrPassword
->Question
.VarStoreId
!= VarStorageData
->VarStoreId
) {
1898 VarWidth
= (UINT16
) (IfrPassword
->MaxSize
* sizeof (UINT16
));
1899 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
1900 if (EFI_ERROR (Status
)) {
1905 // No default value for string.
1910 case EFI_IFR_ONE_OF_OPTION_OP
:
1912 // No matched block data is ignored.
1914 if (BlockData
== NULL
|| BlockData
->Scope
== 0) {
1918 IfrOneOfOption
= (EFI_IFR_ONE_OF_OPTION
*) IfrOpHdr
;
1919 if (BlockData
->OpCode
== EFI_IFR_ORDERED_LIST_OP
) {
1921 // Get ordered list option data type.
1923 if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_8
|| IfrOneOfOption
->Type
== EFI_IFR_TYPE_BOOLEAN
) {
1925 } else if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_16
) {
1927 } else if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_32
) {
1929 } else if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_64
) {
1933 // Invalid ordered list option data type.
1935 Status
= EFI_INVALID_PARAMETER
;
1936 if (BlockData
->Name
!= NULL
) {
1937 FreePool (BlockData
->Name
);
1939 FreePool (BlockData
);
1944 // Calculate Ordered list QuestionId width.
1946 BlockData
->Width
= (UINT16
) (BlockData
->Width
* VarWidth
);
1948 // Check whether this question is in requested block array.
1950 if (!BlockArrayCheck (RequestBlockArray
, BlockData
->Offset
, BlockData
->Width
, (BOOLEAN
)(BlockData
->Name
!= NULL
), HiiHandle
)) {
1952 // This question is not in the requested string. Skip it.
1954 if (BlockData
->Name
!= NULL
) {
1955 FreePool (BlockData
->Name
);
1957 FreePool (BlockData
);
1962 // Check this var question is in the var storage
1964 if ((BlockData
->Name
== NULL
) && ((BlockData
->Offset
+ BlockData
->Width
) > VarStorageData
->Size
)) {
1965 Status
= EFI_INVALID_PARAMETER
;
1966 if (BlockData
->Name
!= NULL
) {
1967 FreePool (BlockData
->Name
);
1969 FreePool (BlockData
);
1973 // Add Block Data into VarStorageData BlockEntry
1975 InsertBlockData (&VarStorageData
->BlockEntry
, &BlockData
);
1977 // No default data for OrderedList.
1984 // 1. Set default value for OneOf option when flag field has default attribute.
1986 if (((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT
) == EFI_IFR_OPTION_DEFAULT
) ||
1987 ((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT_MFG
) == EFI_IFR_OPTION_DEFAULT_MFG
)) {
1989 // This flag is used to specify whether this option is the first. Set it to FALSE for the following options.
1990 // The first oneof option value will be used as default value when no default value is specified.
1992 FirstOneOfOption
= FALSE
;
1994 // Prepare new DefaultValue
1996 DefaultData
.Type
= DefaultValueFromFlag
;
1997 CopyMem (&DefaultData
.Value
, &IfrOneOfOption
->Value
, IfrOneOfOption
->Header
.Length
- OFFSET_OF (EFI_IFR_ONE_OF_OPTION
, Value
));
1998 if ((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT
) == EFI_IFR_OPTION_DEFAULT
) {
1999 DefaultData
.DefaultId
= EFI_HII_DEFAULT_CLASS_STANDARD
;
2000 InsertDefaultValue (BlockData
, &DefaultData
);
2002 if ((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT_MFG
) == EFI_IFR_OPTION_DEFAULT_MFG
) {
2003 DefaultData
.DefaultId
= EFI_HII_DEFAULT_CLASS_MANUFACTURING
;
2004 InsertDefaultValue (BlockData
, &DefaultData
);
2009 // 2. Set as the default value when this is the first option.
2010 // The first oneof option value will be used as default value when no default value is specified.
2012 if (FirstOneOfOption
) {
2013 // This flag is used to specify whether this option is the first. Set it to FALSE for the following options.
2014 FirstOneOfOption
= FALSE
;
2017 // Prepare new DefaultValue
2019 DefaultData
.Type
= DefaultValueFromDefault
;
2020 CopyMem (&DefaultData
.Value
, &IfrOneOfOption
->Value
, IfrOneOfOption
->Header
.Length
- OFFSET_OF (EFI_IFR_ONE_OF_OPTION
, Value
));
2021 for (LinkData
= DefaultIdArray
->Entry
.ForwardLink
; LinkData
!= &DefaultIdArray
->Entry
; LinkData
= LinkData
->ForwardLink
) {
2022 DefaultDataPtr
= BASE_CR (LinkData
, IFR_DEFAULT_DATA
, Entry
);
2023 DefaultData
.DefaultId
= DefaultDataPtr
->DefaultId
;
2024 InsertDefaultValue (BlockData
, &DefaultData
);
2029 case EFI_IFR_DEFAULT_OP
:
2031 // Update Current BlockData to the default value.
2033 if (BlockData
== NULL
|| BlockData
->Scope
== 0) {
2035 // No matched block data is ignored.
2040 if (BlockData
->OpCode
== EFI_IFR_ORDERED_LIST_OP
) {
2042 // OrderedList Opcode is no default value.
2047 // Get the DefaultId
2049 IfrDefault
= (EFI_IFR_DEFAULT
*) IfrOpHdr
;
2050 VarDefaultId
= IfrDefault
->DefaultId
;
2052 // Prepare new DefaultValue
2054 DefaultData
.Type
= DefaultValueFromOpcode
;
2055 DefaultData
.DefaultId
= VarDefaultId
;
2056 CopyMem (&DefaultData
.Value
, &IfrDefault
->Value
, IfrDefault
->Header
.Length
- OFFSET_OF (EFI_IFR_DEFAULT
, Value
));
2058 // If the value field is expression, set the cleaned flag.
2059 if (IfrDefault
->Type
== EFI_IFR_TYPE_OTHER
) {
2060 DefaultData
.Cleaned
= TRUE
;
2063 // Add DefaultValue into current BlockData
2065 InsertDefaultValue (BlockData
, &DefaultData
);
2068 // After insert the default value, reset the cleaned value for next
2069 // time used. If not set here, need to set the value before everytime
2072 DefaultData
.Cleaned
= FALSE
;
2075 case EFI_IFR_END_OP
:
2077 // End Opcode is for Var question.
2079 if (BlockData
!= NULL
&& BlockData
->Scope
> 0) {
2085 if (BlockData
!= NULL
&& BlockData
->Scope
> 0) {
2086 BlockData
->Scope
= (UINT8
) (BlockData
->Scope
+ IfrOpHdr
->Scope
);
2091 IfrOffset
+= IfrOpHdr
->Length
;
2095 for (LinkData
= VarStorageData
->BlockEntry
.ForwardLink
; LinkData
!= &VarStorageData
->BlockEntry
; LinkData
= LinkData
->ForwardLink
) {
2096 BlockData
= BASE_CR (LinkData
, IFR_BLOCK_DATA
, Entry
);
2097 for (LinkDefault
= BlockData
->DefaultValueEntry
.ForwardLink
; LinkDefault
!= &BlockData
->DefaultValueEntry
; ) {
2098 DefaultDataPtr
= BASE_CR (LinkDefault
, IFR_DEFAULT_DATA
, Entry
);
2099 LinkDefault
= LinkDefault
->ForwardLink
;
2100 if (DefaultDataPtr
->Cleaned
== TRUE
) {
2101 RemoveEntryList (&DefaultDataPtr
->Entry
);
2102 FreePool (DefaultDataPtr
);
2111 parse the configrequest string, get the elements.
2113 @param ConfigRequest The input configrequest string.
2114 @param Progress Return the progress data.
2116 @retval Block data pointer.
2120 IN EFI_STRING ConfigRequest
,
2121 OUT EFI_STRING
*Progress
2124 EFI_STRING StringPtr
;
2125 IFR_BLOCK_DATA
*BlockData
;
2126 IFR_BLOCK_DATA
*RequestBlockArray
;
2132 IFR_BLOCK_DATA
*NextBlockData
;
2136 // Init RequestBlockArray
2138 RequestBlockArray
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
2139 if (RequestBlockArray
== NULL
) {
2142 InitializeListHead (&RequestBlockArray
->Entry
);
2145 // Get the request Block array from the request string
2150 // Parse each <RequestElement> if exists
2151 // Only <BlockName> format is supported by this help function.
2152 // <BlockName> ::= &'OFFSET='<Number>&'WIDTH='<Number>
2154 StringPtr
= ConfigRequest
;
2155 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) == 0) {
2157 // Skip the OFFSET string
2159 *Progress
= StringPtr
;
2160 StringPtr
+= StrLen (L
"&OFFSET=");
2164 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
2165 if (EFI_ERROR (Status
)) {
2172 (((Length
+ 1) / 2) < sizeof (UINT16
)) ? ((Length
+ 1) / 2) : sizeof (UINT16
)
2174 FreePool (TmpBuffer
);
2176 StringPtr
+= Length
;
2177 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
2180 StringPtr
+= StrLen (L
"&WIDTH=");
2185 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
2186 if (EFI_ERROR (Status
)) {
2193 (((Length
+ 1) / 2) < sizeof (UINT16
)) ? ((Length
+ 1) / 2) : sizeof (UINT16
)
2195 FreePool (TmpBuffer
);
2197 StringPtr
+= Length
;
2198 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
2205 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
2206 if (BlockData
== NULL
) {
2209 BlockData
->Offset
= Offset
;
2210 BlockData
->Width
= Width
;
2211 InsertBlockData (&RequestBlockArray
->Entry
, &BlockData
);
2214 // Skip &VALUE string if &VALUE does exists.
2216 if (StrnCmp (StringPtr
, L
"&VALUE=", StrLen (L
"&VALUE=")) == 0) {
2217 StringPtr
+= StrLen (L
"&VALUE=");
2222 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
2223 if (EFI_ERROR (Status
)) {
2227 StringPtr
+= Length
;
2228 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
2233 // If '\0', parsing is finished.
2235 if (*StringPtr
== 0) {
2241 // Merge the requested block data.
2243 Link
= RequestBlockArray
->Entry
.ForwardLink
;
2244 while ((Link
!= &RequestBlockArray
->Entry
) && (Link
->ForwardLink
!= &RequestBlockArray
->Entry
)) {
2245 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
2246 NextBlockData
= BASE_CR (Link
->ForwardLink
, IFR_BLOCK_DATA
, Entry
);
2247 if ((NextBlockData
->Offset
>= BlockData
->Offset
) && (NextBlockData
->Offset
<= (BlockData
->Offset
+ BlockData
->Width
))) {
2248 if ((NextBlockData
->Offset
+ NextBlockData
->Width
) > (BlockData
->Offset
+ BlockData
->Width
)) {
2249 BlockData
->Width
= (UINT16
) (NextBlockData
->Offset
+ NextBlockData
->Width
- BlockData
->Offset
);
2251 RemoveEntryList (Link
->ForwardLink
);
2252 FreePool (NextBlockData
);
2255 Link
= Link
->ForwardLink
;
2258 return RequestBlockArray
;
2261 if (RequestBlockArray
!= NULL
) {
2263 // Free Link Array RequestBlockArray
2265 while (!IsListEmpty (&RequestBlockArray
->Entry
)) {
2266 BlockData
= BASE_CR (RequestBlockArray
->Entry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
2267 RemoveEntryList (&BlockData
->Entry
);
2268 FreePool (BlockData
);
2271 FreePool (RequestBlockArray
);
2278 parse the configrequest string, get the elements.
2280 @param ConfigRequest The input config request string.
2281 @param Progress Return the progress data.
2283 @retval return data block array.
2287 IN EFI_STRING ConfigRequest
,
2288 OUT EFI_STRING
*Progress
2291 EFI_STRING StringPtr
;
2293 IFR_BLOCK_DATA
*BlockData
;
2294 IFR_BLOCK_DATA
*RequestBlockArray
;
2297 StringPtr
= ConfigRequest
;
2300 // Init RequestBlockArray
2302 RequestBlockArray
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
2303 if (RequestBlockArray
== NULL
) {
2306 InitializeListHead (&RequestBlockArray
->Entry
);
2309 // Get the request Block array from the request string
2313 // Parse each <RequestElement> if exists
2314 // Only <BlockName> format is supported by this help function.
2315 // <BlockName> ::= &'Name***=***
2317 while (StringPtr
!= NULL
&& *StringPtr
== L
'&') {
2319 *Progress
= StringPtr
;
2321 // Skip the L"&" string
2326 if ((NextTag
= StrStr (StringPtr
, L
"=")) != NULL
) {
2329 } else if ((NextTag
= StrStr (StringPtr
, L
"&")) != NULL
) {
2336 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
2337 if (BlockData
== NULL
) {
2344 BlockData
->Name
= AllocateCopyPool(StrSize (StringPtr
), StringPtr
);
2345 InsertBlockData (&RequestBlockArray
->Entry
, &BlockData
);
2349 // If has value, skip the value.
2351 StringPtr
= NextTag
+ 1;
2353 StringPtr
= StrStr (StringPtr
, L
"&");
2354 } else if (NextTag
!= NULL
) {
2356 // restore the '&' text.
2358 StringPtr
= NextTag
;
2363 return RequestBlockArray
;
2366 if (RequestBlockArray
!= NULL
) {
2368 // Free Link Array RequestBlockArray
2370 while (!IsListEmpty (&RequestBlockArray
->Entry
)) {
2371 BlockData
= BASE_CR (RequestBlockArray
->Entry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
2372 RemoveEntryList (&BlockData
->Entry
);
2373 if (BlockData
->Name
!= NULL
) {
2374 FreePool (BlockData
->Name
);
2376 FreePool (BlockData
);
2379 FreePool (RequestBlockArray
);
2386 Generate ConfigRequest string base on the varstore info.
2388 @param ConfigHdr The config header for this varstore.
2389 @param VarStorageData The varstore info.
2390 @param Status Return Status.
2391 @param ConfigRequest The ConfigRequest info may be return.
2393 @retval TRUE Need to continue
2394 @retval Others NO need to continue or error occur.
2397 GenerateConfigRequest (
2398 IN CHAR16
*ConfigHdr
,
2399 IN IFR_VARSTORAGE_DATA
*VarStorageData
,
2400 OUT EFI_STATUS
*Status
,
2401 IN OUT EFI_STRING
*ConfigRequest
2407 CHAR16
*FullConfigRequest
;
2409 IFR_BLOCK_DATA
*BlockData
;
2412 // Append VarStorageData BlockEntry into *Request string
2413 // Now support only one varstore in a form package.
2417 // Go through all VarStorageData Entry and get BlockEntry for each one for the multiple varstore in a single form package
2418 // Then construct them all to return MultiRequest string : ConfigHdr BlockConfig
2422 // Compute the length of the entire request starting with <ConfigHdr> and a
2426 Length
= StrLen (ConfigHdr
) + 1;
2428 for (Link
= VarStorageData
->BlockEntry
.ForwardLink
; Link
!= &VarStorageData
->BlockEntry
; Link
= Link
->ForwardLink
) {
2430 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
2431 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2433 // Add <BlockName> length for each Name
2435 // <BlockName> ::= &Name1&Name2&...
2436 // |1| StrLen(Name1)
2438 Length
= Length
+ (1 + StrLen (BlockData
->Name
));
2441 // Add <BlockName> length for each Offset/Width pair
2443 // <BlockName> ::= &OFFSET=1234&WIDTH=1234
2444 // | 8 | 4 | 7 | 4 |
2446 Length
= Length
+ (8 + 4 + 7 + 4);
2450 // No any request block data is found. The request string can't be constructed.
2453 *Status
= EFI_SUCCESS
;
2458 // Allocate buffer for the entire <ConfigRequest>
2460 FullConfigRequest
= AllocateZeroPool (Length
* sizeof (CHAR16
));
2461 if (FullConfigRequest
== NULL
) {
2462 *Status
= EFI_OUT_OF_RESOURCES
;
2465 StringPtr
= FullConfigRequest
;
2468 // Start with <ConfigHdr>
2470 StrCpy (StringPtr
, ConfigHdr
);
2471 StringPtr
+= StrLen (StringPtr
);
2474 // Loop through all the Offset/Width pairs and append them to ConfigRequest
2476 for (Link
= VarStorageData
->BlockEntry
.ForwardLink
; Link
!= &VarStorageData
->BlockEntry
; Link
= Link
->ForwardLink
) {
2477 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
2478 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2484 (1 + StrLen (BlockData
->Name
) + 1) * sizeof (CHAR16
),
2490 // Append &OFFSET=XXXX&WIDTH=YYYY\0
2494 (8 + 4 + 7 + 4 + 1) * sizeof (CHAR16
),
2495 L
"&OFFSET=%04X&WIDTH=%04X",
2500 StringPtr
+= StrLen (StringPtr
);
2503 // Set to the got full request string.
2505 HiiToLower (FullConfigRequest
);
2507 if (*ConfigRequest
!= NULL
) {
2508 FreePool (*ConfigRequest
);
2510 *ConfigRequest
= FullConfigRequest
;
2516 Generate ConfigRequest Header base on the varstore info.
2518 @param VarStorageData The varstore info.
2519 @param DevicePath Device path for this varstore.
2520 @param ConfigHdr The config header for this varstore.
2522 @retval EFI_SUCCESS Generate the header success.
2523 @retval EFI_OUT_OF_RESOURCES Allocate buffer fail.
2527 IN IFR_VARSTORAGE_DATA
*VarStorageData
,
2528 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
2529 OUT EFI_STRING
*ConfigHdr
2538 Status
= EFI_SUCCESS
;
2544 // Construct <ConfigHdr> : "GUID=...&NAME=...&PATH=..." by VarStorageData Guid, Name and DriverHandle
2546 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*) &VarStorageData
->Guid
, 1, &GuidStr
);
2547 if (VarStorageData
->Name
!= NULL
) {
2548 GenerateSubStr (L
"NAME=", StrLen (VarStorageData
->Name
) * sizeof (CHAR16
), (VOID
*) VarStorageData
->Name
, 2, &NameStr
);
2550 GenerateSubStr (L
"NAME=", 0, NULL
, 2, &NameStr
);
2554 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) DevicePath
),
2555 (VOID
*) DevicePath
,
2559 Length
= StrLen (GuidStr
) + StrLen (NameStr
) + StrLen (PathStr
) + 1;
2560 if (VarStorageData
->Name
== NULL
) {
2564 *ConfigHdr
= AllocateZeroPool (Length
* sizeof (CHAR16
));
2565 if (*ConfigHdr
== NULL
) {
2566 Status
= EFI_OUT_OF_RESOURCES
;
2569 StrCpy (*ConfigHdr
, GuidStr
);
2570 StrCat (*ConfigHdr
, NameStr
);
2571 if (VarStorageData
->Name
== NULL
) {
2572 StrCat (*ConfigHdr
, L
"&");
2574 StrCat (*ConfigHdr
, PathStr
);
2577 // Remove the last character L'&'
2579 *(*ConfigHdr
+ StrLen (*ConfigHdr
) - 1) = L
'\0';
2582 if (GuidStr
!= NULL
) {
2586 if (NameStr
!= NULL
) {
2590 if (PathStr
!= NULL
) {
2598 Get Data buffer size based on data type.
2600 @param ValueType The input data type.
2602 @retval The data buffer size for the input type.
2609 UINT16 StorageWidth
;
2611 switch (ValueType
) {
2612 case EFI_IFR_NUMERIC_SIZE_1
:
2613 case EFI_IFR_TYPE_BOOLEAN
:
2614 StorageWidth
= (UINT16
) sizeof (UINT8
);
2617 case EFI_IFR_NUMERIC_SIZE_2
:
2618 StorageWidth
= (UINT16
) sizeof (UINT16
);
2621 case EFI_IFR_NUMERIC_SIZE_4
:
2622 StorageWidth
= (UINT16
) sizeof (UINT32
);
2625 case EFI_IFR_NUMERIC_SIZE_8
:
2626 StorageWidth
= (UINT16
) sizeof (UINT64
);
2629 case EFI_IFR_TYPE_TIME
:
2630 StorageWidth
= (UINT16
) sizeof (EFI_IFR_TIME
);
2633 case EFI_IFR_TYPE_DATE
:
2634 StorageWidth
= (UINT16
) sizeof (EFI_IFR_DATE
);
2642 return StorageWidth
;
2646 Generate ConfigAltResp string base on the varstore info.
2648 @param ConfigHdr The config header for this varstore.
2649 @param VarStorageData The varstore info.
2650 @param DefaultIdArray The Default id array.
2651 @param DefaultAltCfgResp The DefaultAltCfgResp info may be return.
2653 @retval TRUE Need to continue
2654 @retval Others NO need to continue or error occur.
2657 GenerateAltConfigResp (
2658 IN CHAR16
*ConfigHdr
,
2659 IN IFR_VARSTORAGE_DATA
*VarStorageData
,
2660 IN IFR_DEFAULT_DATA
*DefaultIdArray
,
2661 IN OUT EFI_STRING
*DefaultAltCfgResp
2667 LIST_ENTRY
*LinkData
;
2668 LIST_ENTRY
*LinkDefault
;
2669 LIST_ENTRY
*ListEntry
;
2671 IFR_BLOCK_DATA
*BlockData
;
2672 IFR_DEFAULT_DATA
*DefaultId
;
2673 IFR_DEFAULT_DATA
*DefaultValueData
;
2681 // Add length for <ConfigHdr> + '\0'
2683 Length
= StrLen (ConfigHdr
) + 1;
2685 for (Link
= DefaultIdArray
->Entry
.ForwardLink
; Link
!= &DefaultIdArray
->Entry
; Link
= Link
->ForwardLink
) {
2686 DefaultId
= BASE_CR (Link
, IFR_DEFAULT_DATA
, Entry
);
2688 // Add length for "&<ConfigHdr>&ALTCFG=XXXX"
2689 // |1| StrLen (ConfigHdr) | 8 | 4 |
2691 Length
+= (1 + StrLen (ConfigHdr
) + 8 + 4);
2693 for (LinkData
= VarStorageData
->BlockEntry
.ForwardLink
; LinkData
!= &VarStorageData
->BlockEntry
; LinkData
= LinkData
->ForwardLink
) {
2694 BlockData
= BASE_CR (LinkData
, IFR_BLOCK_DATA
, Entry
);
2695 ListEntry
= &BlockData
->DefaultValueEntry
;
2696 for (LinkDefault
= ListEntry
->ForwardLink
; LinkDefault
!= ListEntry
; LinkDefault
= LinkDefault
->ForwardLink
) {
2697 DefaultValueData
= BASE_CR (LinkDefault
, IFR_DEFAULT_DATA
, Entry
);
2698 if (DefaultValueData
->DefaultId
!= DefaultId
->DefaultId
) {
2701 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2703 // Add length for "&Name1=zzzzzzzzzzzz"
2706 Length
+= (1 + StrLen (BlockData
->Name
) + 1 + BlockData
->Width
* 2);
2709 // Add length for "&OFFSET=XXXX&WIDTH=YYYY&VALUE=zzzzzzzzzzzz"
2710 // | 8 | 4 | 7 | 4 | 7 | Width * 2 |
2712 Length
+= (8 + 4 + 7 + 4 + 7 + BlockData
->Width
* 2);
2720 // No default value is found. The default string doesn't exist.
2727 // Allocate buffer for the entire <DefaultAltCfgResp>
2729 *DefaultAltCfgResp
= AllocateZeroPool (Length
* sizeof (CHAR16
));
2730 if (*DefaultAltCfgResp
== NULL
) {
2731 return EFI_OUT_OF_RESOURCES
;
2733 StringPtr
= *DefaultAltCfgResp
;
2736 // Start with <ConfigHdr>
2738 StrCpy (StringPtr
, ConfigHdr
);
2739 StringPtr
+= StrLen (StringPtr
);
2741 for (Link
= DefaultIdArray
->Entry
.ForwardLink
; Link
!= &DefaultIdArray
->Entry
; Link
= Link
->ForwardLink
) {
2742 DefaultId
= BASE_CR (Link
, IFR_DEFAULT_DATA
, Entry
);
2744 // Add <AltConfigHdr> of the form "&<ConfigHdr>&ALTCFG=XXXX\0"
2745 // |1| StrLen (ConfigHdr) | 8 | 4 |
2749 (1 + StrLen (ConfigHdr
) + 8 + 4 + 1) * sizeof (CHAR16
),
2752 DefaultId
->DefaultId
2754 StringPtr
+= StrLen (StringPtr
);
2756 for (LinkData
= VarStorageData
->BlockEntry
.ForwardLink
; LinkData
!= &VarStorageData
->BlockEntry
; LinkData
= LinkData
->ForwardLink
) {
2757 BlockData
= BASE_CR (LinkData
, IFR_BLOCK_DATA
, Entry
);
2758 ListEntry
= &BlockData
->DefaultValueEntry
;
2759 for (LinkDefault
= ListEntry
->ForwardLink
; LinkDefault
!= ListEntry
; LinkDefault
= LinkDefault
->ForwardLink
) {
2760 DefaultValueData
= BASE_CR (LinkDefault
, IFR_DEFAULT_DATA
, Entry
);
2761 if (DefaultValueData
->DefaultId
!= DefaultId
->DefaultId
) {
2764 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2767 (1 + StrLen (ConfigHdr
) + 1) * sizeof (CHAR16
),
2771 StringPtr
+= StrLen (StringPtr
);
2774 // Add <BlockConfig>
2775 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>
2779 (8 + 4 + 7 + 4 + 7 + 1) * sizeof (CHAR16
),
2780 L
"&OFFSET=%04X&WIDTH=%04X&VALUE=",
2784 StringPtr
+= StrLen (StringPtr
);
2786 Width
= BlockData
->Width
;
2788 // Convert Value to a hex string in "%x" format
2789 // NOTE: This is in the opposite byte that GUID and PATH use
2791 TmpBuffer
= (UINT8
*) &(DefaultValueData
->Value
);
2792 for (; Width
> 0; Width
--) {
2793 StringPtr
+= UnicodeValueToString (StringPtr
, PREFIX_ZERO
| RADIX_HEX
, TmpBuffer
[Width
- 1], 2);
2799 HiiToLower (*DefaultAltCfgResp
);
2805 This function gets the full request string and full default value string by
2806 parsing IFR data in HII form packages.
2808 When Request points to NULL string, the request string and default value string
2809 for each varstore in form package will return.
2811 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
2812 @param DevicePath Device Path which Hii Config Access Protocol is registered.
2813 @param Request Pointer to a null-terminated Unicode string in
2814 <ConfigRequest> format. When it doesn't contain
2815 any RequestElement, it will be updated to return
2816 the full RequestElement retrieved from IFR data.
2817 If it points to NULL, the request string for the first
2818 varstore in form package will be merged into a
2819 <MultiConfigRequest> format string and return.
2820 @param AltCfgResp Pointer to a null-terminated Unicode string in
2821 <ConfigAltResp> format. When the pointer is to NULL,
2822 the full default value string retrieved from IFR data
2823 will return. When the pinter is to a string, the
2824 full default value string retrieved from IFR data
2825 will be merged into the input string and return.
2826 When Request points to NULL, the default value string
2827 for each varstore in form package will be merged into
2828 a <MultiConfigAltResp> format string and return.
2829 @param PointerProgress Optional parameter, it can be be NULL.
2830 When it is not NULL, if Request is NULL, it returns NULL.
2831 On return, points to a character in the Request
2832 string. Points to the string's null terminator if
2833 request was successful. Points to the most recent
2834 & before the first failing name / value pair (or
2835 the beginning of the string if the failure is in
2836 the first name / value pair) if the request was
2838 @retval EFI_SUCCESS The Results string is set to the full request string.
2839 And AltCfgResp contains all default value string.
2840 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
2841 @retval EFI_NOT_FOUND The varstore (Guid and Name) in Request string
2842 can't be found in Form package.
2843 @retval EFI_NOT_FOUND HiiPackage can't be got on the input HiiHandle.
2844 @retval EFI_INVALID_PARAMETER Request points to NULL.
2849 GetFullStringFromHiiFormPackages (
2850 IN HII_DATABASE_RECORD
*DataBaseRecord
,
2851 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
2852 IN OUT EFI_STRING
*Request
,
2853 IN OUT EFI_STRING
*AltCfgResp
,
2854 OUT EFI_STRING
*PointerProgress OPTIONAL
2858 UINT8
*HiiFormPackage
;
2860 IFR_BLOCK_DATA
*RequestBlockArray
;
2861 IFR_BLOCK_DATA
*BlockData
;
2862 IFR_DEFAULT_DATA
*DefaultValueData
;
2863 IFR_DEFAULT_DATA
*DefaultId
;
2864 IFR_DEFAULT_DATA
*DefaultIdArray
;
2865 IFR_VARSTORAGE_DATA
*VarStorageData
;
2866 EFI_STRING DefaultAltCfgResp
;
2867 EFI_STRING ConfigHdr
;
2868 EFI_STRING StringPtr
;
2869 EFI_STRING Progress
;
2871 if (DataBaseRecord
== NULL
|| DevicePath
== NULL
|| Request
== NULL
|| AltCfgResp
== NULL
) {
2872 return EFI_INVALID_PARAMETER
;
2876 // Initialize the local variables.
2878 RequestBlockArray
= NULL
;
2879 DefaultIdArray
= NULL
;
2880 VarStorageData
= NULL
;
2881 DefaultAltCfgResp
= NULL
;
2883 HiiFormPackage
= NULL
;
2885 Progress
= *Request
;
2887 Status
= GetFormPackageData (DataBaseRecord
, &HiiFormPackage
, &PackageSize
);
2888 if (EFI_ERROR (Status
)) {
2893 // 1. Get the request block array by Request String when Request string containts the block array.
2896 if (*Request
!= NULL
) {
2897 StringPtr
= *Request
;
2901 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
2902 Status
= EFI_INVALID_PARAMETER
;
2905 StringPtr
+= StrLen (L
"GUID=");
2906 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&NAME=", StrLen (L
"&NAME=")) != 0) {
2909 if (*StringPtr
== L
'\0') {
2910 Status
= EFI_INVALID_PARAMETER
;
2913 StringPtr
+= StrLen (L
"&NAME=");
2914 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&PATH=", StrLen (L
"&PATH=")) != 0) {
2917 if (*StringPtr
== L
'\0') {
2918 Status
= EFI_INVALID_PARAMETER
;
2921 StringPtr
+= StrLen (L
"&PATH=");
2922 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
2926 if (*StringPtr
== L
'\0') {
2928 // No request block is found.
2935 // If StringPtr != NULL, get the request elements.
2937 if (StringPtr
!= NULL
) {
2938 if (StrStr (StringPtr
, L
"&OFFSET=") != NULL
) {
2939 RequestBlockArray
= GetBlockElement(StringPtr
, &Progress
);
2941 RequestBlockArray
= GetNameElement(StringPtr
, &Progress
);
2944 if (RequestBlockArray
== NULL
) {
2945 Status
= EFI_INVALID_PARAMETER
;
2951 // Initialize DefaultIdArray to store the map between DeaultId and DefaultName
2953 DefaultIdArray
= (IFR_DEFAULT_DATA
*) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
2954 if (DefaultIdArray
== NULL
) {
2955 Status
= EFI_OUT_OF_RESOURCES
;
2958 InitializeListHead (&DefaultIdArray
->Entry
);
2961 // Initialize VarStorageData to store the var store Block and Default value information.
2963 VarStorageData
= (IFR_VARSTORAGE_DATA
*) AllocateZeroPool (sizeof (IFR_VARSTORAGE_DATA
));
2964 if (VarStorageData
== NULL
) {
2965 Status
= EFI_OUT_OF_RESOURCES
;
2968 InitializeListHead (&VarStorageData
->Entry
);
2969 InitializeListHead (&VarStorageData
->BlockEntry
);
2972 // 2. Parse FormPackage to get BlockArray and DefaultId Array for the request BlockArray.
2976 // Parse the opcode in form pacakge to get the default setting.
2978 Status
= ParseIfrData (DataBaseRecord
->Handle
,
2980 (UINT32
) PackageSize
,
2985 if (EFI_ERROR (Status
)) {
2990 // No requested varstore in IFR data and directly return
2992 if (VarStorageData
->VarStoreId
== 0) {
2993 Status
= EFI_SUCCESS
;
2998 // 3. Construct Request Element (Block Name) for 2.1 and 2.2 case.
3000 Status
= GenerateHdr (VarStorageData
, DevicePath
, &ConfigHdr
);
3001 if (EFI_ERROR (Status
)) {
3005 if (RequestBlockArray
== NULL
) {
3006 if (!GenerateConfigRequest(ConfigHdr
, VarStorageData
, &Status
, Request
)) {
3012 // 4. Construct Default Value string in AltResp according to request element.
3013 // Go through all VarStorageData Entry and get the DefaultId array for each one
3014 // Then construct them all to : ConfigHdr AltConfigHdr ConfigBody AltConfigHdr ConfigBody
3016 Status
= GenerateAltConfigResp (ConfigHdr
, VarStorageData
, DefaultIdArray
, &DefaultAltCfgResp
);
3017 if (EFI_ERROR (Status
)) {
3022 // 5. Merge string into the input AltCfgResp if the iput *AltCfgResp is not NULL.
3024 if (*AltCfgResp
!= NULL
&& DefaultAltCfgResp
!= NULL
) {
3025 Status
= MergeDefaultString (AltCfgResp
, DefaultAltCfgResp
);
3026 FreePool (DefaultAltCfgResp
);
3027 } else if (*AltCfgResp
== NULL
) {
3028 *AltCfgResp
= DefaultAltCfgResp
;
3032 if (RequestBlockArray
!= NULL
) {
3034 // Free Link Array RequestBlockArray
3036 while (!IsListEmpty (&RequestBlockArray
->Entry
)) {
3037 BlockData
= BASE_CR (RequestBlockArray
->Entry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
3038 RemoveEntryList (&BlockData
->Entry
);
3039 if (BlockData
->Name
!= NULL
) {
3040 FreePool (BlockData
->Name
);
3042 FreePool (BlockData
);
3045 FreePool (RequestBlockArray
);
3048 if (VarStorageData
!= NULL
) {
3050 // Free link array VarStorageData
3052 while (!IsListEmpty (&VarStorageData
->BlockEntry
)) {
3053 BlockData
= BASE_CR (VarStorageData
->BlockEntry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
3054 RemoveEntryList (&BlockData
->Entry
);
3055 if (BlockData
->Name
!= NULL
) {
3056 FreePool (BlockData
->Name
);
3059 // Free default value link array
3061 while (!IsListEmpty (&BlockData
->DefaultValueEntry
)) {
3062 DefaultValueData
= BASE_CR (BlockData
->DefaultValueEntry
.ForwardLink
, IFR_DEFAULT_DATA
, Entry
);
3063 RemoveEntryList (&DefaultValueData
->Entry
);
3064 FreePool (DefaultValueData
);
3066 FreePool (BlockData
);
3068 FreePool (VarStorageData
);
3071 if (DefaultIdArray
!= NULL
) {
3073 // Free DefaultId Array
3075 while (!IsListEmpty (&DefaultIdArray
->Entry
)) {
3076 DefaultId
= BASE_CR (DefaultIdArray
->Entry
.ForwardLink
, IFR_DEFAULT_DATA
, Entry
);
3077 RemoveEntryList (&DefaultId
->Entry
);
3078 FreePool (DefaultId
);
3080 FreePool (DefaultIdArray
);
3084 // Free the allocated string
3086 if (ConfigHdr
!= NULL
) {
3087 FreePool (ConfigHdr
);
3091 // Free Pacakge data
3093 if (HiiFormPackage
!= NULL
) {
3094 FreePool (HiiFormPackage
);
3097 if (PointerProgress
!= NULL
) {
3098 if (*Request
== NULL
) {
3099 *PointerProgress
= NULL
;
3100 } else if (EFI_ERROR (Status
)) {
3101 *PointerProgress
= *Request
;
3103 *PointerProgress
= *Request
+ StrLen (*Request
);
3111 This function gets the full request resp string by
3112 parsing IFR data in HII form packages.
3114 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
3116 @param EfiVarStoreInfo The efi varstore info which is save in the EFI
3117 varstore data structure.
3118 @param Request Pointer to a null-terminated Unicode string in
3119 <ConfigRequest> format.
3120 @param RequestResp Pointer to a null-terminated Unicode string in
3121 <ConfigResp> format.
3122 @param AccessProgress On return, points to a character in the Request
3123 string. Points to the string's null terminator if
3124 request was successful. Points to the most recent
3125 & before the first failing name / value pair (or
3126 the beginning of the string if the failure is in
3127 the first name / value pair) if the request was
3130 @retval EFI_SUCCESS The Results string is set to the full request string.
3131 And AltCfgResp contains all default value string.
3132 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
3133 @retval EFI_INVALID_PARAMETER Request points to NULL.
3137 GetConfigRespFromEfiVarStore (
3138 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
3139 IN EFI_IFR_VARSTORE_EFI
*EfiVarStoreInfo
,
3140 IN EFI_STRING Request
,
3141 OUT EFI_STRING
*RequestResp
,
3142 OUT EFI_STRING
*AccessProgress
3146 EFI_STRING VarStoreName
;
3150 Status
= EFI_SUCCESS
;
3153 VarStoreName
= NULL
;
3155 VarStoreName
= AllocateZeroPool (AsciiStrSize ((CHAR8
*)EfiVarStoreInfo
->Name
) * sizeof (CHAR16
));
3156 if (VarStoreName
== NULL
) {
3157 Status
= EFI_OUT_OF_RESOURCES
;
3160 AsciiStrToUnicodeStr ((CHAR8
*) EfiVarStoreInfo
->Name
, VarStoreName
);
3163 Status
= gRT
->GetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, NULL
, &BufferSize
, NULL
);
3164 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
3168 VarStore
= AllocateZeroPool (BufferSize
);
3169 ASSERT (VarStore
!= NULL
);
3170 Status
= gRT
->GetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, NULL
, &BufferSize
, VarStore
);
3171 if (EFI_ERROR (Status
)) {
3175 Status
= HiiBlockToConfig(This
, Request
, VarStore
, BufferSize
, RequestResp
, AccessProgress
);
3176 if (EFI_ERROR (Status
)) {
3181 if (VarStoreName
!= NULL
) {
3182 FreePool (VarStoreName
);
3185 if (VarStore
!= NULL
) {
3186 FreePool (VarStore
);
3194 This function route the full request resp string for efi varstore.
3196 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
3198 @param EfiVarStoreInfo The efi varstore info which is save in the EFI
3199 varstore data structure.
3200 @param RequestResp Pointer to a null-terminated Unicode string in
3201 <ConfigResp> format.
3202 @param Result Pointer to a null-terminated Unicode string in
3203 <ConfigResp> format.
3205 @retval EFI_SUCCESS The Results string is set to the full request string.
3206 And AltCfgResp contains all default value string.
3207 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
3208 @retval EFI_INVALID_PARAMETER Request points to NULL.
3212 RouteConfigRespForEfiVarStore (
3213 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
3214 IN EFI_IFR_VARSTORE_EFI
*EfiVarStoreInfo
,
3215 IN EFI_STRING RequestResp
,
3216 OUT EFI_STRING
*Result
3220 EFI_STRING VarStoreName
;
3225 Status
= EFI_SUCCESS
;
3228 VarStoreName
= NULL
;
3230 VarStoreName
= AllocateZeroPool (AsciiStrSize ((CHAR8
*)EfiVarStoreInfo
->Name
) * sizeof (CHAR16
));
3231 if (VarStoreName
== NULL
) {
3232 Status
= EFI_OUT_OF_RESOURCES
;
3235 AsciiStrToUnicodeStr ((CHAR8
*) EfiVarStoreInfo
->Name
, VarStoreName
);
3237 Status
= gRT
->GetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, NULL
, &BufferSize
, NULL
);
3238 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
3242 BlockSize
= BufferSize
;
3243 VarStore
= AllocateZeroPool (BufferSize
);
3244 ASSERT (VarStore
!= NULL
);
3245 Status
= gRT
->GetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, NULL
, &BufferSize
, VarStore
);
3246 if (EFI_ERROR (Status
)) {
3250 Status
= HiiConfigToBlock(This
, RequestResp
, VarStore
, &BlockSize
, Result
);
3251 if (EFI_ERROR (Status
)) {
3255 Status
= gRT
->SetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, EfiVarStoreInfo
->Attributes
, BufferSize
, VarStore
);
3256 if (EFI_ERROR (Status
)) {
3261 if (VarStoreName
!= NULL
) {
3262 FreePool (VarStoreName
);
3265 if (VarStore
!= NULL
) {
3266 FreePool (VarStore
);
3273 Validate the config request elements.
3275 @param ConfigElements A null-terminated Unicode string in <ConfigRequest> format,
3276 without configHdr field.
3278 @retval CHAR16 * THE first Name/value pair not correct.
3279 @retval NULL Success parse the name/value pair
3282 OffsetWidthValidate (
3283 CHAR16
*ConfigElements
3289 StringPtr
= ConfigElements
;
3293 if (StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) != 0) {
3297 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
3300 if (*StringPtr
== L
'\0') {
3304 StringPtr
+= StrLen (L
"&WIDTH=");
3305 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) != 0) {
3309 if (*StringPtr
== L
'\0') {
3316 Validate the config request elements.
3318 @param ConfigElements A null-terminated Unicode string in <ConfigRequest> format,
3319 without configHdr field.
3321 @retval CHAR16 * THE first Name/value pair not correct.
3322 @retval NULL Success parse the name/value pair
3327 CHAR16
*ConfigElements
3333 StringPtr
= ConfigElements
;
3337 if (*StringPtr
!= L
'&') {
3342 StringPtr
= StrStr (StringPtr
, L
"&");
3344 if (StringPtr
== NULL
) {
3351 Validate the config request string.
3353 @param ConfigRequest A null-terminated Unicode string in <ConfigRequest> format.
3355 @retval CHAR16 * THE first element not correct.
3356 @retval NULL Success parse the name/value pair
3360 ConfigRequestValidate (
3361 CHAR16
*ConfigRequest
3364 BOOLEAN HasNameField
;
3367 HasNameField
= TRUE
;
3368 StringPtr
= ConfigRequest
;
3371 // Check <ConfigHdr>
3373 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
3374 return ConfigRequest
;
3376 StringPtr
+= StrLen (L
"GUID=");
3377 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&NAME=", StrLen (L
"&NAME=")) != 0) {
3380 if (*StringPtr
== L
'\0') {
3381 return ConfigRequest
;
3383 StringPtr
+= StrLen (L
"&NAME=");
3384 if (*StringPtr
== L
'&') {
3385 HasNameField
= FALSE
;
3387 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&PATH=", StrLen (L
"&PATH=")) != 0) {
3390 if (*StringPtr
== L
'\0') {
3391 return ConfigRequest
;
3393 StringPtr
+= StrLen (L
"&PATH=");
3394 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
3398 if (*StringPtr
== L
'\0') {
3404 // Should be Buffer varstore, config request should be "OFFSET/Width" pairs.
3406 return OffsetWidthValidate(StringPtr
);
3409 // Should be Name/Value varstore, config request should be "&name1&name2..." pairs.
3411 return NameValueValidate(StringPtr
);
3416 This function allows a caller to extract the current configuration
3417 for one or more named elements from one or more drivers.
3419 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
3421 @param Request A null-terminated Unicode string in
3422 <MultiConfigRequest> format.
3423 @param Progress On return, points to a character in the Request
3424 string. Points to the string's null terminator if
3425 request was successful. Points to the most recent
3426 & before the first failing name / value pair (or
3427 the beginning of the string if the failure is in
3428 the first name / value pair) if the request was
3430 @param Results Null-terminated Unicode string in
3431 <MultiConfigAltResp> format which has all values
3432 filled in for the names in the Request string.
3433 String to be allocated by the called function.
3435 @retval EFI_SUCCESS The Results string is filled with the values
3436 corresponding to all requested names.
3437 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
3438 results that must be stored awaiting possible
3440 @retval EFI_NOT_FOUND Routing data doesn't match any known driver.
3441 Progress set to the "G" in "GUID" of the routing
3442 header that doesn't match. Note: There is no
3443 requirement that all routing data be validated
3444 before any configuration extraction.
3445 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Request
3446 parameter would result in this type of error. The
3447 Progress parameter is set to NULL.
3448 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set to most recent &
3449 before the error or the beginning of the string.
3450 @retval EFI_INVALID_PARAMETER Unknown name. Progress points to the & before the
3456 HiiConfigRoutingExtractConfig (
3457 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
3458 IN CONST EFI_STRING Request
,
3459 OUT EFI_STRING
*Progress
,
3460 OUT EFI_STRING
*Results
3463 HII_DATABASE_PRIVATE_DATA
*Private
;
3464 EFI_STRING StringPtr
;
3465 EFI_STRING ConfigRequest
;
3467 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
3468 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
3471 HII_DATABASE_RECORD
*Database
;
3472 UINT8
*DevicePathPkg
;
3473 UINT8
*CurrentDevicePath
;
3474 EFI_HANDLE DriverHandle
;
3475 EFI_HII_HANDLE HiiHandle
;
3476 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
3477 EFI_STRING AccessProgress
;
3478 EFI_STRING AccessResults
;
3479 EFI_STRING DefaultResults
;
3480 BOOLEAN FirstElement
;
3481 BOOLEAN IfrDataParsedFlag
;
3482 BOOLEAN IsEfiVarStore
;
3483 EFI_IFR_VARSTORE_EFI
*EfiVarStoreInfo
;
3484 EFI_STRING ErrorPtr
;
3486 if (This
== NULL
|| Progress
== NULL
|| Results
== NULL
) {
3487 return EFI_INVALID_PARAMETER
;
3490 if (Request
== NULL
) {
3492 return EFI_INVALID_PARAMETER
;
3495 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
3496 StringPtr
= Request
;
3497 *Progress
= StringPtr
;
3498 DefaultResults
= NULL
;
3499 ConfigRequest
= NULL
;
3500 Status
= EFI_SUCCESS
;
3501 AccessResults
= NULL
;
3502 AccessProgress
= NULL
;
3504 IfrDataParsedFlag
= FALSE
;
3505 IsEfiVarStore
= FALSE
;
3506 EfiVarStoreInfo
= NULL
;
3509 // The first element of <MultiConfigRequest> should be
3510 // <GuidHdr>, which is in 'GUID='<Guid> syntax.
3512 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
3513 return EFI_INVALID_PARAMETER
;
3516 FirstElement
= TRUE
;
3519 // Allocate a fix length of memory to store Results. Reallocate memory for
3520 // Results if this fix length is insufficient.
3522 *Results
= (EFI_STRING
) AllocateZeroPool (MAX_STRING_LENGTH
);
3523 if (*Results
== NULL
) {
3524 return EFI_OUT_OF_RESOURCES
;
3527 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) == 0) {
3529 // If parsing error, set Progress to the beginning of the <MultiConfigRequest>
3530 // or most recent & before the error.
3532 if (StringPtr
== Request
) {
3533 *Progress
= StringPtr
;
3535 *Progress
= StringPtr
- 1;
3539 // Process each <ConfigRequest> of <MultiConfigRequest>
3541 Length
= CalculateConfigStringLen (StringPtr
);
3542 ConfigRequest
= AllocateCopyPool ((Length
+ 1) * sizeof (CHAR16
), StringPtr
);
3543 if (ConfigRequest
== NULL
) {
3544 Status
= EFI_OUT_OF_RESOURCES
;
3547 *(ConfigRequest
+ Length
) = 0;
3550 // Get the UEFI device path
3552 Status
= GetDevicePath (ConfigRequest
, (UINT8
**) &DevicePath
);
3553 if (EFI_ERROR (Status
)) {
3558 // Find driver which matches the routing data.
3560 DriverHandle
= NULL
;
3563 for (Link
= Private
->DatabaseList
.ForwardLink
;
3564 Link
!= &Private
->DatabaseList
;
3565 Link
= Link
->ForwardLink
3567 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
3568 if ((DevicePathPkg
= Database
->PackageList
->DevicePathPkg
) != NULL
) {
3569 CurrentDevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
3573 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) CurrentDevicePath
)
3575 DriverHandle
= Database
->DriverHandle
;
3576 HiiHandle
= Database
->Handle
;
3583 // Try to find driver handle by device path.
3585 if (DriverHandle
== NULL
) {
3586 TempDevicePath
= DevicePath
;
3587 Status
= gBS
->LocateDevicePath (
3588 &gEfiDevicePathProtocolGuid
,
3592 if (EFI_ERROR (Status
) || (DriverHandle
== NULL
)) {
3594 // Routing data does not match any known driver.
3595 // Set Progress to the 'G' in "GUID" of the routing header.
3597 *Progress
= StringPtr
;
3598 Status
= EFI_NOT_FOUND
;
3604 // Validate ConfigRequest String.
3606 ErrorPtr
= ConfigRequestValidate(ConfigRequest
);
3607 if (ErrorPtr
!= NULL
) {
3608 *Progress
= StrStr (StringPtr
, ErrorPtr
);
3609 Status
= EFI_INVALID_PARAMETER
;
3614 // Check whether ConfigRequest contains request string.
3616 IfrDataParsedFlag
= FALSE
;
3617 if ((HiiHandle
!= NULL
) && !GetElementsFromRequest(ConfigRequest
)) {
3619 // Get the full request string from IFR when HiiPackage is registered to HiiHandle
3621 IfrDataParsedFlag
= TRUE
;
3622 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &ConfigRequest
, &DefaultResults
, &AccessProgress
);
3623 if (EFI_ERROR (Status
)) {
3625 // AccessProgress indicates the parsing progress on <ConfigRequest>.
3626 // Map it to the progress on <MultiConfigRequest> then return it.
3628 ASSERT (AccessProgress
!= NULL
);
3629 *Progress
= StrStr (StringPtr
, AccessProgress
);
3633 // Not any request block is found.
3635 if (!GetElementsFromRequest(ConfigRequest
)) {
3636 AccessResults
= AllocateCopyPool (StrSize (ConfigRequest
), ConfigRequest
);
3637 goto NextConfigString
;
3642 // Check whether this ConfigRequest is search from Efi varstore type storage.
3644 Status
= GetVarStoreType(Database
, ConfigRequest
, &IsEfiVarStore
, &EfiVarStoreInfo
);
3645 if (EFI_ERROR (Status
)) {
3649 if (IsEfiVarStore
) {
3651 // Call the GetVariable function to extract settings.
3653 Status
= GetConfigRespFromEfiVarStore(This
, EfiVarStoreInfo
, ConfigRequest
, &AccessResults
, &AccessProgress
);
3654 FreePool (EfiVarStoreInfo
);
3657 // Call corresponding ConfigAccess protocol to extract settings
3659 Status
= gBS
->HandleProtocol (
3661 &gEfiHiiConfigAccessProtocolGuid
,
3662 (VOID
**) &ConfigAccess
3664 ASSERT_EFI_ERROR (Status
);
3666 Status
= ConfigAccess
->ExtractConfig (
3673 if (EFI_ERROR (Status
)) {
3675 // AccessProgress indicates the parsing progress on <ConfigRequest>.
3676 // Map it to the progress on <MultiConfigRequest> then return it.
3678 *Progress
= StrStr (StringPtr
, AccessProgress
);
3683 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'
3684 // which seperates the first <ConfigAltResp> and the following ones.
3686 ASSERT (*AccessProgress
== 0);
3689 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
3691 if (!IfrDataParsedFlag
&& HiiHandle
!= NULL
) {
3692 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &ConfigRequest
, &DefaultResults
, NULL
);
3693 ASSERT_EFI_ERROR (Status
);
3696 FreePool (DevicePath
);
3699 if (DefaultResults
!= NULL
) {
3700 Status
= MergeDefaultString (&AccessResults
, DefaultResults
);
3701 ASSERT_EFI_ERROR (Status
);
3702 FreePool (DefaultResults
);
3703 DefaultResults
= NULL
;
3707 if (!FirstElement
) {
3708 Status
= AppendToMultiString (Results
, L
"&");
3709 ASSERT_EFI_ERROR (Status
);
3712 Status
= AppendToMultiString (Results
, AccessResults
);
3713 ASSERT_EFI_ERROR (Status
);
3715 FirstElement
= FALSE
;
3717 FreePool (AccessResults
);
3718 AccessResults
= NULL
;
3719 FreePool (ConfigRequest
);
3720 ConfigRequest
= NULL
;
3723 // Go to next <ConfigRequest> (skip '&').
3725 StringPtr
+= Length
;
3726 if (*StringPtr
== 0) {
3727 *Progress
= StringPtr
;
3735 if (EFI_ERROR (Status
)) {
3736 FreePool (*Results
);
3740 if (ConfigRequest
!= NULL
) {
3741 FreePool (ConfigRequest
);
3744 if (AccessResults
!= NULL
) {
3745 FreePool (AccessResults
);
3748 if (DefaultResults
!= NULL
) {
3749 FreePool (DefaultResults
);
3752 if (DevicePath
!= NULL
) {
3753 FreePool (DevicePath
);
3761 This function allows the caller to request the current configuration for the
3762 entirety of the current HII database and returns the data in a
3763 null-terminated Unicode string.
3765 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
3767 @param Results Null-terminated Unicode string in
3768 <MultiConfigAltResp> format which has all values
3769 filled in for the names in the Request string.
3770 String to be allocated by the called function.
3771 De-allocation is up to the caller.
3773 @retval EFI_SUCCESS The Results string is filled with the values
3774 corresponding to all requested names.
3775 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
3776 results that must be stored awaiting possible
3778 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Results
3779 parameter would result in this type of error.
3784 HiiConfigRoutingExportConfig (
3785 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
3786 OUT EFI_STRING
*Results
3790 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
3791 EFI_STRING AccessResults
;
3792 EFI_STRING Progress
;
3793 EFI_STRING StringPtr
;
3794 EFI_STRING ConfigRequest
;
3796 EFI_HANDLE
*ConfigAccessHandles
;
3797 UINTN NumberConfigAccessHandles
;
3798 BOOLEAN FirstElement
;
3799 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
3800 EFI_HII_HANDLE HiiHandle
;
3801 EFI_STRING DefaultResults
;
3802 HII_DATABASE_PRIVATE_DATA
*Private
;
3804 HII_DATABASE_RECORD
*Database
;
3805 UINT8
*DevicePathPkg
;
3806 UINT8
*CurrentDevicePath
;
3807 BOOLEAN IfrDataParsedFlag
;
3809 if (This
== NULL
|| Results
== NULL
) {
3810 return EFI_INVALID_PARAMETER
;
3813 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
3816 // Allocate a fix length of memory to store Results. Reallocate memory for
3817 // Results if this fix length is insufficient.
3819 *Results
= (EFI_STRING
) AllocateZeroPool (MAX_STRING_LENGTH
);
3820 if (*Results
== NULL
) {
3821 return EFI_OUT_OF_RESOURCES
;
3824 NumberConfigAccessHandles
= 0;
3825 Status
= gBS
->LocateHandleBuffer (
3827 &gEfiHiiConfigAccessProtocolGuid
,
3829 &NumberConfigAccessHandles
,
3830 &ConfigAccessHandles
3832 if (EFI_ERROR (Status
)) {
3836 FirstElement
= TRUE
;
3838 for (Index
= 0; Index
< NumberConfigAccessHandles
; Index
++) {
3839 Status
= gBS
->HandleProtocol (
3840 ConfigAccessHandles
[Index
],
3841 &gEfiHiiConfigAccessProtocolGuid
,
3842 (VOID
**) &ConfigAccess
3844 if (EFI_ERROR (Status
)) {
3849 // Get DevicePath and HiiHandle for this ConfigAccess driver handle
3851 IfrDataParsedFlag
= FALSE
;
3854 DefaultResults
= NULL
;
3856 ConfigRequest
= NULL
;
3857 DevicePath
= DevicePathFromHandle (ConfigAccessHandles
[Index
]);
3858 if (DevicePath
!= NULL
) {
3859 for (Link
= Private
->DatabaseList
.ForwardLink
;
3860 Link
!= &Private
->DatabaseList
;
3861 Link
= Link
->ForwardLink
3863 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
3864 if ((DevicePathPkg
= Database
->PackageList
->DevicePathPkg
) != NULL
) {
3865 CurrentDevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
3869 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) CurrentDevicePath
)
3871 HiiHandle
= Database
->Handle
;
3878 Status
= ConfigAccess
->ExtractConfig (
3884 if (EFI_ERROR (Status
)) {
3886 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
3888 if (HiiHandle
!= NULL
&& DevicePath
!= NULL
) {
3889 IfrDataParsedFlag
= TRUE
;
3890 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &ConfigRequest
, &DefaultResults
, NULL
);
3892 // Get the full request string to get the Current setting again.
3894 if (!EFI_ERROR (Status
) && ConfigRequest
!= NULL
) {
3895 Status
= ConfigAccess
->ExtractConfig (
3901 FreePool (ConfigRequest
);
3903 Status
= EFI_NOT_FOUND
;
3908 if (!EFI_ERROR (Status
)) {
3910 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
3912 if (!IfrDataParsedFlag
&& HiiHandle
!= NULL
&& DevicePath
!= NULL
) {
3913 StringPtr
= StrStr (AccessResults
, L
"&GUID=");
3914 if (StringPtr
!= NULL
) {
3917 if (GetElementsFromRequest (AccessResults
)) {
3918 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &AccessResults
, &DefaultResults
, NULL
);
3919 ASSERT_EFI_ERROR (Status
);
3921 if (StringPtr
!= NULL
) {
3926 // Merge the default sting from IFR code into the got setting from driver.
3928 if (DefaultResults
!= NULL
) {
3929 Status
= MergeDefaultString (&AccessResults
, DefaultResults
);
3930 ASSERT_EFI_ERROR (Status
);
3931 FreePool (DefaultResults
);
3932 DefaultResults
= NULL
;
3936 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'
3937 // which seperates the first <ConfigAltResp> and the following ones.
3939 if (!FirstElement
) {
3940 Status
= AppendToMultiString (Results
, L
"&");
3941 ASSERT_EFI_ERROR (Status
);
3944 Status
= AppendToMultiString (Results
, AccessResults
);
3945 ASSERT_EFI_ERROR (Status
);
3947 FirstElement
= FALSE
;
3949 FreePool (AccessResults
);
3950 AccessResults
= NULL
;
3953 FreePool (ConfigAccessHandles
);
3960 This function processes the results of processing forms and routes it to the
3961 appropriate handlers or storage.
3963 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
3965 @param Configuration A null-terminated Unicode string in
3966 <MulltiConfigResp> format.
3967 @param Progress A pointer to a string filled in with the offset of
3968 the most recent & before the first failing name /
3969 value pair (or the beginning of the string if the
3970 failure is in the first name / value pair) or the
3971 terminating NULL if all was successful.
3973 @retval EFI_SUCCESS The results have been distributed or are awaiting
3975 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
3976 results that must be stored awaiting possible
3978 @retval EFI_INVALID_PARAMETER Passing in a NULL for the Configuration parameter
3979 would result in this type of error.
3980 @retval EFI_NOT_FOUND Target for the specified routing data was not
3986 HiiConfigRoutingRouteConfig (
3987 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
3988 IN CONST EFI_STRING Configuration
,
3989 OUT EFI_STRING
*Progress
3992 HII_DATABASE_PRIVATE_DATA
*Private
;
3993 EFI_STRING StringPtr
;
3994 EFI_STRING ConfigResp
;
3997 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
3998 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
4000 HII_DATABASE_RECORD
*Database
;
4001 UINT8
*DevicePathPkg
;
4002 UINT8
*CurrentDevicePath
;
4003 EFI_HANDLE DriverHandle
;
4004 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
4005 EFI_STRING AccessProgress
;
4006 EFI_IFR_VARSTORE_EFI
*EfiVarStoreInfo
;
4007 BOOLEAN IsEfiVarstore
;
4009 if (This
== NULL
|| Progress
== NULL
) {
4010 return EFI_INVALID_PARAMETER
;
4013 if (Configuration
== NULL
) {
4015 return EFI_INVALID_PARAMETER
;
4018 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
4019 StringPtr
= Configuration
;
4020 *Progress
= StringPtr
;
4022 AccessProgress
= NULL
;
4023 EfiVarStoreInfo
= NULL
;
4024 IsEfiVarstore
= FALSE
;
4027 // The first element of <MultiConfigResp> should be
4028 // <GuidHdr>, which is in 'GUID='<Guid> syntax.
4030 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
4031 return EFI_INVALID_PARAMETER
;
4034 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) == 0) {
4036 // If parsing error, set Progress to the beginning of the <MultiConfigResp>
4037 // or most recent & before the error.
4039 if (StringPtr
== Configuration
) {
4040 *Progress
= StringPtr
;
4042 *Progress
= StringPtr
- 1;
4046 // Process each <ConfigResp> of <MultiConfigResp>
4048 Length
= CalculateConfigStringLen (StringPtr
);
4049 ConfigResp
= AllocateCopyPool ((Length
+ 1) * sizeof (CHAR16
), StringPtr
);
4050 if (ConfigResp
== NULL
) {
4051 return EFI_OUT_OF_RESOURCES
;
4054 // Append '\0' to the end of ConfigRequest
4056 *(ConfigResp
+ Length
) = 0;
4059 // Get the UEFI device path
4061 Status
= GetDevicePath (ConfigResp
, (UINT8
**) &DevicePath
);
4062 if (EFI_ERROR (Status
)) {
4063 FreePool (ConfigResp
);
4068 // Find driver which matches the routing data.
4070 DriverHandle
= NULL
;
4071 for (Link
= Private
->DatabaseList
.ForwardLink
;
4072 Link
!= &Private
->DatabaseList
;
4073 Link
= Link
->ForwardLink
4075 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
4077 if ((DevicePathPkg
= Database
->PackageList
->DevicePathPkg
) != NULL
) {
4078 CurrentDevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
4082 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) CurrentDevicePath
)
4084 DriverHandle
= Database
->DriverHandle
;
4091 // Try to find driver handle by device path.
4093 if (DriverHandle
== NULL
) {
4094 TempDevicePath
= DevicePath
;
4095 Status
= gBS
->LocateDevicePath (
4096 &gEfiDevicePathProtocolGuid
,
4100 if (EFI_ERROR (Status
) || (DriverHandle
== NULL
)) {
4102 // Routing data does not match any known driver.
4103 // Set Progress to the 'G' in "GUID" of the routing header.
4105 FreePool (DevicePath
);
4106 *Progress
= StringPtr
;
4107 FreePool (ConfigResp
);
4108 return EFI_NOT_FOUND
;
4112 FreePool (DevicePath
);
4115 // Check whether this ConfigRequest is search from Efi varstore type storage.
4117 Status
= GetVarStoreType(Database
, ConfigResp
, &IsEfiVarstore
, &EfiVarStoreInfo
);
4118 if (EFI_ERROR (Status
)) {
4122 if (IsEfiVarstore
) {
4124 // Call the SetVariable function to route settings.
4126 Status
= RouteConfigRespForEfiVarStore(This
, EfiVarStoreInfo
, ConfigResp
, &AccessProgress
);
4127 FreePool (EfiVarStoreInfo
);
4130 // Call corresponding ConfigAccess protocol to route settings
4132 Status
= gBS
->HandleProtocol (
4134 &gEfiHiiConfigAccessProtocolGuid
,
4135 (VOID
**) &ConfigAccess
4137 ASSERT_EFI_ERROR (Status
);
4139 Status
= ConfigAccess
->RouteConfig (
4145 if (EFI_ERROR (Status
)) {
4147 // AccessProgress indicates the parsing progress on <ConfigResp>.
4148 // Map it to the progress on <MultiConfigResp> then return it.
4150 *Progress
= StrStr (StringPtr
, AccessProgress
);
4152 FreePool (ConfigResp
);
4156 FreePool (ConfigResp
);
4160 // Go to next <ConfigResp> (skip '&').
4162 StringPtr
+= Length
;
4163 if (*StringPtr
== 0) {
4164 *Progress
= StringPtr
;
4177 This helper function is to be called by drivers to map configuration data
4178 stored in byte array ("block") formats such as UEFI Variables into current
4179 configuration strings.
4181 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
4183 @param ConfigRequest A null-terminated Unicode string in
4184 <ConfigRequest> format.
4185 @param Block Array of bytes defining the block's configuration.
4186 @param BlockSize Length in bytes of Block.
4187 @param Config Filled-in configuration string. String allocated
4188 by the function. Returned only if call is
4189 successful. It is <ConfigResp> string format.
4190 @param Progress A pointer to a string filled in with the offset of
4191 the most recent & before the first failing
4192 name/value pair (or the beginning of the string if
4193 the failure is in the first name / value pair) or
4194 the terminating NULL if all was successful.
4196 @retval EFI_SUCCESS The request succeeded. Progress points to the null
4197 terminator at the end of the ConfigRequest
4199 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress
4200 points to the first character of ConfigRequest.
4201 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigRequest or
4202 Block parameter would result in this type of
4203 error. Progress points to the first character of
4205 @retval EFI_DEVICE_ERROR Block not large enough. Progress undefined.
4206 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted string.
4207 Block is left updated and Progress points at
4208 the "&" preceding the first non-<BlockName>.
4214 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
4215 IN CONST EFI_STRING ConfigRequest
,
4216 IN CONST UINT8
*Block
,
4217 IN CONST UINTN BlockSize
,
4218 OUT EFI_STRING
*Config
,
4219 OUT EFI_STRING
*Progress
4222 HII_DATABASE_PRIVATE_DATA
*Private
;
4223 EFI_STRING StringPtr
;
4231 EFI_STRING ValueStr
;
4232 EFI_STRING ConfigElement
;
4238 if (This
== NULL
|| Progress
== NULL
|| Config
== NULL
) {
4239 return EFI_INVALID_PARAMETER
;
4242 if (Block
== NULL
|| ConfigRequest
== NULL
) {
4243 *Progress
= ConfigRequest
;
4244 return EFI_INVALID_PARAMETER
;
4248 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
4249 ASSERT (Private
!= NULL
);
4251 StringPtr
= ConfigRequest
;
4254 ConfigElement
= NULL
;
4257 // Allocate a fix length of memory to store Results. Reallocate memory for
4258 // Results if this fix length is insufficient.
4260 *Config
= (EFI_STRING
) AllocateZeroPool (MAX_STRING_LENGTH
);
4261 if (*Config
== NULL
) {
4262 return EFI_OUT_OF_RESOURCES
;
4268 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
4269 *Progress
= StringPtr
;
4270 Status
= EFI_INVALID_PARAMETER
;
4273 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"PATH=", StrLen (L
"PATH=")) != 0) {
4276 if (*StringPtr
== 0) {
4277 *Progress
= StringPtr
- 1;
4278 Status
= EFI_INVALID_PARAMETER
;
4282 while (*StringPtr
!= L
'&' && *StringPtr
!= 0) {
4285 if (*StringPtr
== 0) {
4286 *Progress
= StringPtr
;
4287 Status
= EFI_SUCCESS
;
4289 AppendToMultiString(Config
, ConfigRequest
);
4290 HiiToLower (*Config
);
4300 // Copy <ConfigHdr> and an additional '&' to <ConfigResp>
4302 TemChar
= *StringPtr
;
4304 AppendToMultiString(Config
, ConfigRequest
);
4305 *StringPtr
= TemChar
;
4308 // Parse each <RequestElement> if exists
4309 // Only <BlockName> format is supported by this help function.
4310 // <BlockName> ::= 'OFFSET='<Number>&'WIDTH='<Number>
4312 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"OFFSET=", StrLen (L
"OFFSET=")) == 0) {
4314 // Back up the header of one <BlockName>
4318 StringPtr
+= StrLen (L
"OFFSET=");
4322 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
4323 if (EFI_ERROR (Status
)) {
4324 *Progress
= ConfigRequest
;
4331 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
4333 FreePool (TmpBuffer
);
4335 StringPtr
+= Length
;
4336 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
4337 *Progress
= StringPtr
- Length
- StrLen (L
"OFFSET=") - 1;
4338 Status
= EFI_INVALID_PARAMETER
;
4341 StringPtr
+= StrLen (L
"&WIDTH=");
4346 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
4347 if (EFI_ERROR (Status
)) {
4348 *Progress
= ConfigRequest
;
4355 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
4357 FreePool (TmpBuffer
);
4359 StringPtr
+= Length
;
4360 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
4361 *Progress
= StringPtr
- Length
- StrLen (L
"&WIDTH=");
4362 Status
= EFI_INVALID_PARAMETER
;
4367 // Calculate Value and convert it to hex string.
4369 if (Offset
+ Width
> BlockSize
) {
4370 *Progress
= StringPtr
;
4371 Status
= EFI_DEVICE_ERROR
;
4375 Value
= (UINT8
*) AllocateZeroPool (Width
);
4376 if (Value
== NULL
) {
4377 *Progress
= ConfigRequest
;
4378 Status
= EFI_OUT_OF_RESOURCES
;
4382 CopyMem (Value
, (UINT8
*) Block
+ Offset
, Width
);
4384 Length
= Width
* 2 + 1;
4385 ValueStr
= (EFI_STRING
) AllocateZeroPool (Length
* sizeof (CHAR16
));
4386 if (ValueStr
== NULL
) {
4387 *Progress
= ConfigRequest
;
4388 Status
= EFI_OUT_OF_RESOURCES
;
4392 TemString
= ValueStr
;
4393 TemBuffer
= Value
+ Width
- 1;
4394 for (Index
= 0; Index
< Width
; Index
++, TemBuffer
--) {
4395 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
4402 // Build a ConfigElement
4404 Length
+= StringPtr
- TmpPtr
+ 1 + StrLen (L
"VALUE=");
4405 ConfigElement
= (EFI_STRING
) AllocateZeroPool (Length
* sizeof (CHAR16
));
4406 if (ConfigElement
== NULL
) {
4407 Status
= EFI_OUT_OF_RESOURCES
;
4410 CopyMem (ConfigElement
, TmpPtr
, (StringPtr
- TmpPtr
+ 1) * sizeof (CHAR16
));
4411 if (*StringPtr
== 0) {
4412 *(ConfigElement
+ (StringPtr
- TmpPtr
)) = L
'&';
4414 *(ConfigElement
+ (StringPtr
- TmpPtr
) + 1) = 0;
4415 StrCat (ConfigElement
, L
"VALUE=");
4416 StrCat (ConfigElement
, ValueStr
);
4418 AppendToMultiString (Config
, ConfigElement
);
4420 FreePool (ConfigElement
);
4421 FreePool (ValueStr
);
4422 ConfigElement
= NULL
;
4426 // If '\0', parsing is finished. Otherwise skip '&' to continue
4428 if (*StringPtr
== 0) {
4431 AppendToMultiString (Config
, L
"&");
4436 if (*StringPtr
!= 0) {
4437 *Progress
= StringPtr
- 1;
4438 Status
= EFI_INVALID_PARAMETER
;
4442 HiiToLower (*Config
);
4443 *Progress
= StringPtr
;
4447 if (*Config
!= NULL
) {
4451 if (ValueStr
!= NULL
) {
4452 FreePool (ValueStr
);
4454 if (Value
!= NULL
) {
4457 if (ConfigElement
!= NULL
) {
4458 FreePool (ConfigElement
);
4467 This helper function is to be called by drivers to map configuration strings
4468 to configurations stored in byte array ("block") formats such as UEFI Variables.
4470 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
4472 @param ConfigResp A null-terminated Unicode string in <ConfigResp>
4474 @param Block A possibly null array of bytes representing the
4475 current block. Only bytes referenced in the
4476 ConfigResp string in the block are modified. If
4477 this parameter is null or if the *BlockSize
4478 parameter is (on input) shorter than required by
4479 the Configuration string, only the BlockSize
4480 parameter is updated and an appropriate status
4481 (see below) is returned.
4482 @param BlockSize The length of the Block in units of UINT8. On
4483 input, this is the size of the Block. On output,
4484 if successful, contains the index of the last
4485 modified byte in the Block.
4486 @param Progress On return, points to an element of the ConfigResp
4487 string filled in with the offset of the most
4488 recent '&' before the first failing name / value
4489 pair (or the beginning of the string if the
4490 failure is in the first name / value pair) or the
4491 terminating NULL if all was successful.
4493 @retval EFI_SUCCESS The request succeeded. Progress points to the null
4494 terminator at the end of the ConfigResp string.
4495 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress
4496 points to the first character of ConfigResp.
4497 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigResp or
4498 Block parameter would result in this type of
4499 error. Progress points to the first character of
4501 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted name /
4502 value pair. Block is left updated and
4503 Progress points at the '&' preceding the first
4505 @retval EFI_DEVICE_ERROR Block not large enough. Progress undefined.
4506 @retval EFI_NOT_FOUND Target for the specified routing data was not found.
4507 Progress points to the "G" in "GUID" of the errant
4514 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
4515 IN CONST EFI_STRING ConfigResp
,
4516 IN OUT UINT8
*Block
,
4517 IN OUT UINTN
*BlockSize
,
4518 OUT EFI_STRING
*Progress
4521 HII_DATABASE_PRIVATE_DATA
*Private
;
4522 EFI_STRING StringPtr
;
4532 if (This
== NULL
|| BlockSize
== NULL
|| Progress
== NULL
) {
4533 return EFI_INVALID_PARAMETER
;
4536 *Progress
= ConfigResp
;
4537 if (ConfigResp
== NULL
) {
4538 return EFI_INVALID_PARAMETER
;
4541 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
4542 ASSERT (Private
!= NULL
);
4544 StringPtr
= ConfigResp
;
4545 BufferSize
= *BlockSize
;
4552 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
4553 *Progress
= StringPtr
;
4554 Status
= EFI_INVALID_PARAMETER
;
4557 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"PATH=", StrLen (L
"PATH=")) != 0) {
4560 if (*StringPtr
== 0) {
4561 *Progress
= StringPtr
;
4562 Status
= EFI_INVALID_PARAMETER
;
4566 while (*StringPtr
!= L
'&' && *StringPtr
!= 0) {
4569 if (*StringPtr
== 0) {
4570 *Progress
= StringPtr
;
4571 Status
= EFI_INVALID_PARAMETER
;
4576 // Parse each <ConfigElement> if exists
4577 // Only '&'<BlockConfig> format is supported by this help function.
4578 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE='<Number>
4580 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) == 0) {
4581 StringPtr
+= StrLen (L
"&OFFSET=");
4585 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
4586 if (EFI_ERROR (Status
)) {
4587 *Progress
= ConfigResp
;
4594 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
4596 FreePool (TmpBuffer
);
4598 StringPtr
+= Length
;
4599 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
4600 *Progress
= StringPtr
- Length
- StrLen (L
"&OFFSET=");
4601 Status
= EFI_INVALID_PARAMETER
;
4604 StringPtr
+= StrLen (L
"&WIDTH=");
4609 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
4610 if (EFI_ERROR (Status
)) {
4611 *Progress
= ConfigResp
;
4618 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
4620 FreePool (TmpBuffer
);
4622 StringPtr
+= Length
;
4623 if (StrnCmp (StringPtr
, L
"&VALUE=", StrLen (L
"&VALUE=")) != 0) {
4624 *Progress
= StringPtr
- Length
- StrLen (L
"&WIDTH=");
4625 Status
= EFI_INVALID_PARAMETER
;
4628 StringPtr
+= StrLen (L
"&VALUE=");
4633 Status
= GetValueOfNumber (StringPtr
, &Value
, &Length
);
4634 if (EFI_ERROR (Status
)) {
4635 *Progress
= ConfigResp
;
4639 StringPtr
+= Length
;
4640 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
4641 *Progress
= StringPtr
- Length
- StrLen (L
"&VALUE=");
4642 Status
= EFI_INVALID_PARAMETER
;
4647 // Update the Block with configuration info
4649 if ((Block
!= NULL
) && (Offset
+ Width
<= BufferSize
)) {
4650 CopyMem (Block
+ Offset
, Value
, Width
);
4652 if (Offset
+ Width
> MaxBlockSize
) {
4653 MaxBlockSize
= Offset
+ Width
;
4660 // If '\0', parsing is finished.
4662 if (*StringPtr
== 0) {
4668 // The input string is not ConfigResp format, return error.
4670 if (*StringPtr
!= 0) {
4671 *Progress
= StringPtr
;
4672 Status
= EFI_INVALID_PARAMETER
;
4676 *Progress
= StringPtr
+ StrLen (StringPtr
);
4677 *BlockSize
= MaxBlockSize
- 1;
4679 if (MaxBlockSize
> BufferSize
) {
4680 *BlockSize
= MaxBlockSize
;
4681 if (Block
!= NULL
) {
4682 return EFI_DEVICE_ERROR
;
4686 if (Block
== NULL
) {
4687 *Progress
= ConfigResp
;
4688 return EFI_INVALID_PARAMETER
;
4695 if (Value
!= NULL
) {
4703 This helper function is to be called by drivers to extract portions of
4704 a larger configuration string.
4706 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
4708 @param Configuration A null-terminated Unicode string in
4709 <MultiConfigAltResp> format.
4710 @param Guid A pointer to the GUID value to search for in the
4711 routing portion of the ConfigResp string when
4712 retrieving the requested data. If Guid is NULL,
4713 then all GUID values will be searched for.
4714 @param Name A pointer to the NAME value to search for in the
4715 routing portion of the ConfigResp string when
4716 retrieving the requested data. If Name is NULL,
4717 then all Name values will be searched for.
4718 @param DevicePath A pointer to the PATH value to search for in the
4719 routing portion of the ConfigResp string when
4720 retrieving the requested data. If DevicePath is
4721 NULL, then all DevicePath values will be searched
4723 @param AltCfgId A pointer to the ALTCFG value to search for in the
4724 routing portion of the ConfigResp string when
4725 retrieving the requested data. If this parameter
4726 is NULL, then the current setting will be
4728 @param AltCfgResp A pointer to a buffer which will be allocated by
4729 the function which contains the retrieved string
4730 as requested. This buffer is only allocated if
4731 the call was successful. It is <ConfigResp> format.
4733 @retval EFI_SUCCESS The request succeeded. The requested data was
4734 extracted and placed in the newly allocated
4736 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate AltCfgResp.
4737 @retval EFI_INVALID_PARAMETER Any parameter is invalid.
4738 @retval EFI_NOT_FOUND Target for the specified routing data was not
4745 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
4746 IN CONST EFI_STRING Configuration
,
4747 IN CONST EFI_GUID
*Guid
,
4748 IN CONST EFI_STRING Name
,
4749 IN CONST EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
4750 IN CONST UINT16
*AltCfgId
,
4751 OUT EFI_STRING
*AltCfgResp
4755 EFI_STRING StringPtr
;
4756 EFI_STRING HdrStart
;
4763 EFI_STRING AltIdStr
;
4780 if (This
== NULL
|| Configuration
== NULL
|| AltCfgResp
== NULL
) {
4781 return EFI_INVALID_PARAMETER
;
4784 StringPtr
= Configuration
;
4785 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
4786 return EFI_INVALID_PARAMETER
;
4790 // Generate the sub string for later matching.
4792 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*) Guid
, 1, &GuidStr
);
4795 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) DevicePath
),
4796 (VOID
*) DevicePath
,
4800 if (AltCfgId
!= NULL
) {
4801 GenerateSubStr (L
"ALTCFG=", sizeof (UINT16
), (VOID
*) AltCfgId
, 3, &AltIdStr
);
4804 GenerateSubStr (L
"NAME=", StrLen (Name
) * sizeof (CHAR16
), (VOID
*) Name
, 2, &NameStr
);
4806 GenerateSubStr (L
"NAME=", 0, NULL
, 2, &NameStr
);
4809 while (*StringPtr
!= 0) {
4811 // Try to match the GUID
4814 TmpPtr
= StrStr (StringPtr
, GuidStr
);
4815 if (TmpPtr
== NULL
) {
4816 Status
= EFI_NOT_FOUND
;
4822 // Jump to <NameHdr>
4825 StringPtr
= TmpPtr
+ StrLen (GuidStr
);
4827 StringPtr
= StrStr (TmpPtr
, L
"NAME=");
4828 if (StringPtr
== NULL
) {
4829 Status
= EFI_NOT_FOUND
;
4837 // Try to match the NAME
4839 if (GuidFlag
&& !NameFlag
) {
4840 if (StrnCmp (StringPtr
, NameStr
, StrLen (NameStr
)) != 0) {
4844 // Jump to <PathHdr>
4847 StringPtr
+= StrLen (NameStr
);
4849 StringPtr
= StrStr (StringPtr
, L
"PATH=");
4850 if (StringPtr
== NULL
) {
4851 Status
= EFI_NOT_FOUND
;
4860 // Try to match the DevicePath
4862 if (GuidFlag
&& NameFlag
&& !PathFlag
) {
4863 if (StrnCmp (StringPtr
, PathStr
, StrLen (PathStr
)) != 0) {
4868 // Jump to '&' before <DescHdr> or <ConfigBody>
4870 if (DevicePath
!= NULL
) {
4871 StringPtr
+= StrLen (PathStr
);
4873 StringPtr
= StrStr (StringPtr
, L
"&");
4874 if (StringPtr
== NULL
) {
4875 Status
= EFI_NOT_FOUND
;
4886 // Try to match the AltCfgId
4888 if (GuidFlag
&& NameFlag
&& PathFlag
) {
4889 if (AltCfgId
== NULL
) {
4891 // Return Current Setting when AltCfgId is NULL.
4893 Status
= OutputConfigBody (StringPtr
, &Result
);
4897 // Search the <ConfigAltResp> to get the <AltResp> with AltCfgId.
4899 if (StrnCmp (StringPtr
, AltIdStr
, StrLen (AltIdStr
)) != 0) {
4905 // Skip AltIdStr and &
4907 StringPtr
= StringPtr
+ StrLen (AltIdStr
);
4908 Status
= OutputConfigBody (StringPtr
, &Result
);
4914 Status
= EFI_NOT_FOUND
;
4918 if (!EFI_ERROR (Status
) && (Result
!= NULL
)) {
4920 // Copy the <ConfigHdr> and <ConfigBody>
4922 Length
= HdrEnd
- HdrStart
+ StrLen (Result
) + 1;
4923 *AltCfgResp
= AllocateZeroPool (Length
* sizeof (CHAR16
));
4924 if (*AltCfgResp
== NULL
) {
4925 Status
= EFI_OUT_OF_RESOURCES
;
4927 StrnCpy (*AltCfgResp
, HdrStart
, HdrEnd
- HdrStart
);
4928 StrCat (*AltCfgResp
, Result
);
4929 Status
= EFI_SUCCESS
;
4933 if (GuidStr
!= NULL
) {
4936 if (NameStr
!= NULL
) {
4939 if (PathStr
!= NULL
) {
4942 if (AltIdStr
!= NULL
) {
4943 FreePool (AltIdStr
);
4945 if (Result
!= NULL
) {