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
));
876 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.
907 case EFI_IFR_DEFAULTSTORE_OP
:
909 // Add new the map between default id and default name.
911 DefaultData
= (IFR_DEFAULT_DATA
*) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
912 if (DefaultData
== NULL
) {
913 Status
= EFI_OUT_OF_RESOURCES
;
916 DefaultData
->DefaultId
= ((EFI_IFR_DEFAULTSTORE
*) IfrOpHdr
)->DefaultId
;
917 DefaultData
->DefaultName
= ((EFI_IFR_DEFAULTSTORE
*) IfrOpHdr
)->DefaultName
;
918 InsertTailList (&DefaultIdArray
->Entry
, &DefaultData
->Entry
);
922 case EFI_IFR_FORM_OP
:
924 // No matched varstore is found and directly return.
926 if (VarStorageData
->Size
== 0) {
927 Status
= EFI_SUCCESS
;
932 case EFI_IFR_ONE_OF_OP
:
933 case EFI_IFR_NUMERIC_OP
:
935 // Numeric and OneOf has the same opcode structure.
939 // Check whether this question is for the requested varstore.
941 IfrOneOf
= (EFI_IFR_ONE_OF
*) IfrOpHdr
;
942 if (IfrOneOf
->Question
.VarStoreId
!= VarStorageData
->VarStoreId
) {
947 // Get Offset/Width by Question header and OneOf Flags
949 VarOffset
= IfrOneOf
->Question
.VarStoreInfo
.VarOffset
;
950 VarWidth
= (UINT16
) (1 << (IfrOneOf
->Flags
& EFI_IFR_NUMERIC_SIZE
));
952 // Check whether this question is in requested block array.
954 if (!BlockArrayCheck (RequestBlockArray
, VarOffset
, VarWidth
)) {
956 // This question is not in the requested string. Skip it.
962 // Check this var question is in the var storage
964 if ((VarOffset
+ VarWidth
) > VarStorageData
->Size
) {
965 Status
= EFI_INVALID_PARAMETER
;
972 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
973 if (BlockData
== NULL
) {
974 Status
= EFI_OUT_OF_RESOURCES
;
977 BlockData
->Offset
= VarOffset
;
978 BlockData
->Width
= VarWidth
;
979 BlockData
->QuestionId
= IfrOneOf
->Question
.QuestionId
;
980 BlockData
->OpCode
= IfrOpHdr
->OpCode
;
981 BlockData
->Scope
= IfrOpHdr
->Scope
;
982 InitializeListHead (&BlockData
->DefaultValueEntry
);
984 // Add Block Data into VarStorageData BlockEntry
986 InsertBlockData (&VarStorageData
->BlockEntry
, &BlockData
);
989 case EFI_IFR_ORDERED_LIST_OP
:
991 // offset by question header
992 // width by EFI_IFR_ORDERED_LIST MaxContainers * OneofOption Type
993 // no default value and default id, how to define its default value?
997 // Check whether this question is for the requested varstore.
999 IfrOrderedList
= (EFI_IFR_ORDERED_LIST
*) IfrOpHdr
;
1000 if (IfrOrderedList
->Question
.VarStoreId
!= VarStorageData
->VarStoreId
) {
1005 // Get Offset/Width by Question header and OneOf Flags
1007 VarOffset
= IfrOrderedList
->Question
.VarStoreInfo
.VarOffset
;
1008 VarWidth
= IfrOrderedList
->MaxContainers
;
1011 // Check whether this question is in requested block array.
1013 if (!BlockArrayCheck (RequestBlockArray
, VarOffset
, VarWidth
)) {
1015 // This question is not in the requested string. Skip it.
1021 // Check this var question is in the var storage
1023 if ((VarOffset
+ VarWidth
) > VarStorageData
->Size
) {
1024 Status
= EFI_INVALID_PARAMETER
;
1031 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
1032 if (BlockData
== NULL
) {
1033 Status
= EFI_OUT_OF_RESOURCES
;
1036 BlockData
->Offset
= VarOffset
;
1037 BlockData
->Width
= VarWidth
;
1038 BlockData
->QuestionId
= IfrOrderedList
->Question
.QuestionId
;
1039 BlockData
->OpCode
= IfrOpHdr
->OpCode
;
1040 BlockData
->Scope
= IfrOpHdr
->Scope
;
1041 InitializeListHead (&BlockData
->DefaultValueEntry
);
1044 // Add Block Data into VarStorageData BlockEntry
1046 InsertBlockData (&VarStorageData
->BlockEntry
, &BlockData
);
1049 case EFI_IFR_CHECKBOX_OP
:
1051 // EFI_IFR_DEFAULT_OP
1052 // offset by question header
1053 // width is 1 sizeof (BOOLEAN)
1054 // default id by CheckBox Flags if CheckBox flags (Default or Mau) is set, the default value is 1 to be set.
1055 // value by DefaultOption
1056 // default id by DeaultOption DefaultId can override CheckBox Flags and Default value.
1060 // Check whether this question is for the requested varstore.
1062 IfrCheckBox
= (EFI_IFR_CHECKBOX
*) IfrOpHdr
;
1063 if (IfrCheckBox
->Question
.VarStoreId
!= VarStorageData
->VarStoreId
) {
1068 // Get Offset/Width by Question header and OneOf Flags
1070 VarOffset
= IfrCheckBox
->Question
.VarStoreInfo
.VarOffset
;
1071 VarWidth
= sizeof (BOOLEAN
);
1074 // Check whether this question is in requested block array.
1076 if (!BlockArrayCheck (RequestBlockArray
, VarOffset
, VarWidth
)) {
1078 // This question is not in the requested string. Skip it.
1084 // Check this var question is in the var storage
1086 if ((VarOffset
+ VarWidth
) > VarStorageData
->Size
) {
1087 Status
= EFI_INVALID_PARAMETER
;
1094 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
1095 if (BlockData
== NULL
) {
1096 Status
= EFI_OUT_OF_RESOURCES
;
1099 BlockData
->Offset
= VarOffset
;
1100 BlockData
->Width
= VarWidth
;
1101 BlockData
->QuestionId
= IfrCheckBox
->Question
.QuestionId
;
1102 BlockData
->OpCode
= IfrOpHdr
->OpCode
;
1103 BlockData
->Scope
= IfrOpHdr
->Scope
;
1104 InitializeListHead (&BlockData
->DefaultValueEntry
);
1106 // Add Block Data into VarStorageData BlockEntry
1108 InsertBlockData (&VarStorageData
->BlockEntry
, &BlockData
);
1111 // Add default value by CheckBox Flags
1113 if ((IfrCheckBox
->Flags
& EFI_IFR_CHECKBOX_DEFAULT
) == EFI_IFR_CHECKBOX_DEFAULT
) {
1115 // Set standard ID to Manufacture ID and Get DefaultName String ID
1117 VarDefaultId
= EFI_HII_DEFAULT_CLASS_STANDARD
;
1118 Status
= FindDefaultName (DefaultIdArray
, VarDefaultId
, &VarDefaultName
);
1119 if (EFI_ERROR (Status
)) {
1123 // Prepare new DefaultValue
1125 DefaultData
= (IFR_DEFAULT_DATA
*) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
1126 if (DefaultData
== NULL
) {
1127 Status
= EFI_OUT_OF_RESOURCES
;
1130 DefaultData
->DefaultId
= VarDefaultId
;
1131 DefaultData
->DefaultName
= VarDefaultName
;
1132 DefaultData
->Value
= 1;
1134 // Add DefaultValue into current BlockData
1136 InsertDefaultValue (BlockData
, DefaultData
);
1139 if ((IfrCheckBox
->Flags
& EFI_IFR_CHECKBOX_DEFAULT_MFG
) == EFI_IFR_CHECKBOX_DEFAULT_MFG
) {
1141 // Set standard ID to Manufacture ID and Get DefaultName String ID
1143 VarDefaultId
= EFI_HII_DEFAULT_CLASS_MANUFACTURING
;
1144 Status
= FindDefaultName (DefaultIdArray
, VarDefaultId
, &VarDefaultName
);
1145 if (EFI_ERROR (Status
)) {
1149 // Prepare new DefaultValue
1151 DefaultData
= (IFR_DEFAULT_DATA
*) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
1152 if (DefaultData
== NULL
) {
1153 Status
= EFI_OUT_OF_RESOURCES
;
1156 DefaultData
->DefaultId
= VarDefaultId
;
1157 DefaultData
->DefaultName
= VarDefaultName
;
1158 DefaultData
->Value
= 1;
1160 // Add DefaultValue into current BlockData
1162 InsertDefaultValue (BlockData
, DefaultData
);
1166 case EFI_IFR_STRING_OP
:
1168 // offset by question header
1169 // width MaxSize * sizeof (CHAR16)
1170 // no default value, only block array
1174 // Check whether this question is for the requested varstore.
1176 IfrString
= (EFI_IFR_STRING
*) IfrOpHdr
;
1177 if (IfrString
->Question
.VarStoreId
!= VarStorageData
->VarStoreId
) {
1182 // Get Offset/Width by Question header and OneOf Flags
1184 VarOffset
= IfrString
->Question
.VarStoreInfo
.VarOffset
;
1185 VarWidth
= (UINT16
) (IfrString
->MaxSize
* sizeof (UINT16
));
1188 // Check whether this question is in requested block array.
1190 if (!BlockArrayCheck (RequestBlockArray
, VarOffset
, VarWidth
)) {
1192 // This question is not in the requested string. Skip it.
1198 // Check this var question is in the var storage
1200 if ((VarOffset
+ VarWidth
) > VarStorageData
->Size
) {
1201 Status
= EFI_INVALID_PARAMETER
;
1208 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
1209 if (BlockData
== NULL
) {
1210 Status
= EFI_OUT_OF_RESOURCES
;
1213 BlockData
->Offset
= VarOffset
;
1214 BlockData
->Width
= VarWidth
;
1215 BlockData
->QuestionId
= IfrString
->Question
.QuestionId
;
1216 BlockData
->OpCode
= IfrOpHdr
->OpCode
;
1217 InitializeListHead (&BlockData
->DefaultValueEntry
);
1220 // Add Block Data into VarStorageData BlockEntry
1222 InsertBlockData (&VarStorageData
->BlockEntry
, &BlockData
);
1225 // No default value for string.
1230 case EFI_IFR_PASSWORD_OP
:
1232 // offset by question header
1233 // width MaxSize * sizeof (CHAR16)
1234 // no default value, only block array
1238 // Check whether this question is for the requested varstore.
1240 IfrPassword
= (EFI_IFR_PASSWORD
*) IfrOpHdr
;
1241 if (IfrPassword
->Question
.VarStoreId
!= VarStorageData
->VarStoreId
) {
1246 // Get Offset/Width by Question header and OneOf Flags
1248 VarOffset
= IfrPassword
->Question
.VarStoreInfo
.VarOffset
;
1249 VarWidth
= (UINT16
) (IfrPassword
->MaxSize
* sizeof (UINT16
));
1252 // Check whether this question is in requested block array.
1254 if (!BlockArrayCheck (RequestBlockArray
, VarOffset
, VarWidth
)) {
1256 // This question is not in the requested string. Skip it.
1262 // Check this var question is in the var storage
1264 if ((VarOffset
+ VarWidth
) > VarStorageData
->Size
) {
1265 Status
= EFI_INVALID_PARAMETER
;
1272 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
1273 if (BlockData
== NULL
) {
1274 Status
= EFI_OUT_OF_RESOURCES
;
1277 BlockData
->Offset
= VarOffset
;
1278 BlockData
->Width
= VarWidth
;
1279 BlockData
->QuestionId
= IfrPassword
->Question
.QuestionId
;
1280 BlockData
->OpCode
= IfrOpHdr
->OpCode
;
1281 InitializeListHead (&BlockData
->DefaultValueEntry
);
1284 // Add Block Data into VarStorageData BlockEntry
1286 InsertBlockData (&VarStorageData
->BlockEntry
, &BlockData
);
1289 // No default value for string.
1294 case EFI_IFR_ONE_OF_OPTION_OP
:
1296 // No matched block data is ignored.
1298 if (BlockData
== NULL
|| BlockData
->Scope
== 0) {
1302 IfrOneOfOption
= (EFI_IFR_ONE_OF_OPTION
*) IfrOpHdr
;
1303 if (BlockData
->OpCode
== EFI_IFR_ORDERED_LIST_OP
) {
1305 // Get ordered list option data type.
1307 if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_8
|| IfrOneOfOption
->Type
== EFI_IFR_TYPE_BOOLEAN
) {
1309 } else if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_16
) {
1311 } else if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_32
) {
1313 } else if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_64
) {
1317 // Invalid ordered list option data type.
1319 Status
= EFI_INVALID_PARAMETER
;
1323 // Calculate Ordered list QuestionId width.
1325 BlockData
->Width
= (UINT16
) (BlockData
->Width
* VarWidth
);
1330 if ((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT
) == EFI_IFR_OPTION_DEFAULT
) {
1332 // Set standard ID to Manufacture ID and Get DefaultName String ID
1334 VarDefaultId
= EFI_HII_DEFAULT_CLASS_STANDARD
;
1335 Status
= FindDefaultName (DefaultIdArray
, VarDefaultId
, &VarDefaultName
);
1336 if (EFI_ERROR (Status
)) {
1340 // Prepare new DefaultValue
1342 DefaultData
= (IFR_DEFAULT_DATA
*) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
1343 if (DefaultData
== NULL
) {
1344 Status
= EFI_OUT_OF_RESOURCES
;
1347 DefaultData
->DefaultId
= VarDefaultId
;
1348 DefaultData
->DefaultName
= VarDefaultName
;
1349 DefaultData
->Value
= IfrOneOfOption
->Value
.u64
;
1351 // Add DefaultValue into current BlockData
1353 InsertDefaultValue (BlockData
, DefaultData
);
1356 if ((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT_MFG
) == EFI_IFR_OPTION_DEFAULT_MFG
) {
1358 // Set default ID to Manufacture ID and Get DefaultName String ID
1360 VarDefaultId
= EFI_HII_DEFAULT_CLASS_MANUFACTURING
;
1361 Status
= FindDefaultName (DefaultIdArray
, VarDefaultId
, &VarDefaultName
);
1362 if (EFI_ERROR (Status
)) {
1366 // Prepare new DefaultValue
1368 DefaultData
= (IFR_DEFAULT_DATA
*) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
1369 if (DefaultData
== NULL
) {
1370 Status
= EFI_OUT_OF_RESOURCES
;
1373 DefaultData
->DefaultId
= VarDefaultId
;
1374 DefaultData
->DefaultName
= VarDefaultName
;
1375 DefaultData
->Value
= IfrOneOfOption
->Value
.u64
;
1377 // Add DefaultValue into current BlockData
1379 InsertDefaultValue (BlockData
, DefaultData
);
1383 case EFI_IFR_DEFAULT_OP
:
1385 // Update Current BlockData to the default value.
1387 if (BlockData
== NULL
|| BlockData
->Scope
== 0) {
1389 // No matched block data is ignored.
1394 if (BlockData
->OpCode
== EFI_IFR_ORDERED_LIST_OP
) {
1396 // OrderedList Opcode is no default value.
1401 // Get the DefaultId and DefaultName String ID
1403 IfrDefault
= (EFI_IFR_DEFAULT
*) IfrOpHdr
;
1404 VarDefaultId
= IfrDefault
->DefaultId
;
1405 Status
= FindDefaultName (DefaultIdArray
, VarDefaultId
, &VarDefaultName
);
1406 if (EFI_ERROR (Status
)) {
1410 // Prepare new DefaultValue
1412 DefaultData
= (IFR_DEFAULT_DATA
*) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
1413 if (DefaultData
== NULL
) {
1414 Status
= EFI_OUT_OF_RESOURCES
;
1417 DefaultData
->DefaultId
= VarDefaultId
;
1418 DefaultData
->DefaultName
= VarDefaultName
;
1419 DefaultData
->Value
= IfrDefault
->Value
.u64
;
1421 // Add DefaultValue into current BlockData
1423 InsertDefaultValue (BlockData
, DefaultData
);
1425 case EFI_IFR_END_OP
:
1427 // End Opcode is for Var.
1429 if (BlockData
!= NULL
&& BlockData
->Scope
> 0) {
1434 if (BlockData
!= NULL
&& BlockData
->Scope
> 0) {
1435 BlockData
->Scope
= (UINT8
) (BlockData
->Scope
+ IfrOpHdr
->Scope
);
1440 IfrOffset
+= IfrOpHdr
->Length
;
1445 // Set the defualt ID array.
1447 *PIfrDefaultIdArray
= DefaultIdArray
;
1453 This function gets the full request string and full default value string by
1454 parsing IFR data in HII form packages.
1456 When Request points to NULL string, the request string and default value string
1457 for each varstore in form package will return.
1459 @param HiiHandle Hii Handle which Hii Packages are registered.
1460 @param DevicePath Device Path which Hii Config Access Protocol is registered.
1461 @param Request Pointer to a null-terminated Unicode string in
1462 <ConfigRequest> format. When it doesn't contain
1463 any RequestElement, it will be updated to return
1464 the full RequestElement retrieved from IFR data.
1465 If it points to NULL, the request string for the first
1466 varstore in form package will be merged into a
1467 <MultiConfigRequest> format string and return.
1468 @param AltCfgResp Pointer to a null-terminated Unicode string in
1469 <ConfigAltResp> format. When the pointer is to NULL,
1470 the full default value string retrieved from IFR data
1471 will return. When the pinter is to a string, the
1472 full default value string retrieved from IFR data
1473 will be merged into the input string and return.
1474 When Request points to NULL, the default value string
1475 for each varstore in form package will be merged into
1476 a <MultiConfigAltResp> format string and return.
1477 @retval EFI_SUCCESS The Results string is set to the full request string.
1478 And AltCfgResp contains all default value string.
1479 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
1480 @retval EFI_NOT_FOUND The varstore (Guid and Name) in Request string
1481 can't be found in Form package.
1482 @retval EFI_NOT_FOUND HiiPackage can't be got on the input HiiHandle.
1483 @retval EFI_INVALID_PARAMETER *Request points to NULL.
1488 GetFullStringFromHiiFormPackages (
1489 IN EFI_HII_HANDLE HiiHandle
,
1490 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
1491 IN OUT EFI_STRING
*Request
,
1492 IN OUT EFI_STRING
*AltCfgResp
1496 EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
;
1497 UINT32 PackageListLength
;
1499 IFR_BLOCK_DATA
*RequestBlockArray
;
1500 IFR_BLOCK_DATA
*BlockData
;
1501 IFR_BLOCK_DATA
*NextBlockData
;
1502 IFR_DEFAULT_DATA
*DefaultValueData
;
1503 IFR_DEFAULT_DATA
*DefaultId
;
1504 IFR_DEFAULT_DATA
*DefaultIdArray
;
1505 EFI_HII_PACKAGE_HEADER PacakgeHeader
;
1506 UINT32 PackageOffset
;
1507 IFR_VARSTORAGE_DATA
*VarStorageData
;
1508 EFI_STRING DefaultAltCfgResp
;
1509 EFI_STRING FullConfigRequest
;
1510 EFI_STRING ConfigHdr
;
1514 EFI_STRING StringPtr
;
1520 LIST_ENTRY
*LinkData
;
1521 LIST_ENTRY
*LinkDefault
;
1524 // Initialize the local variables.
1526 RequestBlockArray
= NULL
;
1527 VarStorageData
= NULL
;
1528 DefaultAltCfgResp
= NULL
;
1529 FullConfigRequest
= NULL
;
1531 DefaultIdArray
= NULL
;
1537 // 1. Get HiiPackage by HiiHandle
1540 HiiPackageList
= NULL
;
1541 Status
= HiiExportPackageLists (&mPrivate
.HiiDatabase
, HiiHandle
, &BufferSize
, HiiPackageList
);
1544 // The return status should always be EFI_BUFFER_TOO_SMALL as input buffer's size is 0.
1546 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
1550 HiiPackageList
= AllocatePool (BufferSize
);
1551 if (HiiPackageList
== NULL
) {
1552 return EFI_OUT_OF_RESOURCES
;
1556 // Get PackageList on HiiHandle
1558 Status
= HiiExportPackageLists (&mPrivate
.HiiDatabase
, HiiHandle
, &BufferSize
, HiiPackageList
);
1559 if (EFI_ERROR (Status
)) {
1564 // 2. Parse FormPackage to get BlockArray and DefaultId Array for the request BlockArray.
1565 // 1) Request is NULL.
1566 // 2) Request is not NULL. And it doesn't contain any BlockArray.
1567 // 3) Request is not NULL. And it containts BlockArray.
1571 // Initialize VarStorageData to store the var store Block and Default value information.
1573 VarStorageData
= (IFR_VARSTORAGE_DATA
*) AllocateZeroPool (sizeof (IFR_VARSTORAGE_DATA
));
1574 if (VarStorageData
== NULL
) {
1575 Status
= EFI_OUT_OF_RESOURCES
;
1579 InitializeListHead (&VarStorageData
->Entry
);
1580 InitializeListHead (&VarStorageData
->BlockEntry
);
1583 // Gte the request block array by Request String
1586 if (*Request
!= NULL
) {
1587 StringPtr
= StrStr (*Request
, L
"&OFFSET=");
1589 if (StringPtr
!= NULL
) {
1591 // Init RequestBlockArray
1593 RequestBlockArray
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
1594 if (RequestBlockArray
== NULL
) {
1595 Status
= EFI_OUT_OF_RESOURCES
;
1598 InitializeListHead (&RequestBlockArray
->Entry
);
1601 // Get the request Block array from the request string
1606 // Parse each <RequestElement> if exists
1607 // Only <BlockName> format is supported by this help function.
1608 // <BlockName> ::= &'OFFSET='<Number>&'WIDTH='<Number>
1610 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) == 0) {
1612 // Skip the OFFSET string
1614 StringPtr
+= StrLen (L
"&OFFSET=");
1618 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
1619 if (EFI_ERROR (Status
)) {
1626 (((Length
+ 1) / 2) < sizeof (UINT16
)) ? ((Length
+ 1) / 2) : sizeof (UINT16
)
1628 FreePool (TmpBuffer
);
1630 StringPtr
+= Length
;
1631 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
1632 Status
= EFI_INVALID_PARAMETER
;
1635 StringPtr
+= StrLen (L
"&WIDTH=");
1640 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
1641 if (EFI_ERROR (Status
)) {
1648 (((Length
+ 1) / 2) < sizeof (UINT16
)) ? ((Length
+ 1) / 2) : sizeof (UINT16
)
1650 FreePool (TmpBuffer
);
1652 StringPtr
+= Length
;
1653 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
1654 Status
= EFI_INVALID_PARAMETER
;
1661 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
1662 if (BlockData
== NULL
) {
1663 Status
= EFI_OUT_OF_RESOURCES
;
1666 BlockData
->Offset
= Offset
;
1667 BlockData
->Width
= Width
;
1668 InsertBlockData (&RequestBlockArray
->Entry
, &BlockData
);
1671 // If '\0', parsing is finished.
1673 if (*StringPtr
== 0) {
1679 // Merge the requested block data.
1681 Link
= RequestBlockArray
->Entry
.ForwardLink
;
1682 while ((Link
!= &RequestBlockArray
->Entry
) && (Link
->ForwardLink
!= &RequestBlockArray
->Entry
)) {
1683 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
1684 NextBlockData
= BASE_CR (Link
->ForwardLink
, IFR_BLOCK_DATA
, Entry
);
1685 if ((NextBlockData
->Offset
>= BlockData
->Offset
) && (NextBlockData
->Offset
<= (BlockData
->Offset
+ BlockData
->Width
))) {
1686 if ((NextBlockData
->Offset
+ NextBlockData
->Width
) > (BlockData
->Offset
+ BlockData
->Width
)) {
1687 BlockData
->Width
= (UINT16
) (NextBlockData
->Offset
+ NextBlockData
->Width
- BlockData
->Offset
);
1689 RemoveEntryList (Link
->ForwardLink
);
1690 FreePool (NextBlockData
);
1693 Link
= Link
->ForwardLink
;
1698 // Get the form package
1700 PackageOffset
= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
1701 PackageListLength
= ReadUnaligned32 (&HiiPackageList
->PackageLength
);
1702 while (PackageOffset
< PackageListLength
) {
1703 CopyMem (&PacakgeHeader
, (UINT8
*) HiiPackageList
+ PackageOffset
, sizeof (PacakgeHeader
));
1705 if (PacakgeHeader
.Type
== EFI_HII_PACKAGE_FORMS
) {
1707 // Reset VarStorageData
1709 VarStorageData
->Size
= 0;
1710 VarStorageData
->VarStoreId
= 0;
1711 if (VarStorageData
->Name
!= NULL
) {
1712 FreePool (VarStorageData
->Name
);
1713 VarStorageData
->Name
= NULL
;
1717 // Parse the opcode in form package
1719 Status
= ParseIfrData ((UINT8
*) HiiPackageList
+ PackageOffset
, PacakgeHeader
.Length
, *Request
, RequestBlockArray
, VarStorageData
, &DefaultIdArray
);
1720 if (EFI_ERROR (Status
)) {
1725 // Only one form is in a pacakge list.
1730 PackageOffset
+= PacakgeHeader
.Length
;
1734 // No requested varstore in IFR data and directly return
1736 if (VarStorageData
->Size
== 0) {
1741 // 3. Construct Request Element (Block Name) for 2.1 and 2.2 case.
1745 // Construct <ConfigHdr> : "GUID=...&NAME=...&PATH=..." by VarStorageData Guid, Name and DriverHandle
1747 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*) &VarStorageData
->Guid
, 1, &GuidStr
);
1748 GenerateSubStr (L
"NAME=", StrLen (VarStorageData
->Name
) * sizeof (CHAR16
), (VOID
*) VarStorageData
->Name
, 2, &NameStr
);
1751 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) DevicePath
),
1752 (VOID
*) DevicePath
,
1756 Length
= StrLen (GuidStr
);
1757 Length
= Length
+ StrLen (NameStr
);
1758 Length
= Length
+ StrLen (PathStr
) + 1;
1759 ConfigHdr
= AllocateZeroPool (Length
* sizeof (CHAR16
));
1760 if (ConfigHdr
== NULL
) {
1761 Status
= EFI_OUT_OF_RESOURCES
;
1764 StrCpy (ConfigHdr
, GuidStr
);
1765 StrCat (ConfigHdr
, NameStr
);
1766 StrCat (ConfigHdr
, PathStr
);
1769 // Remove the last character L'&'
1771 *(ConfigHdr
+ StrLen (ConfigHdr
) - 1) = L
'\0';
1773 if (RequestBlockArray
== NULL
) {
1775 // Append VarStorageData BlockEntry into *Request string
1776 // Now support only one varstore in a form package.
1780 // Go through all VarStorageData Entry and get BlockEntry for each one for the multiple varstore in a single form package
1781 // Then construct them all to return MultiRequest string : ConfigHdr BlockConfig
1785 // Compute the length of the entire request starting with <ConfigHdr> and a
1788 Length
= StrLen (ConfigHdr
) + 1;
1790 for (Link
= VarStorageData
->BlockEntry
.ForwardLink
; Link
!= &VarStorageData
->BlockEntry
; Link
= Link
->ForwardLink
) {
1792 // Add <BlockName> length for each Offset/Width pair
1794 // <BlockName> ::= &OFFSET=1234&WIDTH=1234
1795 // | 8 | 4 | 7 | 4 |
1797 Length
= Length
+ (8 + 4 + 7 + 4);
1801 // Allocate buffer for the entire <ConfigRequest>
1803 FullConfigRequest
= AllocateZeroPool (Length
* sizeof (CHAR16
));
1804 if (FullConfigRequest
== NULL
) {
1807 StringPtr
= FullConfigRequest
;
1810 // Start with <ConfigHdr>
1812 StrCpy (StringPtr
, ConfigHdr
);
1813 StringPtr
+= StrLen (StringPtr
);
1816 // Loop through all the Offset/Width pairs and append them to ConfigRequest
1818 for (Link
= VarStorageData
->BlockEntry
.ForwardLink
; Link
!= &VarStorageData
->BlockEntry
; Link
= Link
->ForwardLink
) {
1819 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
1821 // Append &OFFSET=XXXX&WIDTH=YYYY\0
1825 (8 + 4 + 7 + 4 + 1) * sizeof (CHAR16
),
1826 L
"&OFFSET=%04X&WIDTH=%04X",
1830 StringPtr
+= StrLen (StringPtr
);
1833 // Set to the got full request string.
1835 HiiToLower (FullConfigRequest
);
1836 if (*Request
!= NULL
) {
1837 FreePool (*Request
);
1839 *Request
= FullConfigRequest
;
1843 // 4. Construct Default Value string in AltResp according to request element.
1844 // Go through all VarStorageData Entry and get the DefaultId array for each one
1845 // Then construct them all to : ConfigHdr AltConfigHdr ConfigBody AltConfigHdr ConfigBody
1849 // Add length for <ConfigHdr> + '\0'
1851 Length
= StrLen (ConfigHdr
) + 1;
1853 for (Link
= DefaultIdArray
->Entry
.ForwardLink
; Link
!= &DefaultIdArray
->Entry
; Link
= Link
->ForwardLink
) {
1854 DefaultId
= BASE_CR (Link
, IFR_DEFAULT_DATA
, Entry
);
1856 // Add length for "&<ConfigHdr>&ALTCFG=XXXX"
1857 // |1| StrLen (ConfigHdr) | 8 | 4 |
1859 Length
+= (1 + StrLen (ConfigHdr
) + 8 + 4);
1861 for (LinkData
= VarStorageData
->BlockEntry
.ForwardLink
; LinkData
!= &VarStorageData
->BlockEntry
; LinkData
= LinkData
->ForwardLink
) {
1862 BlockData
= BASE_CR (LinkData
, IFR_BLOCK_DATA
, Entry
);
1863 for (LinkDefault
= BlockData
->DefaultValueEntry
.ForwardLink
; LinkDefault
!= &BlockData
->DefaultValueEntry
; LinkDefault
= LinkDefault
->ForwardLink
) {
1864 DefaultValueData
= BASE_CR (LinkDefault
, IFR_DEFAULT_DATA
, Entry
);
1865 if (DefaultValueData
->DefaultId
== DefaultId
->DefaultId
) {
1867 // Add length for "&OFFSET=XXXX&WIDTH=YYYY&VALUE=zzzzzzzzzzzz"
1868 // | 8 | 4 | 7 | 4 | 7 | Width * 2 |
1870 Length
+= (8 + 4 + 7 + 4 + 7 + BlockData
->Width
* 2);
1877 // Allocate buffer for the entire <DefaultAltCfgResp>
1879 DefaultAltCfgResp
= AllocateZeroPool (Length
* sizeof (CHAR16
));
1880 if (DefaultAltCfgResp
== NULL
) {
1883 StringPtr
= DefaultAltCfgResp
;
1886 // Start with <ConfigHdr>
1888 StrCpy (StringPtr
, ConfigHdr
);
1889 StringPtr
+= StrLen (StringPtr
);
1891 for (Link
= DefaultIdArray
->Entry
.ForwardLink
; Link
!= &DefaultIdArray
->Entry
; Link
= Link
->ForwardLink
) {
1892 DefaultId
= BASE_CR (Link
, IFR_DEFAULT_DATA
, Entry
);
1894 // Add <AltConfigHdr> of the form "&<ConfigHdr>&ALTCFG=XXXX\0"
1895 // |1| StrLen (ConfigHdr) | 8 | 4 |
1899 (1 + StrLen (ConfigHdr
) + 8 + 4 + 1) * sizeof (CHAR16
),
1902 DefaultId
->DefaultName
1904 StringPtr
+= StrLen (StringPtr
);
1906 for (LinkData
= VarStorageData
->BlockEntry
.ForwardLink
; LinkData
!= &VarStorageData
->BlockEntry
; LinkData
= LinkData
->ForwardLink
) {
1907 BlockData
= BASE_CR (LinkData
, IFR_BLOCK_DATA
, Entry
);
1908 for (LinkDefault
= BlockData
->DefaultValueEntry
.ForwardLink
; LinkDefault
!= &BlockData
->DefaultValueEntry
; LinkDefault
= LinkDefault
->ForwardLink
) {
1909 DefaultValueData
= BASE_CR (LinkDefault
, IFR_DEFAULT_DATA
, Entry
);
1910 if (DefaultValueData
->DefaultId
== DefaultId
->DefaultId
) {
1912 // Add <BlockConfig>
1913 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>
1917 (8 + 4 + 7 + 4 + 7 + 1) * sizeof (CHAR16
),
1918 L
"&OFFSET=%04X&WIDTH=%04X&VALUE=",
1922 StringPtr
+= StrLen (StringPtr
);
1925 // Convert Value to a hex string in "%x" format
1926 // NOTE: This is in the opposite byte that GUID and PATH use
1928 Width
= BlockData
->Width
;
1929 TmpBuffer
= (UINT8
*) &(DefaultValueData
->Value
);
1930 for (; Width
> 0; Width
--) {
1931 StringPtr
+= UnicodeValueToString (StringPtr
, PREFIX_ZERO
| RADIX_HEX
, TmpBuffer
[Width
- 1], 2);
1937 HiiToLower (DefaultAltCfgResp
);
1940 // 5. Merge string into the input AltCfgResp if the iput *AltCfgResp is not NULL.
1942 if (*AltCfgResp
!= NULL
) {
1943 Status
= MergeDefaultString (AltCfgResp
, DefaultAltCfgResp
);
1944 FreePool (DefaultAltCfgResp
);
1946 *AltCfgResp
= DefaultAltCfgResp
;
1950 if (RequestBlockArray
!= NULL
) {
1952 // Free Link Array RequestBlockArray
1954 while (!IsListEmpty (&RequestBlockArray
->Entry
)) {
1955 BlockData
= BASE_CR (RequestBlockArray
->Entry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
1956 RemoveEntryList (&BlockData
->Entry
);
1957 FreePool (BlockData
);
1960 FreePool (RequestBlockArray
);
1963 if (VarStorageData
!= NULL
) {
1965 // Free link array VarStorageData
1967 while (!IsListEmpty (&VarStorageData
->BlockEntry
)) {
1968 BlockData
= BASE_CR (VarStorageData
->BlockEntry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
1969 RemoveEntryList (&BlockData
->Entry
);
1971 // Free default value link array
1973 while (!IsListEmpty (&BlockData
->DefaultValueEntry
)) {
1974 DefaultValueData
= BASE_CR (BlockData
->DefaultValueEntry
.ForwardLink
, IFR_DEFAULT_DATA
, Entry
);
1975 RemoveEntryList (&DefaultValueData
->Entry
);
1976 FreePool (DefaultValueData
);
1978 FreePool (BlockData
);
1980 FreePool (VarStorageData
);
1983 if (DefaultIdArray
!= NULL
) {
1985 // Free DefaultId Array
1987 while (!IsListEmpty (&DefaultIdArray
->Entry
)) {
1988 DefaultId
= BASE_CR (DefaultIdArray
->Entry
.ForwardLink
, IFR_DEFAULT_DATA
, Entry
);
1989 RemoveEntryList (&DefaultId
->Entry
);
1990 FreePool (DefaultId
);
1992 FreePool (DefaultIdArray
);
1996 // Free the allocated string
1998 if (GuidStr
!= NULL
) {
2001 if (NameStr
!= NULL
) {
2004 if (PathStr
!= NULL
) {
2007 if (ConfigHdr
!= NULL
) {
2008 FreePool (ConfigHdr
);
2012 // Free Pacakge data
2014 if (HiiPackageList
!= NULL
) {
2015 FreePool (HiiPackageList
);
2022 This function allows a caller to extract the current configuration
2023 for one or more named elements from one or more drivers.
2025 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
2027 @param Request A null-terminated Unicode string in
2028 <MultiConfigRequest> format.
2029 @param Progress On return, points to a character in the Request
2030 string. Points to the string's null terminator if
2031 request was successful. Points to the most recent
2032 & before the first failing name / value pair (or
2033 the beginning of the string if the failure is in
2034 the first name / value pair) if the request was
2036 @param Results Null-terminated Unicode string in
2037 <MultiConfigAltResp> format which has all values
2038 filled in for the names in the Request string.
2039 String to be allocated by the called function.
2041 @retval EFI_SUCCESS The Results string is filled with the values
2042 corresponding to all requested names.
2043 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
2044 results that must be stored awaiting possible
2046 @retval EFI_NOT_FOUND Routing data doesn't match any known driver.
2047 Progress set to the "G" in "GUID" of the routing
2048 header that doesn't match. Note: There is no
2049 requirement that all routing data be validated
2050 before any configuration extraction.
2051 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Request
2052 parameter would result in this type of error. The
2053 Progress parameter is set to NULL.
2054 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set to most recent &
2055 before the error or the beginning of the string.
2056 @retval EFI_INVALID_PARAMETER Unknown name. Progress points to the & before the
2062 HiiConfigRoutingExtractConfig (
2063 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
2064 IN CONST EFI_STRING Request
,
2065 OUT EFI_STRING
*Progress
,
2066 OUT EFI_STRING
*Results
2069 HII_DATABASE_PRIVATE_DATA
*Private
;
2070 EFI_STRING StringPtr
;
2071 EFI_STRING ConfigRequest
;
2073 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
2074 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
2077 HII_DATABASE_RECORD
*Database
;
2078 UINT8
*DevicePathPkg
;
2079 UINT8
*CurrentDevicePath
;
2080 EFI_HANDLE DriverHandle
;
2081 EFI_HII_HANDLE HiiHandle
;
2082 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
2083 EFI_STRING AccessProgress
;
2084 EFI_STRING AccessResults
;
2085 EFI_STRING DefaultResults
;
2086 BOOLEAN FirstElement
;
2087 UINTN DevicePathLength
;
2089 if (This
== NULL
|| Progress
== NULL
|| Results
== NULL
) {
2090 return EFI_INVALID_PARAMETER
;
2093 if (Request
== NULL
) {
2095 return EFI_INVALID_PARAMETER
;
2098 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
2099 StringPtr
= Request
;
2100 *Progress
= StringPtr
;
2101 DefaultResults
= NULL
;
2102 ConfigRequest
= NULL
;
2103 Status
= EFI_SUCCESS
;
2104 AccessResults
= NULL
;
2108 // The first element of <MultiConfigRequest> should be
2109 // <GuidHdr>, which is in 'GUID='<Guid> syntax.
2111 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
2112 return EFI_INVALID_PARAMETER
;
2115 FirstElement
= TRUE
;
2118 // Allocate a fix length of memory to store Results. Reallocate memory for
2119 // Results if this fix length is insufficient.
2121 *Results
= (EFI_STRING
) AllocateZeroPool (MAX_STRING_LENGTH
);
2122 if (*Results
== NULL
) {
2123 return EFI_OUT_OF_RESOURCES
;
2126 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) == 0) {
2128 // If parsing error, set Progress to the beginning of the <MultiConfigRequest>
2129 // or most recent & before the error.
2131 if (StringPtr
== Request
) {
2132 *Progress
= StringPtr
;
2134 *Progress
= StringPtr
- 1;
2138 // Process each <ConfigRequest> of <MultiConfigRequest>
2140 Length
= CalculateConfigStringLen (StringPtr
);
2141 ConfigRequest
= AllocateCopyPool ((Length
+ 1) * sizeof (CHAR16
), StringPtr
);
2142 if (ConfigRequest
== NULL
) {
2143 Status
= EFI_OUT_OF_RESOURCES
;
2146 *(ConfigRequest
+ Length
) = 0;
2149 // Get the UEFI device path
2151 Status
= GetDevicePath (ConfigRequest
, (UINT8
**) &DevicePath
);
2152 if (EFI_ERROR (Status
)) {
2157 // Find driver which matches the routing data.
2159 DriverHandle
= NULL
;
2161 DevicePathLength
= GetDevicePathSize (DevicePath
);
2162 for (Link
= Private
->DatabaseList
.ForwardLink
;
2163 Link
!= &Private
->DatabaseList
;
2164 Link
= Link
->ForwardLink
2166 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
2168 if ((DevicePathPkg
= Database
->PackageList
->DevicePathPkg
) != NULL
) {
2169 CurrentDevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
2170 if ((DevicePathLength
== GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) CurrentDevicePath
)) &&
2176 DriverHandle
= Database
->DriverHandle
;
2177 HiiHandle
= Database
->Handle
;
2184 // Try to find driver handle by device path.
2186 if (DriverHandle
== NULL
) {
2187 TempDevicePath
= DevicePath
;
2188 Status
= gBS
->LocateDevicePath (
2189 &gEfiDevicePathProtocolGuid
,
2193 if (EFI_ERROR (Status
) || (DriverHandle
== NULL
)) {
2195 // Routing data does not match any known driver.
2196 // Set Progress to the 'G' in "GUID" of the routing header.
2198 *Progress
= StringPtr
;
2199 Status
= EFI_NOT_FOUND
;
2205 // Check whether ConfigRequest contains request string OFFSET/WIDTH
2207 if ((HiiHandle
!= NULL
) && (StrStr (ConfigRequest
, L
"&OFFSET=") == NULL
)) {
2209 // Get the full request string from IFR when HiiPackage is registered to HiiHandle
2211 Status
= GetFullStringFromHiiFormPackages (HiiHandle
, DevicePath
, &ConfigRequest
, &DefaultResults
);
2212 if (EFI_ERROR (Status
)) {
2216 // Not any request block is found.
2218 if (StrStr (ConfigRequest
, L
"&OFFSET=") == NULL
) {
2219 AccessResults
= AllocateCopyPool (StrSize (ConfigRequest
), ConfigRequest
);
2220 goto NextConfigString
;
2225 // Call corresponding ConfigAccess protocol to extract settings
2227 Status
= gBS
->HandleProtocol (
2229 &gEfiHiiConfigAccessProtocolGuid
,
2230 (VOID
**) &ConfigAccess
2232 ASSERT_EFI_ERROR (Status
);
2234 Status
= ConfigAccess
->ExtractConfig (
2240 if (EFI_ERROR (Status
)) {
2242 // AccessProgress indicates the parsing progress on <ConfigRequest>.
2243 // Map it to the progress on <MultiConfigRequest> then return it.
2245 *Progress
= StrStr (StringPtr
, AccessProgress
);
2250 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'
2251 // which seperates the first <ConfigAltResp> and the following ones.
2253 ASSERT (*AccessProgress
== 0);
2256 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
2258 if (HiiHandle
!= NULL
) {
2259 if (DefaultResults
== NULL
) {
2260 Status
= GetFullStringFromHiiFormPackages (HiiHandle
, DevicePath
, &ConfigRequest
, &AccessResults
);
2262 Status
= MergeDefaultString (&AccessResults
, DefaultResults
);
2265 FreePool (DevicePath
);
2268 if (EFI_ERROR (Status
)) {
2273 // Free the allocated memory.
2275 if (DefaultResults
!= NULL
) {
2276 FreePool (DefaultResults
);
2277 DefaultResults
= NULL
;
2281 if (!FirstElement
) {
2282 Status
= AppendToMultiString (Results
, L
"&");
2283 ASSERT_EFI_ERROR (Status
);
2286 Status
= AppendToMultiString (Results
, AccessResults
);
2287 ASSERT_EFI_ERROR (Status
);
2289 FirstElement
= FALSE
;
2291 FreePool (AccessResults
);
2292 AccessResults
= NULL
;
2293 FreePool (ConfigRequest
);
2294 ConfigRequest
= NULL
;
2297 // Go to next <ConfigRequest> (skip '&').
2299 StringPtr
+= Length
;
2300 if (*StringPtr
== 0) {
2301 *Progress
= StringPtr
;
2309 if (EFI_ERROR (Status
)) {
2310 FreePool (*Results
);
2314 if (ConfigRequest
!= NULL
) {
2315 FreePool (ConfigRequest
);
2318 if (AccessResults
!= NULL
) {
2319 FreePool (AccessResults
);
2322 if (DefaultResults
!= NULL
) {
2323 FreePool (DefaultResults
);
2326 if (DevicePath
!= NULL
) {
2327 FreePool (DevicePath
);
2335 This function allows the caller to request the current configuration for the
2336 entirety of the current HII database and returns the data in a
2337 null-terminated Unicode string.
2339 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
2341 @param Results Null-terminated Unicode string in
2342 <MultiConfigAltResp> format which has all values
2343 filled in for the names in the Request string.
2344 String to be allocated by the called function.
2345 De-allocation is up to the caller.
2347 @retval EFI_SUCCESS The Results string is filled with the values
2348 corresponding to all requested names.
2349 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
2350 results that must be stored awaiting possible
2352 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Results
2353 parameter would result in this type of error.
2358 HiiConfigRoutingExportConfig (
2359 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
2360 OUT EFI_STRING
*Results
2364 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
2365 EFI_STRING AccessResults
;
2366 EFI_STRING Progress
;
2367 EFI_STRING ConfigRequest
;
2369 EFI_HANDLE
*ConfigAccessHandles
;
2370 UINTN NumberConfigAccessHandles
;
2371 BOOLEAN FirstElement
;
2372 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
2373 EFI_HII_HANDLE HiiHandle
;
2374 EFI_STRING DefaultResults
;
2375 HII_DATABASE_PRIVATE_DATA
*Private
;
2377 HII_DATABASE_RECORD
*Database
;
2378 UINT8
*DevicePathPkg
;
2379 UINT8
*CurrentDevicePath
;
2380 UINTN DevicePathLength
;
2382 if (This
== NULL
|| Results
== NULL
) {
2383 return EFI_INVALID_PARAMETER
;
2386 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
2389 // Allocate a fix length of memory to store Results. Reallocate memory for
2390 // Results if this fix length is insufficient.
2392 *Results
= (EFI_STRING
) AllocateZeroPool (MAX_STRING_LENGTH
);
2393 if (*Results
== NULL
) {
2394 return EFI_OUT_OF_RESOURCES
;
2397 NumberConfigAccessHandles
= 0;
2398 Status
= gBS
->LocateHandleBuffer (
2400 &gEfiHiiConfigAccessProtocolGuid
,
2402 &NumberConfigAccessHandles
,
2403 &ConfigAccessHandles
2405 if (EFI_ERROR (Status
)) {
2409 FirstElement
= TRUE
;
2411 for (Index
= 0; Index
< NumberConfigAccessHandles
; Index
++) {
2412 Status
= gBS
->HandleProtocol (
2413 ConfigAccessHandles
[Index
],
2414 &gEfiHiiConfigAccessProtocolGuid
,
2415 (VOID
**) &ConfigAccess
2417 if (EFI_ERROR (Status
)) {
2422 // Get DevicePath and HiiHandle for this ConfigAccess driver handle
2426 ConfigRequest
= NULL
;
2427 DefaultResults
= NULL
;
2428 DevicePath
= DevicePathFromHandle (ConfigAccessHandles
[Index
]);
2429 DevicePathLength
= GetDevicePathSize (DevicePath
);
2430 if (DevicePath
!= NULL
) {
2431 for (Link
= Private
->DatabaseList
.ForwardLink
;
2432 Link
!= &Private
->DatabaseList
;
2433 Link
= Link
->ForwardLink
2435 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
2436 if ((DevicePathPkg
= Database
->PackageList
->DevicePathPkg
) != NULL
) {
2437 CurrentDevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
2438 if ((DevicePathLength
== GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) CurrentDevicePath
)) &&
2444 HiiHandle
= Database
->Handle
;
2452 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
2454 if (HiiHandle
!= NULL
&& DevicePath
!= NULL
) {
2455 Status
= GetFullStringFromHiiFormPackages (HiiHandle
, DevicePath
, &ConfigRequest
, &DefaultResults
);
2458 // Can't parse IFR data to get the request string and default string.
2460 if (EFI_ERROR (Status
)) {
2461 ConfigRequest
= NULL
;
2462 DefaultResults
= NULL
;
2465 Status
= ConfigAccess
->ExtractConfig (
2471 if (!EFI_ERROR (Status
)) {
2473 // Merge the default sting from IFR code into the got setting from driver.
2475 if (DefaultResults
!= NULL
) {
2476 MergeDefaultString (&AccessResults
, DefaultResults
);
2477 FreePool (DefaultResults
);
2481 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'
2482 // which seperates the first <ConfigAltResp> and the following ones.
2484 if (!FirstElement
) {
2485 Status
= AppendToMultiString (Results
, L
"&");
2486 ASSERT_EFI_ERROR (Status
);
2489 Status
= AppendToMultiString (Results
, AccessResults
);
2490 ASSERT_EFI_ERROR (Status
);
2492 FirstElement
= FALSE
;
2494 FreePool (AccessResults
);
2495 AccessResults
= NULL
;
2498 FreePool (ConfigAccessHandles
);
2505 This function processes the results of processing forms and routes it to the
2506 appropriate handlers or storage.
2508 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
2510 @param Configuration A null-terminated Unicode string in
2511 <MulltiConfigResp> format.
2512 @param Progress A pointer to a string filled in with the offset of
2513 the most recent & before the first failing name /
2514 value pair (or the beginning of the string if the
2515 failure is in the first name / value pair) or the
2516 terminating NULL if all was successful.
2518 @retval EFI_SUCCESS The results have been distributed or are awaiting
2520 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
2521 results that must be stored awaiting possible
2523 @retval EFI_INVALID_PARAMETER Passing in a NULL for the Configuration parameter
2524 would result in this type of error.
2525 @retval EFI_NOT_FOUND Target for the specified routing data was not
2531 HiiConfigRoutingRouteConfig (
2532 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
2533 IN CONST EFI_STRING Configuration
,
2534 OUT EFI_STRING
*Progress
2537 HII_DATABASE_PRIVATE_DATA
*Private
;
2538 EFI_STRING StringPtr
;
2539 EFI_STRING ConfigResp
;
2542 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
2543 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
2545 HII_DATABASE_RECORD
*Database
;
2546 UINT8
*DevicePathPkg
;
2547 UINT8
*CurrentDevicePath
;
2548 EFI_HANDLE DriverHandle
;
2549 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
2550 EFI_STRING AccessProgress
;
2551 UINTN DevicePathLength
;
2553 if (This
== NULL
|| Progress
== NULL
) {
2554 return EFI_INVALID_PARAMETER
;
2557 if (Configuration
== NULL
) {
2559 return EFI_INVALID_PARAMETER
;
2562 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
2563 StringPtr
= Configuration
;
2564 *Progress
= StringPtr
;
2567 // The first element of <MultiConfigResp> should be
2568 // <GuidHdr>, which is in 'GUID='<Guid> syntax.
2570 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
2571 return EFI_INVALID_PARAMETER
;
2574 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) == 0) {
2576 // If parsing error, set Progress to the beginning of the <MultiConfigResp>
2577 // or most recent & before the error.
2579 if (StringPtr
== Configuration
) {
2580 *Progress
= StringPtr
;
2582 *Progress
= StringPtr
- 1;
2586 // Process each <ConfigResp> of <MultiConfigResp>
2588 Length
= CalculateConfigStringLen (StringPtr
);
2589 ConfigResp
= AllocateCopyPool ((Length
+ 1) * sizeof (CHAR16
), StringPtr
);
2590 if (ConfigResp
== NULL
) {
2591 return EFI_OUT_OF_RESOURCES
;
2594 // Append '\0' to the end of ConfigRequest
2596 *(ConfigResp
+ Length
) = 0;
2599 // Get the UEFI device path
2601 Status
= GetDevicePath (ConfigResp
, (UINT8
**) &DevicePath
);
2602 if (EFI_ERROR (Status
)) {
2603 FreePool (ConfigResp
);
2608 // Find driver which matches the routing data.
2610 DriverHandle
= NULL
;
2611 DevicePathLength
= GetDevicePathSize (DevicePath
);
2612 for (Link
= Private
->DatabaseList
.ForwardLink
;
2613 Link
!= &Private
->DatabaseList
;
2614 Link
= Link
->ForwardLink
2616 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
2618 if ((DevicePathPkg
= Database
->PackageList
->DevicePathPkg
) != NULL
) {
2619 CurrentDevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
2620 if ((DevicePathLength
== GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) CurrentDevicePath
)) &&
2626 DriverHandle
= Database
->DriverHandle
;
2633 // Try to find driver handle by device path.
2635 if (DriverHandle
== NULL
) {
2636 TempDevicePath
= DevicePath
;
2637 Status
= gBS
->LocateDevicePath (
2638 &gEfiDevicePathProtocolGuid
,
2642 if (EFI_ERROR (Status
) || (DriverHandle
== NULL
)) {
2644 // Routing data does not match any known driver.
2645 // Set Progress to the 'G' in "GUID" of the routing header.
2647 FreePool (DevicePath
);
2648 *Progress
= StringPtr
;
2649 FreePool (ConfigResp
);
2650 return EFI_NOT_FOUND
;
2654 FreePool (DevicePath
);
2657 // Call corresponding ConfigAccess protocol to route settings
2659 Status
= gBS
->HandleProtocol (
2661 &gEfiHiiConfigAccessProtocolGuid
,
2662 (VOID
**) &ConfigAccess
2664 ASSERT_EFI_ERROR (Status
);
2666 Status
= ConfigAccess
->RouteConfig (
2672 if (EFI_ERROR (Status
)) {
2674 // AccessProgress indicates the parsing progress on <ConfigResp>.
2675 // Map it to the progress on <MultiConfigResp> then return it.
2677 *Progress
= StrStr (StringPtr
, AccessProgress
);
2679 FreePool (ConfigResp
);
2683 FreePool (ConfigResp
);
2687 // Go to next <ConfigResp> (skip '&').
2689 StringPtr
+= Length
;
2690 if (*StringPtr
== 0) {
2691 *Progress
= StringPtr
;
2704 This helper function is to be called by drivers to map configuration data
2705 stored in byte array ("block") formats such as UEFI Variables into current
2706 configuration strings.
2708 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
2710 @param ConfigRequest A null-terminated Unicode string in
2711 <ConfigRequest> format.
2712 @param Block Array of bytes defining the block's configuration.
2713 @param BlockSize Length in bytes of Block.
2714 @param Config Filled-in configuration string. String allocated
2715 by the function. Returned only if call is
2716 successful. It is <ConfigResp> string format.
2717 @param Progress A pointer to a string filled in with the offset of
2718 the most recent & before the first failing
2719 name/value pair (or the beginning of the string if
2720 the failure is in the first name / value pair) or
2721 the terminating NULL if all was successful.
2723 @retval EFI_SUCCESS The request succeeded. Progress points to the null
2724 terminator at the end of the ConfigRequest
2726 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress
2727 points to the first character of ConfigRequest.
2728 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigRequest or
2729 Block parameter would result in this type of
2730 error. Progress points to the first character of
2732 @retval EFI_DEVICE_ERROR Block not large enough. Progress undefined.
2733 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted string.
2734 Block is left updated and Progress points at
2735 the "&" preceding the first non-<BlockName>.
2741 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
2742 IN CONST EFI_STRING ConfigRequest
,
2743 IN CONST UINT8
*Block
,
2744 IN CONST UINTN BlockSize
,
2745 OUT EFI_STRING
*Config
,
2746 OUT EFI_STRING
*Progress
2749 HII_DATABASE_PRIVATE_DATA
*Private
;
2750 EFI_STRING StringPtr
;
2758 EFI_STRING ValueStr
;
2759 EFI_STRING ConfigElement
;
2764 if (This
== NULL
|| Progress
== NULL
|| Config
== NULL
) {
2765 return EFI_INVALID_PARAMETER
;
2768 if (Block
== NULL
|| ConfigRequest
== NULL
) {
2769 *Progress
= ConfigRequest
;
2770 return EFI_INVALID_PARAMETER
;
2774 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
2775 ASSERT (Private
!= NULL
);
2777 StringPtr
= ConfigRequest
;
2780 ConfigElement
= NULL
;
2783 // Allocate a fix length of memory to store Results. Reallocate memory for
2784 // Results if this fix length is insufficient.
2786 *Config
= (EFI_STRING
) AllocateZeroPool (MAX_STRING_LENGTH
);
2787 if (*Config
== NULL
) {
2788 return EFI_OUT_OF_RESOURCES
;
2794 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
2795 *Progress
= StringPtr
;
2796 Status
= EFI_INVALID_PARAMETER
;
2799 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"PATH=", StrLen (L
"PATH=")) != 0) {
2802 if (*StringPtr
== 0) {
2803 *Progress
= StringPtr
- 1;
2804 Status
= EFI_INVALID_PARAMETER
;
2808 while (*StringPtr
!= L
'&' && *StringPtr
!= 0) {
2811 if (*StringPtr
== 0) {
2812 *Progress
= StringPtr
- 1;
2813 Status
= EFI_INVALID_PARAMETER
;
2822 // Copy <ConfigHdr> and an additional '&' to <ConfigResp>
2824 Length
= StringPtr
- ConfigRequest
;
2825 CopyMem (*Config
, ConfigRequest
, Length
* sizeof (CHAR16
));
2828 // Parse each <RequestElement> if exists
2829 // Only <BlockName> format is supported by this help function.
2830 // <BlockName> ::= 'OFFSET='<Number>&'WIDTH='<Number>
2832 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"OFFSET=", StrLen (L
"OFFSET=")) == 0) {
2834 // Back up the header of one <BlockName>
2838 StringPtr
+= StrLen (L
"OFFSET=");
2842 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
2843 if (Status
== EFI_OUT_OF_RESOURCES
) {
2844 *Progress
= ConfigRequest
;
2851 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
2853 FreePool (TmpBuffer
);
2855 StringPtr
+= Length
;
2856 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
2857 *Progress
= StringPtr
- Length
- StrLen (L
"OFFSET=") - 1;
2858 Status
= EFI_INVALID_PARAMETER
;
2861 StringPtr
+= StrLen (L
"&WIDTH=");
2866 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
2867 if (Status
== EFI_OUT_OF_RESOURCES
) {
2868 *Progress
= ConfigRequest
;
2875 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
2877 FreePool (TmpBuffer
);
2879 StringPtr
+= Length
;
2880 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
2881 *Progress
= StringPtr
- Length
- StrLen (L
"&WIDTH=");
2882 Status
= EFI_INVALID_PARAMETER
;
2887 // Calculate Value and convert it to hex string.
2889 if (Offset
+ Width
> BlockSize
) {
2890 *Progress
= StringPtr
;
2891 Status
= EFI_DEVICE_ERROR
;
2895 Value
= (UINT8
*) AllocateZeroPool (Width
);
2896 if (Value
== NULL
) {
2897 *Progress
= ConfigRequest
;
2898 Status
= EFI_OUT_OF_RESOURCES
;
2902 CopyMem (Value
, (UINT8
*) Block
+ Offset
, Width
);
2904 Length
= Width
* 2 + 1;
2905 ValueStr
= (EFI_STRING
) AllocateZeroPool (Length
* sizeof (CHAR16
));
2906 if (ValueStr
== NULL
) {
2907 *Progress
= ConfigRequest
;
2908 Status
= EFI_OUT_OF_RESOURCES
;
2912 TemString
= ValueStr
;
2913 TemBuffer
= Value
+ Width
- 1;
2914 for (Index
= 0; Index
< Width
; Index
++, TemBuffer
--) {
2915 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
2922 // Build a ConfigElement
2924 Length
+= StringPtr
- TmpPtr
+ 1 + StrLen (L
"VALUE=");
2925 ConfigElement
= (EFI_STRING
) AllocateZeroPool (Length
* sizeof (CHAR16
));
2926 if (ConfigElement
== NULL
) {
2927 Status
= EFI_OUT_OF_RESOURCES
;
2930 CopyMem (ConfigElement
, TmpPtr
, (StringPtr
- TmpPtr
+ 1) * sizeof (CHAR16
));
2931 if (*StringPtr
== 0) {
2932 *(ConfigElement
+ (StringPtr
- TmpPtr
)) = L
'&';
2934 *(ConfigElement
+ (StringPtr
- TmpPtr
) + 1) = 0;
2935 StrCat (ConfigElement
, L
"VALUE=");
2936 StrCat (ConfigElement
, ValueStr
);
2938 AppendToMultiString (Config
, ConfigElement
);
2940 FreePool (ConfigElement
);
2941 FreePool (ValueStr
);
2942 ConfigElement
= NULL
;
2946 // If '\0', parsing is finished. Otherwise skip '&' to continue
2948 if (*StringPtr
== 0) {
2951 AppendToMultiString (Config
, L
"&");
2956 if (*StringPtr
!= 0) {
2957 *Progress
= StringPtr
- 1;
2958 Status
= EFI_INVALID_PARAMETER
;
2962 HiiToLower (*Config
);
2963 *Progress
= StringPtr
;
2967 if (*Config
!= NULL
) {
2971 if (ValueStr
!= NULL
) {
2972 FreePool (ValueStr
);
2974 if (Value
!= NULL
) {
2977 if (ConfigElement
!= NULL
) {
2978 FreePool (ConfigElement
);
2987 This helper function is to be called by drivers to map configuration strings
2988 to configurations stored in byte array ("block") formats such as UEFI Variables.
2990 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
2992 @param ConfigResp A null-terminated Unicode string in <ConfigResp>
2993 format. It can be ConfigAltResp format string.
2994 @param Block A possibly null array of bytes representing the
2995 current block. Only bytes referenced in the
2996 ConfigResp string in the block are modified. If
2997 this parameter is null or if the *BlockSize
2998 parameter is (on input) shorter than required by
2999 the Configuration string, only the BlockSize
3000 parameter is updated and an appropriate status
3001 (see below) is returned.
3002 @param BlockSize The length of the Block in units of UINT8. On
3003 input, this is the size of the Block. On output,
3004 if successful, contains the index of the last
3005 modified byte in the Block.
3006 @param Progress On return, points to an element of the ConfigResp
3007 string filled in with the offset of the most
3008 recent '&' before the first failing name / value
3009 pair (or the beginning of the string if the
3010 failure is in the first name / value pair) or the
3011 terminating NULL if all was successful.
3013 @retval EFI_SUCCESS The request succeeded. Progress points to the null
3014 terminator at the end of the ConfigResp string.
3015 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress
3016 points to the first character of ConfigResp.
3017 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigResp or
3018 Block parameter would result in this type of
3019 error. Progress points to the first character of
3021 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted name /
3022 value pair. Block is left updated and
3023 Progress points at the '&' preceding the first
3030 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
3031 IN CONST EFI_STRING ConfigResp
,
3032 IN OUT UINT8
*Block
,
3033 IN OUT UINTN
*BlockSize
,
3034 OUT EFI_STRING
*Progress
3037 HII_DATABASE_PRIVATE_DATA
*Private
;
3038 EFI_STRING StringPtr
;
3047 if (This
== NULL
|| BlockSize
== NULL
|| Progress
== NULL
) {
3048 return EFI_INVALID_PARAMETER
;
3051 if (ConfigResp
== NULL
|| Block
== NULL
) {
3052 *Progress
= ConfigResp
;
3053 return EFI_INVALID_PARAMETER
;
3056 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
3057 ASSERT (Private
!= NULL
);
3059 StringPtr
= ConfigResp
;
3060 BufferSize
= *BlockSize
;
3066 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
3067 *Progress
= StringPtr
;
3068 Status
= EFI_INVALID_PARAMETER
;
3071 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"PATH=", StrLen (L
"PATH=")) != 0) {
3074 if (*StringPtr
== 0) {
3075 *Progress
= StringPtr
;
3076 Status
= EFI_INVALID_PARAMETER
;
3080 while (*StringPtr
!= L
'&' && *StringPtr
!= 0) {
3083 if (*StringPtr
== 0) {
3084 *Progress
= StringPtr
;
3085 Status
= EFI_INVALID_PARAMETER
;
3094 // Parse each <ConfigElement> if exists
3095 // Only <BlockConfig> format is supported by this help function.
3096 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE='<Number>
3098 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"OFFSET=", StrLen (L
"OFFSET=")) == 0) {
3099 StringPtr
+= StrLen (L
"OFFSET=");
3103 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
3104 if (EFI_ERROR (Status
)) {
3105 *Progress
= ConfigResp
;
3112 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
3114 FreePool (TmpBuffer
);
3116 StringPtr
+= Length
;
3117 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
3118 *Progress
= StringPtr
- Length
- StrLen (L
"OFFSET=") - 1;
3119 Status
= EFI_INVALID_PARAMETER
;
3122 StringPtr
+= StrLen (L
"&WIDTH=");
3127 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
3128 if (Status
== EFI_OUT_OF_RESOURCES
) {
3129 *Progress
= ConfigResp
;
3136 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
3138 FreePool (TmpBuffer
);
3140 StringPtr
+= Length
;
3141 if (StrnCmp (StringPtr
, L
"&VALUE=", StrLen (L
"&VALUE=")) != 0) {
3142 *Progress
= StringPtr
- Length
- StrLen (L
"&WIDTH=");
3143 Status
= EFI_INVALID_PARAMETER
;
3146 StringPtr
+= StrLen (L
"&VALUE=");
3151 Status
= GetValueOfNumber (StringPtr
, &Value
, &Length
);
3152 if (EFI_ERROR (Status
)) {
3153 *Progress
= ConfigResp
;
3157 StringPtr
+= Length
;
3158 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
3159 *Progress
= StringPtr
- Length
- 7;
3160 Status
= EFI_INVALID_PARAMETER
;
3165 // Update the Block with configuration info
3168 if (Offset
+ Width
> BufferSize
) {
3169 return EFI_DEVICE_ERROR
;
3172 CopyMem (Block
+ Offset
, Value
, Width
);
3173 *BlockSize
= Offset
+ Width
- 1;
3179 // If '\0', parsing is finished. Otherwise skip '&' to continue
3181 if (*StringPtr
== 0) {
3189 // The input string is ConfigAltResp format.
3191 if ((*StringPtr
!= 0) && (StrnCmp (StringPtr
, L
"&GUID=", StrLen (L
"&GUID=")) != 0)) {
3192 *Progress
= StringPtr
- 1;
3193 Status
= EFI_INVALID_PARAMETER
;
3197 *Progress
= StringPtr
;
3202 if (Value
!= NULL
) {
3210 This helper function is to be called by drivers to extract portions of
3211 a larger configuration string.
3213 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
3215 @param Configuration A null-terminated Unicode string in
3216 <MultiConfigAltResp> format. It is <ConfigAltResp> format.
3217 @param Guid A pointer to the GUID value to search for in the
3218 routing portion of the ConfigResp string when
3219 retrieving the requested data. If Guid is NULL,
3220 then all GUID values will be searched for.
3221 @param Name A pointer to the NAME value to search for in the
3222 routing portion of the ConfigResp string when
3223 retrieving the requested data. If Name is NULL,
3224 then all Name values will be searched for.
3225 @param DevicePath A pointer to the PATH value to search for in the
3226 routing portion of the ConfigResp string when
3227 retrieving the requested data. If DevicePath is
3228 NULL, then all DevicePath values will be searched
3230 @param AltCfgId A pointer to the ALTCFG value to search for in the
3231 routing portion of the ConfigResp string when
3232 retrieving the requested data. If this parameter
3233 is NULL, then the current setting will be
3235 @param AltCfgResp A pointer to a buffer which will be allocated by
3236 the function which contains the retrieved string
3237 as requested. This buffer is only allocated if
3238 the call was successful. It is <ConfigResp> format.
3240 @retval EFI_SUCCESS The request succeeded. The requested data was
3241 extracted and placed in the newly allocated
3243 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate AltCfgResp.
3244 @retval EFI_INVALID_PARAMETER Any parameter is invalid.
3245 @retval EFI_NOT_FOUND Target for the specified routing data was not
3252 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
3253 IN CONST EFI_STRING Configuration
,
3254 IN CONST EFI_GUID
*Guid
,
3255 IN CONST EFI_STRING Name
,
3256 IN CONST EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
3257 IN CONST UINT16
*AltCfgId
,
3258 OUT EFI_STRING
*AltCfgResp
3262 EFI_STRING StringPtr
;
3263 EFI_STRING HdrStart
;
3270 EFI_STRING AltIdStr
;
3287 if (This
== NULL
|| Configuration
== NULL
|| AltCfgResp
== NULL
) {
3288 return EFI_INVALID_PARAMETER
;
3291 StringPtr
= Configuration
;
3292 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
3293 return EFI_INVALID_PARAMETER
;
3297 // Generate the sub string for later matching.
3299 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*) Guid
, 1, &GuidStr
);
3302 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) DevicePath
),
3303 (VOID
*) DevicePath
,
3307 if (AltCfgId
!= NULL
) {
3308 GenerateSubStr (L
"ALTCFG=", sizeof (UINT16
), (VOID
*) AltCfgId
, 3, &AltIdStr
);
3311 GenerateSubStr (L
"NAME=", StrLen (Name
) * sizeof (CHAR16
), (VOID
*) Name
, 2, &NameStr
);
3313 GenerateSubStr (L
"NAME=", 0, NULL
, 2, &NameStr
);
3316 while (*StringPtr
!= 0) {
3318 // Try to match the GUID
3321 TmpPtr
= StrStr (StringPtr
, GuidStr
);
3322 if (TmpPtr
== NULL
) {
3323 Status
= EFI_NOT_FOUND
;
3329 // Jump to <NameHdr>
3332 StringPtr
= TmpPtr
+ StrLen (GuidStr
);
3334 StringPtr
= StrStr (TmpPtr
, L
"NAME=");
3335 if (StringPtr
== NULL
) {
3336 Status
= EFI_NOT_FOUND
;
3344 // Try to match the NAME
3346 if (GuidFlag
&& !NameFlag
) {
3347 if (StrnCmp (StringPtr
, NameStr
, StrLen (NameStr
)) != 0) {
3351 // Jump to <PathHdr>
3354 StringPtr
+= StrLen (NameStr
);
3356 StringPtr
= StrStr (StringPtr
, L
"PATH=");
3357 if (StringPtr
== NULL
) {
3358 Status
= EFI_NOT_FOUND
;
3367 // Try to match the DevicePath
3369 if (GuidFlag
&& NameFlag
&& !PathFlag
) {
3370 if (StrnCmp (StringPtr
, PathStr
, StrLen (PathStr
)) != 0) {
3375 // Jump to '&' before <DescHdr> or <ConfigBody>
3377 if (DevicePath
!= NULL
) {
3378 StringPtr
+= StrLen (PathStr
);
3380 StringPtr
= StrStr (StringPtr
, L
"&");
3381 if (StringPtr
== NULL
) {
3382 Status
= EFI_NOT_FOUND
;
3393 // Try to match the AltCfgId
3395 if (GuidFlag
&& NameFlag
&& PathFlag
) {
3396 if (AltCfgId
== NULL
) {
3398 // Return Current Setting when AltCfgId is NULL.
3400 Status
= OutputConfigBody (StringPtr
, &Result
);
3404 // Search the <ConfigAltResp> to get the <AltResp> with AltCfgId.
3406 if (StrnCmp (StringPtr
, AltIdStr
, StrLen (AltIdStr
)) != 0) {
3412 // Skip AltIdStr and &
3414 StringPtr
= StringPtr
+ StrLen (AltIdStr
);
3415 Status
= OutputConfigBody (StringPtr
, &Result
);
3421 Status
= EFI_NOT_FOUND
;
3425 if (!EFI_ERROR (Status
) && (Result
!= NULL
)) {
3427 // Copy the <ConfigHdr> and <ConfigBody>
3429 Length
= HdrEnd
- HdrStart
+ StrLen (Result
) + 1;
3430 *AltCfgResp
= AllocateZeroPool (Length
* sizeof (CHAR16
));
3431 if (*AltCfgResp
== NULL
) {
3432 Status
= EFI_OUT_OF_RESOURCES
;
3434 StrnCpy (*AltCfgResp
, HdrStart
, HdrEnd
- HdrStart
);
3435 StrCat (*AltCfgResp
, Result
);
3436 Status
= EFI_SUCCESS
;
3440 if (GuidStr
!= NULL
) {
3443 if (NameStr
!= NULL
) {
3446 if (PathStr
!= NULL
) {
3449 if (AltIdStr
!= NULL
) {
3450 FreePool (AltIdStr
);
3452 if (Result
!= NULL
) {