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
) {
658 // DEFAULT_VALUE_FROM_OPCODE has high priority, DEFAULT_VALUE_FROM_DEFAULT has low priority.
660 if (DefaultValueData
->Type
> DefaultValueArray
->Type
) {
662 // Update the default value array in BlockData.
664 CopyMem (&DefaultValueArray
->Value
, &DefaultValueData
->Value
, sizeof (EFI_IFR_TYPE_VALUE
));
665 DefaultValueArray
->Type
= DefaultValueData
->Type
;
666 DefaultValueArray
->Cleaned
= DefaultValueData
->Cleaned
;
673 // Insert new default value data in tail.
675 DefaultValueArray
= AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
676 ASSERT (DefaultValueArray
!= NULL
);
677 CopyMem (DefaultValueArray
, DefaultValueData
, sizeof (IFR_DEFAULT_DATA
));
678 InsertTailList (Link
, &DefaultValueArray
->Entry
);
682 This function inserts new BlockData into the block link
684 @param BlockLink The list entry points to block array.
685 @param BlockData The point to BlockData is added.
690 IN LIST_ENTRY
*BlockLink
,
691 IN IFR_BLOCK_DATA
**BlockData
695 IFR_BLOCK_DATA
*BlockArray
;
696 IFR_BLOCK_DATA
*BlockSingleData
;
698 BlockSingleData
= *BlockData
;
701 // Insert block data in its Offset and Width order.
703 for (Link
= BlockLink
->ForwardLink
; Link
!= BlockLink
; Link
= Link
->ForwardLink
) {
704 BlockArray
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
705 if (BlockArray
->Offset
== BlockSingleData
->Offset
) {
706 if (BlockArray
->Width
> BlockSingleData
->Width
) {
708 // Insert this block data in the front of block array
710 InsertTailList (Link
, &BlockSingleData
->Entry
);
714 if (BlockArray
->Width
== BlockSingleData
->Width
) {
716 // The same block array has been added.
718 FreePool (BlockSingleData
);
719 *BlockData
= BlockArray
;
722 } else if (BlockArray
->Offset
> BlockSingleData
->Offset
) {
724 // Insert new block data in the front of block array
726 InsertTailList (Link
, &BlockSingleData
->Entry
);
732 // Add new block data into the tail.
734 InsertTailList (Link
, &BlockSingleData
->Entry
);
739 This function checks VarOffset and VarWidth is in the block range.
741 @param RequestBlockArray The block array is to be checked.
742 @param VarOffset Offset of var to the structure
743 @param VarWidth Width of var.
745 @retval TRUE This Var is in the block range.
746 @retval FALSE This Var is not in the block range.
750 IN IFR_BLOCK_DATA
*RequestBlockArray
,
756 IFR_BLOCK_DATA
*BlockData
;
759 // No Request Block array, all vars are got.
761 if (RequestBlockArray
== NULL
) {
766 // Check the input var is in the request block range.
768 for (Link
= RequestBlockArray
->Entry
.ForwardLink
; Link
!= &RequestBlockArray
->Entry
; Link
= Link
->ForwardLink
) {
769 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
770 if ((VarOffset
>= BlockData
->Offset
) && ((VarOffset
+ VarWidth
) <= (BlockData
->Offset
+ BlockData
->Width
))) {
779 Get form package data from data base.
781 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
782 @param HiiFormPackage The buffer saves the package data.
783 @param PackageSize The buffer size of the package data.
788 IN HII_DATABASE_RECORD
*DataBaseRecord
,
789 IN OUT UINT8
**HiiFormPackage
,
790 OUT UINTN
*PackageSize
797 if (DataBaseRecord
== NULL
|| HiiFormPackage
== NULL
|| PackageSize
== NULL
) {
798 return EFI_INVALID_PARAMETER
;
804 // 0. Get Hii Form Package by HiiHandle
806 Status
= ExportFormPackages (
808 DataBaseRecord
->Handle
,
809 DataBaseRecord
->PackageList
,
815 if (EFI_ERROR (Status
)) {
819 (*HiiFormPackage
) = AllocatePool (ResultSize
);
820 if (*HiiFormPackage
== NULL
) {
821 Status
= EFI_OUT_OF_RESOURCES
;
826 // Get HiiFormPackage by HiiHandle
830 Status
= ExportFormPackages (
832 DataBaseRecord
->Handle
,
833 DataBaseRecord
->PackageList
,
839 if (EFI_ERROR (Status
)) {
840 FreePool (*HiiFormPackage
);
850 This function parses Form Package to get the efi varstore info according to the request ConfigHdr.
852 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
853 @param ConfigHdr Request string ConfigHdr. If it is NULL,
854 the first found varstore will be as ConfigHdr.
855 @param IsEfiVarstore Whether the request storage type is efi varstore type.
856 @param EfiVarStore The efi varstore info which will return.
860 IN HII_DATABASE_RECORD
*DataBaseRecord
,
861 IN EFI_STRING ConfigHdr
,
862 OUT BOOLEAN
*IsEfiVarstore
,
863 OUT EFI_IFR_VARSTORE_EFI
**EfiVarStore
869 EFI_IFR_OP_HEADER
*IfrOpHdr
;
870 CHAR16
*VarStoreName
;
875 UINT8
*HiiFormPackage
;
877 EFI_IFR_VARSTORE_EFI
*IfrEfiVarStore
;
879 HiiFormPackage
= NULL
;
881 Status
= EFI_SUCCESS
;
886 Status
= GetFormPackageData(DataBaseRecord
, &HiiFormPackage
, &PackageSize
);
887 if (EFI_ERROR (Status
)) {
891 IfrOffset
= sizeof (EFI_HII_PACKAGE_HEADER
);
892 while (IfrOffset
< PackageSize
) {
893 IfrOpHdr
= (EFI_IFR_OP_HEADER
*) (HiiFormPackage
+ IfrOffset
);
894 IfrOffset
+= IfrOpHdr
->Length
;
896 if (IfrOpHdr
->OpCode
== EFI_IFR_VARSTORE_EFI_OP
) {
897 IfrEfiVarStore
= (EFI_IFR_VARSTORE_EFI
*) IfrOpHdr
;
899 // If the length is small than the structure, this is from old efi
900 // varstore definition. Old efi varstore get config directly from
901 // GetVariable function.
903 if (IfrOpHdr
->Length
< sizeof (EFI_IFR_VARSTORE_EFI
)) {
907 VarStoreName
= AllocateZeroPool (AsciiStrSize ((CHAR8
*)IfrEfiVarStore
->Name
) * sizeof (CHAR16
));
908 if (VarStoreName
== NULL
) {
909 Status
= EFI_OUT_OF_RESOURCES
;
912 AsciiStrToUnicodeStr ((CHAR8
*) IfrEfiVarStore
->Name
, VarStoreName
);
914 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*) &IfrEfiVarStore
->Guid
, 1, &GuidStr
);
915 GenerateSubStr (L
"NAME=", StrLen (VarStoreName
) * sizeof (CHAR16
), (VOID
*) VarStoreName
, 2, &NameStr
);
916 LengthString
= StrLen (GuidStr
);
917 LengthString
= LengthString
+ StrLen (NameStr
) + 1;
918 TempStr
= AllocateZeroPool (LengthString
* sizeof (CHAR16
));
919 if (TempStr
== NULL
) {
922 FreePool (VarStoreName
);
923 Status
= EFI_OUT_OF_RESOURCES
;
926 StrCpy (TempStr
, GuidStr
);
927 StrCat (TempStr
, NameStr
);
928 if (ConfigHdr
== NULL
|| StrnCmp (ConfigHdr
, TempStr
, StrLen (TempStr
)) == 0) {
929 *EfiVarStore
= (EFI_IFR_VARSTORE_EFI
*) AllocateZeroPool (IfrOpHdr
->Length
);
930 if (*EfiVarStore
== NULL
) {
931 FreePool (VarStoreName
);
935 Status
= EFI_OUT_OF_RESOURCES
;
938 *IsEfiVarstore
= TRUE
;
939 CopyMem (*EfiVarStore
, IfrEfiVarStore
, IfrOpHdr
->Length
);
943 // Free alllocated temp string.
945 FreePool (VarStoreName
);
952 if (HiiFormPackage
!= NULL
) {
953 FreePool (HiiFormPackage
);
960 This function parses Form Package to get the block array and the default
961 value array according to the request ConfigHdr.
963 @param Package Pointer to the form package data.
964 @param PackageLength Length of the pacakge.
965 @param ConfigHdr Request string ConfigHdr. If it is NULL,
966 the first found varstore will be as ConfigHdr.
967 @param RequestBlockArray The block array is retrieved from the request string.
968 @param VarStorageData VarStorage structure contains the got block and default value.
969 @param PIfrDefaultIdArray Point to the got default id and default name array.
971 @retval EFI_SUCCESS The block array and the default value array are got.
972 @retval EFI_INVALID_PARAMETER The varstore defintion in the differnt form pacakges
974 @retval EFI_OUT_OF_RESOURCES No enough memory.
980 IN UINT32 PackageLength
,
981 IN EFI_STRING ConfigHdr
,
982 IN IFR_BLOCK_DATA
*RequestBlockArray
,
983 IN OUT IFR_VARSTORAGE_DATA
*VarStorageData
,
984 OUT IFR_DEFAULT_DATA
*DefaultIdArray
989 EFI_IFR_VARSTORE
*IfrVarStore
;
990 EFI_IFR_VARSTORE_EFI
*IfrEfiVarStore
;
991 EFI_IFR_OP_HEADER
*IfrOpHdr
;
992 EFI_IFR_ONE_OF
*IfrOneOf
;
993 EFI_IFR_REF4
*IfrRef
;
994 EFI_IFR_ONE_OF_OPTION
*IfrOneOfOption
;
995 EFI_IFR_DEFAULT
*IfrDefault
;
996 EFI_IFR_ORDERED_LIST
*IfrOrderedList
;
997 EFI_IFR_CHECKBOX
*IfrCheckBox
;
998 EFI_IFR_PASSWORD
*IfrPassword
;
999 EFI_IFR_STRING
*IfrString
;
1000 IFR_DEFAULT_DATA DefaultData
;
1001 IFR_DEFAULT_DATA
*DefaultDataPtr
;
1002 IFR_BLOCK_DATA
*BlockData
;
1003 CHAR16
*VarStoreName
;
1006 UINT16 VarDefaultId
;
1011 BOOLEAN FirstOneOfOption
;
1012 LIST_ENTRY
*LinkData
;
1013 LIST_ENTRY
*LinkDefault
;
1016 Status
= EFI_SUCCESS
;
1021 DefaultDataPtr
= NULL
;
1022 FirstOneOfOption
= FALSE
;
1023 ZeroMem (&DefaultData
, sizeof (IFR_DEFAULT_DATA
));
1026 // Go through the form package to parse OpCode one by one.
1028 IfrOffset
= sizeof (EFI_HII_PACKAGE_HEADER
);
1029 while (IfrOffset
< PackageLength
) {
1030 IfrOpHdr
= (EFI_IFR_OP_HEADER
*) (Package
+ IfrOffset
);
1032 switch (IfrOpHdr
->OpCode
) {
1033 case EFI_IFR_VARSTORE_OP
:
1035 // VarStore is found. Don't need to search any more.
1037 if (VarStorageData
->Size
!= 0) {
1042 // Get the requied varstore information
1043 // Add varstore by Guid and Name in ConfigHdr
1044 // Make sure Offset is in varstore size and varstoreid
1046 IfrVarStore
= (EFI_IFR_VARSTORE
*) IfrOpHdr
;
1047 VarStoreName
= AllocateZeroPool (AsciiStrSize ((CHAR8
*)IfrVarStore
->Name
) * sizeof (CHAR16
));
1048 if (VarStoreName
== NULL
) {
1049 Status
= EFI_OUT_OF_RESOURCES
;
1052 AsciiStrToUnicodeStr ((CHAR8
*) IfrVarStore
->Name
, VarStoreName
);
1054 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*) &IfrVarStore
->Guid
, 1, &GuidStr
);
1055 GenerateSubStr (L
"NAME=", StrLen (VarStoreName
) * sizeof (CHAR16
), (VOID
*) VarStoreName
, 2, &NameStr
);
1056 LengthString
= StrLen (GuidStr
);
1057 LengthString
= LengthString
+ StrLen (NameStr
) + 1;
1058 TempStr
= AllocateZeroPool (LengthString
* sizeof (CHAR16
));
1059 if (TempStr
== NULL
) {
1062 FreePool (VarStoreName
);
1063 Status
= EFI_OUT_OF_RESOURCES
;
1066 StrCpy (TempStr
, GuidStr
);
1067 StrCat (TempStr
, NameStr
);
1068 if (ConfigHdr
== NULL
|| StrnCmp (ConfigHdr
, TempStr
, StrLen (TempStr
)) == 0) {
1070 // Find the matched VarStore
1072 CopyGuid (&VarStorageData
->Guid
, (EFI_GUID
*) (VOID
*) &IfrVarStore
->Guid
);
1073 VarStorageData
->VarStoreId
= IfrVarStore
->VarStoreId
;
1074 VarStorageData
->Size
= IfrVarStore
->Size
;
1075 VarStorageData
->Name
= VarStoreName
;
1078 // No found, free the allocated memory
1080 FreePool (VarStoreName
);
1083 // Free alllocated temp string.
1090 case EFI_IFR_VARSTORE_EFI_OP
:
1092 // VarStore is found. Don't need to search any more.
1094 if (VarStorageData
->Size
!= 0) {
1099 // Get the requied varstore information
1100 // Add varstore by Guid and Name in ConfigHdr
1101 // Make sure Offset is in varstore size and varstoreid
1103 IfrEfiVarStore
= (EFI_IFR_VARSTORE_EFI
*) IfrOpHdr
;
1106 // If the length is small than the structure, this is from old efi
1107 // varstore definition. Old efi varstore get config directly from
1108 // GetVariable function.
1110 if (IfrOpHdr
->Length
< sizeof (EFI_IFR_VARSTORE_EFI
)) {
1114 VarStoreName
= AllocateZeroPool (AsciiStrSize ((CHAR8
*)IfrEfiVarStore
->Name
) * sizeof (CHAR16
));
1115 if (VarStoreName
== NULL
) {
1116 Status
= EFI_OUT_OF_RESOURCES
;
1119 AsciiStrToUnicodeStr ((CHAR8
*) IfrEfiVarStore
->Name
, VarStoreName
);
1121 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*) &IfrEfiVarStore
->Guid
, 1, &GuidStr
);
1122 GenerateSubStr (L
"NAME=", StrLen (VarStoreName
) * sizeof (CHAR16
), (VOID
*) VarStoreName
, 2, &NameStr
);
1123 LengthString
= StrLen (GuidStr
);
1124 LengthString
= LengthString
+ StrLen (NameStr
) + 1;
1125 TempStr
= AllocateZeroPool (LengthString
* sizeof (CHAR16
));
1126 if (TempStr
== NULL
) {
1129 FreePool (VarStoreName
);
1130 Status
= EFI_OUT_OF_RESOURCES
;
1133 StrCpy (TempStr
, GuidStr
);
1134 StrCat (TempStr
, NameStr
);
1135 if (ConfigHdr
== NULL
|| StrnCmp (ConfigHdr
, TempStr
, StrLen (TempStr
)) == 0) {
1137 // Find the matched VarStore
1139 CopyGuid (&VarStorageData
->Guid
, (EFI_GUID
*) (VOID
*) &IfrEfiVarStore
->Guid
);
1140 VarStorageData
->VarStoreId
= IfrEfiVarStore
->VarStoreId
;
1141 VarStorageData
->Size
= IfrEfiVarStore
->Size
;
1142 VarStorageData
->Name
= VarStoreName
;
1145 // No found, free the allocated memory
1147 FreePool (VarStoreName
);
1150 // Free alllocated temp string.
1157 case EFI_IFR_DEFAULTSTORE_OP
:
1159 // Add new the map between default id and default name.
1161 DefaultDataPtr
= (IFR_DEFAULT_DATA
*) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
1162 if (DefaultDataPtr
== NULL
) {
1163 Status
= EFI_OUT_OF_RESOURCES
;
1166 DefaultDataPtr
->DefaultId
= ((EFI_IFR_DEFAULTSTORE
*) IfrOpHdr
)->DefaultId
;
1167 InsertTailList (&DefaultIdArray
->Entry
, &DefaultDataPtr
->Entry
);
1168 DefaultDataPtr
= NULL
;
1171 case EFI_IFR_FORM_OP
:
1172 case EFI_IFR_FORM_MAP_OP
:
1174 // No matched varstore is found and directly return.
1176 if (VarStorageData
->Size
== 0) {
1177 Status
= EFI_SUCCESS
;
1182 case EFI_IFR_REF_OP
:
1184 // Ref question is not in IFR Form. This IFR form is not valid.
1186 if (VarStorageData
->Size
== 0) {
1187 Status
= EFI_INVALID_PARAMETER
;
1191 // Check whether this question is for the requested varstore.
1193 IfrRef
= (EFI_IFR_REF4
*) IfrOpHdr
;
1194 if (IfrRef
->Question
.VarStoreId
!= VarStorageData
->VarStoreId
) {
1199 // Get Offset/Width by Question header.
1201 VarOffset
= IfrRef
->Question
.VarStoreInfo
.VarOffset
;
1202 VarWidth
= (UINT16
) (sizeof (EFI_HII_REF
));
1204 // Check whether this question is in requested block array.
1206 if (!BlockArrayCheck (RequestBlockArray
, VarOffset
, VarWidth
)) {
1208 // This question is not in the requested string. Skip it.
1214 // Check this var question is in the var storage
1216 if ((VarOffset
+ VarWidth
) > VarStorageData
->Size
) {
1217 Status
= EFI_INVALID_PARAMETER
;
1224 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
1225 if (BlockData
== NULL
) {
1226 Status
= EFI_OUT_OF_RESOURCES
;
1229 BlockData
->Offset
= VarOffset
;
1230 BlockData
->Width
= VarWidth
;
1231 BlockData
->QuestionId
= IfrRef
->Question
.QuestionId
;
1232 BlockData
->OpCode
= IfrOpHdr
->OpCode
;
1233 BlockData
->Scope
= IfrOpHdr
->Scope
;
1234 InitializeListHead (&BlockData
->DefaultValueEntry
);
1236 // Add Block Data into VarStorageData BlockEntry
1238 InsertBlockData (&VarStorageData
->BlockEntry
, &BlockData
);
1241 case EFI_IFR_ONE_OF_OP
:
1242 case EFI_IFR_NUMERIC_OP
:
1244 // Numeric and OneOf has the same opcode structure.
1248 // Numeric and OneOf question is not in IFR Form. This IFR form is not valid.
1250 if (VarStorageData
->Size
== 0) {
1251 Status
= EFI_INVALID_PARAMETER
;
1255 // Check whether this question is for the requested varstore.
1257 IfrOneOf
= (EFI_IFR_ONE_OF
*) IfrOpHdr
;
1258 if (IfrOneOf
->Question
.VarStoreId
!= VarStorageData
->VarStoreId
) {
1263 // Get Offset/Width by Question header and OneOf Flags
1265 VarOffset
= IfrOneOf
->Question
.VarStoreInfo
.VarOffset
;
1266 VarWidth
= (UINT16
) (1 << (IfrOneOf
->Flags
& EFI_IFR_NUMERIC_SIZE
));
1268 // Check whether this question is in requested block array.
1270 if (!BlockArrayCheck (RequestBlockArray
, VarOffset
, VarWidth
)) {
1272 // This question is not in the requested string. Skip it.
1278 // Check this var question is in the var storage
1280 if ((VarOffset
+ VarWidth
) > VarStorageData
->Size
) {
1281 Status
= EFI_INVALID_PARAMETER
;
1288 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
1289 if (BlockData
== NULL
) {
1290 Status
= EFI_OUT_OF_RESOURCES
;
1293 BlockData
->Offset
= VarOffset
;
1294 BlockData
->Width
= VarWidth
;
1295 BlockData
->QuestionId
= IfrOneOf
->Question
.QuestionId
;
1296 BlockData
->OpCode
= IfrOpHdr
->OpCode
;
1297 BlockData
->Scope
= IfrOpHdr
->Scope
;
1298 InitializeListHead (&BlockData
->DefaultValueEntry
);
1300 // Add Block Data into VarStorageData BlockEntry
1302 InsertBlockData (&VarStorageData
->BlockEntry
, &BlockData
);
1304 if (IfrOpHdr
->OpCode
== EFI_IFR_ONE_OF_OP
) {
1306 // Set this flag to TRUE for the first oneof option.
1308 FirstOneOfOption
= TRUE
;
1309 } else if (IfrOpHdr
->OpCode
== EFI_IFR_NUMERIC_OP
) {
1311 // Numeric minimum value will be used as default value when no default is specified.
1313 DefaultData
.Type
= DefaultValueFromDefault
;
1314 switch (IfrOneOf
->Flags
& EFI_IFR_NUMERIC_SIZE
) {
1315 case EFI_IFR_NUMERIC_SIZE_1
:
1316 DefaultData
.Value
.u8
= IfrOneOf
->data
.u8
.MinValue
;
1319 case EFI_IFR_NUMERIC_SIZE_2
:
1320 CopyMem (&DefaultData
.Value
.u16
, &IfrOneOf
->data
.u16
.MinValue
, sizeof (UINT16
));
1323 case EFI_IFR_NUMERIC_SIZE_4
:
1324 CopyMem (&DefaultData
.Value
.u32
, &IfrOneOf
->data
.u32
.MinValue
, sizeof (UINT32
));
1327 case EFI_IFR_NUMERIC_SIZE_8
:
1328 CopyMem (&DefaultData
.Value
.u64
, &IfrOneOf
->data
.u64
.MinValue
, sizeof (UINT64
));
1332 // Set default value base on the DefaultId list get from IFR data.
1334 for (LinkData
= DefaultIdArray
->Entry
.ForwardLink
; LinkData
!= &DefaultIdArray
->Entry
; LinkData
= LinkData
->ForwardLink
) {
1335 DefaultDataPtr
= BASE_CR (LinkData
, IFR_DEFAULT_DATA
, Entry
);
1336 DefaultData
.DefaultId
= DefaultDataPtr
->DefaultId
;
1337 InsertDefaultValue (BlockData
, &DefaultData
);
1342 case EFI_IFR_ORDERED_LIST_OP
:
1344 // offset by question header
1345 // width by EFI_IFR_ORDERED_LIST MaxContainers * OneofOption Type
1346 // no default value and default id, how to define its default value?
1350 // OrderedList question is not in IFR Form. This IFR form is not valid.
1352 if (VarStorageData
->Size
== 0) {
1353 Status
= EFI_INVALID_PARAMETER
;
1357 // Check whether this question is for the requested varstore.
1359 IfrOrderedList
= (EFI_IFR_ORDERED_LIST
*) IfrOpHdr
;
1360 if (IfrOrderedList
->Question
.VarStoreId
!= VarStorageData
->VarStoreId
) {
1366 // Get Offset/Width by Question header and OneOf Flags
1368 VarOffset
= IfrOrderedList
->Question
.VarStoreInfo
.VarOffset
;
1369 VarWidth
= IfrOrderedList
->MaxContainers
;
1374 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
1375 if (BlockData
== NULL
) {
1376 Status
= EFI_OUT_OF_RESOURCES
;
1379 BlockData
->Offset
= VarOffset
;
1380 BlockData
->Width
= VarWidth
;
1381 BlockData
->QuestionId
= IfrOrderedList
->Question
.QuestionId
;
1382 BlockData
->OpCode
= IfrOpHdr
->OpCode
;
1383 BlockData
->Scope
= IfrOpHdr
->Scope
;
1384 InitializeListHead (&BlockData
->DefaultValueEntry
);
1387 case EFI_IFR_CHECKBOX_OP
:
1389 // EFI_IFR_DEFAULT_OP
1390 // offset by question header
1391 // width is 1 sizeof (BOOLEAN)
1392 // default id by CheckBox Flags if CheckBox flags (Default or Mau) is set, the default value is 1 to be set.
1393 // value by DefaultOption
1394 // default id by DeaultOption DefaultId can override CheckBox Flags and Default value.
1398 // CheckBox question is not in IFR Form. This IFR form is not valid.
1400 if (VarStorageData
->Size
== 0) {
1401 Status
= EFI_INVALID_PARAMETER
;
1405 // Check whether this question is for the requested varstore.
1407 IfrCheckBox
= (EFI_IFR_CHECKBOX
*) IfrOpHdr
;
1408 if (IfrCheckBox
->Question
.VarStoreId
!= VarStorageData
->VarStoreId
) {
1413 // Get Offset/Width by Question header and OneOf Flags
1415 VarOffset
= IfrCheckBox
->Question
.VarStoreInfo
.VarOffset
;
1416 VarWidth
= (UINT16
) sizeof (BOOLEAN
);
1419 // Check whether this question is in requested block array.
1421 if (!BlockArrayCheck (RequestBlockArray
, VarOffset
, VarWidth
)) {
1423 // This question is not in the requested string. Skip it.
1429 // Check this var question is in the var storage
1431 if ((VarOffset
+ VarWidth
) > VarStorageData
->Size
) {
1432 Status
= EFI_INVALID_PARAMETER
;
1439 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
1440 if (BlockData
== NULL
) {
1441 Status
= EFI_OUT_OF_RESOURCES
;
1444 BlockData
->Offset
= VarOffset
;
1445 BlockData
->Width
= VarWidth
;
1446 BlockData
->QuestionId
= IfrCheckBox
->Question
.QuestionId
;
1447 BlockData
->OpCode
= IfrOpHdr
->OpCode
;
1448 BlockData
->Scope
= IfrOpHdr
->Scope
;
1449 InitializeListHead (&BlockData
->DefaultValueEntry
);
1451 // Add Block Data into VarStorageData BlockEntry
1453 InsertBlockData (&VarStorageData
->BlockEntry
, &BlockData
);
1456 // Add default value for standard ID by CheckBox Flag
1458 VarDefaultId
= EFI_HII_DEFAULT_CLASS_STANDARD
;
1460 // Prepare new DefaultValue
1462 DefaultData
.DefaultId
= VarDefaultId
;
1463 if ((IfrCheckBox
->Flags
& EFI_IFR_CHECKBOX_DEFAULT
) == EFI_IFR_CHECKBOX_DEFAULT
) {
1465 // When flag is set, defautl value is TRUE.
1467 DefaultData
.Type
= DefaultValueFromFlag
;
1468 DefaultData
.Value
.b
= TRUE
;
1471 // When flag is not set, defautl value is FASLE.
1473 DefaultData
.Type
= DefaultValueFromDefault
;
1474 DefaultData
.Value
.b
= FALSE
;
1477 // Add DefaultValue into current BlockData
1479 InsertDefaultValue (BlockData
, &DefaultData
);
1482 // Add default value for Manufacture ID by CheckBox Flag
1484 VarDefaultId
= EFI_HII_DEFAULT_CLASS_MANUFACTURING
;
1486 // Prepare new DefaultValue
1488 DefaultData
.DefaultId
= VarDefaultId
;
1489 if ((IfrCheckBox
->Flags
& EFI_IFR_CHECKBOX_DEFAULT_MFG
) == EFI_IFR_CHECKBOX_DEFAULT_MFG
) {
1491 // When flag is set, defautl value is TRUE.
1493 DefaultData
.Type
= DefaultValueFromFlag
;
1494 DefaultData
.Value
.b
= TRUE
;
1497 // When flag is not set, defautl value is FASLE.
1499 DefaultData
.Type
= DefaultValueFromDefault
;
1500 DefaultData
.Value
.b
= FALSE
;
1503 // Add DefaultValue into current BlockData
1505 InsertDefaultValue (BlockData
, &DefaultData
);
1508 case EFI_IFR_STRING_OP
:
1510 // offset by question header
1511 // width MaxSize * sizeof (CHAR16)
1512 // no default value, only block array
1516 // String question is not in IFR Form. This IFR form is not valid.
1518 if (VarStorageData
->Size
== 0) {
1519 Status
= EFI_INVALID_PARAMETER
;
1523 // Check whether this question is for the requested varstore.
1525 IfrString
= (EFI_IFR_STRING
*) IfrOpHdr
;
1526 if (IfrString
->Question
.VarStoreId
!= VarStorageData
->VarStoreId
) {
1531 // Get Offset/Width by Question header and OneOf Flags
1533 VarOffset
= IfrString
->Question
.VarStoreInfo
.VarOffset
;
1534 VarWidth
= (UINT16
) (IfrString
->MaxSize
* sizeof (UINT16
));
1537 // Check whether this question is in requested block array.
1539 if (!BlockArrayCheck (RequestBlockArray
, VarOffset
, VarWidth
)) {
1541 // This question is not in the requested string. Skip it.
1547 // Check this var question is in the var storage
1549 if ((VarOffset
+ VarWidth
) > VarStorageData
->Size
) {
1550 Status
= EFI_INVALID_PARAMETER
;
1557 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
1558 if (BlockData
== NULL
) {
1559 Status
= EFI_OUT_OF_RESOURCES
;
1562 BlockData
->Offset
= VarOffset
;
1563 BlockData
->Width
= VarWidth
;
1564 BlockData
->QuestionId
= IfrString
->Question
.QuestionId
;
1565 BlockData
->OpCode
= IfrOpHdr
->OpCode
;
1566 InitializeListHead (&BlockData
->DefaultValueEntry
);
1569 // Add Block Data into VarStorageData BlockEntry
1571 InsertBlockData (&VarStorageData
->BlockEntry
, &BlockData
);
1574 // No default value for string.
1579 case EFI_IFR_PASSWORD_OP
:
1581 // offset by question header
1582 // width MaxSize * sizeof (CHAR16)
1583 // no default value, only block array
1587 // Password question is not in IFR Form. This IFR form is not valid.
1589 if (VarStorageData
->Size
== 0) {
1590 Status
= EFI_INVALID_PARAMETER
;
1594 // Check whether this question is for the requested varstore.
1596 IfrPassword
= (EFI_IFR_PASSWORD
*) IfrOpHdr
;
1597 if (IfrPassword
->Question
.VarStoreId
!= VarStorageData
->VarStoreId
) {
1602 // Get Offset/Width by Question header and OneOf Flags
1604 VarOffset
= IfrPassword
->Question
.VarStoreInfo
.VarOffset
;
1605 VarWidth
= (UINT16
) (IfrPassword
->MaxSize
* sizeof (UINT16
));
1608 // Check whether this question is in requested block array.
1610 if (!BlockArrayCheck (RequestBlockArray
, VarOffset
, VarWidth
)) {
1612 // This question is not in the requested string. Skip it.
1618 // Check this var question is in the var storage
1620 if ((VarOffset
+ VarWidth
) > VarStorageData
->Size
) {
1621 Status
= EFI_INVALID_PARAMETER
;
1628 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
1629 if (BlockData
== NULL
) {
1630 Status
= EFI_OUT_OF_RESOURCES
;
1633 BlockData
->Offset
= VarOffset
;
1634 BlockData
->Width
= VarWidth
;
1635 BlockData
->QuestionId
= IfrPassword
->Question
.QuestionId
;
1636 BlockData
->OpCode
= IfrOpHdr
->OpCode
;
1637 InitializeListHead (&BlockData
->DefaultValueEntry
);
1640 // Add Block Data into VarStorageData BlockEntry
1642 InsertBlockData (&VarStorageData
->BlockEntry
, &BlockData
);
1645 // No default value for string.
1650 case EFI_IFR_ONE_OF_OPTION_OP
:
1652 // No matched block data is ignored.
1654 if (BlockData
== NULL
|| BlockData
->Scope
== 0) {
1658 IfrOneOfOption
= (EFI_IFR_ONE_OF_OPTION
*) IfrOpHdr
;
1659 if (BlockData
->OpCode
== EFI_IFR_ORDERED_LIST_OP
) {
1661 // Get ordered list option data type.
1663 if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_8
|| IfrOneOfOption
->Type
== EFI_IFR_TYPE_BOOLEAN
) {
1665 } else if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_16
) {
1667 } else if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_32
) {
1669 } else if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_64
) {
1673 // Invalid ordered list option data type.
1675 Status
= EFI_INVALID_PARAMETER
;
1676 FreePool (BlockData
);
1681 // Calculate Ordered list QuestionId width.
1683 BlockData
->Width
= (UINT16
) (BlockData
->Width
* VarWidth
);
1685 // Check whether this question is in requested block array.
1687 if (!BlockArrayCheck (RequestBlockArray
, BlockData
->Offset
, BlockData
->Width
)) {
1689 // This question is not in the requested string. Skip it.
1691 FreePool (BlockData
);
1696 // Check this var question is in the var storage
1698 if ((BlockData
->Offset
+ BlockData
->Width
) > VarStorageData
->Size
) {
1699 Status
= EFI_INVALID_PARAMETER
;
1700 FreePool (BlockData
);
1704 // Add Block Data into VarStorageData BlockEntry
1706 InsertBlockData (&VarStorageData
->BlockEntry
, &BlockData
);
1708 // No default data for OrderedList.
1715 // 1. Set default value for OneOf option when flag field has default attribute.
1717 if (((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT
) == EFI_IFR_OPTION_DEFAULT
) ||
1718 ((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT_MFG
) == EFI_IFR_OPTION_DEFAULT_MFG
)) {
1720 // This flag is used to specify whether this option is the first. Set it to FALSE for the following options.
1721 // The first oneof option value will be used as default value when no default value is specified.
1723 FirstOneOfOption
= FALSE
;
1725 // Prepare new DefaultValue
1727 DefaultData
.Type
= DefaultValueFromFlag
;
1728 CopyMem (&DefaultData
.Value
.u64
, &IfrOneOfOption
->Value
.u64
, sizeof (UINT64
));
1729 if ((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT
) == EFI_IFR_OPTION_DEFAULT
) {
1730 DefaultData
.DefaultId
= EFI_HII_DEFAULT_CLASS_STANDARD
;
1731 InsertDefaultValue (BlockData
, &DefaultData
);
1733 if ((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT_MFG
) == EFI_IFR_OPTION_DEFAULT_MFG
) {
1734 DefaultData
.DefaultId
= EFI_HII_DEFAULT_CLASS_MANUFACTURING
;
1735 InsertDefaultValue (BlockData
, &DefaultData
);
1742 // 2. Set as the default value when this is the first option.
1743 // The first oneof option value will be used as default value when no default value is specified.
1745 if (FirstOneOfOption
) {
1746 // This flag is used to specify whether this option is the first. Set it to FALSE for the following options.
1747 FirstOneOfOption
= FALSE
;
1750 // Prepare new DefaultValue
1752 DefaultData
.Type
= DefaultValueFromDefault
;
1753 CopyMem (&DefaultData
.Value
.u64
, &IfrOneOfOption
->Value
.u64
, sizeof (UINT64
));
1754 for (LinkData
= DefaultIdArray
->Entry
.ForwardLink
; LinkData
!= &DefaultIdArray
->Entry
; LinkData
= LinkData
->ForwardLink
) {
1755 DefaultDataPtr
= BASE_CR (LinkData
, IFR_DEFAULT_DATA
, Entry
);
1756 DefaultData
.DefaultId
= DefaultDataPtr
->DefaultId
;
1757 InsertDefaultValue (BlockData
, &DefaultData
);
1762 case EFI_IFR_DEFAULT_OP
:
1764 // Update Current BlockData to the default value.
1766 if (BlockData
== NULL
|| BlockData
->Scope
== 0) {
1768 // No matched block data is ignored.
1773 if (BlockData
->OpCode
== EFI_IFR_ORDERED_LIST_OP
) {
1775 // OrderedList Opcode is no default value.
1780 // Get the DefaultId
1782 IfrDefault
= (EFI_IFR_DEFAULT
*) IfrOpHdr
;
1783 VarDefaultId
= IfrDefault
->DefaultId
;
1785 // Prepare new DefaultValue
1787 DefaultData
.Type
= DefaultValueFromOpcode
;
1788 DefaultData
.DefaultId
= VarDefaultId
;
1789 CopyMem (&DefaultData
.Value
, &IfrDefault
->Value
, sizeof (EFI_IFR_TYPE_VALUE
));
1791 // If the value field is expression, set the cleaned flag.
1792 if (IfrDefault
->Type
== EFI_IFR_TYPE_OTHER
) {
1793 DefaultData
.Cleaned
= TRUE
;
1796 // Add DefaultValue into current BlockData
1798 InsertDefaultValue (BlockData
, &DefaultData
);
1801 // After insert the default value, reset the cleaned value for next
1802 // time used. If not set here, need to set the value before everytime
1805 DefaultData
.Cleaned
= FALSE
;
1807 case EFI_IFR_END_OP
:
1809 // End Opcode is for Var question.
1811 if (BlockData
!= NULL
&& BlockData
->Scope
> 0) {
1816 if (BlockData
!= NULL
&& BlockData
->Scope
> 0) {
1817 BlockData
->Scope
= (UINT8
) (BlockData
->Scope
+ IfrOpHdr
->Scope
);
1822 IfrOffset
+= IfrOpHdr
->Length
;
1826 for (LinkData
= VarStorageData
->BlockEntry
.ForwardLink
; LinkData
!= &VarStorageData
->BlockEntry
; LinkData
= LinkData
->ForwardLink
) {
1827 BlockData
= BASE_CR (LinkData
, IFR_BLOCK_DATA
, Entry
);
1828 for (LinkDefault
= BlockData
->DefaultValueEntry
.ForwardLink
; LinkDefault
!= &BlockData
->DefaultValueEntry
; ) {
1829 DefaultDataPtr
= BASE_CR (LinkDefault
, IFR_DEFAULT_DATA
, Entry
);
1830 LinkDefault
= LinkDefault
->ForwardLink
;
1831 if (DefaultDataPtr
->Cleaned
== TRUE
) {
1832 RemoveEntryList (&DefaultDataPtr
->Entry
);
1833 FreePool (DefaultDataPtr
);
1842 This function gets the full request string and full default value string by
1843 parsing IFR data in HII form packages.
1845 When Request points to NULL string, the request string and default value string
1846 for each varstore in form package will return.
1848 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
1849 @param DevicePath Device Path which Hii Config Access Protocol is registered.
1850 @param Request Pointer to a null-terminated Unicode string in
1851 <ConfigRequest> format. When it doesn't contain
1852 any RequestElement, it will be updated to return
1853 the full RequestElement retrieved from IFR data.
1854 If it points to NULL, the request string for the first
1855 varstore in form package will be merged into a
1856 <MultiConfigRequest> format string and return.
1857 @param AltCfgResp Pointer to a null-terminated Unicode string in
1858 <ConfigAltResp> format. When the pointer is to NULL,
1859 the full default value string retrieved from IFR data
1860 will return. When the pinter is to a string, the
1861 full default value string retrieved from IFR data
1862 will be merged into the input string and return.
1863 When Request points to NULL, the default value string
1864 for each varstore in form package will be merged into
1865 a <MultiConfigAltResp> format string and return.
1866 @param PointerProgress Optional parameter, it can be be NULL.
1867 When it is not NULL, if Request is NULL, it returns NULL.
1868 On return, points to a character in the Request
1869 string. Points to the string's null terminator if
1870 request was successful. Points to the most recent
1871 & before the first failing name / value pair (or
1872 the beginning of the string if the failure is in
1873 the first name / value pair) if the request was
1875 @retval EFI_SUCCESS The Results string is set to the full request string.
1876 And AltCfgResp contains all default value string.
1877 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
1878 @retval EFI_NOT_FOUND The varstore (Guid and Name) in Request string
1879 can't be found in Form package.
1880 @retval EFI_NOT_FOUND HiiPackage can't be got on the input HiiHandle.
1881 @retval EFI_INVALID_PARAMETER Request points to NULL.
1886 GetFullStringFromHiiFormPackages (
1887 IN HII_DATABASE_RECORD
*DataBaseRecord
,
1888 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
1889 IN OUT EFI_STRING
*Request
,
1890 IN OUT EFI_STRING
*AltCfgResp
,
1891 OUT EFI_STRING
*PointerProgress OPTIONAL
1895 UINT8
*HiiFormPackage
;
1897 IFR_BLOCK_DATA
*RequestBlockArray
;
1898 IFR_BLOCK_DATA
*BlockData
;
1899 IFR_BLOCK_DATA
*NextBlockData
;
1900 IFR_DEFAULT_DATA
*DefaultValueData
;
1901 IFR_DEFAULT_DATA
*DefaultId
;
1902 IFR_DEFAULT_DATA
*DefaultIdArray
;
1903 IFR_VARSTORAGE_DATA
*VarStorageData
;
1904 EFI_STRING DefaultAltCfgResp
;
1905 EFI_STRING FullConfigRequest
;
1906 EFI_STRING ConfigHdr
;
1910 EFI_STRING StringPtr
;
1911 EFI_STRING Progress
;
1917 LIST_ENTRY
*LinkData
;
1918 LIST_ENTRY
*LinkDefault
;
1921 if (DataBaseRecord
== NULL
|| DevicePath
== NULL
|| Request
== NULL
|| AltCfgResp
== NULL
) {
1922 return EFI_INVALID_PARAMETER
;
1926 // Initialize the local variables.
1928 RequestBlockArray
= NULL
;
1929 DefaultIdArray
= NULL
;
1930 VarStorageData
= NULL
;
1931 DefaultAltCfgResp
= NULL
;
1932 FullConfigRequest
= NULL
;
1937 HiiFormPackage
= NULL
;
1940 Progress
= *Request
;
1942 Status
= GetFormPackageData (DataBaseRecord
, &HiiFormPackage
, &PackageSize
);
1943 if (EFI_ERROR (Status
)) {
1948 // 1. Get the request block array by Request String when Request string containts the block array.
1951 if (*Request
!= NULL
) {
1952 StringPtr
= *Request
;
1956 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
1957 Status
= EFI_INVALID_PARAMETER
;
1960 StringPtr
+= StrLen (L
"GUID=");
1961 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&NAME=", StrLen (L
"&NAME=")) != 0) {
1964 if (*StringPtr
== L
'\0') {
1965 Status
= EFI_INVALID_PARAMETER
;
1968 StringPtr
+= StrLen (L
"&NAME=");
1969 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&PATH=", StrLen (L
"&PATH=")) != 0) {
1972 if (*StringPtr
== L
'\0') {
1973 Status
= EFI_INVALID_PARAMETER
;
1976 StringPtr
+= StrLen (L
"&PATH=");
1977 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
1981 // Check the following string &OFFSET=
1983 if (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) != 0) {
1984 Progress
= StringPtr
;
1985 Status
= EFI_INVALID_PARAMETER
;
1987 } else if (*StringPtr
== L
'\0') {
1989 // No request block is found.
1994 if (StringPtr
!= NULL
) {
1996 // Init RequestBlockArray
1998 RequestBlockArray
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
1999 if (RequestBlockArray
== NULL
) {
2000 Status
= EFI_OUT_OF_RESOURCES
;
2003 InitializeListHead (&RequestBlockArray
->Entry
);
2006 // Get the request Block array from the request string
2011 // Parse each <RequestElement> if exists
2012 // Only <BlockName> format is supported by this help function.
2013 // <BlockName> ::= &'OFFSET='<Number>&'WIDTH='<Number>
2015 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) == 0) {
2017 // Skip the OFFSET string
2019 Progress
= StringPtr
;
2020 StringPtr
+= StrLen (L
"&OFFSET=");
2024 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
2025 if (EFI_ERROR (Status
)) {
2032 (((Length
+ 1) / 2) < sizeof (UINT16
)) ? ((Length
+ 1) / 2) : sizeof (UINT16
)
2034 FreePool (TmpBuffer
);
2036 StringPtr
+= Length
;
2037 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
2038 Status
= EFI_INVALID_PARAMETER
;
2041 StringPtr
+= StrLen (L
"&WIDTH=");
2046 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
2047 if (EFI_ERROR (Status
)) {
2054 (((Length
+ 1) / 2) < sizeof (UINT16
)) ? ((Length
+ 1) / 2) : sizeof (UINT16
)
2056 FreePool (TmpBuffer
);
2058 StringPtr
+= Length
;
2059 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
2060 Status
= EFI_INVALID_PARAMETER
;
2067 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
2068 if (BlockData
== NULL
) {
2069 Status
= EFI_OUT_OF_RESOURCES
;
2072 BlockData
->Offset
= Offset
;
2073 BlockData
->Width
= Width
;
2074 InsertBlockData (&RequestBlockArray
->Entry
, &BlockData
);
2077 // Skip &VALUE string if &VALUE does exists.
2079 if (StrnCmp (StringPtr
, L
"&VALUE=", StrLen (L
"&VALUE=")) == 0) {
2080 StringPtr
+= StrLen (L
"&VALUE=");
2085 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
2086 if (EFI_ERROR (Status
)) {
2087 Status
= EFI_INVALID_PARAMETER
;
2091 StringPtr
+= Length
;
2092 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
2093 Status
= EFI_INVALID_PARAMETER
;
2098 // If '\0', parsing is finished.
2100 if (*StringPtr
== 0) {
2106 // Merge the requested block data.
2108 Link
= RequestBlockArray
->Entry
.ForwardLink
;
2109 while ((Link
!= &RequestBlockArray
->Entry
) && (Link
->ForwardLink
!= &RequestBlockArray
->Entry
)) {
2110 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
2111 NextBlockData
= BASE_CR (Link
->ForwardLink
, IFR_BLOCK_DATA
, Entry
);
2112 if ((NextBlockData
->Offset
>= BlockData
->Offset
) && (NextBlockData
->Offset
<= (BlockData
->Offset
+ BlockData
->Width
))) {
2113 if ((NextBlockData
->Offset
+ NextBlockData
->Width
) > (BlockData
->Offset
+ BlockData
->Width
)) {
2114 BlockData
->Width
= (UINT16
) (NextBlockData
->Offset
+ NextBlockData
->Width
- BlockData
->Offset
);
2116 RemoveEntryList (Link
->ForwardLink
);
2117 FreePool (NextBlockData
);
2120 Link
= Link
->ForwardLink
;
2125 // 2. Parse FormPackage to get BlockArray and DefaultId Array for the request BlockArray.
2129 // Initialize DefaultIdArray to store the map between DeaultId and DefaultName
2131 DefaultIdArray
= (IFR_DEFAULT_DATA
*) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
2132 if (DefaultIdArray
== NULL
) {
2133 Status
= EFI_OUT_OF_RESOURCES
;
2136 InitializeListHead (&DefaultIdArray
->Entry
);
2139 // Initialize VarStorageData to store the var store Block and Default value information.
2141 VarStorageData
= (IFR_VARSTORAGE_DATA
*) AllocateZeroPool (sizeof (IFR_VARSTORAGE_DATA
));
2142 if (VarStorageData
== NULL
) {
2143 Status
= EFI_OUT_OF_RESOURCES
;
2146 InitializeListHead (&VarStorageData
->Entry
);
2147 InitializeListHead (&VarStorageData
->BlockEntry
);
2150 // Parse the opcode in form pacakge to get the default setting.
2152 Status
= ParseIfrData (HiiFormPackage
, (UINT32
) PackageSize
, *Request
, RequestBlockArray
, VarStorageData
, DefaultIdArray
);
2153 if (EFI_ERROR (Status
)) {
2158 // No requested varstore in IFR data and directly return
2160 if (VarStorageData
->Size
== 0) {
2161 Status
= EFI_SUCCESS
;
2166 // 3. Construct Request Element (Block Name) for 2.1 and 2.2 case.
2170 // Construct <ConfigHdr> : "GUID=...&NAME=...&PATH=..." by VarStorageData Guid, Name and DriverHandle
2172 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*) &VarStorageData
->Guid
, 1, &GuidStr
);
2173 GenerateSubStr (L
"NAME=", StrLen (VarStorageData
->Name
) * sizeof (CHAR16
), (VOID
*) VarStorageData
->Name
, 2, &NameStr
);
2176 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) DevicePath
),
2177 (VOID
*) DevicePath
,
2181 Length
= StrLen (GuidStr
);
2182 Length
= Length
+ StrLen (NameStr
);
2183 Length
= Length
+ StrLen (PathStr
) + 1;
2184 ConfigHdr
= AllocateZeroPool (Length
* sizeof (CHAR16
));
2185 if (ConfigHdr
== NULL
) {
2186 Status
= EFI_OUT_OF_RESOURCES
;
2189 StrCpy (ConfigHdr
, GuidStr
);
2190 StrCat (ConfigHdr
, NameStr
);
2191 StrCat (ConfigHdr
, PathStr
);
2194 // Remove the last character L'&'
2196 *(ConfigHdr
+ StrLen (ConfigHdr
) - 1) = L
'\0';
2198 if (RequestBlockArray
== NULL
) {
2200 // Append VarStorageData BlockEntry into *Request string
2201 // Now support only one varstore in a form package.
2205 // Go through all VarStorageData Entry and get BlockEntry for each one for the multiple varstore in a single form package
2206 // Then construct them all to return MultiRequest string : ConfigHdr BlockConfig
2210 // Compute the length of the entire request starting with <ConfigHdr> and a
2214 Length
= StrLen (ConfigHdr
) + 1;
2216 for (Link
= VarStorageData
->BlockEntry
.ForwardLink
; Link
!= &VarStorageData
->BlockEntry
; Link
= Link
->ForwardLink
) {
2218 // Add <BlockName> length for each Offset/Width pair
2220 // <BlockName> ::= &OFFSET=1234&WIDTH=1234
2221 // | 8 | 4 | 7 | 4 |
2224 Length
= Length
+ (8 + 4 + 7 + 4);
2228 // No any request block data is found. The request string can't be constructed.
2231 Status
= EFI_SUCCESS
;
2236 // Allocate buffer for the entire <ConfigRequest>
2238 FullConfigRequest
= AllocateZeroPool (Length
* sizeof (CHAR16
));
2239 if (FullConfigRequest
== NULL
) {
2240 Status
= EFI_OUT_OF_RESOURCES
;
2243 StringPtr
= FullConfigRequest
;
2246 // Start with <ConfigHdr>
2248 StrCpy (StringPtr
, ConfigHdr
);
2249 StringPtr
+= StrLen (StringPtr
);
2252 // Loop through all the Offset/Width pairs and append them to ConfigRequest
2254 for (Link
= VarStorageData
->BlockEntry
.ForwardLink
; Link
!= &VarStorageData
->BlockEntry
; Link
= Link
->ForwardLink
) {
2255 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
2257 // Append &OFFSET=XXXX&WIDTH=YYYY\0
2261 (8 + 4 + 7 + 4 + 1) * sizeof (CHAR16
),
2262 L
"&OFFSET=%04X&WIDTH=%04X",
2266 StringPtr
+= StrLen (StringPtr
);
2269 // Set to the got full request string.
2271 HiiToLower (FullConfigRequest
);
2272 if (*Request
!= NULL
) {
2273 FreePool (*Request
);
2275 *Request
= FullConfigRequest
;
2279 // 4. Construct Default Value string in AltResp according to request element.
2280 // Go through all VarStorageData Entry and get the DefaultId array for each one
2281 // Then construct them all to : ConfigHdr AltConfigHdr ConfigBody AltConfigHdr ConfigBody
2285 // Add length for <ConfigHdr> + '\0'
2287 Length
= StrLen (ConfigHdr
) + 1;
2289 for (Link
= DefaultIdArray
->Entry
.ForwardLink
; Link
!= &DefaultIdArray
->Entry
; Link
= Link
->ForwardLink
) {
2290 DefaultId
= BASE_CR (Link
, IFR_DEFAULT_DATA
, Entry
);
2292 // Add length for "&<ConfigHdr>&ALTCFG=XXXX"
2293 // |1| StrLen (ConfigHdr) | 8 | 4 |
2295 Length
+= (1 + StrLen (ConfigHdr
) + 8 + 4);
2297 for (LinkData
= VarStorageData
->BlockEntry
.ForwardLink
; LinkData
!= &VarStorageData
->BlockEntry
; LinkData
= LinkData
->ForwardLink
) {
2298 BlockData
= BASE_CR (LinkData
, IFR_BLOCK_DATA
, Entry
);
2299 for (LinkDefault
= BlockData
->DefaultValueEntry
.ForwardLink
; LinkDefault
!= &BlockData
->DefaultValueEntry
; LinkDefault
= LinkDefault
->ForwardLink
) {
2300 DefaultValueData
= BASE_CR (LinkDefault
, IFR_DEFAULT_DATA
, Entry
);
2301 if (DefaultValueData
->DefaultId
== DefaultId
->DefaultId
) {
2303 // Add length for "&OFFSET=XXXX&WIDTH=YYYY&VALUE=zzzzzzzzzzzz"
2304 // | 8 | 4 | 7 | 4 | 7 | Width * 2 |
2306 Length
+= (8 + 4 + 7 + 4 + 7 + BlockData
->Width
* 2);
2314 // No default value is found. The default string doesn't exist.
2317 Status
= EFI_SUCCESS
;
2322 // Allocate buffer for the entire <DefaultAltCfgResp>
2324 DefaultAltCfgResp
= AllocateZeroPool (Length
* sizeof (CHAR16
));
2325 if (DefaultAltCfgResp
== NULL
) {
2326 Status
= EFI_OUT_OF_RESOURCES
;
2329 StringPtr
= DefaultAltCfgResp
;
2332 // Start with <ConfigHdr>
2334 StrCpy (StringPtr
, ConfigHdr
);
2335 StringPtr
+= StrLen (StringPtr
);
2337 for (Link
= DefaultIdArray
->Entry
.ForwardLink
; Link
!= &DefaultIdArray
->Entry
; Link
= Link
->ForwardLink
) {
2338 DefaultId
= BASE_CR (Link
, IFR_DEFAULT_DATA
, Entry
);
2340 // Add <AltConfigHdr> of the form "&<ConfigHdr>&ALTCFG=XXXX\0"
2341 // |1| StrLen (ConfigHdr) | 8 | 4 |
2345 (1 + StrLen (ConfigHdr
) + 8 + 4 + 1) * sizeof (CHAR16
),
2348 DefaultId
->DefaultId
2350 StringPtr
+= StrLen (StringPtr
);
2352 for (LinkData
= VarStorageData
->BlockEntry
.ForwardLink
; LinkData
!= &VarStorageData
->BlockEntry
; LinkData
= LinkData
->ForwardLink
) {
2353 BlockData
= BASE_CR (LinkData
, IFR_BLOCK_DATA
, Entry
);
2354 for (LinkDefault
= BlockData
->DefaultValueEntry
.ForwardLink
; LinkDefault
!= &BlockData
->DefaultValueEntry
; LinkDefault
= LinkDefault
->ForwardLink
) {
2355 DefaultValueData
= BASE_CR (LinkDefault
, IFR_DEFAULT_DATA
, Entry
);
2356 if (DefaultValueData
->DefaultId
== DefaultId
->DefaultId
) {
2358 // Add <BlockConfig>
2359 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>
2363 (8 + 4 + 7 + 4 + 7 + 1) * sizeof (CHAR16
),
2364 L
"&OFFSET=%04X&WIDTH=%04X&VALUE=",
2368 StringPtr
+= StrLen (StringPtr
);
2371 // Convert Value to a hex string in "%x" format
2372 // NOTE: This is in the opposite byte that GUID and PATH use
2374 Width
= BlockData
->Width
;
2375 TmpBuffer
= (UINT8
*) &(DefaultValueData
->Value
);
2376 for (; Width
> 0; Width
--) {
2377 StringPtr
+= UnicodeValueToString (StringPtr
, PREFIX_ZERO
| RADIX_HEX
, TmpBuffer
[Width
- 1], 2);
2383 HiiToLower (DefaultAltCfgResp
);
2386 // 5. Merge string into the input AltCfgResp if the iput *AltCfgResp is not NULL.
2388 if (*AltCfgResp
!= NULL
&& DefaultAltCfgResp
!= NULL
) {
2389 Status
= MergeDefaultString (AltCfgResp
, DefaultAltCfgResp
);
2390 FreePool (DefaultAltCfgResp
);
2391 } else if (*AltCfgResp
== NULL
) {
2392 *AltCfgResp
= DefaultAltCfgResp
;
2396 if (RequestBlockArray
!= NULL
) {
2398 // Free Link Array RequestBlockArray
2400 while (!IsListEmpty (&RequestBlockArray
->Entry
)) {
2401 BlockData
= BASE_CR (RequestBlockArray
->Entry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
2402 RemoveEntryList (&BlockData
->Entry
);
2403 FreePool (BlockData
);
2406 FreePool (RequestBlockArray
);
2409 if (VarStorageData
!= NULL
) {
2411 // Free link array VarStorageData
2413 while (!IsListEmpty (&VarStorageData
->BlockEntry
)) {
2414 BlockData
= BASE_CR (VarStorageData
->BlockEntry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
2415 RemoveEntryList (&BlockData
->Entry
);
2417 // Free default value link array
2419 while (!IsListEmpty (&BlockData
->DefaultValueEntry
)) {
2420 DefaultValueData
= BASE_CR (BlockData
->DefaultValueEntry
.ForwardLink
, IFR_DEFAULT_DATA
, Entry
);
2421 RemoveEntryList (&DefaultValueData
->Entry
);
2422 FreePool (DefaultValueData
);
2424 FreePool (BlockData
);
2426 FreePool (VarStorageData
);
2429 if (DefaultIdArray
!= NULL
) {
2431 // Free DefaultId Array
2433 while (!IsListEmpty (&DefaultIdArray
->Entry
)) {
2434 DefaultId
= BASE_CR (DefaultIdArray
->Entry
.ForwardLink
, IFR_DEFAULT_DATA
, Entry
);
2435 RemoveEntryList (&DefaultId
->Entry
);
2436 FreePool (DefaultId
);
2438 FreePool (DefaultIdArray
);
2442 // Free the allocated string
2444 if (GuidStr
!= NULL
) {
2447 if (NameStr
!= NULL
) {
2450 if (PathStr
!= NULL
) {
2453 if (ConfigHdr
!= NULL
) {
2454 FreePool (ConfigHdr
);
2458 // Free Pacakge data
2460 if (HiiFormPackage
!= NULL
) {
2461 FreePool (HiiFormPackage
);
2464 if (PointerProgress
!= NULL
) {
2465 if (*Request
== NULL
) {
2466 *PointerProgress
= NULL
;
2467 } else if (EFI_ERROR (Status
)) {
2468 *PointerProgress
= Progress
;
2470 *PointerProgress
= *Request
+ StrLen (*Request
);
2478 This function gets the full request resp string by
2479 parsing IFR data in HII form packages.
2481 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
2483 @param EfiVarStoreInfo The efi varstore info which is save in the EFI
2484 varstore data structure.
2485 @param Request Pointer to a null-terminated Unicode string in
2486 <ConfigRequest> format.
2487 @param RequestResp Pointer to a null-terminated Unicode string in
2488 <ConfigResp> format.
2489 @param AccessProgress On return, points to a character in the Request
2490 string. Points to the string's null terminator if
2491 request was successful. Points to the most recent
2492 & before the first failing name / value pair (or
2493 the beginning of the string if the failure is in
2494 the first name / value pair) if the request was
2497 @retval EFI_SUCCESS The Results string is set to the full request string.
2498 And AltCfgResp contains all default value string.
2499 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
2500 @retval EFI_INVALID_PARAMETER Request points to NULL.
2504 GetConfigRespFromEfiVarStore (
2505 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
2506 IN EFI_IFR_VARSTORE_EFI
*EfiVarStoreInfo
,
2507 IN EFI_STRING Request
,
2508 OUT EFI_STRING
*RequestResp
,
2509 OUT EFI_STRING
*AccessProgress
2513 EFI_STRING VarStoreName
;
2517 Status
= EFI_SUCCESS
;
2520 VarStoreName
= NULL
;
2522 VarStoreName
= AllocateZeroPool (AsciiStrSize ((CHAR8
*)EfiVarStoreInfo
->Name
) * sizeof (CHAR16
));
2523 if (VarStoreName
== NULL
) {
2524 Status
= EFI_OUT_OF_RESOURCES
;
2527 AsciiStrToUnicodeStr ((CHAR8
*) EfiVarStoreInfo
->Name
, VarStoreName
);
2530 Status
= gRT
->GetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, NULL
, &BufferSize
, NULL
);
2531 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
2535 VarStore
= AllocateZeroPool (BufferSize
);
2536 ASSERT (VarStore
!= NULL
);
2537 Status
= gRT
->GetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, NULL
, &BufferSize
, VarStore
);
2538 if (EFI_ERROR (Status
)) {
2542 Status
= HiiBlockToConfig(This
, Request
, VarStore
, BufferSize
, RequestResp
, AccessProgress
);
2543 if (EFI_ERROR (Status
)) {
2548 if (VarStoreName
!= NULL
) {
2549 FreePool (VarStoreName
);
2552 if (VarStore
!= NULL
) {
2553 FreePool (VarStore
);
2561 This function route the full request resp string for efi varstore.
2563 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
2565 @param EfiVarStoreInfo The efi varstore info which is save in the EFI
2566 varstore data structure.
2567 @param RequestResp Pointer to a null-terminated Unicode string in
2568 <ConfigResp> format.
2569 @param Result Pointer to a null-terminated Unicode string in
2570 <ConfigResp> format.
2572 @retval EFI_SUCCESS The Results string is set to the full request string.
2573 And AltCfgResp contains all default value string.
2574 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
2575 @retval EFI_INVALID_PARAMETER Request points to NULL.
2579 RouteConfigRespForEfiVarStore (
2580 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
2581 IN EFI_IFR_VARSTORE_EFI
*EfiVarStoreInfo
,
2582 IN EFI_STRING RequestResp
,
2583 OUT EFI_STRING
*Result
2587 EFI_STRING VarStoreName
;
2592 Status
= EFI_SUCCESS
;
2595 VarStoreName
= NULL
;
2597 VarStoreName
= AllocateZeroPool (AsciiStrSize ((CHAR8
*)EfiVarStoreInfo
->Name
) * sizeof (CHAR16
));
2598 if (VarStoreName
== NULL
) {
2599 Status
= EFI_OUT_OF_RESOURCES
;
2602 AsciiStrToUnicodeStr ((CHAR8
*) EfiVarStoreInfo
->Name
, VarStoreName
);
2604 Status
= gRT
->GetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, NULL
, &BufferSize
, NULL
);
2605 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
2609 BlockSize
= BufferSize
;
2610 VarStore
= AllocateZeroPool (BufferSize
);
2611 ASSERT (VarStore
!= NULL
);
2612 Status
= gRT
->GetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, NULL
, &BufferSize
, VarStore
);
2613 if (EFI_ERROR (Status
)) {
2617 Status
= HiiConfigToBlock(This
, RequestResp
, VarStore
, &BlockSize
, Result
);
2618 if (EFI_ERROR (Status
)) {
2622 Status
= gRT
->SetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, EfiVarStoreInfo
->Attributes
, BufferSize
, VarStore
);
2623 if (EFI_ERROR (Status
)) {
2628 if (VarStoreName
!= NULL
) {
2629 FreePool (VarStoreName
);
2632 if (VarStore
!= NULL
) {
2633 FreePool (VarStore
);
2640 This function allows a caller to extract the current configuration
2641 for one or more named elements from one or more drivers.
2643 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
2645 @param Request A null-terminated Unicode string in
2646 <MultiConfigRequest> format.
2647 @param Progress On return, points to a character in the Request
2648 string. Points to the string's null terminator if
2649 request was successful. Points to the most recent
2650 & before the first failing name / value pair (or
2651 the beginning of the string if the failure is in
2652 the first name / value pair) if the request was
2654 @param Results Null-terminated Unicode string in
2655 <MultiConfigAltResp> format which has all values
2656 filled in for the names in the Request string.
2657 String to be allocated by the called function.
2659 @retval EFI_SUCCESS The Results string is filled with the values
2660 corresponding to all requested names.
2661 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
2662 results that must be stored awaiting possible
2664 @retval EFI_NOT_FOUND Routing data doesn't match any known driver.
2665 Progress set to the "G" in "GUID" of the routing
2666 header that doesn't match. Note: There is no
2667 requirement that all routing data be validated
2668 before any configuration extraction.
2669 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Request
2670 parameter would result in this type of error. The
2671 Progress parameter is set to NULL.
2672 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set to most recent &
2673 before the error or the beginning of the string.
2674 @retval EFI_INVALID_PARAMETER Unknown name. Progress points to the & before the
2680 HiiConfigRoutingExtractConfig (
2681 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
2682 IN CONST EFI_STRING Request
,
2683 OUT EFI_STRING
*Progress
,
2684 OUT EFI_STRING
*Results
2687 HII_DATABASE_PRIVATE_DATA
*Private
;
2688 EFI_STRING StringPtr
;
2689 EFI_STRING ConfigRequest
;
2691 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
2692 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
2695 HII_DATABASE_RECORD
*Database
;
2696 UINT8
*DevicePathPkg
;
2697 UINT8
*CurrentDevicePath
;
2698 EFI_HANDLE DriverHandle
;
2699 EFI_HII_HANDLE HiiHandle
;
2700 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
2701 EFI_STRING AccessProgress
;
2702 EFI_STRING AccessResults
;
2703 EFI_STRING DefaultResults
;
2704 BOOLEAN FirstElement
;
2705 BOOLEAN IfrDataParsedFlag
;
2706 BOOLEAN IsEfiVarStore
;
2707 EFI_IFR_VARSTORE_EFI
*EfiVarStoreInfo
;
2709 if (This
== NULL
|| Progress
== NULL
|| Results
== NULL
) {
2710 return EFI_INVALID_PARAMETER
;
2713 if (Request
== NULL
) {
2715 return EFI_INVALID_PARAMETER
;
2718 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
2719 StringPtr
= Request
;
2720 *Progress
= StringPtr
;
2721 DefaultResults
= NULL
;
2722 ConfigRequest
= NULL
;
2723 Status
= EFI_SUCCESS
;
2724 AccessResults
= NULL
;
2725 AccessProgress
= NULL
;
2727 IfrDataParsedFlag
= FALSE
;
2728 IsEfiVarStore
= FALSE
;
2729 EfiVarStoreInfo
= NULL
;
2732 // The first element of <MultiConfigRequest> should be
2733 // <GuidHdr>, which is in 'GUID='<Guid> syntax.
2735 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
2736 return EFI_INVALID_PARAMETER
;
2739 FirstElement
= TRUE
;
2742 // Allocate a fix length of memory to store Results. Reallocate memory for
2743 // Results if this fix length is insufficient.
2745 *Results
= (EFI_STRING
) AllocateZeroPool (MAX_STRING_LENGTH
);
2746 if (*Results
== NULL
) {
2747 return EFI_OUT_OF_RESOURCES
;
2750 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) == 0) {
2752 // If parsing error, set Progress to the beginning of the <MultiConfigRequest>
2753 // or most recent & before the error.
2755 if (StringPtr
== Request
) {
2756 *Progress
= StringPtr
;
2758 *Progress
= StringPtr
- 1;
2762 // Process each <ConfigRequest> of <MultiConfigRequest>
2764 Length
= CalculateConfigStringLen (StringPtr
);
2765 ConfigRequest
= AllocateCopyPool ((Length
+ 1) * sizeof (CHAR16
), StringPtr
);
2766 if (ConfigRequest
== NULL
) {
2767 Status
= EFI_OUT_OF_RESOURCES
;
2770 *(ConfigRequest
+ Length
) = 0;
2773 // Get the UEFI device path
2775 Status
= GetDevicePath (ConfigRequest
, (UINT8
**) &DevicePath
);
2776 if (EFI_ERROR (Status
)) {
2781 // Find driver which matches the routing data.
2783 DriverHandle
= NULL
;
2786 for (Link
= Private
->DatabaseList
.ForwardLink
;
2787 Link
!= &Private
->DatabaseList
;
2788 Link
= Link
->ForwardLink
2790 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
2791 if ((DevicePathPkg
= Database
->PackageList
->DevicePathPkg
) != NULL
) {
2792 CurrentDevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
2796 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) CurrentDevicePath
)
2798 DriverHandle
= Database
->DriverHandle
;
2799 HiiHandle
= Database
->Handle
;
2806 // Try to find driver handle by device path.
2808 if (DriverHandle
== NULL
) {
2809 TempDevicePath
= DevicePath
;
2810 Status
= gBS
->LocateDevicePath (
2811 &gEfiDevicePathProtocolGuid
,
2815 if (EFI_ERROR (Status
) || (DriverHandle
== NULL
)) {
2817 // Routing data does not match any known driver.
2818 // Set Progress to the 'G' in "GUID" of the routing header.
2820 *Progress
= StringPtr
;
2821 Status
= EFI_NOT_FOUND
;
2827 // Check whether ConfigRequest contains request string OFFSET/WIDTH
2829 IfrDataParsedFlag
= FALSE
;
2830 if ((HiiHandle
!= NULL
) && (StrStr (ConfigRequest
, L
"&OFFSET=") == NULL
)) {
2832 // Get the full request string from IFR when HiiPackage is registered to HiiHandle
2834 IfrDataParsedFlag
= TRUE
;
2835 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &ConfigRequest
, &DefaultResults
, &AccessProgress
);
2836 if (EFI_ERROR (Status
)) {
2838 // AccessProgress indicates the parsing progress on <ConfigRequest>.
2839 // Map it to the progress on <MultiConfigRequest> then return it.
2841 *Progress
= StrStr (StringPtr
, AccessProgress
);
2845 // Not any request block is found.
2847 if (StrStr (ConfigRequest
, L
"&OFFSET=") == NULL
) {
2848 AccessResults
= AllocateCopyPool (StrSize (ConfigRequest
), ConfigRequest
);
2849 goto NextConfigString
;
2854 // Check whether this ConfigRequest is search from Efi varstore type storage.
2856 Status
= GetVarStoreType(Database
, ConfigRequest
, &IsEfiVarStore
, &EfiVarStoreInfo
);
2857 if (EFI_ERROR (Status
)) {
2861 if (IsEfiVarStore
) {
2863 // Call the GetVariable function to extract settings.
2865 Status
= GetConfigRespFromEfiVarStore(This
, EfiVarStoreInfo
, ConfigRequest
, &AccessResults
, &AccessProgress
);
2866 FreePool (EfiVarStoreInfo
);
2869 // Call corresponding ConfigAccess protocol to extract settings
2871 Status
= gBS
->HandleProtocol (
2873 &gEfiHiiConfigAccessProtocolGuid
,
2874 (VOID
**) &ConfigAccess
2876 ASSERT_EFI_ERROR (Status
);
2878 Status
= ConfigAccess
->ExtractConfig (
2885 if (EFI_ERROR (Status
)) {
2887 // AccessProgress indicates the parsing progress on <ConfigRequest>.
2888 // Map it to the progress on <MultiConfigRequest> then return it.
2890 *Progress
= StrStr (StringPtr
, AccessProgress
);
2895 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'
2896 // which seperates the first <ConfigAltResp> and the following ones.
2898 ASSERT (*AccessProgress
== 0);
2901 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
2903 if (!IfrDataParsedFlag
&& HiiHandle
!= NULL
) {
2904 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &ConfigRequest
, &DefaultResults
, NULL
);
2905 ASSERT_EFI_ERROR (Status
);
2908 FreePool (DevicePath
);
2911 if (DefaultResults
!= NULL
) {
2912 Status
= MergeDefaultString (&AccessResults
, DefaultResults
);
2913 ASSERT_EFI_ERROR (Status
);
2914 FreePool (DefaultResults
);
2915 DefaultResults
= NULL
;
2919 if (!FirstElement
) {
2920 Status
= AppendToMultiString (Results
, L
"&");
2921 ASSERT_EFI_ERROR (Status
);
2924 Status
= AppendToMultiString (Results
, AccessResults
);
2925 ASSERT_EFI_ERROR (Status
);
2927 FirstElement
= FALSE
;
2929 FreePool (AccessResults
);
2930 AccessResults
= NULL
;
2931 FreePool (ConfigRequest
);
2932 ConfigRequest
= NULL
;
2935 // Go to next <ConfigRequest> (skip '&').
2937 StringPtr
+= Length
;
2938 if (*StringPtr
== 0) {
2939 *Progress
= StringPtr
;
2947 if (EFI_ERROR (Status
)) {
2948 FreePool (*Results
);
2952 if (ConfigRequest
!= NULL
) {
2953 FreePool (ConfigRequest
);
2956 if (AccessResults
!= NULL
) {
2957 FreePool (AccessResults
);
2960 if (DefaultResults
!= NULL
) {
2961 FreePool (DefaultResults
);
2964 if (DevicePath
!= NULL
) {
2965 FreePool (DevicePath
);
2973 This function allows the caller to request the current configuration for the
2974 entirety of the current HII database and returns the data in a
2975 null-terminated Unicode string.
2977 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
2979 @param Results Null-terminated Unicode string in
2980 <MultiConfigAltResp> format which has all values
2981 filled in for the names in the Request string.
2982 String to be allocated by the called function.
2983 De-allocation is up to the caller.
2985 @retval EFI_SUCCESS The Results string is filled with the values
2986 corresponding to all requested names.
2987 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
2988 results that must be stored awaiting possible
2990 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Results
2991 parameter would result in this type of error.
2996 HiiConfigRoutingExportConfig (
2997 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
2998 OUT EFI_STRING
*Results
3002 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
3003 EFI_STRING AccessResults
;
3004 EFI_STRING Progress
;
3005 EFI_STRING StringPtr
;
3006 EFI_STRING ConfigRequest
;
3008 EFI_HANDLE
*ConfigAccessHandles
;
3009 UINTN NumberConfigAccessHandles
;
3010 BOOLEAN FirstElement
;
3011 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
3012 EFI_HII_HANDLE HiiHandle
;
3013 EFI_STRING DefaultResults
;
3014 HII_DATABASE_PRIVATE_DATA
*Private
;
3016 HII_DATABASE_RECORD
*Database
;
3017 UINT8
*DevicePathPkg
;
3018 UINT8
*CurrentDevicePath
;
3019 BOOLEAN IfrDataParsedFlag
;
3021 if (This
== NULL
|| Results
== NULL
) {
3022 return EFI_INVALID_PARAMETER
;
3025 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
3028 // Allocate a fix length of memory to store Results. Reallocate memory for
3029 // Results if this fix length is insufficient.
3031 *Results
= (EFI_STRING
) AllocateZeroPool (MAX_STRING_LENGTH
);
3032 if (*Results
== NULL
) {
3033 return EFI_OUT_OF_RESOURCES
;
3036 NumberConfigAccessHandles
= 0;
3037 Status
= gBS
->LocateHandleBuffer (
3039 &gEfiHiiConfigAccessProtocolGuid
,
3041 &NumberConfigAccessHandles
,
3042 &ConfigAccessHandles
3044 if (EFI_ERROR (Status
)) {
3048 FirstElement
= TRUE
;
3050 for (Index
= 0; Index
< NumberConfigAccessHandles
; Index
++) {
3051 Status
= gBS
->HandleProtocol (
3052 ConfigAccessHandles
[Index
],
3053 &gEfiHiiConfigAccessProtocolGuid
,
3054 (VOID
**) &ConfigAccess
3056 if (EFI_ERROR (Status
)) {
3061 // Get DevicePath and HiiHandle for this ConfigAccess driver handle
3063 IfrDataParsedFlag
= FALSE
;
3066 DefaultResults
= NULL
;
3068 ConfigRequest
= NULL
;
3069 DevicePath
= DevicePathFromHandle (ConfigAccessHandles
[Index
]);
3070 if (DevicePath
!= NULL
) {
3071 for (Link
= Private
->DatabaseList
.ForwardLink
;
3072 Link
!= &Private
->DatabaseList
;
3073 Link
= Link
->ForwardLink
3075 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
3076 if ((DevicePathPkg
= Database
->PackageList
->DevicePathPkg
) != NULL
) {
3077 CurrentDevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
3081 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) CurrentDevicePath
)
3083 HiiHandle
= Database
->Handle
;
3090 Status
= ConfigAccess
->ExtractConfig (
3096 if (EFI_ERROR (Status
)) {
3098 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
3100 if (HiiHandle
!= NULL
&& DevicePath
!= NULL
) {
3101 IfrDataParsedFlag
= TRUE
;
3102 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &ConfigRequest
, &DefaultResults
, NULL
);
3104 // Get the full request string to get the Current setting again.
3106 if (!EFI_ERROR (Status
) && ConfigRequest
!= NULL
) {
3107 Status
= ConfigAccess
->ExtractConfig (
3113 FreePool (ConfigRequest
);
3115 Status
= EFI_NOT_FOUND
;
3120 if (!EFI_ERROR (Status
)) {
3122 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
3124 if (!IfrDataParsedFlag
&& HiiHandle
!= NULL
&& DevicePath
!= NULL
) {
3125 StringPtr
= StrStr (AccessResults
, L
"&GUID=");
3126 if (StringPtr
!= NULL
) {
3129 if (StrStr (AccessResults
, L
"&OFFSET=") != NULL
) {
3130 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &AccessResults
, &DefaultResults
, NULL
);
3131 ASSERT_EFI_ERROR (Status
);
3133 if (StringPtr
!= NULL
) {
3138 // Merge the default sting from IFR code into the got setting from driver.
3140 if (DefaultResults
!= NULL
) {
3141 Status
= MergeDefaultString (&AccessResults
, DefaultResults
);
3142 ASSERT_EFI_ERROR (Status
);
3143 FreePool (DefaultResults
);
3144 DefaultResults
= NULL
;
3148 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'
3149 // which seperates the first <ConfigAltResp> and the following ones.
3151 if (!FirstElement
) {
3152 Status
= AppendToMultiString (Results
, L
"&");
3153 ASSERT_EFI_ERROR (Status
);
3156 Status
= AppendToMultiString (Results
, AccessResults
);
3157 ASSERT_EFI_ERROR (Status
);
3159 FirstElement
= FALSE
;
3161 FreePool (AccessResults
);
3162 AccessResults
= NULL
;
3165 FreePool (ConfigAccessHandles
);
3172 This function processes the results of processing forms and routes it to the
3173 appropriate handlers or storage.
3175 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
3177 @param Configuration A null-terminated Unicode string in
3178 <MulltiConfigResp> format.
3179 @param Progress A pointer to a string filled in with the offset of
3180 the most recent & before the first failing name /
3181 value pair (or the beginning of the string if the
3182 failure is in the first name / value pair) or the
3183 terminating NULL if all was successful.
3185 @retval EFI_SUCCESS The results have been distributed or are awaiting
3187 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
3188 results that must be stored awaiting possible
3190 @retval EFI_INVALID_PARAMETER Passing in a NULL for the Configuration parameter
3191 would result in this type of error.
3192 @retval EFI_NOT_FOUND Target for the specified routing data was not
3198 HiiConfigRoutingRouteConfig (
3199 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
3200 IN CONST EFI_STRING Configuration
,
3201 OUT EFI_STRING
*Progress
3204 HII_DATABASE_PRIVATE_DATA
*Private
;
3205 EFI_STRING StringPtr
;
3206 EFI_STRING ConfigResp
;
3209 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
3210 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
3212 HII_DATABASE_RECORD
*Database
;
3213 UINT8
*DevicePathPkg
;
3214 UINT8
*CurrentDevicePath
;
3215 EFI_HANDLE DriverHandle
;
3216 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
3217 EFI_STRING AccessProgress
;
3218 EFI_IFR_VARSTORE_EFI
*EfiVarStoreInfo
;
3219 BOOLEAN IsEfiVarstore
;
3221 if (This
== NULL
|| Progress
== NULL
) {
3222 return EFI_INVALID_PARAMETER
;
3225 if (Configuration
== NULL
) {
3227 return EFI_INVALID_PARAMETER
;
3230 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
3231 StringPtr
= Configuration
;
3232 *Progress
= StringPtr
;
3234 AccessProgress
= NULL
;
3235 EfiVarStoreInfo
= NULL
;
3236 IsEfiVarstore
= FALSE
;
3239 // The first element of <MultiConfigResp> should be
3240 // <GuidHdr>, which is in 'GUID='<Guid> syntax.
3242 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
3243 return EFI_INVALID_PARAMETER
;
3246 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) == 0) {
3248 // If parsing error, set Progress to the beginning of the <MultiConfigResp>
3249 // or most recent & before the error.
3251 if (StringPtr
== Configuration
) {
3252 *Progress
= StringPtr
;
3254 *Progress
= StringPtr
- 1;
3258 // Process each <ConfigResp> of <MultiConfigResp>
3260 Length
= CalculateConfigStringLen (StringPtr
);
3261 ConfigResp
= AllocateCopyPool ((Length
+ 1) * sizeof (CHAR16
), StringPtr
);
3262 if (ConfigResp
== NULL
) {
3263 return EFI_OUT_OF_RESOURCES
;
3266 // Append '\0' to the end of ConfigRequest
3268 *(ConfigResp
+ Length
) = 0;
3271 // Get the UEFI device path
3273 Status
= GetDevicePath (ConfigResp
, (UINT8
**) &DevicePath
);
3274 if (EFI_ERROR (Status
)) {
3275 FreePool (ConfigResp
);
3280 // Find driver which matches the routing data.
3282 DriverHandle
= NULL
;
3283 for (Link
= Private
->DatabaseList
.ForwardLink
;
3284 Link
!= &Private
->DatabaseList
;
3285 Link
= Link
->ForwardLink
3287 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
3289 if ((DevicePathPkg
= Database
->PackageList
->DevicePathPkg
) != NULL
) {
3290 CurrentDevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
3294 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) CurrentDevicePath
)
3296 DriverHandle
= Database
->DriverHandle
;
3303 // Try to find driver handle by device path.
3305 if (DriverHandle
== NULL
) {
3306 TempDevicePath
= DevicePath
;
3307 Status
= gBS
->LocateDevicePath (
3308 &gEfiDevicePathProtocolGuid
,
3312 if (EFI_ERROR (Status
) || (DriverHandle
== NULL
)) {
3314 // Routing data does not match any known driver.
3315 // Set Progress to the 'G' in "GUID" of the routing header.
3317 FreePool (DevicePath
);
3318 *Progress
= StringPtr
;
3319 FreePool (ConfigResp
);
3320 return EFI_NOT_FOUND
;
3324 FreePool (DevicePath
);
3327 // Check whether this ConfigRequest is search from Efi varstore type storage.
3329 Status
= GetVarStoreType(Database
, ConfigResp
, &IsEfiVarstore
, &EfiVarStoreInfo
);
3330 if (EFI_ERROR (Status
)) {
3334 if (IsEfiVarstore
) {
3336 // Call the SetVariable function to route settings.
3338 Status
= RouteConfigRespForEfiVarStore(This
, EfiVarStoreInfo
, ConfigResp
, &AccessProgress
);
3339 FreePool (EfiVarStoreInfo
);
3342 // Call corresponding ConfigAccess protocol to route settings
3344 Status
= gBS
->HandleProtocol (
3346 &gEfiHiiConfigAccessProtocolGuid
,
3347 (VOID
**) &ConfigAccess
3349 ASSERT_EFI_ERROR (Status
);
3351 Status
= ConfigAccess
->RouteConfig (
3357 if (EFI_ERROR (Status
)) {
3359 // AccessProgress indicates the parsing progress on <ConfigResp>.
3360 // Map it to the progress on <MultiConfigResp> then return it.
3362 *Progress
= StrStr (StringPtr
, AccessProgress
);
3364 FreePool (ConfigResp
);
3368 FreePool (ConfigResp
);
3372 // Go to next <ConfigResp> (skip '&').
3374 StringPtr
+= Length
;
3375 if (*StringPtr
== 0) {
3376 *Progress
= StringPtr
;
3389 This helper function is to be called by drivers to map configuration data
3390 stored in byte array ("block") formats such as UEFI Variables into current
3391 configuration strings.
3393 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
3395 @param ConfigRequest A null-terminated Unicode string in
3396 <ConfigRequest> format.
3397 @param Block Array of bytes defining the block's configuration.
3398 @param BlockSize Length in bytes of Block.
3399 @param Config Filled-in configuration string. String allocated
3400 by the function. Returned only if call is
3401 successful. It is <ConfigResp> string format.
3402 @param Progress A pointer to a string filled in with the offset of
3403 the most recent & before the first failing
3404 name/value pair (or the beginning of the string if
3405 the failure is in the first name / value pair) or
3406 the terminating NULL if all was successful.
3408 @retval EFI_SUCCESS The request succeeded. Progress points to the null
3409 terminator at the end of the ConfigRequest
3411 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress
3412 points to the first character of ConfigRequest.
3413 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigRequest or
3414 Block parameter would result in this type of
3415 error. Progress points to the first character of
3417 @retval EFI_DEVICE_ERROR Block not large enough. Progress undefined.
3418 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted string.
3419 Block is left updated and Progress points at
3420 the "&" preceding the first non-<BlockName>.
3426 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
3427 IN CONST EFI_STRING ConfigRequest
,
3428 IN CONST UINT8
*Block
,
3429 IN CONST UINTN BlockSize
,
3430 OUT EFI_STRING
*Config
,
3431 OUT EFI_STRING
*Progress
3434 HII_DATABASE_PRIVATE_DATA
*Private
;
3435 EFI_STRING StringPtr
;
3443 EFI_STRING ValueStr
;
3444 EFI_STRING ConfigElement
;
3450 if (This
== NULL
|| Progress
== NULL
|| Config
== NULL
) {
3451 return EFI_INVALID_PARAMETER
;
3454 if (Block
== NULL
|| ConfigRequest
== NULL
) {
3455 *Progress
= ConfigRequest
;
3456 return EFI_INVALID_PARAMETER
;
3460 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
3461 ASSERT (Private
!= NULL
);
3463 StringPtr
= ConfigRequest
;
3466 ConfigElement
= NULL
;
3469 // Allocate a fix length of memory to store Results. Reallocate memory for
3470 // Results if this fix length is insufficient.
3472 *Config
= (EFI_STRING
) AllocateZeroPool (MAX_STRING_LENGTH
);
3473 if (*Config
== NULL
) {
3474 return EFI_OUT_OF_RESOURCES
;
3480 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
3481 *Progress
= StringPtr
;
3482 Status
= EFI_INVALID_PARAMETER
;
3485 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"PATH=", StrLen (L
"PATH=")) != 0) {
3488 if (*StringPtr
== 0) {
3489 *Progress
= StringPtr
- 1;
3490 Status
= EFI_INVALID_PARAMETER
;
3494 while (*StringPtr
!= L
'&' && *StringPtr
!= 0) {
3497 if (*StringPtr
== 0) {
3498 *Progress
= StringPtr
;
3499 Status
= EFI_SUCCESS
;
3501 AppendToMultiString(Config
, ConfigRequest
);
3502 HiiToLower (*Config
);
3512 // Copy <ConfigHdr> and an additional '&' to <ConfigResp>
3514 TemChar
= *StringPtr
;
3516 AppendToMultiString(Config
, ConfigRequest
);
3517 *StringPtr
= TemChar
;
3520 // Parse each <RequestElement> if exists
3521 // Only <BlockName> format is supported by this help function.
3522 // <BlockName> ::= 'OFFSET='<Number>&'WIDTH='<Number>
3524 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"OFFSET=", StrLen (L
"OFFSET=")) == 0) {
3526 // Back up the header of one <BlockName>
3530 StringPtr
+= StrLen (L
"OFFSET=");
3534 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
3535 if (EFI_ERROR (Status
)) {
3536 *Progress
= ConfigRequest
;
3543 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
3545 FreePool (TmpBuffer
);
3547 StringPtr
+= Length
;
3548 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
3549 *Progress
= StringPtr
- Length
- StrLen (L
"OFFSET=") - 1;
3550 Status
= EFI_INVALID_PARAMETER
;
3553 StringPtr
+= StrLen (L
"&WIDTH=");
3558 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
3559 if (EFI_ERROR (Status
)) {
3560 *Progress
= ConfigRequest
;
3567 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
3569 FreePool (TmpBuffer
);
3571 StringPtr
+= Length
;
3572 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
3573 *Progress
= StringPtr
- Length
- StrLen (L
"&WIDTH=");
3574 Status
= EFI_INVALID_PARAMETER
;
3579 // Calculate Value and convert it to hex string.
3581 if (Offset
+ Width
> BlockSize
) {
3582 *Progress
= StringPtr
;
3583 Status
= EFI_DEVICE_ERROR
;
3587 Value
= (UINT8
*) AllocateZeroPool (Width
);
3588 if (Value
== NULL
) {
3589 *Progress
= ConfigRequest
;
3590 Status
= EFI_OUT_OF_RESOURCES
;
3594 CopyMem (Value
, (UINT8
*) Block
+ Offset
, Width
);
3596 Length
= Width
* 2 + 1;
3597 ValueStr
= (EFI_STRING
) AllocateZeroPool (Length
* sizeof (CHAR16
));
3598 if (ValueStr
== NULL
) {
3599 *Progress
= ConfigRequest
;
3600 Status
= EFI_OUT_OF_RESOURCES
;
3604 TemString
= ValueStr
;
3605 TemBuffer
= Value
+ Width
- 1;
3606 for (Index
= 0; Index
< Width
; Index
++, TemBuffer
--) {
3607 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
3614 // Build a ConfigElement
3616 Length
+= StringPtr
- TmpPtr
+ 1 + StrLen (L
"VALUE=");
3617 ConfigElement
= (EFI_STRING
) AllocateZeroPool (Length
* sizeof (CHAR16
));
3618 if (ConfigElement
== NULL
) {
3619 Status
= EFI_OUT_OF_RESOURCES
;
3622 CopyMem (ConfigElement
, TmpPtr
, (StringPtr
- TmpPtr
+ 1) * sizeof (CHAR16
));
3623 if (*StringPtr
== 0) {
3624 *(ConfigElement
+ (StringPtr
- TmpPtr
)) = L
'&';
3626 *(ConfigElement
+ (StringPtr
- TmpPtr
) + 1) = 0;
3627 StrCat (ConfigElement
, L
"VALUE=");
3628 StrCat (ConfigElement
, ValueStr
);
3630 AppendToMultiString (Config
, ConfigElement
);
3632 FreePool (ConfigElement
);
3633 FreePool (ValueStr
);
3634 ConfigElement
= NULL
;
3638 // If '\0', parsing is finished. Otherwise skip '&' to continue
3640 if (*StringPtr
== 0) {
3643 AppendToMultiString (Config
, L
"&");
3648 if (*StringPtr
!= 0) {
3649 *Progress
= StringPtr
- 1;
3650 Status
= EFI_INVALID_PARAMETER
;
3654 HiiToLower (*Config
);
3655 *Progress
= StringPtr
;
3659 if (*Config
!= NULL
) {
3663 if (ValueStr
!= NULL
) {
3664 FreePool (ValueStr
);
3666 if (Value
!= NULL
) {
3669 if (ConfigElement
!= NULL
) {
3670 FreePool (ConfigElement
);
3679 This helper function is to be called by drivers to map configuration strings
3680 to configurations stored in byte array ("block") formats such as UEFI Variables.
3682 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
3684 @param ConfigResp A null-terminated Unicode string in <ConfigResp>
3686 @param Block A possibly null array of bytes representing the
3687 current block. Only bytes referenced in the
3688 ConfigResp string in the block are modified. If
3689 this parameter is null or if the *BlockSize
3690 parameter is (on input) shorter than required by
3691 the Configuration string, only the BlockSize
3692 parameter is updated and an appropriate status
3693 (see below) is returned.
3694 @param BlockSize The length of the Block in units of UINT8. On
3695 input, this is the size of the Block. On output,
3696 if successful, contains the index of the last
3697 modified byte in the Block.
3698 @param Progress On return, points to an element of the ConfigResp
3699 string filled in with the offset of the most
3700 recent '&' before the first failing name / value
3701 pair (or the beginning of the string if the
3702 failure is in the first name / value pair) or the
3703 terminating NULL if all was successful.
3705 @retval EFI_SUCCESS The request succeeded. Progress points to the null
3706 terminator at the end of the ConfigResp string.
3707 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress
3708 points to the first character of ConfigResp.
3709 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigResp or
3710 Block parameter would result in this type of
3711 error. Progress points to the first character of
3713 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted name /
3714 value pair. Block is left updated and
3715 Progress points at the '&' preceding the first
3717 @retval EFI_DEVICE_ERROR Block not large enough. Progress undefined.
3718 @retval EFI_NOT_FOUND Target for the specified routing data was not found.
3719 Progress points to the "G" in "GUID" of the errant
3726 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
3727 IN CONST EFI_STRING ConfigResp
,
3728 IN OUT UINT8
*Block
,
3729 IN OUT UINTN
*BlockSize
,
3730 OUT EFI_STRING
*Progress
3733 HII_DATABASE_PRIVATE_DATA
*Private
;
3734 EFI_STRING StringPtr
;
3744 if (This
== NULL
|| BlockSize
== NULL
|| Progress
== NULL
) {
3745 return EFI_INVALID_PARAMETER
;
3748 *Progress
= ConfigResp
;
3749 if (ConfigResp
== NULL
) {
3750 return EFI_INVALID_PARAMETER
;
3753 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
3754 ASSERT (Private
!= NULL
);
3756 StringPtr
= ConfigResp
;
3757 BufferSize
= *BlockSize
;
3764 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
3765 *Progress
= StringPtr
;
3766 Status
= EFI_INVALID_PARAMETER
;
3769 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"PATH=", StrLen (L
"PATH=")) != 0) {
3772 if (*StringPtr
== 0) {
3773 *Progress
= StringPtr
;
3774 Status
= EFI_INVALID_PARAMETER
;
3778 while (*StringPtr
!= L
'&' && *StringPtr
!= 0) {
3781 if (*StringPtr
== 0) {
3782 *Progress
= StringPtr
;
3783 Status
= EFI_INVALID_PARAMETER
;
3792 // Parse each <ConfigElement> if exists
3793 // Only <BlockConfig> format is supported by this help function.
3794 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE='<Number>
3796 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"OFFSET=", StrLen (L
"OFFSET=")) == 0) {
3797 StringPtr
+= StrLen (L
"OFFSET=");
3801 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
3802 if (EFI_ERROR (Status
)) {
3803 *Progress
= ConfigResp
;
3810 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
3812 FreePool (TmpBuffer
);
3814 StringPtr
+= Length
;
3815 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
3816 *Progress
= StringPtr
- Length
- StrLen (L
"OFFSET=") - 1;
3817 Status
= EFI_INVALID_PARAMETER
;
3820 StringPtr
+= StrLen (L
"&WIDTH=");
3825 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
3826 if (EFI_ERROR (Status
)) {
3827 *Progress
= ConfigResp
;
3834 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
3836 FreePool (TmpBuffer
);
3838 StringPtr
+= Length
;
3839 if (StrnCmp (StringPtr
, L
"&VALUE=", StrLen (L
"&VALUE=")) != 0) {
3840 *Progress
= StringPtr
- Length
- StrLen (L
"&WIDTH=");
3841 Status
= EFI_INVALID_PARAMETER
;
3844 StringPtr
+= StrLen (L
"&VALUE=");
3849 Status
= GetValueOfNumber (StringPtr
, &Value
, &Length
);
3850 if (EFI_ERROR (Status
)) {
3851 *Progress
= ConfigResp
;
3855 StringPtr
+= Length
;
3856 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
3857 *Progress
= StringPtr
- Length
- 7;
3858 Status
= EFI_INVALID_PARAMETER
;
3863 // Update the Block with configuration info
3865 if ((Block
!= NULL
) && (Offset
+ Width
<= BufferSize
)) {
3866 CopyMem (Block
+ Offset
, Value
, Width
);
3868 if (Offset
+ Width
> MaxBlockSize
) {
3869 MaxBlockSize
= Offset
+ Width
;
3876 // If '\0', parsing is finished. Otherwise skip '&' to continue
3878 if (*StringPtr
== 0) {
3886 // The input string is ConfigAltResp format.
3888 if ((*StringPtr
!= 0) && (StrnCmp (StringPtr
, L
"&GUID=", StrLen (L
"&GUID=")) != 0)) {
3889 *Progress
= StringPtr
- 1;
3890 Status
= EFI_INVALID_PARAMETER
;
3894 *Progress
= StringPtr
+ StrLen (StringPtr
);
3895 *BlockSize
= MaxBlockSize
- 1;
3897 if (MaxBlockSize
> BufferSize
) {
3898 *BlockSize
= MaxBlockSize
;
3899 if (Block
!= NULL
) {
3900 return EFI_DEVICE_ERROR
;
3904 if (Block
== NULL
) {
3905 *Progress
= ConfigResp
;
3906 return EFI_INVALID_PARAMETER
;
3913 if (Value
!= NULL
) {
3921 This helper function is to be called by drivers to extract portions of
3922 a larger configuration string.
3924 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
3926 @param Configuration A null-terminated Unicode string in
3927 <MultiConfigAltResp> format.
3928 @param Guid A pointer to the GUID value to search for in the
3929 routing portion of the ConfigResp string when
3930 retrieving the requested data. If Guid is NULL,
3931 then all GUID values will be searched for.
3932 @param Name A pointer to the NAME value to search for in the
3933 routing portion of the ConfigResp string when
3934 retrieving the requested data. If Name is NULL,
3935 then all Name values will be searched for.
3936 @param DevicePath A pointer to the PATH value to search for in the
3937 routing portion of the ConfigResp string when
3938 retrieving the requested data. If DevicePath is
3939 NULL, then all DevicePath values will be searched
3941 @param AltCfgId A pointer to the ALTCFG value to search for in the
3942 routing portion of the ConfigResp string when
3943 retrieving the requested data. If this parameter
3944 is NULL, then the current setting will be
3946 @param AltCfgResp A pointer to a buffer which will be allocated by
3947 the function which contains the retrieved string
3948 as requested. This buffer is only allocated if
3949 the call was successful. It is <ConfigResp> format.
3951 @retval EFI_SUCCESS The request succeeded. The requested data was
3952 extracted and placed in the newly allocated
3954 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate AltCfgResp.
3955 @retval EFI_INVALID_PARAMETER Any parameter is invalid.
3956 @retval EFI_NOT_FOUND Target for the specified routing data was not
3963 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
3964 IN CONST EFI_STRING Configuration
,
3965 IN CONST EFI_GUID
*Guid
,
3966 IN CONST EFI_STRING Name
,
3967 IN CONST EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
3968 IN CONST UINT16
*AltCfgId
,
3969 OUT EFI_STRING
*AltCfgResp
3973 EFI_STRING StringPtr
;
3974 EFI_STRING HdrStart
;
3981 EFI_STRING AltIdStr
;
3998 if (This
== NULL
|| Configuration
== NULL
|| AltCfgResp
== NULL
) {
3999 return EFI_INVALID_PARAMETER
;
4002 StringPtr
= Configuration
;
4003 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
4004 return EFI_INVALID_PARAMETER
;
4008 // Generate the sub string for later matching.
4010 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*) Guid
, 1, &GuidStr
);
4013 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) DevicePath
),
4014 (VOID
*) DevicePath
,
4018 if (AltCfgId
!= NULL
) {
4019 GenerateSubStr (L
"ALTCFG=", sizeof (UINT16
), (VOID
*) AltCfgId
, 3, &AltIdStr
);
4022 GenerateSubStr (L
"NAME=", StrLen (Name
) * sizeof (CHAR16
), (VOID
*) Name
, 2, &NameStr
);
4024 GenerateSubStr (L
"NAME=", 0, NULL
, 2, &NameStr
);
4027 while (*StringPtr
!= 0) {
4029 // Try to match the GUID
4032 TmpPtr
= StrStr (StringPtr
, GuidStr
);
4033 if (TmpPtr
== NULL
) {
4034 Status
= EFI_NOT_FOUND
;
4040 // Jump to <NameHdr>
4043 StringPtr
= TmpPtr
+ StrLen (GuidStr
);
4045 StringPtr
= StrStr (TmpPtr
, L
"NAME=");
4046 if (StringPtr
== NULL
) {
4047 Status
= EFI_NOT_FOUND
;
4055 // Try to match the NAME
4057 if (GuidFlag
&& !NameFlag
) {
4058 if (StrnCmp (StringPtr
, NameStr
, StrLen (NameStr
)) != 0) {
4062 // Jump to <PathHdr>
4065 StringPtr
+= StrLen (NameStr
);
4067 StringPtr
= StrStr (StringPtr
, L
"PATH=");
4068 if (StringPtr
== NULL
) {
4069 Status
= EFI_NOT_FOUND
;
4078 // Try to match the DevicePath
4080 if (GuidFlag
&& NameFlag
&& !PathFlag
) {
4081 if (StrnCmp (StringPtr
, PathStr
, StrLen (PathStr
)) != 0) {
4086 // Jump to '&' before <DescHdr> or <ConfigBody>
4088 if (DevicePath
!= NULL
) {
4089 StringPtr
+= StrLen (PathStr
);
4091 StringPtr
= StrStr (StringPtr
, L
"&");
4092 if (StringPtr
== NULL
) {
4093 Status
= EFI_NOT_FOUND
;
4104 // Try to match the AltCfgId
4106 if (GuidFlag
&& NameFlag
&& PathFlag
) {
4107 if (AltCfgId
== NULL
) {
4109 // Return Current Setting when AltCfgId is NULL.
4111 Status
= OutputConfigBody (StringPtr
, &Result
);
4115 // Search the <ConfigAltResp> to get the <AltResp> with AltCfgId.
4117 if (StrnCmp (StringPtr
, AltIdStr
, StrLen (AltIdStr
)) != 0) {
4123 // Skip AltIdStr and &
4125 StringPtr
= StringPtr
+ StrLen (AltIdStr
);
4126 Status
= OutputConfigBody (StringPtr
, &Result
);
4132 Status
= EFI_NOT_FOUND
;
4136 if (!EFI_ERROR (Status
) && (Result
!= NULL
)) {
4138 // Copy the <ConfigHdr> and <ConfigBody>
4140 Length
= HdrEnd
- HdrStart
+ StrLen (Result
) + 1;
4141 *AltCfgResp
= AllocateZeroPool (Length
* sizeof (CHAR16
));
4142 if (*AltCfgResp
== NULL
) {
4143 Status
= EFI_OUT_OF_RESOURCES
;
4145 StrnCpy (*AltCfgResp
, HdrStart
, HdrEnd
- HdrStart
);
4146 StrCat (*AltCfgResp
, Result
);
4147 Status
= EFI_SUCCESS
;
4151 if (GuidStr
!= NULL
) {
4154 if (NameStr
!= NULL
) {
4157 if (PathStr
!= NULL
) {
4160 if (AltIdStr
!= NULL
) {
4161 FreePool (AltIdStr
);
4163 if (Result
!= NULL
) {