2 Implementation of interfaces function for EFI_HII_CONFIG_ROUTING_PROTOCOL.
4 Copyright (c) 2007 - 2008, Intel Corporation
5 All rights reserved. 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 DevicePath binary of a UEFI device path.
66 @retval EFI_INVALID_PARAMETER Any incoming parameter is invalid.
67 @retval EFI_OUT_OF_RESOURCES Lake of resources to store neccesary structures.
68 @retval EFI_SUCCESS The device path is retrieved and translated to
75 OUT UINT8
**DevicePath
80 EFI_STRING DevicePathString
;
81 UINT8
*DevicePathBuffer
;
86 if (String
== NULL
|| DevicePath
== NULL
) {
87 return EFI_INVALID_PARAMETER
;
91 // Find the 'PATH=' of <PathHdr> and skip it.
93 for (; (*String
!= 0 && StrnCmp (String
, L
"PATH=", StrLen (L
"PATH=")) != 0); String
++);
95 return EFI_INVALID_PARAMETER
;
98 String
+= StrLen (L
"PATH=");
102 // The content between 'PATH=' of <ConfigHdr> and '&' of next element
103 // or '\0' (end of configuration string) is the UNICODE %02x bytes encoding
104 // of UEFI device path.
106 for (Length
= 0; *String
!= 0 && *String
!= L
'&'; String
++, Length
++);
107 DevicePathString
= (EFI_STRING
) AllocateZeroPool ((Length
+ 1) * sizeof (CHAR16
));
108 if (DevicePathString
== NULL
) {
109 return EFI_OUT_OF_RESOURCES
;
111 StrnCpy (DevicePathString
, PathHdr
, Length
);
112 *(DevicePathString
+ Length
) = 0;
115 // The data in <PathHdr> is encoded as hex UNICODE %02x bytes in the same order
116 // as the device path resides in RAM memory.
117 // Translate the data into binary.
119 DevicePathBuffer
= (UINT8
*) AllocateZeroPool ((Length
+ 1) / 2);
120 if (DevicePathBuffer
== NULL
) {
121 FreePool (DevicePathString
);
122 return EFI_OUT_OF_RESOURCES
;
125 ZeroMem (TemStr
, sizeof (TemStr
));
126 for (Index
= 0; DevicePathString
[Index
] != L
'\0'; Index
++) {
127 TemStr
[0] = DevicePathString
[Index
];
128 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
129 if ((Index
& 1) == 0) {
130 DevicePathBuffer
[Index
/2] = DigitUint8
;
132 DevicePathBuffer
[Index
/2] = (UINT8
) ((DevicePathBuffer
[Index
/2] << 4) + DigitUint8
);
136 FreePool (DevicePathString
);
138 *DevicePath
= DevicePathBuffer
;
145 Converts the unicode character of the string from uppercase to lowercase.
146 This is a internal function.
148 @param Str String to be converted
154 IN EFI_STRING ConfigString
160 ASSERT (ConfigString
!= NULL
);
163 // Convert all hex digits in range [A-F] in the configuration header to [a-f]
165 for (String
= ConfigString
, Lower
= FALSE
; *String
!= L
'\0'; String
++) {
166 if (*String
== L
'=') {
168 } else if (*String
== L
'&') {
170 } else if (Lower
&& *String
>= L
'A' && *String
<= L
'F') {
171 *String
= (CHAR16
) (*String
- L
'A' + L
'a');
179 Generate a sub string then output it.
181 This is a internal function.
183 @param String A constant string which is the prefix of the to be
184 generated string, e.g. GUID=
186 @param BufferLen The length of the Buffer in bytes.
188 @param Buffer Points to a buffer which will be converted to be the
189 content of the generated string.
191 @param Flag If 1, the buffer contains data for the value of GUID or PATH stored in
192 UINT8 *; if 2, the buffer contains unicode string for the value of NAME;
193 if 3, the buffer contains other data.
195 @param SubStr Points to the output string. It's caller's
196 responsibility to free this buffer.
202 IN CONST EFI_STRING String
,
206 OUT EFI_STRING
*SubStr
211 EFI_STRING StringHeader
;
217 ASSERT (String
!= NULL
&& SubStr
!= NULL
);
219 if (Buffer
== NULL
) {
220 *SubStr
= AllocateCopyPool (StrSize (String
), String
);
221 ASSERT (*SubStr
!= NULL
);
226 // Header + Data + '&' + '\0'
228 Length
= StrLen (String
) + BufferLen
* 2 + 1 + 1;
229 Str
= AllocateZeroPool (Length
* sizeof (CHAR16
));
230 ASSERT (Str
!= NULL
);
232 StrCpy (Str
, String
);
233 Length
= (BufferLen
* 2 + 1) * sizeof (CHAR16
);
235 StringHeader
= Str
+ StrLen (String
);
236 TemString
= (CHAR16
*) StringHeader
;
241 // Convert Buffer to Hex String in reverse order
243 TemBuffer
= ((UINT8
*) Buffer
);
244 for (Index
= 0; Index
< BufferLen
; Index
++, TemBuffer
++) {
245 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
250 // Check buffer is enough
252 TemName
= (CHAR16
*) Buffer
;
253 ASSERT ((BufferLen
* 2 + 1) >= (StrLen (TemName
) * 4 + 1));
255 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
257 for (; *TemName
!= L
'\0'; TemName
++) {
258 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemName
, 4);
263 // Convert Buffer to Hex String
265 TemBuffer
= ((UINT8
*) Buffer
) + BufferLen
- 1;
266 for (Index
= 0; Index
< BufferLen
; Index
++, TemBuffer
--) {
267 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
275 // Convert the uppercase to lowercase since <HexAf> is defined in lowercase format.
285 Retrieve the <ConfigBody> from String then output it.
287 This is a internal function.
289 @param String A sub string of a configuration string in
290 <MultiConfigAltResp> format.
291 @param ConfigBody Points to the output string. It's caller's
292 responsibility to free this buffer.
294 @retval EFI_INVALID_PARAMETER There is no form package in current hii database.
295 @retval EFI_OUT_OF_RESOURCES Not enough memory to finish this operation.
296 @retval EFI_SUCCESS All existing storage is exported.
301 IN EFI_STRING String
,
302 OUT EFI_STRING
*ConfigBody
309 if (String
== NULL
|| ConfigBody
== NULL
) {
310 return EFI_INVALID_PARAMETER
;
314 // The setting information should start OFFSET, not ALTCFG.
316 if (StrnCmp (String
, L
"&ALTCFG=", StrLen (L
"&ALTCFG=")) == 0) {
317 return EFI_INVALID_PARAMETER
;
320 TmpPtr
= StrStr (String
, L
"GUID=");
321 if (TmpPtr
== NULL
) {
323 // It is the last <ConfigResp> of the incoming configuration string.
325 Result
= AllocateCopyPool (StrSize (String
), String
);
326 if (Result
== NULL
) {
327 return EFI_OUT_OF_RESOURCES
;
329 *ConfigBody
= Result
;
334 Length
= TmpPtr
- String
;
335 Result
= AllocateCopyPool (Length
* sizeof (CHAR16
), String
);
336 if (Result
== NULL
) {
337 return EFI_OUT_OF_RESOURCES
;
340 *(Result
+ Length
- 1) = 0;
341 *ConfigBody
= Result
;
346 Append a string to a multi-string format.
348 This is a internal function.
350 @param MultiString String in <MultiConfigRequest>,
351 <MultiConfigAltResp>, or <MultiConfigResp>. On
352 input, the buffer length of this string is
353 MAX_STRING_LENGTH. On output, the buffer length
355 @param AppendString NULL-terminated Unicode string.
357 @retval EFI_INVALID_PARAMETER Any incoming parameter is invalid.
358 @retval EFI_SUCCESS AppendString is append to the end of MultiString
362 AppendToMultiString (
363 IN OUT EFI_STRING
*MultiString
,
364 IN EFI_STRING AppendString
367 UINTN AppendStringSize
;
368 UINTN MultiStringSize
;
370 if (MultiString
== NULL
|| *MultiString
== NULL
|| AppendString
== NULL
) {
371 return EFI_INVALID_PARAMETER
;
374 AppendStringSize
= StrSize (AppendString
);
375 MultiStringSize
= StrSize (*MultiString
);
378 // Enlarge the buffer each time when length exceeds MAX_STRING_LENGTH.
380 if (MultiStringSize
+ AppendStringSize
> MAX_STRING_LENGTH
||
381 MultiStringSize
> MAX_STRING_LENGTH
) {
382 *MultiString
= (EFI_STRING
) ReallocatePool (
384 MultiStringSize
+ AppendStringSize
,
385 (VOID
*) (*MultiString
)
387 ASSERT (*MultiString
!= NULL
);
390 // Append the incoming string
392 StrCat (*MultiString
, AppendString
);
399 Get the value of <Number> in <BlockConfig> format, i.e. the value of OFFSET
401 <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>
403 This is a internal function.
405 @param StringPtr String in <BlockConfig> format and points to the
406 first character of <Number>.
407 @param Number The output value. Caller takes the responsibility
409 @param Len Length of the <Number>, in characters.
411 @retval EFI_OUT_OF_RESOURCES Insufficient resources to store neccessary
413 @retval EFI_SUCCESS Value of <Number> is outputted in Number
419 IN EFI_STRING StringPtr
,
433 ASSERT (StringPtr
!= NULL
&& Number
!= NULL
&& Len
!= NULL
);
434 ASSERT (*StringPtr
!= L
'\0');
439 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
442 *Len
= StringPtr
- TmpPtr
;
445 Str
= (EFI_STRING
) AllocateZeroPool (Length
* sizeof (CHAR16
));
447 Status
= EFI_OUT_OF_RESOURCES
;
450 CopyMem (Str
, TmpPtr
, *Len
* sizeof (CHAR16
));
451 *(Str
+ *Len
) = L
'\0';
453 Length
= (Length
+ 1) / 2;
454 Buf
= (UINT8
*) AllocateZeroPool (Length
);
456 Status
= EFI_OUT_OF_RESOURCES
;
461 ZeroMem (TemStr
, sizeof (TemStr
));
462 for (Index
= 0; Index
< Length
; Index
++) {
463 TemStr
[0] = Str
[Length
- Index
- 1];
464 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
465 if ((Index
& 1) == 0) {
466 Buf
[Index
/2] = DigitUint8
;
468 Buf
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Buf
[Index
/2]);
473 Status
= EFI_SUCCESS
;
484 This function merges DefaultAltCfgResp string into AltCfgResp string for
485 the missing AltCfgId in AltCfgResq.
487 @param AltCfgResp Pointer to a null-terminated Unicode string in
488 <ConfigAltResp> format. The default value string
489 will be merged into it.
490 @param DefaultAltCfgResp Pointer to a null-terminated Unicode string in
491 <MultiConfigAltResp> format. The default value
492 string may contain more than one ConfigAltResp
493 string for the different varstore buffer.
495 @retval EFI_SUCCESS The merged string returns.
496 @retval EFI_INVALID_PARAMETER *AltCfgResp is to NULL.
501 IN OUT EFI_STRING
*AltCfgResp
,
502 IN EFI_STRING DefaultAltCfgResp
505 EFI_STRING StringPtrDefault
;
506 EFI_STRING StringPtrEnd
;
508 EFI_STRING StringPtr
;
509 EFI_STRING AltConfigHdr
;
511 UINTN SizeAltCfgResp
;
513 if (*AltCfgResp
== NULL
) {
514 return EFI_INVALID_PARAMETER
;
518 // Get the requestr ConfigHdr
521 StringPtr
= *AltCfgResp
;
524 // Find <ConfigHdr> GUID=...&NAME=...&PATH=...
526 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
527 return EFI_INVALID_PARAMETER
;
529 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&NAME=", StrLen (L
"&NAME=")) != 0) {
532 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&PATH=", StrLen (L
"&PATH=")) != 0) {
535 if (*StringPtr
== L
'\0') {
536 return EFI_INVALID_PARAMETER
;
538 StringPtr
+= StrLen (L
"&PATH=");
539 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
542 HeaderLength
= StringPtr
- *AltCfgResp
;
545 // Construct AltConfigHdr string "&<ConfigHdr>&ALTCFG=XXXX\0"
546 // |1| StrLen (ConfigHdr) | 8 | 4 | 1 |
548 AltConfigHdr
= AllocateZeroPool ((1 + HeaderLength
+ 8 + 4 + 1) * sizeof (CHAR16
));
549 if (AltConfigHdr
== NULL
) {
550 return EFI_OUT_OF_RESOURCES
;
552 StrCpy (AltConfigHdr
, L
"&");
553 StrnCat (AltConfigHdr
, *AltCfgResp
, HeaderLength
);
554 StrCat (AltConfigHdr
, L
"&ALTCFG=");
555 HeaderLength
= StrLen (AltConfigHdr
);
557 StringPtrDefault
= StrStr (DefaultAltCfgResp
, AltConfigHdr
);
558 while (StringPtrDefault
!= NULL
) {
562 StrnCat (AltConfigHdr
, StringPtrDefault
+ HeaderLength
, 4);
563 StringPtr
= StrStr (*AltCfgResp
, AltConfigHdr
);
566 // Append the found default value string to the input AltCfgResp
568 if (StringPtr
== NULL
) {
569 StringPtrEnd
= StrStr (StringPtrDefault
+ 1, L
"&GUID");
570 SizeAltCfgResp
= StrSize (*AltCfgResp
);
571 if (StringPtrEnd
== NULL
) {
573 // No more default string is found.
575 *AltCfgResp
= (EFI_STRING
) ReallocatePool (
577 SizeAltCfgResp
+ StrSize (StringPtrDefault
),
578 (VOID
*) (*AltCfgResp
)
580 StrCat (*AltCfgResp
, StringPtrDefault
);
583 TempChar
= *StringPtrEnd
;
584 *StringPtrEnd
= L
'\0';
585 *AltCfgResp
= (EFI_STRING
) ReallocatePool (
587 SizeAltCfgResp
+ StrSize (StringPtrDefault
),
588 (VOID
*) (*AltCfgResp
)
590 StrCat (*AltCfgResp
, StringPtrDefault
);
591 *StringPtrEnd
= TempChar
;
596 // Find next AltCfg String
598 *(AltConfigHdr
+ HeaderLength
) = L
'\0';
599 StringPtrDefault
= StrStr (StringPtrDefault
+ 1, AltConfigHdr
);
606 This function finds the matched DefaultName for the input DefaultId
608 @param DefaultIdArray Array stores the map table between DefaultId and DefaultName.
609 @param VarDefaultId Default Id
610 @param VarDefaultName Default Name string ID for the input default ID.
612 @retval EFI_SUCCESS The mapped default name string ID is found.
613 @retval EFI_NOT_FOUND The mapped default name string ID is not found.
617 IN IFR_DEFAULT_DATA
*DefaultIdArray
,
618 IN UINT16 VarDefaultId
,
619 OUT EFI_STRING_ID
*VarDefaultName
623 IFR_DEFAULT_DATA
*DefaultData
;
625 for (Link
= DefaultIdArray
->Entry
.ForwardLink
; Link
!= &DefaultIdArray
->Entry
; Link
= Link
->ForwardLink
) {
626 DefaultData
= BASE_CR (Link
, IFR_DEFAULT_DATA
, Entry
);
627 if (DefaultData
->DefaultId
== VarDefaultId
) {
628 *VarDefaultName
= DefaultData
->DefaultName
;
633 return EFI_NOT_FOUND
;
637 This function inserts new DefaultValueData into the BlockData DefaultValue array.
639 @param BlockData The BlockData is updated to add new default value.
640 @param DefaultValueData The DefaultValue is added.
645 IN IFR_BLOCK_DATA
*BlockData
,
646 IN IFR_DEFAULT_DATA
*DefaultValueData
650 IFR_DEFAULT_DATA
*DefaultValueArray
;
652 for (Link
= BlockData
->DefaultValueEntry
.ForwardLink
; Link
!= &BlockData
->DefaultValueEntry
; Link
= Link
->ForwardLink
) {
653 DefaultValueArray
= BASE_CR (Link
, IFR_DEFAULT_DATA
, Entry
);
654 if (DefaultValueArray
->DefaultId
== DefaultValueData
->DefaultId
) {
656 // Update the default value array in BlockData.
658 DefaultValueArray
->Value
= DefaultValueData
->Value
;
659 FreePool (DefaultValueData
);
661 } else if (DefaultValueArray
->DefaultId
> DefaultValueData
->DefaultId
) {
663 // Insert new default value data in the front of this default value array.
665 InsertTailList (Link
, &DefaultValueData
->Entry
);
671 // Insert new default value data in tail.
673 InsertTailList (Link
, &DefaultValueData
->Entry
);
678 This function inserts new BlockData into the block link
680 @param BlockLink The list entry points to block array.
681 @param BlockData The point to BlockData is added.
686 IN LIST_ENTRY
*BlockLink
,
687 IN IFR_BLOCK_DATA
**BlockData
691 IFR_BLOCK_DATA
*BlockArray
;
692 IFR_BLOCK_DATA
*BlockSingleData
;
694 BlockSingleData
= *BlockData
;
697 // Insert block data in its Offset and Width order.
699 for (Link
= BlockLink
->ForwardLink
; Link
!= BlockLink
; Link
= Link
->ForwardLink
) {
700 BlockArray
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
701 if (BlockArray
->Offset
== BlockSingleData
->Offset
) {
702 if (BlockArray
->Width
> BlockSingleData
->Width
) {
704 // Insert this block data in the front of block array
706 InsertTailList (Link
, &BlockSingleData
->Entry
);
710 if (BlockArray
->Width
== BlockSingleData
->Width
) {
712 // The same block array has been added.
714 FreePool (BlockSingleData
);
715 *BlockData
= BlockArray
;
718 } else if (BlockArray
->Offset
> BlockSingleData
->Offset
) {
720 // Insert new block data in the front of block array
722 InsertTailList (Link
, &BlockSingleData
->Entry
);
728 // Add new block data into the tail.
730 InsertTailList (Link
, &BlockSingleData
->Entry
);
735 This function checks VarOffset and VarWidth is in the block range.
737 @param BlockArray The block array is to be checked.
738 @param VarOffset Offset of var to the structure
739 @param VarWidth Width of var.
741 @retval TRUE This Var is in the block range.
742 @retval FALSE This Var is not in the block range.
746 IN IFR_BLOCK_DATA
*RequestBlockArray
,
752 IFR_BLOCK_DATA
*BlockData
;
755 // No Request Block array, all vars are got.
757 if (RequestBlockArray
== NULL
) {
762 // Check the input var is in the request block range.
764 for (Link
= RequestBlockArray
->Entry
.ForwardLink
; Link
!= &RequestBlockArray
->Entry
; Link
= Link
->ForwardLink
) {
765 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
766 if ((VarOffset
>= BlockData
->Offset
) && ((VarOffset
+ VarWidth
) <= (BlockData
->Offset
+ BlockData
->Width
))) {
775 This function parses Form Package to get the block array and the default
776 value array according to the request ConfigHdr.
778 @param Package Pointer to the form package data.
779 @param PackageLength Length of the pacakge.
780 @param ConfigHdr Request string ConfigHdr. If it is NULL,
781 the first found varstore will be as ConfigHdr.
782 @param RequestBlockArray The block array is retrieved from the request string.
783 @param VarStorageData VarStorage structure contains the got block and default value.
784 @param PIfrDefaultIdArray Point to the got default id and default name array.
786 @retval EFI_SUCCESS The block array and the default value array are got.
787 @retval EFI_INVALID_PARAMETER The varstore defintion in the differnt form pacakges
789 @retval EFI_OUT_OF_RESOURCES No enough memory.
795 IN UINT32 PackageLenth
,
796 IN EFI_STRING ConfigHdr
,
797 IN IFR_BLOCK_DATA
*RequestBlockArray
,
798 IN OUT IFR_VARSTORAGE_DATA
*VarStorageData
,
799 OUT IFR_DEFAULT_DATA
**PIfrDefaultIdArray
804 EFI_IFR_VARSTORE
*IfrVarStore
;
805 EFI_IFR_OP_HEADER
*IfrOpHdr
;
806 EFI_IFR_ONE_OF
*IfrOneOf
;
807 EFI_IFR_ONE_OF_OPTION
*IfrOneOfOption
;
808 EFI_IFR_DEFAULT
*IfrDefault
;
809 EFI_IFR_ORDERED_LIST
*IfrOrderedList
;
810 EFI_IFR_CHECKBOX
*IfrCheckBox
;
811 EFI_IFR_PASSWORD
*IfrPassword
;
812 EFI_IFR_STRING
*IfrString
;
813 IFR_DEFAULT_DATA
*DefaultIdArray
;
814 IFR_DEFAULT_DATA
*DefaultData
;
815 IFR_BLOCK_DATA
*BlockData
;
816 CHAR16
*VarStoreName
;
819 EFI_STRING_ID VarDefaultName
;
827 // Initialize DefaultIdArray to store the map between DeaultId and DefaultName
830 Status
= EFI_SUCCESS
;
836 DefaultIdArray
= (IFR_DEFAULT_DATA
*) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
837 if (DefaultIdArray
== NULL
) {
838 return EFI_OUT_OF_RESOURCES
;
840 InitializeListHead (&DefaultIdArray
->Entry
);
843 // Go through the form package to parse OpCode one by one.
845 IfrOffset
= sizeof (EFI_HII_PACKAGE_HEADER
);
846 while (IfrOffset
< PackageLenth
) {
847 IfrOpHdr
= (EFI_IFR_OP_HEADER
*) (Package
+ IfrOffset
);
849 switch (IfrOpHdr
->OpCode
) {
850 case EFI_IFR_VARSTORE_OP
:
852 // VarStore is found. Don't need to search any more.
854 if (VarStorageData
->Size
!= 0) {
859 // Get the requied varstore information
860 // Add varstore by Guid and Name in ConfigHdr
861 // Make sure Offset is in varstore size and varstoreid
863 IfrVarStore
= (EFI_IFR_VARSTORE
*) IfrOpHdr
;
864 VarStoreName
= AllocateZeroPool (AsciiStrSize ((CHAR8
*)IfrVarStore
->Name
) * sizeof (CHAR16
));
865 if (VarStoreName
== NULL
) {
866 Status
= EFI_OUT_OF_RESOURCES
;
869 AsciiStrToUnicodeStr ((CHAR8
*) IfrVarStore
->Name
, VarStoreName
);
871 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*) &IfrVarStore
->Guid
, 1, &GuidStr
);
872 GenerateSubStr (L
"NAME=", StrLen (VarStoreName
) * sizeof (CHAR16
), (VOID
*) VarStoreName
, 2, &NameStr
);
873 LengthString
= StrLen (GuidStr
);
874 LengthString
= LengthString
+ StrLen (NameStr
) + 1;
875 TempStr
= AllocateZeroPool (LengthString
* sizeof (CHAR16
));
878 if (TempStr
== NULL
) {
879 FreePool (VarStoreName
);
880 Status
= EFI_OUT_OF_RESOURCES
;
883 StrCpy (TempStr
, GuidStr
);
884 StrCat (TempStr
, NameStr
);
885 if (ConfigHdr
== NULL
|| StrnCmp (ConfigHdr
, TempStr
, StrLen (TempStr
)) == 0) {
887 // Find the matched VarStore
889 CopyGuid (&VarStorageData
->Guid
, (EFI_GUID
*) (VOID
*) &IfrVarStore
->Guid
);
890 VarStorageData
->VarStoreId
= IfrVarStore
->VarStoreId
;
891 VarStorageData
->Size
= IfrVarStore
->Size
;
892 VarStorageData
->Name
= VarStoreName
;
895 // No found, free the allocated memory
897 FreePool (VarStoreName
);
900 // Free alllocated temp string.
905 case EFI_IFR_DEFAULTSTORE_OP
:
907 // Add new the map between default id and default name.
909 DefaultData
= (IFR_DEFAULT_DATA
*) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
910 if (DefaultData
== NULL
) {
911 Status
= EFI_OUT_OF_RESOURCES
;
914 DefaultData
->DefaultId
= ((EFI_IFR_DEFAULTSTORE
*) IfrOpHdr
)->DefaultId
;
915 DefaultData
->DefaultName
= ((EFI_IFR_DEFAULTSTORE
*) IfrOpHdr
)->DefaultName
;
916 InsertTailList (&DefaultIdArray
->Entry
, &DefaultData
->Entry
);
920 case EFI_IFR_FORM_OP
:
922 // No matched varstore is found and directly return.
924 if (VarStorageData
->Size
== 0) {
925 Status
= EFI_SUCCESS
;
930 case EFI_IFR_ONE_OF_OP
:
931 case EFI_IFR_NUMERIC_OP
:
933 // Numeric and OneOf has the same opcode structure.
937 // Check whether this question is for the requested varstore.
939 IfrOneOf
= (EFI_IFR_ONE_OF
*) IfrOpHdr
;
940 if (IfrOneOf
->Question
.VarStoreId
!= VarStorageData
->VarStoreId
) {
945 // Get Offset/Width by Question header and OneOf Flags
947 VarOffset
= IfrOneOf
->Question
.VarStoreInfo
.VarOffset
;
948 VarWidth
= (UINT16
) (1 << (IfrOneOf
->Flags
& EFI_IFR_NUMERIC_SIZE
));
950 // Check whether this question is in requested block array.
952 if (!BlockArrayCheck (RequestBlockArray
, VarOffset
, VarWidth
)) {
954 // This question is not in the requested string. Skip it.
960 // Check this var question is in the var storage
962 if ((VarOffset
+ VarWidth
) > VarStorageData
->Size
) {
963 Status
= EFI_INVALID_PARAMETER
;
970 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
971 if (BlockData
== NULL
) {
972 Status
= EFI_OUT_OF_RESOURCES
;
975 BlockData
->Offset
= VarOffset
;
976 BlockData
->Width
= VarWidth
;
977 BlockData
->QuestionId
= IfrOneOf
->Question
.QuestionId
;
978 BlockData
->OpCode
= IfrOpHdr
->OpCode
;
979 BlockData
->Scope
= IfrOpHdr
->Scope
;
980 InitializeListHead (&BlockData
->DefaultValueEntry
);
982 // Add Block Data into VarStorageData BlockEntry
984 InsertBlockData (&VarStorageData
->BlockEntry
, &BlockData
);
987 case EFI_IFR_ORDERED_LIST_OP
:
989 // offset by question header
990 // width by EFI_IFR_ORDERED_LIST MaxContainers * OneofOption Type
991 // no default value and default id, how to define its default value?
995 // Check whether this question is for the requested varstore.
997 IfrOrderedList
= (EFI_IFR_ORDERED_LIST
*) IfrOpHdr
;
998 if (IfrOrderedList
->Question
.VarStoreId
!= VarStorageData
->VarStoreId
) {
1003 // Get Offset/Width by Question header and OneOf Flags
1005 VarOffset
= IfrOrderedList
->Question
.VarStoreInfo
.VarOffset
;
1006 VarWidth
= IfrOrderedList
->MaxContainers
;
1009 // Check whether this question is in requested block array.
1011 if (!BlockArrayCheck (RequestBlockArray
, VarOffset
, VarWidth
)) {
1013 // This question is not in the requested string. Skip it.
1019 // Check this var question is in the var storage
1021 if ((VarOffset
+ VarWidth
) > VarStorageData
->Size
) {
1022 Status
= EFI_INVALID_PARAMETER
;
1029 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
1030 if (BlockData
== NULL
) {
1031 Status
= EFI_OUT_OF_RESOURCES
;
1034 BlockData
->Offset
= VarOffset
;
1035 BlockData
->Width
= VarWidth
;
1036 BlockData
->QuestionId
= IfrOrderedList
->Question
.QuestionId
;
1037 BlockData
->OpCode
= IfrOpHdr
->OpCode
;
1038 BlockData
->Scope
= IfrOpHdr
->Scope
;
1039 InitializeListHead (&BlockData
->DefaultValueEntry
);
1042 // Add Block Data into VarStorageData BlockEntry
1044 InsertBlockData (&VarStorageData
->BlockEntry
, &BlockData
);
1047 case EFI_IFR_CHECKBOX_OP
:
1049 // EFI_IFR_DEFAULT_OP
1050 // offset by question header
1051 // width is 1 sizeof (BOOLEAN)
1052 // default id by CheckBox Flags if CheckBox flags (Default or Mau) is set, the default value is 1 to be set.
1053 // value by DefaultOption
1054 // default id by DeaultOption DefaultId can override CheckBox Flags and Default value.
1058 // Check whether this question is for the requested varstore.
1060 IfrCheckBox
= (EFI_IFR_CHECKBOX
*) IfrOpHdr
;
1061 if (IfrCheckBox
->Question
.VarStoreId
!= VarStorageData
->VarStoreId
) {
1066 // Get Offset/Width by Question header and OneOf Flags
1068 VarOffset
= IfrCheckBox
->Question
.VarStoreInfo
.VarOffset
;
1069 VarWidth
= sizeof (BOOLEAN
);
1072 // Check whether this question is in requested block array.
1074 if (!BlockArrayCheck (RequestBlockArray
, VarOffset
, VarWidth
)) {
1076 // This question is not in the requested string. Skip it.
1082 // Check this var question is in the var storage
1084 if ((VarOffset
+ VarWidth
) > VarStorageData
->Size
) {
1085 Status
= EFI_INVALID_PARAMETER
;
1092 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
1093 if (BlockData
== NULL
) {
1094 Status
= EFI_OUT_OF_RESOURCES
;
1097 BlockData
->Offset
= VarOffset
;
1098 BlockData
->Width
= VarWidth
;
1099 BlockData
->QuestionId
= IfrCheckBox
->Question
.QuestionId
;
1100 BlockData
->OpCode
= IfrOpHdr
->OpCode
;
1101 BlockData
->Scope
= IfrOpHdr
->Scope
;
1102 InitializeListHead (&BlockData
->DefaultValueEntry
);
1104 // Add Block Data into VarStorageData BlockEntry
1106 InsertBlockData (&VarStorageData
->BlockEntry
, &BlockData
);
1109 // Add default value by CheckBox Flags
1111 if ((IfrCheckBox
->Flags
& EFI_IFR_CHECKBOX_DEFAULT
) == EFI_IFR_CHECKBOX_DEFAULT
) {
1113 // Set standard ID to Manufacture ID and Get DefaultName String ID
1115 VarDefaultId
= EFI_HII_DEFAULT_CLASS_STANDARD
;
1116 Status
= FindDefaultName (DefaultIdArray
, VarDefaultId
, &VarDefaultName
);
1117 if (EFI_ERROR (Status
)) {
1121 // Prepare new DefaultValue
1123 DefaultData
= (IFR_DEFAULT_DATA
*) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
1124 if (DefaultData
== NULL
) {
1125 Status
= EFI_OUT_OF_RESOURCES
;
1128 DefaultData
->DefaultId
= VarDefaultId
;
1129 DefaultData
->DefaultName
= VarDefaultName
;
1130 DefaultData
->Value
= 1;
1132 // Add DefaultValue into current BlockData
1134 InsertDefaultValue (BlockData
, DefaultData
);
1137 if ((IfrCheckBox
->Flags
& EFI_IFR_CHECKBOX_DEFAULT_MFG
) == EFI_IFR_CHECKBOX_DEFAULT_MFG
) {
1139 // Set standard ID to Manufacture ID and Get DefaultName String ID
1141 VarDefaultId
= EFI_HII_DEFAULT_CLASS_MANUFACTURING
;
1142 Status
= FindDefaultName (DefaultIdArray
, VarDefaultId
, &VarDefaultName
);
1143 if (EFI_ERROR (Status
)) {
1147 // Prepare new DefaultValue
1149 DefaultData
= (IFR_DEFAULT_DATA
*) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
1150 if (DefaultData
== NULL
) {
1151 Status
= EFI_OUT_OF_RESOURCES
;
1154 DefaultData
->DefaultId
= VarDefaultId
;
1155 DefaultData
->DefaultName
= VarDefaultName
;
1156 DefaultData
->Value
= 1;
1158 // Add DefaultValue into current BlockData
1160 InsertDefaultValue (BlockData
, DefaultData
);
1164 case EFI_IFR_STRING_OP
:
1166 // offset by question header
1167 // width MaxSize * sizeof (CHAR16)
1168 // no default value, only block array
1172 // Check whether this question is for the requested varstore.
1174 IfrString
= (EFI_IFR_STRING
*) IfrOpHdr
;
1175 if (IfrString
->Question
.VarStoreId
!= VarStorageData
->VarStoreId
) {
1180 // Get Offset/Width by Question header and OneOf Flags
1182 VarOffset
= IfrString
->Question
.VarStoreInfo
.VarOffset
;
1183 VarWidth
= (UINT16
) (IfrString
->MaxSize
* sizeof (UINT16
));
1186 // Check whether this question is in requested block array.
1188 if (!BlockArrayCheck (RequestBlockArray
, VarOffset
, VarWidth
)) {
1190 // This question is not in the requested string. Skip it.
1196 // Check this var question is in the var storage
1198 if ((VarOffset
+ VarWidth
) > VarStorageData
->Size
) {
1199 Status
= EFI_INVALID_PARAMETER
;
1206 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
1207 if (BlockData
== NULL
) {
1208 Status
= EFI_OUT_OF_RESOURCES
;
1211 BlockData
->Offset
= VarOffset
;
1212 BlockData
->Width
= VarWidth
;
1213 BlockData
->QuestionId
= IfrString
->Question
.QuestionId
;
1214 BlockData
->OpCode
= IfrOpHdr
->OpCode
;
1215 InitializeListHead (&BlockData
->DefaultValueEntry
);
1218 // Add Block Data into VarStorageData BlockEntry
1220 InsertBlockData (&VarStorageData
->BlockEntry
, &BlockData
);
1223 // No default value for string.
1228 case EFI_IFR_PASSWORD_OP
:
1230 // offset by question header
1231 // width MaxSize * sizeof (CHAR16)
1232 // no default value, only block array
1236 // Check whether this question is for the requested varstore.
1238 IfrPassword
= (EFI_IFR_PASSWORD
*) IfrOpHdr
;
1239 if (IfrPassword
->Question
.VarStoreId
!= VarStorageData
->VarStoreId
) {
1244 // Get Offset/Width by Question header and OneOf Flags
1246 VarOffset
= IfrPassword
->Question
.VarStoreInfo
.VarOffset
;
1247 VarWidth
= (UINT16
) (IfrPassword
->MaxSize
* sizeof (UINT16
));
1250 // Check whether this question is in requested block array.
1252 if (!BlockArrayCheck (RequestBlockArray
, VarOffset
, VarWidth
)) {
1254 // This question is not in the requested string. Skip it.
1260 // Check this var question is in the var storage
1262 if ((VarOffset
+ VarWidth
) > VarStorageData
->Size
) {
1263 Status
= EFI_INVALID_PARAMETER
;
1270 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
1271 if (BlockData
== NULL
) {
1272 Status
= EFI_OUT_OF_RESOURCES
;
1275 BlockData
->Offset
= VarOffset
;
1276 BlockData
->Width
= VarWidth
;
1277 BlockData
->QuestionId
= IfrPassword
->Question
.QuestionId
;
1278 BlockData
->OpCode
= IfrOpHdr
->OpCode
;
1279 InitializeListHead (&BlockData
->DefaultValueEntry
);
1282 // Add Block Data into VarStorageData BlockEntry
1284 InsertBlockData (&VarStorageData
->BlockEntry
, &BlockData
);
1287 // No default value for string.
1292 case EFI_IFR_ONE_OF_OPTION_OP
:
1294 // No matched block data is ignored.
1296 if (BlockData
== NULL
|| BlockData
->Scope
== 0) {
1300 IfrOneOfOption
= (EFI_IFR_ONE_OF_OPTION
*) IfrOpHdr
;
1301 if (BlockData
->OpCode
== EFI_IFR_ORDERED_LIST_OP
) {
1303 // Get ordered list option data type.
1305 if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_8
|| IfrOneOfOption
->Type
== EFI_IFR_TYPE_BOOLEAN
) {
1307 } else if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_16
) {
1309 } else if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_32
) {
1311 } else if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_64
) {
1315 // Invalid ordered list option data type.
1317 Status
= EFI_INVALID_PARAMETER
;
1321 // Calculate Ordered list QuestionId width.
1323 BlockData
->Width
= (UINT16
) (BlockData
->Width
* VarWidth
);
1328 if ((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT
) == EFI_IFR_OPTION_DEFAULT
) {
1330 // Set standard ID to Manufacture ID and Get DefaultName String ID
1332 VarDefaultId
= EFI_HII_DEFAULT_CLASS_STANDARD
;
1333 Status
= FindDefaultName (DefaultIdArray
, VarDefaultId
, &VarDefaultName
);
1334 if (EFI_ERROR (Status
)) {
1338 // Prepare new DefaultValue
1340 DefaultData
= (IFR_DEFAULT_DATA
*) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
1341 if (DefaultData
== NULL
) {
1342 Status
= EFI_OUT_OF_RESOURCES
;
1345 DefaultData
->DefaultId
= VarDefaultId
;
1346 DefaultData
->DefaultName
= VarDefaultName
;
1347 DefaultData
->Value
= IfrOneOfOption
->Value
.u64
;
1349 // Add DefaultValue into current BlockData
1351 InsertDefaultValue (BlockData
, DefaultData
);
1354 if ((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT_MFG
) == EFI_IFR_OPTION_DEFAULT_MFG
) {
1356 // Set default ID to Manufacture ID and Get DefaultName String ID
1358 VarDefaultId
= EFI_HII_DEFAULT_CLASS_MANUFACTURING
;
1359 Status
= FindDefaultName (DefaultIdArray
, VarDefaultId
, &VarDefaultName
);
1360 if (EFI_ERROR (Status
)) {
1364 // Prepare new DefaultValue
1366 DefaultData
= (IFR_DEFAULT_DATA
*) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
1367 if (DefaultData
== NULL
) {
1368 Status
= EFI_OUT_OF_RESOURCES
;
1371 DefaultData
->DefaultId
= VarDefaultId
;
1372 DefaultData
->DefaultName
= VarDefaultName
;
1373 DefaultData
->Value
= IfrOneOfOption
->Value
.u64
;
1375 // Add DefaultValue into current BlockData
1377 InsertDefaultValue (BlockData
, DefaultData
);
1381 case EFI_IFR_DEFAULT_OP
:
1383 // Update Current BlockData to the default value.
1385 if (BlockData
== NULL
|| BlockData
->Scope
== 0) {
1387 // No matched block data is ignored.
1392 if (BlockData
->OpCode
== EFI_IFR_ORDERED_LIST_OP
) {
1394 // OrderedList Opcode is no default value.
1399 // Get the DefaultId and DefaultName String ID
1401 IfrDefault
= (EFI_IFR_DEFAULT
*) IfrOpHdr
;
1402 VarDefaultId
= IfrDefault
->DefaultId
;
1403 Status
= FindDefaultName (DefaultIdArray
, VarDefaultId
, &VarDefaultName
);
1404 if (EFI_ERROR (Status
)) {
1408 // Prepare new DefaultValue
1410 DefaultData
= (IFR_DEFAULT_DATA
*) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
1411 if (DefaultData
== NULL
) {
1412 Status
= EFI_OUT_OF_RESOURCES
;
1415 DefaultData
->DefaultId
= VarDefaultId
;
1416 DefaultData
->DefaultName
= VarDefaultName
;
1417 DefaultData
->Value
= IfrDefault
->Value
.u64
;
1419 // Add DefaultValue into current BlockData
1421 InsertDefaultValue (BlockData
, DefaultData
);
1423 case EFI_IFR_END_OP
:
1425 // End Opcode is for Var.
1427 if (BlockData
!= NULL
&& BlockData
->Scope
> 0) {
1432 if (BlockData
!= NULL
&& BlockData
->Scope
> 0) {
1433 BlockData
->Scope
= (UINT8
) (BlockData
->Scope
+ IfrOpHdr
->Scope
);
1438 IfrOffset
+= IfrOpHdr
->Length
;
1443 // Set the defualt ID array.
1445 *PIfrDefaultIdArray
= DefaultIdArray
;
1451 This function gets the full request string and full default value string by
1452 parsing IFR data in HII form packages.
1454 When Request points to NULL string, the request string and default value string
1455 for each varstore in form package will return.
1457 @param HiiHandle Hii Handle which Hii Packages are registered.
1458 @param DevicePath Device Path which Hii Config Access Protocol is registered.
1459 @param Request Pointer to a null-terminated Unicode string in
1460 <ConfigRequest> format. When it doesn't contain
1461 any RequestElement, it will be updated to return
1462 the full RequestElement retrieved from IFR data.
1463 If it points to NULL, the request string for the first
1464 varstore in form package will be merged into a
1465 <MultiConfigRequest> format string and return.
1466 @param AltCfgResp Pointer to a null-terminated Unicode string in
1467 <ConfigAltResp> format. When the pointer is to NULL,
1468 the full default value string retrieved from IFR data
1469 will return. When the pinter is to a string, the
1470 full default value string retrieved from IFR data
1471 will be merged into the input string and return.
1472 When Request points to NULL, the default value string
1473 for each varstore in form package will be merged into
1474 a <MultiConfigAltResp> format string and return.
1475 @retval EFI_SUCCESS The Results string is set to the full request string.
1476 And AltCfgResp contains all default value string.
1477 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
1478 @retval EFI_NOT_FOUND The varstore (Guid and Name) in Request string
1479 can't be found in Form package.
1480 @retval EFI_NOT_FOUND HiiPackage can't be got on the input HiiHandle.
1481 @retval EFI_INVALID_PARAMETER *Request points to NULL.
1486 GetFullStringFromHiiFormPackages (
1487 IN EFI_HII_HANDLE HiiHandle
,
1488 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
1489 IN OUT EFI_STRING
*Request
,
1490 IN OUT EFI_STRING
*AltCfgResp
1494 EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
;
1495 UINT32 PackageListLength
;
1497 IFR_BLOCK_DATA
*RequestBlockArray
;
1498 IFR_BLOCK_DATA
*BlockData
;
1499 IFR_BLOCK_DATA
*NextBlockData
;
1500 IFR_DEFAULT_DATA
*DefaultValueData
;
1501 IFR_DEFAULT_DATA
*DefaultId
;
1502 IFR_DEFAULT_DATA
*DefaultIdArray
;
1503 EFI_HII_PACKAGE_HEADER PacakgeHeader
;
1504 UINT32 PackageOffset
;
1505 IFR_VARSTORAGE_DATA
*VarStorageData
;
1506 EFI_STRING DefaultAltCfgResp
;
1507 EFI_STRING FullConfigRequest
;
1508 EFI_STRING ConfigHdr
;
1512 EFI_STRING StringPtr
;
1518 LIST_ENTRY
*LinkData
;
1519 LIST_ENTRY
*LinkDefault
;
1522 // Initialize the local variables.
1524 RequestBlockArray
= NULL
;
1525 VarStorageData
= NULL
;
1526 DefaultAltCfgResp
= NULL
;
1527 FullConfigRequest
= NULL
;
1529 DefaultIdArray
= NULL
;
1535 // 1. Get HiiPackage by HiiHandle
1538 HiiPackageList
= NULL
;
1539 Status
= HiiExportPackageLists (&mPrivate
.HiiDatabase
, HiiHandle
, &BufferSize
, HiiPackageList
);
1542 // The return status should always be EFI_BUFFER_TOO_SMALL as input buffer's size is 0.
1544 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
1548 HiiPackageList
= AllocatePool (BufferSize
);
1549 if (HiiPackageList
== NULL
) {
1550 return EFI_OUT_OF_RESOURCES
;
1554 // Get PackageList on HiiHandle
1556 Status
= HiiExportPackageLists (&mPrivate
.HiiDatabase
, HiiHandle
, &BufferSize
, HiiPackageList
);
1557 if (EFI_ERROR (Status
)) {
1562 // 2. Parse FormPackage to get BlockArray and DefaultId Array for the request BlockArray.
1563 // 1) Request is NULL.
1564 // 2) Request is not NULL. And it doesn't contain any BlockArray.
1565 // 3) Request is not NULL. And it containts BlockArray.
1569 // Initialize VarStorageData to store the var store Block and Default value information.
1571 VarStorageData
= (IFR_VARSTORAGE_DATA
*) AllocateZeroPool (sizeof (IFR_VARSTORAGE_DATA
));
1572 if (VarStorageData
== NULL
) {
1573 Status
= EFI_OUT_OF_RESOURCES
;
1577 InitializeListHead (&VarStorageData
->Entry
);
1578 InitializeListHead (&VarStorageData
->BlockEntry
);
1581 // Gte the request block array by Request String
1584 if (*Request
!= NULL
) {
1585 StringPtr
= StrStr (*Request
, L
"&OFFSET=");
1587 if (StringPtr
!= NULL
) {
1589 // Init RequestBlockArray
1591 RequestBlockArray
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
1592 if (RequestBlockArray
== NULL
) {
1593 Status
= EFI_OUT_OF_RESOURCES
;
1596 InitializeListHead (&RequestBlockArray
->Entry
);
1599 // Get the request Block array from the request string
1604 // Parse each <RequestElement> if exists
1605 // Only <BlockName> format is supported by this help function.
1606 // <BlockName> ::= &'OFFSET='<Number>&'WIDTH='<Number>
1608 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) == 0) {
1610 // Skip the OFFSET string
1612 StringPtr
+= StrLen (L
"&OFFSET=");
1616 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
1617 if (EFI_ERROR (Status
)) {
1624 (((Length
+ 1) / 2) < sizeof (UINT16
)) ? ((Length
+ 1) / 2) : sizeof (UINT16
)
1626 FreePool (TmpBuffer
);
1628 StringPtr
+= Length
;
1629 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
1630 Status
= EFI_INVALID_PARAMETER
;
1633 StringPtr
+= StrLen (L
"&WIDTH=");
1638 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
1639 if (EFI_ERROR (Status
)) {
1646 (((Length
+ 1) / 2) < sizeof (UINT16
)) ? ((Length
+ 1) / 2) : sizeof (UINT16
)
1648 FreePool (TmpBuffer
);
1650 StringPtr
+= Length
;
1651 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
1652 Status
= EFI_INVALID_PARAMETER
;
1659 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
1660 if (BlockData
== NULL
) {
1661 Status
= EFI_OUT_OF_RESOURCES
;
1664 BlockData
->Offset
= Offset
;
1665 BlockData
->Width
= Width
;
1666 InsertBlockData (&RequestBlockArray
->Entry
, &BlockData
);
1669 // If '\0', parsing is finished.
1671 if (*StringPtr
== 0) {
1677 // Merge the requested block data.
1679 Link
= RequestBlockArray
->Entry
.ForwardLink
;
1680 while ((Link
!= &RequestBlockArray
->Entry
) && (Link
->ForwardLink
!= &RequestBlockArray
->Entry
)) {
1681 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
1682 NextBlockData
= BASE_CR (Link
->ForwardLink
, IFR_BLOCK_DATA
, Entry
);
1683 if ((NextBlockData
->Offset
>= BlockData
->Offset
) && (NextBlockData
->Offset
<= (BlockData
->Offset
+ BlockData
->Width
))) {
1684 if ((NextBlockData
->Offset
+ NextBlockData
->Width
) > (BlockData
->Offset
+ BlockData
->Width
)) {
1685 BlockData
->Width
= (UINT16
) (NextBlockData
->Offset
+ NextBlockData
->Width
- BlockData
->Offset
);
1687 RemoveEntryList (Link
->ForwardLink
);
1688 FreePool (NextBlockData
);
1691 Link
= Link
->ForwardLink
;
1696 // Get the form package
1698 PackageOffset
= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
1699 PackageListLength
= ReadUnaligned32 (&HiiPackageList
->PackageLength
);
1700 while (PackageOffset
< PackageListLength
) {
1701 CopyMem (&PacakgeHeader
, (UINT8
*) HiiPackageList
+ PackageOffset
, sizeof (PacakgeHeader
));
1703 if (PacakgeHeader
.Type
== EFI_HII_PACKAGE_FORMS
) {
1705 // Reset VarStorageData
1707 VarStorageData
->Size
= 0;
1708 VarStorageData
->VarStoreId
= 0;
1709 if (VarStorageData
->Name
!= NULL
) {
1710 FreePool (VarStorageData
->Name
);
1711 VarStorageData
->Name
= NULL
;
1715 // Parse the opcode in form package
1717 Status
= ParseIfrData ((UINT8
*) HiiPackageList
+ PackageOffset
, PacakgeHeader
.Length
, *Request
, RequestBlockArray
, VarStorageData
, &DefaultIdArray
);
1718 if (EFI_ERROR (Status
)) {
1723 // Only one form is in a pacakge list.
1728 PackageOffset
+= PacakgeHeader
.Length
;
1732 // No requested varstore in IFR data and directly return
1734 if (VarStorageData
->Size
== 0) {
1739 // 3. Construct Request Element (Block Name) for 2.1 and 2.2 case.
1743 // Construct <ConfigHdr> : "GUID=...&NAME=...&PATH=..." by VarStorageData Guid, Name and DriverHandle
1745 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*) &VarStorageData
->Guid
, 1, &GuidStr
);
1746 GenerateSubStr (L
"NAME=", StrLen (VarStorageData
->Name
) * sizeof (CHAR16
), (VOID
*) VarStorageData
->Name
, 2, &NameStr
);
1749 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) DevicePath
),
1750 (VOID
*) DevicePath
,
1754 Length
= StrLen (GuidStr
);
1755 Length
= Length
+ StrLen (NameStr
);
1756 Length
= Length
+ StrLen (PathStr
) + 1;
1757 ConfigHdr
= AllocateZeroPool (Length
* sizeof (CHAR16
));
1758 if (ConfigHdr
== NULL
) {
1759 Status
= EFI_OUT_OF_RESOURCES
;
1762 StrCpy (ConfigHdr
, GuidStr
);
1763 StrCat (ConfigHdr
, NameStr
);
1764 StrCat (ConfigHdr
, PathStr
);
1767 // Remove the last character L'&'
1769 *(ConfigHdr
+ StrLen (ConfigHdr
) - 1) = L
'\0';
1771 if (RequestBlockArray
== NULL
) {
1773 // Append VarStorageData BlockEntry into *Request string
1774 // Now support only one varstore in a form package.
1778 // Go through all VarStorageData Entry and get BlockEntry for each one for the multiple varstore in a single form package
1779 // Then construct them all to return MultiRequest string : ConfigHdr BlockConfig
1783 // Compute the length of the entire request starting with <ConfigHdr> and a
1786 Length
= StrLen (ConfigHdr
) + 1;
1788 for (Link
= VarStorageData
->BlockEntry
.ForwardLink
; Link
!= &VarStorageData
->BlockEntry
; Link
= Link
->ForwardLink
) {
1790 // Add <BlockName> length for each Offset/Width pair
1792 // <BlockName> ::= &OFFSET=1234&WIDTH=1234
1793 // | 8 | 4 | 7 | 4 |
1795 Length
= Length
+ (8 + 4 + 7 + 4);
1799 // Allocate buffer for the entire <ConfigRequest>
1801 FullConfigRequest
= AllocateZeroPool (Length
* sizeof (CHAR16
));
1802 if (FullConfigRequest
== NULL
) {
1805 StringPtr
= FullConfigRequest
;
1808 // Start with <ConfigHdr>
1810 StrCpy (StringPtr
, ConfigHdr
);
1811 StringPtr
+= StrLen (StringPtr
);
1814 // Loop through all the Offset/Width pairs and append them to ConfigRequest
1816 for (Link
= VarStorageData
->BlockEntry
.ForwardLink
; Link
!= &VarStorageData
->BlockEntry
; Link
= Link
->ForwardLink
) {
1817 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
1819 // Append &OFFSET=XXXX&WIDTH=YYYY\0
1823 (8 + 4 + 7 + 4 + 1) * sizeof (CHAR16
),
1824 L
"&OFFSET=%04X&WIDTH=%04X",
1828 StringPtr
+= StrLen (StringPtr
);
1831 // Set to the got full request string.
1833 HiiToLower (FullConfigRequest
);
1834 if (*Request
!= NULL
) {
1835 FreePool (*Request
);
1837 *Request
= FullConfigRequest
;
1841 // 4. Construct Default Value string in AltResp according to request element.
1842 // Go through all VarStorageData Entry and get the DefaultId array for each one
1843 // Then construct them all to : ConfigHdr AltConfigHdr ConfigBody AltConfigHdr ConfigBody
1847 // Add length for <ConfigHdr> + '\0'
1849 Length
= StrLen (ConfigHdr
) + 1;
1851 for (Link
= DefaultIdArray
->Entry
.ForwardLink
; Link
!= &DefaultIdArray
->Entry
; Link
= Link
->ForwardLink
) {
1852 DefaultId
= BASE_CR (Link
, IFR_DEFAULT_DATA
, Entry
);
1854 // Add length for "&<ConfigHdr>&ALTCFG=XXXX"
1855 // |1| StrLen (ConfigHdr) | 8 | 4 |
1857 Length
+= (1 + StrLen (ConfigHdr
) + 8 + 4);
1859 for (LinkData
= VarStorageData
->BlockEntry
.ForwardLink
; LinkData
!= &VarStorageData
->BlockEntry
; LinkData
= LinkData
->ForwardLink
) {
1860 BlockData
= BASE_CR (LinkData
, IFR_BLOCK_DATA
, Entry
);
1861 for (LinkDefault
= BlockData
->DefaultValueEntry
.ForwardLink
; LinkDefault
!= &BlockData
->DefaultValueEntry
; LinkDefault
= LinkDefault
->ForwardLink
) {
1862 DefaultValueData
= BASE_CR (LinkDefault
, IFR_DEFAULT_DATA
, Entry
);
1863 if (DefaultValueData
->DefaultId
== DefaultId
->DefaultId
) {
1865 // Add length for "&OFFSET=XXXX&WIDTH=YYYY&VALUE=zzzzzzzzzzzz"
1866 // | 8 | 4 | 7 | 4 | 7 | Width * 2 |
1868 Length
+= (8 + 4 + 7 + 4 + 7 + BlockData
->Width
* 2);
1875 // Allocate buffer for the entire <DefaultAltCfgResp>
1877 DefaultAltCfgResp
= AllocateZeroPool (Length
* sizeof (CHAR16
));
1878 if (DefaultAltCfgResp
== NULL
) {
1881 StringPtr
= DefaultAltCfgResp
;
1884 // Start with <ConfigHdr>
1886 StrCpy (StringPtr
, ConfigHdr
);
1887 StringPtr
+= StrLen (StringPtr
);
1889 for (Link
= DefaultIdArray
->Entry
.ForwardLink
; Link
!= &DefaultIdArray
->Entry
; Link
= Link
->ForwardLink
) {
1890 DefaultId
= BASE_CR (Link
, IFR_DEFAULT_DATA
, Entry
);
1892 // Add <AltConfigHdr> of the form "&<ConfigHdr>&ALTCFG=XXXX\0"
1893 // |1| StrLen (ConfigHdr) | 8 | 4 |
1897 (1 + StrLen (ConfigHdr
) + 8 + 4 + 1) * sizeof (CHAR16
),
1900 DefaultId
->DefaultName
1902 StringPtr
+= StrLen (StringPtr
);
1904 for (LinkData
= VarStorageData
->BlockEntry
.ForwardLink
; LinkData
!= &VarStorageData
->BlockEntry
; LinkData
= LinkData
->ForwardLink
) {
1905 BlockData
= BASE_CR (LinkData
, IFR_BLOCK_DATA
, Entry
);
1906 for (LinkDefault
= BlockData
->DefaultValueEntry
.ForwardLink
; LinkDefault
!= &BlockData
->DefaultValueEntry
; LinkDefault
= LinkDefault
->ForwardLink
) {
1907 DefaultValueData
= BASE_CR (LinkDefault
, IFR_DEFAULT_DATA
, Entry
);
1908 if (DefaultValueData
->DefaultId
== DefaultId
->DefaultId
) {
1910 // Add <BlockConfig>
1911 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>
1915 (8 + 4 + 7 + 4 + 7 + 1) * sizeof (CHAR16
),
1916 L
"&OFFSET=%04X&WIDTH=%04X&VALUE=",
1920 StringPtr
+= StrLen (StringPtr
);
1923 // Convert Value to a hex string in "%x" format
1924 // NOTE: This is in the opposite byte that GUID and PATH use
1926 Width
= BlockData
->Width
;
1927 TmpBuffer
= (UINT8
*) &(DefaultValueData
->Value
);
1928 for (; Width
> 0; Width
--) {
1929 StringPtr
+= UnicodeValueToString (StringPtr
, PREFIX_ZERO
| RADIX_HEX
, TmpBuffer
[Width
- 1], 2);
1935 HiiToLower (DefaultAltCfgResp
);
1938 // 5. Merge string into the input AltCfgResp if the iput *AltCfgResp is not NULL.
1940 if (*AltCfgResp
!= NULL
) {
1941 Status
= MergeDefaultString (AltCfgResp
, DefaultAltCfgResp
);
1942 FreePool (DefaultAltCfgResp
);
1944 *AltCfgResp
= DefaultAltCfgResp
;
1948 if (RequestBlockArray
!= NULL
) {
1950 // Free Link Array RequestBlockArray
1952 while (!IsListEmpty (&RequestBlockArray
->Entry
)) {
1953 BlockData
= BASE_CR (RequestBlockArray
->Entry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
1954 RemoveEntryList (&BlockData
->Entry
);
1955 FreePool (BlockData
);
1958 FreePool (RequestBlockArray
);
1961 if (VarStorageData
!= NULL
) {
1963 // Free link array VarStorageData
1965 while (!IsListEmpty (&VarStorageData
->BlockEntry
)) {
1966 BlockData
= BASE_CR (VarStorageData
->BlockEntry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
1967 RemoveEntryList (&BlockData
->Entry
);
1969 // Free default value link array
1971 while (!IsListEmpty (&BlockData
->DefaultValueEntry
)) {
1972 DefaultValueData
= BASE_CR (BlockData
->DefaultValueEntry
.ForwardLink
, IFR_DEFAULT_DATA
, Entry
);
1973 RemoveEntryList (&DefaultValueData
->Entry
);
1974 FreePool (DefaultValueData
);
1976 FreePool (BlockData
);
1978 FreePool (VarStorageData
);
1981 if (DefaultIdArray
!= NULL
) {
1983 // Free DefaultId Array
1985 while (!IsListEmpty (&DefaultIdArray
->Entry
)) {
1986 DefaultId
= BASE_CR (DefaultIdArray
->Entry
.ForwardLink
, IFR_DEFAULT_DATA
, Entry
);
1987 RemoveEntryList (&DefaultId
->Entry
);
1988 FreePool (DefaultId
);
1990 FreePool (DefaultIdArray
);
1994 // Free the allocated string
1996 if (GuidStr
!= NULL
) {
1999 if (NameStr
!= NULL
) {
2002 if (PathStr
!= NULL
) {
2005 if (ConfigHdr
!= NULL
) {
2006 FreePool (ConfigHdr
);
2010 // Free Pacakge data
2012 if (HiiPackageList
!= NULL
) {
2013 FreePool (HiiPackageList
);
2020 This function allows a caller to extract the current configuration
2021 for one or more named elements from one or more drivers.
2023 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
2025 @param Request A null-terminated Unicode string in
2026 <MultiConfigRequest> format.
2027 @param Progress On return, points to a character in the Request
2028 string. Points to the string's null terminator if
2029 request was successful. Points to the most recent
2030 & before the first failing name / value pair (or
2031 the beginning of the string if the failure is in
2032 the first name / value pair) if the request was
2034 @param Results Null-terminated Unicode string in
2035 <MultiConfigAltResp> format which has all values
2036 filled in for the names in the Request string.
2037 String to be allocated by the called function.
2039 @retval EFI_SUCCESS The Results string is filled with the values
2040 corresponding to all requested names.
2041 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
2042 results that must be stored awaiting possible
2044 @retval EFI_NOT_FOUND Routing data doesn't match any known driver.
2045 Progress set to the "G" in "GUID" of the routing
2046 header that doesn't match. Note: There is no
2047 requirement that all routing data be validated
2048 before any configuration extraction.
2049 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Request
2050 parameter would result in this type of error. The
2051 Progress parameter is set to NULL.
2052 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set to most recent &
2053 before the error or the beginning of the string.
2054 @retval EFI_INVALID_PARAMETER Unknown name. Progress points to the & before the
2060 HiiConfigRoutingExtractConfig (
2061 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
2062 IN CONST EFI_STRING Request
,
2063 OUT EFI_STRING
*Progress
,
2064 OUT EFI_STRING
*Results
2067 HII_DATABASE_PRIVATE_DATA
*Private
;
2068 EFI_STRING StringPtr
;
2069 EFI_STRING ConfigRequest
;
2071 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
2072 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
2075 HII_DATABASE_RECORD
*Database
;
2076 UINT8
*DevicePathPkg
;
2077 UINT8
*CurrentDevicePath
;
2078 EFI_HANDLE DriverHandle
;
2079 EFI_HII_HANDLE HiiHandle
;
2080 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
2081 EFI_STRING AccessProgress
;
2082 EFI_STRING AccessResults
;
2083 EFI_STRING DefaultResults
;
2084 BOOLEAN FirstElement
;
2085 UINTN DevicePathLength
;
2087 if (This
== NULL
|| Progress
== NULL
|| Results
== NULL
) {
2088 return EFI_INVALID_PARAMETER
;
2091 if (Request
== NULL
) {
2093 return EFI_INVALID_PARAMETER
;
2096 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
2097 StringPtr
= Request
;
2098 *Progress
= StringPtr
;
2099 DefaultResults
= NULL
;
2100 ConfigRequest
= NULL
;
2101 Status
= EFI_SUCCESS
;
2102 AccessResults
= NULL
;
2106 // The first element of <MultiConfigRequest> should be
2107 // <GuidHdr>, which is in 'GUID='<Guid> syntax.
2109 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
2110 return EFI_INVALID_PARAMETER
;
2113 FirstElement
= TRUE
;
2116 // Allocate a fix length of memory to store Results. Reallocate memory for
2117 // Results if this fix length is insufficient.
2119 *Results
= (EFI_STRING
) AllocateZeroPool (MAX_STRING_LENGTH
);
2120 if (*Results
== NULL
) {
2121 return EFI_OUT_OF_RESOURCES
;
2124 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) == 0) {
2126 // If parsing error, set Progress to the beginning of the <MultiConfigRequest>
2127 // or most recent & before the error.
2129 if (StringPtr
== Request
) {
2130 *Progress
= StringPtr
;
2132 *Progress
= StringPtr
- 1;
2136 // Process each <ConfigRequest> of <MultiConfigRequest>
2138 Length
= CalculateConfigStringLen (StringPtr
);
2139 ConfigRequest
= AllocateCopyPool ((Length
+ 1) * sizeof (CHAR16
), StringPtr
);
2140 if (ConfigRequest
== NULL
) {
2141 Status
= EFI_OUT_OF_RESOURCES
;
2144 *(ConfigRequest
+ Length
) = 0;
2147 // Get the UEFI device path
2149 Status
= GetDevicePath (ConfigRequest
, (UINT8
**) &DevicePath
);
2150 if (EFI_ERROR (Status
)) {
2155 // Find driver which matches the routing data.
2157 DriverHandle
= NULL
;
2159 DevicePathLength
= GetDevicePathSize (DevicePath
);
2160 for (Link
= Private
->DatabaseList
.ForwardLink
;
2161 Link
!= &Private
->DatabaseList
;
2162 Link
= Link
->ForwardLink
2164 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
2166 if ((DevicePathPkg
= Database
->PackageList
->DevicePathPkg
) != NULL
) {
2167 CurrentDevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
2168 if ((DevicePathLength
== GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) CurrentDevicePath
)) &&
2174 DriverHandle
= Database
->DriverHandle
;
2175 HiiHandle
= Database
->Handle
;
2182 // Try to find driver handle by device path.
2184 if (DriverHandle
== NULL
) {
2185 TempDevicePath
= DevicePath
;
2186 Status
= gBS
->LocateDevicePath (
2187 &gEfiDevicePathProtocolGuid
,
2191 if (EFI_ERROR (Status
) || (DriverHandle
== NULL
)) {
2193 // Routing data does not match any known driver.
2194 // Set Progress to the 'G' in "GUID" of the routing header.
2196 *Progress
= StringPtr
;
2197 Status
= EFI_NOT_FOUND
;
2203 // Check whether ConfigRequest contains request string OFFSET/WIDTH
2205 if ((HiiHandle
!= NULL
) && (StrStr (ConfigRequest
, L
"&OFFSET=") == NULL
)) {
2207 // Get the full request string from IFR when HiiPackage is registered to HiiHandle
2209 Status
= GetFullStringFromHiiFormPackages (HiiHandle
, DevicePath
, &ConfigRequest
, &DefaultResults
);
2210 if (EFI_ERROR (Status
)) {
2214 // Not any request block is found.
2216 if (StrStr (ConfigRequest
, L
"&OFFSET=") == NULL
) {
2217 AccessResults
= AllocateCopyPool (StrSize (ConfigRequest
), ConfigRequest
);
2218 goto NextConfigString
;
2223 // Call corresponding ConfigAccess protocol to extract settings
2225 Status
= gBS
->HandleProtocol (
2227 &gEfiHiiConfigAccessProtocolGuid
,
2228 (VOID
**) &ConfigAccess
2230 ASSERT_EFI_ERROR (Status
);
2232 Status
= ConfigAccess
->ExtractConfig (
2238 if (EFI_ERROR (Status
)) {
2240 // AccessProgress indicates the parsing progress on <ConfigRequest>.
2241 // Map it to the progress on <MultiConfigRequest> then return it.
2243 *Progress
= StrStr (StringPtr
, AccessProgress
);
2248 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'
2249 // which seperates the first <ConfigAltResp> and the following ones.
2251 ASSERT (*AccessProgress
== 0);
2254 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
2256 if (HiiHandle
!= NULL
) {
2257 if (DefaultResults
== NULL
) {
2258 Status
= GetFullStringFromHiiFormPackages (HiiHandle
, DevicePath
, &ConfigRequest
, &AccessResults
);
2260 Status
= MergeDefaultString (&AccessResults
, DefaultResults
);
2263 FreePool (DevicePath
);
2266 if (EFI_ERROR (Status
)) {
2271 // Free the allocated memory.
2273 if (DefaultResults
!= NULL
) {
2274 FreePool (DefaultResults
);
2275 DefaultResults
= NULL
;
2279 if (!FirstElement
) {
2280 Status
= AppendToMultiString (Results
, L
"&");
2281 ASSERT_EFI_ERROR (Status
);
2284 Status
= AppendToMultiString (Results
, AccessResults
);
2285 ASSERT_EFI_ERROR (Status
);
2287 FirstElement
= FALSE
;
2289 FreePool (AccessResults
);
2290 AccessResults
= NULL
;
2291 FreePool (ConfigRequest
);
2292 ConfigRequest
= NULL
;
2295 // Go to next <ConfigRequest> (skip '&').
2297 StringPtr
+= Length
;
2298 if (*StringPtr
== 0) {
2299 *Progress
= StringPtr
;
2307 if (EFI_ERROR (Status
)) {
2308 FreePool (*Results
);
2312 if (ConfigRequest
!= NULL
) {
2313 FreePool (ConfigRequest
);
2316 if (AccessResults
!= NULL
) {
2317 FreePool (AccessResults
);
2320 if (DefaultResults
!= NULL
) {
2321 FreePool (DefaultResults
);
2324 if (DevicePath
!= NULL
) {
2325 FreePool (DevicePath
);
2333 This function allows the caller to request the current configuration for the
2334 entirety of the current HII database and returns the data in a
2335 null-terminated Unicode string.
2337 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
2339 @param Results Null-terminated Unicode string in
2340 <MultiConfigAltResp> format which has all values
2341 filled in for the names in the Request string.
2342 String to be allocated by the called function.
2343 De-allocation is up to the caller.
2345 @retval EFI_SUCCESS The Results string is filled with the values
2346 corresponding to all requested names.
2347 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
2348 results that must be stored awaiting possible
2350 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Results
2351 parameter would result in this type of error.
2356 HiiConfigRoutingExportConfig (
2357 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
2358 OUT EFI_STRING
*Results
2362 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
2363 EFI_STRING AccessResults
;
2364 EFI_STRING Progress
;
2365 EFI_STRING ConfigRequest
;
2367 EFI_HANDLE
*ConfigAccessHandles
;
2368 UINTN NumberConfigAccessHandles
;
2369 BOOLEAN FirstElement
;
2370 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
2371 EFI_HII_HANDLE HiiHandle
;
2372 EFI_STRING DefaultResults
;
2373 HII_DATABASE_PRIVATE_DATA
*Private
;
2375 HII_DATABASE_RECORD
*Database
;
2376 UINT8
*DevicePathPkg
;
2377 UINT8
*CurrentDevicePath
;
2378 UINTN DevicePathLength
;
2380 if (This
== NULL
|| Results
== NULL
) {
2381 return EFI_INVALID_PARAMETER
;
2384 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
2387 // Allocate a fix length of memory to store Results. Reallocate memory for
2388 // Results if this fix length is insufficient.
2390 *Results
= (EFI_STRING
) AllocateZeroPool (MAX_STRING_LENGTH
);
2391 if (*Results
== NULL
) {
2392 return EFI_OUT_OF_RESOURCES
;
2395 NumberConfigAccessHandles
= 0;
2396 Status
= gBS
->LocateHandleBuffer (
2398 &gEfiHiiConfigAccessProtocolGuid
,
2400 &NumberConfigAccessHandles
,
2401 &ConfigAccessHandles
2403 if (EFI_ERROR (Status
)) {
2407 FirstElement
= TRUE
;
2409 for (Index
= 0; Index
< NumberConfigAccessHandles
; Index
++) {
2410 Status
= gBS
->HandleProtocol (
2411 ConfigAccessHandles
[Index
],
2412 &gEfiHiiConfigAccessProtocolGuid
,
2413 (VOID
**) &ConfigAccess
2415 if (EFI_ERROR (Status
)) {
2420 // Get DevicePath and HiiHandle for this ConfigAccess driver handle
2424 ConfigRequest
= NULL
;
2425 DefaultResults
= NULL
;
2426 DevicePath
= DevicePathFromHandle (ConfigAccessHandles
[Index
]);
2427 DevicePathLength
= GetDevicePathSize (DevicePath
);
2428 if (DevicePath
!= NULL
) {
2429 for (Link
= Private
->DatabaseList
.ForwardLink
;
2430 Link
!= &Private
->DatabaseList
;
2431 Link
= Link
->ForwardLink
2433 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
2434 if ((DevicePathPkg
= Database
->PackageList
->DevicePathPkg
) != NULL
) {
2435 CurrentDevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
2436 if ((DevicePathLength
== GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) CurrentDevicePath
)) &&
2442 HiiHandle
= Database
->Handle
;
2450 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
2452 if (HiiHandle
!= NULL
&& DevicePath
!= NULL
) {
2453 Status
= GetFullStringFromHiiFormPackages (HiiHandle
, DevicePath
, &ConfigRequest
, &DefaultResults
);
2456 // Can't parse IFR data to get the request string and default string.
2458 if (EFI_ERROR (Status
)) {
2459 ConfigRequest
= NULL
;
2460 DefaultResults
= NULL
;
2463 Status
= ConfigAccess
->ExtractConfig (
2469 if (!EFI_ERROR (Status
)) {
2471 // Merge the default sting from IFR code into the got setting from driver.
2473 if (DefaultResults
!= NULL
) {
2474 MergeDefaultString (&AccessResults
, DefaultResults
);
2475 FreePool (DefaultResults
);
2479 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'
2480 // which seperates the first <ConfigAltResp> and the following ones.
2482 if (!FirstElement
) {
2483 Status
= AppendToMultiString (Results
, L
"&");
2484 ASSERT_EFI_ERROR (Status
);
2487 Status
= AppendToMultiString (Results
, AccessResults
);
2488 ASSERT_EFI_ERROR (Status
);
2490 FirstElement
= FALSE
;
2492 FreePool (AccessResults
);
2493 AccessResults
= NULL
;
2496 FreePool (ConfigAccessHandles
);
2503 This function processes the results of processing forms and routes it to the
2504 appropriate handlers or storage.
2506 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
2508 @param Configuration A null-terminated Unicode string in
2509 <MulltiConfigResp> format.
2510 @param Progress A pointer to a string filled in with the offset of
2511 the most recent & before the first failing name /
2512 value pair (or the beginning of the string if the
2513 failure is in the first name / value pair) or the
2514 terminating NULL if all was successful.
2516 @retval EFI_SUCCESS The results have been distributed or are awaiting
2518 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
2519 results that must be stored awaiting possible
2521 @retval EFI_INVALID_PARAMETER Passing in a NULL for the Configuration parameter
2522 would result in this type of error.
2523 @retval EFI_NOT_FOUND Target for the specified routing data was not
2529 HiiConfigRoutingRouteConfig (
2530 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
2531 IN CONST EFI_STRING Configuration
,
2532 OUT EFI_STRING
*Progress
2535 HII_DATABASE_PRIVATE_DATA
*Private
;
2536 EFI_STRING StringPtr
;
2537 EFI_STRING ConfigResp
;
2540 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
2541 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
2543 HII_DATABASE_RECORD
*Database
;
2544 UINT8
*DevicePathPkg
;
2545 UINT8
*CurrentDevicePath
;
2546 EFI_HANDLE DriverHandle
;
2547 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
2548 EFI_STRING AccessProgress
;
2549 UINTN DevicePathLength
;
2551 if (This
== NULL
|| Progress
== NULL
) {
2552 return EFI_INVALID_PARAMETER
;
2555 if (Configuration
== NULL
) {
2557 return EFI_INVALID_PARAMETER
;
2560 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
2561 StringPtr
= Configuration
;
2562 *Progress
= StringPtr
;
2565 // The first element of <MultiConfigResp> should be
2566 // <GuidHdr>, which is in 'GUID='<Guid> syntax.
2568 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
2569 return EFI_INVALID_PARAMETER
;
2572 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) == 0) {
2574 // If parsing error, set Progress to the beginning of the <MultiConfigResp>
2575 // or most recent & before the error.
2577 if (StringPtr
== Configuration
) {
2578 *Progress
= StringPtr
;
2580 *Progress
= StringPtr
- 1;
2584 // Process each <ConfigResp> of <MultiConfigResp>
2586 Length
= CalculateConfigStringLen (StringPtr
);
2587 ConfigResp
= AllocateCopyPool ((Length
+ 1) * sizeof (CHAR16
), StringPtr
);
2588 if (ConfigResp
== NULL
) {
2589 return EFI_OUT_OF_RESOURCES
;
2592 // Append '\0' to the end of ConfigRequest
2594 *(ConfigResp
+ Length
) = 0;
2597 // Get the UEFI device path
2599 Status
= GetDevicePath (ConfigResp
, (UINT8
**) &DevicePath
);
2600 if (EFI_ERROR (Status
)) {
2601 FreePool (ConfigResp
);
2606 // Find driver which matches the routing data.
2608 DriverHandle
= NULL
;
2609 DevicePathLength
= GetDevicePathSize (DevicePath
);
2610 for (Link
= Private
->DatabaseList
.ForwardLink
;
2611 Link
!= &Private
->DatabaseList
;
2612 Link
= Link
->ForwardLink
2614 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
2616 if ((DevicePathPkg
= Database
->PackageList
->DevicePathPkg
) != NULL
) {
2617 CurrentDevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
2618 if ((DevicePathLength
== GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) CurrentDevicePath
)) &&
2624 DriverHandle
= Database
->DriverHandle
;
2631 // Try to find driver handle by device path.
2633 if (DriverHandle
== NULL
) {
2634 TempDevicePath
= DevicePath
;
2635 Status
= gBS
->LocateDevicePath (
2636 &gEfiDevicePathProtocolGuid
,
2640 if (EFI_ERROR (Status
) || (DriverHandle
== NULL
)) {
2642 // Routing data does not match any known driver.
2643 // Set Progress to the 'G' in "GUID" of the routing header.
2645 FreePool (DevicePath
);
2646 *Progress
= StringPtr
;
2647 FreePool (ConfigResp
);
2648 return EFI_NOT_FOUND
;
2652 FreePool (DevicePath
);
2655 // Call corresponding ConfigAccess protocol to route settings
2657 Status
= gBS
->HandleProtocol (
2659 &gEfiHiiConfigAccessProtocolGuid
,
2660 (VOID
**) &ConfigAccess
2662 ASSERT_EFI_ERROR (Status
);
2664 Status
= ConfigAccess
->RouteConfig (
2670 if (EFI_ERROR (Status
)) {
2672 // AccessProgress indicates the parsing progress on <ConfigResp>.
2673 // Map it to the progress on <MultiConfigResp> then return it.
2675 *Progress
= StrStr (StringPtr
, AccessProgress
);
2677 FreePool (ConfigResp
);
2681 FreePool (ConfigResp
);
2685 // Go to next <ConfigResp> (skip '&').
2687 StringPtr
+= Length
;
2688 if (*StringPtr
== 0) {
2689 *Progress
= StringPtr
;
2702 This helper function is to be called by drivers to map configuration data
2703 stored in byte array ("block") formats such as UEFI Variables into current
2704 configuration strings.
2706 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
2708 @param ConfigRequest A null-terminated Unicode string in
2709 <ConfigRequest> format.
2710 @param Block Array of bytes defining the block's configuration.
2711 @param BlockSize Length in bytes of Block.
2712 @param Config Filled-in configuration string. String allocated
2713 by the function. Returned only if call is
2714 successful. It is <ConfigResp> string format.
2715 @param Progress A pointer to a string filled in with the offset of
2716 the most recent & before the first failing
2717 name/value pair (or the beginning of the string if
2718 the failure is in the first name / value pair) or
2719 the terminating NULL if all was successful.
2721 @retval EFI_SUCCESS The request succeeded. Progress points to the null
2722 terminator at the end of the ConfigRequest
2724 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress
2725 points to the first character of ConfigRequest.
2726 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigRequest or
2727 Block parameter would result in this type of
2728 error. Progress points to the first character of
2730 @retval EFI_DEVICE_ERROR Block not large enough. Progress undefined.
2731 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted string.
2732 Block is left updated and Progress points at
2733 the "&" preceding the first non-<BlockName>.
2739 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
2740 IN CONST EFI_STRING ConfigRequest
,
2741 IN CONST UINT8
*Block
,
2742 IN CONST UINTN BlockSize
,
2743 OUT EFI_STRING
*Config
,
2744 OUT EFI_STRING
*Progress
2747 HII_DATABASE_PRIVATE_DATA
*Private
;
2748 EFI_STRING StringPtr
;
2756 EFI_STRING ValueStr
;
2757 EFI_STRING ConfigElement
;
2762 if (This
== NULL
|| Progress
== NULL
|| Config
== NULL
) {
2763 return EFI_INVALID_PARAMETER
;
2766 if (Block
== NULL
|| ConfigRequest
== NULL
) {
2767 *Progress
= ConfigRequest
;
2768 return EFI_INVALID_PARAMETER
;
2772 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
2773 ASSERT (Private
!= NULL
);
2775 StringPtr
= ConfigRequest
;
2778 ConfigElement
= NULL
;
2781 // Allocate a fix length of memory to store Results. Reallocate memory for
2782 // Results if this fix length is insufficient.
2784 *Config
= (EFI_STRING
) AllocateZeroPool (MAX_STRING_LENGTH
);
2785 if (*Config
== NULL
) {
2786 return EFI_OUT_OF_RESOURCES
;
2792 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
2793 *Progress
= StringPtr
;
2794 Status
= EFI_INVALID_PARAMETER
;
2797 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"PATH=", StrLen (L
"PATH=")) != 0) {
2800 if (*StringPtr
== 0) {
2801 *Progress
= StringPtr
- 1;
2802 Status
= EFI_INVALID_PARAMETER
;
2806 while (*StringPtr
!= L
'&' && *StringPtr
!= 0) {
2809 if (*StringPtr
== 0) {
2810 *Progress
= StringPtr
- 1;
2811 Status
= EFI_INVALID_PARAMETER
;
2820 // Copy <ConfigHdr> and an additional '&' to <ConfigResp>
2822 Length
= StringPtr
- ConfigRequest
;
2823 CopyMem (*Config
, ConfigRequest
, Length
* sizeof (CHAR16
));
2826 // Parse each <RequestElement> if exists
2827 // Only <BlockName> format is supported by this help function.
2828 // <BlockName> ::= 'OFFSET='<Number>&'WIDTH='<Number>
2830 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"OFFSET=", StrLen (L
"OFFSET=")) == 0) {
2832 // Back up the header of one <BlockName>
2836 StringPtr
+= StrLen (L
"OFFSET=");
2840 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
2841 if (Status
== EFI_OUT_OF_RESOURCES
) {
2842 *Progress
= ConfigRequest
;
2849 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
2851 FreePool (TmpBuffer
);
2853 StringPtr
+= Length
;
2854 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
2855 *Progress
= StringPtr
- Length
- StrLen (L
"OFFSET=") - 1;
2856 Status
= EFI_INVALID_PARAMETER
;
2859 StringPtr
+= StrLen (L
"&WIDTH=");
2864 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
2865 if (Status
== EFI_OUT_OF_RESOURCES
) {
2866 *Progress
= ConfigRequest
;
2873 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
2875 FreePool (TmpBuffer
);
2877 StringPtr
+= Length
;
2878 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
2879 *Progress
= StringPtr
- Length
- StrLen (L
"&WIDTH=");
2880 Status
= EFI_INVALID_PARAMETER
;
2885 // Calculate Value and convert it to hex string.
2887 if (Offset
+ Width
> BlockSize
) {
2888 *Progress
= StringPtr
;
2889 Status
= EFI_DEVICE_ERROR
;
2893 Value
= (UINT8
*) AllocateZeroPool (Width
);
2894 if (Value
== NULL
) {
2895 *Progress
= ConfigRequest
;
2896 Status
= EFI_OUT_OF_RESOURCES
;
2900 CopyMem (Value
, (UINT8
*) Block
+ Offset
, Width
);
2902 Length
= Width
* 2 + 1;
2903 ValueStr
= (EFI_STRING
) AllocateZeroPool (Length
* sizeof (CHAR16
));
2904 if (ValueStr
== NULL
) {
2905 *Progress
= ConfigRequest
;
2906 Status
= EFI_OUT_OF_RESOURCES
;
2910 TemString
= ValueStr
;
2911 TemBuffer
= Value
+ Width
- 1;
2912 for (Index
= 0; Index
< Width
; Index
++, TemBuffer
--) {
2913 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
2920 // Build a ConfigElement
2922 Length
+= StringPtr
- TmpPtr
+ 1 + StrLen (L
"VALUE=");
2923 ConfigElement
= (EFI_STRING
) AllocateZeroPool (Length
* sizeof (CHAR16
));
2924 if (ConfigElement
== NULL
) {
2925 Status
= EFI_OUT_OF_RESOURCES
;
2928 CopyMem (ConfigElement
, TmpPtr
, (StringPtr
- TmpPtr
+ 1) * sizeof (CHAR16
));
2929 if (*StringPtr
== 0) {
2930 *(ConfigElement
+ (StringPtr
- TmpPtr
)) = L
'&';
2932 *(ConfigElement
+ (StringPtr
- TmpPtr
) + 1) = 0;
2933 StrCat (ConfigElement
, L
"VALUE=");
2934 StrCat (ConfigElement
, ValueStr
);
2936 AppendToMultiString (Config
, ConfigElement
);
2938 FreePool (ConfigElement
);
2939 FreePool (ValueStr
);
2940 ConfigElement
= NULL
;
2944 // If '\0', parsing is finished. Otherwise skip '&' to continue
2946 if (*StringPtr
== 0) {
2949 AppendToMultiString (Config
, L
"&");
2954 if (*StringPtr
!= 0) {
2955 *Progress
= StringPtr
- 1;
2956 Status
= EFI_INVALID_PARAMETER
;
2960 HiiToLower (*Config
);
2961 *Progress
= StringPtr
;
2965 if (*Config
!= NULL
) {
2969 if (ValueStr
!= NULL
) {
2970 FreePool (ValueStr
);
2972 if (Value
!= NULL
) {
2975 if (ConfigElement
!= NULL
) {
2976 FreePool (ConfigElement
);
2985 This helper function is to be called by drivers to map configuration strings
2986 to configurations stored in byte array ("block") formats such as UEFI Variables.
2988 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
2990 @param ConfigResp A null-terminated Unicode string in <ConfigResp>
2991 format. It can be ConfigAltResp format string.
2992 @param Block A possibly null array of bytes representing the
2993 current block. Only bytes referenced in the
2994 ConfigResp string in the block are modified. If
2995 this parameter is null or if the *BlockSize
2996 parameter is (on input) shorter than required by
2997 the Configuration string, only the BlockSize
2998 parameter is updated and an appropriate status
2999 (see below) is returned.
3000 @param BlockSize The length of the Block in units of UINT8. On
3001 input, this is the size of the Block. On output,
3002 if successful, contains the index of the last
3003 modified byte in the Block.
3004 @param Progress On return, points to an element of the ConfigResp
3005 string filled in with the offset of the most
3006 recent '&' before the first failing name / value
3007 pair (or the beginning of the string if the
3008 failure is in the first name / value pair) or the
3009 terminating NULL if all was successful.
3011 @retval EFI_SUCCESS The request succeeded. Progress points to the null
3012 terminator at the end of the ConfigResp string.
3013 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress
3014 points to the first character of ConfigResp.
3015 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigResp or
3016 Block parameter would result in this type of
3017 error. Progress points to the first character of
3019 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted name /
3020 value pair. Block is left updated and
3021 Progress points at the '&' preceding the first
3028 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
3029 IN CONST EFI_STRING ConfigResp
,
3030 IN OUT UINT8
*Block
,
3031 IN OUT UINTN
*BlockSize
,
3032 OUT EFI_STRING
*Progress
3035 HII_DATABASE_PRIVATE_DATA
*Private
;
3036 EFI_STRING StringPtr
;
3045 if (This
== NULL
|| BlockSize
== NULL
|| Progress
== NULL
) {
3046 return EFI_INVALID_PARAMETER
;
3049 if (ConfigResp
== NULL
|| Block
== NULL
) {
3050 *Progress
= ConfigResp
;
3051 return EFI_INVALID_PARAMETER
;
3054 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
3055 ASSERT (Private
!= NULL
);
3057 StringPtr
= ConfigResp
;
3058 BufferSize
= *BlockSize
;
3064 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
3065 *Progress
= StringPtr
;
3066 Status
= EFI_INVALID_PARAMETER
;
3069 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"PATH=", StrLen (L
"PATH=")) != 0) {
3072 if (*StringPtr
== 0) {
3073 *Progress
= StringPtr
;
3074 Status
= EFI_INVALID_PARAMETER
;
3078 while (*StringPtr
!= L
'&' && *StringPtr
!= 0) {
3081 if (*StringPtr
== 0) {
3082 *Progress
= StringPtr
;
3083 Status
= EFI_INVALID_PARAMETER
;
3092 // Parse each <ConfigElement> if exists
3093 // Only <BlockConfig> format is supported by this help function.
3094 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE='<Number>
3096 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"OFFSET=", StrLen (L
"OFFSET=")) == 0) {
3097 StringPtr
+= StrLen (L
"OFFSET=");
3101 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
3102 if (EFI_ERROR (Status
)) {
3103 *Progress
= ConfigResp
;
3110 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
3112 FreePool (TmpBuffer
);
3114 StringPtr
+= Length
;
3115 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
3116 *Progress
= StringPtr
- Length
- StrLen (L
"OFFSET=") - 1;
3117 Status
= EFI_INVALID_PARAMETER
;
3120 StringPtr
+= StrLen (L
"&WIDTH=");
3125 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
3126 if (Status
== EFI_OUT_OF_RESOURCES
) {
3127 *Progress
= ConfigResp
;
3134 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
3136 FreePool (TmpBuffer
);
3138 StringPtr
+= Length
;
3139 if (StrnCmp (StringPtr
, L
"&VALUE=", StrLen (L
"&VALUE=")) != 0) {
3140 *Progress
= StringPtr
- Length
- StrLen (L
"&WIDTH=");
3141 Status
= EFI_INVALID_PARAMETER
;
3144 StringPtr
+= StrLen (L
"&VALUE=");
3149 Status
= GetValueOfNumber (StringPtr
, &Value
, &Length
);
3150 if (EFI_ERROR (Status
)) {
3151 *Progress
= ConfigResp
;
3155 StringPtr
+= Length
;
3156 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
3157 *Progress
= StringPtr
- Length
- 7;
3158 Status
= EFI_INVALID_PARAMETER
;
3163 // Update the Block with configuration info
3166 if (Offset
+ Width
> BufferSize
) {
3167 return EFI_DEVICE_ERROR
;
3170 CopyMem (Block
+ Offset
, Value
, Width
);
3171 *BlockSize
= Offset
+ Width
- 1;
3177 // If '\0', parsing is finished. Otherwise skip '&' to continue
3179 if (*StringPtr
== 0) {
3187 // The input string is ConfigAltResp format.
3189 if ((*StringPtr
!= 0) && (StrnCmp (StringPtr
, L
"&GUID=", StrLen (L
"&GUID=")) != 0)) {
3190 *Progress
= StringPtr
- 1;
3191 Status
= EFI_INVALID_PARAMETER
;
3195 *Progress
= StringPtr
;
3200 if (Value
!= NULL
) {
3208 This helper function is to be called by drivers to extract portions of
3209 a larger configuration string.
3211 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
3213 @param Configuration A null-terminated Unicode string in
3214 <MultiConfigAltResp> format. It is <ConfigAltResp> format.
3215 @param Guid A pointer to the GUID value to search for in the
3216 routing portion of the ConfigResp string when
3217 retrieving the requested data. If Guid is NULL,
3218 then all GUID values will be searched for.
3219 @param Name A pointer to the NAME value to search for in the
3220 routing portion of the ConfigResp string when
3221 retrieving the requested data. If Name is NULL,
3222 then all Name values will be searched for.
3223 @param DevicePath A pointer to the PATH value to search for in the
3224 routing portion of the ConfigResp string when
3225 retrieving the requested data. If DevicePath is
3226 NULL, then all DevicePath values will be searched
3228 @param AltCfgId A pointer to the ALTCFG value to search for in the
3229 routing portion of the ConfigResp string when
3230 retrieving the requested data. If this parameter
3231 is NULL, then the current setting will be
3233 @param AltCfgResp A pointer to a buffer which will be allocated by
3234 the function which contains the retrieved string
3235 as requested. This buffer is only allocated if
3236 the call was successful. It is <ConfigResp> format.
3238 @retval EFI_SUCCESS The request succeeded. The requested data was
3239 extracted and placed in the newly allocated
3241 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate AltCfgResp.
3242 @retval EFI_INVALID_PARAMETER Any parameter is invalid.
3243 @retval EFI_NOT_FOUND Target for the specified routing data was not
3250 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
3251 IN CONST EFI_STRING Configuration
,
3252 IN CONST EFI_GUID
*Guid
,
3253 IN CONST EFI_STRING Name
,
3254 IN CONST EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
3255 IN CONST UINT16
*AltCfgId
,
3256 OUT EFI_STRING
*AltCfgResp
3260 EFI_STRING StringPtr
;
3261 EFI_STRING HdrStart
;
3268 EFI_STRING AltIdStr
;
3285 if (This
== NULL
|| Configuration
== NULL
|| AltCfgResp
== NULL
) {
3286 return EFI_INVALID_PARAMETER
;
3289 StringPtr
= Configuration
;
3290 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
3291 return EFI_INVALID_PARAMETER
;
3295 // Generate the sub string for later matching.
3297 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*) Guid
, 1, &GuidStr
);
3300 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) DevicePath
),
3301 (VOID
*) DevicePath
,
3305 if (AltCfgId
!= NULL
) {
3306 GenerateSubStr (L
"ALTCFG=", sizeof (UINT16
), (VOID
*) AltCfgId
, 3, &AltIdStr
);
3309 GenerateSubStr (L
"NAME=", StrLen (Name
) * sizeof (CHAR16
), (VOID
*) Name
, 2, &NameStr
);
3311 GenerateSubStr (L
"NAME=", 0, NULL
, 2, &NameStr
);
3314 while (*StringPtr
!= 0) {
3316 // Try to match the GUID
3319 TmpPtr
= StrStr (StringPtr
, GuidStr
);
3320 if (TmpPtr
== NULL
) {
3321 Status
= EFI_NOT_FOUND
;
3327 // Jump to <NameHdr>
3330 StringPtr
= TmpPtr
+ StrLen (GuidStr
);
3332 StringPtr
= StrStr (TmpPtr
, L
"NAME=");
3333 if (StringPtr
== NULL
) {
3334 Status
= EFI_NOT_FOUND
;
3342 // Try to match the NAME
3344 if (GuidFlag
&& !NameFlag
) {
3345 if (StrnCmp (StringPtr
, NameStr
, StrLen (NameStr
)) != 0) {
3349 // Jump to <PathHdr>
3352 StringPtr
+= StrLen (NameStr
);
3354 StringPtr
= StrStr (StringPtr
, L
"PATH=");
3355 if (StringPtr
== NULL
) {
3356 Status
= EFI_NOT_FOUND
;
3365 // Try to match the DevicePath
3367 if (GuidFlag
&& NameFlag
&& !PathFlag
) {
3368 if (StrnCmp (StringPtr
, PathStr
, StrLen (PathStr
)) != 0) {
3373 // Jump to '&' before <DescHdr> or <ConfigBody>
3375 if (DevicePath
!= NULL
) {
3376 StringPtr
+= StrLen (PathStr
);
3378 StringPtr
= StrStr (StringPtr
, L
"&");
3379 if (StringPtr
== NULL
) {
3380 Status
= EFI_NOT_FOUND
;
3391 // Try to match the AltCfgId
3393 if (GuidFlag
&& NameFlag
&& PathFlag
) {
3394 if (AltCfgId
== NULL
) {
3396 // Return Current Setting when AltCfgId is NULL.
3398 Status
= OutputConfigBody (StringPtr
, &Result
);
3402 // Search the <ConfigAltResp> to get the <AltResp> with AltCfgId.
3404 if (StrnCmp (StringPtr
, AltIdStr
, StrLen (AltIdStr
)) != 0) {
3410 // Skip AltIdStr and &
3412 StringPtr
= StringPtr
+ StrLen (AltIdStr
);
3413 Status
= OutputConfigBody (StringPtr
, &Result
);
3419 Status
= EFI_NOT_FOUND
;
3423 if (!EFI_ERROR (Status
) && (Result
!= NULL
)) {
3425 // Copy the <ConfigHdr> and <ConfigBody>
3427 Length
= HdrEnd
- HdrStart
+ StrLen (Result
) + 1;
3428 *AltCfgResp
= AllocateZeroPool (Length
* sizeof (CHAR16
));
3429 if (*AltCfgResp
== NULL
) {
3430 Status
= EFI_OUT_OF_RESOURCES
;
3432 StrnCpy (*AltCfgResp
, HdrStart
, HdrEnd
- HdrStart
);
3433 StrCat (*AltCfgResp
, Result
);
3434 Status
= EFI_SUCCESS
;
3438 if (GuidStr
!= NULL
) {
3441 if (NameStr
!= NULL
) {
3444 if (PathStr
!= NULL
) {
3447 if (AltIdStr
!= NULL
) {
3448 FreePool (AltIdStr
);
3450 if (Result
!= NULL
) {