2 Implementation of interfaces function for EFI_HII_CONFIG_ROUTING_PROTOCOL.
4 Copyright (c) 2007 - 2011, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 #include "HiiDatabase.h"
17 extern HII_DATABASE_PRIVATE_DATA mPrivate
;
20 Calculate the number of Unicode characters of the incoming Configuration string,
21 not including NULL terminator.
23 This is a internal function.
25 @param String String in <MultiConfigRequest> or
26 <MultiConfigResp> format.
28 @return The number of Unicode characters.
32 CalculateConfigStringLen (
39 // "GUID=" should be the first element of incoming string.
41 ASSERT (String
!= NULL
);
42 ASSERT (StrnCmp (String
, L
"GUID=", StrLen (L
"GUID=")) == 0);
45 // The beginning of next <ConfigRequest>/<ConfigResp> should be "&GUID=".
46 // Will meet '\0' if there is only one <ConfigRequest>/<ConfigResp>.
48 TmpPtr
= StrStr (String
, L
"&GUID=");
50 return StrLen (String
);
53 return (TmpPtr
- String
);
58 Convert the hex UNICODE %02x encoding of a UEFI device path to binary
59 from <PathHdr> of <ConfigHdr>.
61 This is a internal function.
63 @param String UEFI configuration string
64 @param DevicePathData Binary of a UEFI device path.
66 @retval EFI_NOT_FOUND The device path is not invalid.
67 @retval EFI_INVALID_PARAMETER Any incoming parameter is invalid.
68 @retval EFI_OUT_OF_RESOURCES Lake of resources to store neccesary structures.
69 @retval EFI_SUCCESS The device path is retrieved and translated to
76 OUT UINT8
**DevicePathData
81 UINT8
*DevicePathBuffer
;
85 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
88 if (String
== NULL
|| DevicePathData
== NULL
) {
89 return EFI_INVALID_PARAMETER
;
93 // Find the 'PATH=' of <PathHdr> and skip it.
95 for (; (*String
!= 0 && StrnCmp (String
, L
"PATH=", StrLen (L
"PATH=")) != 0); String
++);
97 return EFI_INVALID_PARAMETER
;
100 // Check whether path data does exist.
102 String
+= StrLen (L
"PATH=");
104 return EFI_INVALID_PARAMETER
;
109 // The content between 'PATH=' of <ConfigHdr> and '&' of next element
110 // or '\0' (end of configuration string) is the UNICODE %02x bytes encoding
111 // of UEFI device path.
113 for (Length
= 0; *String
!= 0 && *String
!= L
'&'; String
++, Length
++);
115 // Check DevicePath Length
117 if (((Length
+ 1) / 2) < sizeof (EFI_DEVICE_PATH_PROTOCOL
)) {
118 return EFI_NOT_FOUND
;
122 // The data in <PathHdr> is encoded as hex UNICODE %02x bytes in the same order
123 // as the device path resides in RAM memory.
124 // Translate the data into binary.
126 DevicePathBuffer
= (UINT8
*) AllocateZeroPool ((Length
+ 1) / 2);
127 if (DevicePathBuffer
== NULL
) {
128 return EFI_OUT_OF_RESOURCES
;
132 // Convert DevicePath
134 ZeroMem (TemStr
, sizeof (TemStr
));
135 for (Index
= 0; Index
< Length
; Index
++) {
136 TemStr
[0] = PathHdr
[Index
];
137 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
138 if ((Index
& 1) == 0) {
139 DevicePathBuffer
[Index
/2] = DigitUint8
;
141 DevicePathBuffer
[Index
/2] = (UINT8
) ((DevicePathBuffer
[Index
/2] << 4) + DigitUint8
);
146 // Validate DevicePath
148 DevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) DevicePathBuffer
;
149 while (!IsDevicePathEnd (DevicePath
)) {
150 if ((DevicePath
->Type
== 0) || (DevicePath
->SubType
== 0) || (DevicePathNodeLength (DevicePath
) < sizeof (EFI_DEVICE_PATH_PROTOCOL
))) {
152 // Invalid device path
154 FreePool (DevicePathBuffer
);
155 return EFI_NOT_FOUND
;
157 DevicePath
= NextDevicePathNode (DevicePath
);
161 // return the device path
163 *DevicePathData
= DevicePathBuffer
;
168 Converts the unicode character of the string from uppercase to lowercase.
169 This is a internal function.
171 @param ConfigString String to be converted
177 IN EFI_STRING ConfigString
183 ASSERT (ConfigString
!= NULL
);
186 // Convert all hex digits in range [A-F] in the configuration header to [a-f]
188 for (String
= ConfigString
, Lower
= FALSE
; *String
!= L
'\0'; String
++) {
189 if (*String
== L
'=') {
191 } else if (*String
== L
'&') {
193 } else if (Lower
&& *String
>= L
'A' && *String
<= L
'F') {
194 *String
= (CHAR16
) (*String
- L
'A' + L
'a');
202 Generate a sub string then output it.
204 This is a internal function.
206 @param String A constant string which is the prefix of the to be
207 generated string, e.g. GUID=
209 @param BufferLen The length of the Buffer in bytes.
211 @param Buffer Points to a buffer which will be converted to be the
212 content of the generated string.
214 @param Flag If 1, the buffer contains data for the value of GUID or PATH stored in
215 UINT8 *; if 2, the buffer contains unicode string for the value of NAME;
216 if 3, the buffer contains other data.
218 @param SubStr Points to the output string. It's caller's
219 responsibility to free this buffer.
225 IN CONST EFI_STRING String
,
229 OUT EFI_STRING
*SubStr
234 EFI_STRING StringHeader
;
240 ASSERT (String
!= NULL
&& SubStr
!= NULL
);
242 if (Buffer
== NULL
) {
243 *SubStr
= AllocateCopyPool (StrSize (String
), String
);
244 ASSERT (*SubStr
!= NULL
);
249 // Header + Data + '&' + '\0'
251 Length
= StrLen (String
) + BufferLen
* 2 + 1 + 1;
252 Str
= AllocateZeroPool (Length
* sizeof (CHAR16
));
253 ASSERT (Str
!= NULL
);
255 StrCpy (Str
, String
);
256 Length
= (BufferLen
* 2 + 1) * sizeof (CHAR16
);
258 StringHeader
= Str
+ StrLen (String
);
259 TemString
= (CHAR16
*) StringHeader
;
264 // Convert Buffer to Hex String in reverse order
266 TemBuffer
= ((UINT8
*) Buffer
);
267 for (Index
= 0; Index
< BufferLen
; Index
++, TemBuffer
++) {
268 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
273 // Check buffer is enough
275 TemName
= (CHAR16
*) Buffer
;
276 ASSERT ((BufferLen
* 2 + 1) >= (StrLen (TemName
) * 4 + 1));
278 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
280 for (; *TemName
!= L
'\0'; TemName
++) {
281 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemName
, 4);
286 // Convert Buffer to Hex String
288 TemBuffer
= ((UINT8
*) Buffer
) + BufferLen
- 1;
289 for (Index
= 0; Index
< BufferLen
; Index
++, TemBuffer
--) {
290 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
298 // Convert the uppercase to lowercase since <HexAf> is defined in lowercase format.
308 Retrieve the <ConfigBody> from String then output it.
310 This is a internal function.
312 @param String A sub string of a configuration string in
313 <MultiConfigAltResp> format.
314 @param ConfigBody Points to the output string. It's caller's
315 responsibility to free this buffer.
317 @retval EFI_INVALID_PARAMETER There is no form package in current hii database.
318 @retval EFI_OUT_OF_RESOURCES Not enough memory to finish this operation.
319 @retval EFI_SUCCESS All existing storage is exported.
324 IN EFI_STRING String
,
325 OUT EFI_STRING
*ConfigBody
332 if (String
== NULL
|| ConfigBody
== NULL
) {
333 return EFI_INVALID_PARAMETER
;
337 // The setting information should start OFFSET, not ALTCFG.
339 if (StrnCmp (String
, L
"&ALTCFG=", StrLen (L
"&ALTCFG=")) == 0) {
340 return EFI_INVALID_PARAMETER
;
343 TmpPtr
= StrStr (String
, L
"GUID=");
344 if (TmpPtr
== NULL
) {
346 // It is the last <ConfigResp> of the incoming configuration string.
348 Result
= AllocateCopyPool (StrSize (String
), String
);
349 if (Result
== NULL
) {
350 return EFI_OUT_OF_RESOURCES
;
352 *ConfigBody
= Result
;
357 Length
= TmpPtr
- String
;
358 Result
= AllocateCopyPool (Length
* sizeof (CHAR16
), String
);
359 if (Result
== NULL
) {
360 return EFI_OUT_OF_RESOURCES
;
363 *(Result
+ Length
- 1) = 0;
364 *ConfigBody
= Result
;
369 Append a string to a multi-string format.
371 This is a internal function.
373 @param MultiString String in <MultiConfigRequest>,
374 <MultiConfigAltResp>, or <MultiConfigResp>. On
375 input, the buffer length of this string is
376 MAX_STRING_LENGTH. On output, the buffer length
378 @param AppendString NULL-terminated Unicode string.
380 @retval EFI_INVALID_PARAMETER Any incoming parameter is invalid.
381 @retval EFI_SUCCESS AppendString is append to the end of MultiString
385 AppendToMultiString (
386 IN OUT EFI_STRING
*MultiString
,
387 IN EFI_STRING AppendString
390 UINTN AppendStringSize
;
391 UINTN MultiStringSize
;
393 if (MultiString
== NULL
|| *MultiString
== NULL
|| AppendString
== NULL
) {
394 return EFI_INVALID_PARAMETER
;
397 AppendStringSize
= StrSize (AppendString
);
398 MultiStringSize
= StrSize (*MultiString
);
401 // Enlarge the buffer each time when length exceeds MAX_STRING_LENGTH.
403 if (MultiStringSize
+ AppendStringSize
> MAX_STRING_LENGTH
||
404 MultiStringSize
> MAX_STRING_LENGTH
) {
405 *MultiString
= (EFI_STRING
) ReallocatePool (
407 MultiStringSize
+ AppendStringSize
,
408 (VOID
*) (*MultiString
)
410 ASSERT (*MultiString
!= NULL
);
413 // Append the incoming string
415 StrCat (*MultiString
, AppendString
);
422 Get the value of <Number> in <BlockConfig> format, i.e. the value of OFFSET
424 <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>
426 This is a internal function.
428 @param StringPtr String in <BlockConfig> format and points to the
429 first character of <Number>.
430 @param Number The output value. Caller takes the responsibility
432 @param Len Length of the <Number>, in characters.
434 @retval EFI_OUT_OF_RESOURCES Insufficient resources to store neccessary
436 @retval EFI_SUCCESS Value of <Number> is outputted in Number
442 IN EFI_STRING StringPtr
,
456 if (StringPtr
== NULL
|| *StringPtr
== L
'\0' || Number
== NULL
|| Len
== NULL
) {
457 return EFI_INVALID_PARAMETER
;
463 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
466 *Len
= StringPtr
- TmpPtr
;
469 Str
= (EFI_STRING
) AllocateZeroPool (Length
* sizeof (CHAR16
));
471 Status
= EFI_OUT_OF_RESOURCES
;
474 CopyMem (Str
, TmpPtr
, *Len
* sizeof (CHAR16
));
475 *(Str
+ *Len
) = L
'\0';
477 Length
= (Length
+ 1) / 2;
478 Buf
= (UINT8
*) AllocateZeroPool (Length
);
480 Status
= EFI_OUT_OF_RESOURCES
;
485 ZeroMem (TemStr
, sizeof (TemStr
));
486 for (Index
= 0; Index
< Length
; Index
++) {
487 TemStr
[0] = Str
[Length
- Index
- 1];
488 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
489 if ((Index
& 1) == 0) {
490 Buf
[Index
/2] = DigitUint8
;
492 Buf
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Buf
[Index
/2]);
497 Status
= EFI_SUCCESS
;
508 This function merges DefaultAltCfgResp string into AltCfgResp string for
509 the missing AltCfgId in AltCfgResq.
511 @param AltCfgResp Pointer to a null-terminated Unicode string in
512 <ConfigAltResp> format. The default value string
513 will be merged into it.
514 @param DefaultAltCfgResp Pointer to a null-terminated Unicode string in
515 <MultiConfigAltResp> format. The default value
516 string may contain more than one ConfigAltResp
517 string for the different varstore buffer.
519 @retval EFI_SUCCESS The merged string returns.
520 @retval EFI_INVALID_PARAMETER *AltCfgResp is to NULL.
525 IN OUT EFI_STRING
*AltCfgResp
,
526 IN EFI_STRING DefaultAltCfgResp
529 EFI_STRING StringPtrDefault
;
530 EFI_STRING StringPtrEnd
;
532 EFI_STRING StringPtr
;
533 EFI_STRING AltConfigHdr
;
535 UINTN SizeAltCfgResp
;
537 if (*AltCfgResp
== NULL
) {
538 return EFI_INVALID_PARAMETER
;
542 // Get the requestr ConfigHdr
545 StringPtr
= *AltCfgResp
;
548 // Find <ConfigHdr> GUID=...&NAME=...&PATH=...
550 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
551 return EFI_INVALID_PARAMETER
;
553 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&NAME=", StrLen (L
"&NAME=")) != 0) {
556 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&PATH=", StrLen (L
"&PATH=")) != 0) {
559 if (*StringPtr
== L
'\0') {
560 return EFI_INVALID_PARAMETER
;
562 StringPtr
+= StrLen (L
"&PATH=");
563 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
566 HeaderLength
= StringPtr
- *AltCfgResp
;
569 // Construct AltConfigHdr string "&<ConfigHdr>&ALTCFG=XXXX\0"
570 // |1| StrLen (ConfigHdr) | 8 | 4 | 1 |
572 AltConfigHdr
= AllocateZeroPool ((1 + HeaderLength
+ 8 + 4 + 1) * sizeof (CHAR16
));
573 if (AltConfigHdr
== NULL
) {
574 return EFI_OUT_OF_RESOURCES
;
576 StrCpy (AltConfigHdr
, L
"&");
577 StrnCat (AltConfigHdr
, *AltCfgResp
, HeaderLength
);
578 StrCat (AltConfigHdr
, L
"&ALTCFG=");
579 HeaderLength
= StrLen (AltConfigHdr
);
581 StringPtrDefault
= StrStr (DefaultAltCfgResp
, AltConfigHdr
);
582 while (StringPtrDefault
!= NULL
) {
586 StrnCat (AltConfigHdr
, StringPtrDefault
+ HeaderLength
, 4);
587 StringPtr
= StrStr (*AltCfgResp
, AltConfigHdr
);
590 // Append the found default value string to the input AltCfgResp
592 if (StringPtr
== NULL
) {
593 StringPtrEnd
= StrStr (StringPtrDefault
+ 1, L
"&GUID");
594 SizeAltCfgResp
= StrSize (*AltCfgResp
);
595 if (StringPtrEnd
== NULL
) {
597 // No more default string is found.
599 *AltCfgResp
= (EFI_STRING
) ReallocatePool (
601 SizeAltCfgResp
+ StrSize (StringPtrDefault
),
602 (VOID
*) (*AltCfgResp
)
604 if (*AltCfgResp
== NULL
) {
605 FreePool (AltConfigHdr
);
606 return EFI_OUT_OF_RESOURCES
;
608 StrCat (*AltCfgResp
, StringPtrDefault
);
611 TempChar
= *StringPtrEnd
;
612 *StringPtrEnd
= L
'\0';
613 *AltCfgResp
= (EFI_STRING
) ReallocatePool (
615 SizeAltCfgResp
+ StrSize (StringPtrDefault
),
616 (VOID
*) (*AltCfgResp
)
618 if (*AltCfgResp
== NULL
) {
619 FreePool (AltConfigHdr
);
620 return EFI_OUT_OF_RESOURCES
;
622 StrCat (*AltCfgResp
, StringPtrDefault
);
623 *StringPtrEnd
= TempChar
;
628 // Find next AltCfg String
630 *(AltConfigHdr
+ HeaderLength
) = L
'\0';
631 StringPtrDefault
= StrStr (StringPtrDefault
+ 1, AltConfigHdr
);
634 FreePool (AltConfigHdr
);
639 This function finds the matched DefaultName for the input DefaultId
641 @param DefaultIdArray Array stores the map table between DefaultId and DefaultName.
642 @param VarDefaultId Default Id
643 @param VarDefaultName Default Name string ID for the input default ID.
645 @retval EFI_SUCCESS The mapped default name string ID is found.
646 @retval EFI_NOT_FOUND The mapped default name string ID is not found.
650 IN IFR_DEFAULT_DATA
*DefaultIdArray
,
651 IN UINT16 VarDefaultId
,
652 OUT EFI_STRING_ID
*VarDefaultName
656 IFR_DEFAULT_DATA
*DefaultData
;
658 for (Link
= DefaultIdArray
->Entry
.ForwardLink
; Link
!= &DefaultIdArray
->Entry
; Link
= Link
->ForwardLink
) {
659 DefaultData
= BASE_CR (Link
, IFR_DEFAULT_DATA
, Entry
);
660 if (DefaultData
->DefaultId
== VarDefaultId
) {
661 *VarDefaultName
= DefaultData
->DefaultName
;
666 return EFI_NOT_FOUND
;
670 This function inserts new DefaultValueData into the BlockData DefaultValue array.
672 @param BlockData The BlockData is updated to add new default value.
673 @param DefaultValueData The DefaultValue is added.
678 IN IFR_BLOCK_DATA
*BlockData
,
679 IN IFR_DEFAULT_DATA
*DefaultValueData
683 IFR_DEFAULT_DATA
*DefaultValueArray
;
685 for (Link
= BlockData
->DefaultValueEntry
.ForwardLink
; Link
!= &BlockData
->DefaultValueEntry
; Link
= Link
->ForwardLink
) {
686 DefaultValueArray
= BASE_CR (Link
, IFR_DEFAULT_DATA
, Entry
);
687 if (DefaultValueArray
->DefaultId
== DefaultValueData
->DefaultId
) {
688 if (DefaultValueData
->OpCode
== EFI_IFR_DEFAULT_OP
) {
690 // Update the default value array in BlockData.
692 DefaultValueArray
->Value
= DefaultValueData
->Value
;
693 } else if (DefaultValueArray
->OpCode
!= EFI_IFR_DEFAULT_OP
) {
695 // Update the default value array in BlockData.
697 DefaultValueArray
->Value
= DefaultValueData
->Value
;
699 FreePool (DefaultValueData
);
701 } else if (DefaultValueArray
->DefaultId
> DefaultValueData
->DefaultId
) {
703 // Insert new default value data in the front of this default value array.
705 InsertTailList (Link
, &DefaultValueData
->Entry
);
711 // Insert new default value data in tail.
713 InsertTailList (Link
, &DefaultValueData
->Entry
);
718 This function inserts new BlockData into the block link
720 @param BlockLink The list entry points to block array.
721 @param BlockData The point to BlockData is added.
726 IN LIST_ENTRY
*BlockLink
,
727 IN IFR_BLOCK_DATA
**BlockData
731 IFR_BLOCK_DATA
*BlockArray
;
732 IFR_BLOCK_DATA
*BlockSingleData
;
734 BlockSingleData
= *BlockData
;
737 // Insert block data in its Offset and Width order.
739 for (Link
= BlockLink
->ForwardLink
; Link
!= BlockLink
; Link
= Link
->ForwardLink
) {
740 BlockArray
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
741 if (BlockArray
->Offset
== BlockSingleData
->Offset
) {
742 if (BlockArray
->Width
> BlockSingleData
->Width
) {
744 // Insert this block data in the front of block array
746 InsertTailList (Link
, &BlockSingleData
->Entry
);
750 if (BlockArray
->Width
== BlockSingleData
->Width
) {
752 // The same block array has been added.
754 FreePool (BlockSingleData
);
755 *BlockData
= BlockArray
;
758 } else if (BlockArray
->Offset
> BlockSingleData
->Offset
) {
760 // Insert new block data in the front of block array
762 InsertTailList (Link
, &BlockSingleData
->Entry
);
768 // Add new block data into the tail.
770 InsertTailList (Link
, &BlockSingleData
->Entry
);
775 This function checks VarOffset and VarWidth is in the block range.
777 @param RequestBlockArray The block array is to be checked.
778 @param VarOffset Offset of var to the structure
779 @param VarWidth Width of var.
781 @retval TRUE This Var is in the block range.
782 @retval FALSE This Var is not in the block range.
786 IN IFR_BLOCK_DATA
*RequestBlockArray
,
792 IFR_BLOCK_DATA
*BlockData
;
795 // No Request Block array, all vars are got.
797 if (RequestBlockArray
== NULL
) {
802 // Check the input var is in the request block range.
804 for (Link
= RequestBlockArray
->Entry
.ForwardLink
; Link
!= &RequestBlockArray
->Entry
; Link
= Link
->ForwardLink
) {
805 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
806 if ((VarOffset
>= BlockData
->Offset
) && ((VarOffset
+ VarWidth
) <= (BlockData
->Offset
+ BlockData
->Width
))) {
815 This function parses Form Package to get the block array and the default
816 value array according to the request ConfigHdr.
818 @param Package Pointer to the form package data.
819 @param PackageLength Length of the pacakge.
820 @param ConfigHdr Request string ConfigHdr. If it is NULL,
821 the first found varstore will be as ConfigHdr.
822 @param RequestBlockArray The block array is retrieved from the request string.
823 @param VarStorageData VarStorage structure contains the got block and default value.
824 @param PIfrDefaultIdArray Point to the got default id and default name array.
826 @retval EFI_SUCCESS The block array and the default value array are got.
827 @retval EFI_INVALID_PARAMETER The varstore defintion in the differnt form pacakges
829 @retval EFI_OUT_OF_RESOURCES No enough memory.
835 IN UINT32 PackageLength
,
836 IN EFI_STRING ConfigHdr
,
837 IN IFR_BLOCK_DATA
*RequestBlockArray
,
838 IN OUT IFR_VARSTORAGE_DATA
*VarStorageData
,
839 OUT IFR_DEFAULT_DATA
*DefaultIdArray
844 EFI_IFR_VARSTORE
*IfrVarStore
;
845 EFI_IFR_OP_HEADER
*IfrOpHdr
;
846 EFI_IFR_ONE_OF
*IfrOneOf
;
847 EFI_IFR_ONE_OF_OPTION
*IfrOneOfOption
;
848 EFI_IFR_DEFAULT
*IfrDefault
;
849 EFI_IFR_ORDERED_LIST
*IfrOrderedList
;
850 EFI_IFR_CHECKBOX
*IfrCheckBox
;
851 EFI_IFR_PASSWORD
*IfrPassword
;
852 EFI_IFR_STRING
*IfrString
;
853 IFR_DEFAULT_DATA
*DefaultData
;
854 IFR_BLOCK_DATA
*BlockData
;
855 CHAR16
*VarStoreName
;
858 EFI_STRING_ID VarDefaultName
;
864 BOOLEAN FirstOneOfOption
;
867 Status
= EFI_SUCCESS
;
874 FirstOneOfOption
= FALSE
;
877 // Go through the form package to parse OpCode one by one.
879 IfrOffset
= sizeof (EFI_HII_PACKAGE_HEADER
);
880 while (IfrOffset
< PackageLength
) {
881 IfrOpHdr
= (EFI_IFR_OP_HEADER
*) (Package
+ IfrOffset
);
883 switch (IfrOpHdr
->OpCode
) {
884 case EFI_IFR_VARSTORE_OP
:
886 // VarStore is found. Don't need to search any more.
888 if (VarStorageData
->Size
!= 0) {
893 // Get the requied varstore information
894 // Add varstore by Guid and Name in ConfigHdr
895 // Make sure Offset is in varstore size and varstoreid
897 IfrVarStore
= (EFI_IFR_VARSTORE
*) IfrOpHdr
;
898 VarStoreName
= AllocateZeroPool (AsciiStrSize ((CHAR8
*)IfrVarStore
->Name
) * sizeof (CHAR16
));
899 if (VarStoreName
== NULL
) {
900 Status
= EFI_OUT_OF_RESOURCES
;
903 AsciiStrToUnicodeStr ((CHAR8
*) IfrVarStore
->Name
, VarStoreName
);
905 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*) &IfrVarStore
->Guid
, 1, &GuidStr
);
906 GenerateSubStr (L
"NAME=", StrLen (VarStoreName
) * sizeof (CHAR16
), (VOID
*) VarStoreName
, 2, &NameStr
);
907 LengthString
= StrLen (GuidStr
);
908 LengthString
= LengthString
+ StrLen (NameStr
) + 1;
909 TempStr
= AllocateZeroPool (LengthString
* sizeof (CHAR16
));
910 if (TempStr
== NULL
) {
913 FreePool (VarStoreName
);
914 Status
= EFI_OUT_OF_RESOURCES
;
917 StrCpy (TempStr
, GuidStr
);
918 StrCat (TempStr
, NameStr
);
919 if (ConfigHdr
== NULL
|| StrnCmp (ConfigHdr
, TempStr
, StrLen (TempStr
)) == 0) {
921 // Find the matched VarStore
923 CopyGuid (&VarStorageData
->Guid
, (EFI_GUID
*) (VOID
*) &IfrVarStore
->Guid
);
924 VarStorageData
->VarStoreId
= IfrVarStore
->VarStoreId
;
925 VarStorageData
->Size
= IfrVarStore
->Size
;
926 VarStorageData
->Name
= VarStoreName
;
929 // No found, free the allocated memory
931 FreePool (VarStoreName
);
934 // Free alllocated temp string.
941 case EFI_IFR_DEFAULTSTORE_OP
:
943 // Add new the map between default id and default name.
945 DefaultData
= (IFR_DEFAULT_DATA
*) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
946 if (DefaultData
== NULL
) {
947 Status
= EFI_OUT_OF_RESOURCES
;
950 DefaultData
->DefaultId
= ((EFI_IFR_DEFAULTSTORE
*) IfrOpHdr
)->DefaultId
;
951 DefaultData
->DefaultName
= ((EFI_IFR_DEFAULTSTORE
*) IfrOpHdr
)->DefaultName
;
952 InsertTailList (&DefaultIdArray
->Entry
, &DefaultData
->Entry
);
956 case EFI_IFR_FORM_OP
:
957 case EFI_IFR_FORM_MAP_OP
:
959 // No matched varstore is found and directly return.
961 if (VarStorageData
->Size
== 0) {
962 Status
= EFI_SUCCESS
;
967 case EFI_IFR_ONE_OF_OP
:
968 case EFI_IFR_NUMERIC_OP
:
970 // Numeric and OneOf has the same opcode structure.
974 // Numeric and OneOf question is not in IFR Form. This IFR form is not valid.
976 if (VarStorageData
->Size
== 0) {
977 Status
= EFI_INVALID_PARAMETER
;
981 // Check whether this question is for the requested varstore.
983 IfrOneOf
= (EFI_IFR_ONE_OF
*) IfrOpHdr
;
984 if (IfrOneOf
->Question
.VarStoreId
!= VarStorageData
->VarStoreId
) {
989 // Get Offset/Width by Question header and OneOf Flags
991 VarOffset
= IfrOneOf
->Question
.VarStoreInfo
.VarOffset
;
992 VarWidth
= (UINT16
) (1 << (IfrOneOf
->Flags
& EFI_IFR_NUMERIC_SIZE
));
994 // Check whether this question is in requested block array.
996 if (!BlockArrayCheck (RequestBlockArray
, VarOffset
, VarWidth
)) {
998 // This question is not in the requested string. Skip it.
1004 // Check this var question is in the var storage
1006 if ((VarOffset
+ VarWidth
) > VarStorageData
->Size
) {
1007 Status
= EFI_INVALID_PARAMETER
;
1014 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
1015 if (BlockData
== NULL
) {
1016 Status
= EFI_OUT_OF_RESOURCES
;
1019 BlockData
->Offset
= VarOffset
;
1020 BlockData
->Width
= VarWidth
;
1021 BlockData
->QuestionId
= IfrOneOf
->Question
.QuestionId
;
1022 BlockData
->OpCode
= IfrOpHdr
->OpCode
;
1023 BlockData
->Scope
= IfrOpHdr
->Scope
;
1024 InitializeListHead (&BlockData
->DefaultValueEntry
);
1026 // Add Block Data into VarStorageData BlockEntry
1028 InsertBlockData (&VarStorageData
->BlockEntry
, &BlockData
);
1030 if (IfrOpHdr
->OpCode
== EFI_IFR_ONE_OF_OP
) {
1032 // Set this flag to TRUE for the first oneof option.
1034 FirstOneOfOption
= TRUE
;
1035 } else if (IfrOpHdr
->OpCode
== EFI_IFR_NUMERIC_OP
) {
1037 // Numeric minimum value will be used as default value when no default is specified.
1041 // Set standard ID and Get DefaultName String ID
1043 VarDefaultId
= EFI_HII_DEFAULT_CLASS_STANDARD
;
1044 Status
= FindDefaultName (DefaultIdArray
, VarDefaultId
, &VarDefaultName
);
1045 if (EFI_ERROR (Status
)) {
1049 // Prepare new DefaultValue
1051 DefaultData
= (IFR_DEFAULT_DATA
*) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
1052 if (DefaultData
== NULL
) {
1053 Status
= EFI_OUT_OF_RESOURCES
;
1056 DefaultData
->OpCode
= IfrOpHdr
->OpCode
;
1057 DefaultData
->DefaultId
= VarDefaultId
;
1058 DefaultData
->DefaultName
= VarDefaultName
;
1060 switch (IfrOneOf
->Flags
& EFI_IFR_NUMERIC_SIZE
) {
1061 case EFI_IFR_NUMERIC_SIZE_1
:
1062 DefaultData
->Value
= (UINT64
) IfrOneOf
->data
.u8
.MinValue
;
1065 case EFI_IFR_NUMERIC_SIZE_2
:
1066 CopyMem (&DefaultData
->Value
, &IfrOneOf
->data
.u16
.MinValue
, sizeof (UINT16
));
1069 case EFI_IFR_NUMERIC_SIZE_4
:
1070 CopyMem (&DefaultData
->Value
, &IfrOneOf
->data
.u32
.MinValue
, sizeof (UINT32
));
1073 case EFI_IFR_NUMERIC_SIZE_8
:
1074 CopyMem (&DefaultData
->Value
, &IfrOneOf
->data
.u64
.MinValue
, sizeof (UINT64
));
1078 // Add DefaultValue into current BlockData
1080 InsertDefaultValue (BlockData
, DefaultData
);
1084 case EFI_IFR_ORDERED_LIST_OP
:
1086 // offset by question header
1087 // width by EFI_IFR_ORDERED_LIST MaxContainers * OneofOption Type
1088 // no default value and default id, how to define its default value?
1092 // OrderedList question is not in IFR Form. This IFR form is not valid.
1094 if (VarStorageData
->Size
== 0) {
1095 Status
= EFI_INVALID_PARAMETER
;
1099 // Check whether this question is for the requested varstore.
1101 IfrOrderedList
= (EFI_IFR_ORDERED_LIST
*) IfrOpHdr
;
1102 if (IfrOrderedList
->Question
.VarStoreId
!= VarStorageData
->VarStoreId
) {
1108 // Get Offset/Width by Question header and OneOf Flags
1110 VarOffset
= IfrOrderedList
->Question
.VarStoreInfo
.VarOffset
;
1111 VarWidth
= IfrOrderedList
->MaxContainers
;
1116 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
1117 if (BlockData
== NULL
) {
1118 Status
= EFI_OUT_OF_RESOURCES
;
1121 BlockData
->Offset
= VarOffset
;
1122 BlockData
->Width
= VarWidth
;
1123 BlockData
->QuestionId
= IfrOrderedList
->Question
.QuestionId
;
1124 BlockData
->OpCode
= IfrOpHdr
->OpCode
;
1125 BlockData
->Scope
= IfrOpHdr
->Scope
;
1126 InitializeListHead (&BlockData
->DefaultValueEntry
);
1129 case EFI_IFR_CHECKBOX_OP
:
1131 // EFI_IFR_DEFAULT_OP
1132 // offset by question header
1133 // width is 1 sizeof (BOOLEAN)
1134 // default id by CheckBox Flags if CheckBox flags (Default or Mau) is set, the default value is 1 to be set.
1135 // value by DefaultOption
1136 // default id by DeaultOption DefaultId can override CheckBox Flags and Default value.
1140 // CheckBox question is not in IFR Form. This IFR form is not valid.
1142 if (VarStorageData
->Size
== 0) {
1143 Status
= EFI_INVALID_PARAMETER
;
1147 // Check whether this question is for the requested varstore.
1149 IfrCheckBox
= (EFI_IFR_CHECKBOX
*) IfrOpHdr
;
1150 if (IfrCheckBox
->Question
.VarStoreId
!= VarStorageData
->VarStoreId
) {
1155 // Get Offset/Width by Question header and OneOf Flags
1157 VarOffset
= IfrCheckBox
->Question
.VarStoreInfo
.VarOffset
;
1158 VarWidth
= (UINT16
) sizeof (BOOLEAN
);
1161 // Check whether this question is in requested block array.
1163 if (!BlockArrayCheck (RequestBlockArray
, VarOffset
, VarWidth
)) {
1165 // This question is not in the requested string. Skip it.
1171 // Check this var question is in the var storage
1173 if ((VarOffset
+ VarWidth
) > VarStorageData
->Size
) {
1174 Status
= EFI_INVALID_PARAMETER
;
1181 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
1182 if (BlockData
== NULL
) {
1183 Status
= EFI_OUT_OF_RESOURCES
;
1186 BlockData
->Offset
= VarOffset
;
1187 BlockData
->Width
= VarWidth
;
1188 BlockData
->QuestionId
= IfrCheckBox
->Question
.QuestionId
;
1189 BlockData
->OpCode
= IfrOpHdr
->OpCode
;
1190 BlockData
->Scope
= IfrOpHdr
->Scope
;
1191 InitializeListHead (&BlockData
->DefaultValueEntry
);
1193 // Add Block Data into VarStorageData BlockEntry
1195 InsertBlockData (&VarStorageData
->BlockEntry
, &BlockData
);
1198 // Add default value by CheckBox Flags
1200 if ((IfrCheckBox
->Flags
& EFI_IFR_CHECKBOX_DEFAULT
) == EFI_IFR_CHECKBOX_DEFAULT
) {
1202 // Set standard ID to Manufacture ID and Get DefaultName String ID
1204 VarDefaultId
= EFI_HII_DEFAULT_CLASS_STANDARD
;
1205 Status
= FindDefaultName (DefaultIdArray
, VarDefaultId
, &VarDefaultName
);
1206 if (EFI_ERROR (Status
)) {
1210 // Prepare new DefaultValue
1212 DefaultData
= (IFR_DEFAULT_DATA
*) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
1213 if (DefaultData
== NULL
) {
1214 Status
= EFI_OUT_OF_RESOURCES
;
1217 DefaultData
->OpCode
= IfrOpHdr
->OpCode
;
1218 DefaultData
->DefaultId
= VarDefaultId
;
1219 DefaultData
->DefaultName
= VarDefaultName
;
1220 DefaultData
->Value
= 1;
1222 // Add DefaultValue into current BlockData
1224 InsertDefaultValue (BlockData
, DefaultData
);
1227 if ((IfrCheckBox
->Flags
& EFI_IFR_CHECKBOX_DEFAULT_MFG
) == EFI_IFR_CHECKBOX_DEFAULT_MFG
) {
1229 // Set standard ID to Manufacture ID and Get DefaultName String ID
1231 VarDefaultId
= EFI_HII_DEFAULT_CLASS_MANUFACTURING
;
1232 Status
= FindDefaultName (DefaultIdArray
, VarDefaultId
, &VarDefaultName
);
1233 if (EFI_ERROR (Status
)) {
1237 // Prepare new DefaultValue
1239 DefaultData
= (IFR_DEFAULT_DATA
*) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
1240 if (DefaultData
== NULL
) {
1241 Status
= EFI_OUT_OF_RESOURCES
;
1244 DefaultData
->OpCode
= IfrOpHdr
->OpCode
;
1245 DefaultData
->DefaultId
= VarDefaultId
;
1246 DefaultData
->DefaultName
= VarDefaultName
;
1247 DefaultData
->Value
= 1;
1249 // Add DefaultValue into current BlockData
1251 InsertDefaultValue (BlockData
, DefaultData
);
1255 case EFI_IFR_STRING_OP
:
1257 // offset by question header
1258 // width MaxSize * sizeof (CHAR16)
1259 // no default value, only block array
1263 // String question is not in IFR Form. This IFR form is not valid.
1265 if (VarStorageData
->Size
== 0) {
1266 Status
= EFI_INVALID_PARAMETER
;
1270 // Check whether this question is for the requested varstore.
1272 IfrString
= (EFI_IFR_STRING
*) IfrOpHdr
;
1273 if (IfrString
->Question
.VarStoreId
!= VarStorageData
->VarStoreId
) {
1278 // Get Offset/Width by Question header and OneOf Flags
1280 VarOffset
= IfrString
->Question
.VarStoreInfo
.VarOffset
;
1281 VarWidth
= (UINT16
) (IfrString
->MaxSize
* sizeof (UINT16
));
1284 // Check whether this question is in requested block array.
1286 if (!BlockArrayCheck (RequestBlockArray
, VarOffset
, VarWidth
)) {
1288 // This question is not in the requested string. Skip it.
1294 // Check this var question is in the var storage
1296 if ((VarOffset
+ VarWidth
) > VarStorageData
->Size
) {
1297 Status
= EFI_INVALID_PARAMETER
;
1304 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
1305 if (BlockData
== NULL
) {
1306 Status
= EFI_OUT_OF_RESOURCES
;
1309 BlockData
->Offset
= VarOffset
;
1310 BlockData
->Width
= VarWidth
;
1311 BlockData
->QuestionId
= IfrString
->Question
.QuestionId
;
1312 BlockData
->OpCode
= IfrOpHdr
->OpCode
;
1313 InitializeListHead (&BlockData
->DefaultValueEntry
);
1316 // Add Block Data into VarStorageData BlockEntry
1318 InsertBlockData (&VarStorageData
->BlockEntry
, &BlockData
);
1321 // No default value for string.
1326 case EFI_IFR_PASSWORD_OP
:
1328 // offset by question header
1329 // width MaxSize * sizeof (CHAR16)
1330 // no default value, only block array
1334 // Password question is not in IFR Form. This IFR form is not valid.
1336 if (VarStorageData
->Size
== 0) {
1337 Status
= EFI_INVALID_PARAMETER
;
1341 // Check whether this question is for the requested varstore.
1343 IfrPassword
= (EFI_IFR_PASSWORD
*) IfrOpHdr
;
1344 if (IfrPassword
->Question
.VarStoreId
!= VarStorageData
->VarStoreId
) {
1349 // Get Offset/Width by Question header and OneOf Flags
1351 VarOffset
= IfrPassword
->Question
.VarStoreInfo
.VarOffset
;
1352 VarWidth
= (UINT16
) (IfrPassword
->MaxSize
* sizeof (UINT16
));
1355 // Check whether this question is in requested block array.
1357 if (!BlockArrayCheck (RequestBlockArray
, VarOffset
, VarWidth
)) {
1359 // This question is not in the requested string. Skip it.
1365 // Check this var question is in the var storage
1367 if ((VarOffset
+ VarWidth
) > VarStorageData
->Size
) {
1368 Status
= EFI_INVALID_PARAMETER
;
1375 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
1376 if (BlockData
== NULL
) {
1377 Status
= EFI_OUT_OF_RESOURCES
;
1380 BlockData
->Offset
= VarOffset
;
1381 BlockData
->Width
= VarWidth
;
1382 BlockData
->QuestionId
= IfrPassword
->Question
.QuestionId
;
1383 BlockData
->OpCode
= IfrOpHdr
->OpCode
;
1384 InitializeListHead (&BlockData
->DefaultValueEntry
);
1387 // Add Block Data into VarStorageData BlockEntry
1389 InsertBlockData (&VarStorageData
->BlockEntry
, &BlockData
);
1392 // No default value for string.
1397 case EFI_IFR_ONE_OF_OPTION_OP
:
1399 // No matched block data is ignored.
1401 if (BlockData
== NULL
|| BlockData
->Scope
== 0) {
1405 IfrOneOfOption
= (EFI_IFR_ONE_OF_OPTION
*) IfrOpHdr
;
1406 if (BlockData
->OpCode
== EFI_IFR_ORDERED_LIST_OP
) {
1408 // Get ordered list option data type.
1410 if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_8
|| IfrOneOfOption
->Type
== EFI_IFR_TYPE_BOOLEAN
) {
1412 } else if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_16
) {
1414 } else if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_32
) {
1416 } else if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_64
) {
1420 // Invalid ordered list option data type.
1422 Status
= EFI_INVALID_PARAMETER
;
1423 FreePool (BlockData
);
1428 // Calculate Ordered list QuestionId width.
1430 BlockData
->Width
= (UINT16
) (BlockData
->Width
* VarWidth
);
1432 // Check whether this question is in requested block array.
1434 if (!BlockArrayCheck (RequestBlockArray
, BlockData
->Offset
, BlockData
->Width
)) {
1436 // This question is not in the requested string. Skip it.
1438 FreePool (BlockData
);
1443 // Check this var question is in the var storage
1445 if ((BlockData
->Offset
+ BlockData
->Width
) > VarStorageData
->Size
) {
1446 Status
= EFI_INVALID_PARAMETER
;
1447 FreePool (BlockData
);
1451 // Add Block Data into VarStorageData BlockEntry
1453 InsertBlockData (&VarStorageData
->BlockEntry
, &BlockData
);
1455 // No default data for OrderedList.
1461 if (((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT
) == EFI_IFR_OPTION_DEFAULT
) ||
1462 (BlockData
->OpCode
== EFI_IFR_ONE_OF_OP
&& FirstOneOfOption
)) {
1464 // This flag is used to specify whether this option is the first. Set it to FALSE for the following options.
1465 // The first oneof option value will be used as default value when no default value is specified.
1467 FirstOneOfOption
= FALSE
;
1469 // Set standard ID to Manufacture ID and Get DefaultName String ID
1471 VarDefaultId
= EFI_HII_DEFAULT_CLASS_STANDARD
;
1472 Status
= FindDefaultName (DefaultIdArray
, VarDefaultId
, &VarDefaultName
);
1473 if (EFI_ERROR (Status
)) {
1477 // Prepare new DefaultValue
1479 DefaultData
= (IFR_DEFAULT_DATA
*) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
1480 if (DefaultData
== NULL
) {
1481 Status
= EFI_OUT_OF_RESOURCES
;
1484 DefaultData
->OpCode
= IfrOpHdr
->OpCode
;
1485 DefaultData
->DefaultId
= VarDefaultId
;
1486 DefaultData
->DefaultName
= VarDefaultName
;
1487 DefaultData
->Value
= IfrOneOfOption
->Value
.u64
;
1489 // Add DefaultValue into current BlockData
1491 InsertDefaultValue (BlockData
, DefaultData
);
1494 if ((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT_MFG
) == EFI_IFR_OPTION_DEFAULT_MFG
) {
1496 // Set default ID to Manufacture ID and Get DefaultName String ID
1498 VarDefaultId
= EFI_HII_DEFAULT_CLASS_MANUFACTURING
;
1499 Status
= FindDefaultName (DefaultIdArray
, VarDefaultId
, &VarDefaultName
);
1500 if (EFI_ERROR (Status
)) {
1504 // Prepare new DefaultValue
1506 DefaultData
= (IFR_DEFAULT_DATA
*) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
1507 if (DefaultData
== NULL
) {
1508 Status
= EFI_OUT_OF_RESOURCES
;
1511 DefaultData
->OpCode
= IfrOpHdr
->OpCode
;
1512 DefaultData
->DefaultId
= VarDefaultId
;
1513 DefaultData
->DefaultName
= VarDefaultName
;
1514 DefaultData
->Value
= IfrOneOfOption
->Value
.u64
;
1516 // Add DefaultValue into current BlockData
1518 InsertDefaultValue (BlockData
, DefaultData
);
1522 case EFI_IFR_DEFAULT_OP
:
1524 // Update Current BlockData to the default value.
1526 if (BlockData
== NULL
|| BlockData
->Scope
== 0) {
1528 // No matched block data is ignored.
1533 if (BlockData
->OpCode
== EFI_IFR_ORDERED_LIST_OP
) {
1535 // OrderedList Opcode is no default value.
1540 // Get the DefaultId and DefaultName String ID
1542 IfrDefault
= (EFI_IFR_DEFAULT
*) IfrOpHdr
;
1543 VarDefaultId
= IfrDefault
->DefaultId
;
1544 Status
= FindDefaultName (DefaultIdArray
, VarDefaultId
, &VarDefaultName
);
1545 if (EFI_ERROR (Status
)) {
1549 // Prepare new DefaultValue
1551 DefaultData
= (IFR_DEFAULT_DATA
*) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
1552 if (DefaultData
== NULL
) {
1553 Status
= EFI_OUT_OF_RESOURCES
;
1556 DefaultData
->OpCode
= IfrOpHdr
->OpCode
;
1557 DefaultData
->DefaultId
= VarDefaultId
;
1558 DefaultData
->DefaultName
= VarDefaultName
;
1559 DefaultData
->Value
= IfrDefault
->Value
.u64
;
1561 // Add DefaultValue into current BlockData
1563 InsertDefaultValue (BlockData
, DefaultData
);
1565 case EFI_IFR_END_OP
:
1567 // End Opcode is for Var question.
1569 if (BlockData
!= NULL
&& BlockData
->Scope
> 0) {
1574 if (BlockData
!= NULL
&& BlockData
->Scope
> 0) {
1575 BlockData
->Scope
= (UINT8
) (BlockData
->Scope
+ IfrOpHdr
->Scope
);
1580 IfrOffset
+= IfrOpHdr
->Length
;
1588 This function gets the full request string and full default value string by
1589 parsing IFR data in HII form packages.
1591 When Request points to NULL string, the request string and default value string
1592 for each varstore in form package will return.
1594 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
1595 @param DevicePath Device Path which Hii Config Access Protocol is registered.
1596 @param Request Pointer to a null-terminated Unicode string in
1597 <ConfigRequest> format. When it doesn't contain
1598 any RequestElement, it will be updated to return
1599 the full RequestElement retrieved from IFR data.
1600 If it points to NULL, the request string for the first
1601 varstore in form package will be merged into a
1602 <MultiConfigRequest> format string and return.
1603 @param AltCfgResp Pointer to a null-terminated Unicode string in
1604 <ConfigAltResp> format. When the pointer is to NULL,
1605 the full default value string retrieved from IFR data
1606 will return. When the pinter is to a string, the
1607 full default value string retrieved from IFR data
1608 will be merged into the input string and return.
1609 When Request points to NULL, the default value string
1610 for each varstore in form package will be merged into
1611 a <MultiConfigAltResp> format string and return.
1612 @param PointerProgress Optional parameter, it can be be NULL.
1613 When it is not NULL, if Request is NULL, it returns NULL.
1614 On return, points to a character in the Request
1615 string. Points to the string's null terminator if
1616 request was successful. Points to the most recent
1617 & before the first failing name / value pair (or
1618 the beginning of the string if the failure is in
1619 the first name / value pair) if the request was
1621 @retval EFI_SUCCESS The Results string is set to the full request string.
1622 And AltCfgResp contains all default value string.
1623 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
1624 @retval EFI_NOT_FOUND The varstore (Guid and Name) in Request string
1625 can't be found in Form package.
1626 @retval EFI_NOT_FOUND HiiPackage can't be got on the input HiiHandle.
1627 @retval EFI_INVALID_PARAMETER Request points to NULL.
1632 GetFullStringFromHiiFormPackages (
1633 IN HII_DATABASE_RECORD
*DataBaseRecord
,
1634 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
1635 IN OUT EFI_STRING
*Request
,
1636 IN OUT EFI_STRING
*AltCfgResp
,
1637 OUT EFI_STRING
*PointerProgress OPTIONAL
1641 UINT8
*HiiFormPackage
;
1644 IFR_BLOCK_DATA
*RequestBlockArray
;
1645 IFR_BLOCK_DATA
*BlockData
;
1646 IFR_BLOCK_DATA
*NextBlockData
;
1647 IFR_DEFAULT_DATA
*DefaultValueData
;
1648 IFR_DEFAULT_DATA
*DefaultId
;
1649 IFR_DEFAULT_DATA
*DefaultIdArray
;
1650 IFR_VARSTORAGE_DATA
*VarStorageData
;
1651 EFI_STRING DefaultAltCfgResp
;
1652 EFI_STRING FullConfigRequest
;
1653 EFI_STRING ConfigHdr
;
1657 EFI_STRING StringPtr
;
1658 EFI_STRING Progress
;
1664 LIST_ENTRY
*LinkData
;
1665 LIST_ENTRY
*LinkDefault
;
1668 if (DataBaseRecord
== NULL
|| DevicePath
== NULL
|| Request
== NULL
|| AltCfgResp
== NULL
) {
1669 return EFI_INVALID_PARAMETER
;
1673 // Initialize the local variables.
1675 RequestBlockArray
= NULL
;
1676 DefaultIdArray
= NULL
;
1677 VarStorageData
= NULL
;
1678 DefaultAltCfgResp
= NULL
;
1679 FullConfigRequest
= NULL
;
1684 HiiFormPackage
= NULL
;
1688 Progress
= *Request
;
1691 // 0. Get Hii Form Package by HiiHandle
1693 Status
= ExportFormPackages (
1695 DataBaseRecord
->Handle
,
1696 DataBaseRecord
->PackageList
,
1702 if (EFI_ERROR (Status
)) {
1706 HiiFormPackage
= AllocatePool (ResultSize
);
1707 if (HiiFormPackage
== NULL
) {
1708 Status
= EFI_OUT_OF_RESOURCES
;
1713 // Get HiiFormPackage by HiiHandle
1715 PackageSize
= ResultSize
;
1717 Status
= ExportFormPackages (
1719 DataBaseRecord
->Handle
,
1720 DataBaseRecord
->PackageList
,
1726 if (EFI_ERROR (Status
)) {
1731 // 1. Get the request block array by Request String when Request string containts the block array.
1734 if (*Request
!= NULL
) {
1735 StringPtr
= *Request
;
1739 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
1740 Status
= EFI_INVALID_PARAMETER
;
1743 StringPtr
+= StrLen (L
"GUID=");
1744 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&NAME=", StrLen (L
"&NAME=")) != 0) {
1747 if (*StringPtr
== L
'\0') {
1748 Status
= EFI_INVALID_PARAMETER
;
1751 StringPtr
+= StrLen (L
"&NAME=");
1752 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&PATH=", StrLen (L
"&PATH=")) != 0) {
1755 if (*StringPtr
== L
'\0') {
1756 Status
= EFI_INVALID_PARAMETER
;
1759 StringPtr
+= StrLen (L
"&PATH=");
1760 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
1764 // Check the following string &OFFSET=
1766 if (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) != 0) {
1767 Progress
= StringPtr
;
1768 Status
= EFI_INVALID_PARAMETER
;
1770 } else if (*StringPtr
== L
'\0') {
1772 // No request block is found.
1777 if (StringPtr
!= NULL
) {
1779 // Init RequestBlockArray
1781 RequestBlockArray
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
1782 if (RequestBlockArray
== NULL
) {
1783 Status
= EFI_OUT_OF_RESOURCES
;
1786 InitializeListHead (&RequestBlockArray
->Entry
);
1789 // Get the request Block array from the request string
1794 // Parse each <RequestElement> if exists
1795 // Only <BlockName> format is supported by this help function.
1796 // <BlockName> ::= &'OFFSET='<Number>&'WIDTH='<Number>
1798 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) == 0) {
1800 // Skip the OFFSET string
1802 Progress
= StringPtr
;
1803 StringPtr
+= StrLen (L
"&OFFSET=");
1807 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
1808 if (EFI_ERROR (Status
)) {
1815 (((Length
+ 1) / 2) < sizeof (UINT16
)) ? ((Length
+ 1) / 2) : sizeof (UINT16
)
1817 FreePool (TmpBuffer
);
1819 StringPtr
+= Length
;
1820 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
1821 Status
= EFI_INVALID_PARAMETER
;
1824 StringPtr
+= StrLen (L
"&WIDTH=");
1829 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
1830 if (EFI_ERROR (Status
)) {
1837 (((Length
+ 1) / 2) < sizeof (UINT16
)) ? ((Length
+ 1) / 2) : sizeof (UINT16
)
1839 FreePool (TmpBuffer
);
1841 StringPtr
+= Length
;
1842 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
1843 Status
= EFI_INVALID_PARAMETER
;
1850 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
1851 if (BlockData
== NULL
) {
1852 Status
= EFI_OUT_OF_RESOURCES
;
1855 BlockData
->Offset
= Offset
;
1856 BlockData
->Width
= Width
;
1857 InsertBlockData (&RequestBlockArray
->Entry
, &BlockData
);
1860 // Skip &VALUE string if &VALUE does exists.
1862 if (StrnCmp (StringPtr
, L
"&VALUE=", StrLen (L
"&VALUE=")) == 0) {
1863 StringPtr
+= StrLen (L
"&VALUE=");
1868 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
1869 if (EFI_ERROR (Status
)) {
1870 Status
= EFI_INVALID_PARAMETER
;
1874 StringPtr
+= Length
;
1875 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
1876 Status
= EFI_INVALID_PARAMETER
;
1881 // If '\0', parsing is finished.
1883 if (*StringPtr
== 0) {
1889 // Merge the requested block data.
1891 Link
= RequestBlockArray
->Entry
.ForwardLink
;
1892 while ((Link
!= &RequestBlockArray
->Entry
) && (Link
->ForwardLink
!= &RequestBlockArray
->Entry
)) {
1893 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
1894 NextBlockData
= BASE_CR (Link
->ForwardLink
, IFR_BLOCK_DATA
, Entry
);
1895 if ((NextBlockData
->Offset
>= BlockData
->Offset
) && (NextBlockData
->Offset
<= (BlockData
->Offset
+ BlockData
->Width
))) {
1896 if ((NextBlockData
->Offset
+ NextBlockData
->Width
) > (BlockData
->Offset
+ BlockData
->Width
)) {
1897 BlockData
->Width
= (UINT16
) (NextBlockData
->Offset
+ NextBlockData
->Width
- BlockData
->Offset
);
1899 RemoveEntryList (Link
->ForwardLink
);
1900 FreePool (NextBlockData
);
1903 Link
= Link
->ForwardLink
;
1908 // 2. Parse FormPackage to get BlockArray and DefaultId Array for the request BlockArray.
1912 // Initialize DefaultIdArray to store the map between DeaultId and DefaultName
1914 DefaultIdArray
= (IFR_DEFAULT_DATA
*) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
1915 if (DefaultIdArray
== NULL
) {
1916 Status
= EFI_OUT_OF_RESOURCES
;
1919 InitializeListHead (&DefaultIdArray
->Entry
);
1922 // Initialize VarStorageData to store the var store Block and Default value information.
1924 VarStorageData
= (IFR_VARSTORAGE_DATA
*) AllocateZeroPool (sizeof (IFR_VARSTORAGE_DATA
));
1925 if (VarStorageData
== NULL
) {
1926 Status
= EFI_OUT_OF_RESOURCES
;
1929 InitializeListHead (&VarStorageData
->Entry
);
1930 InitializeListHead (&VarStorageData
->BlockEntry
);
1933 // Parse the opcode in form pacakge to get the default setting.
1935 Status
= ParseIfrData (HiiFormPackage
, (UINT32
) PackageSize
, *Request
, RequestBlockArray
, VarStorageData
, DefaultIdArray
);
1936 if (EFI_ERROR (Status
)) {
1941 // No requested varstore in IFR data and directly return
1943 if (VarStorageData
->Size
== 0) {
1944 Status
= EFI_SUCCESS
;
1949 // 3. Construct Request Element (Block Name) for 2.1 and 2.2 case.
1953 // Construct <ConfigHdr> : "GUID=...&NAME=...&PATH=..." by VarStorageData Guid, Name and DriverHandle
1955 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*) &VarStorageData
->Guid
, 1, &GuidStr
);
1956 GenerateSubStr (L
"NAME=", StrLen (VarStorageData
->Name
) * sizeof (CHAR16
), (VOID
*) VarStorageData
->Name
, 2, &NameStr
);
1959 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) DevicePath
),
1960 (VOID
*) DevicePath
,
1964 Length
= StrLen (GuidStr
);
1965 Length
= Length
+ StrLen (NameStr
);
1966 Length
= Length
+ StrLen (PathStr
) + 1;
1967 ConfigHdr
= AllocateZeroPool (Length
* sizeof (CHAR16
));
1968 if (ConfigHdr
== NULL
) {
1969 Status
= EFI_OUT_OF_RESOURCES
;
1972 StrCpy (ConfigHdr
, GuidStr
);
1973 StrCat (ConfigHdr
, NameStr
);
1974 StrCat (ConfigHdr
, PathStr
);
1977 // Remove the last character L'&'
1979 *(ConfigHdr
+ StrLen (ConfigHdr
) - 1) = L
'\0';
1981 if (RequestBlockArray
== NULL
) {
1983 // Append VarStorageData BlockEntry into *Request string
1984 // Now support only one varstore in a form package.
1988 // Go through all VarStorageData Entry and get BlockEntry for each one for the multiple varstore in a single form package
1989 // Then construct them all to return MultiRequest string : ConfigHdr BlockConfig
1993 // Compute the length of the entire request starting with <ConfigHdr> and a
1997 Length
= StrLen (ConfigHdr
) + 1;
1999 for (Link
= VarStorageData
->BlockEntry
.ForwardLink
; Link
!= &VarStorageData
->BlockEntry
; Link
= Link
->ForwardLink
) {
2001 // Add <BlockName> length for each Offset/Width pair
2003 // <BlockName> ::= &OFFSET=1234&WIDTH=1234
2004 // | 8 | 4 | 7 | 4 |
2007 Length
= Length
+ (8 + 4 + 7 + 4);
2011 // No any request block data is found. The request string can't be constructed.
2014 Status
= EFI_SUCCESS
;
2019 // Allocate buffer for the entire <ConfigRequest>
2021 FullConfigRequest
= AllocateZeroPool (Length
* sizeof (CHAR16
));
2022 if (FullConfigRequest
== NULL
) {
2023 Status
= EFI_OUT_OF_RESOURCES
;
2026 StringPtr
= FullConfigRequest
;
2029 // Start with <ConfigHdr>
2031 StrCpy (StringPtr
, ConfigHdr
);
2032 StringPtr
+= StrLen (StringPtr
);
2035 // Loop through all the Offset/Width pairs and append them to ConfigRequest
2037 for (Link
= VarStorageData
->BlockEntry
.ForwardLink
; Link
!= &VarStorageData
->BlockEntry
; Link
= Link
->ForwardLink
) {
2038 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
2040 // Append &OFFSET=XXXX&WIDTH=YYYY\0
2044 (8 + 4 + 7 + 4 + 1) * sizeof (CHAR16
),
2045 L
"&OFFSET=%04X&WIDTH=%04X",
2049 StringPtr
+= StrLen (StringPtr
);
2052 // Set to the got full request string.
2054 HiiToLower (FullConfigRequest
);
2055 if (*Request
!= NULL
) {
2056 FreePool (*Request
);
2058 *Request
= FullConfigRequest
;
2062 // 4. Construct Default Value string in AltResp according to request element.
2063 // Go through all VarStorageData Entry and get the DefaultId array for each one
2064 // Then construct them all to : ConfigHdr AltConfigHdr ConfigBody AltConfigHdr ConfigBody
2068 // Add length for <ConfigHdr> + '\0'
2070 Length
= StrLen (ConfigHdr
) + 1;
2072 for (Link
= DefaultIdArray
->Entry
.ForwardLink
; Link
!= &DefaultIdArray
->Entry
; Link
= Link
->ForwardLink
) {
2073 DefaultId
= BASE_CR (Link
, IFR_DEFAULT_DATA
, Entry
);
2075 // Add length for "&<ConfigHdr>&ALTCFG=XXXX"
2076 // |1| StrLen (ConfigHdr) | 8 | 4 |
2078 Length
+= (1 + StrLen (ConfigHdr
) + 8 + 4);
2080 for (LinkData
= VarStorageData
->BlockEntry
.ForwardLink
; LinkData
!= &VarStorageData
->BlockEntry
; LinkData
= LinkData
->ForwardLink
) {
2081 BlockData
= BASE_CR (LinkData
, IFR_BLOCK_DATA
, Entry
);
2082 for (LinkDefault
= BlockData
->DefaultValueEntry
.ForwardLink
; LinkDefault
!= &BlockData
->DefaultValueEntry
; LinkDefault
= LinkDefault
->ForwardLink
) {
2083 DefaultValueData
= BASE_CR (LinkDefault
, IFR_DEFAULT_DATA
, Entry
);
2084 if (DefaultValueData
->DefaultId
== DefaultId
->DefaultId
) {
2086 // Add length for "&OFFSET=XXXX&WIDTH=YYYY&VALUE=zzzzzzzzzzzz"
2087 // | 8 | 4 | 7 | 4 | 7 | Width * 2 |
2089 Length
+= (8 + 4 + 7 + 4 + 7 + BlockData
->Width
* 2);
2097 // No default value is found. The default string doesn't exist.
2100 Status
= EFI_SUCCESS
;
2105 // Allocate buffer for the entire <DefaultAltCfgResp>
2107 DefaultAltCfgResp
= AllocateZeroPool (Length
* sizeof (CHAR16
));
2108 if (DefaultAltCfgResp
== NULL
) {
2109 Status
= EFI_OUT_OF_RESOURCES
;
2112 StringPtr
= DefaultAltCfgResp
;
2115 // Start with <ConfigHdr>
2117 StrCpy (StringPtr
, ConfigHdr
);
2118 StringPtr
+= StrLen (StringPtr
);
2120 for (Link
= DefaultIdArray
->Entry
.ForwardLink
; Link
!= &DefaultIdArray
->Entry
; Link
= Link
->ForwardLink
) {
2121 DefaultId
= BASE_CR (Link
, IFR_DEFAULT_DATA
, Entry
);
2123 // Add <AltConfigHdr> of the form "&<ConfigHdr>&ALTCFG=XXXX\0"
2124 // |1| StrLen (ConfigHdr) | 8 | 4 |
2128 (1 + StrLen (ConfigHdr
) + 8 + 4 + 1) * sizeof (CHAR16
),
2131 DefaultId
->DefaultName
2133 StringPtr
+= StrLen (StringPtr
);
2135 for (LinkData
= VarStorageData
->BlockEntry
.ForwardLink
; LinkData
!= &VarStorageData
->BlockEntry
; LinkData
= LinkData
->ForwardLink
) {
2136 BlockData
= BASE_CR (LinkData
, IFR_BLOCK_DATA
, Entry
);
2137 for (LinkDefault
= BlockData
->DefaultValueEntry
.ForwardLink
; LinkDefault
!= &BlockData
->DefaultValueEntry
; LinkDefault
= LinkDefault
->ForwardLink
) {
2138 DefaultValueData
= BASE_CR (LinkDefault
, IFR_DEFAULT_DATA
, Entry
);
2139 if (DefaultValueData
->DefaultId
== DefaultId
->DefaultId
) {
2141 // Add <BlockConfig>
2142 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>
2146 (8 + 4 + 7 + 4 + 7 + 1) * sizeof (CHAR16
),
2147 L
"&OFFSET=%04X&WIDTH=%04X&VALUE=",
2151 StringPtr
+= StrLen (StringPtr
);
2154 // Convert Value to a hex string in "%x" format
2155 // NOTE: This is in the opposite byte that GUID and PATH use
2157 Width
= BlockData
->Width
;
2158 TmpBuffer
= (UINT8
*) &(DefaultValueData
->Value
);
2159 for (; Width
> 0; Width
--) {
2160 StringPtr
+= UnicodeValueToString (StringPtr
, PREFIX_ZERO
| RADIX_HEX
, TmpBuffer
[Width
- 1], 2);
2166 HiiToLower (DefaultAltCfgResp
);
2169 // 5. Merge string into the input AltCfgResp if the iput *AltCfgResp is not NULL.
2171 if (*AltCfgResp
!= NULL
&& DefaultAltCfgResp
!= NULL
) {
2172 Status
= MergeDefaultString (AltCfgResp
, DefaultAltCfgResp
);
2173 FreePool (DefaultAltCfgResp
);
2174 } else if (*AltCfgResp
== NULL
) {
2175 *AltCfgResp
= DefaultAltCfgResp
;
2179 if (RequestBlockArray
!= NULL
) {
2181 // Free Link Array RequestBlockArray
2183 while (!IsListEmpty (&RequestBlockArray
->Entry
)) {
2184 BlockData
= BASE_CR (RequestBlockArray
->Entry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
2185 RemoveEntryList (&BlockData
->Entry
);
2186 FreePool (BlockData
);
2189 FreePool (RequestBlockArray
);
2192 if (VarStorageData
!= NULL
) {
2194 // Free link array VarStorageData
2196 while (!IsListEmpty (&VarStorageData
->BlockEntry
)) {
2197 BlockData
= BASE_CR (VarStorageData
->BlockEntry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
2198 RemoveEntryList (&BlockData
->Entry
);
2200 // Free default value link array
2202 while (!IsListEmpty (&BlockData
->DefaultValueEntry
)) {
2203 DefaultValueData
= BASE_CR (BlockData
->DefaultValueEntry
.ForwardLink
, IFR_DEFAULT_DATA
, Entry
);
2204 RemoveEntryList (&DefaultValueData
->Entry
);
2205 FreePool (DefaultValueData
);
2207 FreePool (BlockData
);
2209 FreePool (VarStorageData
);
2212 if (DefaultIdArray
!= NULL
) {
2214 // Free DefaultId Array
2216 while (!IsListEmpty (&DefaultIdArray
->Entry
)) {
2217 DefaultId
= BASE_CR (DefaultIdArray
->Entry
.ForwardLink
, IFR_DEFAULT_DATA
, Entry
);
2218 RemoveEntryList (&DefaultId
->Entry
);
2219 FreePool (DefaultId
);
2221 FreePool (DefaultIdArray
);
2225 // Free the allocated string
2227 if (GuidStr
!= NULL
) {
2230 if (NameStr
!= NULL
) {
2233 if (PathStr
!= NULL
) {
2236 if (ConfigHdr
!= NULL
) {
2237 FreePool (ConfigHdr
);
2241 // Free Pacakge data
2243 if (HiiFormPackage
!= NULL
) {
2244 FreePool (HiiFormPackage
);
2247 if (PointerProgress
!= NULL
) {
2248 if (*Request
== NULL
) {
2249 *PointerProgress
= NULL
;
2250 } else if (EFI_ERROR (Status
)) {
2251 *PointerProgress
= Progress
;
2253 *PointerProgress
= *Request
+ StrLen (*Request
);
2261 This function allows a caller to extract the current configuration
2262 for one or more named elements from one or more drivers.
2264 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
2266 @param Request A null-terminated Unicode string in
2267 <MultiConfigRequest> format.
2268 @param Progress On return, points to a character in the Request
2269 string. Points to the string's null terminator if
2270 request was successful. Points to the most recent
2271 & before the first failing name / value pair (or
2272 the beginning of the string if the failure is in
2273 the first name / value pair) if the request was
2275 @param Results Null-terminated Unicode string in
2276 <MultiConfigAltResp> format which has all values
2277 filled in for the names in the Request string.
2278 String to be allocated by the called function.
2280 @retval EFI_SUCCESS The Results string is filled with the values
2281 corresponding to all requested names.
2282 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
2283 results that must be stored awaiting possible
2285 @retval EFI_NOT_FOUND Routing data doesn't match any known driver.
2286 Progress set to the "G" in "GUID" of the routing
2287 header that doesn't match. Note: There is no
2288 requirement that all routing data be validated
2289 before any configuration extraction.
2290 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Request
2291 parameter would result in this type of error. The
2292 Progress parameter is set to NULL.
2293 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set to most recent &
2294 before the error or the beginning of the string.
2295 @retval EFI_INVALID_PARAMETER Unknown name. Progress points to the & before the
2301 HiiConfigRoutingExtractConfig (
2302 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
2303 IN CONST EFI_STRING Request
,
2304 OUT EFI_STRING
*Progress
,
2305 OUT EFI_STRING
*Results
2308 HII_DATABASE_PRIVATE_DATA
*Private
;
2309 EFI_STRING StringPtr
;
2310 EFI_STRING ConfigRequest
;
2312 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
2313 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
2316 HII_DATABASE_RECORD
*Database
;
2317 UINT8
*DevicePathPkg
;
2318 UINT8
*CurrentDevicePath
;
2319 EFI_HANDLE DriverHandle
;
2320 EFI_HII_HANDLE HiiHandle
;
2321 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
2322 EFI_STRING AccessProgress
;
2323 EFI_STRING AccessResults
;
2324 EFI_STRING DefaultResults
;
2325 BOOLEAN FirstElement
;
2326 BOOLEAN IfrDataParsedFlag
;
2328 if (This
== NULL
|| Progress
== NULL
|| Results
== NULL
) {
2329 return EFI_INVALID_PARAMETER
;
2332 if (Request
== NULL
) {
2334 return EFI_INVALID_PARAMETER
;
2337 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
2338 StringPtr
= Request
;
2339 *Progress
= StringPtr
;
2340 DefaultResults
= NULL
;
2341 ConfigRequest
= NULL
;
2342 Status
= EFI_SUCCESS
;
2343 AccessResults
= NULL
;
2345 IfrDataParsedFlag
= FALSE
;
2348 // The first element of <MultiConfigRequest> should be
2349 // <GuidHdr>, which is in 'GUID='<Guid> syntax.
2351 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
2352 return EFI_INVALID_PARAMETER
;
2355 FirstElement
= TRUE
;
2358 // Allocate a fix length of memory to store Results. Reallocate memory for
2359 // Results if this fix length is insufficient.
2361 *Results
= (EFI_STRING
) AllocateZeroPool (MAX_STRING_LENGTH
);
2362 if (*Results
== NULL
) {
2363 return EFI_OUT_OF_RESOURCES
;
2366 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) == 0) {
2368 // If parsing error, set Progress to the beginning of the <MultiConfigRequest>
2369 // or most recent & before the error.
2371 if (StringPtr
== Request
) {
2372 *Progress
= StringPtr
;
2374 *Progress
= StringPtr
- 1;
2378 // Process each <ConfigRequest> of <MultiConfigRequest>
2380 Length
= CalculateConfigStringLen (StringPtr
);
2381 ConfigRequest
= AllocateCopyPool ((Length
+ 1) * sizeof (CHAR16
), StringPtr
);
2382 if (ConfigRequest
== NULL
) {
2383 Status
= EFI_OUT_OF_RESOURCES
;
2386 *(ConfigRequest
+ Length
) = 0;
2389 // Get the UEFI device path
2391 Status
= GetDevicePath (ConfigRequest
, (UINT8
**) &DevicePath
);
2392 if (EFI_ERROR (Status
)) {
2397 // Find driver which matches the routing data.
2399 DriverHandle
= NULL
;
2402 for (Link
= Private
->DatabaseList
.ForwardLink
;
2403 Link
!= &Private
->DatabaseList
;
2404 Link
= Link
->ForwardLink
2406 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
2407 if ((DevicePathPkg
= Database
->PackageList
->DevicePathPkg
) != NULL
) {
2408 CurrentDevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
2412 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) CurrentDevicePath
)
2414 DriverHandle
= Database
->DriverHandle
;
2415 HiiHandle
= Database
->Handle
;
2422 // Try to find driver handle by device path.
2424 if (DriverHandle
== NULL
) {
2425 TempDevicePath
= DevicePath
;
2426 Status
= gBS
->LocateDevicePath (
2427 &gEfiDevicePathProtocolGuid
,
2431 if (EFI_ERROR (Status
) || (DriverHandle
== NULL
)) {
2433 // Routing data does not match any known driver.
2434 // Set Progress to the 'G' in "GUID" of the routing header.
2436 *Progress
= StringPtr
;
2437 Status
= EFI_NOT_FOUND
;
2443 // Check whether ConfigRequest contains request string OFFSET/WIDTH
2445 IfrDataParsedFlag
= FALSE
;
2446 if ((HiiHandle
!= NULL
) && (StrStr (ConfigRequest
, L
"&OFFSET=") == NULL
)) {
2448 // Get the full request string from IFR when HiiPackage is registered to HiiHandle
2450 IfrDataParsedFlag
= TRUE
;
2451 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &ConfigRequest
, &DefaultResults
, &AccessProgress
);
2452 if (EFI_ERROR (Status
)) {
2454 // AccessProgress indicates the parsing progress on <ConfigRequest>.
2455 // Map it to the progress on <MultiConfigRequest> then return it.
2457 *Progress
= StrStr (StringPtr
, AccessProgress
);
2461 // Not any request block is found.
2463 if (StrStr (ConfigRequest
, L
"&OFFSET=") == NULL
) {
2464 AccessResults
= AllocateCopyPool (StrSize (ConfigRequest
), ConfigRequest
);
2465 goto NextConfigString
;
2470 // Call corresponding ConfigAccess protocol to extract settings
2472 Status
= gBS
->HandleProtocol (
2474 &gEfiHiiConfigAccessProtocolGuid
,
2475 (VOID
**) &ConfigAccess
2477 ASSERT_EFI_ERROR (Status
);
2479 Status
= ConfigAccess
->ExtractConfig (
2485 if (EFI_ERROR (Status
)) {
2487 // AccessProgress indicates the parsing progress on <ConfigRequest>.
2488 // Map it to the progress on <MultiConfigRequest> then return it.
2490 *Progress
= StrStr (StringPtr
, AccessProgress
);
2495 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'
2496 // which seperates the first <ConfigAltResp> and the following ones.
2498 ASSERT (*AccessProgress
== 0);
2501 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
2503 if (!IfrDataParsedFlag
&& HiiHandle
!= NULL
) {
2504 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &ConfigRequest
, &DefaultResults
, NULL
);
2505 ASSERT_EFI_ERROR (Status
);
2508 FreePool (DevicePath
);
2511 if (DefaultResults
!= NULL
) {
2512 Status
= MergeDefaultString (&AccessResults
, DefaultResults
);
2513 ASSERT_EFI_ERROR (Status
);
2514 FreePool (DefaultResults
);
2515 DefaultResults
= NULL
;
2519 if (!FirstElement
) {
2520 Status
= AppendToMultiString (Results
, L
"&");
2521 ASSERT_EFI_ERROR (Status
);
2524 Status
= AppendToMultiString (Results
, AccessResults
);
2525 ASSERT_EFI_ERROR (Status
);
2527 FirstElement
= FALSE
;
2529 FreePool (AccessResults
);
2530 AccessResults
= NULL
;
2531 FreePool (ConfigRequest
);
2532 ConfigRequest
= NULL
;
2535 // Go to next <ConfigRequest> (skip '&').
2537 StringPtr
+= Length
;
2538 if (*StringPtr
== 0) {
2539 *Progress
= StringPtr
;
2547 if (EFI_ERROR (Status
)) {
2548 FreePool (*Results
);
2552 if (ConfigRequest
!= NULL
) {
2553 FreePool (ConfigRequest
);
2556 if (AccessResults
!= NULL
) {
2557 FreePool (AccessResults
);
2560 if (DefaultResults
!= NULL
) {
2561 FreePool (DefaultResults
);
2564 if (DevicePath
!= NULL
) {
2565 FreePool (DevicePath
);
2573 This function allows the caller to request the current configuration for the
2574 entirety of the current HII database and returns the data in a
2575 null-terminated Unicode string.
2577 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
2579 @param Results Null-terminated Unicode string in
2580 <MultiConfigAltResp> format which has all values
2581 filled in for the names in the Request string.
2582 String to be allocated by the called function.
2583 De-allocation is up to the caller.
2585 @retval EFI_SUCCESS The Results string is filled with the values
2586 corresponding to all requested names.
2587 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
2588 results that must be stored awaiting possible
2590 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Results
2591 parameter would result in this type of error.
2596 HiiConfigRoutingExportConfig (
2597 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
2598 OUT EFI_STRING
*Results
2602 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
2603 EFI_STRING AccessResults
;
2604 EFI_STRING Progress
;
2605 EFI_STRING StringPtr
;
2606 EFI_STRING ConfigRequest
;
2608 EFI_HANDLE
*ConfigAccessHandles
;
2609 UINTN NumberConfigAccessHandles
;
2610 BOOLEAN FirstElement
;
2611 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
2612 EFI_HII_HANDLE HiiHandle
;
2613 EFI_STRING DefaultResults
;
2614 HII_DATABASE_PRIVATE_DATA
*Private
;
2616 HII_DATABASE_RECORD
*Database
;
2617 UINT8
*DevicePathPkg
;
2618 UINT8
*CurrentDevicePath
;
2619 BOOLEAN IfrDataParsedFlag
;
2621 if (This
== NULL
|| Results
== NULL
) {
2622 return EFI_INVALID_PARAMETER
;
2625 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
2628 // Allocate a fix length of memory to store Results. Reallocate memory for
2629 // Results if this fix length is insufficient.
2631 *Results
= (EFI_STRING
) AllocateZeroPool (MAX_STRING_LENGTH
);
2632 if (*Results
== NULL
) {
2633 return EFI_OUT_OF_RESOURCES
;
2636 NumberConfigAccessHandles
= 0;
2637 Status
= gBS
->LocateHandleBuffer (
2639 &gEfiHiiConfigAccessProtocolGuid
,
2641 &NumberConfigAccessHandles
,
2642 &ConfigAccessHandles
2644 if (EFI_ERROR (Status
)) {
2648 FirstElement
= TRUE
;
2650 for (Index
= 0; Index
< NumberConfigAccessHandles
; Index
++) {
2651 Status
= gBS
->HandleProtocol (
2652 ConfigAccessHandles
[Index
],
2653 &gEfiHiiConfigAccessProtocolGuid
,
2654 (VOID
**) &ConfigAccess
2656 if (EFI_ERROR (Status
)) {
2661 // Get DevicePath and HiiHandle for this ConfigAccess driver handle
2663 IfrDataParsedFlag
= FALSE
;
2666 DefaultResults
= NULL
;
2668 ConfigRequest
= NULL
;
2669 DevicePath
= DevicePathFromHandle (ConfigAccessHandles
[Index
]);
2670 if (DevicePath
!= NULL
) {
2671 for (Link
= Private
->DatabaseList
.ForwardLink
;
2672 Link
!= &Private
->DatabaseList
;
2673 Link
= Link
->ForwardLink
2675 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
2676 if ((DevicePathPkg
= Database
->PackageList
->DevicePathPkg
) != NULL
) {
2677 CurrentDevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
2681 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) CurrentDevicePath
)
2683 HiiHandle
= Database
->Handle
;
2690 Status
= ConfigAccess
->ExtractConfig (
2696 if (EFI_ERROR (Status
)) {
2698 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
2700 if (HiiHandle
!= NULL
&& DevicePath
!= NULL
) {
2701 IfrDataParsedFlag
= TRUE
;
2702 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &ConfigRequest
, &DefaultResults
, NULL
);
2704 // Get the full request string to get the Current setting again.
2706 if (!EFI_ERROR (Status
) && ConfigRequest
!= NULL
) {
2707 Status
= ConfigAccess
->ExtractConfig (
2713 FreePool (ConfigRequest
);
2715 Status
= EFI_NOT_FOUND
;
2720 if (!EFI_ERROR (Status
)) {
2722 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
2724 if (!IfrDataParsedFlag
&& HiiHandle
!= NULL
&& DevicePath
!= NULL
) {
2725 StringPtr
= StrStr (AccessResults
, L
"&GUID=");
2726 if (StringPtr
!= NULL
) {
2729 if (StrStr (AccessResults
, L
"&OFFSET=") != NULL
) {
2730 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &AccessResults
, &DefaultResults
, NULL
);
2731 ASSERT_EFI_ERROR (Status
);
2733 if (StringPtr
!= NULL
) {
2738 // Merge the default sting from IFR code into the got setting from driver.
2740 if (DefaultResults
!= NULL
) {
2741 Status
= MergeDefaultString (&AccessResults
, DefaultResults
);
2742 ASSERT_EFI_ERROR (Status
);
2743 FreePool (DefaultResults
);
2744 DefaultResults
= NULL
;
2748 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'
2749 // which seperates the first <ConfigAltResp> and the following ones.
2751 if (!FirstElement
) {
2752 Status
= AppendToMultiString (Results
, L
"&");
2753 ASSERT_EFI_ERROR (Status
);
2756 Status
= AppendToMultiString (Results
, AccessResults
);
2757 ASSERT_EFI_ERROR (Status
);
2759 FirstElement
= FALSE
;
2761 FreePool (AccessResults
);
2762 AccessResults
= NULL
;
2765 FreePool (ConfigAccessHandles
);
2772 This function processes the results of processing forms and routes it to the
2773 appropriate handlers or storage.
2775 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
2777 @param Configuration A null-terminated Unicode string in
2778 <MulltiConfigResp> format.
2779 @param Progress A pointer to a string filled in with the offset of
2780 the most recent & before the first failing name /
2781 value pair (or the beginning of the string if the
2782 failure is in the first name / value pair) or the
2783 terminating NULL if all was successful.
2785 @retval EFI_SUCCESS The results have been distributed or are awaiting
2787 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
2788 results that must be stored awaiting possible
2790 @retval EFI_INVALID_PARAMETER Passing in a NULL for the Configuration parameter
2791 would result in this type of error.
2792 @retval EFI_NOT_FOUND Target for the specified routing data was not
2798 HiiConfigRoutingRouteConfig (
2799 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
2800 IN CONST EFI_STRING Configuration
,
2801 OUT EFI_STRING
*Progress
2804 HII_DATABASE_PRIVATE_DATA
*Private
;
2805 EFI_STRING StringPtr
;
2806 EFI_STRING ConfigResp
;
2809 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
2810 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
2812 HII_DATABASE_RECORD
*Database
;
2813 UINT8
*DevicePathPkg
;
2814 UINT8
*CurrentDevicePath
;
2815 EFI_HANDLE DriverHandle
;
2816 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
2817 EFI_STRING AccessProgress
;
2819 if (This
== NULL
|| Progress
== NULL
) {
2820 return EFI_INVALID_PARAMETER
;
2823 if (Configuration
== NULL
) {
2825 return EFI_INVALID_PARAMETER
;
2828 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
2829 StringPtr
= Configuration
;
2830 *Progress
= StringPtr
;
2833 // The first element of <MultiConfigResp> should be
2834 // <GuidHdr>, which is in 'GUID='<Guid> syntax.
2836 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
2837 return EFI_INVALID_PARAMETER
;
2840 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) == 0) {
2842 // If parsing error, set Progress to the beginning of the <MultiConfigResp>
2843 // or most recent & before the error.
2845 if (StringPtr
== Configuration
) {
2846 *Progress
= StringPtr
;
2848 *Progress
= StringPtr
- 1;
2852 // Process each <ConfigResp> of <MultiConfigResp>
2854 Length
= CalculateConfigStringLen (StringPtr
);
2855 ConfigResp
= AllocateCopyPool ((Length
+ 1) * sizeof (CHAR16
), StringPtr
);
2856 if (ConfigResp
== NULL
) {
2857 return EFI_OUT_OF_RESOURCES
;
2860 // Append '\0' to the end of ConfigRequest
2862 *(ConfigResp
+ Length
) = 0;
2865 // Get the UEFI device path
2867 Status
= GetDevicePath (ConfigResp
, (UINT8
**) &DevicePath
);
2868 if (EFI_ERROR (Status
)) {
2869 FreePool (ConfigResp
);
2874 // Find driver which matches the routing data.
2876 DriverHandle
= NULL
;
2877 for (Link
= Private
->DatabaseList
.ForwardLink
;
2878 Link
!= &Private
->DatabaseList
;
2879 Link
= Link
->ForwardLink
2881 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
2883 if ((DevicePathPkg
= Database
->PackageList
->DevicePathPkg
) != NULL
) {
2884 CurrentDevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
2888 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) CurrentDevicePath
)
2890 DriverHandle
= Database
->DriverHandle
;
2897 // Try to find driver handle by device path.
2899 if (DriverHandle
== NULL
) {
2900 TempDevicePath
= DevicePath
;
2901 Status
= gBS
->LocateDevicePath (
2902 &gEfiDevicePathProtocolGuid
,
2906 if (EFI_ERROR (Status
) || (DriverHandle
== NULL
)) {
2908 // Routing data does not match any known driver.
2909 // Set Progress to the 'G' in "GUID" of the routing header.
2911 FreePool (DevicePath
);
2912 *Progress
= StringPtr
;
2913 FreePool (ConfigResp
);
2914 return EFI_NOT_FOUND
;
2918 FreePool (DevicePath
);
2921 // Call corresponding ConfigAccess protocol to route settings
2923 Status
= gBS
->HandleProtocol (
2925 &gEfiHiiConfigAccessProtocolGuid
,
2926 (VOID
**) &ConfigAccess
2928 ASSERT_EFI_ERROR (Status
);
2930 Status
= ConfigAccess
->RouteConfig (
2936 if (EFI_ERROR (Status
)) {
2938 // AccessProgress indicates the parsing progress on <ConfigResp>.
2939 // Map it to the progress on <MultiConfigResp> then return it.
2941 *Progress
= StrStr (StringPtr
, AccessProgress
);
2943 FreePool (ConfigResp
);
2947 FreePool (ConfigResp
);
2951 // Go to next <ConfigResp> (skip '&').
2953 StringPtr
+= Length
;
2954 if (*StringPtr
== 0) {
2955 *Progress
= StringPtr
;
2968 This helper function is to be called by drivers to map configuration data
2969 stored in byte array ("block") formats such as UEFI Variables into current
2970 configuration strings.
2972 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
2974 @param ConfigRequest A null-terminated Unicode string in
2975 <ConfigRequest> format.
2976 @param Block Array of bytes defining the block's configuration.
2977 @param BlockSize Length in bytes of Block.
2978 @param Config Filled-in configuration string. String allocated
2979 by the function. Returned only if call is
2980 successful. It is <ConfigResp> string format.
2981 @param Progress A pointer to a string filled in with the offset of
2982 the most recent & before the first failing
2983 name/value pair (or the beginning of the string if
2984 the failure is in the first name / value pair) or
2985 the terminating NULL if all was successful.
2987 @retval EFI_SUCCESS The request succeeded. Progress points to the null
2988 terminator at the end of the ConfigRequest
2990 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress
2991 points to the first character of ConfigRequest.
2992 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigRequest or
2993 Block parameter would result in this type of
2994 error. Progress points to the first character of
2996 @retval EFI_DEVICE_ERROR Block not large enough. Progress undefined.
2997 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted string.
2998 Block is left updated and Progress points at
2999 the "&" preceding the first non-<BlockName>.
3005 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
3006 IN CONST EFI_STRING ConfigRequest
,
3007 IN CONST UINT8
*Block
,
3008 IN CONST UINTN BlockSize
,
3009 OUT EFI_STRING
*Config
,
3010 OUT EFI_STRING
*Progress
3013 HII_DATABASE_PRIVATE_DATA
*Private
;
3014 EFI_STRING StringPtr
;
3022 EFI_STRING ValueStr
;
3023 EFI_STRING ConfigElement
;
3028 if (This
== NULL
|| Progress
== NULL
|| Config
== NULL
) {
3029 return EFI_INVALID_PARAMETER
;
3032 if (Block
== NULL
|| ConfigRequest
== NULL
) {
3033 *Progress
= ConfigRequest
;
3034 return EFI_INVALID_PARAMETER
;
3038 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
3039 ASSERT (Private
!= NULL
);
3041 StringPtr
= ConfigRequest
;
3044 ConfigElement
= NULL
;
3047 // Allocate a fix length of memory to store Results. Reallocate memory for
3048 // Results if this fix length is insufficient.
3050 *Config
= (EFI_STRING
) AllocateZeroPool (MAX_STRING_LENGTH
);
3051 if (*Config
== NULL
) {
3052 return EFI_OUT_OF_RESOURCES
;
3058 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
3059 *Progress
= StringPtr
;
3060 Status
= EFI_INVALID_PARAMETER
;
3063 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"PATH=", StrLen (L
"PATH=")) != 0) {
3066 if (*StringPtr
== 0) {
3067 *Progress
= StringPtr
- 1;
3068 Status
= EFI_INVALID_PARAMETER
;
3072 while (*StringPtr
!= L
'&' && *StringPtr
!= 0) {
3075 if (*StringPtr
== 0) {
3076 *Progress
= StringPtr
- 1;
3077 Status
= EFI_INVALID_PARAMETER
;
3086 // Copy <ConfigHdr> and an additional '&' to <ConfigResp>
3088 Length
= StringPtr
- ConfigRequest
;
3089 CopyMem (*Config
, ConfigRequest
, Length
* sizeof (CHAR16
));
3092 // Parse each <RequestElement> if exists
3093 // Only <BlockName> format is supported by this help function.
3094 // <BlockName> ::= 'OFFSET='<Number>&'WIDTH='<Number>
3096 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"OFFSET=", StrLen (L
"OFFSET=")) == 0) {
3098 // Back up the header of one <BlockName>
3102 StringPtr
+= StrLen (L
"OFFSET=");
3106 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
3107 if (EFI_ERROR (Status
)) {
3108 *Progress
= ConfigRequest
;
3115 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
3117 FreePool (TmpBuffer
);
3119 StringPtr
+= Length
;
3120 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
3121 *Progress
= StringPtr
- Length
- StrLen (L
"OFFSET=") - 1;
3122 Status
= EFI_INVALID_PARAMETER
;
3125 StringPtr
+= StrLen (L
"&WIDTH=");
3130 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
3131 if (EFI_ERROR (Status
)) {
3132 *Progress
= ConfigRequest
;
3139 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
3141 FreePool (TmpBuffer
);
3143 StringPtr
+= Length
;
3144 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
3145 *Progress
= StringPtr
- Length
- StrLen (L
"&WIDTH=");
3146 Status
= EFI_INVALID_PARAMETER
;
3151 // Calculate Value and convert it to hex string.
3153 if (Offset
+ Width
> BlockSize
) {
3154 *Progress
= StringPtr
;
3155 Status
= EFI_DEVICE_ERROR
;
3159 Value
= (UINT8
*) AllocateZeroPool (Width
);
3160 if (Value
== NULL
) {
3161 *Progress
= ConfigRequest
;
3162 Status
= EFI_OUT_OF_RESOURCES
;
3166 CopyMem (Value
, (UINT8
*) Block
+ Offset
, Width
);
3168 Length
= Width
* 2 + 1;
3169 ValueStr
= (EFI_STRING
) AllocateZeroPool (Length
* sizeof (CHAR16
));
3170 if (ValueStr
== NULL
) {
3171 *Progress
= ConfigRequest
;
3172 Status
= EFI_OUT_OF_RESOURCES
;
3176 TemString
= ValueStr
;
3177 TemBuffer
= Value
+ Width
- 1;
3178 for (Index
= 0; Index
< Width
; Index
++, TemBuffer
--) {
3179 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
3186 // Build a ConfigElement
3188 Length
+= StringPtr
- TmpPtr
+ 1 + StrLen (L
"VALUE=");
3189 ConfigElement
= (EFI_STRING
) AllocateZeroPool (Length
* sizeof (CHAR16
));
3190 if (ConfigElement
== NULL
) {
3191 Status
= EFI_OUT_OF_RESOURCES
;
3194 CopyMem (ConfigElement
, TmpPtr
, (StringPtr
- TmpPtr
+ 1) * sizeof (CHAR16
));
3195 if (*StringPtr
== 0) {
3196 *(ConfigElement
+ (StringPtr
- TmpPtr
)) = L
'&';
3198 *(ConfigElement
+ (StringPtr
- TmpPtr
) + 1) = 0;
3199 StrCat (ConfigElement
, L
"VALUE=");
3200 StrCat (ConfigElement
, ValueStr
);
3202 AppendToMultiString (Config
, ConfigElement
);
3204 FreePool (ConfigElement
);
3205 FreePool (ValueStr
);
3206 ConfigElement
= NULL
;
3210 // If '\0', parsing is finished. Otherwise skip '&' to continue
3212 if (*StringPtr
== 0) {
3215 AppendToMultiString (Config
, L
"&");
3220 if (*StringPtr
!= 0) {
3221 *Progress
= StringPtr
- 1;
3222 Status
= EFI_INVALID_PARAMETER
;
3226 HiiToLower (*Config
);
3227 *Progress
= StringPtr
;
3231 if (*Config
!= NULL
) {
3235 if (ValueStr
!= NULL
) {
3236 FreePool (ValueStr
);
3238 if (Value
!= NULL
) {
3241 if (ConfigElement
!= NULL
) {
3242 FreePool (ConfigElement
);
3251 This helper function is to be called by drivers to map configuration strings
3252 to configurations stored in byte array ("block") formats such as UEFI Variables.
3254 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
3256 @param ConfigResp A null-terminated Unicode string in <ConfigResp>
3258 @param Block A possibly null array of bytes representing the
3259 current block. Only bytes referenced in the
3260 ConfigResp string in the block are modified. If
3261 this parameter is null or if the *BlockSize
3262 parameter is (on input) shorter than required by
3263 the Configuration string, only the BlockSize
3264 parameter is updated and an appropriate status
3265 (see below) is returned.
3266 @param BlockSize The length of the Block in units of UINT8. On
3267 input, this is the size of the Block. On output,
3268 if successful, contains the index of the last
3269 modified byte in the Block.
3270 @param Progress On return, points to an element of the ConfigResp
3271 string filled in with the offset of the most
3272 recent '&' before the first failing name / value
3273 pair (or the beginning of the string if the
3274 failure is in the first name / value pair) or the
3275 terminating NULL if all was successful.
3277 @retval EFI_SUCCESS The request succeeded. Progress points to the null
3278 terminator at the end of the ConfigResp string.
3279 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress
3280 points to the first character of ConfigResp.
3281 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigResp or
3282 Block parameter would result in this type of
3283 error. Progress points to the first character of
3285 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted name /
3286 value pair. Block is left updated and
3287 Progress points at the '&' preceding the first
3289 @retval EFI_DEVICE_ERROR Block not large enough. Progress undefined.
3290 @retval EFI_NOT_FOUND Target for the specified routing data was not found.
3291 Progress points to the "G" in "GUID" of the errant
3298 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
3299 IN CONST EFI_STRING ConfigResp
,
3300 IN OUT UINT8
*Block
,
3301 IN OUT UINTN
*BlockSize
,
3302 OUT EFI_STRING
*Progress
3305 HII_DATABASE_PRIVATE_DATA
*Private
;
3306 EFI_STRING StringPtr
;
3316 if (This
== NULL
|| BlockSize
== NULL
|| Progress
== NULL
) {
3317 return EFI_INVALID_PARAMETER
;
3320 *Progress
= ConfigResp
;
3321 if (ConfigResp
== NULL
) {
3322 return EFI_INVALID_PARAMETER
;
3325 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
3326 ASSERT (Private
!= NULL
);
3328 StringPtr
= ConfigResp
;
3329 BufferSize
= *BlockSize
;
3336 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
3337 *Progress
= StringPtr
;
3338 Status
= EFI_INVALID_PARAMETER
;
3341 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"PATH=", StrLen (L
"PATH=")) != 0) {
3344 if (*StringPtr
== 0) {
3345 *Progress
= StringPtr
;
3346 Status
= EFI_INVALID_PARAMETER
;
3350 while (*StringPtr
!= L
'&' && *StringPtr
!= 0) {
3353 if (*StringPtr
== 0) {
3354 *Progress
= StringPtr
;
3355 Status
= EFI_INVALID_PARAMETER
;
3364 // Parse each <ConfigElement> if exists
3365 // Only <BlockConfig> format is supported by this help function.
3366 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE='<Number>
3368 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"OFFSET=", StrLen (L
"OFFSET=")) == 0) {
3369 StringPtr
+= StrLen (L
"OFFSET=");
3373 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
3374 if (EFI_ERROR (Status
)) {
3375 *Progress
= ConfigResp
;
3382 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
3384 FreePool (TmpBuffer
);
3386 StringPtr
+= Length
;
3387 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
3388 *Progress
= StringPtr
- Length
- StrLen (L
"OFFSET=") - 1;
3389 Status
= EFI_INVALID_PARAMETER
;
3392 StringPtr
+= StrLen (L
"&WIDTH=");
3397 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
3398 if (EFI_ERROR (Status
)) {
3399 *Progress
= ConfigResp
;
3406 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
3408 FreePool (TmpBuffer
);
3410 StringPtr
+= Length
;
3411 if (StrnCmp (StringPtr
, L
"&VALUE=", StrLen (L
"&VALUE=")) != 0) {
3412 *Progress
= StringPtr
- Length
- StrLen (L
"&WIDTH=");
3413 Status
= EFI_INVALID_PARAMETER
;
3416 StringPtr
+= StrLen (L
"&VALUE=");
3421 Status
= GetValueOfNumber (StringPtr
, &Value
, &Length
);
3422 if (EFI_ERROR (Status
)) {
3423 *Progress
= ConfigResp
;
3427 StringPtr
+= Length
;
3428 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
3429 *Progress
= StringPtr
- Length
- 7;
3430 Status
= EFI_INVALID_PARAMETER
;
3435 // Update the Block with configuration info
3437 if ((Block
!= NULL
) && (Offset
+ Width
<= BufferSize
)) {
3438 CopyMem (Block
+ Offset
, Value
, Width
);
3440 if (Offset
+ Width
> MaxBlockSize
) {
3441 MaxBlockSize
= Offset
+ Width
;
3448 // If '\0', parsing is finished. Otherwise skip '&' to continue
3450 if (*StringPtr
== 0) {
3458 // The input string is ConfigAltResp format.
3460 if ((*StringPtr
!= 0) && (StrnCmp (StringPtr
, L
"&GUID=", StrLen (L
"&GUID=")) != 0)) {
3461 *Progress
= StringPtr
- 1;
3462 Status
= EFI_INVALID_PARAMETER
;
3466 *Progress
= StringPtr
+ StrLen (StringPtr
);
3467 *BlockSize
= MaxBlockSize
- 1;
3469 if (MaxBlockSize
> BufferSize
) {
3470 *BlockSize
= MaxBlockSize
;
3471 if (Block
!= NULL
) {
3472 return EFI_DEVICE_ERROR
;
3476 if (Block
== NULL
) {
3477 *Progress
= ConfigResp
;
3478 return EFI_INVALID_PARAMETER
;
3485 if (Value
!= NULL
) {
3493 This helper function is to be called by drivers to extract portions of
3494 a larger configuration string.
3496 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
3498 @param Configuration A null-terminated Unicode string in
3499 <MultiConfigAltResp> format.
3500 @param Guid A pointer to the GUID value to search for in the
3501 routing portion of the ConfigResp string when
3502 retrieving the requested data. If Guid is NULL,
3503 then all GUID values will be searched for.
3504 @param Name A pointer to the NAME value to search for in the
3505 routing portion of the ConfigResp string when
3506 retrieving the requested data. If Name is NULL,
3507 then all Name values will be searched for.
3508 @param DevicePath A pointer to the PATH value to search for in the
3509 routing portion of the ConfigResp string when
3510 retrieving the requested data. If DevicePath is
3511 NULL, then all DevicePath values will be searched
3513 @param AltCfgId A pointer to the ALTCFG value to search for in the
3514 routing portion of the ConfigResp string when
3515 retrieving the requested data. If this parameter
3516 is NULL, then the current setting will be
3518 @param AltCfgResp A pointer to a buffer which will be allocated by
3519 the function which contains the retrieved string
3520 as requested. This buffer is only allocated if
3521 the call was successful. It is <ConfigResp> format.
3523 @retval EFI_SUCCESS The request succeeded. The requested data was
3524 extracted and placed in the newly allocated
3526 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate AltCfgResp.
3527 @retval EFI_INVALID_PARAMETER Any parameter is invalid.
3528 @retval EFI_NOT_FOUND Target for the specified routing data was not
3535 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
3536 IN CONST EFI_STRING Configuration
,
3537 IN CONST EFI_GUID
*Guid
,
3538 IN CONST EFI_STRING Name
,
3539 IN CONST EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
3540 IN CONST UINT16
*AltCfgId
,
3541 OUT EFI_STRING
*AltCfgResp
3545 EFI_STRING StringPtr
;
3546 EFI_STRING HdrStart
;
3553 EFI_STRING AltIdStr
;
3570 if (This
== NULL
|| Configuration
== NULL
|| AltCfgResp
== NULL
) {
3571 return EFI_INVALID_PARAMETER
;
3574 StringPtr
= Configuration
;
3575 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
3576 return EFI_INVALID_PARAMETER
;
3580 // Generate the sub string for later matching.
3582 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*) Guid
, 1, &GuidStr
);
3585 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) DevicePath
),
3586 (VOID
*) DevicePath
,
3590 if (AltCfgId
!= NULL
) {
3591 GenerateSubStr (L
"ALTCFG=", sizeof (UINT16
), (VOID
*) AltCfgId
, 3, &AltIdStr
);
3594 GenerateSubStr (L
"NAME=", StrLen (Name
) * sizeof (CHAR16
), (VOID
*) Name
, 2, &NameStr
);
3596 GenerateSubStr (L
"NAME=", 0, NULL
, 2, &NameStr
);
3599 while (*StringPtr
!= 0) {
3601 // Try to match the GUID
3604 TmpPtr
= StrStr (StringPtr
, GuidStr
);
3605 if (TmpPtr
== NULL
) {
3606 Status
= EFI_NOT_FOUND
;
3612 // Jump to <NameHdr>
3615 StringPtr
= TmpPtr
+ StrLen (GuidStr
);
3617 StringPtr
= StrStr (TmpPtr
, L
"NAME=");
3618 if (StringPtr
== NULL
) {
3619 Status
= EFI_NOT_FOUND
;
3627 // Try to match the NAME
3629 if (GuidFlag
&& !NameFlag
) {
3630 if (StrnCmp (StringPtr
, NameStr
, StrLen (NameStr
)) != 0) {
3634 // Jump to <PathHdr>
3637 StringPtr
+= StrLen (NameStr
);
3639 StringPtr
= StrStr (StringPtr
, L
"PATH=");
3640 if (StringPtr
== NULL
) {
3641 Status
= EFI_NOT_FOUND
;
3650 // Try to match the DevicePath
3652 if (GuidFlag
&& NameFlag
&& !PathFlag
) {
3653 if (StrnCmp (StringPtr
, PathStr
, StrLen (PathStr
)) != 0) {
3658 // Jump to '&' before <DescHdr> or <ConfigBody>
3660 if (DevicePath
!= NULL
) {
3661 StringPtr
+= StrLen (PathStr
);
3663 StringPtr
= StrStr (StringPtr
, L
"&");
3664 if (StringPtr
== NULL
) {
3665 Status
= EFI_NOT_FOUND
;
3676 // Try to match the AltCfgId
3678 if (GuidFlag
&& NameFlag
&& PathFlag
) {
3679 if (AltCfgId
== NULL
) {
3681 // Return Current Setting when AltCfgId is NULL.
3683 Status
= OutputConfigBody (StringPtr
, &Result
);
3687 // Search the <ConfigAltResp> to get the <AltResp> with AltCfgId.
3689 if (StrnCmp (StringPtr
, AltIdStr
, StrLen (AltIdStr
)) != 0) {
3695 // Skip AltIdStr and &
3697 StringPtr
= StringPtr
+ StrLen (AltIdStr
);
3698 Status
= OutputConfigBody (StringPtr
, &Result
);
3704 Status
= EFI_NOT_FOUND
;
3708 if (!EFI_ERROR (Status
) && (Result
!= NULL
)) {
3710 // Copy the <ConfigHdr> and <ConfigBody>
3712 Length
= HdrEnd
- HdrStart
+ StrLen (Result
) + 1;
3713 *AltCfgResp
= AllocateZeroPool (Length
* sizeof (CHAR16
));
3714 if (*AltCfgResp
== NULL
) {
3715 Status
= EFI_OUT_OF_RESOURCES
;
3717 StrnCpy (*AltCfgResp
, HdrStart
, HdrEnd
- HdrStart
);
3718 StrCat (*AltCfgResp
, Result
);
3719 Status
= EFI_SUCCESS
;
3723 if (GuidStr
!= NULL
) {
3726 if (NameStr
!= NULL
) {
3729 if (PathStr
!= NULL
) {
3732 if (AltIdStr
!= NULL
) {
3733 FreePool (AltIdStr
);
3735 if (Result
!= NULL
) {