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 DefaultValueArray
->Value
= DefaultValueData
->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_ONE_OF_OPTION
*IfrOneOfOption
;
994 EFI_IFR_DEFAULT
*IfrDefault
;
995 EFI_IFR_ORDERED_LIST
*IfrOrderedList
;
996 EFI_IFR_CHECKBOX
*IfrCheckBox
;
997 EFI_IFR_PASSWORD
*IfrPassword
;
998 EFI_IFR_STRING
*IfrString
;
999 IFR_DEFAULT_DATA DefaultData
;
1000 IFR_DEFAULT_DATA
*DefaultDataPtr
;
1001 IFR_BLOCK_DATA
*BlockData
;
1002 CHAR16
*VarStoreName
;
1005 UINT16 VarDefaultId
;
1010 BOOLEAN FirstOneOfOption
;
1011 LIST_ENTRY
*LinkData
;
1012 LIST_ENTRY
*LinkDefault
;
1015 Status
= EFI_SUCCESS
;
1020 DefaultDataPtr
= NULL
;
1021 FirstOneOfOption
= FALSE
;
1022 ZeroMem (&DefaultData
, sizeof (IFR_DEFAULT_DATA
));
1025 // Go through the form package to parse OpCode one by one.
1027 IfrOffset
= sizeof (EFI_HII_PACKAGE_HEADER
);
1028 while (IfrOffset
< PackageLength
) {
1029 IfrOpHdr
= (EFI_IFR_OP_HEADER
*) (Package
+ IfrOffset
);
1031 switch (IfrOpHdr
->OpCode
) {
1032 case EFI_IFR_VARSTORE_OP
:
1034 // VarStore is found. Don't need to search any more.
1036 if (VarStorageData
->Size
!= 0) {
1041 // Get the requied varstore information
1042 // Add varstore by Guid and Name in ConfigHdr
1043 // Make sure Offset is in varstore size and varstoreid
1045 IfrVarStore
= (EFI_IFR_VARSTORE
*) IfrOpHdr
;
1046 VarStoreName
= AllocateZeroPool (AsciiStrSize ((CHAR8
*)IfrVarStore
->Name
) * sizeof (CHAR16
));
1047 if (VarStoreName
== NULL
) {
1048 Status
= EFI_OUT_OF_RESOURCES
;
1051 AsciiStrToUnicodeStr ((CHAR8
*) IfrVarStore
->Name
, VarStoreName
);
1053 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*) &IfrVarStore
->Guid
, 1, &GuidStr
);
1054 GenerateSubStr (L
"NAME=", StrLen (VarStoreName
) * sizeof (CHAR16
), (VOID
*) VarStoreName
, 2, &NameStr
);
1055 LengthString
= StrLen (GuidStr
);
1056 LengthString
= LengthString
+ StrLen (NameStr
) + 1;
1057 TempStr
= AllocateZeroPool (LengthString
* sizeof (CHAR16
));
1058 if (TempStr
== NULL
) {
1061 FreePool (VarStoreName
);
1062 Status
= EFI_OUT_OF_RESOURCES
;
1065 StrCpy (TempStr
, GuidStr
);
1066 StrCat (TempStr
, NameStr
);
1067 if (ConfigHdr
== NULL
|| StrnCmp (ConfigHdr
, TempStr
, StrLen (TempStr
)) == 0) {
1069 // Find the matched VarStore
1071 CopyGuid (&VarStorageData
->Guid
, (EFI_GUID
*) (VOID
*) &IfrVarStore
->Guid
);
1072 VarStorageData
->VarStoreId
= IfrVarStore
->VarStoreId
;
1073 VarStorageData
->Size
= IfrVarStore
->Size
;
1074 VarStorageData
->Name
= VarStoreName
;
1077 // No found, free the allocated memory
1079 FreePool (VarStoreName
);
1082 // Free alllocated temp string.
1089 case EFI_IFR_VARSTORE_EFI_OP
:
1091 // VarStore is found. Don't need to search any more.
1093 if (VarStorageData
->Size
!= 0) {
1098 // Get the requied varstore information
1099 // Add varstore by Guid and Name in ConfigHdr
1100 // Make sure Offset is in varstore size and varstoreid
1102 IfrEfiVarStore
= (EFI_IFR_VARSTORE_EFI
*) IfrOpHdr
;
1105 // If the length is small than the structure, this is from old efi
1106 // varstore definition. Old efi varstore get config directly from
1107 // GetVariable function.
1109 if (IfrOpHdr
->Length
< sizeof (EFI_IFR_VARSTORE_EFI
)) {
1113 VarStoreName
= AllocateZeroPool (AsciiStrSize ((CHAR8
*)IfrEfiVarStore
->Name
) * sizeof (CHAR16
));
1114 if (VarStoreName
== NULL
) {
1115 Status
= EFI_OUT_OF_RESOURCES
;
1118 AsciiStrToUnicodeStr ((CHAR8
*) IfrEfiVarStore
->Name
, VarStoreName
);
1120 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*) &IfrEfiVarStore
->Guid
, 1, &GuidStr
);
1121 GenerateSubStr (L
"NAME=", StrLen (VarStoreName
) * sizeof (CHAR16
), (VOID
*) VarStoreName
, 2, &NameStr
);
1122 LengthString
= StrLen (GuidStr
);
1123 LengthString
= LengthString
+ StrLen (NameStr
) + 1;
1124 TempStr
= AllocateZeroPool (LengthString
* sizeof (CHAR16
));
1125 if (TempStr
== NULL
) {
1128 FreePool (VarStoreName
);
1129 Status
= EFI_OUT_OF_RESOURCES
;
1132 StrCpy (TempStr
, GuidStr
);
1133 StrCat (TempStr
, NameStr
);
1134 if (ConfigHdr
== NULL
|| StrnCmp (ConfigHdr
, TempStr
, StrLen (TempStr
)) == 0) {
1136 // Find the matched VarStore
1138 CopyGuid (&VarStorageData
->Guid
, (EFI_GUID
*) (VOID
*) &IfrEfiVarStore
->Guid
);
1139 VarStorageData
->VarStoreId
= IfrEfiVarStore
->VarStoreId
;
1140 VarStorageData
->Size
= IfrEfiVarStore
->Size
;
1141 VarStorageData
->Name
= VarStoreName
;
1144 // No found, free the allocated memory
1146 FreePool (VarStoreName
);
1149 // Free alllocated temp string.
1156 case EFI_IFR_DEFAULTSTORE_OP
:
1158 // Add new the map between default id and default name.
1160 DefaultDataPtr
= (IFR_DEFAULT_DATA
*) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
1161 if (DefaultDataPtr
== NULL
) {
1162 Status
= EFI_OUT_OF_RESOURCES
;
1165 DefaultDataPtr
->DefaultId
= ((EFI_IFR_DEFAULTSTORE
*) IfrOpHdr
)->DefaultId
;
1166 InsertTailList (&DefaultIdArray
->Entry
, &DefaultDataPtr
->Entry
);
1167 DefaultDataPtr
= NULL
;
1170 case EFI_IFR_FORM_OP
:
1171 case EFI_IFR_FORM_MAP_OP
:
1173 // No matched varstore is found and directly return.
1175 if (VarStorageData
->Size
== 0) {
1176 Status
= EFI_SUCCESS
;
1181 case EFI_IFR_ONE_OF_OP
:
1182 case EFI_IFR_NUMERIC_OP
:
1184 // Numeric and OneOf has the same opcode structure.
1188 // Numeric and OneOf question is not in IFR Form. This IFR form is not valid.
1190 if (VarStorageData
->Size
== 0) {
1191 Status
= EFI_INVALID_PARAMETER
;
1195 // Check whether this question is for the requested varstore.
1197 IfrOneOf
= (EFI_IFR_ONE_OF
*) IfrOpHdr
;
1198 if (IfrOneOf
->Question
.VarStoreId
!= VarStorageData
->VarStoreId
) {
1203 // Get Offset/Width by Question header and OneOf Flags
1205 VarOffset
= IfrOneOf
->Question
.VarStoreInfo
.VarOffset
;
1206 VarWidth
= (UINT16
) (1 << (IfrOneOf
->Flags
& EFI_IFR_NUMERIC_SIZE
));
1208 // Check whether this question is in requested block array.
1210 if (!BlockArrayCheck (RequestBlockArray
, VarOffset
, VarWidth
)) {
1212 // This question is not in the requested string. Skip it.
1218 // Check this var question is in the var storage
1220 if ((VarOffset
+ VarWidth
) > VarStorageData
->Size
) {
1221 Status
= EFI_INVALID_PARAMETER
;
1228 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
1229 if (BlockData
== NULL
) {
1230 Status
= EFI_OUT_OF_RESOURCES
;
1233 BlockData
->Offset
= VarOffset
;
1234 BlockData
->Width
= VarWidth
;
1235 BlockData
->QuestionId
= IfrOneOf
->Question
.QuestionId
;
1236 BlockData
->OpCode
= IfrOpHdr
->OpCode
;
1237 BlockData
->Scope
= IfrOpHdr
->Scope
;
1238 InitializeListHead (&BlockData
->DefaultValueEntry
);
1240 // Add Block Data into VarStorageData BlockEntry
1242 InsertBlockData (&VarStorageData
->BlockEntry
, &BlockData
);
1244 if (IfrOpHdr
->OpCode
== EFI_IFR_ONE_OF_OP
) {
1246 // Set this flag to TRUE for the first oneof option.
1248 FirstOneOfOption
= TRUE
;
1249 } else if (IfrOpHdr
->OpCode
== EFI_IFR_NUMERIC_OP
) {
1251 // Numeric minimum value will be used as default value when no default is specified.
1253 DefaultData
.Type
= DEFAULT_VALUE_FROM_DEFAULT
;
1254 switch (IfrOneOf
->Flags
& EFI_IFR_NUMERIC_SIZE
) {
1255 case EFI_IFR_NUMERIC_SIZE_1
:
1256 DefaultData
.Value
= (UINT64
) IfrOneOf
->data
.u8
.MinValue
;
1259 case EFI_IFR_NUMERIC_SIZE_2
:
1260 CopyMem (&DefaultData
.Value
, &IfrOneOf
->data
.u16
.MinValue
, sizeof (UINT16
));
1263 case EFI_IFR_NUMERIC_SIZE_4
:
1264 CopyMem (&DefaultData
.Value
, &IfrOneOf
->data
.u32
.MinValue
, sizeof (UINT32
));
1267 case EFI_IFR_NUMERIC_SIZE_8
:
1268 CopyMem (&DefaultData
.Value
, &IfrOneOf
->data
.u64
.MinValue
, sizeof (UINT64
));
1272 // Set default value base on the DefaultId list get from IFR data.
1274 for (LinkData
= DefaultIdArray
->Entry
.ForwardLink
; LinkData
!= &DefaultIdArray
->Entry
; LinkData
= LinkData
->ForwardLink
) {
1275 DefaultDataPtr
= BASE_CR (LinkData
, IFR_DEFAULT_DATA
, Entry
);
1276 DefaultData
.DefaultId
= DefaultDataPtr
->DefaultId
;
1277 InsertDefaultValue (BlockData
, &DefaultData
);
1282 case EFI_IFR_ORDERED_LIST_OP
:
1284 // offset by question header
1285 // width by EFI_IFR_ORDERED_LIST MaxContainers * OneofOption Type
1286 // no default value and default id, how to define its default value?
1290 // OrderedList question is not in IFR Form. This IFR form is not valid.
1292 if (VarStorageData
->Size
== 0) {
1293 Status
= EFI_INVALID_PARAMETER
;
1297 // Check whether this question is for the requested varstore.
1299 IfrOrderedList
= (EFI_IFR_ORDERED_LIST
*) IfrOpHdr
;
1300 if (IfrOrderedList
->Question
.VarStoreId
!= VarStorageData
->VarStoreId
) {
1306 // Get Offset/Width by Question header and OneOf Flags
1308 VarOffset
= IfrOrderedList
->Question
.VarStoreInfo
.VarOffset
;
1309 VarWidth
= IfrOrderedList
->MaxContainers
;
1314 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
1315 if (BlockData
== NULL
) {
1316 Status
= EFI_OUT_OF_RESOURCES
;
1319 BlockData
->Offset
= VarOffset
;
1320 BlockData
->Width
= VarWidth
;
1321 BlockData
->QuestionId
= IfrOrderedList
->Question
.QuestionId
;
1322 BlockData
->OpCode
= IfrOpHdr
->OpCode
;
1323 BlockData
->Scope
= IfrOpHdr
->Scope
;
1324 InitializeListHead (&BlockData
->DefaultValueEntry
);
1327 case EFI_IFR_CHECKBOX_OP
:
1329 // EFI_IFR_DEFAULT_OP
1330 // offset by question header
1331 // width is 1 sizeof (BOOLEAN)
1332 // default id by CheckBox Flags if CheckBox flags (Default or Mau) is set, the default value is 1 to be set.
1333 // value by DefaultOption
1334 // default id by DeaultOption DefaultId can override CheckBox Flags and Default value.
1338 // CheckBox question is not in IFR Form. This IFR form is not valid.
1340 if (VarStorageData
->Size
== 0) {
1341 Status
= EFI_INVALID_PARAMETER
;
1345 // Check whether this question is for the requested varstore.
1347 IfrCheckBox
= (EFI_IFR_CHECKBOX
*) IfrOpHdr
;
1348 if (IfrCheckBox
->Question
.VarStoreId
!= VarStorageData
->VarStoreId
) {
1353 // Get Offset/Width by Question header and OneOf Flags
1355 VarOffset
= IfrCheckBox
->Question
.VarStoreInfo
.VarOffset
;
1356 VarWidth
= (UINT16
) sizeof (BOOLEAN
);
1359 // Check whether this question is in requested block array.
1361 if (!BlockArrayCheck (RequestBlockArray
, VarOffset
, VarWidth
)) {
1363 // This question is not in the requested string. Skip it.
1369 // Check this var question is in the var storage
1371 if ((VarOffset
+ VarWidth
) > VarStorageData
->Size
) {
1372 Status
= EFI_INVALID_PARAMETER
;
1379 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
1380 if (BlockData
== NULL
) {
1381 Status
= EFI_OUT_OF_RESOURCES
;
1384 BlockData
->Offset
= VarOffset
;
1385 BlockData
->Width
= VarWidth
;
1386 BlockData
->QuestionId
= IfrCheckBox
->Question
.QuestionId
;
1387 BlockData
->OpCode
= IfrOpHdr
->OpCode
;
1388 BlockData
->Scope
= IfrOpHdr
->Scope
;
1389 InitializeListHead (&BlockData
->DefaultValueEntry
);
1391 // Add Block Data into VarStorageData BlockEntry
1393 InsertBlockData (&VarStorageData
->BlockEntry
, &BlockData
);
1396 // Add default value for standard ID by CheckBox Flag
1398 VarDefaultId
= EFI_HII_DEFAULT_CLASS_STANDARD
;
1400 // Prepare new DefaultValue
1402 DefaultData
.DefaultId
= VarDefaultId
;
1403 if ((IfrCheckBox
->Flags
& EFI_IFR_CHECKBOX_DEFAULT
) == EFI_IFR_CHECKBOX_DEFAULT
) {
1405 // When flag is set, defautl value is TRUE.
1407 DefaultData
.Type
= DEFAULT_VALUE_FROM_FLAG
;
1408 DefaultData
.Value
= 1;
1411 // When flag is not set, defautl value is FASLE.
1413 DefaultData
.Type
= DEFAULT_VALUE_FROM_DEFAULT
;
1414 DefaultData
.Value
= 0;
1417 // Add DefaultValue into current BlockData
1419 InsertDefaultValue (BlockData
, &DefaultData
);
1422 // Add default value for Manufacture ID by CheckBox Flag
1424 VarDefaultId
= EFI_HII_DEFAULT_CLASS_MANUFACTURING
;
1426 // Prepare new DefaultValue
1428 DefaultData
.DefaultId
= VarDefaultId
;
1429 if ((IfrCheckBox
->Flags
& EFI_IFR_CHECKBOX_DEFAULT_MFG
) == EFI_IFR_CHECKBOX_DEFAULT_MFG
) {
1431 // When flag is set, defautl value is TRUE.
1433 DefaultData
.Type
= DEFAULT_VALUE_FROM_FLAG
;
1434 DefaultData
.Value
= 1;
1437 // When flag is not set, defautl value is FASLE.
1439 DefaultData
.Type
= DEFAULT_VALUE_FROM_DEFAULT
;
1440 DefaultData
.Value
= 0;
1443 // Add DefaultValue into current BlockData
1445 InsertDefaultValue (BlockData
, &DefaultData
);
1448 case EFI_IFR_STRING_OP
:
1450 // offset by question header
1451 // width MaxSize * sizeof (CHAR16)
1452 // no default value, only block array
1456 // String question is not in IFR Form. This IFR form is not valid.
1458 if (VarStorageData
->Size
== 0) {
1459 Status
= EFI_INVALID_PARAMETER
;
1463 // Check whether this question is for the requested varstore.
1465 IfrString
= (EFI_IFR_STRING
*) IfrOpHdr
;
1466 if (IfrString
->Question
.VarStoreId
!= VarStorageData
->VarStoreId
) {
1471 // Get Offset/Width by Question header and OneOf Flags
1473 VarOffset
= IfrString
->Question
.VarStoreInfo
.VarOffset
;
1474 VarWidth
= (UINT16
) (IfrString
->MaxSize
* sizeof (UINT16
));
1477 // Check whether this question is in requested block array.
1479 if (!BlockArrayCheck (RequestBlockArray
, VarOffset
, VarWidth
)) {
1481 // This question is not in the requested string. Skip it.
1487 // Check this var question is in the var storage
1489 if ((VarOffset
+ VarWidth
) > VarStorageData
->Size
) {
1490 Status
= EFI_INVALID_PARAMETER
;
1497 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
1498 if (BlockData
== NULL
) {
1499 Status
= EFI_OUT_OF_RESOURCES
;
1502 BlockData
->Offset
= VarOffset
;
1503 BlockData
->Width
= VarWidth
;
1504 BlockData
->QuestionId
= IfrString
->Question
.QuestionId
;
1505 BlockData
->OpCode
= IfrOpHdr
->OpCode
;
1506 InitializeListHead (&BlockData
->DefaultValueEntry
);
1509 // Add Block Data into VarStorageData BlockEntry
1511 InsertBlockData (&VarStorageData
->BlockEntry
, &BlockData
);
1514 // No default value for string.
1519 case EFI_IFR_PASSWORD_OP
:
1521 // offset by question header
1522 // width MaxSize * sizeof (CHAR16)
1523 // no default value, only block array
1527 // Password question is not in IFR Form. This IFR form is not valid.
1529 if (VarStorageData
->Size
== 0) {
1530 Status
= EFI_INVALID_PARAMETER
;
1534 // Check whether this question is for the requested varstore.
1536 IfrPassword
= (EFI_IFR_PASSWORD
*) IfrOpHdr
;
1537 if (IfrPassword
->Question
.VarStoreId
!= VarStorageData
->VarStoreId
) {
1542 // Get Offset/Width by Question header and OneOf Flags
1544 VarOffset
= IfrPassword
->Question
.VarStoreInfo
.VarOffset
;
1545 VarWidth
= (UINT16
) (IfrPassword
->MaxSize
* sizeof (UINT16
));
1548 // Check whether this question is in requested block array.
1550 if (!BlockArrayCheck (RequestBlockArray
, VarOffset
, VarWidth
)) {
1552 // This question is not in the requested string. Skip it.
1558 // Check this var question is in the var storage
1560 if ((VarOffset
+ VarWidth
) > VarStorageData
->Size
) {
1561 Status
= EFI_INVALID_PARAMETER
;
1568 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
1569 if (BlockData
== NULL
) {
1570 Status
= EFI_OUT_OF_RESOURCES
;
1573 BlockData
->Offset
= VarOffset
;
1574 BlockData
->Width
= VarWidth
;
1575 BlockData
->QuestionId
= IfrPassword
->Question
.QuestionId
;
1576 BlockData
->OpCode
= IfrOpHdr
->OpCode
;
1577 InitializeListHead (&BlockData
->DefaultValueEntry
);
1580 // Add Block Data into VarStorageData BlockEntry
1582 InsertBlockData (&VarStorageData
->BlockEntry
, &BlockData
);
1585 // No default value for string.
1590 case EFI_IFR_ONE_OF_OPTION_OP
:
1592 // No matched block data is ignored.
1594 if (BlockData
== NULL
|| BlockData
->Scope
== 0) {
1598 IfrOneOfOption
= (EFI_IFR_ONE_OF_OPTION
*) IfrOpHdr
;
1599 if (BlockData
->OpCode
== EFI_IFR_ORDERED_LIST_OP
) {
1601 // Get ordered list option data type.
1603 if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_8
|| IfrOneOfOption
->Type
== EFI_IFR_TYPE_BOOLEAN
) {
1605 } else if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_16
) {
1607 } else if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_32
) {
1609 } else if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_64
) {
1613 // Invalid ordered list option data type.
1615 Status
= EFI_INVALID_PARAMETER
;
1616 FreePool (BlockData
);
1621 // Calculate Ordered list QuestionId width.
1623 BlockData
->Width
= (UINT16
) (BlockData
->Width
* VarWidth
);
1625 // Check whether this question is in requested block array.
1627 if (!BlockArrayCheck (RequestBlockArray
, BlockData
->Offset
, BlockData
->Width
)) {
1629 // This question is not in the requested string. Skip it.
1631 FreePool (BlockData
);
1636 // Check this var question is in the var storage
1638 if ((BlockData
->Offset
+ BlockData
->Width
) > VarStorageData
->Size
) {
1639 Status
= EFI_INVALID_PARAMETER
;
1640 FreePool (BlockData
);
1644 // Add Block Data into VarStorageData BlockEntry
1646 InsertBlockData (&VarStorageData
->BlockEntry
, &BlockData
);
1648 // No default data for OrderedList.
1655 // 1. Set default value for OneOf option when flag field has default attribute.
1657 if (((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT
) == EFI_IFR_OPTION_DEFAULT
) ||
1658 ((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT_MFG
) == EFI_IFR_OPTION_DEFAULT_MFG
)) {
1660 // This flag is used to specify whether this option is the first. Set it to FALSE for the following options.
1661 // The first oneof option value will be used as default value when no default value is specified.
1663 FirstOneOfOption
= FALSE
;
1665 // Prepare new DefaultValue
1667 DefaultData
.Type
= DEFAULT_VALUE_FROM_FLAG
;
1668 DefaultData
.Value
= IfrOneOfOption
->Value
.u64
;
1669 if ((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT
) == EFI_IFR_OPTION_DEFAULT
) {
1670 DefaultData
.DefaultId
= EFI_HII_DEFAULT_CLASS_STANDARD
;
1671 InsertDefaultValue (BlockData
, &DefaultData
);
1673 if ((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT_MFG
) == EFI_IFR_OPTION_DEFAULT_MFG
) {
1674 DefaultData
.DefaultId
= EFI_HII_DEFAULT_CLASS_MANUFACTURING
;
1675 InsertDefaultValue (BlockData
, &DefaultData
);
1682 // 2. Set as the default value when this is the first option.
1683 // The first oneof option value will be used as default value when no default value is specified.
1685 if (FirstOneOfOption
) {
1686 // This flag is used to specify whether this option is the first. Set it to FALSE for the following options.
1687 FirstOneOfOption
= FALSE
;
1690 // Prepare new DefaultValue
1692 DefaultData
.Type
= DEFAULT_VALUE_FROM_DEFAULT
;
1693 DefaultData
.Value
= IfrOneOfOption
->Value
.u64
;
1694 for (LinkData
= DefaultIdArray
->Entry
.ForwardLink
; LinkData
!= &DefaultIdArray
->Entry
; LinkData
= LinkData
->ForwardLink
) {
1695 DefaultDataPtr
= BASE_CR (LinkData
, IFR_DEFAULT_DATA
, Entry
);
1696 DefaultData
.DefaultId
= DefaultDataPtr
->DefaultId
;
1697 InsertDefaultValue (BlockData
, &DefaultData
);
1702 case EFI_IFR_DEFAULT_OP
:
1704 // Update Current BlockData to the default value.
1706 if (BlockData
== NULL
|| BlockData
->Scope
== 0) {
1708 // No matched block data is ignored.
1713 if (BlockData
->OpCode
== EFI_IFR_ORDERED_LIST_OP
) {
1715 // OrderedList Opcode is no default value.
1720 // Get the DefaultId
1722 IfrDefault
= (EFI_IFR_DEFAULT
*) IfrOpHdr
;
1723 VarDefaultId
= IfrDefault
->DefaultId
;
1725 // Prepare new DefaultValue
1727 DefaultData
.Type
= DEFAULT_VALUE_FROM_OPCODE
;
1728 DefaultData
.DefaultId
= VarDefaultId
;
1729 DefaultData
.Value
= IfrDefault
->Value
.u64
;
1731 // If the value field is expression, set the cleaned flag.
1732 if (IfrDefault
->Type
== EFI_IFR_TYPE_OTHER
) {
1733 DefaultData
.Cleaned
= TRUE
;
1736 // Add DefaultValue into current BlockData
1738 InsertDefaultValue (BlockData
, &DefaultData
);
1741 // After insert the default value, reset the cleaned value for next
1742 // time used. If not set here, need to set the value before everytime
1745 DefaultData
.Cleaned
= FALSE
;
1747 case EFI_IFR_END_OP
:
1749 // End Opcode is for Var question.
1751 if (BlockData
!= NULL
&& BlockData
->Scope
> 0) {
1756 if (BlockData
!= NULL
&& BlockData
->Scope
> 0) {
1757 BlockData
->Scope
= (UINT8
) (BlockData
->Scope
+ IfrOpHdr
->Scope
);
1762 IfrOffset
+= IfrOpHdr
->Length
;
1766 for (LinkData
= VarStorageData
->BlockEntry
.ForwardLink
; LinkData
!= &VarStorageData
->BlockEntry
; LinkData
= LinkData
->ForwardLink
) {
1767 BlockData
= BASE_CR (LinkData
, IFR_BLOCK_DATA
, Entry
);
1768 for (LinkDefault
= BlockData
->DefaultValueEntry
.ForwardLink
; LinkDefault
!= &BlockData
->DefaultValueEntry
; ) {
1769 DefaultDataPtr
= BASE_CR (LinkDefault
, IFR_DEFAULT_DATA
, Entry
);
1770 LinkDefault
= LinkDefault
->ForwardLink
;
1771 if (DefaultDataPtr
->Cleaned
== TRUE
) {
1772 RemoveEntryList (&DefaultDataPtr
->Entry
);
1773 FreePool (DefaultDataPtr
);
1782 This function gets the full request string and full default value string by
1783 parsing IFR data in HII form packages.
1785 When Request points to NULL string, the request string and default value string
1786 for each varstore in form package will return.
1788 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
1789 @param DevicePath Device Path which Hii Config Access Protocol is registered.
1790 @param Request Pointer to a null-terminated Unicode string in
1791 <ConfigRequest> format. When it doesn't contain
1792 any RequestElement, it will be updated to return
1793 the full RequestElement retrieved from IFR data.
1794 If it points to NULL, the request string for the first
1795 varstore in form package will be merged into a
1796 <MultiConfigRequest> format string and return.
1797 @param AltCfgResp Pointer to a null-terminated Unicode string in
1798 <ConfigAltResp> format. When the pointer is to NULL,
1799 the full default value string retrieved from IFR data
1800 will return. When the pinter is to a string, the
1801 full default value string retrieved from IFR data
1802 will be merged into the input string and return.
1803 When Request points to NULL, the default value string
1804 for each varstore in form package will be merged into
1805 a <MultiConfigAltResp> format string and return.
1806 @param PointerProgress Optional parameter, it can be be NULL.
1807 When it is not NULL, if Request is NULL, it returns NULL.
1808 On return, points to a character in the Request
1809 string. Points to the string's null terminator if
1810 request was successful. Points to the most recent
1811 & before the first failing name / value pair (or
1812 the beginning of the string if the failure is in
1813 the first name / value pair) if the request was
1815 @retval EFI_SUCCESS The Results string is set to the full request string.
1816 And AltCfgResp contains all default value string.
1817 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
1818 @retval EFI_NOT_FOUND The varstore (Guid and Name) in Request string
1819 can't be found in Form package.
1820 @retval EFI_NOT_FOUND HiiPackage can't be got on the input HiiHandle.
1821 @retval EFI_INVALID_PARAMETER Request points to NULL.
1826 GetFullStringFromHiiFormPackages (
1827 IN HII_DATABASE_RECORD
*DataBaseRecord
,
1828 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
1829 IN OUT EFI_STRING
*Request
,
1830 IN OUT EFI_STRING
*AltCfgResp
,
1831 OUT EFI_STRING
*PointerProgress OPTIONAL
1835 UINT8
*HiiFormPackage
;
1837 IFR_BLOCK_DATA
*RequestBlockArray
;
1838 IFR_BLOCK_DATA
*BlockData
;
1839 IFR_BLOCK_DATA
*NextBlockData
;
1840 IFR_DEFAULT_DATA
*DefaultValueData
;
1841 IFR_DEFAULT_DATA
*DefaultId
;
1842 IFR_DEFAULT_DATA
*DefaultIdArray
;
1843 IFR_VARSTORAGE_DATA
*VarStorageData
;
1844 EFI_STRING DefaultAltCfgResp
;
1845 EFI_STRING FullConfigRequest
;
1846 EFI_STRING ConfigHdr
;
1850 EFI_STRING StringPtr
;
1851 EFI_STRING Progress
;
1857 LIST_ENTRY
*LinkData
;
1858 LIST_ENTRY
*LinkDefault
;
1861 if (DataBaseRecord
== NULL
|| DevicePath
== NULL
|| Request
== NULL
|| AltCfgResp
== NULL
) {
1862 return EFI_INVALID_PARAMETER
;
1866 // Initialize the local variables.
1868 RequestBlockArray
= NULL
;
1869 DefaultIdArray
= NULL
;
1870 VarStorageData
= NULL
;
1871 DefaultAltCfgResp
= NULL
;
1872 FullConfigRequest
= NULL
;
1877 HiiFormPackage
= NULL
;
1880 Progress
= *Request
;
1882 Status
= GetFormPackageData (DataBaseRecord
, &HiiFormPackage
, &PackageSize
);
1883 if (EFI_ERROR (Status
)) {
1888 // 1. Get the request block array by Request String when Request string containts the block array.
1891 if (*Request
!= NULL
) {
1892 StringPtr
= *Request
;
1896 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
1897 Status
= EFI_INVALID_PARAMETER
;
1900 StringPtr
+= StrLen (L
"GUID=");
1901 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&NAME=", StrLen (L
"&NAME=")) != 0) {
1904 if (*StringPtr
== L
'\0') {
1905 Status
= EFI_INVALID_PARAMETER
;
1908 StringPtr
+= StrLen (L
"&NAME=");
1909 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&PATH=", StrLen (L
"&PATH=")) != 0) {
1912 if (*StringPtr
== L
'\0') {
1913 Status
= EFI_INVALID_PARAMETER
;
1916 StringPtr
+= StrLen (L
"&PATH=");
1917 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
1921 // Check the following string &OFFSET=
1923 if (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) != 0) {
1924 Progress
= StringPtr
;
1925 Status
= EFI_INVALID_PARAMETER
;
1927 } else if (*StringPtr
== L
'\0') {
1929 // No request block is found.
1934 if (StringPtr
!= NULL
) {
1936 // Init RequestBlockArray
1938 RequestBlockArray
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
1939 if (RequestBlockArray
== NULL
) {
1940 Status
= EFI_OUT_OF_RESOURCES
;
1943 InitializeListHead (&RequestBlockArray
->Entry
);
1946 // Get the request Block array from the request string
1951 // Parse each <RequestElement> if exists
1952 // Only <BlockName> format is supported by this help function.
1953 // <BlockName> ::= &'OFFSET='<Number>&'WIDTH='<Number>
1955 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) == 0) {
1957 // Skip the OFFSET string
1959 Progress
= StringPtr
;
1960 StringPtr
+= StrLen (L
"&OFFSET=");
1964 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
1965 if (EFI_ERROR (Status
)) {
1972 (((Length
+ 1) / 2) < sizeof (UINT16
)) ? ((Length
+ 1) / 2) : sizeof (UINT16
)
1974 FreePool (TmpBuffer
);
1976 StringPtr
+= Length
;
1977 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
1978 Status
= EFI_INVALID_PARAMETER
;
1981 StringPtr
+= StrLen (L
"&WIDTH=");
1986 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
1987 if (EFI_ERROR (Status
)) {
1994 (((Length
+ 1) / 2) < sizeof (UINT16
)) ? ((Length
+ 1) / 2) : sizeof (UINT16
)
1996 FreePool (TmpBuffer
);
1998 StringPtr
+= Length
;
1999 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
2000 Status
= EFI_INVALID_PARAMETER
;
2007 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
2008 if (BlockData
== NULL
) {
2009 Status
= EFI_OUT_OF_RESOURCES
;
2012 BlockData
->Offset
= Offset
;
2013 BlockData
->Width
= Width
;
2014 InsertBlockData (&RequestBlockArray
->Entry
, &BlockData
);
2017 // Skip &VALUE string if &VALUE does exists.
2019 if (StrnCmp (StringPtr
, L
"&VALUE=", StrLen (L
"&VALUE=")) == 0) {
2020 StringPtr
+= StrLen (L
"&VALUE=");
2025 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
2026 if (EFI_ERROR (Status
)) {
2027 Status
= EFI_INVALID_PARAMETER
;
2031 StringPtr
+= Length
;
2032 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
2033 Status
= EFI_INVALID_PARAMETER
;
2038 // If '\0', parsing is finished.
2040 if (*StringPtr
== 0) {
2046 // Merge the requested block data.
2048 Link
= RequestBlockArray
->Entry
.ForwardLink
;
2049 while ((Link
!= &RequestBlockArray
->Entry
) && (Link
->ForwardLink
!= &RequestBlockArray
->Entry
)) {
2050 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
2051 NextBlockData
= BASE_CR (Link
->ForwardLink
, IFR_BLOCK_DATA
, Entry
);
2052 if ((NextBlockData
->Offset
>= BlockData
->Offset
) && (NextBlockData
->Offset
<= (BlockData
->Offset
+ BlockData
->Width
))) {
2053 if ((NextBlockData
->Offset
+ NextBlockData
->Width
) > (BlockData
->Offset
+ BlockData
->Width
)) {
2054 BlockData
->Width
= (UINT16
) (NextBlockData
->Offset
+ NextBlockData
->Width
- BlockData
->Offset
);
2056 RemoveEntryList (Link
->ForwardLink
);
2057 FreePool (NextBlockData
);
2060 Link
= Link
->ForwardLink
;
2065 // 2. Parse FormPackage to get BlockArray and DefaultId Array for the request BlockArray.
2069 // Initialize DefaultIdArray to store the map between DeaultId and DefaultName
2071 DefaultIdArray
= (IFR_DEFAULT_DATA
*) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
2072 if (DefaultIdArray
== NULL
) {
2073 Status
= EFI_OUT_OF_RESOURCES
;
2076 InitializeListHead (&DefaultIdArray
->Entry
);
2079 // Initialize VarStorageData to store the var store Block and Default value information.
2081 VarStorageData
= (IFR_VARSTORAGE_DATA
*) AllocateZeroPool (sizeof (IFR_VARSTORAGE_DATA
));
2082 if (VarStorageData
== NULL
) {
2083 Status
= EFI_OUT_OF_RESOURCES
;
2086 InitializeListHead (&VarStorageData
->Entry
);
2087 InitializeListHead (&VarStorageData
->BlockEntry
);
2090 // Parse the opcode in form pacakge to get the default setting.
2092 Status
= ParseIfrData (HiiFormPackage
, (UINT32
) PackageSize
, *Request
, RequestBlockArray
, VarStorageData
, DefaultIdArray
);
2093 if (EFI_ERROR (Status
)) {
2098 // No requested varstore in IFR data and directly return
2100 if (VarStorageData
->Size
== 0) {
2101 Status
= EFI_SUCCESS
;
2106 // 3. Construct Request Element (Block Name) for 2.1 and 2.2 case.
2110 // Construct <ConfigHdr> : "GUID=...&NAME=...&PATH=..." by VarStorageData Guid, Name and DriverHandle
2112 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*) &VarStorageData
->Guid
, 1, &GuidStr
);
2113 GenerateSubStr (L
"NAME=", StrLen (VarStorageData
->Name
) * sizeof (CHAR16
), (VOID
*) VarStorageData
->Name
, 2, &NameStr
);
2116 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) DevicePath
),
2117 (VOID
*) DevicePath
,
2121 Length
= StrLen (GuidStr
);
2122 Length
= Length
+ StrLen (NameStr
);
2123 Length
= Length
+ StrLen (PathStr
) + 1;
2124 ConfigHdr
= AllocateZeroPool (Length
* sizeof (CHAR16
));
2125 if (ConfigHdr
== NULL
) {
2126 Status
= EFI_OUT_OF_RESOURCES
;
2129 StrCpy (ConfigHdr
, GuidStr
);
2130 StrCat (ConfigHdr
, NameStr
);
2131 StrCat (ConfigHdr
, PathStr
);
2134 // Remove the last character L'&'
2136 *(ConfigHdr
+ StrLen (ConfigHdr
) - 1) = L
'\0';
2138 if (RequestBlockArray
== NULL
) {
2140 // Append VarStorageData BlockEntry into *Request string
2141 // Now support only one varstore in a form package.
2145 // Go through all VarStorageData Entry and get BlockEntry for each one for the multiple varstore in a single form package
2146 // Then construct them all to return MultiRequest string : ConfigHdr BlockConfig
2150 // Compute the length of the entire request starting with <ConfigHdr> and a
2154 Length
= StrLen (ConfigHdr
) + 1;
2156 for (Link
= VarStorageData
->BlockEntry
.ForwardLink
; Link
!= &VarStorageData
->BlockEntry
; Link
= Link
->ForwardLink
) {
2158 // Add <BlockName> length for each Offset/Width pair
2160 // <BlockName> ::= &OFFSET=1234&WIDTH=1234
2161 // | 8 | 4 | 7 | 4 |
2164 Length
= Length
+ (8 + 4 + 7 + 4);
2168 // No any request block data is found. The request string can't be constructed.
2171 Status
= EFI_SUCCESS
;
2176 // Allocate buffer for the entire <ConfigRequest>
2178 FullConfigRequest
= AllocateZeroPool (Length
* sizeof (CHAR16
));
2179 if (FullConfigRequest
== NULL
) {
2180 Status
= EFI_OUT_OF_RESOURCES
;
2183 StringPtr
= FullConfigRequest
;
2186 // Start with <ConfigHdr>
2188 StrCpy (StringPtr
, ConfigHdr
);
2189 StringPtr
+= StrLen (StringPtr
);
2192 // Loop through all the Offset/Width pairs and append them to ConfigRequest
2194 for (Link
= VarStorageData
->BlockEntry
.ForwardLink
; Link
!= &VarStorageData
->BlockEntry
; Link
= Link
->ForwardLink
) {
2195 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
2197 // Append &OFFSET=XXXX&WIDTH=YYYY\0
2201 (8 + 4 + 7 + 4 + 1) * sizeof (CHAR16
),
2202 L
"&OFFSET=%04X&WIDTH=%04X",
2206 StringPtr
+= StrLen (StringPtr
);
2209 // Set to the got full request string.
2211 HiiToLower (FullConfigRequest
);
2212 if (*Request
!= NULL
) {
2213 FreePool (*Request
);
2215 *Request
= FullConfigRequest
;
2219 // 4. Construct Default Value string in AltResp according to request element.
2220 // Go through all VarStorageData Entry and get the DefaultId array for each one
2221 // Then construct them all to : ConfigHdr AltConfigHdr ConfigBody AltConfigHdr ConfigBody
2225 // Add length for <ConfigHdr> + '\0'
2227 Length
= StrLen (ConfigHdr
) + 1;
2229 for (Link
= DefaultIdArray
->Entry
.ForwardLink
; Link
!= &DefaultIdArray
->Entry
; Link
= Link
->ForwardLink
) {
2230 DefaultId
= BASE_CR (Link
, IFR_DEFAULT_DATA
, Entry
);
2232 // Add length for "&<ConfigHdr>&ALTCFG=XXXX"
2233 // |1| StrLen (ConfigHdr) | 8 | 4 |
2235 Length
+= (1 + StrLen (ConfigHdr
) + 8 + 4);
2237 for (LinkData
= VarStorageData
->BlockEntry
.ForwardLink
; LinkData
!= &VarStorageData
->BlockEntry
; LinkData
= LinkData
->ForwardLink
) {
2238 BlockData
= BASE_CR (LinkData
, IFR_BLOCK_DATA
, Entry
);
2239 for (LinkDefault
= BlockData
->DefaultValueEntry
.ForwardLink
; LinkDefault
!= &BlockData
->DefaultValueEntry
; LinkDefault
= LinkDefault
->ForwardLink
) {
2240 DefaultValueData
= BASE_CR (LinkDefault
, IFR_DEFAULT_DATA
, Entry
);
2241 if (DefaultValueData
->DefaultId
== DefaultId
->DefaultId
) {
2243 // Add length for "&OFFSET=XXXX&WIDTH=YYYY&VALUE=zzzzzzzzzzzz"
2244 // | 8 | 4 | 7 | 4 | 7 | Width * 2 |
2246 Length
+= (8 + 4 + 7 + 4 + 7 + BlockData
->Width
* 2);
2254 // No default value is found. The default string doesn't exist.
2257 Status
= EFI_SUCCESS
;
2262 // Allocate buffer for the entire <DefaultAltCfgResp>
2264 DefaultAltCfgResp
= AllocateZeroPool (Length
* sizeof (CHAR16
));
2265 if (DefaultAltCfgResp
== NULL
) {
2266 Status
= EFI_OUT_OF_RESOURCES
;
2269 StringPtr
= DefaultAltCfgResp
;
2272 // Start with <ConfigHdr>
2274 StrCpy (StringPtr
, ConfigHdr
);
2275 StringPtr
+= StrLen (StringPtr
);
2277 for (Link
= DefaultIdArray
->Entry
.ForwardLink
; Link
!= &DefaultIdArray
->Entry
; Link
= Link
->ForwardLink
) {
2278 DefaultId
= BASE_CR (Link
, IFR_DEFAULT_DATA
, Entry
);
2280 // Add <AltConfigHdr> of the form "&<ConfigHdr>&ALTCFG=XXXX\0"
2281 // |1| StrLen (ConfigHdr) | 8 | 4 |
2285 (1 + StrLen (ConfigHdr
) + 8 + 4 + 1) * sizeof (CHAR16
),
2288 DefaultId
->DefaultId
2290 StringPtr
+= StrLen (StringPtr
);
2292 for (LinkData
= VarStorageData
->BlockEntry
.ForwardLink
; LinkData
!= &VarStorageData
->BlockEntry
; LinkData
= LinkData
->ForwardLink
) {
2293 BlockData
= BASE_CR (LinkData
, IFR_BLOCK_DATA
, Entry
);
2294 for (LinkDefault
= BlockData
->DefaultValueEntry
.ForwardLink
; LinkDefault
!= &BlockData
->DefaultValueEntry
; LinkDefault
= LinkDefault
->ForwardLink
) {
2295 DefaultValueData
= BASE_CR (LinkDefault
, IFR_DEFAULT_DATA
, Entry
);
2296 if (DefaultValueData
->DefaultId
== DefaultId
->DefaultId
) {
2298 // Add <BlockConfig>
2299 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>
2303 (8 + 4 + 7 + 4 + 7 + 1) * sizeof (CHAR16
),
2304 L
"&OFFSET=%04X&WIDTH=%04X&VALUE=",
2308 StringPtr
+= StrLen (StringPtr
);
2311 // Convert Value to a hex string in "%x" format
2312 // NOTE: This is in the opposite byte that GUID and PATH use
2314 Width
= BlockData
->Width
;
2315 TmpBuffer
= (UINT8
*) &(DefaultValueData
->Value
);
2316 for (; Width
> 0; Width
--) {
2317 StringPtr
+= UnicodeValueToString (StringPtr
, PREFIX_ZERO
| RADIX_HEX
, TmpBuffer
[Width
- 1], 2);
2323 HiiToLower (DefaultAltCfgResp
);
2326 // 5. Merge string into the input AltCfgResp if the iput *AltCfgResp is not NULL.
2328 if (*AltCfgResp
!= NULL
&& DefaultAltCfgResp
!= NULL
) {
2329 Status
= MergeDefaultString (AltCfgResp
, DefaultAltCfgResp
);
2330 FreePool (DefaultAltCfgResp
);
2331 } else if (*AltCfgResp
== NULL
) {
2332 *AltCfgResp
= DefaultAltCfgResp
;
2336 if (RequestBlockArray
!= NULL
) {
2338 // Free Link Array RequestBlockArray
2340 while (!IsListEmpty (&RequestBlockArray
->Entry
)) {
2341 BlockData
= BASE_CR (RequestBlockArray
->Entry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
2342 RemoveEntryList (&BlockData
->Entry
);
2343 FreePool (BlockData
);
2346 FreePool (RequestBlockArray
);
2349 if (VarStorageData
!= NULL
) {
2351 // Free link array VarStorageData
2353 while (!IsListEmpty (&VarStorageData
->BlockEntry
)) {
2354 BlockData
= BASE_CR (VarStorageData
->BlockEntry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
2355 RemoveEntryList (&BlockData
->Entry
);
2357 // Free default value link array
2359 while (!IsListEmpty (&BlockData
->DefaultValueEntry
)) {
2360 DefaultValueData
= BASE_CR (BlockData
->DefaultValueEntry
.ForwardLink
, IFR_DEFAULT_DATA
, Entry
);
2361 RemoveEntryList (&DefaultValueData
->Entry
);
2362 FreePool (DefaultValueData
);
2364 FreePool (BlockData
);
2366 FreePool (VarStorageData
);
2369 if (DefaultIdArray
!= NULL
) {
2371 // Free DefaultId Array
2373 while (!IsListEmpty (&DefaultIdArray
->Entry
)) {
2374 DefaultId
= BASE_CR (DefaultIdArray
->Entry
.ForwardLink
, IFR_DEFAULT_DATA
, Entry
);
2375 RemoveEntryList (&DefaultId
->Entry
);
2376 FreePool (DefaultId
);
2378 FreePool (DefaultIdArray
);
2382 // Free the allocated string
2384 if (GuidStr
!= NULL
) {
2387 if (NameStr
!= NULL
) {
2390 if (PathStr
!= NULL
) {
2393 if (ConfigHdr
!= NULL
) {
2394 FreePool (ConfigHdr
);
2398 // Free Pacakge data
2400 if (HiiFormPackage
!= NULL
) {
2401 FreePool (HiiFormPackage
);
2404 if (PointerProgress
!= NULL
) {
2405 if (*Request
== NULL
) {
2406 *PointerProgress
= NULL
;
2407 } else if (EFI_ERROR (Status
)) {
2408 *PointerProgress
= Progress
;
2410 *PointerProgress
= *Request
+ StrLen (*Request
);
2418 This function gets the full request resp string by
2419 parsing IFR data in HII form packages.
2421 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
2423 @param EfiVarStoreInfo The efi varstore info which is save in the EFI
2424 varstore data structure.
2425 @param Request Pointer to a null-terminated Unicode string in
2426 <ConfigRequest> format.
2427 @param RequestResp Pointer to a null-terminated Unicode string in
2428 <ConfigResp> format.
2429 @param AccessProgress On return, points to a character in the Request
2430 string. Points to the string's null terminator if
2431 request was successful. Points to the most recent
2432 & before the first failing name / value pair (or
2433 the beginning of the string if the failure is in
2434 the first name / value pair) if the request was
2437 @retval EFI_SUCCESS The Results string is set to the full request string.
2438 And AltCfgResp contains all default value string.
2439 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
2440 @retval EFI_INVALID_PARAMETER Request points to NULL.
2444 GetConfigRespFromEfiVarStore (
2445 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
2446 IN EFI_IFR_VARSTORE_EFI
*EfiVarStoreInfo
,
2447 IN EFI_STRING Request
,
2448 OUT EFI_STRING
*RequestResp
,
2449 OUT EFI_STRING
*AccessProgress
2453 EFI_STRING VarStoreName
;
2457 Status
= EFI_SUCCESS
;
2460 VarStoreName
= NULL
;
2462 VarStoreName
= AllocateZeroPool (AsciiStrSize ((CHAR8
*)EfiVarStoreInfo
->Name
) * sizeof (CHAR16
));
2463 if (VarStoreName
== NULL
) {
2464 Status
= EFI_OUT_OF_RESOURCES
;
2467 AsciiStrToUnicodeStr ((CHAR8
*) EfiVarStoreInfo
->Name
, VarStoreName
);
2470 Status
= gRT
->GetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, NULL
, &BufferSize
, NULL
);
2471 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
2475 VarStore
= AllocateZeroPool (BufferSize
);
2476 ASSERT (VarStore
!= NULL
);
2477 Status
= gRT
->GetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, NULL
, &BufferSize
, VarStore
);
2478 if (EFI_ERROR (Status
)) {
2482 Status
= HiiBlockToConfig(This
, Request
, VarStore
, BufferSize
, RequestResp
, AccessProgress
);
2483 if (EFI_ERROR (Status
)) {
2488 if (VarStoreName
!= NULL
) {
2489 FreePool (VarStoreName
);
2492 if (VarStore
!= NULL
) {
2493 FreePool (VarStore
);
2501 This function route the full request resp string for efi varstore.
2503 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
2505 @param EfiVarStoreInfo The efi varstore info which is save in the EFI
2506 varstore data structure.
2507 @param RequestResp Pointer to a null-terminated Unicode string in
2508 <ConfigResp> format.
2509 @param Result Pointer to a null-terminated Unicode string in
2510 <ConfigResp> format.
2512 @retval EFI_SUCCESS The Results string is set to the full request string.
2513 And AltCfgResp contains all default value string.
2514 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
2515 @retval EFI_INVALID_PARAMETER Request points to NULL.
2519 RouteConfigRespForEfiVarStore (
2520 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
2521 IN EFI_IFR_VARSTORE_EFI
*EfiVarStoreInfo
,
2522 IN EFI_STRING RequestResp
,
2523 OUT EFI_STRING
*Result
2527 EFI_STRING VarStoreName
;
2532 Status
= EFI_SUCCESS
;
2535 VarStoreName
= NULL
;
2537 VarStoreName
= AllocateZeroPool (AsciiStrSize ((CHAR8
*)EfiVarStoreInfo
->Name
) * sizeof (CHAR16
));
2538 if (VarStoreName
== NULL
) {
2539 Status
= EFI_OUT_OF_RESOURCES
;
2542 AsciiStrToUnicodeStr ((CHAR8
*) EfiVarStoreInfo
->Name
, VarStoreName
);
2544 Status
= gRT
->GetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, NULL
, &BufferSize
, NULL
);
2545 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
2549 BlockSize
= BufferSize
;
2550 VarStore
= AllocateZeroPool (BufferSize
);
2551 ASSERT (VarStore
!= NULL
);
2552 Status
= gRT
->GetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, NULL
, &BufferSize
, VarStore
);
2553 if (EFI_ERROR (Status
)) {
2557 Status
= HiiConfigToBlock(This
, RequestResp
, VarStore
, &BlockSize
, Result
);
2558 if (EFI_ERROR (Status
)) {
2562 Status
= gRT
->SetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, EfiVarStoreInfo
->Attributes
, BufferSize
, VarStore
);
2563 if (EFI_ERROR (Status
)) {
2568 if (VarStoreName
!= NULL
) {
2569 FreePool (VarStoreName
);
2572 if (VarStore
!= NULL
) {
2573 FreePool (VarStore
);
2580 This function allows a caller to extract the current configuration
2581 for one or more named elements from one or more drivers.
2583 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
2585 @param Request A null-terminated Unicode string in
2586 <MultiConfigRequest> format.
2587 @param Progress On return, points to a character in the Request
2588 string. Points to the string's null terminator if
2589 request was successful. Points to the most recent
2590 & before the first failing name / value pair (or
2591 the beginning of the string if the failure is in
2592 the first name / value pair) if the request was
2594 @param Results Null-terminated Unicode string in
2595 <MultiConfigAltResp> format which has all values
2596 filled in for the names in the Request string.
2597 String to be allocated by the called function.
2599 @retval EFI_SUCCESS The Results string is filled with the values
2600 corresponding to all requested names.
2601 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
2602 results that must be stored awaiting possible
2604 @retval EFI_NOT_FOUND Routing data doesn't match any known driver.
2605 Progress set to the "G" in "GUID" of the routing
2606 header that doesn't match. Note: There is no
2607 requirement that all routing data be validated
2608 before any configuration extraction.
2609 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Request
2610 parameter would result in this type of error. The
2611 Progress parameter is set to NULL.
2612 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set to most recent &
2613 before the error or the beginning of the string.
2614 @retval EFI_INVALID_PARAMETER Unknown name. Progress points to the & before the
2620 HiiConfigRoutingExtractConfig (
2621 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
2622 IN CONST EFI_STRING Request
,
2623 OUT EFI_STRING
*Progress
,
2624 OUT EFI_STRING
*Results
2627 HII_DATABASE_PRIVATE_DATA
*Private
;
2628 EFI_STRING StringPtr
;
2629 EFI_STRING ConfigRequest
;
2631 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
2632 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
2635 HII_DATABASE_RECORD
*Database
;
2636 UINT8
*DevicePathPkg
;
2637 UINT8
*CurrentDevicePath
;
2638 EFI_HANDLE DriverHandle
;
2639 EFI_HII_HANDLE HiiHandle
;
2640 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
2641 EFI_STRING AccessProgress
;
2642 EFI_STRING AccessResults
;
2643 EFI_STRING DefaultResults
;
2644 BOOLEAN FirstElement
;
2645 BOOLEAN IfrDataParsedFlag
;
2646 BOOLEAN IsEfiVarStore
;
2647 EFI_IFR_VARSTORE_EFI
*EfiVarStoreInfo
;
2649 if (This
== NULL
|| Progress
== NULL
|| Results
== NULL
) {
2650 return EFI_INVALID_PARAMETER
;
2653 if (Request
== NULL
) {
2655 return EFI_INVALID_PARAMETER
;
2658 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
2659 StringPtr
= Request
;
2660 *Progress
= StringPtr
;
2661 DefaultResults
= NULL
;
2662 ConfigRequest
= NULL
;
2663 Status
= EFI_SUCCESS
;
2664 AccessResults
= NULL
;
2665 AccessProgress
= NULL
;
2667 IfrDataParsedFlag
= FALSE
;
2668 IsEfiVarStore
= FALSE
;
2669 EfiVarStoreInfo
= NULL
;
2672 // The first element of <MultiConfigRequest> should be
2673 // <GuidHdr>, which is in 'GUID='<Guid> syntax.
2675 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
2676 return EFI_INVALID_PARAMETER
;
2679 FirstElement
= TRUE
;
2682 // Allocate a fix length of memory to store Results. Reallocate memory for
2683 // Results if this fix length is insufficient.
2685 *Results
= (EFI_STRING
) AllocateZeroPool (MAX_STRING_LENGTH
);
2686 if (*Results
== NULL
) {
2687 return EFI_OUT_OF_RESOURCES
;
2690 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) == 0) {
2692 // If parsing error, set Progress to the beginning of the <MultiConfigRequest>
2693 // or most recent & before the error.
2695 if (StringPtr
== Request
) {
2696 *Progress
= StringPtr
;
2698 *Progress
= StringPtr
- 1;
2702 // Process each <ConfigRequest> of <MultiConfigRequest>
2704 Length
= CalculateConfigStringLen (StringPtr
);
2705 ConfigRequest
= AllocateCopyPool ((Length
+ 1) * sizeof (CHAR16
), StringPtr
);
2706 if (ConfigRequest
== NULL
) {
2707 Status
= EFI_OUT_OF_RESOURCES
;
2710 *(ConfigRequest
+ Length
) = 0;
2713 // Get the UEFI device path
2715 Status
= GetDevicePath (ConfigRequest
, (UINT8
**) &DevicePath
);
2716 if (EFI_ERROR (Status
)) {
2721 // Find driver which matches the routing data.
2723 DriverHandle
= NULL
;
2726 for (Link
= Private
->DatabaseList
.ForwardLink
;
2727 Link
!= &Private
->DatabaseList
;
2728 Link
= Link
->ForwardLink
2730 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
2731 if ((DevicePathPkg
= Database
->PackageList
->DevicePathPkg
) != NULL
) {
2732 CurrentDevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
2736 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) CurrentDevicePath
)
2738 DriverHandle
= Database
->DriverHandle
;
2739 HiiHandle
= Database
->Handle
;
2746 // Try to find driver handle by device path.
2748 if (DriverHandle
== NULL
) {
2749 TempDevicePath
= DevicePath
;
2750 Status
= gBS
->LocateDevicePath (
2751 &gEfiDevicePathProtocolGuid
,
2755 if (EFI_ERROR (Status
) || (DriverHandle
== NULL
)) {
2757 // Routing data does not match any known driver.
2758 // Set Progress to the 'G' in "GUID" of the routing header.
2760 *Progress
= StringPtr
;
2761 Status
= EFI_NOT_FOUND
;
2767 // Check whether ConfigRequest contains request string OFFSET/WIDTH
2769 IfrDataParsedFlag
= FALSE
;
2770 if ((HiiHandle
!= NULL
) && (StrStr (ConfigRequest
, L
"&OFFSET=") == NULL
)) {
2772 // Get the full request string from IFR when HiiPackage is registered to HiiHandle
2774 IfrDataParsedFlag
= TRUE
;
2775 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &ConfigRequest
, &DefaultResults
, &AccessProgress
);
2776 if (EFI_ERROR (Status
)) {
2778 // AccessProgress indicates the parsing progress on <ConfigRequest>.
2779 // Map it to the progress on <MultiConfigRequest> then return it.
2781 *Progress
= StrStr (StringPtr
, AccessProgress
);
2785 // Not any request block is found.
2787 if (StrStr (ConfigRequest
, L
"&OFFSET=") == NULL
) {
2788 AccessResults
= AllocateCopyPool (StrSize (ConfigRequest
), ConfigRequest
);
2789 goto NextConfigString
;
2794 // Check whether this ConfigRequest is search from Efi varstore type storage.
2796 Status
= GetVarStoreType(Database
, ConfigRequest
, &IsEfiVarStore
, &EfiVarStoreInfo
);
2797 if (EFI_ERROR (Status
)) {
2801 if (IsEfiVarStore
) {
2803 // Call the GetVariable function to extract settings.
2805 Status
= GetConfigRespFromEfiVarStore(This
, EfiVarStoreInfo
, ConfigRequest
, &AccessResults
, &AccessProgress
);
2806 FreePool (EfiVarStoreInfo
);
2809 // Call corresponding ConfigAccess protocol to extract settings
2811 Status
= gBS
->HandleProtocol (
2813 &gEfiHiiConfigAccessProtocolGuid
,
2814 (VOID
**) &ConfigAccess
2816 ASSERT_EFI_ERROR (Status
);
2818 Status
= ConfigAccess
->ExtractConfig (
2825 if (EFI_ERROR (Status
)) {
2827 // AccessProgress indicates the parsing progress on <ConfigRequest>.
2828 // Map it to the progress on <MultiConfigRequest> then return it.
2830 *Progress
= StrStr (StringPtr
, AccessProgress
);
2835 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'
2836 // which seperates the first <ConfigAltResp> and the following ones.
2838 ASSERT (*AccessProgress
== 0);
2841 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
2843 if (!IfrDataParsedFlag
&& HiiHandle
!= NULL
) {
2844 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &ConfigRequest
, &DefaultResults
, NULL
);
2845 ASSERT_EFI_ERROR (Status
);
2848 FreePool (DevicePath
);
2851 if (DefaultResults
!= NULL
) {
2852 Status
= MergeDefaultString (&AccessResults
, DefaultResults
);
2853 ASSERT_EFI_ERROR (Status
);
2854 FreePool (DefaultResults
);
2855 DefaultResults
= NULL
;
2859 if (!FirstElement
) {
2860 Status
= AppendToMultiString (Results
, L
"&");
2861 ASSERT_EFI_ERROR (Status
);
2864 Status
= AppendToMultiString (Results
, AccessResults
);
2865 ASSERT_EFI_ERROR (Status
);
2867 FirstElement
= FALSE
;
2869 FreePool (AccessResults
);
2870 AccessResults
= NULL
;
2871 FreePool (ConfigRequest
);
2872 ConfigRequest
= NULL
;
2875 // Go to next <ConfigRequest> (skip '&').
2877 StringPtr
+= Length
;
2878 if (*StringPtr
== 0) {
2879 *Progress
= StringPtr
;
2887 if (EFI_ERROR (Status
)) {
2888 FreePool (*Results
);
2892 if (ConfigRequest
!= NULL
) {
2893 FreePool (ConfigRequest
);
2896 if (AccessResults
!= NULL
) {
2897 FreePool (AccessResults
);
2900 if (DefaultResults
!= NULL
) {
2901 FreePool (DefaultResults
);
2904 if (DevicePath
!= NULL
) {
2905 FreePool (DevicePath
);
2913 This function allows the caller to request the current configuration for the
2914 entirety of the current HII database and returns the data in a
2915 null-terminated Unicode string.
2917 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
2919 @param Results Null-terminated Unicode string in
2920 <MultiConfigAltResp> format which has all values
2921 filled in for the names in the Request string.
2922 String to be allocated by the called function.
2923 De-allocation is up to the caller.
2925 @retval EFI_SUCCESS The Results string is filled with the values
2926 corresponding to all requested names.
2927 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
2928 results that must be stored awaiting possible
2930 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Results
2931 parameter would result in this type of error.
2936 HiiConfigRoutingExportConfig (
2937 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
2938 OUT EFI_STRING
*Results
2942 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
2943 EFI_STRING AccessResults
;
2944 EFI_STRING Progress
;
2945 EFI_STRING StringPtr
;
2946 EFI_STRING ConfigRequest
;
2948 EFI_HANDLE
*ConfigAccessHandles
;
2949 UINTN NumberConfigAccessHandles
;
2950 BOOLEAN FirstElement
;
2951 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
2952 EFI_HII_HANDLE HiiHandle
;
2953 EFI_STRING DefaultResults
;
2954 HII_DATABASE_PRIVATE_DATA
*Private
;
2956 HII_DATABASE_RECORD
*Database
;
2957 UINT8
*DevicePathPkg
;
2958 UINT8
*CurrentDevicePath
;
2959 BOOLEAN IfrDataParsedFlag
;
2961 if (This
== NULL
|| Results
== NULL
) {
2962 return EFI_INVALID_PARAMETER
;
2965 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
2968 // Allocate a fix length of memory to store Results. Reallocate memory for
2969 // Results if this fix length is insufficient.
2971 *Results
= (EFI_STRING
) AllocateZeroPool (MAX_STRING_LENGTH
);
2972 if (*Results
== NULL
) {
2973 return EFI_OUT_OF_RESOURCES
;
2976 NumberConfigAccessHandles
= 0;
2977 Status
= gBS
->LocateHandleBuffer (
2979 &gEfiHiiConfigAccessProtocolGuid
,
2981 &NumberConfigAccessHandles
,
2982 &ConfigAccessHandles
2984 if (EFI_ERROR (Status
)) {
2988 FirstElement
= TRUE
;
2990 for (Index
= 0; Index
< NumberConfigAccessHandles
; Index
++) {
2991 Status
= gBS
->HandleProtocol (
2992 ConfigAccessHandles
[Index
],
2993 &gEfiHiiConfigAccessProtocolGuid
,
2994 (VOID
**) &ConfigAccess
2996 if (EFI_ERROR (Status
)) {
3001 // Get DevicePath and HiiHandle for this ConfigAccess driver handle
3003 IfrDataParsedFlag
= FALSE
;
3006 DefaultResults
= NULL
;
3008 ConfigRequest
= NULL
;
3009 DevicePath
= DevicePathFromHandle (ConfigAccessHandles
[Index
]);
3010 if (DevicePath
!= NULL
) {
3011 for (Link
= Private
->DatabaseList
.ForwardLink
;
3012 Link
!= &Private
->DatabaseList
;
3013 Link
= Link
->ForwardLink
3015 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
3016 if ((DevicePathPkg
= Database
->PackageList
->DevicePathPkg
) != NULL
) {
3017 CurrentDevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
3021 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) CurrentDevicePath
)
3023 HiiHandle
= Database
->Handle
;
3030 Status
= ConfigAccess
->ExtractConfig (
3036 if (EFI_ERROR (Status
)) {
3038 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
3040 if (HiiHandle
!= NULL
&& DevicePath
!= NULL
) {
3041 IfrDataParsedFlag
= TRUE
;
3042 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &ConfigRequest
, &DefaultResults
, NULL
);
3044 // Get the full request string to get the Current setting again.
3046 if (!EFI_ERROR (Status
) && ConfigRequest
!= NULL
) {
3047 Status
= ConfigAccess
->ExtractConfig (
3053 FreePool (ConfigRequest
);
3055 Status
= EFI_NOT_FOUND
;
3060 if (!EFI_ERROR (Status
)) {
3062 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
3064 if (!IfrDataParsedFlag
&& HiiHandle
!= NULL
&& DevicePath
!= NULL
) {
3065 StringPtr
= StrStr (AccessResults
, L
"&GUID=");
3066 if (StringPtr
!= NULL
) {
3069 if (StrStr (AccessResults
, L
"&OFFSET=") != NULL
) {
3070 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &AccessResults
, &DefaultResults
, NULL
);
3071 ASSERT_EFI_ERROR (Status
);
3073 if (StringPtr
!= NULL
) {
3078 // Merge the default sting from IFR code into the got setting from driver.
3080 if (DefaultResults
!= NULL
) {
3081 Status
= MergeDefaultString (&AccessResults
, DefaultResults
);
3082 ASSERT_EFI_ERROR (Status
);
3083 FreePool (DefaultResults
);
3084 DefaultResults
= NULL
;
3088 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'
3089 // which seperates the first <ConfigAltResp> and the following ones.
3091 if (!FirstElement
) {
3092 Status
= AppendToMultiString (Results
, L
"&");
3093 ASSERT_EFI_ERROR (Status
);
3096 Status
= AppendToMultiString (Results
, AccessResults
);
3097 ASSERT_EFI_ERROR (Status
);
3099 FirstElement
= FALSE
;
3101 FreePool (AccessResults
);
3102 AccessResults
= NULL
;
3105 FreePool (ConfigAccessHandles
);
3112 This function processes the results of processing forms and routes it to the
3113 appropriate handlers or storage.
3115 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
3117 @param Configuration A null-terminated Unicode string in
3118 <MulltiConfigResp> format.
3119 @param Progress A pointer to a string filled in with the offset of
3120 the most recent & before the first failing name /
3121 value pair (or the beginning of the string if the
3122 failure is in the first name / value pair) or the
3123 terminating NULL if all was successful.
3125 @retval EFI_SUCCESS The results have been distributed or are awaiting
3127 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
3128 results that must be stored awaiting possible
3130 @retval EFI_INVALID_PARAMETER Passing in a NULL for the Configuration parameter
3131 would result in this type of error.
3132 @retval EFI_NOT_FOUND Target for the specified routing data was not
3138 HiiConfigRoutingRouteConfig (
3139 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
3140 IN CONST EFI_STRING Configuration
,
3141 OUT EFI_STRING
*Progress
3144 HII_DATABASE_PRIVATE_DATA
*Private
;
3145 EFI_STRING StringPtr
;
3146 EFI_STRING ConfigResp
;
3149 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
3150 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
3152 HII_DATABASE_RECORD
*Database
;
3153 UINT8
*DevicePathPkg
;
3154 UINT8
*CurrentDevicePath
;
3155 EFI_HANDLE DriverHandle
;
3156 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
3157 EFI_STRING AccessProgress
;
3158 EFI_IFR_VARSTORE_EFI
*EfiVarStoreInfo
;
3159 BOOLEAN IsEfiVarstore
;
3161 if (This
== NULL
|| Progress
== NULL
) {
3162 return EFI_INVALID_PARAMETER
;
3165 if (Configuration
== NULL
) {
3167 return EFI_INVALID_PARAMETER
;
3170 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
3171 StringPtr
= Configuration
;
3172 *Progress
= StringPtr
;
3174 AccessProgress
= NULL
;
3175 EfiVarStoreInfo
= NULL
;
3176 IsEfiVarstore
= FALSE
;
3179 // The first element of <MultiConfigResp> should be
3180 // <GuidHdr>, which is in 'GUID='<Guid> syntax.
3182 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
3183 return EFI_INVALID_PARAMETER
;
3186 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) == 0) {
3188 // If parsing error, set Progress to the beginning of the <MultiConfigResp>
3189 // or most recent & before the error.
3191 if (StringPtr
== Configuration
) {
3192 *Progress
= StringPtr
;
3194 *Progress
= StringPtr
- 1;
3198 // Process each <ConfigResp> of <MultiConfigResp>
3200 Length
= CalculateConfigStringLen (StringPtr
);
3201 ConfigResp
= AllocateCopyPool ((Length
+ 1) * sizeof (CHAR16
), StringPtr
);
3202 if (ConfigResp
== NULL
) {
3203 return EFI_OUT_OF_RESOURCES
;
3206 // Append '\0' to the end of ConfigRequest
3208 *(ConfigResp
+ Length
) = 0;
3211 // Get the UEFI device path
3213 Status
= GetDevicePath (ConfigResp
, (UINT8
**) &DevicePath
);
3214 if (EFI_ERROR (Status
)) {
3215 FreePool (ConfigResp
);
3220 // Find driver which matches the routing data.
3222 DriverHandle
= NULL
;
3223 for (Link
= Private
->DatabaseList
.ForwardLink
;
3224 Link
!= &Private
->DatabaseList
;
3225 Link
= Link
->ForwardLink
3227 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
3229 if ((DevicePathPkg
= Database
->PackageList
->DevicePathPkg
) != NULL
) {
3230 CurrentDevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
3234 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) CurrentDevicePath
)
3236 DriverHandle
= Database
->DriverHandle
;
3243 // Try to find driver handle by device path.
3245 if (DriverHandle
== NULL
) {
3246 TempDevicePath
= DevicePath
;
3247 Status
= gBS
->LocateDevicePath (
3248 &gEfiDevicePathProtocolGuid
,
3252 if (EFI_ERROR (Status
) || (DriverHandle
== NULL
)) {
3254 // Routing data does not match any known driver.
3255 // Set Progress to the 'G' in "GUID" of the routing header.
3257 FreePool (DevicePath
);
3258 *Progress
= StringPtr
;
3259 FreePool (ConfigResp
);
3260 return EFI_NOT_FOUND
;
3264 FreePool (DevicePath
);
3267 // Check whether this ConfigRequest is search from Efi varstore type storage.
3269 Status
= GetVarStoreType(Database
, ConfigResp
, &IsEfiVarstore
, &EfiVarStoreInfo
);
3270 if (EFI_ERROR (Status
)) {
3274 if (IsEfiVarstore
) {
3276 // Call the SetVariable function to route settings.
3278 Status
= RouteConfigRespForEfiVarStore(This
, EfiVarStoreInfo
, ConfigResp
, &AccessProgress
);
3279 FreePool (EfiVarStoreInfo
);
3282 // Call corresponding ConfigAccess protocol to route settings
3284 Status
= gBS
->HandleProtocol (
3286 &gEfiHiiConfigAccessProtocolGuid
,
3287 (VOID
**) &ConfigAccess
3289 ASSERT_EFI_ERROR (Status
);
3291 Status
= ConfigAccess
->RouteConfig (
3297 if (EFI_ERROR (Status
)) {
3299 // AccessProgress indicates the parsing progress on <ConfigResp>.
3300 // Map it to the progress on <MultiConfigResp> then return it.
3302 *Progress
= StrStr (StringPtr
, AccessProgress
);
3304 FreePool (ConfigResp
);
3308 FreePool (ConfigResp
);
3312 // Go to next <ConfigResp> (skip '&').
3314 StringPtr
+= Length
;
3315 if (*StringPtr
== 0) {
3316 *Progress
= StringPtr
;
3329 This helper function is to be called by drivers to map configuration data
3330 stored in byte array ("block") formats such as UEFI Variables into current
3331 configuration strings.
3333 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
3335 @param ConfigRequest A null-terminated Unicode string in
3336 <ConfigRequest> format.
3337 @param Block Array of bytes defining the block's configuration.
3338 @param BlockSize Length in bytes of Block.
3339 @param Config Filled-in configuration string. String allocated
3340 by the function. Returned only if call is
3341 successful. It is <ConfigResp> string format.
3342 @param Progress A pointer to a string filled in with the offset of
3343 the most recent & before the first failing
3344 name/value pair (or the beginning of the string if
3345 the failure is in the first name / value pair) or
3346 the terminating NULL if all was successful.
3348 @retval EFI_SUCCESS The request succeeded. Progress points to the null
3349 terminator at the end of the ConfigRequest
3351 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress
3352 points to the first character of ConfigRequest.
3353 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigRequest or
3354 Block parameter would result in this type of
3355 error. Progress points to the first character of
3357 @retval EFI_DEVICE_ERROR Block not large enough. Progress undefined.
3358 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted string.
3359 Block is left updated and Progress points at
3360 the "&" preceding the first non-<BlockName>.
3366 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
3367 IN CONST EFI_STRING ConfigRequest
,
3368 IN CONST UINT8
*Block
,
3369 IN CONST UINTN BlockSize
,
3370 OUT EFI_STRING
*Config
,
3371 OUT EFI_STRING
*Progress
3374 HII_DATABASE_PRIVATE_DATA
*Private
;
3375 EFI_STRING StringPtr
;
3383 EFI_STRING ValueStr
;
3384 EFI_STRING ConfigElement
;
3390 if (This
== NULL
|| Progress
== NULL
|| Config
== NULL
) {
3391 return EFI_INVALID_PARAMETER
;
3394 if (Block
== NULL
|| ConfigRequest
== NULL
) {
3395 *Progress
= ConfigRequest
;
3396 return EFI_INVALID_PARAMETER
;
3400 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
3401 ASSERT (Private
!= NULL
);
3403 StringPtr
= ConfigRequest
;
3406 ConfigElement
= NULL
;
3409 // Allocate a fix length of memory to store Results. Reallocate memory for
3410 // Results if this fix length is insufficient.
3412 *Config
= (EFI_STRING
) AllocateZeroPool (MAX_STRING_LENGTH
);
3413 if (*Config
== NULL
) {
3414 return EFI_OUT_OF_RESOURCES
;
3420 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
3421 *Progress
= StringPtr
;
3422 Status
= EFI_INVALID_PARAMETER
;
3425 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"PATH=", StrLen (L
"PATH=")) != 0) {
3428 if (*StringPtr
== 0) {
3429 *Progress
= StringPtr
- 1;
3430 Status
= EFI_INVALID_PARAMETER
;
3434 while (*StringPtr
!= L
'&' && *StringPtr
!= 0) {
3437 if (*StringPtr
== 0) {
3438 *Progress
= StringPtr
;
3439 Status
= EFI_SUCCESS
;
3441 AppendToMultiString(Config
, ConfigRequest
);
3442 HiiToLower (*Config
);
3452 // Copy <ConfigHdr> and an additional '&' to <ConfigResp>
3454 TemChar
= *StringPtr
;
3456 AppendToMultiString(Config
, ConfigRequest
);
3457 *StringPtr
= TemChar
;
3460 // Parse each <RequestElement> if exists
3461 // Only <BlockName> format is supported by this help function.
3462 // <BlockName> ::= 'OFFSET='<Number>&'WIDTH='<Number>
3464 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"OFFSET=", StrLen (L
"OFFSET=")) == 0) {
3466 // Back up the header of one <BlockName>
3470 StringPtr
+= StrLen (L
"OFFSET=");
3474 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
3475 if (EFI_ERROR (Status
)) {
3476 *Progress
= ConfigRequest
;
3483 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
3485 FreePool (TmpBuffer
);
3487 StringPtr
+= Length
;
3488 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
3489 *Progress
= StringPtr
- Length
- StrLen (L
"OFFSET=") - 1;
3490 Status
= EFI_INVALID_PARAMETER
;
3493 StringPtr
+= StrLen (L
"&WIDTH=");
3498 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
3499 if (EFI_ERROR (Status
)) {
3500 *Progress
= ConfigRequest
;
3507 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
3509 FreePool (TmpBuffer
);
3511 StringPtr
+= Length
;
3512 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
3513 *Progress
= StringPtr
- Length
- StrLen (L
"&WIDTH=");
3514 Status
= EFI_INVALID_PARAMETER
;
3519 // Calculate Value and convert it to hex string.
3521 if (Offset
+ Width
> BlockSize
) {
3522 *Progress
= StringPtr
;
3523 Status
= EFI_DEVICE_ERROR
;
3527 Value
= (UINT8
*) AllocateZeroPool (Width
);
3528 if (Value
== NULL
) {
3529 *Progress
= ConfigRequest
;
3530 Status
= EFI_OUT_OF_RESOURCES
;
3534 CopyMem (Value
, (UINT8
*) Block
+ Offset
, Width
);
3536 Length
= Width
* 2 + 1;
3537 ValueStr
= (EFI_STRING
) AllocateZeroPool (Length
* sizeof (CHAR16
));
3538 if (ValueStr
== NULL
) {
3539 *Progress
= ConfigRequest
;
3540 Status
= EFI_OUT_OF_RESOURCES
;
3544 TemString
= ValueStr
;
3545 TemBuffer
= Value
+ Width
- 1;
3546 for (Index
= 0; Index
< Width
; Index
++, TemBuffer
--) {
3547 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
3554 // Build a ConfigElement
3556 Length
+= StringPtr
- TmpPtr
+ 1 + StrLen (L
"VALUE=");
3557 ConfigElement
= (EFI_STRING
) AllocateZeroPool (Length
* sizeof (CHAR16
));
3558 if (ConfigElement
== NULL
) {
3559 Status
= EFI_OUT_OF_RESOURCES
;
3562 CopyMem (ConfigElement
, TmpPtr
, (StringPtr
- TmpPtr
+ 1) * sizeof (CHAR16
));
3563 if (*StringPtr
== 0) {
3564 *(ConfigElement
+ (StringPtr
- TmpPtr
)) = L
'&';
3566 *(ConfigElement
+ (StringPtr
- TmpPtr
) + 1) = 0;
3567 StrCat (ConfigElement
, L
"VALUE=");
3568 StrCat (ConfigElement
, ValueStr
);
3570 AppendToMultiString (Config
, ConfigElement
);
3572 FreePool (ConfigElement
);
3573 FreePool (ValueStr
);
3574 ConfigElement
= NULL
;
3578 // If '\0', parsing is finished. Otherwise skip '&' to continue
3580 if (*StringPtr
== 0) {
3583 AppendToMultiString (Config
, L
"&");
3588 if (*StringPtr
!= 0) {
3589 *Progress
= StringPtr
- 1;
3590 Status
= EFI_INVALID_PARAMETER
;
3594 HiiToLower (*Config
);
3595 *Progress
= StringPtr
;
3599 if (*Config
!= NULL
) {
3603 if (ValueStr
!= NULL
) {
3604 FreePool (ValueStr
);
3606 if (Value
!= NULL
) {
3609 if (ConfigElement
!= NULL
) {
3610 FreePool (ConfigElement
);
3619 This helper function is to be called by drivers to map configuration strings
3620 to configurations stored in byte array ("block") formats such as UEFI Variables.
3622 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
3624 @param ConfigResp A null-terminated Unicode string in <ConfigResp>
3626 @param Block A possibly null array of bytes representing the
3627 current block. Only bytes referenced in the
3628 ConfigResp string in the block are modified. If
3629 this parameter is null or if the *BlockSize
3630 parameter is (on input) shorter than required by
3631 the Configuration string, only the BlockSize
3632 parameter is updated and an appropriate status
3633 (see below) is returned.
3634 @param BlockSize The length of the Block in units of UINT8. On
3635 input, this is the size of the Block. On output,
3636 if successful, contains the index of the last
3637 modified byte in the Block.
3638 @param Progress On return, points to an element of the ConfigResp
3639 string filled in with the offset of the most
3640 recent '&' before the first failing name / value
3641 pair (or the beginning of the string if the
3642 failure is in the first name / value pair) or the
3643 terminating NULL if all was successful.
3645 @retval EFI_SUCCESS The request succeeded. Progress points to the null
3646 terminator at the end of the ConfigResp string.
3647 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress
3648 points to the first character of ConfigResp.
3649 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigResp or
3650 Block parameter would result in this type of
3651 error. Progress points to the first character of
3653 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted name /
3654 value pair. Block is left updated and
3655 Progress points at the '&' preceding the first
3657 @retval EFI_DEVICE_ERROR Block not large enough. Progress undefined.
3658 @retval EFI_NOT_FOUND Target for the specified routing data was not found.
3659 Progress points to the "G" in "GUID" of the errant
3666 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
3667 IN CONST EFI_STRING ConfigResp
,
3668 IN OUT UINT8
*Block
,
3669 IN OUT UINTN
*BlockSize
,
3670 OUT EFI_STRING
*Progress
3673 HII_DATABASE_PRIVATE_DATA
*Private
;
3674 EFI_STRING StringPtr
;
3684 if (This
== NULL
|| BlockSize
== NULL
|| Progress
== NULL
) {
3685 return EFI_INVALID_PARAMETER
;
3688 *Progress
= ConfigResp
;
3689 if (ConfigResp
== NULL
) {
3690 return EFI_INVALID_PARAMETER
;
3693 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
3694 ASSERT (Private
!= NULL
);
3696 StringPtr
= ConfigResp
;
3697 BufferSize
= *BlockSize
;
3704 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
3705 *Progress
= StringPtr
;
3706 Status
= EFI_INVALID_PARAMETER
;
3709 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"PATH=", StrLen (L
"PATH=")) != 0) {
3712 if (*StringPtr
== 0) {
3713 *Progress
= StringPtr
;
3714 Status
= EFI_INVALID_PARAMETER
;
3718 while (*StringPtr
!= L
'&' && *StringPtr
!= 0) {
3721 if (*StringPtr
== 0) {
3722 *Progress
= StringPtr
;
3723 Status
= EFI_INVALID_PARAMETER
;
3732 // Parse each <ConfigElement> if exists
3733 // Only <BlockConfig> format is supported by this help function.
3734 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE='<Number>
3736 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"OFFSET=", StrLen (L
"OFFSET=")) == 0) {
3737 StringPtr
+= StrLen (L
"OFFSET=");
3741 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
3742 if (EFI_ERROR (Status
)) {
3743 *Progress
= ConfigResp
;
3750 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
3752 FreePool (TmpBuffer
);
3754 StringPtr
+= Length
;
3755 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
3756 *Progress
= StringPtr
- Length
- StrLen (L
"OFFSET=") - 1;
3757 Status
= EFI_INVALID_PARAMETER
;
3760 StringPtr
+= StrLen (L
"&WIDTH=");
3765 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
3766 if (EFI_ERROR (Status
)) {
3767 *Progress
= ConfigResp
;
3774 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
3776 FreePool (TmpBuffer
);
3778 StringPtr
+= Length
;
3779 if (StrnCmp (StringPtr
, L
"&VALUE=", StrLen (L
"&VALUE=")) != 0) {
3780 *Progress
= StringPtr
- Length
- StrLen (L
"&WIDTH=");
3781 Status
= EFI_INVALID_PARAMETER
;
3784 StringPtr
+= StrLen (L
"&VALUE=");
3789 Status
= GetValueOfNumber (StringPtr
, &Value
, &Length
);
3790 if (EFI_ERROR (Status
)) {
3791 *Progress
= ConfigResp
;
3795 StringPtr
+= Length
;
3796 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
3797 *Progress
= StringPtr
- Length
- 7;
3798 Status
= EFI_INVALID_PARAMETER
;
3803 // Update the Block with configuration info
3805 if ((Block
!= NULL
) && (Offset
+ Width
<= BufferSize
)) {
3806 CopyMem (Block
+ Offset
, Value
, Width
);
3808 if (Offset
+ Width
> MaxBlockSize
) {
3809 MaxBlockSize
= Offset
+ Width
;
3816 // If '\0', parsing is finished. Otherwise skip '&' to continue
3818 if (*StringPtr
== 0) {
3826 // The input string is ConfigAltResp format.
3828 if ((*StringPtr
!= 0) && (StrnCmp (StringPtr
, L
"&GUID=", StrLen (L
"&GUID=")) != 0)) {
3829 *Progress
= StringPtr
- 1;
3830 Status
= EFI_INVALID_PARAMETER
;
3834 *Progress
= StringPtr
+ StrLen (StringPtr
);
3835 *BlockSize
= MaxBlockSize
- 1;
3837 if (MaxBlockSize
> BufferSize
) {
3838 *BlockSize
= MaxBlockSize
;
3839 if (Block
!= NULL
) {
3840 return EFI_DEVICE_ERROR
;
3844 if (Block
== NULL
) {
3845 *Progress
= ConfigResp
;
3846 return EFI_INVALID_PARAMETER
;
3853 if (Value
!= NULL
) {
3861 This helper function is to be called by drivers to extract portions of
3862 a larger configuration string.
3864 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
3866 @param Configuration A null-terminated Unicode string in
3867 <MultiConfigAltResp> format.
3868 @param Guid A pointer to the GUID value to search for in the
3869 routing portion of the ConfigResp string when
3870 retrieving the requested data. If Guid is NULL,
3871 then all GUID values will be searched for.
3872 @param Name A pointer to the NAME value to search for in the
3873 routing portion of the ConfigResp string when
3874 retrieving the requested data. If Name is NULL,
3875 then all Name values will be searched for.
3876 @param DevicePath A pointer to the PATH value to search for in the
3877 routing portion of the ConfigResp string when
3878 retrieving the requested data. If DevicePath is
3879 NULL, then all DevicePath values will be searched
3881 @param AltCfgId A pointer to the ALTCFG value to search for in the
3882 routing portion of the ConfigResp string when
3883 retrieving the requested data. If this parameter
3884 is NULL, then the current setting will be
3886 @param AltCfgResp A pointer to a buffer which will be allocated by
3887 the function which contains the retrieved string
3888 as requested. This buffer is only allocated if
3889 the call was successful. It is <ConfigResp> format.
3891 @retval EFI_SUCCESS The request succeeded. The requested data was
3892 extracted and placed in the newly allocated
3894 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate AltCfgResp.
3895 @retval EFI_INVALID_PARAMETER Any parameter is invalid.
3896 @retval EFI_NOT_FOUND Target for the specified routing data was not
3903 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
3904 IN CONST EFI_STRING Configuration
,
3905 IN CONST EFI_GUID
*Guid
,
3906 IN CONST EFI_STRING Name
,
3907 IN CONST EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
3908 IN CONST UINT16
*AltCfgId
,
3909 OUT EFI_STRING
*AltCfgResp
3913 EFI_STRING StringPtr
;
3914 EFI_STRING HdrStart
;
3921 EFI_STRING AltIdStr
;
3938 if (This
== NULL
|| Configuration
== NULL
|| AltCfgResp
== NULL
) {
3939 return EFI_INVALID_PARAMETER
;
3942 StringPtr
= Configuration
;
3943 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
3944 return EFI_INVALID_PARAMETER
;
3948 // Generate the sub string for later matching.
3950 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*) Guid
, 1, &GuidStr
);
3953 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) DevicePath
),
3954 (VOID
*) DevicePath
,
3958 if (AltCfgId
!= NULL
) {
3959 GenerateSubStr (L
"ALTCFG=", sizeof (UINT16
), (VOID
*) AltCfgId
, 3, &AltIdStr
);
3962 GenerateSubStr (L
"NAME=", StrLen (Name
) * sizeof (CHAR16
), (VOID
*) Name
, 2, &NameStr
);
3964 GenerateSubStr (L
"NAME=", 0, NULL
, 2, &NameStr
);
3967 while (*StringPtr
!= 0) {
3969 // Try to match the GUID
3972 TmpPtr
= StrStr (StringPtr
, GuidStr
);
3973 if (TmpPtr
== NULL
) {
3974 Status
= EFI_NOT_FOUND
;
3980 // Jump to <NameHdr>
3983 StringPtr
= TmpPtr
+ StrLen (GuidStr
);
3985 StringPtr
= StrStr (TmpPtr
, L
"NAME=");
3986 if (StringPtr
== NULL
) {
3987 Status
= EFI_NOT_FOUND
;
3995 // Try to match the NAME
3997 if (GuidFlag
&& !NameFlag
) {
3998 if (StrnCmp (StringPtr
, NameStr
, StrLen (NameStr
)) != 0) {
4002 // Jump to <PathHdr>
4005 StringPtr
+= StrLen (NameStr
);
4007 StringPtr
= StrStr (StringPtr
, L
"PATH=");
4008 if (StringPtr
== NULL
) {
4009 Status
= EFI_NOT_FOUND
;
4018 // Try to match the DevicePath
4020 if (GuidFlag
&& NameFlag
&& !PathFlag
) {
4021 if (StrnCmp (StringPtr
, PathStr
, StrLen (PathStr
)) != 0) {
4026 // Jump to '&' before <DescHdr> or <ConfigBody>
4028 if (DevicePath
!= NULL
) {
4029 StringPtr
+= StrLen (PathStr
);
4031 StringPtr
= StrStr (StringPtr
, L
"&");
4032 if (StringPtr
== NULL
) {
4033 Status
= EFI_NOT_FOUND
;
4044 // Try to match the AltCfgId
4046 if (GuidFlag
&& NameFlag
&& PathFlag
) {
4047 if (AltCfgId
== NULL
) {
4049 // Return Current Setting when AltCfgId is NULL.
4051 Status
= OutputConfigBody (StringPtr
, &Result
);
4055 // Search the <ConfigAltResp> to get the <AltResp> with AltCfgId.
4057 if (StrnCmp (StringPtr
, AltIdStr
, StrLen (AltIdStr
)) != 0) {
4063 // Skip AltIdStr and &
4065 StringPtr
= StringPtr
+ StrLen (AltIdStr
);
4066 Status
= OutputConfigBody (StringPtr
, &Result
);
4072 Status
= EFI_NOT_FOUND
;
4076 if (!EFI_ERROR (Status
) && (Result
!= NULL
)) {
4078 // Copy the <ConfigHdr> and <ConfigBody>
4080 Length
= HdrEnd
- HdrStart
+ StrLen (Result
) + 1;
4081 *AltCfgResp
= AllocateZeroPool (Length
* sizeof (CHAR16
));
4082 if (*AltCfgResp
== NULL
) {
4083 Status
= EFI_OUT_OF_RESOURCES
;
4085 StrnCpy (*AltCfgResp
, HdrStart
, HdrEnd
- HdrStart
);
4086 StrCat (*AltCfgResp
, Result
);
4087 Status
= EFI_SUCCESS
;
4091 if (GuidStr
!= NULL
) {
4094 if (NameStr
!= NULL
) {
4097 if (PathStr
!= NULL
) {
4100 if (AltIdStr
!= NULL
) {
4101 FreePool (AltIdStr
);
4103 if (Result
!= NULL
) {