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
;
1128 *IsEfiVarstore
= FALSE
;
1130 Status
= GetFormPackageData(DataBaseRecord
, &HiiFormPackage
, &PackageSize
);
1131 if (EFI_ERROR (Status
)) {
1135 IfrOffset
= sizeof (EFI_HII_PACKAGE_HEADER
);
1136 while (IfrOffset
< PackageSize
) {
1137 IfrOpHdr
= (EFI_IFR_OP_HEADER
*) (HiiFormPackage
+ IfrOffset
);
1138 IfrOffset
+= IfrOpHdr
->Length
;
1140 if (IfrOpHdr
->OpCode
== EFI_IFR_VARSTORE_EFI_OP
) {
1141 IfrEfiVarStore
= (EFI_IFR_VARSTORE_EFI
*) IfrOpHdr
;
1143 // If the length is small than the structure, this is from old efi
1144 // varstore definition. Old efi varstore get config directly from
1145 // GetVariable function.
1147 if (IfrOpHdr
->Length
< sizeof (EFI_IFR_VARSTORE_EFI
)) {
1151 VarStoreName
= AllocateZeroPool (AsciiStrSize ((CHAR8
*)IfrEfiVarStore
->Name
) * sizeof (CHAR16
));
1152 if (VarStoreName
== NULL
) {
1153 Status
= EFI_OUT_OF_RESOURCES
;
1156 AsciiStrToUnicodeStr ((CHAR8
*) IfrEfiVarStore
->Name
, VarStoreName
);
1158 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*) &IfrEfiVarStore
->Guid
, 1, &GuidStr
);
1159 GenerateSubStr (L
"NAME=", StrLen (VarStoreName
) * sizeof (CHAR16
), (VOID
*) VarStoreName
, 2, &NameStr
);
1160 LengthString
= StrLen (GuidStr
);
1161 LengthString
= LengthString
+ StrLen (NameStr
) + 1;
1162 TempStr
= AllocateZeroPool (LengthString
* sizeof (CHAR16
));
1163 if (TempStr
== NULL
) {
1166 FreePool (VarStoreName
);
1167 Status
= EFI_OUT_OF_RESOURCES
;
1170 StrCpy (TempStr
, GuidStr
);
1171 StrCat (TempStr
, NameStr
);
1172 if (ConfigHdr
== NULL
|| StrnCmp (ConfigHdr
, TempStr
, StrLen (TempStr
)) == 0) {
1173 *EfiVarStore
= (EFI_IFR_VARSTORE_EFI
*) AllocateZeroPool (IfrOpHdr
->Length
);
1174 if (*EfiVarStore
== NULL
) {
1175 FreePool (VarStoreName
);
1179 Status
= EFI_OUT_OF_RESOURCES
;
1182 *IsEfiVarstore
= TRUE
;
1183 CopyMem (*EfiVarStore
, IfrEfiVarStore
, IfrOpHdr
->Length
);
1187 // Free alllocated temp string.
1189 FreePool (VarStoreName
);
1196 if (HiiFormPackage
!= NULL
) {
1197 FreePool (HiiFormPackage
);
1204 Check whether the ConfigRequest string has the request elements.
1205 For EFI_HII_VARSTORE_BUFFER type, the request has "&OFFSET=****&WIDTH=****..." format.
1206 For EFI_HII_VARSTORE_NAME_VALUE type, the request has "&NAME1**&NAME2..." format.
1208 @param ConfigRequest The input config request string.
1210 @retval TRUE The input include config request elements.
1211 @retval FALSE The input string not includes.
1215 GetElementsFromRequest (
1216 IN EFI_STRING ConfigRequest
1219 EFI_STRING TmpRequest
;
1221 TmpRequest
= StrStr (ConfigRequest
, L
"PATH=");
1222 ASSERT (TmpRequest
!= NULL
);
1224 if ((StrStr (TmpRequest
, L
"&OFFSET=") != NULL
) || (StrStr (TmpRequest
, L
"&") != NULL
)) {
1232 Check whether the this varstore is the request varstore.
1234 @param VarstoreGuid Varstore guid.
1235 @param Name Varstore name.
1236 @param ConfigHdr Current configRequest info.
1238 @retval TRUE This varstore is the requst one.
1239 @retval FALSE This varstore is not the requst one.
1244 IN EFI_GUID
*VarstoreGuid
,
1246 IN CHAR16
*ConfigHdr
1259 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*)VarstoreGuid
, 1, &GuidStr
);
1261 GenerateSubStr (L
"NAME=", StrLen (Name
) * sizeof (CHAR16
), (VOID
*) Name
, 2, &NameStr
);
1263 GenerateSubStr (L
"NAME=", 0, NULL
, 2, &NameStr
);
1265 LengthString
= StrLen (GuidStr
);
1266 LengthString
= LengthString
+ StrLen (NameStr
) + 1;
1267 TempStr
= AllocateZeroPool (LengthString
* sizeof (CHAR16
));
1268 if (TempStr
== NULL
) {
1272 StrCpy (TempStr
, GuidStr
);
1273 StrCat (TempStr
, NameStr
);
1275 if (ConfigHdr
== NULL
|| StrnCmp (ConfigHdr
, TempStr
, StrLen (TempStr
)) == 0) {
1280 if (GuidStr
!= NULL
) {
1284 if (NameStr
!= NULL
) {
1288 if (TempStr
!= NULL
) {
1296 Check whether the this op code is required.
1298 @param RequestBlockArray The array includes all the request info or NULL.
1299 @param HiiHandle The hii handle for this form package.
1300 @param VarStorageData The varstore data strucure.
1301 @param IfrOpHdr Ifr opcode header for this opcode.
1302 @param VarWidth The buffer width for this opcode.
1303 @param ReturnData The data block added for this opcode.
1305 @retval EFI_SUCCESS This opcode is required.
1306 @retval Others This opcode is not required or error occur.
1310 IsThisOpcodeRequired (
1311 IN IFR_BLOCK_DATA
*RequestBlockArray
,
1312 IN EFI_HII_HANDLE HiiHandle
,
1313 IN OUT IFR_VARSTORAGE_DATA
*VarStorageData
,
1314 IN EFI_IFR_OP_HEADER
*IfrOpHdr
,
1316 OUT IFR_BLOCK_DATA
**ReturnData
1319 IFR_BLOCK_DATA
*BlockData
;
1321 EFI_STRING_ID NameId
;
1322 EFI_IFR_QUESTION_HEADER
*IfrQuestionHdr
;
1326 IfrQuestionHdr
= (EFI_IFR_QUESTION_HEADER
*)((CHAR8
*) IfrOpHdr
+ sizeof (EFI_IFR_OP_HEADER
));
1328 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
1329 NameId
= IfrQuestionHdr
->VarStoreInfo
.VarName
;
1332 // Check whether this question is in requested block array.
1334 if (!BlockArrayCheck (RequestBlockArray
, NameId
, 0, TRUE
, HiiHandle
)) {
1336 // This question is not in the requested string. Skip it.
1341 VarOffset
= IfrQuestionHdr
->VarStoreInfo
.VarOffset
;
1344 // Check whether this question is in requested block array.
1346 if (!BlockArrayCheck (RequestBlockArray
, VarOffset
, VarWidth
, FALSE
, HiiHandle
)) {
1348 // This question is not in the requested string. Skip it.
1354 // Check this var question is in the var storage
1356 if (((VarOffset
+ VarWidth
) > VarStorageData
->Size
)) {
1357 return EFI_INVALID_PARAMETER
;
1361 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
1362 if (BlockData
== NULL
) {
1363 return EFI_OUT_OF_RESOURCES
;
1366 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
1367 BlockData
->Name
= InternalGetString(HiiHandle
, NameId
);
1369 BlockData
->Offset
= VarOffset
;
1372 BlockData
->Width
= VarWidth
;
1373 BlockData
->QuestionId
= IfrQuestionHdr
->QuestionId
;
1374 BlockData
->OpCode
= IfrOpHdr
->OpCode
;
1375 BlockData
->Scope
= IfrOpHdr
->Scope
;
1376 InitializeListHead (&BlockData
->DefaultValueEntry
);
1378 // Add Block Data into VarStorageData BlockEntry
1380 InsertBlockData (&VarStorageData
->BlockEntry
, &BlockData
);
1381 *ReturnData
= BlockData
;
1387 This function parses Form Package to get the block array and the default
1388 value array according to the request ConfigHdr.
1390 @param HiiHandle Hii Handle for this hii package.
1391 @param Package Pointer to the form package data.
1392 @param PackageLength Length of the pacakge.
1393 @param ConfigHdr Request string ConfigHdr. If it is NULL,
1394 the first found varstore will be as ConfigHdr.
1395 @param RequestBlockArray The block array is retrieved from the request string.
1396 @param VarStorageData VarStorage structure contains the got block and default value.
1397 @param DefaultIdArray Point to the got default id and default name array.
1399 @retval EFI_SUCCESS The block array and the default value array are got.
1400 @retval EFI_INVALID_PARAMETER The varstore defintion in the differnt form pacakges
1402 @retval EFI_OUT_OF_RESOURCES No enough memory.
1407 IN EFI_HII_HANDLE HiiHandle
,
1409 IN UINT32 PackageLength
,
1410 IN EFI_STRING ConfigHdr
,
1411 IN IFR_BLOCK_DATA
*RequestBlockArray
,
1412 IN OUT IFR_VARSTORAGE_DATA
*VarStorageData
,
1413 OUT IFR_DEFAULT_DATA
*DefaultIdArray
1418 EFI_IFR_VARSTORE
*IfrVarStore
;
1419 EFI_IFR_VARSTORE_EFI
*IfrEfiVarStore
;
1420 EFI_IFR_OP_HEADER
*IfrOpHdr
;
1421 EFI_IFR_ONE_OF
*IfrOneOf
;
1422 EFI_IFR_REF4
*IfrRef
;
1423 EFI_IFR_ONE_OF_OPTION
*IfrOneOfOption
;
1424 EFI_IFR_DEFAULT
*IfrDefault
;
1425 EFI_IFR_ORDERED_LIST
*IfrOrderedList
;
1426 EFI_IFR_CHECKBOX
*IfrCheckBox
;
1427 EFI_IFR_PASSWORD
*IfrPassword
;
1428 EFI_IFR_STRING
*IfrString
;
1429 EFI_IFR_DATE
*IfrDate
;
1430 EFI_IFR_TIME
*IfrTime
;
1431 IFR_DEFAULT_DATA DefaultData
;
1432 IFR_DEFAULT_DATA
*DefaultDataPtr
;
1433 IFR_BLOCK_DATA
*BlockData
;
1434 CHAR16
*VarStoreName
;
1436 UINT16 VarDefaultId
;
1437 BOOLEAN FirstOneOfOption
;
1438 LIST_ENTRY
*LinkData
;
1439 LIST_ENTRY
*LinkDefault
;
1440 EFI_IFR_VARSTORE_NAME_VALUE
*IfrNameValueVarStore
;
1442 Status
= EFI_SUCCESS
;
1444 DefaultDataPtr
= NULL
;
1445 FirstOneOfOption
= FALSE
;
1446 ZeroMem (&DefaultData
, sizeof (IFR_DEFAULT_DATA
));
1449 // Go through the form package to parse OpCode one by one.
1451 IfrOffset
= sizeof (EFI_HII_PACKAGE_HEADER
);
1452 while (IfrOffset
< PackageLength
) {
1453 IfrOpHdr
= (EFI_IFR_OP_HEADER
*) (Package
+ IfrOffset
);
1454 switch (IfrOpHdr
->OpCode
) {
1455 case EFI_IFR_VARSTORE_OP
:
1457 // VarStore is found. Don't need to search any more.
1459 if (VarStorageData
->VarStoreId
!= 0) {
1463 IfrVarStore
= (EFI_IFR_VARSTORE
*) IfrOpHdr
;
1465 VarStoreName
= AllocateZeroPool (AsciiStrSize ((CHAR8
*)IfrVarStore
->Name
) * sizeof (CHAR16
));
1466 if (VarStoreName
== NULL
) {
1467 Status
= EFI_OUT_OF_RESOURCES
;
1470 AsciiStrToUnicodeStr ((CHAR8
*)IfrVarStore
->Name
, VarStoreName
);
1472 if (IsThisVarstore((VOID
*)&IfrVarStore
->Guid
, VarStoreName
, ConfigHdr
)) {
1474 // Find the matched VarStore
1476 CopyGuid (&VarStorageData
->Guid
, (EFI_GUID
*) (VOID
*) &IfrVarStore
->Guid
);
1477 VarStorageData
->VarStoreId
= IfrVarStore
->VarStoreId
;
1478 VarStorageData
->Size
= IfrVarStore
->Size
;
1479 VarStorageData
->Name
= VarStoreName
;
1480 VarStorageData
->Type
= EFI_HII_VARSTORE_BUFFER
;
1484 case EFI_IFR_VARSTORE_EFI_OP
:
1486 // VarStore is found. Don't need to search any more.
1488 if (VarStorageData
->VarStoreId
!= 0) {
1492 IfrEfiVarStore
= (EFI_IFR_VARSTORE_EFI
*) IfrOpHdr
;
1495 // If the length is small than the structure, this is from old efi
1496 // varstore definition. Old efi varstore get config directly from
1497 // GetVariable function.
1499 if (IfrOpHdr
->Length
< sizeof (EFI_IFR_VARSTORE_EFI
)) {
1503 VarStoreName
= AllocateZeroPool (AsciiStrSize ((CHAR8
*)IfrEfiVarStore
->Name
) * sizeof (CHAR16
));
1504 if (VarStoreName
== NULL
) {
1505 Status
= EFI_OUT_OF_RESOURCES
;
1508 AsciiStrToUnicodeStr ((CHAR8
*)IfrEfiVarStore
->Name
, VarStoreName
);
1510 if (IsThisVarstore (&IfrEfiVarStore
->Guid
, VarStoreName
, ConfigHdr
)) {
1512 // Find the matched VarStore
1514 CopyGuid (&VarStorageData
->Guid
, (EFI_GUID
*) (VOID
*) &IfrEfiVarStore
->Guid
);
1515 VarStorageData
->VarStoreId
= IfrEfiVarStore
->VarStoreId
;
1516 VarStorageData
->Size
= IfrEfiVarStore
->Size
;
1517 VarStorageData
->Name
= VarStoreName
;
1518 VarStorageData
->Type
= EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
;
1522 case EFI_IFR_VARSTORE_NAME_VALUE_OP
:
1524 // VarStore is found. Don't need to search any more.
1526 if (VarStorageData
->VarStoreId
!= 0) {
1530 IfrNameValueVarStore
= (EFI_IFR_VARSTORE_NAME_VALUE
*) IfrOpHdr
;
1532 if (IsThisVarstore (&IfrNameValueVarStore
->Guid
, NULL
, ConfigHdr
)) {
1534 // Find the matched VarStore
1536 CopyGuid (&VarStorageData
->Guid
, (EFI_GUID
*) (VOID
*) &IfrNameValueVarStore
->Guid
);
1537 VarStorageData
->VarStoreId
= IfrNameValueVarStore
->VarStoreId
;
1538 VarStorageData
->Type
= EFI_HII_VARSTORE_NAME_VALUE
;
1542 case EFI_IFR_DEFAULTSTORE_OP
:
1544 // Add new the map between default id and default name.
1546 DefaultDataPtr
= (IFR_DEFAULT_DATA
*) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
1547 if (DefaultDataPtr
== NULL
) {
1548 Status
= EFI_OUT_OF_RESOURCES
;
1551 DefaultDataPtr
->DefaultId
= ((EFI_IFR_DEFAULTSTORE
*) IfrOpHdr
)->DefaultId
;
1552 InsertTailList (&DefaultIdArray
->Entry
, &DefaultDataPtr
->Entry
);
1553 DefaultDataPtr
= NULL
;
1556 case EFI_IFR_FORM_OP
:
1557 case EFI_IFR_FORM_MAP_OP
:
1559 // No matched varstore is found and directly return.
1561 if (VarStorageData
->VarStoreId
== 0) {
1562 Status
= EFI_SUCCESS
;
1567 case EFI_IFR_REF_OP
:
1569 // Ref question is not in IFR Form. This IFR form is not valid.
1571 if (VarStorageData
->VarStoreId
== 0) {
1572 Status
= EFI_INVALID_PARAMETER
;
1576 // Check whether this question is for the requested varstore.
1578 IfrRef
= (EFI_IFR_REF4
*) IfrOpHdr
;
1579 if (IfrRef
->Question
.VarStoreId
!= VarStorageData
->VarStoreId
) {
1582 VarWidth
= (UINT16
) (sizeof (EFI_HII_REF
));
1584 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
1585 if (EFI_ERROR (Status
)) {
1590 case EFI_IFR_ONE_OF_OP
:
1591 case EFI_IFR_NUMERIC_OP
:
1593 // Numeric and OneOf has the same opcode structure.
1597 // Numeric and OneOf question is not in IFR Form. This IFR form is not valid.
1599 if (VarStorageData
->VarStoreId
== 0) {
1600 Status
= EFI_INVALID_PARAMETER
;
1604 // Check whether this question is for the requested varstore.
1606 IfrOneOf
= (EFI_IFR_ONE_OF
*) IfrOpHdr
;
1607 if (IfrOneOf
->Question
.VarStoreId
!= VarStorageData
->VarStoreId
) {
1610 VarWidth
= (UINT16
) (1 << (IfrOneOf
->Flags
& EFI_IFR_NUMERIC_SIZE
));
1612 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
1613 if (EFI_ERROR (Status
)) {
1617 if (BlockData
== NULL
) {
1619 // BlockData == NULL means this opcode is not in the requst array.
1624 if (IfrOpHdr
->OpCode
== EFI_IFR_ONE_OF_OP
) {
1626 // Set this flag to TRUE for the first oneof option.
1628 FirstOneOfOption
= TRUE
;
1629 } else if (IfrOpHdr
->OpCode
== EFI_IFR_NUMERIC_OP
) {
1631 // Numeric minimum value will be used as default value when no default is specified.
1633 DefaultData
.Type
= DefaultValueFromDefault
;
1634 switch (IfrOneOf
->Flags
& EFI_IFR_NUMERIC_SIZE
) {
1635 case EFI_IFR_NUMERIC_SIZE_1
:
1636 DefaultData
.Value
.u8
= IfrOneOf
->data
.u8
.MinValue
;
1639 case EFI_IFR_NUMERIC_SIZE_2
:
1640 CopyMem (&DefaultData
.Value
.u16
, &IfrOneOf
->data
.u16
.MinValue
, sizeof (UINT16
));
1643 case EFI_IFR_NUMERIC_SIZE_4
:
1644 CopyMem (&DefaultData
.Value
.u32
, &IfrOneOf
->data
.u32
.MinValue
, sizeof (UINT32
));
1647 case EFI_IFR_NUMERIC_SIZE_8
:
1648 CopyMem (&DefaultData
.Value
.u64
, &IfrOneOf
->data
.u64
.MinValue
, sizeof (UINT64
));
1652 Status
= EFI_INVALID_PARAMETER
;
1656 // Set default value base on the DefaultId list get from IFR data.
1658 for (LinkData
= DefaultIdArray
->Entry
.ForwardLink
; LinkData
!= &DefaultIdArray
->Entry
; LinkData
= LinkData
->ForwardLink
) {
1659 DefaultDataPtr
= BASE_CR (LinkData
, IFR_DEFAULT_DATA
, Entry
);
1660 DefaultData
.DefaultId
= DefaultDataPtr
->DefaultId
;
1661 InsertDefaultValue (BlockData
, &DefaultData
);
1666 case EFI_IFR_ORDERED_LIST_OP
:
1668 // offset by question header
1669 // width by EFI_IFR_ORDERED_LIST MaxContainers * OneofOption Type
1670 // no default value and default id, how to define its default value?
1674 // OrderedList question is not in IFR Form. This IFR form is not valid.
1676 if (VarStorageData
->VarStoreId
== 0) {
1677 Status
= EFI_INVALID_PARAMETER
;
1681 // Check whether this question is for the requested varstore.
1683 IfrOrderedList
= (EFI_IFR_ORDERED_LIST
*) IfrOpHdr
;
1684 if (IfrOrderedList
->Question
.VarStoreId
!= VarStorageData
->VarStoreId
) {
1688 VarWidth
= IfrOrderedList
->MaxContainers
;
1689 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
1690 if (EFI_ERROR (Status
)) {
1695 case EFI_IFR_CHECKBOX_OP
:
1697 // EFI_IFR_DEFAULT_OP
1698 // offset by question header
1699 // width is 1 sizeof (BOOLEAN)
1700 // default id by CheckBox Flags if CheckBox flags (Default or Mau) is set, the default value is 1 to be set.
1701 // value by DefaultOption
1702 // default id by DeaultOption DefaultId can override CheckBox Flags and Default value.
1706 // CheckBox question is not in IFR Form. This IFR form is not valid.
1708 if (VarStorageData
->VarStoreId
== 0) {
1709 Status
= EFI_INVALID_PARAMETER
;
1713 // Check whether this question is for the requested varstore.
1715 IfrCheckBox
= (EFI_IFR_CHECKBOX
*) IfrOpHdr
;
1716 if (IfrCheckBox
->Question
.VarStoreId
!= VarStorageData
->VarStoreId
) {
1719 VarWidth
= (UINT16
) sizeof (BOOLEAN
);
1720 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
1721 if (EFI_ERROR (Status
)) {
1725 if (BlockData
== NULL
) {
1727 // BlockData == NULL means this opcode is not in the requst array.
1733 // Add default value for standard ID by CheckBox Flag
1735 VarDefaultId
= EFI_HII_DEFAULT_CLASS_STANDARD
;
1737 // Prepare new DefaultValue
1739 DefaultData
.DefaultId
= VarDefaultId
;
1740 if ((IfrCheckBox
->Flags
& EFI_IFR_CHECKBOX_DEFAULT
) == EFI_IFR_CHECKBOX_DEFAULT
) {
1742 // When flag is set, defautl value is TRUE.
1744 DefaultData
.Type
= DefaultValueFromFlag
;
1745 DefaultData
.Value
.b
= TRUE
;
1748 // When flag is not set, defautl value is FASLE.
1750 DefaultData
.Type
= DefaultValueFromDefault
;
1751 DefaultData
.Value
.b
= FALSE
;
1754 // Add DefaultValue into current BlockData
1756 InsertDefaultValue (BlockData
, &DefaultData
);
1759 // Add default value for Manufacture ID by CheckBox Flag
1761 VarDefaultId
= EFI_HII_DEFAULT_CLASS_MANUFACTURING
;
1763 // Prepare new DefaultValue
1765 DefaultData
.DefaultId
= VarDefaultId
;
1766 if ((IfrCheckBox
->Flags
& EFI_IFR_CHECKBOX_DEFAULT_MFG
) == EFI_IFR_CHECKBOX_DEFAULT_MFG
) {
1768 // When flag is set, defautl value is TRUE.
1770 DefaultData
.Type
= DefaultValueFromFlag
;
1771 DefaultData
.Value
.b
= TRUE
;
1774 // When flag is not set, defautl value is FASLE.
1776 DefaultData
.Type
= DefaultValueFromDefault
;
1777 DefaultData
.Value
.b
= FALSE
;
1780 // Add DefaultValue into current BlockData
1782 InsertDefaultValue (BlockData
, &DefaultData
);
1785 case EFI_IFR_DATE_OP
:
1787 // offset by question header
1788 // width MaxSize * sizeof (CHAR16)
1789 // no default value, only block array
1793 // Date question is not in IFR Form. This IFR form is not valid.
1795 if (VarStorageData
->VarStoreId
== 0) {
1796 Status
= EFI_INVALID_PARAMETER
;
1800 // Check whether this question is for the requested varstore.
1802 IfrDate
= (EFI_IFR_DATE
*) IfrOpHdr
;
1803 if (IfrDate
->Question
.VarStoreId
!= VarStorageData
->VarStoreId
) {
1807 VarWidth
= (UINT16
) sizeof (EFI_HII_DATE
);
1808 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
1809 if (EFI_ERROR (Status
)) {
1814 case EFI_IFR_TIME_OP
:
1816 // offset by question header
1817 // width MaxSize * sizeof (CHAR16)
1818 // no default value, only block array
1822 // Time question is not in IFR Form. This IFR form is not valid.
1824 if (VarStorageData
->VarStoreId
== 0) {
1825 Status
= EFI_INVALID_PARAMETER
;
1829 // Check whether this question is for the requested varstore.
1831 IfrTime
= (EFI_IFR_TIME
*) IfrOpHdr
;
1832 if (IfrTime
->Question
.VarStoreId
!= VarStorageData
->VarStoreId
) {
1836 VarWidth
= (UINT16
) sizeof (EFI_HII_TIME
);
1837 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
1838 if (EFI_ERROR (Status
)) {
1843 case EFI_IFR_STRING_OP
:
1845 // offset by question header
1846 // width MaxSize * sizeof (CHAR16)
1847 // no default value, only block array
1851 // String question is not in IFR Form. This IFR form is not valid.
1853 if (VarStorageData
->VarStoreId
== 0) {
1854 Status
= EFI_INVALID_PARAMETER
;
1858 // Check whether this question is for the requested varstore.
1860 IfrString
= (EFI_IFR_STRING
*) IfrOpHdr
;
1861 if (IfrString
->Question
.VarStoreId
!= VarStorageData
->VarStoreId
) {
1865 VarWidth
= (UINT16
) (IfrString
->MaxSize
* sizeof (UINT16
));
1866 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
1867 if (EFI_ERROR (Status
)) {
1872 // No default value for string.
1877 case EFI_IFR_PASSWORD_OP
:
1879 // offset by question header
1880 // width MaxSize * sizeof (CHAR16)
1881 // no default value, only block array
1885 // Password question is not in IFR Form. This IFR form is not valid.
1887 if (VarStorageData
->VarStoreId
== 0) {
1888 Status
= EFI_INVALID_PARAMETER
;
1892 // Check whether this question is for the requested varstore.
1894 IfrPassword
= (EFI_IFR_PASSWORD
*) IfrOpHdr
;
1895 if (IfrPassword
->Question
.VarStoreId
!= VarStorageData
->VarStoreId
) {
1899 VarWidth
= (UINT16
) (IfrPassword
->MaxSize
* sizeof (UINT16
));
1900 Status
= IsThisOpcodeRequired(RequestBlockArray
, HiiHandle
, VarStorageData
, IfrOpHdr
, VarWidth
, &BlockData
);
1901 if (EFI_ERROR (Status
)) {
1906 // No default value for string.
1911 case EFI_IFR_ONE_OF_OPTION_OP
:
1913 // No matched block data is ignored.
1915 if (BlockData
== NULL
|| BlockData
->Scope
== 0) {
1919 IfrOneOfOption
= (EFI_IFR_ONE_OF_OPTION
*) IfrOpHdr
;
1920 if (BlockData
->OpCode
== EFI_IFR_ORDERED_LIST_OP
) {
1922 // Get ordered list option data type.
1924 if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_8
|| IfrOneOfOption
->Type
== EFI_IFR_TYPE_BOOLEAN
) {
1926 } else if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_16
) {
1928 } else if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_32
) {
1930 } else if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_64
) {
1934 // Invalid ordered list option data type.
1936 Status
= EFI_INVALID_PARAMETER
;
1937 if (BlockData
->Name
!= NULL
) {
1938 FreePool (BlockData
->Name
);
1940 FreePool (BlockData
);
1945 // Calculate Ordered list QuestionId width.
1947 BlockData
->Width
= (UINT16
) (BlockData
->Width
* VarWidth
);
1949 // Check whether this question is in requested block array.
1951 if (!BlockArrayCheck (RequestBlockArray
, BlockData
->Offset
, BlockData
->Width
, (BOOLEAN
)(BlockData
->Name
!= NULL
), HiiHandle
)) {
1953 // This question is not in the requested string. Skip it.
1955 if (BlockData
->Name
!= NULL
) {
1956 FreePool (BlockData
->Name
);
1958 FreePool (BlockData
);
1963 // Check this var question is in the var storage
1965 if ((BlockData
->Name
== NULL
) && ((BlockData
->Offset
+ BlockData
->Width
) > VarStorageData
->Size
)) {
1966 Status
= EFI_INVALID_PARAMETER
;
1967 if (BlockData
->Name
!= NULL
) {
1968 FreePool (BlockData
->Name
);
1970 FreePool (BlockData
);
1974 // Add Block Data into VarStorageData BlockEntry
1976 InsertBlockData (&VarStorageData
->BlockEntry
, &BlockData
);
1978 // No default data for OrderedList.
1985 // 1. Set default value for OneOf option when flag field has default attribute.
1987 if (((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT
) == EFI_IFR_OPTION_DEFAULT
) ||
1988 ((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT_MFG
) == EFI_IFR_OPTION_DEFAULT_MFG
)) {
1990 // This flag is used to specify whether this option is the first. Set it to FALSE for the following options.
1991 // The first oneof option value will be used as default value when no default value is specified.
1993 FirstOneOfOption
= FALSE
;
1995 // Prepare new DefaultValue
1997 DefaultData
.Type
= DefaultValueFromFlag
;
1998 CopyMem (&DefaultData
.Value
, &IfrOneOfOption
->Value
, IfrOneOfOption
->Header
.Length
- OFFSET_OF (EFI_IFR_ONE_OF_OPTION
, Value
));
1999 if ((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT
) == EFI_IFR_OPTION_DEFAULT
) {
2000 DefaultData
.DefaultId
= EFI_HII_DEFAULT_CLASS_STANDARD
;
2001 InsertDefaultValue (BlockData
, &DefaultData
);
2003 if ((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT_MFG
) == EFI_IFR_OPTION_DEFAULT_MFG
) {
2004 DefaultData
.DefaultId
= EFI_HII_DEFAULT_CLASS_MANUFACTURING
;
2005 InsertDefaultValue (BlockData
, &DefaultData
);
2010 // 2. Set as the default value when this is the first option.
2011 // The first oneof option value will be used as default value when no default value is specified.
2013 if (FirstOneOfOption
) {
2014 // This flag is used to specify whether this option is the first. Set it to FALSE for the following options.
2015 FirstOneOfOption
= FALSE
;
2018 // Prepare new DefaultValue
2020 DefaultData
.Type
= DefaultValueFromDefault
;
2021 CopyMem (&DefaultData
.Value
, &IfrOneOfOption
->Value
, IfrOneOfOption
->Header
.Length
- OFFSET_OF (EFI_IFR_ONE_OF_OPTION
, Value
));
2022 for (LinkData
= DefaultIdArray
->Entry
.ForwardLink
; LinkData
!= &DefaultIdArray
->Entry
; LinkData
= LinkData
->ForwardLink
) {
2023 DefaultDataPtr
= BASE_CR (LinkData
, IFR_DEFAULT_DATA
, Entry
);
2024 DefaultData
.DefaultId
= DefaultDataPtr
->DefaultId
;
2025 InsertDefaultValue (BlockData
, &DefaultData
);
2030 case EFI_IFR_DEFAULT_OP
:
2032 // Update Current BlockData to the default value.
2034 if (BlockData
== NULL
|| BlockData
->Scope
== 0) {
2036 // No matched block data is ignored.
2041 if (BlockData
->OpCode
== EFI_IFR_ORDERED_LIST_OP
) {
2043 // OrderedList Opcode is no default value.
2048 // Get the DefaultId
2050 IfrDefault
= (EFI_IFR_DEFAULT
*) IfrOpHdr
;
2051 VarDefaultId
= IfrDefault
->DefaultId
;
2053 // Prepare new DefaultValue
2055 DefaultData
.Type
= DefaultValueFromOpcode
;
2056 DefaultData
.DefaultId
= VarDefaultId
;
2057 CopyMem (&DefaultData
.Value
, &IfrDefault
->Value
, IfrDefault
->Header
.Length
- OFFSET_OF (EFI_IFR_DEFAULT
, Value
));
2059 // If the value field is expression, set the cleaned flag.
2060 if (IfrDefault
->Type
== EFI_IFR_TYPE_OTHER
) {
2061 DefaultData
.Cleaned
= TRUE
;
2064 // Add DefaultValue into current BlockData
2066 InsertDefaultValue (BlockData
, &DefaultData
);
2069 // After insert the default value, reset the cleaned value for next
2070 // time used. If not set here, need to set the value before everytime
2073 DefaultData
.Cleaned
= FALSE
;
2076 case EFI_IFR_END_OP
:
2078 // End Opcode is for Var question.
2080 if (BlockData
!= NULL
&& BlockData
->Scope
> 0) {
2086 if (BlockData
!= NULL
&& BlockData
->Scope
> 0) {
2087 BlockData
->Scope
= (UINT8
) (BlockData
->Scope
+ IfrOpHdr
->Scope
);
2092 IfrOffset
+= IfrOpHdr
->Length
;
2096 for (LinkData
= VarStorageData
->BlockEntry
.ForwardLink
; LinkData
!= &VarStorageData
->BlockEntry
; LinkData
= LinkData
->ForwardLink
) {
2097 BlockData
= BASE_CR (LinkData
, IFR_BLOCK_DATA
, Entry
);
2098 for (LinkDefault
= BlockData
->DefaultValueEntry
.ForwardLink
; LinkDefault
!= &BlockData
->DefaultValueEntry
; ) {
2099 DefaultDataPtr
= BASE_CR (LinkDefault
, IFR_DEFAULT_DATA
, Entry
);
2100 LinkDefault
= LinkDefault
->ForwardLink
;
2101 if (DefaultDataPtr
->Cleaned
== TRUE
) {
2102 RemoveEntryList (&DefaultDataPtr
->Entry
);
2103 FreePool (DefaultDataPtr
);
2112 parse the configrequest string, get the elements.
2114 @param ConfigRequest The input configrequest string.
2115 @param Progress Return the progress data.
2117 @retval Block data pointer.
2121 IN EFI_STRING ConfigRequest
,
2122 OUT EFI_STRING
*Progress
2125 EFI_STRING StringPtr
;
2126 IFR_BLOCK_DATA
*BlockData
;
2127 IFR_BLOCK_DATA
*RequestBlockArray
;
2133 IFR_BLOCK_DATA
*NextBlockData
;
2137 // Init RequestBlockArray
2139 RequestBlockArray
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
2140 if (RequestBlockArray
== NULL
) {
2143 InitializeListHead (&RequestBlockArray
->Entry
);
2146 // Get the request Block array from the request string
2151 // Parse each <RequestElement> if exists
2152 // Only <BlockName> format is supported by this help function.
2153 // <BlockName> ::= &'OFFSET='<Number>&'WIDTH='<Number>
2155 StringPtr
= ConfigRequest
;
2156 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) == 0) {
2158 // Skip the OFFSET string
2160 *Progress
= StringPtr
;
2161 StringPtr
+= StrLen (L
"&OFFSET=");
2165 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
2166 if (EFI_ERROR (Status
)) {
2173 (((Length
+ 1) / 2) < sizeof (UINT16
)) ? ((Length
+ 1) / 2) : sizeof (UINT16
)
2175 FreePool (TmpBuffer
);
2177 StringPtr
+= Length
;
2178 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
2181 StringPtr
+= StrLen (L
"&WIDTH=");
2186 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
2187 if (EFI_ERROR (Status
)) {
2194 (((Length
+ 1) / 2) < sizeof (UINT16
)) ? ((Length
+ 1) / 2) : sizeof (UINT16
)
2196 FreePool (TmpBuffer
);
2198 StringPtr
+= Length
;
2199 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
2206 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
2207 if (BlockData
== NULL
) {
2210 BlockData
->Offset
= Offset
;
2211 BlockData
->Width
= Width
;
2212 InsertBlockData (&RequestBlockArray
->Entry
, &BlockData
);
2215 // Skip &VALUE string if &VALUE does exists.
2217 if (StrnCmp (StringPtr
, L
"&VALUE=", StrLen (L
"&VALUE=")) == 0) {
2218 StringPtr
+= StrLen (L
"&VALUE=");
2223 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
2224 if (EFI_ERROR (Status
)) {
2228 StringPtr
+= Length
;
2229 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
2234 // If '\0', parsing is finished.
2236 if (*StringPtr
== 0) {
2242 // Merge the requested block data.
2244 Link
= RequestBlockArray
->Entry
.ForwardLink
;
2245 while ((Link
!= &RequestBlockArray
->Entry
) && (Link
->ForwardLink
!= &RequestBlockArray
->Entry
)) {
2246 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
2247 NextBlockData
= BASE_CR (Link
->ForwardLink
, IFR_BLOCK_DATA
, Entry
);
2248 if ((NextBlockData
->Offset
>= BlockData
->Offset
) && (NextBlockData
->Offset
<= (BlockData
->Offset
+ BlockData
->Width
))) {
2249 if ((NextBlockData
->Offset
+ NextBlockData
->Width
) > (BlockData
->Offset
+ BlockData
->Width
)) {
2250 BlockData
->Width
= (UINT16
) (NextBlockData
->Offset
+ NextBlockData
->Width
- BlockData
->Offset
);
2252 RemoveEntryList (Link
->ForwardLink
);
2253 FreePool (NextBlockData
);
2256 Link
= Link
->ForwardLink
;
2259 return RequestBlockArray
;
2262 if (RequestBlockArray
!= NULL
) {
2264 // Free Link Array RequestBlockArray
2266 while (!IsListEmpty (&RequestBlockArray
->Entry
)) {
2267 BlockData
= BASE_CR (RequestBlockArray
->Entry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
2268 RemoveEntryList (&BlockData
->Entry
);
2269 FreePool (BlockData
);
2272 FreePool (RequestBlockArray
);
2279 parse the configrequest string, get the elements.
2281 @param ConfigRequest The input config request string.
2282 @param Progress Return the progress data.
2284 @retval return data block array.
2288 IN EFI_STRING ConfigRequest
,
2289 OUT EFI_STRING
*Progress
2292 EFI_STRING StringPtr
;
2294 IFR_BLOCK_DATA
*BlockData
;
2295 IFR_BLOCK_DATA
*RequestBlockArray
;
2298 StringPtr
= ConfigRequest
;
2301 // Init RequestBlockArray
2303 RequestBlockArray
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
2304 if (RequestBlockArray
== NULL
) {
2307 InitializeListHead (&RequestBlockArray
->Entry
);
2310 // Get the request Block array from the request string
2314 // Parse each <RequestElement> if exists
2315 // Only <BlockName> format is supported by this help function.
2316 // <BlockName> ::= &'Name***=***
2318 while (StringPtr
!= NULL
&& *StringPtr
== L
'&') {
2320 *Progress
= StringPtr
;
2322 // Skip the L"&" string
2327 if ((NextTag
= StrStr (StringPtr
, L
"=")) != NULL
) {
2330 } else if ((NextTag
= StrStr (StringPtr
, L
"&")) != NULL
) {
2337 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
2338 if (BlockData
== NULL
) {
2345 BlockData
->Name
= AllocateCopyPool(StrSize (StringPtr
), StringPtr
);
2346 InsertBlockData (&RequestBlockArray
->Entry
, &BlockData
);
2350 // If has value, skip the value.
2352 StringPtr
= NextTag
+ 1;
2354 StringPtr
= StrStr (StringPtr
, L
"&");
2355 } else if (NextTag
!= NULL
) {
2357 // restore the '&' text.
2359 StringPtr
= NextTag
;
2364 return RequestBlockArray
;
2367 if (RequestBlockArray
!= NULL
) {
2369 // Free Link Array RequestBlockArray
2371 while (!IsListEmpty (&RequestBlockArray
->Entry
)) {
2372 BlockData
= BASE_CR (RequestBlockArray
->Entry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
2373 RemoveEntryList (&BlockData
->Entry
);
2374 if (BlockData
->Name
!= NULL
) {
2375 FreePool (BlockData
->Name
);
2377 FreePool (BlockData
);
2380 FreePool (RequestBlockArray
);
2387 Generate ConfigRequest string base on the varstore info.
2389 @param ConfigHdr The config header for this varstore.
2390 @param VarStorageData The varstore info.
2391 @param Status Return Status.
2392 @param ConfigRequest The ConfigRequest info may be return.
2394 @retval TRUE Need to continue
2395 @retval Others NO need to continue or error occur.
2398 GenerateConfigRequest (
2399 IN CHAR16
*ConfigHdr
,
2400 IN IFR_VARSTORAGE_DATA
*VarStorageData
,
2401 OUT EFI_STATUS
*Status
,
2402 IN OUT EFI_STRING
*ConfigRequest
2408 CHAR16
*FullConfigRequest
;
2410 IFR_BLOCK_DATA
*BlockData
;
2413 // Append VarStorageData BlockEntry into *Request string
2414 // Now support only one varstore in a form package.
2418 // Go through all VarStorageData Entry and get BlockEntry for each one for the multiple varstore in a single form package
2419 // Then construct them all to return MultiRequest string : ConfigHdr BlockConfig
2423 // Compute the length of the entire request starting with <ConfigHdr> and a
2427 Length
= StrLen (ConfigHdr
) + 1;
2429 for (Link
= VarStorageData
->BlockEntry
.ForwardLink
; Link
!= &VarStorageData
->BlockEntry
; Link
= Link
->ForwardLink
) {
2431 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
2432 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2434 // Add <BlockName> length for each Name
2436 // <BlockName> ::= &Name1&Name2&...
2437 // |1| StrLen(Name1)
2439 Length
= Length
+ (1 + StrLen (BlockData
->Name
));
2442 // Add <BlockName> length for each Offset/Width pair
2444 // <BlockName> ::= &OFFSET=1234&WIDTH=1234
2445 // | 8 | 4 | 7 | 4 |
2447 Length
= Length
+ (8 + 4 + 7 + 4);
2451 // No any request block data is found. The request string can't be constructed.
2454 *Status
= EFI_SUCCESS
;
2459 // Allocate buffer for the entire <ConfigRequest>
2461 FullConfigRequest
= AllocateZeroPool (Length
* sizeof (CHAR16
));
2462 if (FullConfigRequest
== NULL
) {
2463 *Status
= EFI_OUT_OF_RESOURCES
;
2466 StringPtr
= FullConfigRequest
;
2469 // Start with <ConfigHdr>
2471 StrCpy (StringPtr
, ConfigHdr
);
2472 StringPtr
+= StrLen (StringPtr
);
2475 // Loop through all the Offset/Width pairs and append them to ConfigRequest
2477 for (Link
= VarStorageData
->BlockEntry
.ForwardLink
; Link
!= &VarStorageData
->BlockEntry
; Link
= Link
->ForwardLink
) {
2478 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
2479 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2485 (1 + StrLen (BlockData
->Name
) + 1) * sizeof (CHAR16
),
2491 // Append &OFFSET=XXXX&WIDTH=YYYY\0
2495 (8 + 4 + 7 + 4 + 1) * sizeof (CHAR16
),
2496 L
"&OFFSET=%04X&WIDTH=%04X",
2501 StringPtr
+= StrLen (StringPtr
);
2504 // Set to the got full request string.
2506 HiiToLower (FullConfigRequest
);
2508 if (*ConfigRequest
!= NULL
) {
2509 FreePool (*ConfigRequest
);
2511 *ConfigRequest
= FullConfigRequest
;
2517 Generate ConfigRequest Header base on the varstore info.
2519 @param VarStorageData The varstore info.
2520 @param DevicePath Device path for this varstore.
2521 @param ConfigHdr The config header for this varstore.
2523 @retval EFI_SUCCESS Generate the header success.
2524 @retval EFI_OUT_OF_RESOURCES Allocate buffer fail.
2528 IN IFR_VARSTORAGE_DATA
*VarStorageData
,
2529 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
2530 OUT EFI_STRING
*ConfigHdr
2539 Status
= EFI_SUCCESS
;
2545 // Construct <ConfigHdr> : "GUID=...&NAME=...&PATH=..." by VarStorageData Guid, Name and DriverHandle
2547 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*) &VarStorageData
->Guid
, 1, &GuidStr
);
2548 if (VarStorageData
->Name
!= NULL
) {
2549 GenerateSubStr (L
"NAME=", StrLen (VarStorageData
->Name
) * sizeof (CHAR16
), (VOID
*) VarStorageData
->Name
, 2, &NameStr
);
2551 GenerateSubStr (L
"NAME=", 0, NULL
, 2, &NameStr
);
2555 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) DevicePath
),
2556 (VOID
*) DevicePath
,
2560 Length
= StrLen (GuidStr
) + StrLen (NameStr
) + StrLen (PathStr
) + 1;
2561 if (VarStorageData
->Name
== NULL
) {
2565 *ConfigHdr
= AllocateZeroPool (Length
* sizeof (CHAR16
));
2566 if (*ConfigHdr
== NULL
) {
2567 Status
= EFI_OUT_OF_RESOURCES
;
2570 StrCpy (*ConfigHdr
, GuidStr
);
2571 StrCat (*ConfigHdr
, NameStr
);
2572 if (VarStorageData
->Name
== NULL
) {
2573 StrCat (*ConfigHdr
, L
"&");
2575 StrCat (*ConfigHdr
, PathStr
);
2578 // Remove the last character L'&'
2580 *(*ConfigHdr
+ StrLen (*ConfigHdr
) - 1) = L
'\0';
2583 if (GuidStr
!= NULL
) {
2587 if (NameStr
!= NULL
) {
2591 if (PathStr
!= NULL
) {
2599 Get Data buffer size based on data type.
2601 @param ValueType The input data type.
2603 @retval The data buffer size for the input type.
2610 UINT16 StorageWidth
;
2612 switch (ValueType
) {
2613 case EFI_IFR_NUMERIC_SIZE_1
:
2614 case EFI_IFR_TYPE_BOOLEAN
:
2615 StorageWidth
= (UINT16
) sizeof (UINT8
);
2618 case EFI_IFR_NUMERIC_SIZE_2
:
2619 StorageWidth
= (UINT16
) sizeof (UINT16
);
2622 case EFI_IFR_NUMERIC_SIZE_4
:
2623 StorageWidth
= (UINT16
) sizeof (UINT32
);
2626 case EFI_IFR_NUMERIC_SIZE_8
:
2627 StorageWidth
= (UINT16
) sizeof (UINT64
);
2630 case EFI_IFR_TYPE_TIME
:
2631 StorageWidth
= (UINT16
) sizeof (EFI_IFR_TIME
);
2634 case EFI_IFR_TYPE_DATE
:
2635 StorageWidth
= (UINT16
) sizeof (EFI_IFR_DATE
);
2643 return StorageWidth
;
2647 Generate ConfigAltResp string base on the varstore info.
2649 @param ConfigHdr The config header for this varstore.
2650 @param VarStorageData The varstore info.
2651 @param DefaultIdArray The Default id array.
2652 @param DefaultAltCfgResp The DefaultAltCfgResp info may be return.
2654 @retval TRUE Need to continue
2655 @retval Others NO need to continue or error occur.
2658 GenerateAltConfigResp (
2659 IN CHAR16
*ConfigHdr
,
2660 IN IFR_VARSTORAGE_DATA
*VarStorageData
,
2661 IN IFR_DEFAULT_DATA
*DefaultIdArray
,
2662 IN OUT EFI_STRING
*DefaultAltCfgResp
2668 LIST_ENTRY
*LinkData
;
2669 LIST_ENTRY
*LinkDefault
;
2670 LIST_ENTRY
*ListEntry
;
2672 IFR_BLOCK_DATA
*BlockData
;
2673 IFR_DEFAULT_DATA
*DefaultId
;
2674 IFR_DEFAULT_DATA
*DefaultValueData
;
2682 // Add length for <ConfigHdr> + '\0'
2684 Length
= StrLen (ConfigHdr
) + 1;
2686 for (Link
= DefaultIdArray
->Entry
.ForwardLink
; Link
!= &DefaultIdArray
->Entry
; Link
= Link
->ForwardLink
) {
2687 DefaultId
= BASE_CR (Link
, IFR_DEFAULT_DATA
, Entry
);
2689 // Add length for "&<ConfigHdr>&ALTCFG=XXXX"
2690 // |1| StrLen (ConfigHdr) | 8 | 4 |
2692 Length
+= (1 + StrLen (ConfigHdr
) + 8 + 4);
2694 for (LinkData
= VarStorageData
->BlockEntry
.ForwardLink
; LinkData
!= &VarStorageData
->BlockEntry
; LinkData
= LinkData
->ForwardLink
) {
2695 BlockData
= BASE_CR (LinkData
, IFR_BLOCK_DATA
, Entry
);
2696 ListEntry
= &BlockData
->DefaultValueEntry
;
2697 for (LinkDefault
= ListEntry
->ForwardLink
; LinkDefault
!= ListEntry
; LinkDefault
= LinkDefault
->ForwardLink
) {
2698 DefaultValueData
= BASE_CR (LinkDefault
, IFR_DEFAULT_DATA
, Entry
);
2699 if (DefaultValueData
->DefaultId
!= DefaultId
->DefaultId
) {
2702 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2704 // Add length for "&Name1=zzzzzzzzzzzz"
2707 Length
+= (1 + StrLen (BlockData
->Name
) + 1 + BlockData
->Width
* 2);
2710 // Add length for "&OFFSET=XXXX&WIDTH=YYYY&VALUE=zzzzzzzzzzzz"
2711 // | 8 | 4 | 7 | 4 | 7 | Width * 2 |
2713 Length
+= (8 + 4 + 7 + 4 + 7 + BlockData
->Width
* 2);
2721 // No default value is found. The default string doesn't exist.
2728 // Allocate buffer for the entire <DefaultAltCfgResp>
2730 *DefaultAltCfgResp
= AllocateZeroPool (Length
* sizeof (CHAR16
));
2731 if (*DefaultAltCfgResp
== NULL
) {
2732 return EFI_OUT_OF_RESOURCES
;
2734 StringPtr
= *DefaultAltCfgResp
;
2737 // Start with <ConfigHdr>
2739 StrCpy (StringPtr
, ConfigHdr
);
2740 StringPtr
+= StrLen (StringPtr
);
2742 for (Link
= DefaultIdArray
->Entry
.ForwardLink
; Link
!= &DefaultIdArray
->Entry
; Link
= Link
->ForwardLink
) {
2743 DefaultId
= BASE_CR (Link
, IFR_DEFAULT_DATA
, Entry
);
2745 // Add <AltConfigHdr> of the form "&<ConfigHdr>&ALTCFG=XXXX\0"
2746 // |1| StrLen (ConfigHdr) | 8 | 4 |
2750 (1 + StrLen (ConfigHdr
) + 8 + 4 + 1) * sizeof (CHAR16
),
2753 DefaultId
->DefaultId
2755 StringPtr
+= StrLen (StringPtr
);
2757 for (LinkData
= VarStorageData
->BlockEntry
.ForwardLink
; LinkData
!= &VarStorageData
->BlockEntry
; LinkData
= LinkData
->ForwardLink
) {
2758 BlockData
= BASE_CR (LinkData
, IFR_BLOCK_DATA
, Entry
);
2759 ListEntry
= &BlockData
->DefaultValueEntry
;
2760 for (LinkDefault
= ListEntry
->ForwardLink
; LinkDefault
!= ListEntry
; LinkDefault
= LinkDefault
->ForwardLink
) {
2761 DefaultValueData
= BASE_CR (LinkDefault
, IFR_DEFAULT_DATA
, Entry
);
2762 if (DefaultValueData
->DefaultId
!= DefaultId
->DefaultId
) {
2765 if (VarStorageData
->Type
== EFI_HII_VARSTORE_NAME_VALUE
) {
2768 (1 + StrLen (ConfigHdr
) + 1) * sizeof (CHAR16
),
2772 StringPtr
+= StrLen (StringPtr
);
2775 // Add <BlockConfig>
2776 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>
2780 (8 + 4 + 7 + 4 + 7 + 1) * sizeof (CHAR16
),
2781 L
"&OFFSET=%04X&WIDTH=%04X&VALUE=",
2785 StringPtr
+= StrLen (StringPtr
);
2787 Width
= BlockData
->Width
;
2789 // Convert Value to a hex string in "%x" format
2790 // NOTE: This is in the opposite byte that GUID and PATH use
2792 TmpBuffer
= (UINT8
*) &(DefaultValueData
->Value
);
2793 for (; Width
> 0; Width
--) {
2794 StringPtr
+= UnicodeValueToString (StringPtr
, PREFIX_ZERO
| RADIX_HEX
, TmpBuffer
[Width
- 1], 2);
2800 HiiToLower (*DefaultAltCfgResp
);
2806 This function gets the full request string and full default value string by
2807 parsing IFR data in HII form packages.
2809 When Request points to NULL string, the request string and default value string
2810 for each varstore in form package will return.
2812 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
2813 @param DevicePath Device Path which Hii Config Access Protocol is registered.
2814 @param Request Pointer to a null-terminated Unicode string in
2815 <ConfigRequest> format. When it doesn't contain
2816 any RequestElement, it will be updated to return
2817 the full RequestElement retrieved from IFR data.
2818 If it points to NULL, the request string for the first
2819 varstore in form package will be merged into a
2820 <MultiConfigRequest> format string and return.
2821 @param AltCfgResp Pointer to a null-terminated Unicode string in
2822 <ConfigAltResp> format. When the pointer is to NULL,
2823 the full default value string retrieved from IFR data
2824 will return. When the pinter is to a string, the
2825 full default value string retrieved from IFR data
2826 will be merged into the input string and return.
2827 When Request points to NULL, the default value string
2828 for each varstore in form package will be merged into
2829 a <MultiConfigAltResp> format string and return.
2830 @param PointerProgress Optional parameter, it can be be NULL.
2831 When it is not NULL, if Request is NULL, it returns NULL.
2832 On return, points to a character in the Request
2833 string. Points to the string's null terminator if
2834 request was successful. Points to the most recent
2835 & before the first failing name / value pair (or
2836 the beginning of the string if the failure is in
2837 the first name / value pair) if the request was
2839 @retval EFI_SUCCESS The Results string is set to the full request string.
2840 And AltCfgResp contains all default value string.
2841 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
2842 @retval EFI_NOT_FOUND The varstore (Guid and Name) in Request string
2843 can't be found in Form package.
2844 @retval EFI_NOT_FOUND HiiPackage can't be got on the input HiiHandle.
2845 @retval EFI_INVALID_PARAMETER Request points to NULL.
2850 GetFullStringFromHiiFormPackages (
2851 IN HII_DATABASE_RECORD
*DataBaseRecord
,
2852 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
2853 IN OUT EFI_STRING
*Request
,
2854 IN OUT EFI_STRING
*AltCfgResp
,
2855 OUT EFI_STRING
*PointerProgress OPTIONAL
2859 UINT8
*HiiFormPackage
;
2861 IFR_BLOCK_DATA
*RequestBlockArray
;
2862 IFR_BLOCK_DATA
*BlockData
;
2863 IFR_DEFAULT_DATA
*DefaultValueData
;
2864 IFR_DEFAULT_DATA
*DefaultId
;
2865 IFR_DEFAULT_DATA
*DefaultIdArray
;
2866 IFR_VARSTORAGE_DATA
*VarStorageData
;
2867 EFI_STRING DefaultAltCfgResp
;
2868 EFI_STRING ConfigHdr
;
2869 EFI_STRING StringPtr
;
2870 EFI_STRING Progress
;
2872 if (DataBaseRecord
== NULL
|| DevicePath
== NULL
|| Request
== NULL
|| AltCfgResp
== NULL
) {
2873 return EFI_INVALID_PARAMETER
;
2877 // Initialize the local variables.
2879 RequestBlockArray
= NULL
;
2880 DefaultIdArray
= NULL
;
2881 VarStorageData
= NULL
;
2882 DefaultAltCfgResp
= NULL
;
2884 HiiFormPackage
= NULL
;
2886 Progress
= *Request
;
2888 Status
= GetFormPackageData (DataBaseRecord
, &HiiFormPackage
, &PackageSize
);
2889 if (EFI_ERROR (Status
)) {
2894 // 1. Get the request block array by Request String when Request string containts the block array.
2897 if (*Request
!= NULL
) {
2898 StringPtr
= *Request
;
2902 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
2903 Status
= EFI_INVALID_PARAMETER
;
2906 StringPtr
+= StrLen (L
"GUID=");
2907 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&NAME=", StrLen (L
"&NAME=")) != 0) {
2910 if (*StringPtr
== L
'\0') {
2911 Status
= EFI_INVALID_PARAMETER
;
2914 StringPtr
+= StrLen (L
"&NAME=");
2915 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&PATH=", StrLen (L
"&PATH=")) != 0) {
2918 if (*StringPtr
== L
'\0') {
2919 Status
= EFI_INVALID_PARAMETER
;
2922 StringPtr
+= StrLen (L
"&PATH=");
2923 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
2927 if (*StringPtr
== L
'\0') {
2929 // No request block is found.
2936 // If StringPtr != NULL, get the request elements.
2938 if (StringPtr
!= NULL
) {
2939 if (StrStr (StringPtr
, L
"&OFFSET=") != NULL
) {
2940 RequestBlockArray
= GetBlockElement(StringPtr
, &Progress
);
2942 RequestBlockArray
= GetNameElement(StringPtr
, &Progress
);
2945 if (RequestBlockArray
== NULL
) {
2946 Status
= EFI_INVALID_PARAMETER
;
2952 // Initialize DefaultIdArray to store the map between DeaultId and DefaultName
2954 DefaultIdArray
= (IFR_DEFAULT_DATA
*) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
2955 if (DefaultIdArray
== NULL
) {
2956 Status
= EFI_OUT_OF_RESOURCES
;
2959 InitializeListHead (&DefaultIdArray
->Entry
);
2962 // Initialize VarStorageData to store the var store Block and Default value information.
2964 VarStorageData
= (IFR_VARSTORAGE_DATA
*) AllocateZeroPool (sizeof (IFR_VARSTORAGE_DATA
));
2965 if (VarStorageData
== NULL
) {
2966 Status
= EFI_OUT_OF_RESOURCES
;
2969 InitializeListHead (&VarStorageData
->Entry
);
2970 InitializeListHead (&VarStorageData
->BlockEntry
);
2973 // 2. Parse FormPackage to get BlockArray and DefaultId Array for the request BlockArray.
2977 // Parse the opcode in form pacakge to get the default setting.
2979 Status
= ParseIfrData (DataBaseRecord
->Handle
,
2981 (UINT32
) PackageSize
,
2986 if (EFI_ERROR (Status
)) {
2991 // No requested varstore in IFR data and directly return
2993 if (VarStorageData
->VarStoreId
== 0) {
2994 Status
= EFI_SUCCESS
;
2999 // 3. Construct Request Element (Block Name) for 2.1 and 2.2 case.
3001 Status
= GenerateHdr (VarStorageData
, DevicePath
, &ConfigHdr
);
3002 if (EFI_ERROR (Status
)) {
3006 if (RequestBlockArray
== NULL
) {
3007 if (!GenerateConfigRequest(ConfigHdr
, VarStorageData
, &Status
, Request
)) {
3013 // 4. Construct Default Value string in AltResp according to request element.
3014 // Go through all VarStorageData Entry and get the DefaultId array for each one
3015 // Then construct them all to : ConfigHdr AltConfigHdr ConfigBody AltConfigHdr ConfigBody
3017 Status
= GenerateAltConfigResp (ConfigHdr
, VarStorageData
, DefaultIdArray
, &DefaultAltCfgResp
);
3018 if (EFI_ERROR (Status
)) {
3023 // 5. Merge string into the input AltCfgResp if the iput *AltCfgResp is not NULL.
3025 if (*AltCfgResp
!= NULL
&& DefaultAltCfgResp
!= NULL
) {
3026 Status
= MergeDefaultString (AltCfgResp
, DefaultAltCfgResp
);
3027 FreePool (DefaultAltCfgResp
);
3028 } else if (*AltCfgResp
== NULL
) {
3029 *AltCfgResp
= DefaultAltCfgResp
;
3033 if (RequestBlockArray
!= NULL
) {
3035 // Free Link Array RequestBlockArray
3037 while (!IsListEmpty (&RequestBlockArray
->Entry
)) {
3038 BlockData
= BASE_CR (RequestBlockArray
->Entry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
3039 RemoveEntryList (&BlockData
->Entry
);
3040 if (BlockData
->Name
!= NULL
) {
3041 FreePool (BlockData
->Name
);
3043 FreePool (BlockData
);
3046 FreePool (RequestBlockArray
);
3049 if (VarStorageData
!= NULL
) {
3051 // Free link array VarStorageData
3053 while (!IsListEmpty (&VarStorageData
->BlockEntry
)) {
3054 BlockData
= BASE_CR (VarStorageData
->BlockEntry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
3055 RemoveEntryList (&BlockData
->Entry
);
3056 if (BlockData
->Name
!= NULL
) {
3057 FreePool (BlockData
->Name
);
3060 // Free default value link array
3062 while (!IsListEmpty (&BlockData
->DefaultValueEntry
)) {
3063 DefaultValueData
= BASE_CR (BlockData
->DefaultValueEntry
.ForwardLink
, IFR_DEFAULT_DATA
, Entry
);
3064 RemoveEntryList (&DefaultValueData
->Entry
);
3065 FreePool (DefaultValueData
);
3067 FreePool (BlockData
);
3069 FreePool (VarStorageData
);
3072 if (DefaultIdArray
!= NULL
) {
3074 // Free DefaultId Array
3076 while (!IsListEmpty (&DefaultIdArray
->Entry
)) {
3077 DefaultId
= BASE_CR (DefaultIdArray
->Entry
.ForwardLink
, IFR_DEFAULT_DATA
, Entry
);
3078 RemoveEntryList (&DefaultId
->Entry
);
3079 FreePool (DefaultId
);
3081 FreePool (DefaultIdArray
);
3085 // Free the allocated string
3087 if (ConfigHdr
!= NULL
) {
3088 FreePool (ConfigHdr
);
3092 // Free Pacakge data
3094 if (HiiFormPackage
!= NULL
) {
3095 FreePool (HiiFormPackage
);
3098 if (PointerProgress
!= NULL
) {
3099 if (*Request
== NULL
) {
3100 *PointerProgress
= NULL
;
3101 } else if (EFI_ERROR (Status
)) {
3102 *PointerProgress
= *Request
;
3104 *PointerProgress
= *Request
+ StrLen (*Request
);
3112 This function gets the full request resp string by
3113 parsing IFR data in HII form packages.
3115 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
3117 @param EfiVarStoreInfo The efi varstore info which is save in the EFI
3118 varstore data structure.
3119 @param Request Pointer to a null-terminated Unicode string in
3120 <ConfigRequest> format.
3121 @param RequestResp Pointer to a null-terminated Unicode string in
3122 <ConfigResp> format.
3123 @param AccessProgress On return, points to a character in the Request
3124 string. Points to the string's null terminator if
3125 request was successful. Points to the most recent
3126 & before the first failing name / value pair (or
3127 the beginning of the string if the failure is in
3128 the first name / value pair) if the request was
3131 @retval EFI_SUCCESS The Results string is set to the full request string.
3132 And AltCfgResp contains all default value string.
3133 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
3134 @retval EFI_INVALID_PARAMETER Request points to NULL.
3138 GetConfigRespFromEfiVarStore (
3139 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
3140 IN EFI_IFR_VARSTORE_EFI
*EfiVarStoreInfo
,
3141 IN EFI_STRING Request
,
3142 OUT EFI_STRING
*RequestResp
,
3143 OUT EFI_STRING
*AccessProgress
3147 EFI_STRING VarStoreName
;
3151 Status
= EFI_SUCCESS
;
3154 VarStoreName
= NULL
;
3156 VarStoreName
= AllocateZeroPool (AsciiStrSize ((CHAR8
*)EfiVarStoreInfo
->Name
) * sizeof (CHAR16
));
3157 if (VarStoreName
== NULL
) {
3158 Status
= EFI_OUT_OF_RESOURCES
;
3161 AsciiStrToUnicodeStr ((CHAR8
*) EfiVarStoreInfo
->Name
, VarStoreName
);
3164 Status
= gRT
->GetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, NULL
, &BufferSize
, NULL
);
3165 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
3169 VarStore
= AllocateZeroPool (BufferSize
);
3170 ASSERT (VarStore
!= NULL
);
3171 Status
= gRT
->GetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, NULL
, &BufferSize
, VarStore
);
3172 if (EFI_ERROR (Status
)) {
3176 Status
= HiiBlockToConfig(This
, Request
, VarStore
, BufferSize
, RequestResp
, AccessProgress
);
3177 if (EFI_ERROR (Status
)) {
3182 if (VarStoreName
!= NULL
) {
3183 FreePool (VarStoreName
);
3186 if (VarStore
!= NULL
) {
3187 FreePool (VarStore
);
3195 This function route the full request resp string for efi varstore.
3197 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
3199 @param EfiVarStoreInfo The efi varstore info which is save in the EFI
3200 varstore data structure.
3201 @param RequestResp Pointer to a null-terminated Unicode string in
3202 <ConfigResp> format.
3203 @param Result Pointer to a null-terminated Unicode string in
3204 <ConfigResp> format.
3206 @retval EFI_SUCCESS The Results string is set to the full request string.
3207 And AltCfgResp contains all default value string.
3208 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
3209 @retval EFI_INVALID_PARAMETER Request points to NULL.
3213 RouteConfigRespForEfiVarStore (
3214 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
3215 IN EFI_IFR_VARSTORE_EFI
*EfiVarStoreInfo
,
3216 IN EFI_STRING RequestResp
,
3217 OUT EFI_STRING
*Result
3221 EFI_STRING VarStoreName
;
3226 Status
= EFI_SUCCESS
;
3229 VarStoreName
= NULL
;
3231 VarStoreName
= AllocateZeroPool (AsciiStrSize ((CHAR8
*)EfiVarStoreInfo
->Name
) * sizeof (CHAR16
));
3232 if (VarStoreName
== NULL
) {
3233 Status
= EFI_OUT_OF_RESOURCES
;
3236 AsciiStrToUnicodeStr ((CHAR8
*) EfiVarStoreInfo
->Name
, VarStoreName
);
3238 Status
= gRT
->GetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, NULL
, &BufferSize
, NULL
);
3239 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
3243 BlockSize
= BufferSize
;
3244 VarStore
= AllocateZeroPool (BufferSize
);
3245 ASSERT (VarStore
!= NULL
);
3246 Status
= gRT
->GetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, NULL
, &BufferSize
, VarStore
);
3247 if (EFI_ERROR (Status
)) {
3251 Status
= HiiConfigToBlock(This
, RequestResp
, VarStore
, &BlockSize
, Result
);
3252 if (EFI_ERROR (Status
)) {
3256 Status
= gRT
->SetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, EfiVarStoreInfo
->Attributes
, BufferSize
, VarStore
);
3257 if (EFI_ERROR (Status
)) {
3262 if (VarStoreName
!= NULL
) {
3263 FreePool (VarStoreName
);
3266 if (VarStore
!= NULL
) {
3267 FreePool (VarStore
);
3274 Validate the config request elements.
3276 @param ConfigElements A null-terminated Unicode string in <ConfigRequest> format,
3277 without configHdr field.
3279 @retval CHAR16 * THE first Name/value pair not correct.
3280 @retval NULL Success parse the name/value pair
3283 OffsetWidthValidate (
3284 CHAR16
*ConfigElements
3290 StringPtr
= ConfigElements
;
3294 if (StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) != 0) {
3298 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
3301 if (*StringPtr
== L
'\0') {
3305 StringPtr
+= StrLen (L
"&WIDTH=");
3306 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) != 0) {
3310 if (*StringPtr
== L
'\0') {
3317 Validate the config request elements.
3319 @param ConfigElements A null-terminated Unicode string in <ConfigRequest> format,
3320 without configHdr field.
3322 @retval CHAR16 * THE first Name/value pair not correct.
3323 @retval NULL Success parse the name/value pair
3328 CHAR16
*ConfigElements
3334 StringPtr
= ConfigElements
;
3338 if (*StringPtr
!= L
'&') {
3343 StringPtr
= StrStr (StringPtr
, L
"&");
3345 if (StringPtr
== NULL
) {
3352 Validate the config request string.
3354 @param ConfigRequest A null-terminated Unicode string in <ConfigRequest> format.
3356 @retval CHAR16 * THE first element not correct.
3357 @retval NULL Success parse the name/value pair
3361 ConfigRequestValidate (
3362 CHAR16
*ConfigRequest
3365 BOOLEAN HasNameField
;
3368 HasNameField
= TRUE
;
3369 StringPtr
= ConfigRequest
;
3372 // Check <ConfigHdr>
3374 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
3375 return ConfigRequest
;
3377 StringPtr
+= StrLen (L
"GUID=");
3378 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&NAME=", StrLen (L
"&NAME=")) != 0) {
3381 if (*StringPtr
== L
'\0') {
3382 return ConfigRequest
;
3384 StringPtr
+= StrLen (L
"&NAME=");
3385 if (*StringPtr
== L
'&') {
3386 HasNameField
= FALSE
;
3388 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&PATH=", StrLen (L
"&PATH=")) != 0) {
3391 if (*StringPtr
== L
'\0') {
3392 return ConfigRequest
;
3394 StringPtr
+= StrLen (L
"&PATH=");
3395 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
3399 if (*StringPtr
== L
'\0') {
3405 // Should be Buffer varstore, config request should be "OFFSET/Width" pairs.
3407 return OffsetWidthValidate(StringPtr
);
3410 // Should be Name/Value varstore, config request should be "&name1&name2..." pairs.
3412 return NameValueValidate(StringPtr
);
3417 This function allows a caller to extract the current configuration
3418 for one or more named elements from one or more drivers.
3420 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
3422 @param Request A null-terminated Unicode string in
3423 <MultiConfigRequest> format.
3424 @param Progress On return, points to a character in the Request
3425 string. Points to the string's null terminator if
3426 request was successful. Points to the most recent
3427 & before the first failing name / value pair (or
3428 the beginning of the string if the failure is in
3429 the first name / value pair) if the request was
3431 @param Results Null-terminated Unicode string in
3432 <MultiConfigAltResp> format which has all values
3433 filled in for the names in the Request string.
3434 String to be allocated by the called function.
3436 @retval EFI_SUCCESS The Results string is filled with the values
3437 corresponding to all requested names.
3438 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
3439 results that must be stored awaiting possible
3441 @retval EFI_NOT_FOUND Routing data doesn't match any known driver.
3442 Progress set to the "G" in "GUID" of the routing
3443 header that doesn't match. Note: There is no
3444 requirement that all routing data be validated
3445 before any configuration extraction.
3446 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Request
3447 parameter would result in this type of error. The
3448 Progress parameter is set to NULL.
3449 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set to most recent &
3450 before the error or the beginning of the string.
3451 @retval EFI_INVALID_PARAMETER Unknown name. Progress points to the & before the
3457 HiiConfigRoutingExtractConfig (
3458 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
3459 IN CONST EFI_STRING Request
,
3460 OUT EFI_STRING
*Progress
,
3461 OUT EFI_STRING
*Results
3464 HII_DATABASE_PRIVATE_DATA
*Private
;
3465 EFI_STRING StringPtr
;
3466 EFI_STRING ConfigRequest
;
3468 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
3469 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
3472 HII_DATABASE_RECORD
*Database
;
3473 UINT8
*DevicePathPkg
;
3474 UINT8
*CurrentDevicePath
;
3475 EFI_HANDLE DriverHandle
;
3476 EFI_HII_HANDLE HiiHandle
;
3477 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
3478 EFI_STRING AccessProgress
;
3479 EFI_STRING AccessResults
;
3480 EFI_STRING DefaultResults
;
3481 BOOLEAN FirstElement
;
3482 BOOLEAN IfrDataParsedFlag
;
3483 BOOLEAN IsEfiVarStore
;
3484 EFI_IFR_VARSTORE_EFI
*EfiVarStoreInfo
;
3485 EFI_STRING ErrorPtr
;
3487 if (This
== NULL
|| Progress
== NULL
|| Results
== NULL
) {
3488 return EFI_INVALID_PARAMETER
;
3491 if (Request
== NULL
) {
3493 return EFI_INVALID_PARAMETER
;
3496 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
3497 StringPtr
= Request
;
3498 *Progress
= StringPtr
;
3499 DefaultResults
= NULL
;
3500 ConfigRequest
= NULL
;
3501 Status
= EFI_SUCCESS
;
3502 AccessResults
= NULL
;
3503 AccessProgress
= NULL
;
3505 IfrDataParsedFlag
= FALSE
;
3506 IsEfiVarStore
= FALSE
;
3507 EfiVarStoreInfo
= NULL
;
3510 // The first element of <MultiConfigRequest> should be
3511 // <GuidHdr>, which is in 'GUID='<Guid> syntax.
3513 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
3514 return EFI_INVALID_PARAMETER
;
3517 FirstElement
= TRUE
;
3520 // Allocate a fix length of memory to store Results. Reallocate memory for
3521 // Results if this fix length is insufficient.
3523 *Results
= (EFI_STRING
) AllocateZeroPool (MAX_STRING_LENGTH
);
3524 if (*Results
== NULL
) {
3525 return EFI_OUT_OF_RESOURCES
;
3528 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) == 0) {
3530 // If parsing error, set Progress to the beginning of the <MultiConfigRequest>
3531 // or most recent & before the error.
3533 if (StringPtr
== Request
) {
3534 *Progress
= StringPtr
;
3536 *Progress
= StringPtr
- 1;
3540 // Process each <ConfigRequest> of <MultiConfigRequest>
3542 Length
= CalculateConfigStringLen (StringPtr
);
3543 ConfigRequest
= AllocateCopyPool ((Length
+ 1) * sizeof (CHAR16
), StringPtr
);
3544 if (ConfigRequest
== NULL
) {
3545 Status
= EFI_OUT_OF_RESOURCES
;
3548 *(ConfigRequest
+ Length
) = 0;
3551 // Get the UEFI device path
3553 Status
= GetDevicePath (ConfigRequest
, (UINT8
**) &DevicePath
);
3554 if (EFI_ERROR (Status
)) {
3559 // Find driver which matches the routing data.
3561 DriverHandle
= NULL
;
3564 for (Link
= Private
->DatabaseList
.ForwardLink
;
3565 Link
!= &Private
->DatabaseList
;
3566 Link
= Link
->ForwardLink
3568 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
3569 if ((DevicePathPkg
= Database
->PackageList
->DevicePathPkg
) != NULL
) {
3570 CurrentDevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
3574 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) CurrentDevicePath
)
3576 DriverHandle
= Database
->DriverHandle
;
3577 HiiHandle
= Database
->Handle
;
3584 // Try to find driver handle by device path.
3586 if (DriverHandle
== NULL
) {
3587 TempDevicePath
= DevicePath
;
3588 Status
= gBS
->LocateDevicePath (
3589 &gEfiDevicePathProtocolGuid
,
3593 if (EFI_ERROR (Status
) || (DriverHandle
== NULL
)) {
3595 // Routing data does not match any known driver.
3596 // Set Progress to the 'G' in "GUID" of the routing header.
3598 *Progress
= StringPtr
;
3599 Status
= EFI_NOT_FOUND
;
3605 // Validate ConfigRequest String.
3607 ErrorPtr
= ConfigRequestValidate(ConfigRequest
);
3608 if (ErrorPtr
!= NULL
) {
3609 *Progress
= StrStr (StringPtr
, ErrorPtr
);
3610 Status
= EFI_INVALID_PARAMETER
;
3615 // Check whether ConfigRequest contains request string.
3617 IfrDataParsedFlag
= FALSE
;
3618 if ((HiiHandle
!= NULL
) && !GetElementsFromRequest(ConfigRequest
)) {
3620 // Get the full request string from IFR when HiiPackage is registered to HiiHandle
3622 IfrDataParsedFlag
= TRUE
;
3623 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &ConfigRequest
, &DefaultResults
, &AccessProgress
);
3624 if (EFI_ERROR (Status
)) {
3626 // AccessProgress indicates the parsing progress on <ConfigRequest>.
3627 // Map it to the progress on <MultiConfigRequest> then return it.
3629 ASSERT (AccessProgress
!= NULL
);
3630 *Progress
= StrStr (StringPtr
, AccessProgress
);
3634 // Not any request block is found.
3636 if (!GetElementsFromRequest(ConfigRequest
)) {
3637 AccessResults
= AllocateCopyPool (StrSize (ConfigRequest
), ConfigRequest
);
3638 goto NextConfigString
;
3643 // Check whether this ConfigRequest is search from Efi varstore type storage.
3645 Status
= GetVarStoreType(Database
, ConfigRequest
, &IsEfiVarStore
, &EfiVarStoreInfo
);
3646 if (EFI_ERROR (Status
)) {
3650 if (IsEfiVarStore
) {
3652 // Call the GetVariable function to extract settings.
3654 Status
= GetConfigRespFromEfiVarStore(This
, EfiVarStoreInfo
, ConfigRequest
, &AccessResults
, &AccessProgress
);
3655 FreePool (EfiVarStoreInfo
);
3658 // Call corresponding ConfigAccess protocol to extract settings
3660 Status
= gBS
->HandleProtocol (
3662 &gEfiHiiConfigAccessProtocolGuid
,
3663 (VOID
**) &ConfigAccess
3665 ASSERT_EFI_ERROR (Status
);
3667 Status
= ConfigAccess
->ExtractConfig (
3674 if (EFI_ERROR (Status
)) {
3676 // AccessProgress indicates the parsing progress on <ConfigRequest>.
3677 // Map it to the progress on <MultiConfigRequest> then return it.
3679 *Progress
= StrStr (StringPtr
, AccessProgress
);
3684 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'
3685 // which seperates the first <ConfigAltResp> and the following ones.
3687 ASSERT (*AccessProgress
== 0);
3690 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
3692 if (!IfrDataParsedFlag
&& HiiHandle
!= NULL
) {
3693 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &ConfigRequest
, &DefaultResults
, NULL
);
3694 ASSERT_EFI_ERROR (Status
);
3697 FreePool (DevicePath
);
3700 if (DefaultResults
!= NULL
) {
3701 Status
= MergeDefaultString (&AccessResults
, DefaultResults
);
3702 ASSERT_EFI_ERROR (Status
);
3703 FreePool (DefaultResults
);
3704 DefaultResults
= NULL
;
3708 if (!FirstElement
) {
3709 Status
= AppendToMultiString (Results
, L
"&");
3710 ASSERT_EFI_ERROR (Status
);
3713 Status
= AppendToMultiString (Results
, AccessResults
);
3714 ASSERT_EFI_ERROR (Status
);
3716 FirstElement
= FALSE
;
3718 FreePool (AccessResults
);
3719 AccessResults
= NULL
;
3720 FreePool (ConfigRequest
);
3721 ConfigRequest
= NULL
;
3724 // Go to next <ConfigRequest> (skip '&').
3726 StringPtr
+= Length
;
3727 if (*StringPtr
== 0) {
3728 *Progress
= StringPtr
;
3736 if (EFI_ERROR (Status
)) {
3737 FreePool (*Results
);
3741 if (ConfigRequest
!= NULL
) {
3742 FreePool (ConfigRequest
);
3745 if (AccessResults
!= NULL
) {
3746 FreePool (AccessResults
);
3749 if (DefaultResults
!= NULL
) {
3750 FreePool (DefaultResults
);
3753 if (DevicePath
!= NULL
) {
3754 FreePool (DevicePath
);
3762 This function allows the caller to request the current configuration for the
3763 entirety of the current HII database and returns the data in a
3764 null-terminated Unicode string.
3766 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
3768 @param Results Null-terminated Unicode string in
3769 <MultiConfigAltResp> format which has all values
3770 filled in for the names in the Request string.
3771 String to be allocated by the called function.
3772 De-allocation is up to the caller.
3774 @retval EFI_SUCCESS The Results string is filled with the values
3775 corresponding to all requested names.
3776 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
3777 results that must be stored awaiting possible
3779 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Results
3780 parameter would result in this type of error.
3785 HiiConfigRoutingExportConfig (
3786 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
3787 OUT EFI_STRING
*Results
3791 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
3792 EFI_STRING AccessResults
;
3793 EFI_STRING Progress
;
3794 EFI_STRING StringPtr
;
3795 EFI_STRING ConfigRequest
;
3797 EFI_HANDLE
*ConfigAccessHandles
;
3798 UINTN NumberConfigAccessHandles
;
3799 BOOLEAN FirstElement
;
3800 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
3801 EFI_HII_HANDLE HiiHandle
;
3802 EFI_STRING DefaultResults
;
3803 HII_DATABASE_PRIVATE_DATA
*Private
;
3805 HII_DATABASE_RECORD
*Database
;
3806 UINT8
*DevicePathPkg
;
3807 UINT8
*CurrentDevicePath
;
3808 BOOLEAN IfrDataParsedFlag
;
3810 if (This
== NULL
|| Results
== NULL
) {
3811 return EFI_INVALID_PARAMETER
;
3814 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
3817 // Allocate a fix length of memory to store Results. Reallocate memory for
3818 // Results if this fix length is insufficient.
3820 *Results
= (EFI_STRING
) AllocateZeroPool (MAX_STRING_LENGTH
);
3821 if (*Results
== NULL
) {
3822 return EFI_OUT_OF_RESOURCES
;
3825 NumberConfigAccessHandles
= 0;
3826 Status
= gBS
->LocateHandleBuffer (
3828 &gEfiHiiConfigAccessProtocolGuid
,
3830 &NumberConfigAccessHandles
,
3831 &ConfigAccessHandles
3833 if (EFI_ERROR (Status
)) {
3837 FirstElement
= TRUE
;
3839 for (Index
= 0; Index
< NumberConfigAccessHandles
; Index
++) {
3840 Status
= gBS
->HandleProtocol (
3841 ConfigAccessHandles
[Index
],
3842 &gEfiHiiConfigAccessProtocolGuid
,
3843 (VOID
**) &ConfigAccess
3845 if (EFI_ERROR (Status
)) {
3850 // Get DevicePath and HiiHandle for this ConfigAccess driver handle
3852 IfrDataParsedFlag
= FALSE
;
3855 DefaultResults
= NULL
;
3857 ConfigRequest
= NULL
;
3858 DevicePath
= DevicePathFromHandle (ConfigAccessHandles
[Index
]);
3859 if (DevicePath
!= NULL
) {
3860 for (Link
= Private
->DatabaseList
.ForwardLink
;
3861 Link
!= &Private
->DatabaseList
;
3862 Link
= Link
->ForwardLink
3864 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
3865 if ((DevicePathPkg
= Database
->PackageList
->DevicePathPkg
) != NULL
) {
3866 CurrentDevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
3870 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) CurrentDevicePath
)
3872 HiiHandle
= Database
->Handle
;
3879 Status
= ConfigAccess
->ExtractConfig (
3885 if (EFI_ERROR (Status
)) {
3887 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
3889 if (HiiHandle
!= NULL
&& DevicePath
!= NULL
) {
3890 IfrDataParsedFlag
= TRUE
;
3891 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &ConfigRequest
, &DefaultResults
, NULL
);
3893 // Get the full request string to get the Current setting again.
3895 if (!EFI_ERROR (Status
) && ConfigRequest
!= NULL
) {
3896 Status
= ConfigAccess
->ExtractConfig (
3902 FreePool (ConfigRequest
);
3904 Status
= EFI_NOT_FOUND
;
3909 if (!EFI_ERROR (Status
)) {
3911 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
3913 if (!IfrDataParsedFlag
&& HiiHandle
!= NULL
&& DevicePath
!= NULL
) {
3914 StringPtr
= StrStr (AccessResults
, L
"&GUID=");
3915 if (StringPtr
!= NULL
) {
3918 if (GetElementsFromRequest (AccessResults
)) {
3919 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &AccessResults
, &DefaultResults
, NULL
);
3920 ASSERT_EFI_ERROR (Status
);
3922 if (StringPtr
!= NULL
) {
3927 // Merge the default sting from IFR code into the got setting from driver.
3929 if (DefaultResults
!= NULL
) {
3930 Status
= MergeDefaultString (&AccessResults
, DefaultResults
);
3931 ASSERT_EFI_ERROR (Status
);
3932 FreePool (DefaultResults
);
3933 DefaultResults
= NULL
;
3937 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'
3938 // which seperates the first <ConfigAltResp> and the following ones.
3940 if (!FirstElement
) {
3941 Status
= AppendToMultiString (Results
, L
"&");
3942 ASSERT_EFI_ERROR (Status
);
3945 Status
= AppendToMultiString (Results
, AccessResults
);
3946 ASSERT_EFI_ERROR (Status
);
3948 FirstElement
= FALSE
;
3950 FreePool (AccessResults
);
3951 AccessResults
= NULL
;
3954 FreePool (ConfigAccessHandles
);
3961 This function processes the results of processing forms and routes it to the
3962 appropriate handlers or storage.
3964 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
3966 @param Configuration A null-terminated Unicode string in
3967 <MulltiConfigResp> format.
3968 @param Progress A pointer to a string filled in with the offset of
3969 the most recent & before the first failing name /
3970 value pair (or the beginning of the string if the
3971 failure is in the first name / value pair) or the
3972 terminating NULL if all was successful.
3974 @retval EFI_SUCCESS The results have been distributed or are awaiting
3976 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
3977 results that must be stored awaiting possible
3979 @retval EFI_INVALID_PARAMETER Passing in a NULL for the Configuration parameter
3980 would result in this type of error.
3981 @retval EFI_NOT_FOUND Target for the specified routing data was not
3987 HiiConfigRoutingRouteConfig (
3988 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
3989 IN CONST EFI_STRING Configuration
,
3990 OUT EFI_STRING
*Progress
3993 HII_DATABASE_PRIVATE_DATA
*Private
;
3994 EFI_STRING StringPtr
;
3995 EFI_STRING ConfigResp
;
3998 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
3999 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
4001 HII_DATABASE_RECORD
*Database
;
4002 UINT8
*DevicePathPkg
;
4003 UINT8
*CurrentDevicePath
;
4004 EFI_HANDLE DriverHandle
;
4005 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
4006 EFI_STRING AccessProgress
;
4007 EFI_IFR_VARSTORE_EFI
*EfiVarStoreInfo
;
4008 BOOLEAN IsEfiVarstore
;
4010 if (This
== NULL
|| Progress
== NULL
) {
4011 return EFI_INVALID_PARAMETER
;
4014 if (Configuration
== NULL
) {
4016 return EFI_INVALID_PARAMETER
;
4019 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
4020 StringPtr
= Configuration
;
4021 *Progress
= StringPtr
;
4023 AccessProgress
= NULL
;
4024 EfiVarStoreInfo
= NULL
;
4025 IsEfiVarstore
= FALSE
;
4028 // The first element of <MultiConfigResp> should be
4029 // <GuidHdr>, which is in 'GUID='<Guid> syntax.
4031 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
4032 return EFI_INVALID_PARAMETER
;
4035 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) == 0) {
4037 // If parsing error, set Progress to the beginning of the <MultiConfigResp>
4038 // or most recent & before the error.
4040 if (StringPtr
== Configuration
) {
4041 *Progress
= StringPtr
;
4043 *Progress
= StringPtr
- 1;
4047 // Process each <ConfigResp> of <MultiConfigResp>
4049 Length
= CalculateConfigStringLen (StringPtr
);
4050 ConfigResp
= AllocateCopyPool ((Length
+ 1) * sizeof (CHAR16
), StringPtr
);
4051 if (ConfigResp
== NULL
) {
4052 return EFI_OUT_OF_RESOURCES
;
4055 // Append '\0' to the end of ConfigRequest
4057 *(ConfigResp
+ Length
) = 0;
4060 // Get the UEFI device path
4062 Status
= GetDevicePath (ConfigResp
, (UINT8
**) &DevicePath
);
4063 if (EFI_ERROR (Status
)) {
4064 FreePool (ConfigResp
);
4069 // Find driver which matches the routing data.
4071 DriverHandle
= NULL
;
4072 for (Link
= Private
->DatabaseList
.ForwardLink
;
4073 Link
!= &Private
->DatabaseList
;
4074 Link
= Link
->ForwardLink
4076 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
4078 if ((DevicePathPkg
= Database
->PackageList
->DevicePathPkg
) != NULL
) {
4079 CurrentDevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
4083 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) CurrentDevicePath
)
4085 DriverHandle
= Database
->DriverHandle
;
4092 // Try to find driver handle by device path.
4094 if (DriverHandle
== NULL
) {
4095 TempDevicePath
= DevicePath
;
4096 Status
= gBS
->LocateDevicePath (
4097 &gEfiDevicePathProtocolGuid
,
4101 if (EFI_ERROR (Status
) || (DriverHandle
== NULL
)) {
4103 // Routing data does not match any known driver.
4104 // Set Progress to the 'G' in "GUID" of the routing header.
4106 FreePool (DevicePath
);
4107 *Progress
= StringPtr
;
4108 FreePool (ConfigResp
);
4109 return EFI_NOT_FOUND
;
4113 FreePool (DevicePath
);
4116 // Check whether this ConfigRequest is search from Efi varstore type storage.
4118 Status
= GetVarStoreType(Database
, ConfigResp
, &IsEfiVarstore
, &EfiVarStoreInfo
);
4119 if (EFI_ERROR (Status
)) {
4123 if (IsEfiVarstore
) {
4125 // Call the SetVariable function to route settings.
4127 Status
= RouteConfigRespForEfiVarStore(This
, EfiVarStoreInfo
, ConfigResp
, &AccessProgress
);
4128 FreePool (EfiVarStoreInfo
);
4131 // Call corresponding ConfigAccess protocol to route settings
4133 Status
= gBS
->HandleProtocol (
4135 &gEfiHiiConfigAccessProtocolGuid
,
4136 (VOID
**) &ConfigAccess
4138 ASSERT_EFI_ERROR (Status
);
4140 Status
= ConfigAccess
->RouteConfig (
4146 if (EFI_ERROR (Status
)) {
4148 // AccessProgress indicates the parsing progress on <ConfigResp>.
4149 // Map it to the progress on <MultiConfigResp> then return it.
4151 *Progress
= StrStr (StringPtr
, AccessProgress
);
4153 FreePool (ConfigResp
);
4157 FreePool (ConfigResp
);
4161 // Go to next <ConfigResp> (skip '&').
4163 StringPtr
+= Length
;
4164 if (*StringPtr
== 0) {
4165 *Progress
= StringPtr
;
4178 This helper function is to be called by drivers to map configuration data
4179 stored in byte array ("block") formats such as UEFI Variables into current
4180 configuration strings.
4182 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
4184 @param ConfigRequest A null-terminated Unicode string in
4185 <ConfigRequest> format.
4186 @param Block Array of bytes defining the block's configuration.
4187 @param BlockSize Length in bytes of Block.
4188 @param Config Filled-in configuration string. String allocated
4189 by the function. Returned only if call is
4190 successful. It is <ConfigResp> string format.
4191 @param Progress A pointer to a string filled in with the offset of
4192 the most recent & before the first failing
4193 name/value pair (or the beginning of the string if
4194 the failure is in the first name / value pair) or
4195 the terminating NULL if all was successful.
4197 @retval EFI_SUCCESS The request succeeded. Progress points to the null
4198 terminator at the end of the ConfigRequest
4200 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress
4201 points to the first character of ConfigRequest.
4202 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigRequest or
4203 Block parameter would result in this type of
4204 error. Progress points to the first character of
4206 @retval EFI_DEVICE_ERROR Block not large enough. Progress undefined.
4207 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted string.
4208 Block is left updated and Progress points at
4209 the "&" preceding the first non-<BlockName>.
4215 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
4216 IN CONST EFI_STRING ConfigRequest
,
4217 IN CONST UINT8
*Block
,
4218 IN CONST UINTN BlockSize
,
4219 OUT EFI_STRING
*Config
,
4220 OUT EFI_STRING
*Progress
4223 HII_DATABASE_PRIVATE_DATA
*Private
;
4224 EFI_STRING StringPtr
;
4232 EFI_STRING ValueStr
;
4233 EFI_STRING ConfigElement
;
4239 if (This
== NULL
|| Progress
== NULL
|| Config
== NULL
) {
4240 return EFI_INVALID_PARAMETER
;
4243 if (Block
== NULL
|| ConfigRequest
== NULL
) {
4244 *Progress
= ConfigRequest
;
4245 return EFI_INVALID_PARAMETER
;
4249 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
4250 ASSERT (Private
!= NULL
);
4252 StringPtr
= ConfigRequest
;
4255 ConfigElement
= NULL
;
4258 // Allocate a fix length of memory to store Results. Reallocate memory for
4259 // Results if this fix length is insufficient.
4261 *Config
= (EFI_STRING
) AllocateZeroPool (MAX_STRING_LENGTH
);
4262 if (*Config
== NULL
) {
4263 return EFI_OUT_OF_RESOURCES
;
4269 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
4270 *Progress
= StringPtr
;
4271 Status
= EFI_INVALID_PARAMETER
;
4274 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"PATH=", StrLen (L
"PATH=")) != 0) {
4277 if (*StringPtr
== 0) {
4278 *Progress
= StringPtr
- 1;
4279 Status
= EFI_INVALID_PARAMETER
;
4283 while (*StringPtr
!= L
'&' && *StringPtr
!= 0) {
4286 if (*StringPtr
== 0) {
4287 *Progress
= StringPtr
;
4288 Status
= EFI_SUCCESS
;
4290 AppendToMultiString(Config
, ConfigRequest
);
4291 HiiToLower (*Config
);
4301 // Copy <ConfigHdr> and an additional '&' to <ConfigResp>
4303 TemChar
= *StringPtr
;
4305 AppendToMultiString(Config
, ConfigRequest
);
4306 *StringPtr
= TemChar
;
4309 // Parse each <RequestElement> if exists
4310 // Only <BlockName> format is supported by this help function.
4311 // <BlockName> ::= 'OFFSET='<Number>&'WIDTH='<Number>
4313 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"OFFSET=", StrLen (L
"OFFSET=")) == 0) {
4315 // Back up the header of one <BlockName>
4319 StringPtr
+= StrLen (L
"OFFSET=");
4323 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
4324 if (EFI_ERROR (Status
)) {
4325 *Progress
= ConfigRequest
;
4332 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
4334 FreePool (TmpBuffer
);
4336 StringPtr
+= Length
;
4337 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
4338 *Progress
= StringPtr
- Length
- StrLen (L
"OFFSET=") - 1;
4339 Status
= EFI_INVALID_PARAMETER
;
4342 StringPtr
+= StrLen (L
"&WIDTH=");
4347 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
4348 if (EFI_ERROR (Status
)) {
4349 *Progress
= ConfigRequest
;
4356 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
4358 FreePool (TmpBuffer
);
4360 StringPtr
+= Length
;
4361 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
4362 *Progress
= StringPtr
- Length
- StrLen (L
"&WIDTH=");
4363 Status
= EFI_INVALID_PARAMETER
;
4368 // Calculate Value and convert it to hex string.
4370 if (Offset
+ Width
> BlockSize
) {
4371 *Progress
= StringPtr
;
4372 Status
= EFI_DEVICE_ERROR
;
4376 Value
= (UINT8
*) AllocateZeroPool (Width
);
4377 if (Value
== NULL
) {
4378 *Progress
= ConfigRequest
;
4379 Status
= EFI_OUT_OF_RESOURCES
;
4383 CopyMem (Value
, (UINT8
*) Block
+ Offset
, Width
);
4385 Length
= Width
* 2 + 1;
4386 ValueStr
= (EFI_STRING
) AllocateZeroPool (Length
* sizeof (CHAR16
));
4387 if (ValueStr
== NULL
) {
4388 *Progress
= ConfigRequest
;
4389 Status
= EFI_OUT_OF_RESOURCES
;
4393 TemString
= ValueStr
;
4394 TemBuffer
= Value
+ Width
- 1;
4395 for (Index
= 0; Index
< Width
; Index
++, TemBuffer
--) {
4396 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
4403 // Build a ConfigElement
4405 Length
+= StringPtr
- TmpPtr
+ 1 + StrLen (L
"VALUE=");
4406 ConfigElement
= (EFI_STRING
) AllocateZeroPool (Length
* sizeof (CHAR16
));
4407 if (ConfigElement
== NULL
) {
4408 Status
= EFI_OUT_OF_RESOURCES
;
4411 CopyMem (ConfigElement
, TmpPtr
, (StringPtr
- TmpPtr
+ 1) * sizeof (CHAR16
));
4412 if (*StringPtr
== 0) {
4413 *(ConfigElement
+ (StringPtr
- TmpPtr
)) = L
'&';
4415 *(ConfigElement
+ (StringPtr
- TmpPtr
) + 1) = 0;
4416 StrCat (ConfigElement
, L
"VALUE=");
4417 StrCat (ConfigElement
, ValueStr
);
4419 AppendToMultiString (Config
, ConfigElement
);
4421 FreePool (ConfigElement
);
4422 FreePool (ValueStr
);
4423 ConfigElement
= NULL
;
4427 // If '\0', parsing is finished. Otherwise skip '&' to continue
4429 if (*StringPtr
== 0) {
4432 AppendToMultiString (Config
, L
"&");
4437 if (*StringPtr
!= 0) {
4438 *Progress
= StringPtr
- 1;
4439 Status
= EFI_INVALID_PARAMETER
;
4443 HiiToLower (*Config
);
4444 *Progress
= StringPtr
;
4448 if (*Config
!= NULL
) {
4452 if (ValueStr
!= NULL
) {
4453 FreePool (ValueStr
);
4455 if (Value
!= NULL
) {
4458 if (ConfigElement
!= NULL
) {
4459 FreePool (ConfigElement
);
4468 This helper function is to be called by drivers to map configuration strings
4469 to configurations stored in byte array ("block") formats such as UEFI Variables.
4471 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
4473 @param ConfigResp A null-terminated Unicode string in <ConfigResp>
4475 @param Block A possibly null array of bytes representing the
4476 current block. Only bytes referenced in the
4477 ConfigResp string in the block are modified. If
4478 this parameter is null or if the *BlockSize
4479 parameter is (on input) shorter than required by
4480 the Configuration string, only the BlockSize
4481 parameter is updated and an appropriate status
4482 (see below) is returned.
4483 @param BlockSize The length of the Block in units of UINT8. On
4484 input, this is the size of the Block. On output,
4485 if successful, contains the index of the last
4486 modified byte in the Block.
4487 @param Progress On return, points to an element of the ConfigResp
4488 string filled in with the offset of the most
4489 recent '&' before the first failing name / value
4490 pair (or the beginning of the string if the
4491 failure is in the first name / value pair) or the
4492 terminating NULL if all was successful.
4494 @retval EFI_SUCCESS The request succeeded. Progress points to the null
4495 terminator at the end of the ConfigResp string.
4496 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress
4497 points to the first character of ConfigResp.
4498 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigResp or
4499 Block parameter would result in this type of
4500 error. Progress points to the first character of
4502 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted name /
4503 value pair. Block is left updated and
4504 Progress points at the '&' preceding the first
4506 @retval EFI_DEVICE_ERROR Block not large enough. Progress undefined.
4507 @retval EFI_NOT_FOUND Target for the specified routing data was not found.
4508 Progress points to the "G" in "GUID" of the errant
4515 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
4516 IN CONST EFI_STRING ConfigResp
,
4517 IN OUT UINT8
*Block
,
4518 IN OUT UINTN
*BlockSize
,
4519 OUT EFI_STRING
*Progress
4522 HII_DATABASE_PRIVATE_DATA
*Private
;
4523 EFI_STRING StringPtr
;
4533 if (This
== NULL
|| BlockSize
== NULL
|| Progress
== NULL
) {
4534 return EFI_INVALID_PARAMETER
;
4537 *Progress
= ConfigResp
;
4538 if (ConfigResp
== NULL
) {
4539 return EFI_INVALID_PARAMETER
;
4542 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
4543 ASSERT (Private
!= NULL
);
4545 StringPtr
= ConfigResp
;
4546 BufferSize
= *BlockSize
;
4553 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
4554 *Progress
= StringPtr
;
4555 Status
= EFI_INVALID_PARAMETER
;
4558 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"PATH=", StrLen (L
"PATH=")) != 0) {
4561 if (*StringPtr
== 0) {
4562 *Progress
= StringPtr
;
4563 Status
= EFI_INVALID_PARAMETER
;
4567 while (*StringPtr
!= L
'&' && *StringPtr
!= 0) {
4570 if (*StringPtr
== 0) {
4571 *Progress
= StringPtr
;
4572 Status
= EFI_INVALID_PARAMETER
;
4577 // Parse each <ConfigElement> if exists
4578 // Only '&'<BlockConfig> format is supported by this help function.
4579 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE='<Number>
4581 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) == 0) {
4582 StringPtr
+= StrLen (L
"&OFFSET=");
4586 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
4587 if (EFI_ERROR (Status
)) {
4588 *Progress
= ConfigResp
;
4595 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
4597 FreePool (TmpBuffer
);
4599 StringPtr
+= Length
;
4600 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
4601 *Progress
= StringPtr
- Length
- StrLen (L
"&OFFSET=");
4602 Status
= EFI_INVALID_PARAMETER
;
4605 StringPtr
+= StrLen (L
"&WIDTH=");
4610 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
4611 if (EFI_ERROR (Status
)) {
4612 *Progress
= ConfigResp
;
4619 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
4621 FreePool (TmpBuffer
);
4623 StringPtr
+= Length
;
4624 if (StrnCmp (StringPtr
, L
"&VALUE=", StrLen (L
"&VALUE=")) != 0) {
4625 *Progress
= StringPtr
- Length
- StrLen (L
"&WIDTH=");
4626 Status
= EFI_INVALID_PARAMETER
;
4629 StringPtr
+= StrLen (L
"&VALUE=");
4634 Status
= GetValueOfNumber (StringPtr
, &Value
, &Length
);
4635 if (EFI_ERROR (Status
)) {
4636 *Progress
= ConfigResp
;
4640 StringPtr
+= Length
;
4641 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
4642 *Progress
= StringPtr
- Length
- StrLen (L
"&VALUE=");
4643 Status
= EFI_INVALID_PARAMETER
;
4648 // Update the Block with configuration info
4650 if ((Block
!= NULL
) && (Offset
+ Width
<= BufferSize
)) {
4651 CopyMem (Block
+ Offset
, Value
, Width
);
4653 if (Offset
+ Width
> MaxBlockSize
) {
4654 MaxBlockSize
= Offset
+ Width
;
4661 // If '\0', parsing is finished.
4663 if (*StringPtr
== 0) {
4669 // The input string is not ConfigResp format, return error.
4671 if (*StringPtr
!= 0) {
4672 *Progress
= StringPtr
;
4673 Status
= EFI_INVALID_PARAMETER
;
4677 *Progress
= StringPtr
+ StrLen (StringPtr
);
4678 *BlockSize
= MaxBlockSize
- 1;
4680 if (MaxBlockSize
> BufferSize
) {
4681 *BlockSize
= MaxBlockSize
;
4682 if (Block
!= NULL
) {
4683 return EFI_DEVICE_ERROR
;
4687 if (Block
== NULL
) {
4688 *Progress
= ConfigResp
;
4689 return EFI_INVALID_PARAMETER
;
4696 if (Value
!= NULL
) {
4704 This helper function is to be called by drivers to extract portions of
4705 a larger configuration string.
4707 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
4709 @param Configuration A null-terminated Unicode string in
4710 <MultiConfigAltResp> format.
4711 @param Guid A pointer to the GUID value to search for in the
4712 routing portion of the ConfigResp string when
4713 retrieving the requested data. If Guid is NULL,
4714 then all GUID values will be searched for.
4715 @param Name A pointer to the NAME value to search for in the
4716 routing portion of the ConfigResp string when
4717 retrieving the requested data. If Name is NULL,
4718 then all Name values will be searched for.
4719 @param DevicePath A pointer to the PATH value to search for in the
4720 routing portion of the ConfigResp string when
4721 retrieving the requested data. If DevicePath is
4722 NULL, then all DevicePath values will be searched
4724 @param AltCfgId A pointer to the ALTCFG value to search for in the
4725 routing portion of the ConfigResp string when
4726 retrieving the requested data. If this parameter
4727 is NULL, then the current setting will be
4729 @param AltCfgResp A pointer to a buffer which will be allocated by
4730 the function which contains the retrieved string
4731 as requested. This buffer is only allocated if
4732 the call was successful. It is <ConfigResp> format.
4734 @retval EFI_SUCCESS The request succeeded. The requested data was
4735 extracted and placed in the newly allocated
4737 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate AltCfgResp.
4738 @retval EFI_INVALID_PARAMETER Any parameter is invalid.
4739 @retval EFI_NOT_FOUND Target for the specified routing data was not
4746 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
4747 IN CONST EFI_STRING Configuration
,
4748 IN CONST EFI_GUID
*Guid
,
4749 IN CONST EFI_STRING Name
,
4750 IN CONST EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
4751 IN CONST UINT16
*AltCfgId
,
4752 OUT EFI_STRING
*AltCfgResp
4756 EFI_STRING StringPtr
;
4757 EFI_STRING HdrStart
;
4764 EFI_STRING AltIdStr
;
4781 if (This
== NULL
|| Configuration
== NULL
|| AltCfgResp
== NULL
) {
4782 return EFI_INVALID_PARAMETER
;
4785 StringPtr
= Configuration
;
4786 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
4787 return EFI_INVALID_PARAMETER
;
4791 // Generate the sub string for later matching.
4793 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*) Guid
, 1, &GuidStr
);
4796 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) DevicePath
),
4797 (VOID
*) DevicePath
,
4801 if (AltCfgId
!= NULL
) {
4802 GenerateSubStr (L
"ALTCFG=", sizeof (UINT16
), (VOID
*) AltCfgId
, 3, &AltIdStr
);
4805 GenerateSubStr (L
"NAME=", StrLen (Name
) * sizeof (CHAR16
), (VOID
*) Name
, 2, &NameStr
);
4807 GenerateSubStr (L
"NAME=", 0, NULL
, 2, &NameStr
);
4810 while (*StringPtr
!= 0) {
4812 // Try to match the GUID
4815 TmpPtr
= StrStr (StringPtr
, GuidStr
);
4816 if (TmpPtr
== NULL
) {
4817 Status
= EFI_NOT_FOUND
;
4823 // Jump to <NameHdr>
4826 StringPtr
= TmpPtr
+ StrLen (GuidStr
);
4828 StringPtr
= StrStr (TmpPtr
, L
"NAME=");
4829 if (StringPtr
== NULL
) {
4830 Status
= EFI_NOT_FOUND
;
4838 // Try to match the NAME
4840 if (GuidFlag
&& !NameFlag
) {
4841 if (StrnCmp (StringPtr
, NameStr
, StrLen (NameStr
)) != 0) {
4845 // Jump to <PathHdr>
4848 StringPtr
+= StrLen (NameStr
);
4850 StringPtr
= StrStr (StringPtr
, L
"PATH=");
4851 if (StringPtr
== NULL
) {
4852 Status
= EFI_NOT_FOUND
;
4861 // Try to match the DevicePath
4863 if (GuidFlag
&& NameFlag
&& !PathFlag
) {
4864 if (StrnCmp (StringPtr
, PathStr
, StrLen (PathStr
)) != 0) {
4869 // Jump to '&' before <DescHdr> or <ConfigBody>
4871 if (DevicePath
!= NULL
) {
4872 StringPtr
+= StrLen (PathStr
);
4874 StringPtr
= StrStr (StringPtr
, L
"&");
4875 if (StringPtr
== NULL
) {
4876 Status
= EFI_NOT_FOUND
;
4887 // Try to match the AltCfgId
4889 if (GuidFlag
&& NameFlag
&& PathFlag
) {
4890 if (AltCfgId
== NULL
) {
4892 // Return Current Setting when AltCfgId is NULL.
4894 Status
= OutputConfigBody (StringPtr
, &Result
);
4898 // Search the <ConfigAltResp> to get the <AltResp> with AltCfgId.
4900 if (StrnCmp (StringPtr
, AltIdStr
, StrLen (AltIdStr
)) != 0) {
4906 // Skip AltIdStr and &
4908 StringPtr
= StringPtr
+ StrLen (AltIdStr
);
4909 Status
= OutputConfigBody (StringPtr
, &Result
);
4915 Status
= EFI_NOT_FOUND
;
4919 if (!EFI_ERROR (Status
) && (Result
!= NULL
)) {
4921 // Copy the <ConfigHdr> and <ConfigBody>
4923 Length
= HdrEnd
- HdrStart
+ StrLen (Result
) + 1;
4924 *AltCfgResp
= AllocateZeroPool (Length
* sizeof (CHAR16
));
4925 if (*AltCfgResp
== NULL
) {
4926 Status
= EFI_OUT_OF_RESOURCES
;
4928 StrnCpy (*AltCfgResp
, HdrStart
, HdrEnd
- HdrStart
);
4929 StrCat (*AltCfgResp
, Result
);
4930 Status
= EFI_SUCCESS
;
4934 if (GuidStr
!= NULL
) {
4937 if (NameStr
!= NULL
) {
4940 if (PathStr
!= NULL
) {
4943 if (AltIdStr
!= NULL
) {
4944 FreePool (AltIdStr
);
4946 if (Result
!= NULL
) {