2 Implementation of interfaces function for EFI_HII_CONFIG_ROUTING_PROTOCOL.
4 Copyright (c) 2007 - 2011, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 #include "HiiDatabase.h"
17 extern HII_DATABASE_PRIVATE_DATA mPrivate
;
20 Calculate the number of Unicode characters of the incoming Configuration string,
21 not including NULL terminator.
23 This is a internal function.
25 @param String String in <MultiConfigRequest> or
26 <MultiConfigResp> format.
28 @return The number of Unicode characters.
32 CalculateConfigStringLen (
39 // "GUID=" should be the first element of incoming string.
41 ASSERT (String
!= NULL
);
42 ASSERT (StrnCmp (String
, L
"GUID=", StrLen (L
"GUID=")) == 0);
45 // The beginning of next <ConfigRequest>/<ConfigResp> should be "&GUID=".
46 // Will meet '\0' if there is only one <ConfigRequest>/<ConfigResp>.
48 TmpPtr
= StrStr (String
, L
"&GUID=");
50 return StrLen (String
);
53 return (TmpPtr
- String
);
58 Convert the hex UNICODE %02x encoding of a UEFI device path to binary
59 from <PathHdr> of <ConfigHdr>.
61 This is a internal function.
63 @param String UEFI configuration string
64 @param DevicePathData Binary of a UEFI device path.
66 @retval EFI_NOT_FOUND The device path is not invalid.
67 @retval EFI_INVALID_PARAMETER Any incoming parameter is invalid.
68 @retval EFI_OUT_OF_RESOURCES Lake of resources to store neccesary structures.
69 @retval EFI_SUCCESS The device path is retrieved and translated to
76 OUT UINT8
**DevicePathData
81 UINT8
*DevicePathBuffer
;
85 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
88 if (String
== NULL
|| DevicePathData
== NULL
) {
89 return EFI_INVALID_PARAMETER
;
93 // Find the 'PATH=' of <PathHdr> and skip it.
95 for (; (*String
!= 0 && StrnCmp (String
, L
"PATH=", StrLen (L
"PATH=")) != 0); String
++);
97 return EFI_INVALID_PARAMETER
;
100 // Check whether path data does exist.
102 String
+= StrLen (L
"PATH=");
104 return EFI_INVALID_PARAMETER
;
109 // The content between 'PATH=' of <ConfigHdr> and '&' of next element
110 // or '\0' (end of configuration string) is the UNICODE %02x bytes encoding
111 // of UEFI device path.
113 for (Length
= 0; *String
!= 0 && *String
!= L
'&'; String
++, Length
++);
115 // Check DevicePath Length
117 if (((Length
+ 1) / 2) < sizeof (EFI_DEVICE_PATH_PROTOCOL
)) {
118 return EFI_NOT_FOUND
;
122 // The data in <PathHdr> is encoded as hex UNICODE %02x bytes in the same order
123 // as the device path resides in RAM memory.
124 // Translate the data into binary.
126 DevicePathBuffer
= (UINT8
*) AllocateZeroPool ((Length
+ 1) / 2);
127 if (DevicePathBuffer
== NULL
) {
128 return EFI_OUT_OF_RESOURCES
;
132 // Convert DevicePath
134 ZeroMem (TemStr
, sizeof (TemStr
));
135 for (Index
= 0; Index
< Length
; Index
++) {
136 TemStr
[0] = PathHdr
[Index
];
137 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
138 if ((Index
& 1) == 0) {
139 DevicePathBuffer
[Index
/2] = DigitUint8
;
141 DevicePathBuffer
[Index
/2] = (UINT8
) ((DevicePathBuffer
[Index
/2] << 4) + DigitUint8
);
146 // Validate DevicePath
148 DevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) DevicePathBuffer
;
149 while (!IsDevicePathEnd (DevicePath
)) {
150 if ((DevicePath
->Type
== 0) || (DevicePath
->SubType
== 0) || (DevicePathNodeLength (DevicePath
) < sizeof (EFI_DEVICE_PATH_PROTOCOL
))) {
152 // Invalid device path
154 FreePool (DevicePathBuffer
);
155 return EFI_NOT_FOUND
;
157 DevicePath
= NextDevicePathNode (DevicePath
);
161 // return the device path
163 *DevicePathData
= DevicePathBuffer
;
168 Converts the unicode character of the string from uppercase to lowercase.
169 This is a internal function.
171 @param ConfigString String to be converted
177 IN EFI_STRING ConfigString
183 ASSERT (ConfigString
!= NULL
);
186 // Convert all hex digits in range [A-F] in the configuration header to [a-f]
188 for (String
= ConfigString
, Lower
= FALSE
; *String
!= L
'\0'; String
++) {
189 if (*String
== L
'=') {
191 } else if (*String
== L
'&') {
193 } else if (Lower
&& *String
>= L
'A' && *String
<= L
'F') {
194 *String
= (CHAR16
) (*String
- L
'A' + L
'a');
202 Generate a sub string then output it.
204 This is a internal function.
206 @param String A constant string which is the prefix of the to be
207 generated string, e.g. GUID=
209 @param BufferLen The length of the Buffer in bytes.
211 @param Buffer Points to a buffer which will be converted to be the
212 content of the generated string.
214 @param Flag If 1, the buffer contains data for the value of GUID or PATH stored in
215 UINT8 *; if 2, the buffer contains unicode string for the value of NAME;
216 if 3, the buffer contains other data.
218 @param SubStr Points to the output string. It's caller's
219 responsibility to free this buffer.
225 IN CONST EFI_STRING String
,
229 OUT EFI_STRING
*SubStr
234 EFI_STRING StringHeader
;
240 ASSERT (String
!= NULL
&& SubStr
!= NULL
);
242 if (Buffer
== NULL
) {
243 *SubStr
= AllocateCopyPool (StrSize (String
), String
);
244 ASSERT (*SubStr
!= NULL
);
249 // Header + Data + '&' + '\0'
251 Length
= StrLen (String
) + BufferLen
* 2 + 1 + 1;
252 Str
= AllocateZeroPool (Length
* sizeof (CHAR16
));
253 ASSERT (Str
!= NULL
);
255 StrCpy (Str
, String
);
256 Length
= (BufferLen
* 2 + 1) * sizeof (CHAR16
);
258 StringHeader
= Str
+ StrLen (String
);
259 TemString
= (CHAR16
*) StringHeader
;
264 // Convert Buffer to Hex String in reverse order
266 TemBuffer
= ((UINT8
*) Buffer
);
267 for (Index
= 0; Index
< BufferLen
; Index
++, TemBuffer
++) {
268 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
273 // Check buffer is enough
275 TemName
= (CHAR16
*) Buffer
;
276 ASSERT ((BufferLen
* 2 + 1) >= (StrLen (TemName
) * 4 + 1));
278 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
280 for (; *TemName
!= L
'\0'; TemName
++) {
281 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemName
, 4);
286 // Convert Buffer to Hex String
288 TemBuffer
= ((UINT8
*) Buffer
) + BufferLen
- 1;
289 for (Index
= 0; Index
< BufferLen
; Index
++, TemBuffer
--) {
290 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
298 // Convert the uppercase to lowercase since <HexAf> is defined in lowercase format.
308 Retrieve the <ConfigBody> from String then output it.
310 This is a internal function.
312 @param String A sub string of a configuration string in
313 <MultiConfigAltResp> format.
314 @param ConfigBody Points to the output string. It's caller's
315 responsibility to free this buffer.
317 @retval EFI_INVALID_PARAMETER There is no form package in current hii database.
318 @retval EFI_OUT_OF_RESOURCES Not enough memory to finish this operation.
319 @retval EFI_SUCCESS All existing storage is exported.
324 IN EFI_STRING String
,
325 OUT EFI_STRING
*ConfigBody
332 if (String
== NULL
|| ConfigBody
== NULL
) {
333 return EFI_INVALID_PARAMETER
;
337 // The setting information should start OFFSET, not ALTCFG.
339 if (StrnCmp (String
, L
"&ALTCFG=", StrLen (L
"&ALTCFG=")) == 0) {
340 return EFI_INVALID_PARAMETER
;
343 TmpPtr
= StrStr (String
, L
"GUID=");
344 if (TmpPtr
== NULL
) {
346 // It is the last <ConfigResp> of the incoming configuration string.
348 Result
= AllocateCopyPool (StrSize (String
), String
);
349 if (Result
== NULL
) {
350 return EFI_OUT_OF_RESOURCES
;
352 *ConfigBody
= Result
;
357 Length
= TmpPtr
- String
;
358 Result
= AllocateCopyPool (Length
* sizeof (CHAR16
), String
);
359 if (Result
== NULL
) {
360 return EFI_OUT_OF_RESOURCES
;
363 *(Result
+ Length
- 1) = 0;
364 *ConfigBody
= Result
;
369 Append a string to a multi-string format.
371 This is a internal function.
373 @param MultiString String in <MultiConfigRequest>,
374 <MultiConfigAltResp>, or <MultiConfigResp>. On
375 input, the buffer length of this string is
376 MAX_STRING_LENGTH. On output, the buffer length
378 @param AppendString NULL-terminated Unicode string.
380 @retval EFI_INVALID_PARAMETER Any incoming parameter is invalid.
381 @retval EFI_SUCCESS AppendString is append to the end of MultiString
385 AppendToMultiString (
386 IN OUT EFI_STRING
*MultiString
,
387 IN EFI_STRING AppendString
390 UINTN AppendStringSize
;
391 UINTN MultiStringSize
;
393 if (MultiString
== NULL
|| *MultiString
== NULL
|| AppendString
== NULL
) {
394 return EFI_INVALID_PARAMETER
;
397 AppendStringSize
= StrSize (AppendString
);
398 MultiStringSize
= StrSize (*MultiString
);
401 // Enlarge the buffer each time when length exceeds MAX_STRING_LENGTH.
403 if (MultiStringSize
+ AppendStringSize
> MAX_STRING_LENGTH
||
404 MultiStringSize
> MAX_STRING_LENGTH
) {
405 *MultiString
= (EFI_STRING
) ReallocatePool (
407 MultiStringSize
+ AppendStringSize
,
408 (VOID
*) (*MultiString
)
410 ASSERT (*MultiString
!= NULL
);
413 // Append the incoming string
415 StrCat (*MultiString
, AppendString
);
422 Get the value of <Number> in <BlockConfig> format, i.e. the value of OFFSET
424 <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>
426 This is a internal function.
428 @param StringPtr String in <BlockConfig> format and points to the
429 first character of <Number>.
430 @param Number The output value. Caller takes the responsibility
432 @param Len Length of the <Number>, in characters.
434 @retval EFI_OUT_OF_RESOURCES Insufficient resources to store neccessary
436 @retval EFI_SUCCESS Value of <Number> is outputted in Number
442 IN EFI_STRING StringPtr
,
456 if (StringPtr
== NULL
|| *StringPtr
== L
'\0' || Number
== NULL
|| Len
== NULL
) {
457 return EFI_INVALID_PARAMETER
;
463 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
466 *Len
= StringPtr
- TmpPtr
;
469 Str
= (EFI_STRING
) AllocateZeroPool (Length
* sizeof (CHAR16
));
471 Status
= EFI_OUT_OF_RESOURCES
;
474 CopyMem (Str
, TmpPtr
, *Len
* sizeof (CHAR16
));
475 *(Str
+ *Len
) = L
'\0';
477 Length
= (Length
+ 1) / 2;
478 Buf
= (UINT8
*) AllocateZeroPool (Length
);
480 Status
= EFI_OUT_OF_RESOURCES
;
485 ZeroMem (TemStr
, sizeof (TemStr
));
486 for (Index
= 0; Index
< Length
; Index
++) {
487 TemStr
[0] = Str
[Length
- Index
- 1];
488 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
489 if ((Index
& 1) == 0) {
490 Buf
[Index
/2] = DigitUint8
;
492 Buf
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Buf
[Index
/2]);
497 Status
= EFI_SUCCESS
;
508 This function merges DefaultAltCfgResp string into AltCfgResp string for
509 the missing AltCfgId in AltCfgResq.
511 @param AltCfgResp Pointer to a null-terminated Unicode string in
512 <ConfigAltResp> format. The default value string
513 will be merged into it.
514 @param DefaultAltCfgResp Pointer to a null-terminated Unicode string in
515 <MultiConfigAltResp> format. The default value
516 string may contain more than one ConfigAltResp
517 string for the different varstore buffer.
519 @retval EFI_SUCCESS The merged string returns.
520 @retval EFI_INVALID_PARAMETER *AltCfgResp is to NULL.
525 IN OUT EFI_STRING
*AltCfgResp
,
526 IN EFI_STRING DefaultAltCfgResp
529 EFI_STRING StringPtrDefault
;
530 EFI_STRING StringPtrEnd
;
532 EFI_STRING StringPtr
;
533 EFI_STRING AltConfigHdr
;
535 UINTN SizeAltCfgResp
;
537 if (*AltCfgResp
== NULL
) {
538 return EFI_INVALID_PARAMETER
;
542 // Get the requestr ConfigHdr
545 StringPtr
= *AltCfgResp
;
548 // Find <ConfigHdr> GUID=...&NAME=...&PATH=...
550 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
551 return EFI_INVALID_PARAMETER
;
553 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&NAME=", StrLen (L
"&NAME=")) != 0) {
556 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&PATH=", StrLen (L
"&PATH=")) != 0) {
559 if (*StringPtr
== L
'\0') {
560 return EFI_INVALID_PARAMETER
;
562 StringPtr
+= StrLen (L
"&PATH=");
563 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
566 HeaderLength
= StringPtr
- *AltCfgResp
;
569 // Construct AltConfigHdr string "&<ConfigHdr>&ALTCFG=XXXX\0"
570 // |1| StrLen (ConfigHdr) | 8 | 4 | 1 |
572 AltConfigHdr
= AllocateZeroPool ((1 + HeaderLength
+ 8 + 4 + 1) * sizeof (CHAR16
));
573 if (AltConfigHdr
== NULL
) {
574 return EFI_OUT_OF_RESOURCES
;
576 StrCpy (AltConfigHdr
, L
"&");
577 StrnCat (AltConfigHdr
, *AltCfgResp
, HeaderLength
);
578 StrCat (AltConfigHdr
, L
"&ALTCFG=");
579 HeaderLength
= StrLen (AltConfigHdr
);
581 StringPtrDefault
= StrStr (DefaultAltCfgResp
, AltConfigHdr
);
582 while (StringPtrDefault
!= NULL
) {
586 StrnCat (AltConfigHdr
, StringPtrDefault
+ HeaderLength
, 4);
587 StringPtr
= StrStr (*AltCfgResp
, AltConfigHdr
);
590 // Append the found default value string to the input AltCfgResp
592 if (StringPtr
== NULL
) {
593 StringPtrEnd
= StrStr (StringPtrDefault
+ 1, L
"&GUID");
594 SizeAltCfgResp
= StrSize (*AltCfgResp
);
595 if (StringPtrEnd
== NULL
) {
597 // No more default string is found.
599 *AltCfgResp
= (EFI_STRING
) ReallocatePool (
601 SizeAltCfgResp
+ StrSize (StringPtrDefault
),
602 (VOID
*) (*AltCfgResp
)
604 if (*AltCfgResp
== NULL
) {
605 FreePool (AltConfigHdr
);
606 return EFI_OUT_OF_RESOURCES
;
608 StrCat (*AltCfgResp
, StringPtrDefault
);
611 TempChar
= *StringPtrEnd
;
612 *StringPtrEnd
= L
'\0';
613 *AltCfgResp
= (EFI_STRING
) ReallocatePool (
615 SizeAltCfgResp
+ StrSize (StringPtrDefault
),
616 (VOID
*) (*AltCfgResp
)
618 if (*AltCfgResp
== NULL
) {
619 FreePool (AltConfigHdr
);
620 return EFI_OUT_OF_RESOURCES
;
622 StrCat (*AltCfgResp
, StringPtrDefault
);
623 *StringPtrEnd
= TempChar
;
628 // Find next AltCfg String
630 *(AltConfigHdr
+ HeaderLength
) = L
'\0';
631 StringPtrDefault
= StrStr (StringPtrDefault
+ 1, AltConfigHdr
);
634 FreePool (AltConfigHdr
);
639 This function inserts new DefaultValueData into the BlockData DefaultValue array.
641 @param BlockData The BlockData is updated to add new default value.
642 @param DefaultValueData The DefaultValue is added.
647 IN IFR_BLOCK_DATA
*BlockData
,
648 IN IFR_DEFAULT_DATA
*DefaultValueData
652 IFR_DEFAULT_DATA
*DefaultValueArray
;
654 for (Link
= BlockData
->DefaultValueEntry
.ForwardLink
; Link
!= &BlockData
->DefaultValueEntry
; Link
= Link
->ForwardLink
) {
655 DefaultValueArray
= BASE_CR (Link
, IFR_DEFAULT_DATA
, Entry
);
656 if (DefaultValueArray
->DefaultId
== DefaultValueData
->DefaultId
) {
657 if (DefaultValueData
->OpCode
== EFI_IFR_DEFAULT_OP
) {
659 // Update the default value array in BlockData.
661 DefaultValueArray
->Value
= DefaultValueData
->Value
;
662 } else if (DefaultValueArray
->OpCode
!= EFI_IFR_DEFAULT_OP
) {
664 // Update the default value array in BlockData.
666 DefaultValueArray
->Value
= DefaultValueData
->Value
;
668 FreePool (DefaultValueData
);
670 } else if (DefaultValueArray
->DefaultId
> DefaultValueData
->DefaultId
) {
672 // Insert new default value data in the front of this default value array.
674 InsertTailList (Link
, &DefaultValueData
->Entry
);
680 // Insert new default value data in tail.
682 InsertTailList (Link
, &DefaultValueData
->Entry
);
687 This function inserts new BlockData into the block link
689 @param BlockLink The list entry points to block array.
690 @param BlockData The point to BlockData is added.
695 IN LIST_ENTRY
*BlockLink
,
696 IN IFR_BLOCK_DATA
**BlockData
700 IFR_BLOCK_DATA
*BlockArray
;
701 IFR_BLOCK_DATA
*BlockSingleData
;
703 BlockSingleData
= *BlockData
;
706 // Insert block data in its Offset and Width order.
708 for (Link
= BlockLink
->ForwardLink
; Link
!= BlockLink
; Link
= Link
->ForwardLink
) {
709 BlockArray
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
710 if (BlockArray
->Offset
== BlockSingleData
->Offset
) {
711 if (BlockArray
->Width
> BlockSingleData
->Width
) {
713 // Insert this block data in the front of block array
715 InsertTailList (Link
, &BlockSingleData
->Entry
);
719 if (BlockArray
->Width
== BlockSingleData
->Width
) {
721 // The same block array has been added.
723 FreePool (BlockSingleData
);
724 *BlockData
= BlockArray
;
727 } else if (BlockArray
->Offset
> BlockSingleData
->Offset
) {
729 // Insert new block data in the front of block array
731 InsertTailList (Link
, &BlockSingleData
->Entry
);
737 // Add new block data into the tail.
739 InsertTailList (Link
, &BlockSingleData
->Entry
);
744 This function checks VarOffset and VarWidth is in the block range.
746 @param RequestBlockArray The block array is to be checked.
747 @param VarOffset Offset of var to the structure
748 @param VarWidth Width of var.
750 @retval TRUE This Var is in the block range.
751 @retval FALSE This Var is not in the block range.
755 IN IFR_BLOCK_DATA
*RequestBlockArray
,
761 IFR_BLOCK_DATA
*BlockData
;
764 // No Request Block array, all vars are got.
766 if (RequestBlockArray
== NULL
) {
771 // Check the input var is in the request block range.
773 for (Link
= RequestBlockArray
->Entry
.ForwardLink
; Link
!= &RequestBlockArray
->Entry
; Link
= Link
->ForwardLink
) {
774 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
775 if ((VarOffset
>= BlockData
->Offset
) && ((VarOffset
+ VarWidth
) <= (BlockData
->Offset
+ BlockData
->Width
))) {
784 Get form package data from data base.
786 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
787 @param HiiFormPackage The buffer saves the package data.
788 @param PackageSize The buffer size of the package data.
793 IN HII_DATABASE_RECORD
*DataBaseRecord
,
794 IN OUT UINT8
**HiiFormPackage
,
795 OUT UINTN
*PackageSize
802 if (DataBaseRecord
== NULL
|| HiiFormPackage
== NULL
|| PackageSize
== NULL
) {
803 return EFI_INVALID_PARAMETER
;
809 // 0. Get Hii Form Package by HiiHandle
811 Status
= ExportFormPackages (
813 DataBaseRecord
->Handle
,
814 DataBaseRecord
->PackageList
,
820 if (EFI_ERROR (Status
)) {
824 (*HiiFormPackage
) = AllocatePool (ResultSize
);
825 if (*HiiFormPackage
== NULL
) {
826 Status
= EFI_OUT_OF_RESOURCES
;
831 // Get HiiFormPackage by HiiHandle
835 Status
= ExportFormPackages (
837 DataBaseRecord
->Handle
,
838 DataBaseRecord
->PackageList
,
844 if (EFI_ERROR (Status
)) {
845 FreePool (*HiiFormPackage
);
855 This function parses Form Package to get the efi varstore info according to the request ConfigHdr.
857 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
858 @param ConfigHdr Request string ConfigHdr. If it is NULL,
859 the first found varstore will be as ConfigHdr.
860 @param IsEfiVarstore Whether the request storage type is efi varstore type.
861 @param EfiVarStore The efi varstore info which will return.
865 IN HII_DATABASE_RECORD
*DataBaseRecord
,
866 IN EFI_STRING ConfigHdr
,
867 OUT BOOLEAN
*IsEfiVarstore
,
868 OUT EFI_IFR_VARSTORE_EFI
**EfiVarStore
874 EFI_IFR_OP_HEADER
*IfrOpHdr
;
875 CHAR16
*VarStoreName
;
880 UINT8
*HiiFormPackage
;
882 EFI_IFR_VARSTORE_EFI
*IfrEfiVarStore
;
884 HiiFormPackage
= NULL
;
886 Status
= EFI_SUCCESS
;
891 Status
= GetFormPackageData(DataBaseRecord
, &HiiFormPackage
, &PackageSize
);
892 if (EFI_ERROR (Status
)) {
896 IfrOffset
= sizeof (EFI_HII_PACKAGE_HEADER
);
897 while (IfrOffset
< PackageSize
) {
898 IfrOpHdr
= (EFI_IFR_OP_HEADER
*) (HiiFormPackage
+ IfrOffset
);
899 IfrOffset
+= IfrOpHdr
->Length
;
901 if (IfrOpHdr
->OpCode
== EFI_IFR_VARSTORE_EFI_OP
) {
902 IfrEfiVarStore
= (EFI_IFR_VARSTORE_EFI
*) IfrOpHdr
;
904 // If the length is small than the structure, this is from old efi
905 // varstore definition. Old efi varstore get config directly from
906 // GetVariable function.
908 if (IfrOpHdr
->Length
< sizeof (EFI_IFR_VARSTORE_EFI
)) {
912 VarStoreName
= AllocateZeroPool (AsciiStrSize ((CHAR8
*)IfrEfiVarStore
->Name
) * sizeof (CHAR16
));
913 if (VarStoreName
== NULL
) {
914 Status
= EFI_OUT_OF_RESOURCES
;
917 AsciiStrToUnicodeStr ((CHAR8
*) IfrEfiVarStore
->Name
, VarStoreName
);
919 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*) &IfrEfiVarStore
->Guid
, 1, &GuidStr
);
920 GenerateSubStr (L
"NAME=", StrLen (VarStoreName
) * sizeof (CHAR16
), (VOID
*) VarStoreName
, 2, &NameStr
);
921 LengthString
= StrLen (GuidStr
);
922 LengthString
= LengthString
+ StrLen (NameStr
) + 1;
923 TempStr
= AllocateZeroPool (LengthString
* sizeof (CHAR16
));
924 if (TempStr
== NULL
) {
927 FreePool (VarStoreName
);
928 Status
= EFI_OUT_OF_RESOURCES
;
931 StrCpy (TempStr
, GuidStr
);
932 StrCat (TempStr
, NameStr
);
933 if (ConfigHdr
== NULL
|| StrnCmp (ConfigHdr
, TempStr
, StrLen (TempStr
)) == 0) {
934 *EfiVarStore
= (EFI_IFR_VARSTORE_EFI
*) AllocateZeroPool (IfrOpHdr
->Length
);
935 if (*EfiVarStore
== NULL
) {
936 FreePool (VarStoreName
);
940 Status
= EFI_OUT_OF_RESOURCES
;
943 *IsEfiVarstore
= TRUE
;
944 CopyMem (*EfiVarStore
, IfrEfiVarStore
, IfrOpHdr
->Length
);
948 // Free alllocated temp string.
950 FreePool (VarStoreName
);
957 if (HiiFormPackage
!= NULL
) {
958 FreePool (HiiFormPackage
);
965 This function parses Form Package to get the block array and the default
966 value array according to the request ConfigHdr.
968 @param Package Pointer to the form package data.
969 @param PackageLength Length of the pacakge.
970 @param ConfigHdr Request string ConfigHdr. If it is NULL,
971 the first found varstore will be as ConfigHdr.
972 @param RequestBlockArray The block array is retrieved from the request string.
973 @param VarStorageData VarStorage structure contains the got block and default value.
974 @param PIfrDefaultIdArray Point to the got default id and default name array.
976 @retval EFI_SUCCESS The block array and the default value array are got.
977 @retval EFI_INVALID_PARAMETER The varstore defintion in the differnt form pacakges
979 @retval EFI_OUT_OF_RESOURCES No enough memory.
985 IN UINT32 PackageLength
,
986 IN EFI_STRING ConfigHdr
,
987 IN IFR_BLOCK_DATA
*RequestBlockArray
,
988 IN OUT IFR_VARSTORAGE_DATA
*VarStorageData
,
989 OUT IFR_DEFAULT_DATA
*DefaultIdArray
994 EFI_IFR_VARSTORE
*IfrVarStore
;
995 EFI_IFR_VARSTORE_EFI
*IfrEfiVarStore
;
996 EFI_IFR_OP_HEADER
*IfrOpHdr
;
997 EFI_IFR_ONE_OF
*IfrOneOf
;
998 EFI_IFR_ONE_OF_OPTION
*IfrOneOfOption
;
999 EFI_IFR_DEFAULT
*IfrDefault
;
1000 EFI_IFR_ORDERED_LIST
*IfrOrderedList
;
1001 EFI_IFR_CHECKBOX
*IfrCheckBox
;
1002 EFI_IFR_PASSWORD
*IfrPassword
;
1003 EFI_IFR_STRING
*IfrString
;
1004 IFR_DEFAULT_DATA
*DefaultData
;
1005 IFR_BLOCK_DATA
*BlockData
;
1006 CHAR16
*VarStoreName
;
1009 UINT16 VarDefaultId
;
1014 BOOLEAN FirstOneOfOption
;
1017 Status
= EFI_SUCCESS
;
1023 FirstOneOfOption
= FALSE
;
1026 // Go through the form package to parse OpCode one by one.
1028 IfrOffset
= sizeof (EFI_HII_PACKAGE_HEADER
);
1029 while (IfrOffset
< PackageLength
) {
1030 IfrOpHdr
= (EFI_IFR_OP_HEADER
*) (Package
+ IfrOffset
);
1032 switch (IfrOpHdr
->OpCode
) {
1033 case EFI_IFR_VARSTORE_OP
:
1035 // VarStore is found. Don't need to search any more.
1037 if (VarStorageData
->Size
!= 0) {
1042 // Get the requied varstore information
1043 // Add varstore by Guid and Name in ConfigHdr
1044 // Make sure Offset is in varstore size and varstoreid
1046 IfrVarStore
= (EFI_IFR_VARSTORE
*) IfrOpHdr
;
1047 VarStoreName
= AllocateZeroPool (AsciiStrSize ((CHAR8
*)IfrVarStore
->Name
) * sizeof (CHAR16
));
1048 if (VarStoreName
== NULL
) {
1049 Status
= EFI_OUT_OF_RESOURCES
;
1052 AsciiStrToUnicodeStr ((CHAR8
*) IfrVarStore
->Name
, VarStoreName
);
1054 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*) &IfrVarStore
->Guid
, 1, &GuidStr
);
1055 GenerateSubStr (L
"NAME=", StrLen (VarStoreName
) * sizeof (CHAR16
), (VOID
*) VarStoreName
, 2, &NameStr
);
1056 LengthString
= StrLen (GuidStr
);
1057 LengthString
= LengthString
+ StrLen (NameStr
) + 1;
1058 TempStr
= AllocateZeroPool (LengthString
* sizeof (CHAR16
));
1059 if (TempStr
== NULL
) {
1062 FreePool (VarStoreName
);
1063 Status
= EFI_OUT_OF_RESOURCES
;
1066 StrCpy (TempStr
, GuidStr
);
1067 StrCat (TempStr
, NameStr
);
1068 if (ConfigHdr
== NULL
|| StrnCmp (ConfigHdr
, TempStr
, StrLen (TempStr
)) == 0) {
1070 // Find the matched VarStore
1072 CopyGuid (&VarStorageData
->Guid
, (EFI_GUID
*) (VOID
*) &IfrVarStore
->Guid
);
1073 VarStorageData
->VarStoreId
= IfrVarStore
->VarStoreId
;
1074 VarStorageData
->Size
= IfrVarStore
->Size
;
1075 VarStorageData
->Name
= VarStoreName
;
1078 // No found, free the allocated memory
1080 FreePool (VarStoreName
);
1083 // Free alllocated temp string.
1090 case EFI_IFR_VARSTORE_EFI_OP
:
1092 // VarStore is found. Don't need to search any more.
1094 if (VarStorageData
->Size
!= 0) {
1099 // Get the requied varstore information
1100 // Add varstore by Guid and Name in ConfigHdr
1101 // Make sure Offset is in varstore size and varstoreid
1103 IfrEfiVarStore
= (EFI_IFR_VARSTORE_EFI
*) IfrOpHdr
;
1106 // If the length is small than the structure, this is from old efi
1107 // varstore definition. Old efi varstore get config directly from
1108 // GetVariable function.
1110 if (IfrOpHdr
->Length
< sizeof (EFI_IFR_VARSTORE_EFI
)) {
1114 VarStoreName
= AllocateZeroPool (AsciiStrSize ((CHAR8
*)IfrEfiVarStore
->Name
) * sizeof (CHAR16
));
1115 if (VarStoreName
== NULL
) {
1116 Status
= EFI_OUT_OF_RESOURCES
;
1119 AsciiStrToUnicodeStr ((CHAR8
*) IfrEfiVarStore
->Name
, VarStoreName
);
1121 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*) &IfrEfiVarStore
->Guid
, 1, &GuidStr
);
1122 GenerateSubStr (L
"NAME=", StrLen (VarStoreName
) * sizeof (CHAR16
), (VOID
*) VarStoreName
, 2, &NameStr
);
1123 LengthString
= StrLen (GuidStr
);
1124 LengthString
= LengthString
+ StrLen (NameStr
) + 1;
1125 TempStr
= AllocateZeroPool (LengthString
* sizeof (CHAR16
));
1126 if (TempStr
== NULL
) {
1129 FreePool (VarStoreName
);
1130 Status
= EFI_OUT_OF_RESOURCES
;
1133 StrCpy (TempStr
, GuidStr
);
1134 StrCat (TempStr
, NameStr
);
1135 if (ConfigHdr
== NULL
|| StrnCmp (ConfigHdr
, TempStr
, StrLen (TempStr
)) == 0) {
1137 // Find the matched VarStore
1139 CopyGuid (&VarStorageData
->Guid
, (EFI_GUID
*) (VOID
*) &IfrEfiVarStore
->Guid
);
1140 VarStorageData
->VarStoreId
= IfrEfiVarStore
->VarStoreId
;
1141 VarStorageData
->Size
= IfrEfiVarStore
->Size
;
1142 VarStorageData
->Name
= VarStoreName
;
1145 // No found, free the allocated memory
1147 FreePool (VarStoreName
);
1150 // Free alllocated temp string.
1157 case EFI_IFR_DEFAULTSTORE_OP
:
1159 // Add new the map between default id and default name.
1161 DefaultData
= (IFR_DEFAULT_DATA
*) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
1162 if (DefaultData
== NULL
) {
1163 Status
= EFI_OUT_OF_RESOURCES
;
1166 DefaultData
->DefaultId
= ((EFI_IFR_DEFAULTSTORE
*) IfrOpHdr
)->DefaultId
;
1167 InsertTailList (&DefaultIdArray
->Entry
, &DefaultData
->Entry
);
1171 case EFI_IFR_FORM_OP
:
1172 case EFI_IFR_FORM_MAP_OP
:
1174 // No matched varstore is found and directly return.
1176 if (VarStorageData
->Size
== 0) {
1177 Status
= EFI_SUCCESS
;
1182 case EFI_IFR_ONE_OF_OP
:
1183 case EFI_IFR_NUMERIC_OP
:
1185 // Numeric and OneOf has the same opcode structure.
1189 // Numeric and OneOf question is not in IFR Form. This IFR form is not valid.
1191 if (VarStorageData
->Size
== 0) {
1192 Status
= EFI_INVALID_PARAMETER
;
1196 // Check whether this question is for the requested varstore.
1198 IfrOneOf
= (EFI_IFR_ONE_OF
*) IfrOpHdr
;
1199 if (IfrOneOf
->Question
.VarStoreId
!= VarStorageData
->VarStoreId
) {
1204 // Get Offset/Width by Question header and OneOf Flags
1206 VarOffset
= IfrOneOf
->Question
.VarStoreInfo
.VarOffset
;
1207 VarWidth
= (UINT16
) (1 << (IfrOneOf
->Flags
& EFI_IFR_NUMERIC_SIZE
));
1209 // Check whether this question is in requested block array.
1211 if (!BlockArrayCheck (RequestBlockArray
, VarOffset
, VarWidth
)) {
1213 // This question is not in the requested string. Skip it.
1219 // Check this var question is in the var storage
1221 if ((VarOffset
+ VarWidth
) > VarStorageData
->Size
) {
1222 Status
= EFI_INVALID_PARAMETER
;
1229 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
1230 if (BlockData
== NULL
) {
1231 Status
= EFI_OUT_OF_RESOURCES
;
1234 BlockData
->Offset
= VarOffset
;
1235 BlockData
->Width
= VarWidth
;
1236 BlockData
->QuestionId
= IfrOneOf
->Question
.QuestionId
;
1237 BlockData
->OpCode
= IfrOpHdr
->OpCode
;
1238 BlockData
->Scope
= IfrOpHdr
->Scope
;
1239 InitializeListHead (&BlockData
->DefaultValueEntry
);
1241 // Add Block Data into VarStorageData BlockEntry
1243 InsertBlockData (&VarStorageData
->BlockEntry
, &BlockData
);
1245 if (IfrOpHdr
->OpCode
== EFI_IFR_ONE_OF_OP
) {
1247 // Set this flag to TRUE for the first oneof option.
1249 FirstOneOfOption
= TRUE
;
1250 } else if (IfrOpHdr
->OpCode
== EFI_IFR_NUMERIC_OP
) {
1252 // Numeric minimum value will be used as default value when no default is specified.
1258 VarDefaultId
= EFI_HII_DEFAULT_CLASS_STANDARD
;
1260 // Prepare new DefaultValue
1262 DefaultData
= (IFR_DEFAULT_DATA
*) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
1263 if (DefaultData
== NULL
) {
1264 Status
= EFI_OUT_OF_RESOURCES
;
1267 DefaultData
->OpCode
= IfrOpHdr
->OpCode
;
1268 DefaultData
->DefaultId
= VarDefaultId
;
1270 switch (IfrOneOf
->Flags
& EFI_IFR_NUMERIC_SIZE
) {
1271 case EFI_IFR_NUMERIC_SIZE_1
:
1272 DefaultData
->Value
= (UINT64
) IfrOneOf
->data
.u8
.MinValue
;
1275 case EFI_IFR_NUMERIC_SIZE_2
:
1276 CopyMem (&DefaultData
->Value
, &IfrOneOf
->data
.u16
.MinValue
, sizeof (UINT16
));
1279 case EFI_IFR_NUMERIC_SIZE_4
:
1280 CopyMem (&DefaultData
->Value
, &IfrOneOf
->data
.u32
.MinValue
, sizeof (UINT32
));
1283 case EFI_IFR_NUMERIC_SIZE_8
:
1284 CopyMem (&DefaultData
->Value
, &IfrOneOf
->data
.u64
.MinValue
, sizeof (UINT64
));
1288 // Add DefaultValue into current BlockData
1290 InsertDefaultValue (BlockData
, DefaultData
);
1294 case EFI_IFR_ORDERED_LIST_OP
:
1296 // offset by question header
1297 // width by EFI_IFR_ORDERED_LIST MaxContainers * OneofOption Type
1298 // no default value and default id, how to define its default value?
1302 // OrderedList question is not in IFR Form. This IFR form is not valid.
1304 if (VarStorageData
->Size
== 0) {
1305 Status
= EFI_INVALID_PARAMETER
;
1309 // Check whether this question is for the requested varstore.
1311 IfrOrderedList
= (EFI_IFR_ORDERED_LIST
*) IfrOpHdr
;
1312 if (IfrOrderedList
->Question
.VarStoreId
!= VarStorageData
->VarStoreId
) {
1318 // Get Offset/Width by Question header and OneOf Flags
1320 VarOffset
= IfrOrderedList
->Question
.VarStoreInfo
.VarOffset
;
1321 VarWidth
= IfrOrderedList
->MaxContainers
;
1326 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
1327 if (BlockData
== NULL
) {
1328 Status
= EFI_OUT_OF_RESOURCES
;
1331 BlockData
->Offset
= VarOffset
;
1332 BlockData
->Width
= VarWidth
;
1333 BlockData
->QuestionId
= IfrOrderedList
->Question
.QuestionId
;
1334 BlockData
->OpCode
= IfrOpHdr
->OpCode
;
1335 BlockData
->Scope
= IfrOpHdr
->Scope
;
1336 InitializeListHead (&BlockData
->DefaultValueEntry
);
1339 case EFI_IFR_CHECKBOX_OP
:
1341 // EFI_IFR_DEFAULT_OP
1342 // offset by question header
1343 // width is 1 sizeof (BOOLEAN)
1344 // default id by CheckBox Flags if CheckBox flags (Default or Mau) is set, the default value is 1 to be set.
1345 // value by DefaultOption
1346 // default id by DeaultOption DefaultId can override CheckBox Flags and Default value.
1350 // CheckBox question is not in IFR Form. This IFR form is not valid.
1352 if (VarStorageData
->Size
== 0) {
1353 Status
= EFI_INVALID_PARAMETER
;
1357 // Check whether this question is for the requested varstore.
1359 IfrCheckBox
= (EFI_IFR_CHECKBOX
*) IfrOpHdr
;
1360 if (IfrCheckBox
->Question
.VarStoreId
!= VarStorageData
->VarStoreId
) {
1365 // Get Offset/Width by Question header and OneOf Flags
1367 VarOffset
= IfrCheckBox
->Question
.VarStoreInfo
.VarOffset
;
1368 VarWidth
= (UINT16
) sizeof (BOOLEAN
);
1371 // Check whether this question is in requested block array.
1373 if (!BlockArrayCheck (RequestBlockArray
, VarOffset
, VarWidth
)) {
1375 // This question is not in the requested string. Skip it.
1381 // Check this var question is in the var storage
1383 if ((VarOffset
+ VarWidth
) > VarStorageData
->Size
) {
1384 Status
= EFI_INVALID_PARAMETER
;
1391 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
1392 if (BlockData
== NULL
) {
1393 Status
= EFI_OUT_OF_RESOURCES
;
1396 BlockData
->Offset
= VarOffset
;
1397 BlockData
->Width
= VarWidth
;
1398 BlockData
->QuestionId
= IfrCheckBox
->Question
.QuestionId
;
1399 BlockData
->OpCode
= IfrOpHdr
->OpCode
;
1400 BlockData
->Scope
= IfrOpHdr
->Scope
;
1401 InitializeListHead (&BlockData
->DefaultValueEntry
);
1403 // Add Block Data into VarStorageData BlockEntry
1405 InsertBlockData (&VarStorageData
->BlockEntry
, &BlockData
);
1408 // Add default value for standard ID by CheckBox Flag
1410 VarDefaultId
= EFI_HII_DEFAULT_CLASS_STANDARD
;
1412 // Prepare new DefaultValue
1414 DefaultData
= (IFR_DEFAULT_DATA
*) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
1415 if (DefaultData
== NULL
) {
1416 Status
= EFI_OUT_OF_RESOURCES
;
1419 DefaultData
->OpCode
= IfrOpHdr
->OpCode
;
1420 DefaultData
->DefaultId
= VarDefaultId
;
1421 if ((IfrCheckBox
->Flags
& EFI_IFR_CHECKBOX_DEFAULT
) == EFI_IFR_CHECKBOX_DEFAULT
) {
1423 // When flag is set, defautl value is TRUE.
1425 DefaultData
->Value
= 1;
1428 // When flag is not set, defautl value is FASLE.
1430 DefaultData
->Value
= 0;
1433 // Add DefaultValue into current BlockData
1435 InsertDefaultValue (BlockData
, DefaultData
);
1438 // Add default value for Manufacture ID by CheckBox Flag
1440 VarDefaultId
= EFI_HII_DEFAULT_CLASS_MANUFACTURING
;
1442 // Prepare new DefaultValue
1444 DefaultData
= (IFR_DEFAULT_DATA
*) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
1445 if (DefaultData
== NULL
) {
1446 Status
= EFI_OUT_OF_RESOURCES
;
1449 DefaultData
->OpCode
= IfrOpHdr
->OpCode
;
1450 DefaultData
->DefaultId
= VarDefaultId
;
1451 if ((IfrCheckBox
->Flags
& EFI_IFR_CHECKBOX_DEFAULT_MFG
) == EFI_IFR_CHECKBOX_DEFAULT_MFG
) {
1453 // When flag is set, defautl value is TRUE.
1455 DefaultData
->Value
= 1;
1458 // When flag is not set, defautl value is FASLE.
1460 DefaultData
->Value
= 0;
1463 // Add DefaultValue into current BlockData
1465 InsertDefaultValue (BlockData
, DefaultData
);
1468 case EFI_IFR_STRING_OP
:
1470 // offset by question header
1471 // width MaxSize * sizeof (CHAR16)
1472 // no default value, only block array
1476 // String question is not in IFR Form. This IFR form is not valid.
1478 if (VarStorageData
->Size
== 0) {
1479 Status
= EFI_INVALID_PARAMETER
;
1483 // Check whether this question is for the requested varstore.
1485 IfrString
= (EFI_IFR_STRING
*) IfrOpHdr
;
1486 if (IfrString
->Question
.VarStoreId
!= VarStorageData
->VarStoreId
) {
1491 // Get Offset/Width by Question header and OneOf Flags
1493 VarOffset
= IfrString
->Question
.VarStoreInfo
.VarOffset
;
1494 VarWidth
= (UINT16
) (IfrString
->MaxSize
* sizeof (UINT16
));
1497 // Check whether this question is in requested block array.
1499 if (!BlockArrayCheck (RequestBlockArray
, VarOffset
, VarWidth
)) {
1501 // This question is not in the requested string. Skip it.
1507 // Check this var question is in the var storage
1509 if ((VarOffset
+ VarWidth
) > VarStorageData
->Size
) {
1510 Status
= EFI_INVALID_PARAMETER
;
1517 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
1518 if (BlockData
== NULL
) {
1519 Status
= EFI_OUT_OF_RESOURCES
;
1522 BlockData
->Offset
= VarOffset
;
1523 BlockData
->Width
= VarWidth
;
1524 BlockData
->QuestionId
= IfrString
->Question
.QuestionId
;
1525 BlockData
->OpCode
= IfrOpHdr
->OpCode
;
1526 InitializeListHead (&BlockData
->DefaultValueEntry
);
1529 // Add Block Data into VarStorageData BlockEntry
1531 InsertBlockData (&VarStorageData
->BlockEntry
, &BlockData
);
1534 // No default value for string.
1539 case EFI_IFR_PASSWORD_OP
:
1541 // offset by question header
1542 // width MaxSize * sizeof (CHAR16)
1543 // no default value, only block array
1547 // Password question is not in IFR Form. This IFR form is not valid.
1549 if (VarStorageData
->Size
== 0) {
1550 Status
= EFI_INVALID_PARAMETER
;
1554 // Check whether this question is for the requested varstore.
1556 IfrPassword
= (EFI_IFR_PASSWORD
*) IfrOpHdr
;
1557 if (IfrPassword
->Question
.VarStoreId
!= VarStorageData
->VarStoreId
) {
1562 // Get Offset/Width by Question header and OneOf Flags
1564 VarOffset
= IfrPassword
->Question
.VarStoreInfo
.VarOffset
;
1565 VarWidth
= (UINT16
) (IfrPassword
->MaxSize
* sizeof (UINT16
));
1568 // Check whether this question is in requested block array.
1570 if (!BlockArrayCheck (RequestBlockArray
, VarOffset
, VarWidth
)) {
1572 // This question is not in the requested string. Skip it.
1578 // Check this var question is in the var storage
1580 if ((VarOffset
+ VarWidth
) > VarStorageData
->Size
) {
1581 Status
= EFI_INVALID_PARAMETER
;
1588 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
1589 if (BlockData
== NULL
) {
1590 Status
= EFI_OUT_OF_RESOURCES
;
1593 BlockData
->Offset
= VarOffset
;
1594 BlockData
->Width
= VarWidth
;
1595 BlockData
->QuestionId
= IfrPassword
->Question
.QuestionId
;
1596 BlockData
->OpCode
= IfrOpHdr
->OpCode
;
1597 InitializeListHead (&BlockData
->DefaultValueEntry
);
1600 // Add Block Data into VarStorageData BlockEntry
1602 InsertBlockData (&VarStorageData
->BlockEntry
, &BlockData
);
1605 // No default value for string.
1610 case EFI_IFR_ONE_OF_OPTION_OP
:
1612 // No matched block data is ignored.
1614 if (BlockData
== NULL
|| BlockData
->Scope
== 0) {
1618 IfrOneOfOption
= (EFI_IFR_ONE_OF_OPTION
*) IfrOpHdr
;
1619 if (BlockData
->OpCode
== EFI_IFR_ORDERED_LIST_OP
) {
1621 // Get ordered list option data type.
1623 if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_8
|| IfrOneOfOption
->Type
== EFI_IFR_TYPE_BOOLEAN
) {
1625 } else if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_16
) {
1627 } else if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_32
) {
1629 } else if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_64
) {
1633 // Invalid ordered list option data type.
1635 Status
= EFI_INVALID_PARAMETER
;
1636 FreePool (BlockData
);
1641 // Calculate Ordered list QuestionId width.
1643 BlockData
->Width
= (UINT16
) (BlockData
->Width
* VarWidth
);
1645 // Check whether this question is in requested block array.
1647 if (!BlockArrayCheck (RequestBlockArray
, BlockData
->Offset
, BlockData
->Width
)) {
1649 // This question is not in the requested string. Skip it.
1651 FreePool (BlockData
);
1656 // Check this var question is in the var storage
1658 if ((BlockData
->Offset
+ BlockData
->Width
) > VarStorageData
->Size
) {
1659 Status
= EFI_INVALID_PARAMETER
;
1660 FreePool (BlockData
);
1664 // Add Block Data into VarStorageData BlockEntry
1666 InsertBlockData (&VarStorageData
->BlockEntry
, &BlockData
);
1668 // No default data for OrderedList.
1674 if (((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT
) == EFI_IFR_OPTION_DEFAULT
) ||
1675 (BlockData
->OpCode
== EFI_IFR_ONE_OF_OP
&& FirstOneOfOption
)) {
1677 // This flag is used to specify whether this option is the first. Set it to FALSE for the following options.
1678 // The first oneof option value will be used as default value when no default value is specified.
1680 FirstOneOfOption
= FALSE
;
1682 // Set standard ID to Manufacture ID
1684 VarDefaultId
= EFI_HII_DEFAULT_CLASS_STANDARD
;
1686 // Prepare new DefaultValue
1688 DefaultData
= (IFR_DEFAULT_DATA
*) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
1689 if (DefaultData
== NULL
) {
1690 Status
= EFI_OUT_OF_RESOURCES
;
1693 DefaultData
->OpCode
= IfrOpHdr
->OpCode
;
1694 DefaultData
->DefaultId
= VarDefaultId
;
1695 DefaultData
->Value
= IfrOneOfOption
->Value
.u64
;
1697 // Add DefaultValue into current BlockData
1699 InsertDefaultValue (BlockData
, DefaultData
);
1702 if ((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT_MFG
) == EFI_IFR_OPTION_DEFAULT_MFG
) {
1704 // Set default ID to Manufacture ID
1706 VarDefaultId
= EFI_HII_DEFAULT_CLASS_MANUFACTURING
;
1708 // Prepare new DefaultValue
1710 DefaultData
= (IFR_DEFAULT_DATA
*) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
1711 if (DefaultData
== NULL
) {
1712 Status
= EFI_OUT_OF_RESOURCES
;
1715 DefaultData
->OpCode
= IfrOpHdr
->OpCode
;
1716 DefaultData
->DefaultId
= VarDefaultId
;
1717 DefaultData
->Value
= IfrOneOfOption
->Value
.u64
;
1719 // Add DefaultValue into current BlockData
1721 InsertDefaultValue (BlockData
, DefaultData
);
1725 case EFI_IFR_DEFAULT_OP
:
1727 // Update Current BlockData to the default value.
1729 if (BlockData
== NULL
|| BlockData
->Scope
== 0) {
1731 // No matched block data is ignored.
1736 if (BlockData
->OpCode
== EFI_IFR_ORDERED_LIST_OP
) {
1738 // OrderedList Opcode is no default value.
1743 // Get the DefaultId
1745 IfrDefault
= (EFI_IFR_DEFAULT
*) IfrOpHdr
;
1746 VarDefaultId
= IfrDefault
->DefaultId
;
1748 // Prepare new DefaultValue
1750 DefaultData
= (IFR_DEFAULT_DATA
*) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
1751 if (DefaultData
== NULL
) {
1752 Status
= EFI_OUT_OF_RESOURCES
;
1755 DefaultData
->OpCode
= IfrOpHdr
->OpCode
;
1756 DefaultData
->DefaultId
= VarDefaultId
;
1757 DefaultData
->Value
= IfrDefault
->Value
.u64
;
1759 // Add DefaultValue into current BlockData
1761 InsertDefaultValue (BlockData
, DefaultData
);
1763 case EFI_IFR_END_OP
:
1765 // End Opcode is for Var question.
1767 if (BlockData
!= NULL
&& BlockData
->Scope
> 0) {
1772 if (BlockData
!= NULL
&& BlockData
->Scope
> 0) {
1773 BlockData
->Scope
= (UINT8
) (BlockData
->Scope
+ IfrOpHdr
->Scope
);
1778 IfrOffset
+= IfrOpHdr
->Length
;
1786 This function gets the full request string and full default value string by
1787 parsing IFR data in HII form packages.
1789 When Request points to NULL string, the request string and default value string
1790 for each varstore in form package will return.
1792 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
1793 @param DevicePath Device Path which Hii Config Access Protocol is registered.
1794 @param Request Pointer to a null-terminated Unicode string in
1795 <ConfigRequest> format. When it doesn't contain
1796 any RequestElement, it will be updated to return
1797 the full RequestElement retrieved from IFR data.
1798 If it points to NULL, the request string for the first
1799 varstore in form package will be merged into a
1800 <MultiConfigRequest> format string and return.
1801 @param AltCfgResp Pointer to a null-terminated Unicode string in
1802 <ConfigAltResp> format. When the pointer is to NULL,
1803 the full default value string retrieved from IFR data
1804 will return. When the pinter is to a string, the
1805 full default value string retrieved from IFR data
1806 will be merged into the input string and return.
1807 When Request points to NULL, the default value string
1808 for each varstore in form package will be merged into
1809 a <MultiConfigAltResp> format string and return.
1810 @param PointerProgress Optional parameter, it can be be NULL.
1811 When it is not NULL, if Request is NULL, it returns NULL.
1812 On return, points to a character in the Request
1813 string. Points to the string's null terminator if
1814 request was successful. Points to the most recent
1815 & before the first failing name / value pair (or
1816 the beginning of the string if the failure is in
1817 the first name / value pair) if the request was
1819 @retval EFI_SUCCESS The Results string is set to the full request string.
1820 And AltCfgResp contains all default value string.
1821 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
1822 @retval EFI_NOT_FOUND The varstore (Guid and Name) in Request string
1823 can't be found in Form package.
1824 @retval EFI_NOT_FOUND HiiPackage can't be got on the input HiiHandle.
1825 @retval EFI_INVALID_PARAMETER Request points to NULL.
1830 GetFullStringFromHiiFormPackages (
1831 IN HII_DATABASE_RECORD
*DataBaseRecord
,
1832 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
1833 IN OUT EFI_STRING
*Request
,
1834 IN OUT EFI_STRING
*AltCfgResp
,
1835 OUT EFI_STRING
*PointerProgress OPTIONAL
1839 UINT8
*HiiFormPackage
;
1841 IFR_BLOCK_DATA
*RequestBlockArray
;
1842 IFR_BLOCK_DATA
*BlockData
;
1843 IFR_BLOCK_DATA
*NextBlockData
;
1844 IFR_DEFAULT_DATA
*DefaultValueData
;
1845 IFR_DEFAULT_DATA
*DefaultId
;
1846 IFR_DEFAULT_DATA
*DefaultIdArray
;
1847 IFR_VARSTORAGE_DATA
*VarStorageData
;
1848 EFI_STRING DefaultAltCfgResp
;
1849 EFI_STRING FullConfigRequest
;
1850 EFI_STRING ConfigHdr
;
1854 EFI_STRING StringPtr
;
1855 EFI_STRING Progress
;
1861 LIST_ENTRY
*LinkData
;
1862 LIST_ENTRY
*LinkDefault
;
1865 if (DataBaseRecord
== NULL
|| DevicePath
== NULL
|| Request
== NULL
|| AltCfgResp
== NULL
) {
1866 return EFI_INVALID_PARAMETER
;
1870 // Initialize the local variables.
1872 RequestBlockArray
= NULL
;
1873 DefaultIdArray
= NULL
;
1874 VarStorageData
= NULL
;
1875 DefaultAltCfgResp
= NULL
;
1876 FullConfigRequest
= NULL
;
1881 HiiFormPackage
= NULL
;
1884 Progress
= *Request
;
1886 Status
= GetFormPackageData (DataBaseRecord
, &HiiFormPackage
, &PackageSize
);
1887 if (EFI_ERROR (Status
)) {
1892 // 1. Get the request block array by Request String when Request string containts the block array.
1895 if (*Request
!= NULL
) {
1896 StringPtr
= *Request
;
1900 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
1901 Status
= EFI_INVALID_PARAMETER
;
1904 StringPtr
+= StrLen (L
"GUID=");
1905 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&NAME=", StrLen (L
"&NAME=")) != 0) {
1908 if (*StringPtr
== L
'\0') {
1909 Status
= EFI_INVALID_PARAMETER
;
1912 StringPtr
+= StrLen (L
"&NAME=");
1913 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&PATH=", StrLen (L
"&PATH=")) != 0) {
1916 if (*StringPtr
== L
'\0') {
1917 Status
= EFI_INVALID_PARAMETER
;
1920 StringPtr
+= StrLen (L
"&PATH=");
1921 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
1925 // Check the following string &OFFSET=
1927 if (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) != 0) {
1928 Progress
= StringPtr
;
1929 Status
= EFI_INVALID_PARAMETER
;
1931 } else if (*StringPtr
== L
'\0') {
1933 // No request block is found.
1938 if (StringPtr
!= NULL
) {
1940 // Init RequestBlockArray
1942 RequestBlockArray
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
1943 if (RequestBlockArray
== NULL
) {
1944 Status
= EFI_OUT_OF_RESOURCES
;
1947 InitializeListHead (&RequestBlockArray
->Entry
);
1950 // Get the request Block array from the request string
1955 // Parse each <RequestElement> if exists
1956 // Only <BlockName> format is supported by this help function.
1957 // <BlockName> ::= &'OFFSET='<Number>&'WIDTH='<Number>
1959 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) == 0) {
1961 // Skip the OFFSET string
1963 Progress
= StringPtr
;
1964 StringPtr
+= StrLen (L
"&OFFSET=");
1968 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
1969 if (EFI_ERROR (Status
)) {
1976 (((Length
+ 1) / 2) < sizeof (UINT16
)) ? ((Length
+ 1) / 2) : sizeof (UINT16
)
1978 FreePool (TmpBuffer
);
1980 StringPtr
+= Length
;
1981 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
1982 Status
= EFI_INVALID_PARAMETER
;
1985 StringPtr
+= StrLen (L
"&WIDTH=");
1990 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
1991 if (EFI_ERROR (Status
)) {
1998 (((Length
+ 1) / 2) < sizeof (UINT16
)) ? ((Length
+ 1) / 2) : sizeof (UINT16
)
2000 FreePool (TmpBuffer
);
2002 StringPtr
+= Length
;
2003 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
2004 Status
= EFI_INVALID_PARAMETER
;
2011 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
2012 if (BlockData
== NULL
) {
2013 Status
= EFI_OUT_OF_RESOURCES
;
2016 BlockData
->Offset
= Offset
;
2017 BlockData
->Width
= Width
;
2018 InsertBlockData (&RequestBlockArray
->Entry
, &BlockData
);
2021 // Skip &VALUE string if &VALUE does exists.
2023 if (StrnCmp (StringPtr
, L
"&VALUE=", StrLen (L
"&VALUE=")) == 0) {
2024 StringPtr
+= StrLen (L
"&VALUE=");
2029 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
2030 if (EFI_ERROR (Status
)) {
2031 Status
= EFI_INVALID_PARAMETER
;
2035 StringPtr
+= Length
;
2036 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
2037 Status
= EFI_INVALID_PARAMETER
;
2042 // If '\0', parsing is finished.
2044 if (*StringPtr
== 0) {
2050 // Merge the requested block data.
2052 Link
= RequestBlockArray
->Entry
.ForwardLink
;
2053 while ((Link
!= &RequestBlockArray
->Entry
) && (Link
->ForwardLink
!= &RequestBlockArray
->Entry
)) {
2054 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
2055 NextBlockData
= BASE_CR (Link
->ForwardLink
, IFR_BLOCK_DATA
, Entry
);
2056 if ((NextBlockData
->Offset
>= BlockData
->Offset
) && (NextBlockData
->Offset
<= (BlockData
->Offset
+ BlockData
->Width
))) {
2057 if ((NextBlockData
->Offset
+ NextBlockData
->Width
) > (BlockData
->Offset
+ BlockData
->Width
)) {
2058 BlockData
->Width
= (UINT16
) (NextBlockData
->Offset
+ NextBlockData
->Width
- BlockData
->Offset
);
2060 RemoveEntryList (Link
->ForwardLink
);
2061 FreePool (NextBlockData
);
2064 Link
= Link
->ForwardLink
;
2069 // 2. Parse FormPackage to get BlockArray and DefaultId Array for the request BlockArray.
2073 // Initialize DefaultIdArray to store the map between DeaultId and DefaultName
2075 DefaultIdArray
= (IFR_DEFAULT_DATA
*) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
2076 if (DefaultIdArray
== NULL
) {
2077 Status
= EFI_OUT_OF_RESOURCES
;
2080 InitializeListHead (&DefaultIdArray
->Entry
);
2083 // Initialize VarStorageData to store the var store Block and Default value information.
2085 VarStorageData
= (IFR_VARSTORAGE_DATA
*) AllocateZeroPool (sizeof (IFR_VARSTORAGE_DATA
));
2086 if (VarStorageData
== NULL
) {
2087 Status
= EFI_OUT_OF_RESOURCES
;
2090 InitializeListHead (&VarStorageData
->Entry
);
2091 InitializeListHead (&VarStorageData
->BlockEntry
);
2094 // Parse the opcode in form pacakge to get the default setting.
2096 Status
= ParseIfrData (HiiFormPackage
, (UINT32
) PackageSize
, *Request
, RequestBlockArray
, VarStorageData
, DefaultIdArray
);
2097 if (EFI_ERROR (Status
)) {
2102 // No requested varstore in IFR data and directly return
2104 if (VarStorageData
->Size
== 0) {
2105 Status
= EFI_SUCCESS
;
2110 // 3. Construct Request Element (Block Name) for 2.1 and 2.2 case.
2114 // Construct <ConfigHdr> : "GUID=...&NAME=...&PATH=..." by VarStorageData Guid, Name and DriverHandle
2116 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*) &VarStorageData
->Guid
, 1, &GuidStr
);
2117 GenerateSubStr (L
"NAME=", StrLen (VarStorageData
->Name
) * sizeof (CHAR16
), (VOID
*) VarStorageData
->Name
, 2, &NameStr
);
2120 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) DevicePath
),
2121 (VOID
*) DevicePath
,
2125 Length
= StrLen (GuidStr
);
2126 Length
= Length
+ StrLen (NameStr
);
2127 Length
= Length
+ StrLen (PathStr
) + 1;
2128 ConfigHdr
= AllocateZeroPool (Length
* sizeof (CHAR16
));
2129 if (ConfigHdr
== NULL
) {
2130 Status
= EFI_OUT_OF_RESOURCES
;
2133 StrCpy (ConfigHdr
, GuidStr
);
2134 StrCat (ConfigHdr
, NameStr
);
2135 StrCat (ConfigHdr
, PathStr
);
2138 // Remove the last character L'&'
2140 *(ConfigHdr
+ StrLen (ConfigHdr
) - 1) = L
'\0';
2142 if (RequestBlockArray
== NULL
) {
2144 // Append VarStorageData BlockEntry into *Request string
2145 // Now support only one varstore in a form package.
2149 // Go through all VarStorageData Entry and get BlockEntry for each one for the multiple varstore in a single form package
2150 // Then construct them all to return MultiRequest string : ConfigHdr BlockConfig
2154 // Compute the length of the entire request starting with <ConfigHdr> and a
2158 Length
= StrLen (ConfigHdr
) + 1;
2160 for (Link
= VarStorageData
->BlockEntry
.ForwardLink
; Link
!= &VarStorageData
->BlockEntry
; Link
= Link
->ForwardLink
) {
2162 // Add <BlockName> length for each Offset/Width pair
2164 // <BlockName> ::= &OFFSET=1234&WIDTH=1234
2165 // | 8 | 4 | 7 | 4 |
2168 Length
= Length
+ (8 + 4 + 7 + 4);
2172 // No any request block data is found. The request string can't be constructed.
2175 Status
= EFI_SUCCESS
;
2180 // Allocate buffer for the entire <ConfigRequest>
2182 FullConfigRequest
= AllocateZeroPool (Length
* sizeof (CHAR16
));
2183 if (FullConfigRequest
== NULL
) {
2184 Status
= EFI_OUT_OF_RESOURCES
;
2187 StringPtr
= FullConfigRequest
;
2190 // Start with <ConfigHdr>
2192 StrCpy (StringPtr
, ConfigHdr
);
2193 StringPtr
+= StrLen (StringPtr
);
2196 // Loop through all the Offset/Width pairs and append them to ConfigRequest
2198 for (Link
= VarStorageData
->BlockEntry
.ForwardLink
; Link
!= &VarStorageData
->BlockEntry
; Link
= Link
->ForwardLink
) {
2199 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
2201 // Append &OFFSET=XXXX&WIDTH=YYYY\0
2205 (8 + 4 + 7 + 4 + 1) * sizeof (CHAR16
),
2206 L
"&OFFSET=%04X&WIDTH=%04X",
2210 StringPtr
+= StrLen (StringPtr
);
2213 // Set to the got full request string.
2215 HiiToLower (FullConfigRequest
);
2216 if (*Request
!= NULL
) {
2217 FreePool (*Request
);
2219 *Request
= FullConfigRequest
;
2223 // 4. Construct Default Value string in AltResp according to request element.
2224 // Go through all VarStorageData Entry and get the DefaultId array for each one
2225 // Then construct them all to : ConfigHdr AltConfigHdr ConfigBody AltConfigHdr ConfigBody
2229 // Add length for <ConfigHdr> + '\0'
2231 Length
= StrLen (ConfigHdr
) + 1;
2233 for (Link
= DefaultIdArray
->Entry
.ForwardLink
; Link
!= &DefaultIdArray
->Entry
; Link
= Link
->ForwardLink
) {
2234 DefaultId
= BASE_CR (Link
, IFR_DEFAULT_DATA
, Entry
);
2236 // Add length for "&<ConfigHdr>&ALTCFG=XXXX"
2237 // |1| StrLen (ConfigHdr) | 8 | 4 |
2239 Length
+= (1 + StrLen (ConfigHdr
) + 8 + 4);
2241 for (LinkData
= VarStorageData
->BlockEntry
.ForwardLink
; LinkData
!= &VarStorageData
->BlockEntry
; LinkData
= LinkData
->ForwardLink
) {
2242 BlockData
= BASE_CR (LinkData
, IFR_BLOCK_DATA
, Entry
);
2243 for (LinkDefault
= BlockData
->DefaultValueEntry
.ForwardLink
; LinkDefault
!= &BlockData
->DefaultValueEntry
; LinkDefault
= LinkDefault
->ForwardLink
) {
2244 DefaultValueData
= BASE_CR (LinkDefault
, IFR_DEFAULT_DATA
, Entry
);
2245 if (DefaultValueData
->DefaultId
== DefaultId
->DefaultId
) {
2247 // Add length for "&OFFSET=XXXX&WIDTH=YYYY&VALUE=zzzzzzzzzzzz"
2248 // | 8 | 4 | 7 | 4 | 7 | Width * 2 |
2250 Length
+= (8 + 4 + 7 + 4 + 7 + BlockData
->Width
* 2);
2258 // No default value is found. The default string doesn't exist.
2261 Status
= EFI_SUCCESS
;
2266 // Allocate buffer for the entire <DefaultAltCfgResp>
2268 DefaultAltCfgResp
= AllocateZeroPool (Length
* sizeof (CHAR16
));
2269 if (DefaultAltCfgResp
== NULL
) {
2270 Status
= EFI_OUT_OF_RESOURCES
;
2273 StringPtr
= DefaultAltCfgResp
;
2276 // Start with <ConfigHdr>
2278 StrCpy (StringPtr
, ConfigHdr
);
2279 StringPtr
+= StrLen (StringPtr
);
2281 for (Link
= DefaultIdArray
->Entry
.ForwardLink
; Link
!= &DefaultIdArray
->Entry
; Link
= Link
->ForwardLink
) {
2282 DefaultId
= BASE_CR (Link
, IFR_DEFAULT_DATA
, Entry
);
2284 // Add <AltConfigHdr> of the form "&<ConfigHdr>&ALTCFG=XXXX\0"
2285 // |1| StrLen (ConfigHdr) | 8 | 4 |
2289 (1 + StrLen (ConfigHdr
) + 8 + 4 + 1) * sizeof (CHAR16
),
2292 DefaultId
->DefaultId
2294 StringPtr
+= StrLen (StringPtr
);
2296 for (LinkData
= VarStorageData
->BlockEntry
.ForwardLink
; LinkData
!= &VarStorageData
->BlockEntry
; LinkData
= LinkData
->ForwardLink
) {
2297 BlockData
= BASE_CR (LinkData
, IFR_BLOCK_DATA
, Entry
);
2298 for (LinkDefault
= BlockData
->DefaultValueEntry
.ForwardLink
; LinkDefault
!= &BlockData
->DefaultValueEntry
; LinkDefault
= LinkDefault
->ForwardLink
) {
2299 DefaultValueData
= BASE_CR (LinkDefault
, IFR_DEFAULT_DATA
, Entry
);
2300 if (DefaultValueData
->DefaultId
== DefaultId
->DefaultId
) {
2302 // Add <BlockConfig>
2303 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>
2307 (8 + 4 + 7 + 4 + 7 + 1) * sizeof (CHAR16
),
2308 L
"&OFFSET=%04X&WIDTH=%04X&VALUE=",
2312 StringPtr
+= StrLen (StringPtr
);
2315 // Convert Value to a hex string in "%x" format
2316 // NOTE: This is in the opposite byte that GUID and PATH use
2318 Width
= BlockData
->Width
;
2319 TmpBuffer
= (UINT8
*) &(DefaultValueData
->Value
);
2320 for (; Width
> 0; Width
--) {
2321 StringPtr
+= UnicodeValueToString (StringPtr
, PREFIX_ZERO
| RADIX_HEX
, TmpBuffer
[Width
- 1], 2);
2327 HiiToLower (DefaultAltCfgResp
);
2330 // 5. Merge string into the input AltCfgResp if the iput *AltCfgResp is not NULL.
2332 if (*AltCfgResp
!= NULL
&& DefaultAltCfgResp
!= NULL
) {
2333 Status
= MergeDefaultString (AltCfgResp
, DefaultAltCfgResp
);
2334 FreePool (DefaultAltCfgResp
);
2335 } else if (*AltCfgResp
== NULL
) {
2336 *AltCfgResp
= DefaultAltCfgResp
;
2340 if (RequestBlockArray
!= NULL
) {
2342 // Free Link Array RequestBlockArray
2344 while (!IsListEmpty (&RequestBlockArray
->Entry
)) {
2345 BlockData
= BASE_CR (RequestBlockArray
->Entry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
2346 RemoveEntryList (&BlockData
->Entry
);
2347 FreePool (BlockData
);
2350 FreePool (RequestBlockArray
);
2353 if (VarStorageData
!= NULL
) {
2355 // Free link array VarStorageData
2357 while (!IsListEmpty (&VarStorageData
->BlockEntry
)) {
2358 BlockData
= BASE_CR (VarStorageData
->BlockEntry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
2359 RemoveEntryList (&BlockData
->Entry
);
2361 // Free default value link array
2363 while (!IsListEmpty (&BlockData
->DefaultValueEntry
)) {
2364 DefaultValueData
= BASE_CR (BlockData
->DefaultValueEntry
.ForwardLink
, IFR_DEFAULT_DATA
, Entry
);
2365 RemoveEntryList (&DefaultValueData
->Entry
);
2366 FreePool (DefaultValueData
);
2368 FreePool (BlockData
);
2370 FreePool (VarStorageData
);
2373 if (DefaultIdArray
!= NULL
) {
2375 // Free DefaultId Array
2377 while (!IsListEmpty (&DefaultIdArray
->Entry
)) {
2378 DefaultId
= BASE_CR (DefaultIdArray
->Entry
.ForwardLink
, IFR_DEFAULT_DATA
, Entry
);
2379 RemoveEntryList (&DefaultId
->Entry
);
2380 FreePool (DefaultId
);
2382 FreePool (DefaultIdArray
);
2386 // Free the allocated string
2388 if (GuidStr
!= NULL
) {
2391 if (NameStr
!= NULL
) {
2394 if (PathStr
!= NULL
) {
2397 if (ConfigHdr
!= NULL
) {
2398 FreePool (ConfigHdr
);
2402 // Free Pacakge data
2404 if (HiiFormPackage
!= NULL
) {
2405 FreePool (HiiFormPackage
);
2408 if (PointerProgress
!= NULL
) {
2409 if (*Request
== NULL
) {
2410 *PointerProgress
= NULL
;
2411 } else if (EFI_ERROR (Status
)) {
2412 *PointerProgress
= Progress
;
2414 *PointerProgress
= *Request
+ StrLen (*Request
);
2422 This function gets the full request resp string by
2423 parsing IFR data in HII form packages.
2425 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
2427 @param EfiVarStoreInfo The efi varstore info which is save in the EFI
2428 varstore data structure.
2429 @param Request Pointer to a null-terminated Unicode string in
2430 <ConfigRequest> format.
2431 @param RequestResp Pointer to a null-terminated Unicode string in
2432 <ConfigResp> format.
2433 @param AccessProgress On return, points to a character in the Request
2434 string. Points to the string's null terminator if
2435 request was successful. Points to the most recent
2436 & before the first failing name / value pair (or
2437 the beginning of the string if the failure is in
2438 the first name / value pair) if the request was
2441 @retval EFI_SUCCESS The Results string is set to the full request string.
2442 And AltCfgResp contains all default value string.
2443 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
2444 @retval EFI_INVALID_PARAMETER Request points to NULL.
2448 GetConfigRespFromEfiVarStore (
2449 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
2450 IN EFI_IFR_VARSTORE_EFI
*EfiVarStoreInfo
,
2451 IN EFI_STRING Request
,
2452 OUT EFI_STRING
*RequestResp
,
2453 OUT EFI_STRING
*AccessProgress
2457 EFI_STRING VarStoreName
;
2461 Status
= EFI_SUCCESS
;
2464 VarStoreName
= NULL
;
2466 VarStoreName
= AllocateZeroPool (AsciiStrSize ((CHAR8
*)EfiVarStoreInfo
->Name
) * sizeof (CHAR16
));
2467 if (VarStoreName
== NULL
) {
2468 Status
= EFI_OUT_OF_RESOURCES
;
2471 AsciiStrToUnicodeStr ((CHAR8
*) EfiVarStoreInfo
->Name
, VarStoreName
);
2474 Status
= gRT
->GetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, NULL
, &BufferSize
, NULL
);
2475 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
2479 VarStore
= AllocateZeroPool (BufferSize
);
2480 ASSERT (VarStore
!= NULL
);
2481 Status
= gRT
->GetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, NULL
, &BufferSize
, VarStore
);
2482 if (EFI_ERROR (Status
)) {
2486 Status
= HiiBlockToConfig(This
, Request
, VarStore
, BufferSize
, RequestResp
, AccessProgress
);
2487 if (EFI_ERROR (Status
)) {
2492 if (VarStoreName
!= NULL
) {
2493 FreePool (VarStoreName
);
2496 if (VarStore
!= NULL
) {
2497 FreePool (VarStore
);
2505 This function route the full request resp string for efi varstore.
2507 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
2509 @param EfiVarStoreInfo The efi varstore info which is save in the EFI
2510 varstore data structure.
2511 @param RequestResp Pointer to a null-terminated Unicode string in
2512 <ConfigResp> format.
2513 @param Result Pointer to a null-terminated Unicode string in
2514 <ConfigResp> format.
2516 @retval EFI_SUCCESS The Results string is set to the full request string.
2517 And AltCfgResp contains all default value string.
2518 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
2519 @retval EFI_INVALID_PARAMETER Request points to NULL.
2523 RouteConfigRespForEfiVarStore (
2524 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
2525 IN EFI_IFR_VARSTORE_EFI
*EfiVarStoreInfo
,
2526 IN EFI_STRING RequestResp
,
2527 OUT EFI_STRING
*Result
2531 EFI_STRING VarStoreName
;
2536 Status
= EFI_SUCCESS
;
2539 VarStoreName
= NULL
;
2541 VarStoreName
= AllocateZeroPool (AsciiStrSize ((CHAR8
*)EfiVarStoreInfo
->Name
) * sizeof (CHAR16
));
2542 if (VarStoreName
== NULL
) {
2543 Status
= EFI_OUT_OF_RESOURCES
;
2546 AsciiStrToUnicodeStr ((CHAR8
*) EfiVarStoreInfo
->Name
, VarStoreName
);
2548 Status
= gRT
->GetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, NULL
, &BufferSize
, NULL
);
2549 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
2553 BlockSize
= BufferSize
;
2554 VarStore
= AllocateZeroPool (BufferSize
);
2555 ASSERT (VarStore
!= NULL
);
2556 Status
= gRT
->GetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, NULL
, &BufferSize
, VarStore
);
2557 if (EFI_ERROR (Status
)) {
2561 Status
= HiiConfigToBlock(This
, RequestResp
, VarStore
, &BlockSize
, Result
);
2562 if (EFI_ERROR (Status
)) {
2566 Status
= gRT
->SetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, EfiVarStoreInfo
->Attributes
, BufferSize
, VarStore
);
2567 if (EFI_ERROR (Status
)) {
2572 if (VarStoreName
!= NULL
) {
2573 FreePool (VarStoreName
);
2576 if (VarStore
!= NULL
) {
2577 FreePool (VarStore
);
2584 This function allows a caller to extract the current configuration
2585 for one or more named elements from one or more drivers.
2587 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
2589 @param Request A null-terminated Unicode string in
2590 <MultiConfigRequest> format.
2591 @param Progress On return, points to a character in the Request
2592 string. Points to the string's null terminator if
2593 request was successful. Points to the most recent
2594 & before the first failing name / value pair (or
2595 the beginning of the string if the failure is in
2596 the first name / value pair) if the request was
2598 @param Results Null-terminated Unicode string in
2599 <MultiConfigAltResp> format which has all values
2600 filled in for the names in the Request string.
2601 String to be allocated by the called function.
2603 @retval EFI_SUCCESS The Results string is filled with the values
2604 corresponding to all requested names.
2605 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
2606 results that must be stored awaiting possible
2608 @retval EFI_NOT_FOUND Routing data doesn't match any known driver.
2609 Progress set to the "G" in "GUID" of the routing
2610 header that doesn't match. Note: There is no
2611 requirement that all routing data be validated
2612 before any configuration extraction.
2613 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Request
2614 parameter would result in this type of error. The
2615 Progress parameter is set to NULL.
2616 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set to most recent &
2617 before the error or the beginning of the string.
2618 @retval EFI_INVALID_PARAMETER Unknown name. Progress points to the & before the
2624 HiiConfigRoutingExtractConfig (
2625 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
2626 IN CONST EFI_STRING Request
,
2627 OUT EFI_STRING
*Progress
,
2628 OUT EFI_STRING
*Results
2631 HII_DATABASE_PRIVATE_DATA
*Private
;
2632 EFI_STRING StringPtr
;
2633 EFI_STRING ConfigRequest
;
2635 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
2636 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
2639 HII_DATABASE_RECORD
*Database
;
2640 UINT8
*DevicePathPkg
;
2641 UINT8
*CurrentDevicePath
;
2642 EFI_HANDLE DriverHandle
;
2643 EFI_HII_HANDLE HiiHandle
;
2644 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
2645 EFI_STRING AccessProgress
;
2646 EFI_STRING AccessResults
;
2647 EFI_STRING DefaultResults
;
2648 BOOLEAN FirstElement
;
2649 BOOLEAN IfrDataParsedFlag
;
2650 BOOLEAN IsEfiVarStore
;
2651 EFI_IFR_VARSTORE_EFI
*EfiVarStoreInfo
;
2653 if (This
== NULL
|| Progress
== NULL
|| Results
== NULL
) {
2654 return EFI_INVALID_PARAMETER
;
2657 if (Request
== NULL
) {
2659 return EFI_INVALID_PARAMETER
;
2662 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
2663 StringPtr
= Request
;
2664 *Progress
= StringPtr
;
2665 DefaultResults
= NULL
;
2666 ConfigRequest
= NULL
;
2667 Status
= EFI_SUCCESS
;
2668 AccessResults
= NULL
;
2669 AccessProgress
= NULL
;
2671 IfrDataParsedFlag
= FALSE
;
2672 IsEfiVarStore
= FALSE
;
2673 EfiVarStoreInfo
= NULL
;
2676 // The first element of <MultiConfigRequest> should be
2677 // <GuidHdr>, which is in 'GUID='<Guid> syntax.
2679 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
2680 return EFI_INVALID_PARAMETER
;
2683 FirstElement
= TRUE
;
2686 // Allocate a fix length of memory to store Results. Reallocate memory for
2687 // Results if this fix length is insufficient.
2689 *Results
= (EFI_STRING
) AllocateZeroPool (MAX_STRING_LENGTH
);
2690 if (*Results
== NULL
) {
2691 return EFI_OUT_OF_RESOURCES
;
2694 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) == 0) {
2696 // If parsing error, set Progress to the beginning of the <MultiConfigRequest>
2697 // or most recent & before the error.
2699 if (StringPtr
== Request
) {
2700 *Progress
= StringPtr
;
2702 *Progress
= StringPtr
- 1;
2706 // Process each <ConfigRequest> of <MultiConfigRequest>
2708 Length
= CalculateConfigStringLen (StringPtr
);
2709 ConfigRequest
= AllocateCopyPool ((Length
+ 1) * sizeof (CHAR16
), StringPtr
);
2710 if (ConfigRequest
== NULL
) {
2711 Status
= EFI_OUT_OF_RESOURCES
;
2714 *(ConfigRequest
+ Length
) = 0;
2717 // Get the UEFI device path
2719 Status
= GetDevicePath (ConfigRequest
, (UINT8
**) &DevicePath
);
2720 if (EFI_ERROR (Status
)) {
2725 // Find driver which matches the routing data.
2727 DriverHandle
= NULL
;
2730 for (Link
= Private
->DatabaseList
.ForwardLink
;
2731 Link
!= &Private
->DatabaseList
;
2732 Link
= Link
->ForwardLink
2734 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
2735 if ((DevicePathPkg
= Database
->PackageList
->DevicePathPkg
) != NULL
) {
2736 CurrentDevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
2740 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) CurrentDevicePath
)
2742 DriverHandle
= Database
->DriverHandle
;
2743 HiiHandle
= Database
->Handle
;
2750 // Try to find driver handle by device path.
2752 if (DriverHandle
== NULL
) {
2753 TempDevicePath
= DevicePath
;
2754 Status
= gBS
->LocateDevicePath (
2755 &gEfiDevicePathProtocolGuid
,
2759 if (EFI_ERROR (Status
) || (DriverHandle
== NULL
)) {
2761 // Routing data does not match any known driver.
2762 // Set Progress to the 'G' in "GUID" of the routing header.
2764 *Progress
= StringPtr
;
2765 Status
= EFI_NOT_FOUND
;
2771 // Check whether ConfigRequest contains request string OFFSET/WIDTH
2773 IfrDataParsedFlag
= FALSE
;
2774 if ((HiiHandle
!= NULL
) && (StrStr (ConfigRequest
, L
"&OFFSET=") == NULL
)) {
2776 // Get the full request string from IFR when HiiPackage is registered to HiiHandle
2778 IfrDataParsedFlag
= TRUE
;
2779 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &ConfigRequest
, &DefaultResults
, &AccessProgress
);
2780 if (EFI_ERROR (Status
)) {
2782 // AccessProgress indicates the parsing progress on <ConfigRequest>.
2783 // Map it to the progress on <MultiConfigRequest> then return it.
2785 *Progress
= StrStr (StringPtr
, AccessProgress
);
2789 // Not any request block is found.
2791 if (StrStr (ConfigRequest
, L
"&OFFSET=") == NULL
) {
2792 AccessResults
= AllocateCopyPool (StrSize (ConfigRequest
), ConfigRequest
);
2793 goto NextConfigString
;
2798 // Check whether this ConfigRequest is search from Efi varstore type storage.
2800 Status
= GetVarStoreType(Database
, ConfigRequest
, &IsEfiVarStore
, &EfiVarStoreInfo
);
2801 if (EFI_ERROR (Status
)) {
2805 if (IsEfiVarStore
) {
2807 // Call the GetVariable function to extract settings.
2809 Status
= GetConfigRespFromEfiVarStore(This
, EfiVarStoreInfo
, ConfigRequest
, &AccessResults
, &AccessProgress
);
2810 FreePool (EfiVarStoreInfo
);
2813 // Call corresponding ConfigAccess protocol to extract settings
2815 Status
= gBS
->HandleProtocol (
2817 &gEfiHiiConfigAccessProtocolGuid
,
2818 (VOID
**) &ConfigAccess
2820 ASSERT_EFI_ERROR (Status
);
2822 Status
= ConfigAccess
->ExtractConfig (
2829 if (EFI_ERROR (Status
)) {
2831 // AccessProgress indicates the parsing progress on <ConfigRequest>.
2832 // Map it to the progress on <MultiConfigRequest> then return it.
2834 *Progress
= StrStr (StringPtr
, AccessProgress
);
2839 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'
2840 // which seperates the first <ConfigAltResp> and the following ones.
2842 ASSERT (*AccessProgress
== 0);
2845 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
2847 if (!IfrDataParsedFlag
&& HiiHandle
!= NULL
) {
2848 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &ConfigRequest
, &DefaultResults
, NULL
);
2849 ASSERT_EFI_ERROR (Status
);
2852 FreePool (DevicePath
);
2855 if (DefaultResults
!= NULL
) {
2856 Status
= MergeDefaultString (&AccessResults
, DefaultResults
);
2857 ASSERT_EFI_ERROR (Status
);
2858 FreePool (DefaultResults
);
2859 DefaultResults
= NULL
;
2863 if (!FirstElement
) {
2864 Status
= AppendToMultiString (Results
, L
"&");
2865 ASSERT_EFI_ERROR (Status
);
2868 Status
= AppendToMultiString (Results
, AccessResults
);
2869 ASSERT_EFI_ERROR (Status
);
2871 FirstElement
= FALSE
;
2873 FreePool (AccessResults
);
2874 AccessResults
= NULL
;
2875 FreePool (ConfigRequest
);
2876 ConfigRequest
= NULL
;
2879 // Go to next <ConfigRequest> (skip '&').
2881 StringPtr
+= Length
;
2882 if (*StringPtr
== 0) {
2883 *Progress
= StringPtr
;
2891 if (EFI_ERROR (Status
)) {
2892 FreePool (*Results
);
2896 if (ConfigRequest
!= NULL
) {
2897 FreePool (ConfigRequest
);
2900 if (AccessResults
!= NULL
) {
2901 FreePool (AccessResults
);
2904 if (DefaultResults
!= NULL
) {
2905 FreePool (DefaultResults
);
2908 if (DevicePath
!= NULL
) {
2909 FreePool (DevicePath
);
2917 This function allows the caller to request the current configuration for the
2918 entirety of the current HII database and returns the data in a
2919 null-terminated Unicode string.
2921 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
2923 @param Results Null-terminated Unicode string in
2924 <MultiConfigAltResp> format which has all values
2925 filled in for the names in the Request string.
2926 String to be allocated by the called function.
2927 De-allocation is up to the caller.
2929 @retval EFI_SUCCESS The Results string is filled with the values
2930 corresponding to all requested names.
2931 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
2932 results that must be stored awaiting possible
2934 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Results
2935 parameter would result in this type of error.
2940 HiiConfigRoutingExportConfig (
2941 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
2942 OUT EFI_STRING
*Results
2946 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
2947 EFI_STRING AccessResults
;
2948 EFI_STRING Progress
;
2949 EFI_STRING StringPtr
;
2950 EFI_STRING ConfigRequest
;
2952 EFI_HANDLE
*ConfigAccessHandles
;
2953 UINTN NumberConfigAccessHandles
;
2954 BOOLEAN FirstElement
;
2955 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
2956 EFI_HII_HANDLE HiiHandle
;
2957 EFI_STRING DefaultResults
;
2958 HII_DATABASE_PRIVATE_DATA
*Private
;
2960 HII_DATABASE_RECORD
*Database
;
2961 UINT8
*DevicePathPkg
;
2962 UINT8
*CurrentDevicePath
;
2963 BOOLEAN IfrDataParsedFlag
;
2965 if (This
== NULL
|| Results
== NULL
) {
2966 return EFI_INVALID_PARAMETER
;
2969 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
2972 // Allocate a fix length of memory to store Results. Reallocate memory for
2973 // Results if this fix length is insufficient.
2975 *Results
= (EFI_STRING
) AllocateZeroPool (MAX_STRING_LENGTH
);
2976 if (*Results
== NULL
) {
2977 return EFI_OUT_OF_RESOURCES
;
2980 NumberConfigAccessHandles
= 0;
2981 Status
= gBS
->LocateHandleBuffer (
2983 &gEfiHiiConfigAccessProtocolGuid
,
2985 &NumberConfigAccessHandles
,
2986 &ConfigAccessHandles
2988 if (EFI_ERROR (Status
)) {
2992 FirstElement
= TRUE
;
2994 for (Index
= 0; Index
< NumberConfigAccessHandles
; Index
++) {
2995 Status
= gBS
->HandleProtocol (
2996 ConfigAccessHandles
[Index
],
2997 &gEfiHiiConfigAccessProtocolGuid
,
2998 (VOID
**) &ConfigAccess
3000 if (EFI_ERROR (Status
)) {
3005 // Get DevicePath and HiiHandle for this ConfigAccess driver handle
3007 IfrDataParsedFlag
= FALSE
;
3010 DefaultResults
= NULL
;
3012 ConfigRequest
= NULL
;
3013 DevicePath
= DevicePathFromHandle (ConfigAccessHandles
[Index
]);
3014 if (DevicePath
!= NULL
) {
3015 for (Link
= Private
->DatabaseList
.ForwardLink
;
3016 Link
!= &Private
->DatabaseList
;
3017 Link
= Link
->ForwardLink
3019 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
3020 if ((DevicePathPkg
= Database
->PackageList
->DevicePathPkg
) != NULL
) {
3021 CurrentDevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
3025 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) CurrentDevicePath
)
3027 HiiHandle
= Database
->Handle
;
3034 Status
= ConfigAccess
->ExtractConfig (
3040 if (EFI_ERROR (Status
)) {
3042 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
3044 if (HiiHandle
!= NULL
&& DevicePath
!= NULL
) {
3045 IfrDataParsedFlag
= TRUE
;
3046 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &ConfigRequest
, &DefaultResults
, NULL
);
3048 // Get the full request string to get the Current setting again.
3050 if (!EFI_ERROR (Status
) && ConfigRequest
!= NULL
) {
3051 Status
= ConfigAccess
->ExtractConfig (
3057 FreePool (ConfigRequest
);
3059 Status
= EFI_NOT_FOUND
;
3064 if (!EFI_ERROR (Status
)) {
3066 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
3068 if (!IfrDataParsedFlag
&& HiiHandle
!= NULL
&& DevicePath
!= NULL
) {
3069 StringPtr
= StrStr (AccessResults
, L
"&GUID=");
3070 if (StringPtr
!= NULL
) {
3073 if (StrStr (AccessResults
, L
"&OFFSET=") != NULL
) {
3074 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &AccessResults
, &DefaultResults
, NULL
);
3075 ASSERT_EFI_ERROR (Status
);
3077 if (StringPtr
!= NULL
) {
3082 // Merge the default sting from IFR code into the got setting from driver.
3084 if (DefaultResults
!= NULL
) {
3085 Status
= MergeDefaultString (&AccessResults
, DefaultResults
);
3086 ASSERT_EFI_ERROR (Status
);
3087 FreePool (DefaultResults
);
3088 DefaultResults
= NULL
;
3092 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'
3093 // which seperates the first <ConfigAltResp> and the following ones.
3095 if (!FirstElement
) {
3096 Status
= AppendToMultiString (Results
, L
"&");
3097 ASSERT_EFI_ERROR (Status
);
3100 Status
= AppendToMultiString (Results
, AccessResults
);
3101 ASSERT_EFI_ERROR (Status
);
3103 FirstElement
= FALSE
;
3105 FreePool (AccessResults
);
3106 AccessResults
= NULL
;
3109 FreePool (ConfigAccessHandles
);
3116 This function processes the results of processing forms and routes it to the
3117 appropriate handlers or storage.
3119 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
3121 @param Configuration A null-terminated Unicode string in
3122 <MulltiConfigResp> format.
3123 @param Progress A pointer to a string filled in with the offset of
3124 the most recent & before the first failing name /
3125 value pair (or the beginning of the string if the
3126 failure is in the first name / value pair) or the
3127 terminating NULL if all was successful.
3129 @retval EFI_SUCCESS The results have been distributed or are awaiting
3131 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
3132 results that must be stored awaiting possible
3134 @retval EFI_INVALID_PARAMETER Passing in a NULL for the Configuration parameter
3135 would result in this type of error.
3136 @retval EFI_NOT_FOUND Target for the specified routing data was not
3142 HiiConfigRoutingRouteConfig (
3143 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
3144 IN CONST EFI_STRING Configuration
,
3145 OUT EFI_STRING
*Progress
3148 HII_DATABASE_PRIVATE_DATA
*Private
;
3149 EFI_STRING StringPtr
;
3150 EFI_STRING ConfigResp
;
3153 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
3154 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
3156 HII_DATABASE_RECORD
*Database
;
3157 UINT8
*DevicePathPkg
;
3158 UINT8
*CurrentDevicePath
;
3159 EFI_HANDLE DriverHandle
;
3160 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
3161 EFI_STRING AccessProgress
;
3162 EFI_IFR_VARSTORE_EFI
*EfiVarStoreInfo
;
3163 BOOLEAN IsEfiVarstore
;
3165 if (This
== NULL
|| Progress
== NULL
) {
3166 return EFI_INVALID_PARAMETER
;
3169 if (Configuration
== NULL
) {
3171 return EFI_INVALID_PARAMETER
;
3174 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
3175 StringPtr
= Configuration
;
3176 *Progress
= StringPtr
;
3178 AccessProgress
= NULL
;
3179 EfiVarStoreInfo
= NULL
;
3180 IsEfiVarstore
= FALSE
;
3183 // The first element of <MultiConfigResp> should be
3184 // <GuidHdr>, which is in 'GUID='<Guid> syntax.
3186 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
3187 return EFI_INVALID_PARAMETER
;
3190 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) == 0) {
3192 // If parsing error, set Progress to the beginning of the <MultiConfigResp>
3193 // or most recent & before the error.
3195 if (StringPtr
== Configuration
) {
3196 *Progress
= StringPtr
;
3198 *Progress
= StringPtr
- 1;
3202 // Process each <ConfigResp> of <MultiConfigResp>
3204 Length
= CalculateConfigStringLen (StringPtr
);
3205 ConfigResp
= AllocateCopyPool ((Length
+ 1) * sizeof (CHAR16
), StringPtr
);
3206 if (ConfigResp
== NULL
) {
3207 return EFI_OUT_OF_RESOURCES
;
3210 // Append '\0' to the end of ConfigRequest
3212 *(ConfigResp
+ Length
) = 0;
3215 // Get the UEFI device path
3217 Status
= GetDevicePath (ConfigResp
, (UINT8
**) &DevicePath
);
3218 if (EFI_ERROR (Status
)) {
3219 FreePool (ConfigResp
);
3224 // Find driver which matches the routing data.
3226 DriverHandle
= NULL
;
3227 for (Link
= Private
->DatabaseList
.ForwardLink
;
3228 Link
!= &Private
->DatabaseList
;
3229 Link
= Link
->ForwardLink
3231 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
3233 if ((DevicePathPkg
= Database
->PackageList
->DevicePathPkg
) != NULL
) {
3234 CurrentDevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
3238 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) CurrentDevicePath
)
3240 DriverHandle
= Database
->DriverHandle
;
3247 // Try to find driver handle by device path.
3249 if (DriverHandle
== NULL
) {
3250 TempDevicePath
= DevicePath
;
3251 Status
= gBS
->LocateDevicePath (
3252 &gEfiDevicePathProtocolGuid
,
3256 if (EFI_ERROR (Status
) || (DriverHandle
== NULL
)) {
3258 // Routing data does not match any known driver.
3259 // Set Progress to the 'G' in "GUID" of the routing header.
3261 FreePool (DevicePath
);
3262 *Progress
= StringPtr
;
3263 FreePool (ConfigResp
);
3264 return EFI_NOT_FOUND
;
3268 FreePool (DevicePath
);
3271 // Check whether this ConfigRequest is search from Efi varstore type storage.
3273 Status
= GetVarStoreType(Database
, ConfigResp
, &IsEfiVarstore
, &EfiVarStoreInfo
);
3274 if (EFI_ERROR (Status
)) {
3278 if (IsEfiVarstore
) {
3280 // Call the SetVariable function to route settings.
3282 Status
= RouteConfigRespForEfiVarStore(This
, EfiVarStoreInfo
, ConfigResp
, &AccessProgress
);
3283 FreePool (EfiVarStoreInfo
);
3286 // Call corresponding ConfigAccess protocol to route settings
3288 Status
= gBS
->HandleProtocol (
3290 &gEfiHiiConfigAccessProtocolGuid
,
3291 (VOID
**) &ConfigAccess
3293 ASSERT_EFI_ERROR (Status
);
3295 Status
= ConfigAccess
->RouteConfig (
3301 if (EFI_ERROR (Status
)) {
3303 // AccessProgress indicates the parsing progress on <ConfigResp>.
3304 // Map it to the progress on <MultiConfigResp> then return it.
3306 *Progress
= StrStr (StringPtr
, AccessProgress
);
3308 FreePool (ConfigResp
);
3312 FreePool (ConfigResp
);
3316 // Go to next <ConfigResp> (skip '&').
3318 StringPtr
+= Length
;
3319 if (*StringPtr
== 0) {
3320 *Progress
= StringPtr
;
3333 This helper function is to be called by drivers to map configuration data
3334 stored in byte array ("block") formats such as UEFI Variables into current
3335 configuration strings.
3337 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
3339 @param ConfigRequest A null-terminated Unicode string in
3340 <ConfigRequest> format.
3341 @param Block Array of bytes defining the block's configuration.
3342 @param BlockSize Length in bytes of Block.
3343 @param Config Filled-in configuration string. String allocated
3344 by the function. Returned only if call is
3345 successful. It is <ConfigResp> string format.
3346 @param Progress A pointer to a string filled in with the offset of
3347 the most recent & before the first failing
3348 name/value pair (or the beginning of the string if
3349 the failure is in the first name / value pair) or
3350 the terminating NULL if all was successful.
3352 @retval EFI_SUCCESS The request succeeded. Progress points to the null
3353 terminator at the end of the ConfigRequest
3355 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress
3356 points to the first character of ConfigRequest.
3357 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigRequest or
3358 Block parameter would result in this type of
3359 error. Progress points to the first character of
3361 @retval EFI_DEVICE_ERROR Block not large enough. Progress undefined.
3362 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted string.
3363 Block is left updated and Progress points at
3364 the "&" preceding the first non-<BlockName>.
3370 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
3371 IN CONST EFI_STRING ConfigRequest
,
3372 IN CONST UINT8
*Block
,
3373 IN CONST UINTN BlockSize
,
3374 OUT EFI_STRING
*Config
,
3375 OUT EFI_STRING
*Progress
3378 HII_DATABASE_PRIVATE_DATA
*Private
;
3379 EFI_STRING StringPtr
;
3387 EFI_STRING ValueStr
;
3388 EFI_STRING ConfigElement
;
3394 if (This
== NULL
|| Progress
== NULL
|| Config
== NULL
) {
3395 return EFI_INVALID_PARAMETER
;
3398 if (Block
== NULL
|| ConfigRequest
== NULL
) {
3399 *Progress
= ConfigRequest
;
3400 return EFI_INVALID_PARAMETER
;
3404 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
3405 ASSERT (Private
!= NULL
);
3407 StringPtr
= ConfigRequest
;
3410 ConfigElement
= NULL
;
3413 // Allocate a fix length of memory to store Results. Reallocate memory for
3414 // Results if this fix length is insufficient.
3416 *Config
= (EFI_STRING
) AllocateZeroPool (MAX_STRING_LENGTH
);
3417 if (*Config
== NULL
) {
3418 return EFI_OUT_OF_RESOURCES
;
3424 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
3425 *Progress
= StringPtr
;
3426 Status
= EFI_INVALID_PARAMETER
;
3429 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"PATH=", StrLen (L
"PATH=")) != 0) {
3432 if (*StringPtr
== 0) {
3433 *Progress
= StringPtr
- 1;
3434 Status
= EFI_INVALID_PARAMETER
;
3438 while (*StringPtr
!= L
'&' && *StringPtr
!= 0) {
3441 if (*StringPtr
== 0) {
3442 *Progress
= StringPtr
;
3443 Status
= EFI_SUCCESS
;
3445 AppendToMultiString(Config
, ConfigRequest
);
3446 HiiToLower (*Config
);
3456 // Copy <ConfigHdr> and an additional '&' to <ConfigResp>
3458 TemChar
= *StringPtr
;
3460 AppendToMultiString(Config
, ConfigRequest
);
3461 *StringPtr
= TemChar
;
3464 // Parse each <RequestElement> if exists
3465 // Only <BlockName> format is supported by this help function.
3466 // <BlockName> ::= 'OFFSET='<Number>&'WIDTH='<Number>
3468 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"OFFSET=", StrLen (L
"OFFSET=")) == 0) {
3470 // Back up the header of one <BlockName>
3474 StringPtr
+= StrLen (L
"OFFSET=");
3478 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
3479 if (EFI_ERROR (Status
)) {
3480 *Progress
= ConfigRequest
;
3487 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
3489 FreePool (TmpBuffer
);
3491 StringPtr
+= Length
;
3492 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
3493 *Progress
= StringPtr
- Length
- StrLen (L
"OFFSET=") - 1;
3494 Status
= EFI_INVALID_PARAMETER
;
3497 StringPtr
+= StrLen (L
"&WIDTH=");
3502 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
3503 if (EFI_ERROR (Status
)) {
3504 *Progress
= ConfigRequest
;
3511 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
3513 FreePool (TmpBuffer
);
3515 StringPtr
+= Length
;
3516 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
3517 *Progress
= StringPtr
- Length
- StrLen (L
"&WIDTH=");
3518 Status
= EFI_INVALID_PARAMETER
;
3523 // Calculate Value and convert it to hex string.
3525 if (Offset
+ Width
> BlockSize
) {
3526 *Progress
= StringPtr
;
3527 Status
= EFI_DEVICE_ERROR
;
3531 Value
= (UINT8
*) AllocateZeroPool (Width
);
3532 if (Value
== NULL
) {
3533 *Progress
= ConfigRequest
;
3534 Status
= EFI_OUT_OF_RESOURCES
;
3538 CopyMem (Value
, (UINT8
*) Block
+ Offset
, Width
);
3540 Length
= Width
* 2 + 1;
3541 ValueStr
= (EFI_STRING
) AllocateZeroPool (Length
* sizeof (CHAR16
));
3542 if (ValueStr
== NULL
) {
3543 *Progress
= ConfigRequest
;
3544 Status
= EFI_OUT_OF_RESOURCES
;
3548 TemString
= ValueStr
;
3549 TemBuffer
= Value
+ Width
- 1;
3550 for (Index
= 0; Index
< Width
; Index
++, TemBuffer
--) {
3551 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
3558 // Build a ConfigElement
3560 Length
+= StringPtr
- TmpPtr
+ 1 + StrLen (L
"VALUE=");
3561 ConfigElement
= (EFI_STRING
) AllocateZeroPool (Length
* sizeof (CHAR16
));
3562 if (ConfigElement
== NULL
) {
3563 Status
= EFI_OUT_OF_RESOURCES
;
3566 CopyMem (ConfigElement
, TmpPtr
, (StringPtr
- TmpPtr
+ 1) * sizeof (CHAR16
));
3567 if (*StringPtr
== 0) {
3568 *(ConfigElement
+ (StringPtr
- TmpPtr
)) = L
'&';
3570 *(ConfigElement
+ (StringPtr
- TmpPtr
) + 1) = 0;
3571 StrCat (ConfigElement
, L
"VALUE=");
3572 StrCat (ConfigElement
, ValueStr
);
3574 AppendToMultiString (Config
, ConfigElement
);
3576 FreePool (ConfigElement
);
3577 FreePool (ValueStr
);
3578 ConfigElement
= NULL
;
3582 // If '\0', parsing is finished. Otherwise skip '&' to continue
3584 if (*StringPtr
== 0) {
3587 AppendToMultiString (Config
, L
"&");
3592 if (*StringPtr
!= 0) {
3593 *Progress
= StringPtr
- 1;
3594 Status
= EFI_INVALID_PARAMETER
;
3598 HiiToLower (*Config
);
3599 *Progress
= StringPtr
;
3603 if (*Config
!= NULL
) {
3607 if (ValueStr
!= NULL
) {
3608 FreePool (ValueStr
);
3610 if (Value
!= NULL
) {
3613 if (ConfigElement
!= NULL
) {
3614 FreePool (ConfigElement
);
3623 This helper function is to be called by drivers to map configuration strings
3624 to configurations stored in byte array ("block") formats such as UEFI Variables.
3626 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
3628 @param ConfigResp A null-terminated Unicode string in <ConfigResp>
3630 @param Block A possibly null array of bytes representing the
3631 current block. Only bytes referenced in the
3632 ConfigResp string in the block are modified. If
3633 this parameter is null or if the *BlockSize
3634 parameter is (on input) shorter than required by
3635 the Configuration string, only the BlockSize
3636 parameter is updated and an appropriate status
3637 (see below) is returned.
3638 @param BlockSize The length of the Block in units of UINT8. On
3639 input, this is the size of the Block. On output,
3640 if successful, contains the index of the last
3641 modified byte in the Block.
3642 @param Progress On return, points to an element of the ConfigResp
3643 string filled in with the offset of the most
3644 recent '&' before the first failing name / value
3645 pair (or the beginning of the string if the
3646 failure is in the first name / value pair) or the
3647 terminating NULL if all was successful.
3649 @retval EFI_SUCCESS The request succeeded. Progress points to the null
3650 terminator at the end of the ConfigResp string.
3651 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress
3652 points to the first character of ConfigResp.
3653 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigResp or
3654 Block parameter would result in this type of
3655 error. Progress points to the first character of
3657 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted name /
3658 value pair. Block is left updated and
3659 Progress points at the '&' preceding the first
3661 @retval EFI_DEVICE_ERROR Block not large enough. Progress undefined.
3662 @retval EFI_NOT_FOUND Target for the specified routing data was not found.
3663 Progress points to the "G" in "GUID" of the errant
3670 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
3671 IN CONST EFI_STRING ConfigResp
,
3672 IN OUT UINT8
*Block
,
3673 IN OUT UINTN
*BlockSize
,
3674 OUT EFI_STRING
*Progress
3677 HII_DATABASE_PRIVATE_DATA
*Private
;
3678 EFI_STRING StringPtr
;
3688 if (This
== NULL
|| BlockSize
== NULL
|| Progress
== NULL
) {
3689 return EFI_INVALID_PARAMETER
;
3692 *Progress
= ConfigResp
;
3693 if (ConfigResp
== NULL
) {
3694 return EFI_INVALID_PARAMETER
;
3697 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
3698 ASSERT (Private
!= NULL
);
3700 StringPtr
= ConfigResp
;
3701 BufferSize
= *BlockSize
;
3708 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
3709 *Progress
= StringPtr
;
3710 Status
= EFI_INVALID_PARAMETER
;
3713 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"PATH=", StrLen (L
"PATH=")) != 0) {
3716 if (*StringPtr
== 0) {
3717 *Progress
= StringPtr
;
3718 Status
= EFI_INVALID_PARAMETER
;
3722 while (*StringPtr
!= L
'&' && *StringPtr
!= 0) {
3725 if (*StringPtr
== 0) {
3726 *Progress
= StringPtr
;
3727 Status
= EFI_INVALID_PARAMETER
;
3736 // Parse each <ConfigElement> if exists
3737 // Only <BlockConfig> format is supported by this help function.
3738 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE='<Number>
3740 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"OFFSET=", StrLen (L
"OFFSET=")) == 0) {
3741 StringPtr
+= StrLen (L
"OFFSET=");
3745 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
3746 if (EFI_ERROR (Status
)) {
3747 *Progress
= ConfigResp
;
3754 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
3756 FreePool (TmpBuffer
);
3758 StringPtr
+= Length
;
3759 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
3760 *Progress
= StringPtr
- Length
- StrLen (L
"OFFSET=") - 1;
3761 Status
= EFI_INVALID_PARAMETER
;
3764 StringPtr
+= StrLen (L
"&WIDTH=");
3769 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
3770 if (EFI_ERROR (Status
)) {
3771 *Progress
= ConfigResp
;
3778 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
3780 FreePool (TmpBuffer
);
3782 StringPtr
+= Length
;
3783 if (StrnCmp (StringPtr
, L
"&VALUE=", StrLen (L
"&VALUE=")) != 0) {
3784 *Progress
= StringPtr
- Length
- StrLen (L
"&WIDTH=");
3785 Status
= EFI_INVALID_PARAMETER
;
3788 StringPtr
+= StrLen (L
"&VALUE=");
3793 Status
= GetValueOfNumber (StringPtr
, &Value
, &Length
);
3794 if (EFI_ERROR (Status
)) {
3795 *Progress
= ConfigResp
;
3799 StringPtr
+= Length
;
3800 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
3801 *Progress
= StringPtr
- Length
- 7;
3802 Status
= EFI_INVALID_PARAMETER
;
3807 // Update the Block with configuration info
3809 if ((Block
!= NULL
) && (Offset
+ Width
<= BufferSize
)) {
3810 CopyMem (Block
+ Offset
, Value
, Width
);
3812 if (Offset
+ Width
> MaxBlockSize
) {
3813 MaxBlockSize
= Offset
+ Width
;
3820 // If '\0', parsing is finished. Otherwise skip '&' to continue
3822 if (*StringPtr
== 0) {
3830 // The input string is ConfigAltResp format.
3832 if ((*StringPtr
!= 0) && (StrnCmp (StringPtr
, L
"&GUID=", StrLen (L
"&GUID=")) != 0)) {
3833 *Progress
= StringPtr
- 1;
3834 Status
= EFI_INVALID_PARAMETER
;
3838 *Progress
= StringPtr
+ StrLen (StringPtr
);
3839 *BlockSize
= MaxBlockSize
- 1;
3841 if (MaxBlockSize
> BufferSize
) {
3842 *BlockSize
= MaxBlockSize
;
3843 if (Block
!= NULL
) {
3844 return EFI_DEVICE_ERROR
;
3848 if (Block
== NULL
) {
3849 *Progress
= ConfigResp
;
3850 return EFI_INVALID_PARAMETER
;
3857 if (Value
!= NULL
) {
3865 This helper function is to be called by drivers to extract portions of
3866 a larger configuration string.
3868 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
3870 @param Configuration A null-terminated Unicode string in
3871 <MultiConfigAltResp> format.
3872 @param Guid A pointer to the GUID value to search for in the
3873 routing portion of the ConfigResp string when
3874 retrieving the requested data. If Guid is NULL,
3875 then all GUID values will be searched for.
3876 @param Name A pointer to the NAME value to search for in the
3877 routing portion of the ConfigResp string when
3878 retrieving the requested data. If Name is NULL,
3879 then all Name values will be searched for.
3880 @param DevicePath A pointer to the PATH value to search for in the
3881 routing portion of the ConfigResp string when
3882 retrieving the requested data. If DevicePath is
3883 NULL, then all DevicePath values will be searched
3885 @param AltCfgId A pointer to the ALTCFG value to search for in the
3886 routing portion of the ConfigResp string when
3887 retrieving the requested data. If this parameter
3888 is NULL, then the current setting will be
3890 @param AltCfgResp A pointer to a buffer which will be allocated by
3891 the function which contains the retrieved string
3892 as requested. This buffer is only allocated if
3893 the call was successful. It is <ConfigResp> format.
3895 @retval EFI_SUCCESS The request succeeded. The requested data was
3896 extracted and placed in the newly allocated
3898 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate AltCfgResp.
3899 @retval EFI_INVALID_PARAMETER Any parameter is invalid.
3900 @retval EFI_NOT_FOUND Target for the specified routing data was not
3907 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
3908 IN CONST EFI_STRING Configuration
,
3909 IN CONST EFI_GUID
*Guid
,
3910 IN CONST EFI_STRING Name
,
3911 IN CONST EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
3912 IN CONST UINT16
*AltCfgId
,
3913 OUT EFI_STRING
*AltCfgResp
3917 EFI_STRING StringPtr
;
3918 EFI_STRING HdrStart
;
3925 EFI_STRING AltIdStr
;
3942 if (This
== NULL
|| Configuration
== NULL
|| AltCfgResp
== NULL
) {
3943 return EFI_INVALID_PARAMETER
;
3946 StringPtr
= Configuration
;
3947 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
3948 return EFI_INVALID_PARAMETER
;
3952 // Generate the sub string for later matching.
3954 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*) Guid
, 1, &GuidStr
);
3957 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) DevicePath
),
3958 (VOID
*) DevicePath
,
3962 if (AltCfgId
!= NULL
) {
3963 GenerateSubStr (L
"ALTCFG=", sizeof (UINT16
), (VOID
*) AltCfgId
, 3, &AltIdStr
);
3966 GenerateSubStr (L
"NAME=", StrLen (Name
) * sizeof (CHAR16
), (VOID
*) Name
, 2, &NameStr
);
3968 GenerateSubStr (L
"NAME=", 0, NULL
, 2, &NameStr
);
3971 while (*StringPtr
!= 0) {
3973 // Try to match the GUID
3976 TmpPtr
= StrStr (StringPtr
, GuidStr
);
3977 if (TmpPtr
== NULL
) {
3978 Status
= EFI_NOT_FOUND
;
3984 // Jump to <NameHdr>
3987 StringPtr
= TmpPtr
+ StrLen (GuidStr
);
3989 StringPtr
= StrStr (TmpPtr
, L
"NAME=");
3990 if (StringPtr
== NULL
) {
3991 Status
= EFI_NOT_FOUND
;
3999 // Try to match the NAME
4001 if (GuidFlag
&& !NameFlag
) {
4002 if (StrnCmp (StringPtr
, NameStr
, StrLen (NameStr
)) != 0) {
4006 // Jump to <PathHdr>
4009 StringPtr
+= StrLen (NameStr
);
4011 StringPtr
= StrStr (StringPtr
, L
"PATH=");
4012 if (StringPtr
== NULL
) {
4013 Status
= EFI_NOT_FOUND
;
4022 // Try to match the DevicePath
4024 if (GuidFlag
&& NameFlag
&& !PathFlag
) {
4025 if (StrnCmp (StringPtr
, PathStr
, StrLen (PathStr
)) != 0) {
4030 // Jump to '&' before <DescHdr> or <ConfigBody>
4032 if (DevicePath
!= NULL
) {
4033 StringPtr
+= StrLen (PathStr
);
4035 StringPtr
= StrStr (StringPtr
, L
"&");
4036 if (StringPtr
== NULL
) {
4037 Status
= EFI_NOT_FOUND
;
4048 // Try to match the AltCfgId
4050 if (GuidFlag
&& NameFlag
&& PathFlag
) {
4051 if (AltCfgId
== NULL
) {
4053 // Return Current Setting when AltCfgId is NULL.
4055 Status
= OutputConfigBody (StringPtr
, &Result
);
4059 // Search the <ConfigAltResp> to get the <AltResp> with AltCfgId.
4061 if (StrnCmp (StringPtr
, AltIdStr
, StrLen (AltIdStr
)) != 0) {
4067 // Skip AltIdStr and &
4069 StringPtr
= StringPtr
+ StrLen (AltIdStr
);
4070 Status
= OutputConfigBody (StringPtr
, &Result
);
4076 Status
= EFI_NOT_FOUND
;
4080 if (!EFI_ERROR (Status
) && (Result
!= NULL
)) {
4082 // Copy the <ConfigHdr> and <ConfigBody>
4084 Length
= HdrEnd
- HdrStart
+ StrLen (Result
) + 1;
4085 *AltCfgResp
= AllocateZeroPool (Length
* sizeof (CHAR16
));
4086 if (*AltCfgResp
== NULL
) {
4087 Status
= EFI_OUT_OF_RESOURCES
;
4089 StrnCpy (*AltCfgResp
, HdrStart
, HdrEnd
- HdrStart
);
4090 StrCat (*AltCfgResp
, Result
);
4091 Status
= EFI_SUCCESS
;
4095 if (GuidStr
!= NULL
) {
4098 if (NameStr
!= NULL
) {
4101 if (PathStr
!= NULL
) {
4104 if (AltIdStr
!= NULL
) {
4105 FreePool (AltIdStr
);
4107 if (Result
!= NULL
) {