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 inserts new DefaultValueData into the BlockData DefaultValue array.
641 @param BlockData The BlockData is updated to add new default value.
642 @param DefaultValueData The DefaultValue is added.
647 IN IFR_BLOCK_DATA
*BlockData
,
648 IN IFR_DEFAULT_DATA
*DefaultValueData
652 IFR_DEFAULT_DATA
*DefaultValueArray
;
654 for (Link
= BlockData
->DefaultValueEntry
.ForwardLink
; Link
!= &BlockData
->DefaultValueEntry
; Link
= Link
->ForwardLink
) {
655 DefaultValueArray
= BASE_CR (Link
, IFR_DEFAULT_DATA
, Entry
);
656 if (DefaultValueArray
->DefaultId
== DefaultValueData
->DefaultId
) {
657 if (DefaultValueData
->OpCode
== EFI_IFR_DEFAULT_OP
) {
659 // Update the default value array in BlockData.
661 DefaultValueArray
->Value
= DefaultValueData
->Value
;
662 } else if (DefaultValueArray
->OpCode
!= EFI_IFR_DEFAULT_OP
) {
664 // Update the default value array in BlockData.
666 DefaultValueArray
->Value
= DefaultValueData
->Value
;
668 FreePool (DefaultValueData
);
670 } else if (DefaultValueArray
->DefaultId
> DefaultValueData
->DefaultId
) {
672 // Insert new default value data in the front of this default value array.
674 InsertTailList (Link
, &DefaultValueData
->Entry
);
680 // Insert new default value data in tail.
682 InsertTailList (Link
, &DefaultValueData
->Entry
);
687 This function inserts new BlockData into the block link
689 @param BlockLink The list entry points to block array.
690 @param BlockData The point to BlockData is added.
695 IN LIST_ENTRY
*BlockLink
,
696 IN IFR_BLOCK_DATA
**BlockData
700 IFR_BLOCK_DATA
*BlockArray
;
701 IFR_BLOCK_DATA
*BlockSingleData
;
703 BlockSingleData
= *BlockData
;
706 // Insert block data in its Offset and Width order.
708 for (Link
= BlockLink
->ForwardLink
; Link
!= BlockLink
; Link
= Link
->ForwardLink
) {
709 BlockArray
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
710 if (BlockArray
->Offset
== BlockSingleData
->Offset
) {
711 if (BlockArray
->Width
> BlockSingleData
->Width
) {
713 // Insert this block data in the front of block array
715 InsertTailList (Link
, &BlockSingleData
->Entry
);
719 if (BlockArray
->Width
== BlockSingleData
->Width
) {
721 // The same block array has been added.
723 FreePool (BlockSingleData
);
724 *BlockData
= BlockArray
;
727 } else if (BlockArray
->Offset
> BlockSingleData
->Offset
) {
729 // Insert new block data in the front of block array
731 InsertTailList (Link
, &BlockSingleData
->Entry
);
737 // Add new block data into the tail.
739 InsertTailList (Link
, &BlockSingleData
->Entry
);
744 This function checks VarOffset and VarWidth is in the block range.
746 @param RequestBlockArray The block array is to be checked.
747 @param VarOffset Offset of var to the structure
748 @param VarWidth Width of var.
750 @retval TRUE This Var is in the block range.
751 @retval FALSE This Var is not in the block range.
755 IN IFR_BLOCK_DATA
*RequestBlockArray
,
761 IFR_BLOCK_DATA
*BlockData
;
764 // No Request Block array, all vars are got.
766 if (RequestBlockArray
== NULL
) {
771 // Check the input var is in the request block range.
773 for (Link
= RequestBlockArray
->Entry
.ForwardLink
; Link
!= &RequestBlockArray
->Entry
; Link
= Link
->ForwardLink
) {
774 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
775 if ((VarOffset
>= BlockData
->Offset
) && ((VarOffset
+ VarWidth
) <= (BlockData
->Offset
+ BlockData
->Width
))) {
784 This function parses Form Package to get the block array and the default
785 value array according to the request ConfigHdr.
787 @param Package Pointer to the form package data.
788 @param PackageLength Length of the pacakge.
789 @param ConfigHdr Request string ConfigHdr. If it is NULL,
790 the first found varstore will be as ConfigHdr.
791 @param RequestBlockArray The block array is retrieved from the request string.
792 @param VarStorageData VarStorage structure contains the got block and default value.
793 @param PIfrDefaultIdArray Point to the got default id and default name array.
795 @retval EFI_SUCCESS The block array and the default value array are got.
796 @retval EFI_INVALID_PARAMETER The varstore defintion in the differnt form pacakges
798 @retval EFI_OUT_OF_RESOURCES No enough memory.
804 IN UINT32 PackageLength
,
805 IN EFI_STRING ConfigHdr
,
806 IN IFR_BLOCK_DATA
*RequestBlockArray
,
807 IN OUT IFR_VARSTORAGE_DATA
*VarStorageData
,
808 OUT IFR_DEFAULT_DATA
*DefaultIdArray
813 EFI_IFR_VARSTORE
*IfrVarStore
;
814 EFI_IFR_OP_HEADER
*IfrOpHdr
;
815 EFI_IFR_ONE_OF
*IfrOneOf
;
816 EFI_IFR_ONE_OF_OPTION
*IfrOneOfOption
;
817 EFI_IFR_DEFAULT
*IfrDefault
;
818 EFI_IFR_ORDERED_LIST
*IfrOrderedList
;
819 EFI_IFR_CHECKBOX
*IfrCheckBox
;
820 EFI_IFR_PASSWORD
*IfrPassword
;
821 EFI_IFR_STRING
*IfrString
;
822 IFR_DEFAULT_DATA
*DefaultData
;
823 IFR_BLOCK_DATA
*BlockData
;
824 CHAR16
*VarStoreName
;
827 EFI_STRING_ID VarDefaultName
;
833 BOOLEAN FirstOneOfOption
;
836 Status
= EFI_SUCCESS
;
843 FirstOneOfOption
= FALSE
;
846 // Go through the form package to parse OpCode one by one.
848 IfrOffset
= sizeof (EFI_HII_PACKAGE_HEADER
);
849 while (IfrOffset
< PackageLength
) {
850 IfrOpHdr
= (EFI_IFR_OP_HEADER
*) (Package
+ IfrOffset
);
852 switch (IfrOpHdr
->OpCode
) {
853 case EFI_IFR_VARSTORE_OP
:
855 // VarStore is found. Don't need to search any more.
857 if (VarStorageData
->Size
!= 0) {
862 // Get the requied varstore information
863 // Add varstore by Guid and Name in ConfigHdr
864 // Make sure Offset is in varstore size and varstoreid
866 IfrVarStore
= (EFI_IFR_VARSTORE
*) IfrOpHdr
;
867 VarStoreName
= AllocateZeroPool (AsciiStrSize ((CHAR8
*)IfrVarStore
->Name
) * sizeof (CHAR16
));
868 if (VarStoreName
== NULL
) {
869 Status
= EFI_OUT_OF_RESOURCES
;
872 AsciiStrToUnicodeStr ((CHAR8
*) IfrVarStore
->Name
, VarStoreName
);
874 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*) &IfrVarStore
->Guid
, 1, &GuidStr
);
875 GenerateSubStr (L
"NAME=", StrLen (VarStoreName
) * sizeof (CHAR16
), (VOID
*) VarStoreName
, 2, &NameStr
);
876 LengthString
= StrLen (GuidStr
);
877 LengthString
= LengthString
+ StrLen (NameStr
) + 1;
878 TempStr
= AllocateZeroPool (LengthString
* sizeof (CHAR16
));
879 if (TempStr
== NULL
) {
882 FreePool (VarStoreName
);
883 Status
= EFI_OUT_OF_RESOURCES
;
886 StrCpy (TempStr
, GuidStr
);
887 StrCat (TempStr
, NameStr
);
888 if (ConfigHdr
== NULL
|| StrnCmp (ConfigHdr
, TempStr
, StrLen (TempStr
)) == 0) {
890 // Find the matched VarStore
892 CopyGuid (&VarStorageData
->Guid
, (EFI_GUID
*) (VOID
*) &IfrVarStore
->Guid
);
893 VarStorageData
->VarStoreId
= IfrVarStore
->VarStoreId
;
894 VarStorageData
->Size
= IfrVarStore
->Size
;
895 VarStorageData
->Name
= VarStoreName
;
898 // No found, free the allocated memory
900 FreePool (VarStoreName
);
903 // Free alllocated temp string.
910 case EFI_IFR_DEFAULTSTORE_OP
:
912 // Add new the map between default id and default name.
914 DefaultData
= (IFR_DEFAULT_DATA
*) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
915 if (DefaultData
== NULL
) {
916 Status
= EFI_OUT_OF_RESOURCES
;
919 DefaultData
->DefaultId
= ((EFI_IFR_DEFAULTSTORE
*) IfrOpHdr
)->DefaultId
;
920 InsertTailList (&DefaultIdArray
->Entry
, &DefaultData
->Entry
);
924 case EFI_IFR_FORM_OP
:
925 case EFI_IFR_FORM_MAP_OP
:
927 // No matched varstore is found and directly return.
929 if (VarStorageData
->Size
== 0) {
930 Status
= EFI_SUCCESS
;
935 case EFI_IFR_ONE_OF_OP
:
936 case EFI_IFR_NUMERIC_OP
:
938 // Numeric and OneOf has the same opcode structure.
942 // Numeric and OneOf question is not in IFR Form. This IFR form is not valid.
944 if (VarStorageData
->Size
== 0) {
945 Status
= EFI_INVALID_PARAMETER
;
949 // Check whether this question is for the requested varstore.
951 IfrOneOf
= (EFI_IFR_ONE_OF
*) IfrOpHdr
;
952 if (IfrOneOf
->Question
.VarStoreId
!= VarStorageData
->VarStoreId
) {
957 // Get Offset/Width by Question header and OneOf Flags
959 VarOffset
= IfrOneOf
->Question
.VarStoreInfo
.VarOffset
;
960 VarWidth
= (UINT16
) (1 << (IfrOneOf
->Flags
& EFI_IFR_NUMERIC_SIZE
));
962 // Check whether this question is in requested block array.
964 if (!BlockArrayCheck (RequestBlockArray
, VarOffset
, VarWidth
)) {
966 // This question is not in the requested string. Skip it.
972 // Check this var question is in the var storage
974 if ((VarOffset
+ VarWidth
) > VarStorageData
->Size
) {
975 Status
= EFI_INVALID_PARAMETER
;
982 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
983 if (BlockData
== NULL
) {
984 Status
= EFI_OUT_OF_RESOURCES
;
987 BlockData
->Offset
= VarOffset
;
988 BlockData
->Width
= VarWidth
;
989 BlockData
->QuestionId
= IfrOneOf
->Question
.QuestionId
;
990 BlockData
->OpCode
= IfrOpHdr
->OpCode
;
991 BlockData
->Scope
= IfrOpHdr
->Scope
;
992 InitializeListHead (&BlockData
->DefaultValueEntry
);
994 // Add Block Data into VarStorageData BlockEntry
996 InsertBlockData (&VarStorageData
->BlockEntry
, &BlockData
);
998 if (IfrOpHdr
->OpCode
== EFI_IFR_ONE_OF_OP
) {
1000 // Set this flag to TRUE for the first oneof option.
1002 FirstOneOfOption
= TRUE
;
1003 } else if (IfrOpHdr
->OpCode
== EFI_IFR_NUMERIC_OP
) {
1005 // Numeric minimum value will be used as default value when no default is specified.
1011 VarDefaultId
= EFI_HII_DEFAULT_CLASS_STANDARD
;
1013 // Prepare new DefaultValue
1015 DefaultData
= (IFR_DEFAULT_DATA
*) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
1016 if (DefaultData
== NULL
) {
1017 Status
= EFI_OUT_OF_RESOURCES
;
1020 DefaultData
->OpCode
= IfrOpHdr
->OpCode
;
1021 DefaultData
->DefaultId
= VarDefaultId
;
1023 switch (IfrOneOf
->Flags
& EFI_IFR_NUMERIC_SIZE
) {
1024 case EFI_IFR_NUMERIC_SIZE_1
:
1025 DefaultData
->Value
= (UINT64
) IfrOneOf
->data
.u8
.MinValue
;
1028 case EFI_IFR_NUMERIC_SIZE_2
:
1029 CopyMem (&DefaultData
->Value
, &IfrOneOf
->data
.u16
.MinValue
, sizeof (UINT16
));
1032 case EFI_IFR_NUMERIC_SIZE_4
:
1033 CopyMem (&DefaultData
->Value
, &IfrOneOf
->data
.u32
.MinValue
, sizeof (UINT32
));
1036 case EFI_IFR_NUMERIC_SIZE_8
:
1037 CopyMem (&DefaultData
->Value
, &IfrOneOf
->data
.u64
.MinValue
, sizeof (UINT64
));
1041 // Add DefaultValue into current BlockData
1043 InsertDefaultValue (BlockData
, DefaultData
);
1047 case EFI_IFR_ORDERED_LIST_OP
:
1049 // offset by question header
1050 // width by EFI_IFR_ORDERED_LIST MaxContainers * OneofOption Type
1051 // no default value and default id, how to define its default value?
1055 // OrderedList question is not in IFR Form. This IFR form is not valid.
1057 if (VarStorageData
->Size
== 0) {
1058 Status
= EFI_INVALID_PARAMETER
;
1062 // Check whether this question is for the requested varstore.
1064 IfrOrderedList
= (EFI_IFR_ORDERED_LIST
*) IfrOpHdr
;
1065 if (IfrOrderedList
->Question
.VarStoreId
!= VarStorageData
->VarStoreId
) {
1071 // Get Offset/Width by Question header and OneOf Flags
1073 VarOffset
= IfrOrderedList
->Question
.VarStoreInfo
.VarOffset
;
1074 VarWidth
= IfrOrderedList
->MaxContainers
;
1079 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
1080 if (BlockData
== NULL
) {
1081 Status
= EFI_OUT_OF_RESOURCES
;
1084 BlockData
->Offset
= VarOffset
;
1085 BlockData
->Width
= VarWidth
;
1086 BlockData
->QuestionId
= IfrOrderedList
->Question
.QuestionId
;
1087 BlockData
->OpCode
= IfrOpHdr
->OpCode
;
1088 BlockData
->Scope
= IfrOpHdr
->Scope
;
1089 InitializeListHead (&BlockData
->DefaultValueEntry
);
1092 case EFI_IFR_CHECKBOX_OP
:
1094 // EFI_IFR_DEFAULT_OP
1095 // offset by question header
1096 // width is 1 sizeof (BOOLEAN)
1097 // default id by CheckBox Flags if CheckBox flags (Default or Mau) is set, the default value is 1 to be set.
1098 // value by DefaultOption
1099 // default id by DeaultOption DefaultId can override CheckBox Flags and Default value.
1103 // CheckBox question is not in IFR Form. This IFR form is not valid.
1105 if (VarStorageData
->Size
== 0) {
1106 Status
= EFI_INVALID_PARAMETER
;
1110 // Check whether this question is for the requested varstore.
1112 IfrCheckBox
= (EFI_IFR_CHECKBOX
*) IfrOpHdr
;
1113 if (IfrCheckBox
->Question
.VarStoreId
!= VarStorageData
->VarStoreId
) {
1118 // Get Offset/Width by Question header and OneOf Flags
1120 VarOffset
= IfrCheckBox
->Question
.VarStoreInfo
.VarOffset
;
1121 VarWidth
= (UINT16
) sizeof (BOOLEAN
);
1124 // Check whether this question is in requested block array.
1126 if (!BlockArrayCheck (RequestBlockArray
, VarOffset
, VarWidth
)) {
1128 // This question is not in the requested string. Skip it.
1134 // Check this var question is in the var storage
1136 if ((VarOffset
+ VarWidth
) > VarStorageData
->Size
) {
1137 Status
= EFI_INVALID_PARAMETER
;
1144 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
1145 if (BlockData
== NULL
) {
1146 Status
= EFI_OUT_OF_RESOURCES
;
1149 BlockData
->Offset
= VarOffset
;
1150 BlockData
->Width
= VarWidth
;
1151 BlockData
->QuestionId
= IfrCheckBox
->Question
.QuestionId
;
1152 BlockData
->OpCode
= IfrOpHdr
->OpCode
;
1153 BlockData
->Scope
= IfrOpHdr
->Scope
;
1154 InitializeListHead (&BlockData
->DefaultValueEntry
);
1156 // Add Block Data into VarStorageData BlockEntry
1158 InsertBlockData (&VarStorageData
->BlockEntry
, &BlockData
);
1161 // Add default value for standard ID by CheckBox Flag
1163 VarDefaultId
= EFI_HII_DEFAULT_CLASS_STANDARD
;
1165 // Prepare new DefaultValue
1167 DefaultData
= (IFR_DEFAULT_DATA
*) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
1168 if (DefaultData
== NULL
) {
1169 Status
= EFI_OUT_OF_RESOURCES
;
1172 DefaultData
->OpCode
= IfrOpHdr
->OpCode
;
1173 DefaultData
->DefaultId
= VarDefaultId
;
1174 if ((IfrCheckBox
->Flags
& EFI_IFR_CHECKBOX_DEFAULT
) == EFI_IFR_CHECKBOX_DEFAULT
) {
1176 // When flag is set, defautl value is TRUE.
1178 DefaultData
->Value
= 1;
1181 // When flag is not set, defautl value is FASLE.
1183 DefaultData
->Value
= 0;
1186 // Add DefaultValue into current BlockData
1188 InsertDefaultValue (BlockData
, DefaultData
);
1191 // Add default value for Manufacture ID by CheckBox Flag
1193 VarDefaultId
= EFI_HII_DEFAULT_CLASS_MANUFACTURING
;
1195 // Prepare new DefaultValue
1197 DefaultData
= (IFR_DEFAULT_DATA
*) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
1198 if (DefaultData
== NULL
) {
1199 Status
= EFI_OUT_OF_RESOURCES
;
1202 DefaultData
->OpCode
= IfrOpHdr
->OpCode
;
1203 DefaultData
->DefaultId
= VarDefaultId
;
1204 if ((IfrCheckBox
->Flags
& EFI_IFR_CHECKBOX_DEFAULT_MFG
) == EFI_IFR_CHECKBOX_DEFAULT_MFG
) {
1206 // When flag is set, defautl value is TRUE.
1208 DefaultData
->Value
= 1;
1211 // When flag is not set, defautl value is FASLE.
1213 DefaultData
->Value
= 0;
1216 // Add DefaultValue into current BlockData
1218 InsertDefaultValue (BlockData
, DefaultData
);
1221 case EFI_IFR_STRING_OP
:
1223 // offset by question header
1224 // width MaxSize * sizeof (CHAR16)
1225 // no default value, only block array
1229 // String question is not in IFR Form. This IFR form is not valid.
1231 if (VarStorageData
->Size
== 0) {
1232 Status
= EFI_INVALID_PARAMETER
;
1236 // Check whether this question is for the requested varstore.
1238 IfrString
= (EFI_IFR_STRING
*) IfrOpHdr
;
1239 if (IfrString
->Question
.VarStoreId
!= VarStorageData
->VarStoreId
) {
1244 // Get Offset/Width by Question header and OneOf Flags
1246 VarOffset
= IfrString
->Question
.VarStoreInfo
.VarOffset
;
1247 VarWidth
= (UINT16
) (IfrString
->MaxSize
* sizeof (UINT16
));
1250 // Check whether this question is in requested block array.
1252 if (!BlockArrayCheck (RequestBlockArray
, VarOffset
, VarWidth
)) {
1254 // This question is not in the requested string. Skip it.
1260 // Check this var question is in the var storage
1262 if ((VarOffset
+ VarWidth
) > VarStorageData
->Size
) {
1263 Status
= EFI_INVALID_PARAMETER
;
1270 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
1271 if (BlockData
== NULL
) {
1272 Status
= EFI_OUT_OF_RESOURCES
;
1275 BlockData
->Offset
= VarOffset
;
1276 BlockData
->Width
= VarWidth
;
1277 BlockData
->QuestionId
= IfrString
->Question
.QuestionId
;
1278 BlockData
->OpCode
= IfrOpHdr
->OpCode
;
1279 InitializeListHead (&BlockData
->DefaultValueEntry
);
1282 // Add Block Data into VarStorageData BlockEntry
1284 InsertBlockData (&VarStorageData
->BlockEntry
, &BlockData
);
1287 // No default value for string.
1292 case EFI_IFR_PASSWORD_OP
:
1294 // offset by question header
1295 // width MaxSize * sizeof (CHAR16)
1296 // no default value, only block array
1300 // Password question is not in IFR Form. This IFR form is not valid.
1302 if (VarStorageData
->Size
== 0) {
1303 Status
= EFI_INVALID_PARAMETER
;
1307 // Check whether this question is for the requested varstore.
1309 IfrPassword
= (EFI_IFR_PASSWORD
*) IfrOpHdr
;
1310 if (IfrPassword
->Question
.VarStoreId
!= VarStorageData
->VarStoreId
) {
1315 // Get Offset/Width by Question header and OneOf Flags
1317 VarOffset
= IfrPassword
->Question
.VarStoreInfo
.VarOffset
;
1318 VarWidth
= (UINT16
) (IfrPassword
->MaxSize
* sizeof (UINT16
));
1321 // Check whether this question is in requested block array.
1323 if (!BlockArrayCheck (RequestBlockArray
, VarOffset
, VarWidth
)) {
1325 // This question is not in the requested string. Skip it.
1331 // Check this var question is in the var storage
1333 if ((VarOffset
+ VarWidth
) > VarStorageData
->Size
) {
1334 Status
= EFI_INVALID_PARAMETER
;
1341 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
1342 if (BlockData
== NULL
) {
1343 Status
= EFI_OUT_OF_RESOURCES
;
1346 BlockData
->Offset
= VarOffset
;
1347 BlockData
->Width
= VarWidth
;
1348 BlockData
->QuestionId
= IfrPassword
->Question
.QuestionId
;
1349 BlockData
->OpCode
= IfrOpHdr
->OpCode
;
1350 InitializeListHead (&BlockData
->DefaultValueEntry
);
1353 // Add Block Data into VarStorageData BlockEntry
1355 InsertBlockData (&VarStorageData
->BlockEntry
, &BlockData
);
1358 // No default value for string.
1363 case EFI_IFR_ONE_OF_OPTION_OP
:
1365 // No matched block data is ignored.
1367 if (BlockData
== NULL
|| BlockData
->Scope
== 0) {
1371 IfrOneOfOption
= (EFI_IFR_ONE_OF_OPTION
*) IfrOpHdr
;
1372 if (BlockData
->OpCode
== EFI_IFR_ORDERED_LIST_OP
) {
1374 // Get ordered list option data type.
1376 if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_8
|| IfrOneOfOption
->Type
== EFI_IFR_TYPE_BOOLEAN
) {
1378 } else if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_16
) {
1380 } else if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_32
) {
1382 } else if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_64
) {
1386 // Invalid ordered list option data type.
1388 Status
= EFI_INVALID_PARAMETER
;
1389 FreePool (BlockData
);
1394 // Calculate Ordered list QuestionId width.
1396 BlockData
->Width
= (UINT16
) (BlockData
->Width
* VarWidth
);
1398 // Check whether this question is in requested block array.
1400 if (!BlockArrayCheck (RequestBlockArray
, BlockData
->Offset
, BlockData
->Width
)) {
1402 // This question is not in the requested string. Skip it.
1404 FreePool (BlockData
);
1409 // Check this var question is in the var storage
1411 if ((BlockData
->Offset
+ BlockData
->Width
) > VarStorageData
->Size
) {
1412 Status
= EFI_INVALID_PARAMETER
;
1413 FreePool (BlockData
);
1417 // Add Block Data into VarStorageData BlockEntry
1419 InsertBlockData (&VarStorageData
->BlockEntry
, &BlockData
);
1421 // No default data for OrderedList.
1427 if (((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT
) == EFI_IFR_OPTION_DEFAULT
) ||
1428 (BlockData
->OpCode
== EFI_IFR_ONE_OF_OP
&& FirstOneOfOption
)) {
1430 // This flag is used to specify whether this option is the first. Set it to FALSE for the following options.
1431 // The first oneof option value will be used as default value when no default value is specified.
1433 FirstOneOfOption
= FALSE
;
1435 // Set standard ID to Manufacture ID
1437 VarDefaultId
= EFI_HII_DEFAULT_CLASS_STANDARD
;
1439 // Prepare new DefaultValue
1441 DefaultData
= (IFR_DEFAULT_DATA
*) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
1442 if (DefaultData
== NULL
) {
1443 Status
= EFI_OUT_OF_RESOURCES
;
1446 DefaultData
->OpCode
= IfrOpHdr
->OpCode
;
1447 DefaultData
->DefaultId
= VarDefaultId
;
1448 DefaultData
->Value
= IfrOneOfOption
->Value
.u64
;
1450 // Add DefaultValue into current BlockData
1452 InsertDefaultValue (BlockData
, DefaultData
);
1455 if ((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT_MFG
) == EFI_IFR_OPTION_DEFAULT_MFG
) {
1457 // Set default ID to Manufacture ID
1459 VarDefaultId
= EFI_HII_DEFAULT_CLASS_MANUFACTURING
;
1461 // Prepare new DefaultValue
1463 DefaultData
= (IFR_DEFAULT_DATA
*) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
1464 if (DefaultData
== NULL
) {
1465 Status
= EFI_OUT_OF_RESOURCES
;
1468 DefaultData
->OpCode
= IfrOpHdr
->OpCode
;
1469 DefaultData
->DefaultId
= VarDefaultId
;
1470 DefaultData
->Value
= IfrOneOfOption
->Value
.u64
;
1472 // Add DefaultValue into current BlockData
1474 InsertDefaultValue (BlockData
, DefaultData
);
1478 case EFI_IFR_DEFAULT_OP
:
1480 // Update Current BlockData to the default value.
1482 if (BlockData
== NULL
|| BlockData
->Scope
== 0) {
1484 // No matched block data is ignored.
1489 if (BlockData
->OpCode
== EFI_IFR_ORDERED_LIST_OP
) {
1491 // OrderedList Opcode is no default value.
1496 // Get the DefaultId
1498 IfrDefault
= (EFI_IFR_DEFAULT
*) IfrOpHdr
;
1499 VarDefaultId
= IfrDefault
->DefaultId
;
1501 // Prepare new DefaultValue
1503 DefaultData
= (IFR_DEFAULT_DATA
*) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
1504 if (DefaultData
== NULL
) {
1505 Status
= EFI_OUT_OF_RESOURCES
;
1508 DefaultData
->OpCode
= IfrOpHdr
->OpCode
;
1509 DefaultData
->DefaultId
= VarDefaultId
;
1510 DefaultData
->Value
= IfrDefault
->Value
.u64
;
1512 // Add DefaultValue into current BlockData
1514 InsertDefaultValue (BlockData
, DefaultData
);
1516 case EFI_IFR_END_OP
:
1518 // End Opcode is for Var question.
1520 if (BlockData
!= NULL
&& BlockData
->Scope
> 0) {
1525 if (BlockData
!= NULL
&& BlockData
->Scope
> 0) {
1526 BlockData
->Scope
= (UINT8
) (BlockData
->Scope
+ IfrOpHdr
->Scope
);
1531 IfrOffset
+= IfrOpHdr
->Length
;
1539 This function gets the full request string and full default value string by
1540 parsing IFR data in HII form packages.
1542 When Request points to NULL string, the request string and default value string
1543 for each varstore in form package will return.
1545 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
1546 @param DevicePath Device Path which Hii Config Access Protocol is registered.
1547 @param Request Pointer to a null-terminated Unicode string in
1548 <ConfigRequest> format. When it doesn't contain
1549 any RequestElement, it will be updated to return
1550 the full RequestElement retrieved from IFR data.
1551 If it points to NULL, the request string for the first
1552 varstore in form package will be merged into a
1553 <MultiConfigRequest> format string and return.
1554 @param AltCfgResp Pointer to a null-terminated Unicode string in
1555 <ConfigAltResp> format. When the pointer is to NULL,
1556 the full default value string retrieved from IFR data
1557 will return. When the pinter is to a string, the
1558 full default value string retrieved from IFR data
1559 will be merged into the input string and return.
1560 When Request points to NULL, the default value string
1561 for each varstore in form package will be merged into
1562 a <MultiConfigAltResp> format string and return.
1563 @param PointerProgress Optional parameter, it can be be NULL.
1564 When it is not NULL, if Request is NULL, it returns NULL.
1565 On return, points to a character in the Request
1566 string. Points to the string's null terminator if
1567 request was successful. Points to the most recent
1568 & before the first failing name / value pair (or
1569 the beginning of the string if the failure is in
1570 the first name / value pair) if the request was
1572 @retval EFI_SUCCESS The Results string is set to the full request string.
1573 And AltCfgResp contains all default value string.
1574 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
1575 @retval EFI_NOT_FOUND The varstore (Guid and Name) in Request string
1576 can't be found in Form package.
1577 @retval EFI_NOT_FOUND HiiPackage can't be got on the input HiiHandle.
1578 @retval EFI_INVALID_PARAMETER Request points to NULL.
1583 GetFullStringFromHiiFormPackages (
1584 IN HII_DATABASE_RECORD
*DataBaseRecord
,
1585 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
1586 IN OUT EFI_STRING
*Request
,
1587 IN OUT EFI_STRING
*AltCfgResp
,
1588 OUT EFI_STRING
*PointerProgress OPTIONAL
1592 UINT8
*HiiFormPackage
;
1595 IFR_BLOCK_DATA
*RequestBlockArray
;
1596 IFR_BLOCK_DATA
*BlockData
;
1597 IFR_BLOCK_DATA
*NextBlockData
;
1598 IFR_DEFAULT_DATA
*DefaultValueData
;
1599 IFR_DEFAULT_DATA
*DefaultId
;
1600 IFR_DEFAULT_DATA
*DefaultIdArray
;
1601 IFR_VARSTORAGE_DATA
*VarStorageData
;
1602 EFI_STRING DefaultAltCfgResp
;
1603 EFI_STRING FullConfigRequest
;
1604 EFI_STRING ConfigHdr
;
1608 EFI_STRING StringPtr
;
1609 EFI_STRING Progress
;
1615 LIST_ENTRY
*LinkData
;
1616 LIST_ENTRY
*LinkDefault
;
1619 if (DataBaseRecord
== NULL
|| DevicePath
== NULL
|| Request
== NULL
|| AltCfgResp
== NULL
) {
1620 return EFI_INVALID_PARAMETER
;
1624 // Initialize the local variables.
1626 RequestBlockArray
= NULL
;
1627 DefaultIdArray
= NULL
;
1628 VarStorageData
= NULL
;
1629 DefaultAltCfgResp
= NULL
;
1630 FullConfigRequest
= NULL
;
1635 HiiFormPackage
= NULL
;
1639 Progress
= *Request
;
1642 // 0. Get Hii Form Package by HiiHandle
1644 Status
= ExportFormPackages (
1646 DataBaseRecord
->Handle
,
1647 DataBaseRecord
->PackageList
,
1653 if (EFI_ERROR (Status
)) {
1657 HiiFormPackage
= AllocatePool (ResultSize
);
1658 if (HiiFormPackage
== NULL
) {
1659 Status
= EFI_OUT_OF_RESOURCES
;
1664 // Get HiiFormPackage by HiiHandle
1666 PackageSize
= ResultSize
;
1668 Status
= ExportFormPackages (
1670 DataBaseRecord
->Handle
,
1671 DataBaseRecord
->PackageList
,
1677 if (EFI_ERROR (Status
)) {
1682 // 1. Get the request block array by Request String when Request string containts the block array.
1685 if (*Request
!= NULL
) {
1686 StringPtr
= *Request
;
1690 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
1691 Status
= EFI_INVALID_PARAMETER
;
1694 StringPtr
+= StrLen (L
"GUID=");
1695 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&NAME=", StrLen (L
"&NAME=")) != 0) {
1698 if (*StringPtr
== L
'\0') {
1699 Status
= EFI_INVALID_PARAMETER
;
1702 StringPtr
+= StrLen (L
"&NAME=");
1703 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&PATH=", StrLen (L
"&PATH=")) != 0) {
1706 if (*StringPtr
== L
'\0') {
1707 Status
= EFI_INVALID_PARAMETER
;
1710 StringPtr
+= StrLen (L
"&PATH=");
1711 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
1715 // Check the following string &OFFSET=
1717 if (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) != 0) {
1718 Progress
= StringPtr
;
1719 Status
= EFI_INVALID_PARAMETER
;
1721 } else if (*StringPtr
== L
'\0') {
1723 // No request block is found.
1728 if (StringPtr
!= NULL
) {
1730 // Init RequestBlockArray
1732 RequestBlockArray
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
1733 if (RequestBlockArray
== NULL
) {
1734 Status
= EFI_OUT_OF_RESOURCES
;
1737 InitializeListHead (&RequestBlockArray
->Entry
);
1740 // Get the request Block array from the request string
1745 // Parse each <RequestElement> if exists
1746 // Only <BlockName> format is supported by this help function.
1747 // <BlockName> ::= &'OFFSET='<Number>&'WIDTH='<Number>
1749 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) == 0) {
1751 // Skip the OFFSET string
1753 Progress
= StringPtr
;
1754 StringPtr
+= StrLen (L
"&OFFSET=");
1758 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
1759 if (EFI_ERROR (Status
)) {
1766 (((Length
+ 1) / 2) < sizeof (UINT16
)) ? ((Length
+ 1) / 2) : sizeof (UINT16
)
1768 FreePool (TmpBuffer
);
1770 StringPtr
+= Length
;
1771 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
1772 Status
= EFI_INVALID_PARAMETER
;
1775 StringPtr
+= StrLen (L
"&WIDTH=");
1780 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
1781 if (EFI_ERROR (Status
)) {
1788 (((Length
+ 1) / 2) < sizeof (UINT16
)) ? ((Length
+ 1) / 2) : sizeof (UINT16
)
1790 FreePool (TmpBuffer
);
1792 StringPtr
+= Length
;
1793 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
1794 Status
= EFI_INVALID_PARAMETER
;
1801 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
1802 if (BlockData
== NULL
) {
1803 Status
= EFI_OUT_OF_RESOURCES
;
1806 BlockData
->Offset
= Offset
;
1807 BlockData
->Width
= Width
;
1808 InsertBlockData (&RequestBlockArray
->Entry
, &BlockData
);
1811 // Skip &VALUE string if &VALUE does exists.
1813 if (StrnCmp (StringPtr
, L
"&VALUE=", StrLen (L
"&VALUE=")) == 0) {
1814 StringPtr
+= StrLen (L
"&VALUE=");
1819 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
1820 if (EFI_ERROR (Status
)) {
1821 Status
= EFI_INVALID_PARAMETER
;
1825 StringPtr
+= Length
;
1826 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
1827 Status
= EFI_INVALID_PARAMETER
;
1832 // If '\0', parsing is finished.
1834 if (*StringPtr
== 0) {
1840 // Merge the requested block data.
1842 Link
= RequestBlockArray
->Entry
.ForwardLink
;
1843 while ((Link
!= &RequestBlockArray
->Entry
) && (Link
->ForwardLink
!= &RequestBlockArray
->Entry
)) {
1844 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
1845 NextBlockData
= BASE_CR (Link
->ForwardLink
, IFR_BLOCK_DATA
, Entry
);
1846 if ((NextBlockData
->Offset
>= BlockData
->Offset
) && (NextBlockData
->Offset
<= (BlockData
->Offset
+ BlockData
->Width
))) {
1847 if ((NextBlockData
->Offset
+ NextBlockData
->Width
) > (BlockData
->Offset
+ BlockData
->Width
)) {
1848 BlockData
->Width
= (UINT16
) (NextBlockData
->Offset
+ NextBlockData
->Width
- BlockData
->Offset
);
1850 RemoveEntryList (Link
->ForwardLink
);
1851 FreePool (NextBlockData
);
1854 Link
= Link
->ForwardLink
;
1859 // 2. Parse FormPackage to get BlockArray and DefaultId Array for the request BlockArray.
1863 // Initialize DefaultIdArray to store the map between DeaultId and DefaultName
1865 DefaultIdArray
= (IFR_DEFAULT_DATA
*) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
1866 if (DefaultIdArray
== NULL
) {
1867 Status
= EFI_OUT_OF_RESOURCES
;
1870 InitializeListHead (&DefaultIdArray
->Entry
);
1873 // Initialize VarStorageData to store the var store Block and Default value information.
1875 VarStorageData
= (IFR_VARSTORAGE_DATA
*) AllocateZeroPool (sizeof (IFR_VARSTORAGE_DATA
));
1876 if (VarStorageData
== NULL
) {
1877 Status
= EFI_OUT_OF_RESOURCES
;
1880 InitializeListHead (&VarStorageData
->Entry
);
1881 InitializeListHead (&VarStorageData
->BlockEntry
);
1884 // Parse the opcode in form pacakge to get the default setting.
1886 Status
= ParseIfrData (HiiFormPackage
, (UINT32
) PackageSize
, *Request
, RequestBlockArray
, VarStorageData
, DefaultIdArray
);
1887 if (EFI_ERROR (Status
)) {
1892 // No requested varstore in IFR data and directly return
1894 if (VarStorageData
->Size
== 0) {
1895 Status
= EFI_SUCCESS
;
1900 // 3. Construct Request Element (Block Name) for 2.1 and 2.2 case.
1904 // Construct <ConfigHdr> : "GUID=...&NAME=...&PATH=..." by VarStorageData Guid, Name and DriverHandle
1906 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*) &VarStorageData
->Guid
, 1, &GuidStr
);
1907 GenerateSubStr (L
"NAME=", StrLen (VarStorageData
->Name
) * sizeof (CHAR16
), (VOID
*) VarStorageData
->Name
, 2, &NameStr
);
1910 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) DevicePath
),
1911 (VOID
*) DevicePath
,
1915 Length
= StrLen (GuidStr
);
1916 Length
= Length
+ StrLen (NameStr
);
1917 Length
= Length
+ StrLen (PathStr
) + 1;
1918 ConfigHdr
= AllocateZeroPool (Length
* sizeof (CHAR16
));
1919 if (ConfigHdr
== NULL
) {
1920 Status
= EFI_OUT_OF_RESOURCES
;
1923 StrCpy (ConfigHdr
, GuidStr
);
1924 StrCat (ConfigHdr
, NameStr
);
1925 StrCat (ConfigHdr
, PathStr
);
1928 // Remove the last character L'&'
1930 *(ConfigHdr
+ StrLen (ConfigHdr
) - 1) = L
'\0';
1932 if (RequestBlockArray
== NULL
) {
1934 // Append VarStorageData BlockEntry into *Request string
1935 // Now support only one varstore in a form package.
1939 // Go through all VarStorageData Entry and get BlockEntry for each one for the multiple varstore in a single form package
1940 // Then construct them all to return MultiRequest string : ConfigHdr BlockConfig
1944 // Compute the length of the entire request starting with <ConfigHdr> and a
1948 Length
= StrLen (ConfigHdr
) + 1;
1950 for (Link
= VarStorageData
->BlockEntry
.ForwardLink
; Link
!= &VarStorageData
->BlockEntry
; Link
= Link
->ForwardLink
) {
1952 // Add <BlockName> length for each Offset/Width pair
1954 // <BlockName> ::= &OFFSET=1234&WIDTH=1234
1955 // | 8 | 4 | 7 | 4 |
1958 Length
= Length
+ (8 + 4 + 7 + 4);
1962 // No any request block data is found. The request string can't be constructed.
1965 Status
= EFI_SUCCESS
;
1970 // Allocate buffer for the entire <ConfigRequest>
1972 FullConfigRequest
= AllocateZeroPool (Length
* sizeof (CHAR16
));
1973 if (FullConfigRequest
== NULL
) {
1974 Status
= EFI_OUT_OF_RESOURCES
;
1977 StringPtr
= FullConfigRequest
;
1980 // Start with <ConfigHdr>
1982 StrCpy (StringPtr
, ConfigHdr
);
1983 StringPtr
+= StrLen (StringPtr
);
1986 // Loop through all the Offset/Width pairs and append them to ConfigRequest
1988 for (Link
= VarStorageData
->BlockEntry
.ForwardLink
; Link
!= &VarStorageData
->BlockEntry
; Link
= Link
->ForwardLink
) {
1989 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
1991 // Append &OFFSET=XXXX&WIDTH=YYYY\0
1995 (8 + 4 + 7 + 4 + 1) * sizeof (CHAR16
),
1996 L
"&OFFSET=%04X&WIDTH=%04X",
2000 StringPtr
+= StrLen (StringPtr
);
2003 // Set to the got full request string.
2005 HiiToLower (FullConfigRequest
);
2006 if (*Request
!= NULL
) {
2007 FreePool (*Request
);
2009 *Request
= FullConfigRequest
;
2013 // 4. Construct Default Value string in AltResp according to request element.
2014 // Go through all VarStorageData Entry and get the DefaultId array for each one
2015 // Then construct them all to : ConfigHdr AltConfigHdr ConfigBody AltConfigHdr ConfigBody
2019 // Add length for <ConfigHdr> + '\0'
2021 Length
= StrLen (ConfigHdr
) + 1;
2023 for (Link
= DefaultIdArray
->Entry
.ForwardLink
; Link
!= &DefaultIdArray
->Entry
; Link
= Link
->ForwardLink
) {
2024 DefaultId
= BASE_CR (Link
, IFR_DEFAULT_DATA
, Entry
);
2026 // Add length for "&<ConfigHdr>&ALTCFG=XXXX"
2027 // |1| StrLen (ConfigHdr) | 8 | 4 |
2029 Length
+= (1 + StrLen (ConfigHdr
) + 8 + 4);
2031 for (LinkData
= VarStorageData
->BlockEntry
.ForwardLink
; LinkData
!= &VarStorageData
->BlockEntry
; LinkData
= LinkData
->ForwardLink
) {
2032 BlockData
= BASE_CR (LinkData
, IFR_BLOCK_DATA
, Entry
);
2033 for (LinkDefault
= BlockData
->DefaultValueEntry
.ForwardLink
; LinkDefault
!= &BlockData
->DefaultValueEntry
; LinkDefault
= LinkDefault
->ForwardLink
) {
2034 DefaultValueData
= BASE_CR (LinkDefault
, IFR_DEFAULT_DATA
, Entry
);
2035 if (DefaultValueData
->DefaultId
== DefaultId
->DefaultId
) {
2037 // Add length for "&OFFSET=XXXX&WIDTH=YYYY&VALUE=zzzzzzzzzzzz"
2038 // | 8 | 4 | 7 | 4 | 7 | Width * 2 |
2040 Length
+= (8 + 4 + 7 + 4 + 7 + BlockData
->Width
* 2);
2048 // No default value is found. The default string doesn't exist.
2051 Status
= EFI_SUCCESS
;
2056 // Allocate buffer for the entire <DefaultAltCfgResp>
2058 DefaultAltCfgResp
= AllocateZeroPool (Length
* sizeof (CHAR16
));
2059 if (DefaultAltCfgResp
== NULL
) {
2060 Status
= EFI_OUT_OF_RESOURCES
;
2063 StringPtr
= DefaultAltCfgResp
;
2066 // Start with <ConfigHdr>
2068 StrCpy (StringPtr
, ConfigHdr
);
2069 StringPtr
+= StrLen (StringPtr
);
2071 for (Link
= DefaultIdArray
->Entry
.ForwardLink
; Link
!= &DefaultIdArray
->Entry
; Link
= Link
->ForwardLink
) {
2072 DefaultId
= BASE_CR (Link
, IFR_DEFAULT_DATA
, Entry
);
2074 // Add <AltConfigHdr> of the form "&<ConfigHdr>&ALTCFG=XXXX\0"
2075 // |1| StrLen (ConfigHdr) | 8 | 4 |
2079 (1 + StrLen (ConfigHdr
) + 8 + 4 + 1) * sizeof (CHAR16
),
2082 DefaultId
->DefaultId
2084 StringPtr
+= StrLen (StringPtr
);
2086 for (LinkData
= VarStorageData
->BlockEntry
.ForwardLink
; LinkData
!= &VarStorageData
->BlockEntry
; LinkData
= LinkData
->ForwardLink
) {
2087 BlockData
= BASE_CR (LinkData
, IFR_BLOCK_DATA
, Entry
);
2088 for (LinkDefault
= BlockData
->DefaultValueEntry
.ForwardLink
; LinkDefault
!= &BlockData
->DefaultValueEntry
; LinkDefault
= LinkDefault
->ForwardLink
) {
2089 DefaultValueData
= BASE_CR (LinkDefault
, IFR_DEFAULT_DATA
, Entry
);
2090 if (DefaultValueData
->DefaultId
== DefaultId
->DefaultId
) {
2092 // Add <BlockConfig>
2093 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>
2097 (8 + 4 + 7 + 4 + 7 + 1) * sizeof (CHAR16
),
2098 L
"&OFFSET=%04X&WIDTH=%04X&VALUE=",
2102 StringPtr
+= StrLen (StringPtr
);
2105 // Convert Value to a hex string in "%x" format
2106 // NOTE: This is in the opposite byte that GUID and PATH use
2108 Width
= BlockData
->Width
;
2109 TmpBuffer
= (UINT8
*) &(DefaultValueData
->Value
);
2110 for (; Width
> 0; Width
--) {
2111 StringPtr
+= UnicodeValueToString (StringPtr
, PREFIX_ZERO
| RADIX_HEX
, TmpBuffer
[Width
- 1], 2);
2117 HiiToLower (DefaultAltCfgResp
);
2120 // 5. Merge string into the input AltCfgResp if the iput *AltCfgResp is not NULL.
2122 if (*AltCfgResp
!= NULL
&& DefaultAltCfgResp
!= NULL
) {
2123 Status
= MergeDefaultString (AltCfgResp
, DefaultAltCfgResp
);
2124 FreePool (DefaultAltCfgResp
);
2125 } else if (*AltCfgResp
== NULL
) {
2126 *AltCfgResp
= DefaultAltCfgResp
;
2130 if (RequestBlockArray
!= NULL
) {
2132 // Free Link Array RequestBlockArray
2134 while (!IsListEmpty (&RequestBlockArray
->Entry
)) {
2135 BlockData
= BASE_CR (RequestBlockArray
->Entry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
2136 RemoveEntryList (&BlockData
->Entry
);
2137 FreePool (BlockData
);
2140 FreePool (RequestBlockArray
);
2143 if (VarStorageData
!= NULL
) {
2145 // Free link array VarStorageData
2147 while (!IsListEmpty (&VarStorageData
->BlockEntry
)) {
2148 BlockData
= BASE_CR (VarStorageData
->BlockEntry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
2149 RemoveEntryList (&BlockData
->Entry
);
2151 // Free default value link array
2153 while (!IsListEmpty (&BlockData
->DefaultValueEntry
)) {
2154 DefaultValueData
= BASE_CR (BlockData
->DefaultValueEntry
.ForwardLink
, IFR_DEFAULT_DATA
, Entry
);
2155 RemoveEntryList (&DefaultValueData
->Entry
);
2156 FreePool (DefaultValueData
);
2158 FreePool (BlockData
);
2160 FreePool (VarStorageData
);
2163 if (DefaultIdArray
!= NULL
) {
2165 // Free DefaultId Array
2167 while (!IsListEmpty (&DefaultIdArray
->Entry
)) {
2168 DefaultId
= BASE_CR (DefaultIdArray
->Entry
.ForwardLink
, IFR_DEFAULT_DATA
, Entry
);
2169 RemoveEntryList (&DefaultId
->Entry
);
2170 FreePool (DefaultId
);
2172 FreePool (DefaultIdArray
);
2176 // Free the allocated string
2178 if (GuidStr
!= NULL
) {
2181 if (NameStr
!= NULL
) {
2184 if (PathStr
!= NULL
) {
2187 if (ConfigHdr
!= NULL
) {
2188 FreePool (ConfigHdr
);
2192 // Free Pacakge data
2194 if (HiiFormPackage
!= NULL
) {
2195 FreePool (HiiFormPackage
);
2198 if (PointerProgress
!= NULL
) {
2199 if (*Request
== NULL
) {
2200 *PointerProgress
= NULL
;
2201 } else if (EFI_ERROR (Status
)) {
2202 *PointerProgress
= Progress
;
2204 *PointerProgress
= *Request
+ StrLen (*Request
);
2212 This function allows a caller to extract the current configuration
2213 for one or more named elements from one or more drivers.
2215 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
2217 @param Request A null-terminated Unicode string in
2218 <MultiConfigRequest> format.
2219 @param Progress On return, points to a character in the Request
2220 string. Points to the string's null terminator if
2221 request was successful. Points to the most recent
2222 & before the first failing name / value pair (or
2223 the beginning of the string if the failure is in
2224 the first name / value pair) if the request was
2226 @param Results Null-terminated Unicode string in
2227 <MultiConfigAltResp> format which has all values
2228 filled in for the names in the Request string.
2229 String to be allocated by the called function.
2231 @retval EFI_SUCCESS The Results string is filled with the values
2232 corresponding to all requested names.
2233 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
2234 results that must be stored awaiting possible
2236 @retval EFI_NOT_FOUND Routing data doesn't match any known driver.
2237 Progress set to the "G" in "GUID" of the routing
2238 header that doesn't match. Note: There is no
2239 requirement that all routing data be validated
2240 before any configuration extraction.
2241 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Request
2242 parameter would result in this type of error. The
2243 Progress parameter is set to NULL.
2244 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set to most recent &
2245 before the error or the beginning of the string.
2246 @retval EFI_INVALID_PARAMETER Unknown name. Progress points to the & before the
2252 HiiConfigRoutingExtractConfig (
2253 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
2254 IN CONST EFI_STRING Request
,
2255 OUT EFI_STRING
*Progress
,
2256 OUT EFI_STRING
*Results
2259 HII_DATABASE_PRIVATE_DATA
*Private
;
2260 EFI_STRING StringPtr
;
2261 EFI_STRING ConfigRequest
;
2263 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
2264 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
2267 HII_DATABASE_RECORD
*Database
;
2268 UINT8
*DevicePathPkg
;
2269 UINT8
*CurrentDevicePath
;
2270 EFI_HANDLE DriverHandle
;
2271 EFI_HII_HANDLE HiiHandle
;
2272 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
2273 EFI_STRING AccessProgress
;
2274 EFI_STRING AccessResults
;
2275 EFI_STRING DefaultResults
;
2276 BOOLEAN FirstElement
;
2277 BOOLEAN IfrDataParsedFlag
;
2279 if (This
== NULL
|| Progress
== NULL
|| Results
== NULL
) {
2280 return EFI_INVALID_PARAMETER
;
2283 if (Request
== NULL
) {
2285 return EFI_INVALID_PARAMETER
;
2288 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
2289 StringPtr
= Request
;
2290 *Progress
= StringPtr
;
2291 DefaultResults
= NULL
;
2292 ConfigRequest
= NULL
;
2293 Status
= EFI_SUCCESS
;
2294 AccessResults
= NULL
;
2296 IfrDataParsedFlag
= FALSE
;
2299 // The first element of <MultiConfigRequest> should be
2300 // <GuidHdr>, which is in 'GUID='<Guid> syntax.
2302 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
2303 return EFI_INVALID_PARAMETER
;
2306 FirstElement
= TRUE
;
2309 // Allocate a fix length of memory to store Results. Reallocate memory for
2310 // Results if this fix length is insufficient.
2312 *Results
= (EFI_STRING
) AllocateZeroPool (MAX_STRING_LENGTH
);
2313 if (*Results
== NULL
) {
2314 return EFI_OUT_OF_RESOURCES
;
2317 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) == 0) {
2319 // If parsing error, set Progress to the beginning of the <MultiConfigRequest>
2320 // or most recent & before the error.
2322 if (StringPtr
== Request
) {
2323 *Progress
= StringPtr
;
2325 *Progress
= StringPtr
- 1;
2329 // Process each <ConfigRequest> of <MultiConfigRequest>
2331 Length
= CalculateConfigStringLen (StringPtr
);
2332 ConfigRequest
= AllocateCopyPool ((Length
+ 1) * sizeof (CHAR16
), StringPtr
);
2333 if (ConfigRequest
== NULL
) {
2334 Status
= EFI_OUT_OF_RESOURCES
;
2337 *(ConfigRequest
+ Length
) = 0;
2340 // Get the UEFI device path
2342 Status
= GetDevicePath (ConfigRequest
, (UINT8
**) &DevicePath
);
2343 if (EFI_ERROR (Status
)) {
2348 // Find driver which matches the routing data.
2350 DriverHandle
= NULL
;
2353 for (Link
= Private
->DatabaseList
.ForwardLink
;
2354 Link
!= &Private
->DatabaseList
;
2355 Link
= Link
->ForwardLink
2357 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
2358 if ((DevicePathPkg
= Database
->PackageList
->DevicePathPkg
) != NULL
) {
2359 CurrentDevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
2363 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) CurrentDevicePath
)
2365 DriverHandle
= Database
->DriverHandle
;
2366 HiiHandle
= Database
->Handle
;
2373 // Try to find driver handle by device path.
2375 if (DriverHandle
== NULL
) {
2376 TempDevicePath
= DevicePath
;
2377 Status
= gBS
->LocateDevicePath (
2378 &gEfiDevicePathProtocolGuid
,
2382 if (EFI_ERROR (Status
) || (DriverHandle
== NULL
)) {
2384 // Routing data does not match any known driver.
2385 // Set Progress to the 'G' in "GUID" of the routing header.
2387 *Progress
= StringPtr
;
2388 Status
= EFI_NOT_FOUND
;
2394 // Check whether ConfigRequest contains request string OFFSET/WIDTH
2396 IfrDataParsedFlag
= FALSE
;
2397 if ((HiiHandle
!= NULL
) && (StrStr (ConfigRequest
, L
"&OFFSET=") == NULL
)) {
2399 // Get the full request string from IFR when HiiPackage is registered to HiiHandle
2401 IfrDataParsedFlag
= TRUE
;
2402 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &ConfigRequest
, &DefaultResults
, &AccessProgress
);
2403 if (EFI_ERROR (Status
)) {
2405 // AccessProgress indicates the parsing progress on <ConfigRequest>.
2406 // Map it to the progress on <MultiConfigRequest> then return it.
2408 *Progress
= StrStr (StringPtr
, AccessProgress
);
2412 // Not any request block is found.
2414 if (StrStr (ConfigRequest
, L
"&OFFSET=") == NULL
) {
2415 AccessResults
= AllocateCopyPool (StrSize (ConfigRequest
), ConfigRequest
);
2416 goto NextConfigString
;
2421 // Call corresponding ConfigAccess protocol to extract settings
2423 Status
= gBS
->HandleProtocol (
2425 &gEfiHiiConfigAccessProtocolGuid
,
2426 (VOID
**) &ConfigAccess
2428 ASSERT_EFI_ERROR (Status
);
2430 Status
= ConfigAccess
->ExtractConfig (
2436 if (EFI_ERROR (Status
)) {
2438 // AccessProgress indicates the parsing progress on <ConfigRequest>.
2439 // Map it to the progress on <MultiConfigRequest> then return it.
2441 *Progress
= StrStr (StringPtr
, AccessProgress
);
2446 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'
2447 // which seperates the first <ConfigAltResp> and the following ones.
2449 ASSERT (*AccessProgress
== 0);
2452 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
2454 if (!IfrDataParsedFlag
&& HiiHandle
!= NULL
) {
2455 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &ConfigRequest
, &DefaultResults
, NULL
);
2456 ASSERT_EFI_ERROR (Status
);
2459 FreePool (DevicePath
);
2462 if (DefaultResults
!= NULL
) {
2463 Status
= MergeDefaultString (&AccessResults
, DefaultResults
);
2464 ASSERT_EFI_ERROR (Status
);
2465 FreePool (DefaultResults
);
2466 DefaultResults
= NULL
;
2470 if (!FirstElement
) {
2471 Status
= AppendToMultiString (Results
, L
"&");
2472 ASSERT_EFI_ERROR (Status
);
2475 Status
= AppendToMultiString (Results
, AccessResults
);
2476 ASSERT_EFI_ERROR (Status
);
2478 FirstElement
= FALSE
;
2480 FreePool (AccessResults
);
2481 AccessResults
= NULL
;
2482 FreePool (ConfigRequest
);
2483 ConfigRequest
= NULL
;
2486 // Go to next <ConfigRequest> (skip '&').
2488 StringPtr
+= Length
;
2489 if (*StringPtr
== 0) {
2490 *Progress
= StringPtr
;
2498 if (EFI_ERROR (Status
)) {
2499 FreePool (*Results
);
2503 if (ConfigRequest
!= NULL
) {
2504 FreePool (ConfigRequest
);
2507 if (AccessResults
!= NULL
) {
2508 FreePool (AccessResults
);
2511 if (DefaultResults
!= NULL
) {
2512 FreePool (DefaultResults
);
2515 if (DevicePath
!= NULL
) {
2516 FreePool (DevicePath
);
2524 This function allows the caller to request the current configuration for the
2525 entirety of the current HII database and returns the data in a
2526 null-terminated Unicode string.
2528 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
2530 @param Results Null-terminated Unicode string in
2531 <MultiConfigAltResp> format which has all values
2532 filled in for the names in the Request string.
2533 String to be allocated by the called function.
2534 De-allocation is up to the caller.
2536 @retval EFI_SUCCESS The Results string is filled with the values
2537 corresponding to all requested names.
2538 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
2539 results that must be stored awaiting possible
2541 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Results
2542 parameter would result in this type of error.
2547 HiiConfigRoutingExportConfig (
2548 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
2549 OUT EFI_STRING
*Results
2553 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
2554 EFI_STRING AccessResults
;
2555 EFI_STRING Progress
;
2556 EFI_STRING StringPtr
;
2557 EFI_STRING ConfigRequest
;
2559 EFI_HANDLE
*ConfigAccessHandles
;
2560 UINTN NumberConfigAccessHandles
;
2561 BOOLEAN FirstElement
;
2562 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
2563 EFI_HII_HANDLE HiiHandle
;
2564 EFI_STRING DefaultResults
;
2565 HII_DATABASE_PRIVATE_DATA
*Private
;
2567 HII_DATABASE_RECORD
*Database
;
2568 UINT8
*DevicePathPkg
;
2569 UINT8
*CurrentDevicePath
;
2570 BOOLEAN IfrDataParsedFlag
;
2572 if (This
== NULL
|| Results
== NULL
) {
2573 return EFI_INVALID_PARAMETER
;
2576 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
2579 // Allocate a fix length of memory to store Results. Reallocate memory for
2580 // Results if this fix length is insufficient.
2582 *Results
= (EFI_STRING
) AllocateZeroPool (MAX_STRING_LENGTH
);
2583 if (*Results
== NULL
) {
2584 return EFI_OUT_OF_RESOURCES
;
2587 NumberConfigAccessHandles
= 0;
2588 Status
= gBS
->LocateHandleBuffer (
2590 &gEfiHiiConfigAccessProtocolGuid
,
2592 &NumberConfigAccessHandles
,
2593 &ConfigAccessHandles
2595 if (EFI_ERROR (Status
)) {
2599 FirstElement
= TRUE
;
2601 for (Index
= 0; Index
< NumberConfigAccessHandles
; Index
++) {
2602 Status
= gBS
->HandleProtocol (
2603 ConfigAccessHandles
[Index
],
2604 &gEfiHiiConfigAccessProtocolGuid
,
2605 (VOID
**) &ConfigAccess
2607 if (EFI_ERROR (Status
)) {
2612 // Get DevicePath and HiiHandle for this ConfigAccess driver handle
2614 IfrDataParsedFlag
= FALSE
;
2617 DefaultResults
= NULL
;
2619 ConfigRequest
= NULL
;
2620 DevicePath
= DevicePathFromHandle (ConfigAccessHandles
[Index
]);
2621 if (DevicePath
!= NULL
) {
2622 for (Link
= Private
->DatabaseList
.ForwardLink
;
2623 Link
!= &Private
->DatabaseList
;
2624 Link
= Link
->ForwardLink
2626 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
2627 if ((DevicePathPkg
= Database
->PackageList
->DevicePathPkg
) != NULL
) {
2628 CurrentDevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
2632 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) CurrentDevicePath
)
2634 HiiHandle
= Database
->Handle
;
2641 Status
= ConfigAccess
->ExtractConfig (
2647 if (EFI_ERROR (Status
)) {
2649 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
2651 if (HiiHandle
!= NULL
&& DevicePath
!= NULL
) {
2652 IfrDataParsedFlag
= TRUE
;
2653 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &ConfigRequest
, &DefaultResults
, NULL
);
2655 // Get the full request string to get the Current setting again.
2657 if (!EFI_ERROR (Status
) && ConfigRequest
!= NULL
) {
2658 Status
= ConfigAccess
->ExtractConfig (
2664 FreePool (ConfigRequest
);
2666 Status
= EFI_NOT_FOUND
;
2671 if (!EFI_ERROR (Status
)) {
2673 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
2675 if (!IfrDataParsedFlag
&& HiiHandle
!= NULL
&& DevicePath
!= NULL
) {
2676 StringPtr
= StrStr (AccessResults
, L
"&GUID=");
2677 if (StringPtr
!= NULL
) {
2680 if (StrStr (AccessResults
, L
"&OFFSET=") != NULL
) {
2681 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &AccessResults
, &DefaultResults
, NULL
);
2682 ASSERT_EFI_ERROR (Status
);
2684 if (StringPtr
!= NULL
) {
2689 // Merge the default sting from IFR code into the got setting from driver.
2691 if (DefaultResults
!= NULL
) {
2692 Status
= MergeDefaultString (&AccessResults
, DefaultResults
);
2693 ASSERT_EFI_ERROR (Status
);
2694 FreePool (DefaultResults
);
2695 DefaultResults
= NULL
;
2699 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'
2700 // which seperates the first <ConfigAltResp> and the following ones.
2702 if (!FirstElement
) {
2703 Status
= AppendToMultiString (Results
, L
"&");
2704 ASSERT_EFI_ERROR (Status
);
2707 Status
= AppendToMultiString (Results
, AccessResults
);
2708 ASSERT_EFI_ERROR (Status
);
2710 FirstElement
= FALSE
;
2712 FreePool (AccessResults
);
2713 AccessResults
= NULL
;
2716 FreePool (ConfigAccessHandles
);
2723 This function processes the results of processing forms and routes it to the
2724 appropriate handlers or storage.
2726 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
2728 @param Configuration A null-terminated Unicode string in
2729 <MulltiConfigResp> format.
2730 @param Progress A pointer to a string filled in with the offset of
2731 the most recent & before the first failing name /
2732 value pair (or the beginning of the string if the
2733 failure is in the first name / value pair) or the
2734 terminating NULL if all was successful.
2736 @retval EFI_SUCCESS The results have been distributed or are awaiting
2738 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
2739 results that must be stored awaiting possible
2741 @retval EFI_INVALID_PARAMETER Passing in a NULL for the Configuration parameter
2742 would result in this type of error.
2743 @retval EFI_NOT_FOUND Target for the specified routing data was not
2749 HiiConfigRoutingRouteConfig (
2750 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
2751 IN CONST EFI_STRING Configuration
,
2752 OUT EFI_STRING
*Progress
2755 HII_DATABASE_PRIVATE_DATA
*Private
;
2756 EFI_STRING StringPtr
;
2757 EFI_STRING ConfigResp
;
2760 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
2761 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
2763 HII_DATABASE_RECORD
*Database
;
2764 UINT8
*DevicePathPkg
;
2765 UINT8
*CurrentDevicePath
;
2766 EFI_HANDLE DriverHandle
;
2767 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
2768 EFI_STRING AccessProgress
;
2770 if (This
== NULL
|| Progress
== NULL
) {
2771 return EFI_INVALID_PARAMETER
;
2774 if (Configuration
== NULL
) {
2776 return EFI_INVALID_PARAMETER
;
2779 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
2780 StringPtr
= Configuration
;
2781 *Progress
= StringPtr
;
2784 // The first element of <MultiConfigResp> should be
2785 // <GuidHdr>, which is in 'GUID='<Guid> syntax.
2787 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
2788 return EFI_INVALID_PARAMETER
;
2791 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) == 0) {
2793 // If parsing error, set Progress to the beginning of the <MultiConfigResp>
2794 // or most recent & before the error.
2796 if (StringPtr
== Configuration
) {
2797 *Progress
= StringPtr
;
2799 *Progress
= StringPtr
- 1;
2803 // Process each <ConfigResp> of <MultiConfigResp>
2805 Length
= CalculateConfigStringLen (StringPtr
);
2806 ConfigResp
= AllocateCopyPool ((Length
+ 1) * sizeof (CHAR16
), StringPtr
);
2807 if (ConfigResp
== NULL
) {
2808 return EFI_OUT_OF_RESOURCES
;
2811 // Append '\0' to the end of ConfigRequest
2813 *(ConfigResp
+ Length
) = 0;
2816 // Get the UEFI device path
2818 Status
= GetDevicePath (ConfigResp
, (UINT8
**) &DevicePath
);
2819 if (EFI_ERROR (Status
)) {
2820 FreePool (ConfigResp
);
2825 // Find driver which matches the routing data.
2827 DriverHandle
= NULL
;
2828 for (Link
= Private
->DatabaseList
.ForwardLink
;
2829 Link
!= &Private
->DatabaseList
;
2830 Link
= Link
->ForwardLink
2832 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
2834 if ((DevicePathPkg
= Database
->PackageList
->DevicePathPkg
) != NULL
) {
2835 CurrentDevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
2839 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) CurrentDevicePath
)
2841 DriverHandle
= Database
->DriverHandle
;
2848 // Try to find driver handle by device path.
2850 if (DriverHandle
== NULL
) {
2851 TempDevicePath
= DevicePath
;
2852 Status
= gBS
->LocateDevicePath (
2853 &gEfiDevicePathProtocolGuid
,
2857 if (EFI_ERROR (Status
) || (DriverHandle
== NULL
)) {
2859 // Routing data does not match any known driver.
2860 // Set Progress to the 'G' in "GUID" of the routing header.
2862 FreePool (DevicePath
);
2863 *Progress
= StringPtr
;
2864 FreePool (ConfigResp
);
2865 return EFI_NOT_FOUND
;
2869 FreePool (DevicePath
);
2872 // Call corresponding ConfigAccess protocol to route settings
2874 Status
= gBS
->HandleProtocol (
2876 &gEfiHiiConfigAccessProtocolGuid
,
2877 (VOID
**) &ConfigAccess
2879 ASSERT_EFI_ERROR (Status
);
2881 Status
= ConfigAccess
->RouteConfig (
2887 if (EFI_ERROR (Status
)) {
2889 // AccessProgress indicates the parsing progress on <ConfigResp>.
2890 // Map it to the progress on <MultiConfigResp> then return it.
2892 *Progress
= StrStr (StringPtr
, AccessProgress
);
2894 FreePool (ConfigResp
);
2898 FreePool (ConfigResp
);
2902 // Go to next <ConfigResp> (skip '&').
2904 StringPtr
+= Length
;
2905 if (*StringPtr
== 0) {
2906 *Progress
= StringPtr
;
2919 This helper function is to be called by drivers to map configuration data
2920 stored in byte array ("block") formats such as UEFI Variables into current
2921 configuration strings.
2923 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
2925 @param ConfigRequest A null-terminated Unicode string in
2926 <ConfigRequest> format.
2927 @param Block Array of bytes defining the block's configuration.
2928 @param BlockSize Length in bytes of Block.
2929 @param Config Filled-in configuration string. String allocated
2930 by the function. Returned only if call is
2931 successful. It is <ConfigResp> string format.
2932 @param Progress A pointer to a string filled in with the offset of
2933 the most recent & before the first failing
2934 name/value pair (or the beginning of the string if
2935 the failure is in the first name / value pair) or
2936 the terminating NULL if all was successful.
2938 @retval EFI_SUCCESS The request succeeded. Progress points to the null
2939 terminator at the end of the ConfigRequest
2941 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress
2942 points to the first character of ConfigRequest.
2943 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigRequest or
2944 Block parameter would result in this type of
2945 error. Progress points to the first character of
2947 @retval EFI_DEVICE_ERROR Block not large enough. Progress undefined.
2948 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted string.
2949 Block is left updated and Progress points at
2950 the "&" preceding the first non-<BlockName>.
2956 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
2957 IN CONST EFI_STRING ConfigRequest
,
2958 IN CONST UINT8
*Block
,
2959 IN CONST UINTN BlockSize
,
2960 OUT EFI_STRING
*Config
,
2961 OUT EFI_STRING
*Progress
2964 HII_DATABASE_PRIVATE_DATA
*Private
;
2965 EFI_STRING StringPtr
;
2973 EFI_STRING ValueStr
;
2974 EFI_STRING ConfigElement
;
2979 if (This
== NULL
|| Progress
== NULL
|| Config
== NULL
) {
2980 return EFI_INVALID_PARAMETER
;
2983 if (Block
== NULL
|| ConfigRequest
== NULL
) {
2984 *Progress
= ConfigRequest
;
2985 return EFI_INVALID_PARAMETER
;
2989 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
2990 ASSERT (Private
!= NULL
);
2992 StringPtr
= ConfigRequest
;
2995 ConfigElement
= NULL
;
2998 // Allocate a fix length of memory to store Results. Reallocate memory for
2999 // Results if this fix length is insufficient.
3001 *Config
= (EFI_STRING
) AllocateZeroPool (MAX_STRING_LENGTH
);
3002 if (*Config
== NULL
) {
3003 return EFI_OUT_OF_RESOURCES
;
3009 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
3010 *Progress
= StringPtr
;
3011 Status
= EFI_INVALID_PARAMETER
;
3014 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"PATH=", StrLen (L
"PATH=")) != 0) {
3017 if (*StringPtr
== 0) {
3018 *Progress
= StringPtr
- 1;
3019 Status
= EFI_INVALID_PARAMETER
;
3023 while (*StringPtr
!= L
'&' && *StringPtr
!= 0) {
3026 if (*StringPtr
== 0) {
3027 *Progress
= StringPtr
- 1;
3028 Status
= EFI_INVALID_PARAMETER
;
3037 // Copy <ConfigHdr> and an additional '&' to <ConfigResp>
3039 Length
= StringPtr
- ConfigRequest
;
3040 CopyMem (*Config
, ConfigRequest
, Length
* sizeof (CHAR16
));
3043 // Parse each <RequestElement> if exists
3044 // Only <BlockName> format is supported by this help function.
3045 // <BlockName> ::= 'OFFSET='<Number>&'WIDTH='<Number>
3047 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"OFFSET=", StrLen (L
"OFFSET=")) == 0) {
3049 // Back up the header of one <BlockName>
3053 StringPtr
+= StrLen (L
"OFFSET=");
3057 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
3058 if (EFI_ERROR (Status
)) {
3059 *Progress
= ConfigRequest
;
3066 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
3068 FreePool (TmpBuffer
);
3070 StringPtr
+= Length
;
3071 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
3072 *Progress
= StringPtr
- Length
- StrLen (L
"OFFSET=") - 1;
3073 Status
= EFI_INVALID_PARAMETER
;
3076 StringPtr
+= StrLen (L
"&WIDTH=");
3081 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
3082 if (EFI_ERROR (Status
)) {
3083 *Progress
= ConfigRequest
;
3090 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
3092 FreePool (TmpBuffer
);
3094 StringPtr
+= Length
;
3095 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
3096 *Progress
= StringPtr
- Length
- StrLen (L
"&WIDTH=");
3097 Status
= EFI_INVALID_PARAMETER
;
3102 // Calculate Value and convert it to hex string.
3104 if (Offset
+ Width
> BlockSize
) {
3105 *Progress
= StringPtr
;
3106 Status
= EFI_DEVICE_ERROR
;
3110 Value
= (UINT8
*) AllocateZeroPool (Width
);
3111 if (Value
== NULL
) {
3112 *Progress
= ConfigRequest
;
3113 Status
= EFI_OUT_OF_RESOURCES
;
3117 CopyMem (Value
, (UINT8
*) Block
+ Offset
, Width
);
3119 Length
= Width
* 2 + 1;
3120 ValueStr
= (EFI_STRING
) AllocateZeroPool (Length
* sizeof (CHAR16
));
3121 if (ValueStr
== NULL
) {
3122 *Progress
= ConfigRequest
;
3123 Status
= EFI_OUT_OF_RESOURCES
;
3127 TemString
= ValueStr
;
3128 TemBuffer
= Value
+ Width
- 1;
3129 for (Index
= 0; Index
< Width
; Index
++, TemBuffer
--) {
3130 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
3137 // Build a ConfigElement
3139 Length
+= StringPtr
- TmpPtr
+ 1 + StrLen (L
"VALUE=");
3140 ConfigElement
= (EFI_STRING
) AllocateZeroPool (Length
* sizeof (CHAR16
));
3141 if (ConfigElement
== NULL
) {
3142 Status
= EFI_OUT_OF_RESOURCES
;
3145 CopyMem (ConfigElement
, TmpPtr
, (StringPtr
- TmpPtr
+ 1) * sizeof (CHAR16
));
3146 if (*StringPtr
== 0) {
3147 *(ConfigElement
+ (StringPtr
- TmpPtr
)) = L
'&';
3149 *(ConfigElement
+ (StringPtr
- TmpPtr
) + 1) = 0;
3150 StrCat (ConfigElement
, L
"VALUE=");
3151 StrCat (ConfigElement
, ValueStr
);
3153 AppendToMultiString (Config
, ConfigElement
);
3155 FreePool (ConfigElement
);
3156 FreePool (ValueStr
);
3157 ConfigElement
= NULL
;
3161 // If '\0', parsing is finished. Otherwise skip '&' to continue
3163 if (*StringPtr
== 0) {
3166 AppendToMultiString (Config
, L
"&");
3171 if (*StringPtr
!= 0) {
3172 *Progress
= StringPtr
- 1;
3173 Status
= EFI_INVALID_PARAMETER
;
3177 HiiToLower (*Config
);
3178 *Progress
= StringPtr
;
3182 if (*Config
!= NULL
) {
3186 if (ValueStr
!= NULL
) {
3187 FreePool (ValueStr
);
3189 if (Value
!= NULL
) {
3192 if (ConfigElement
!= NULL
) {
3193 FreePool (ConfigElement
);
3202 This helper function is to be called by drivers to map configuration strings
3203 to configurations stored in byte array ("block") formats such as UEFI Variables.
3205 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
3207 @param ConfigResp A null-terminated Unicode string in <ConfigResp>
3209 @param Block A possibly null array of bytes representing the
3210 current block. Only bytes referenced in the
3211 ConfigResp string in the block are modified. If
3212 this parameter is null or if the *BlockSize
3213 parameter is (on input) shorter than required by
3214 the Configuration string, only the BlockSize
3215 parameter is updated and an appropriate status
3216 (see below) is returned.
3217 @param BlockSize The length of the Block in units of UINT8. On
3218 input, this is the size of the Block. On output,
3219 if successful, contains the index of the last
3220 modified byte in the Block.
3221 @param Progress On return, points to an element of the ConfigResp
3222 string filled in with the offset of the most
3223 recent '&' before the first failing name / value
3224 pair (or the beginning of the string if the
3225 failure is in the first name / value pair) or the
3226 terminating NULL if all was successful.
3228 @retval EFI_SUCCESS The request succeeded. Progress points to the null
3229 terminator at the end of the ConfigResp string.
3230 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress
3231 points to the first character of ConfigResp.
3232 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigResp or
3233 Block parameter would result in this type of
3234 error. Progress points to the first character of
3236 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted name /
3237 value pair. Block is left updated and
3238 Progress points at the '&' preceding the first
3240 @retval EFI_DEVICE_ERROR Block not large enough. Progress undefined.
3241 @retval EFI_NOT_FOUND Target for the specified routing data was not found.
3242 Progress points to the "G" in "GUID" of the errant
3249 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
3250 IN CONST EFI_STRING ConfigResp
,
3251 IN OUT UINT8
*Block
,
3252 IN OUT UINTN
*BlockSize
,
3253 OUT EFI_STRING
*Progress
3256 HII_DATABASE_PRIVATE_DATA
*Private
;
3257 EFI_STRING StringPtr
;
3267 if (This
== NULL
|| BlockSize
== NULL
|| Progress
== NULL
) {
3268 return EFI_INVALID_PARAMETER
;
3271 *Progress
= ConfigResp
;
3272 if (ConfigResp
== NULL
) {
3273 return EFI_INVALID_PARAMETER
;
3276 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
3277 ASSERT (Private
!= NULL
);
3279 StringPtr
= ConfigResp
;
3280 BufferSize
= *BlockSize
;
3287 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
3288 *Progress
= StringPtr
;
3289 Status
= EFI_INVALID_PARAMETER
;
3292 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"PATH=", StrLen (L
"PATH=")) != 0) {
3295 if (*StringPtr
== 0) {
3296 *Progress
= StringPtr
;
3297 Status
= EFI_INVALID_PARAMETER
;
3301 while (*StringPtr
!= L
'&' && *StringPtr
!= 0) {
3304 if (*StringPtr
== 0) {
3305 *Progress
= StringPtr
;
3306 Status
= EFI_INVALID_PARAMETER
;
3315 // Parse each <ConfigElement> if exists
3316 // Only <BlockConfig> format is supported by this help function.
3317 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE='<Number>
3319 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"OFFSET=", StrLen (L
"OFFSET=")) == 0) {
3320 StringPtr
+= StrLen (L
"OFFSET=");
3324 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
3325 if (EFI_ERROR (Status
)) {
3326 *Progress
= ConfigResp
;
3333 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
3335 FreePool (TmpBuffer
);
3337 StringPtr
+= Length
;
3338 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
3339 *Progress
= StringPtr
- Length
- StrLen (L
"OFFSET=") - 1;
3340 Status
= EFI_INVALID_PARAMETER
;
3343 StringPtr
+= StrLen (L
"&WIDTH=");
3348 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
3349 if (EFI_ERROR (Status
)) {
3350 *Progress
= ConfigResp
;
3357 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
3359 FreePool (TmpBuffer
);
3361 StringPtr
+= Length
;
3362 if (StrnCmp (StringPtr
, L
"&VALUE=", StrLen (L
"&VALUE=")) != 0) {
3363 *Progress
= StringPtr
- Length
- StrLen (L
"&WIDTH=");
3364 Status
= EFI_INVALID_PARAMETER
;
3367 StringPtr
+= StrLen (L
"&VALUE=");
3372 Status
= GetValueOfNumber (StringPtr
, &Value
, &Length
);
3373 if (EFI_ERROR (Status
)) {
3374 *Progress
= ConfigResp
;
3378 StringPtr
+= Length
;
3379 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
3380 *Progress
= StringPtr
- Length
- 7;
3381 Status
= EFI_INVALID_PARAMETER
;
3386 // Update the Block with configuration info
3388 if ((Block
!= NULL
) && (Offset
+ Width
<= BufferSize
)) {
3389 CopyMem (Block
+ Offset
, Value
, Width
);
3391 if (Offset
+ Width
> MaxBlockSize
) {
3392 MaxBlockSize
= Offset
+ Width
;
3399 // If '\0', parsing is finished. Otherwise skip '&' to continue
3401 if (*StringPtr
== 0) {
3409 // The input string is ConfigAltResp format.
3411 if ((*StringPtr
!= 0) && (StrnCmp (StringPtr
, L
"&GUID=", StrLen (L
"&GUID=")) != 0)) {
3412 *Progress
= StringPtr
- 1;
3413 Status
= EFI_INVALID_PARAMETER
;
3417 *Progress
= StringPtr
+ StrLen (StringPtr
);
3418 *BlockSize
= MaxBlockSize
- 1;
3420 if (MaxBlockSize
> BufferSize
) {
3421 *BlockSize
= MaxBlockSize
;
3422 if (Block
!= NULL
) {
3423 return EFI_DEVICE_ERROR
;
3427 if (Block
== NULL
) {
3428 *Progress
= ConfigResp
;
3429 return EFI_INVALID_PARAMETER
;
3436 if (Value
!= NULL
) {
3444 This helper function is to be called by drivers to extract portions of
3445 a larger configuration string.
3447 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
3449 @param Configuration A null-terminated Unicode string in
3450 <MultiConfigAltResp> format.
3451 @param Guid A pointer to the GUID value to search for in the
3452 routing portion of the ConfigResp string when
3453 retrieving the requested data. If Guid is NULL,
3454 then all GUID values will be searched for.
3455 @param Name A pointer to the NAME value to search for in the
3456 routing portion of the ConfigResp string when
3457 retrieving the requested data. If Name is NULL,
3458 then all Name values will be searched for.
3459 @param DevicePath A pointer to the PATH value to search for in the
3460 routing portion of the ConfigResp string when
3461 retrieving the requested data. If DevicePath is
3462 NULL, then all DevicePath values will be searched
3464 @param AltCfgId A pointer to the ALTCFG value to search for in the
3465 routing portion of the ConfigResp string when
3466 retrieving the requested data. If this parameter
3467 is NULL, then the current setting will be
3469 @param AltCfgResp A pointer to a buffer which will be allocated by
3470 the function which contains the retrieved string
3471 as requested. This buffer is only allocated if
3472 the call was successful. It is <ConfigResp> format.
3474 @retval EFI_SUCCESS The request succeeded. The requested data was
3475 extracted and placed in the newly allocated
3477 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate AltCfgResp.
3478 @retval EFI_INVALID_PARAMETER Any parameter is invalid.
3479 @retval EFI_NOT_FOUND Target for the specified routing data was not
3486 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
3487 IN CONST EFI_STRING Configuration
,
3488 IN CONST EFI_GUID
*Guid
,
3489 IN CONST EFI_STRING Name
,
3490 IN CONST EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
3491 IN CONST UINT16
*AltCfgId
,
3492 OUT EFI_STRING
*AltCfgResp
3496 EFI_STRING StringPtr
;
3497 EFI_STRING HdrStart
;
3504 EFI_STRING AltIdStr
;
3521 if (This
== NULL
|| Configuration
== NULL
|| AltCfgResp
== NULL
) {
3522 return EFI_INVALID_PARAMETER
;
3525 StringPtr
= Configuration
;
3526 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
3527 return EFI_INVALID_PARAMETER
;
3531 // Generate the sub string for later matching.
3533 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*) Guid
, 1, &GuidStr
);
3536 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) DevicePath
),
3537 (VOID
*) DevicePath
,
3541 if (AltCfgId
!= NULL
) {
3542 GenerateSubStr (L
"ALTCFG=", sizeof (UINT16
), (VOID
*) AltCfgId
, 3, &AltIdStr
);
3545 GenerateSubStr (L
"NAME=", StrLen (Name
) * sizeof (CHAR16
), (VOID
*) Name
, 2, &NameStr
);
3547 GenerateSubStr (L
"NAME=", 0, NULL
, 2, &NameStr
);
3550 while (*StringPtr
!= 0) {
3552 // Try to match the GUID
3555 TmpPtr
= StrStr (StringPtr
, GuidStr
);
3556 if (TmpPtr
== NULL
) {
3557 Status
= EFI_NOT_FOUND
;
3563 // Jump to <NameHdr>
3566 StringPtr
= TmpPtr
+ StrLen (GuidStr
);
3568 StringPtr
= StrStr (TmpPtr
, L
"NAME=");
3569 if (StringPtr
== NULL
) {
3570 Status
= EFI_NOT_FOUND
;
3578 // Try to match the NAME
3580 if (GuidFlag
&& !NameFlag
) {
3581 if (StrnCmp (StringPtr
, NameStr
, StrLen (NameStr
)) != 0) {
3585 // Jump to <PathHdr>
3588 StringPtr
+= StrLen (NameStr
);
3590 StringPtr
= StrStr (StringPtr
, L
"PATH=");
3591 if (StringPtr
== NULL
) {
3592 Status
= EFI_NOT_FOUND
;
3601 // Try to match the DevicePath
3603 if (GuidFlag
&& NameFlag
&& !PathFlag
) {
3604 if (StrnCmp (StringPtr
, PathStr
, StrLen (PathStr
)) != 0) {
3609 // Jump to '&' before <DescHdr> or <ConfigBody>
3611 if (DevicePath
!= NULL
) {
3612 StringPtr
+= StrLen (PathStr
);
3614 StringPtr
= StrStr (StringPtr
, L
"&");
3615 if (StringPtr
== NULL
) {
3616 Status
= EFI_NOT_FOUND
;
3627 // Try to match the AltCfgId
3629 if (GuidFlag
&& NameFlag
&& PathFlag
) {
3630 if (AltCfgId
== NULL
) {
3632 // Return Current Setting when AltCfgId is NULL.
3634 Status
= OutputConfigBody (StringPtr
, &Result
);
3638 // Search the <ConfigAltResp> to get the <AltResp> with AltCfgId.
3640 if (StrnCmp (StringPtr
, AltIdStr
, StrLen (AltIdStr
)) != 0) {
3646 // Skip AltIdStr and &
3648 StringPtr
= StringPtr
+ StrLen (AltIdStr
);
3649 Status
= OutputConfigBody (StringPtr
, &Result
);
3655 Status
= EFI_NOT_FOUND
;
3659 if (!EFI_ERROR (Status
) && (Result
!= NULL
)) {
3661 // Copy the <ConfigHdr> and <ConfigBody>
3663 Length
= HdrEnd
- HdrStart
+ StrLen (Result
) + 1;
3664 *AltCfgResp
= AllocateZeroPool (Length
* sizeof (CHAR16
));
3665 if (*AltCfgResp
== NULL
) {
3666 Status
= EFI_OUT_OF_RESOURCES
;
3668 StrnCpy (*AltCfgResp
, HdrStart
, HdrEnd
- HdrStart
);
3669 StrCat (*AltCfgResp
, Result
);
3670 Status
= EFI_SUCCESS
;
3674 if (GuidStr
!= NULL
) {
3677 if (NameStr
!= NULL
) {
3680 if (PathStr
!= NULL
) {
3683 if (AltIdStr
!= NULL
) {
3684 FreePool (AltIdStr
);
3686 if (Result
!= NULL
) {