2 Implementation of interfaces function for EFI_HII_CONFIG_ROUTING_PROTOCOL.
4 Copyright (c) 2007 - 2012, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 #include "HiiDatabase.h"
17 extern HII_DATABASE_PRIVATE_DATA mPrivate
;
20 Calculate the number of Unicode characters of the incoming Configuration string,
21 not including NULL terminator.
23 This is a internal function.
25 @param String String in <MultiConfigRequest> or
26 <MultiConfigResp> format.
28 @return The number of Unicode characters.
32 CalculateConfigStringLen (
39 // "GUID=" should be the first element of incoming string.
41 ASSERT (String
!= NULL
);
42 ASSERT (StrnCmp (String
, L
"GUID=", StrLen (L
"GUID=")) == 0);
45 // The beginning of next <ConfigRequest>/<ConfigResp> should be "&GUID=".
46 // Will meet '\0' if there is only one <ConfigRequest>/<ConfigResp>.
48 TmpPtr
= StrStr (String
, L
"&GUID=");
50 return StrLen (String
);
53 return (TmpPtr
- String
);
58 Convert the hex UNICODE %02x encoding of a UEFI device path to binary
59 from <PathHdr> of <ConfigHdr>.
61 This is a internal function.
63 @param String UEFI configuration string
64 @param DevicePathData Binary of a UEFI device path.
66 @retval EFI_NOT_FOUND The device path is not invalid.
67 @retval EFI_INVALID_PARAMETER Any incoming parameter is invalid.
68 @retval EFI_OUT_OF_RESOURCES Lake of resources to store neccesary structures.
69 @retval EFI_SUCCESS The device path is retrieved and translated to
76 OUT UINT8
**DevicePathData
81 UINT8
*DevicePathBuffer
;
85 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
88 if (String
== NULL
|| DevicePathData
== NULL
) {
89 return EFI_INVALID_PARAMETER
;
93 // Find the 'PATH=' of <PathHdr> and skip it.
95 for (; (*String
!= 0 && StrnCmp (String
, L
"PATH=", StrLen (L
"PATH=")) != 0); String
++);
97 return EFI_INVALID_PARAMETER
;
100 // Check whether path data does exist.
102 String
+= StrLen (L
"PATH=");
104 return EFI_INVALID_PARAMETER
;
109 // The content between 'PATH=' of <ConfigHdr> and '&' of next element
110 // or '\0' (end of configuration string) is the UNICODE %02x bytes encoding
111 // of UEFI device path.
113 for (Length
= 0; *String
!= 0 && *String
!= L
'&'; String
++, Length
++);
115 // Check DevicePath Length
117 if (((Length
+ 1) / 2) < sizeof (EFI_DEVICE_PATH_PROTOCOL
)) {
118 return EFI_NOT_FOUND
;
122 // The data in <PathHdr> is encoded as hex UNICODE %02x bytes in the same order
123 // as the device path resides in RAM memory.
124 // Translate the data into binary.
126 DevicePathBuffer
= (UINT8
*) AllocateZeroPool ((Length
+ 1) / 2);
127 if (DevicePathBuffer
== NULL
) {
128 return EFI_OUT_OF_RESOURCES
;
132 // Convert DevicePath
134 ZeroMem (TemStr
, sizeof (TemStr
));
135 for (Index
= 0; Index
< Length
; Index
++) {
136 TemStr
[0] = PathHdr
[Index
];
137 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
138 if ((Index
& 1) == 0) {
139 DevicePathBuffer
[Index
/2] = DigitUint8
;
141 DevicePathBuffer
[Index
/2] = (UINT8
) ((DevicePathBuffer
[Index
/2] << 4) + DigitUint8
);
146 // Validate DevicePath
148 DevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) DevicePathBuffer
;
149 while (!IsDevicePathEnd (DevicePath
)) {
150 if ((DevicePath
->Type
== 0) || (DevicePath
->SubType
== 0) || (DevicePathNodeLength (DevicePath
) < sizeof (EFI_DEVICE_PATH_PROTOCOL
))) {
152 // Invalid device path
154 FreePool (DevicePathBuffer
);
155 return EFI_NOT_FOUND
;
157 DevicePath
= NextDevicePathNode (DevicePath
);
161 // return the device path
163 *DevicePathData
= DevicePathBuffer
;
168 Converts the unicode character of the string from uppercase to lowercase.
169 This is a internal function.
171 @param ConfigString String to be converted
177 IN EFI_STRING ConfigString
183 ASSERT (ConfigString
!= NULL
);
186 // Convert all hex digits in range [A-F] in the configuration header to [a-f]
188 for (String
= ConfigString
, Lower
= FALSE
; *String
!= L
'\0'; String
++) {
189 if (*String
== L
'=') {
191 } else if (*String
== L
'&') {
193 } else if (Lower
&& *String
>= L
'A' && *String
<= L
'F') {
194 *String
= (CHAR16
) (*String
- L
'A' + L
'a');
202 Generate a sub string then output it.
204 This is a internal function.
206 @param String A constant string which is the prefix of the to be
207 generated string, e.g. GUID=
209 @param BufferLen The length of the Buffer in bytes.
211 @param Buffer Points to a buffer which will be converted to be the
212 content of the generated string.
214 @param Flag If 1, the buffer contains data for the value of GUID or PATH stored in
215 UINT8 *; if 2, the buffer contains unicode string for the value of NAME;
216 if 3, the buffer contains other data.
218 @param SubStr Points to the output string. It's caller's
219 responsibility to free this buffer.
225 IN CONST EFI_STRING String
,
229 OUT EFI_STRING
*SubStr
234 EFI_STRING StringHeader
;
240 ASSERT (String
!= NULL
&& SubStr
!= NULL
);
242 if (Buffer
== NULL
) {
243 *SubStr
= AllocateCopyPool (StrSize (String
), String
);
244 ASSERT (*SubStr
!= NULL
);
249 // Header + Data + '&' + '\0'
251 Length
= StrLen (String
) + BufferLen
* 2 + 1 + 1;
252 Str
= AllocateZeroPool (Length
* sizeof (CHAR16
));
253 ASSERT (Str
!= NULL
);
255 StrCpy (Str
, String
);
256 Length
= (BufferLen
* 2 + 1) * sizeof (CHAR16
);
258 StringHeader
= Str
+ StrLen (String
);
259 TemString
= (CHAR16
*) StringHeader
;
264 // Convert Buffer to Hex String in reverse order
266 TemBuffer
= ((UINT8
*) Buffer
);
267 for (Index
= 0; Index
< BufferLen
; Index
++, TemBuffer
++) {
268 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
273 // Check buffer is enough
275 TemName
= (CHAR16
*) Buffer
;
276 ASSERT ((BufferLen
* 2 + 1) >= (StrLen (TemName
) * 4 + 1));
278 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
280 for (; *TemName
!= L
'\0'; TemName
++) {
281 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemName
, 4);
286 // Convert Buffer to Hex String
288 TemBuffer
= ((UINT8
*) Buffer
) + BufferLen
- 1;
289 for (Index
= 0; Index
< BufferLen
; Index
++, TemBuffer
--) {
290 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
298 // Convert the uppercase to lowercase since <HexAf> is defined in lowercase format.
308 Retrieve the <ConfigBody> from String then output it.
310 This is a internal function.
312 @param String A sub string of a configuration string in
313 <MultiConfigAltResp> format.
314 @param ConfigBody Points to the output string. It's caller's
315 responsibility to free this buffer.
317 @retval EFI_INVALID_PARAMETER There is no form package in current hii database.
318 @retval EFI_OUT_OF_RESOURCES Not enough memory to finish this operation.
319 @retval EFI_SUCCESS All existing storage is exported.
324 IN EFI_STRING String
,
325 OUT EFI_STRING
*ConfigBody
332 if (String
== NULL
|| ConfigBody
== NULL
) {
333 return EFI_INVALID_PARAMETER
;
337 // The setting information should start OFFSET, not ALTCFG.
339 if (StrnCmp (String
, L
"&ALTCFG=", StrLen (L
"&ALTCFG=")) == 0) {
340 return EFI_INVALID_PARAMETER
;
343 TmpPtr
= StrStr (String
, L
"GUID=");
344 if (TmpPtr
== NULL
) {
346 // It is the last <ConfigResp> of the incoming configuration string.
348 Result
= AllocateCopyPool (StrSize (String
), String
);
349 if (Result
== NULL
) {
350 return EFI_OUT_OF_RESOURCES
;
352 *ConfigBody
= Result
;
357 Length
= TmpPtr
- String
;
358 Result
= AllocateCopyPool (Length
* sizeof (CHAR16
), String
);
359 if (Result
== NULL
) {
360 return EFI_OUT_OF_RESOURCES
;
363 *(Result
+ Length
- 1) = 0;
364 *ConfigBody
= Result
;
369 Append a string to a multi-string format.
371 This is a internal function.
373 @param MultiString String in <MultiConfigRequest>,
374 <MultiConfigAltResp>, or <MultiConfigResp>. On
375 input, the buffer length of this string is
376 MAX_STRING_LENGTH. On output, the buffer length
378 @param AppendString NULL-terminated Unicode string.
380 @retval EFI_INVALID_PARAMETER Any incoming parameter is invalid.
381 @retval EFI_SUCCESS AppendString is append to the end of MultiString
385 AppendToMultiString (
386 IN OUT EFI_STRING
*MultiString
,
387 IN EFI_STRING AppendString
390 UINTN AppendStringSize
;
391 UINTN MultiStringSize
;
393 if (MultiString
== NULL
|| *MultiString
== NULL
|| AppendString
== NULL
) {
394 return EFI_INVALID_PARAMETER
;
397 AppendStringSize
= StrSize (AppendString
);
398 MultiStringSize
= StrSize (*MultiString
);
401 // Enlarge the buffer each time when length exceeds MAX_STRING_LENGTH.
403 if (MultiStringSize
+ AppendStringSize
> MAX_STRING_LENGTH
||
404 MultiStringSize
> MAX_STRING_LENGTH
) {
405 *MultiString
= (EFI_STRING
) ReallocatePool (
407 MultiStringSize
+ AppendStringSize
,
408 (VOID
*) (*MultiString
)
410 ASSERT (*MultiString
!= NULL
);
413 // Append the incoming string
415 StrCat (*MultiString
, AppendString
);
422 Get the value of <Number> in <BlockConfig> format, i.e. the value of OFFSET
424 <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>
426 This is a internal function.
428 @param StringPtr String in <BlockConfig> format and points to the
429 first character of <Number>.
430 @param Number The output value. Caller takes the responsibility
432 @param Len Length of the <Number>, in characters.
434 @retval EFI_OUT_OF_RESOURCES Insufficient resources to store neccessary
436 @retval EFI_SUCCESS Value of <Number> is outputted in Number
442 IN EFI_STRING StringPtr
,
456 if (StringPtr
== NULL
|| *StringPtr
== L
'\0' || Number
== NULL
|| Len
== NULL
) {
457 return EFI_INVALID_PARAMETER
;
463 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
466 *Len
= StringPtr
- TmpPtr
;
469 Str
= (EFI_STRING
) AllocateZeroPool (Length
* sizeof (CHAR16
));
471 Status
= EFI_OUT_OF_RESOURCES
;
474 CopyMem (Str
, TmpPtr
, *Len
* sizeof (CHAR16
));
475 *(Str
+ *Len
) = L
'\0';
477 Length
= (Length
+ 1) / 2;
478 Buf
= (UINT8
*) AllocateZeroPool (Length
);
480 Status
= EFI_OUT_OF_RESOURCES
;
485 ZeroMem (TemStr
, sizeof (TemStr
));
486 for (Index
= 0; Index
< Length
; Index
++) {
487 TemStr
[0] = Str
[Length
- Index
- 1];
488 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
489 if ((Index
& 1) == 0) {
490 Buf
[Index
/2] = DigitUint8
;
492 Buf
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Buf
[Index
/2]);
497 Status
= EFI_SUCCESS
;
508 This function merges DefaultAltCfgResp string into AltCfgResp string for
509 the missing AltCfgId in AltCfgResq.
511 @param AltCfgResp Pointer to a null-terminated Unicode string in
512 <ConfigAltResp> format. The default value string
513 will be merged into it.
514 @param DefaultAltCfgResp Pointer to a null-terminated Unicode string in
515 <MultiConfigAltResp> format. The default value
516 string may contain more than one ConfigAltResp
517 string for the different varstore buffer.
519 @retval EFI_SUCCESS The merged string returns.
520 @retval EFI_INVALID_PARAMETER *AltCfgResp is to NULL.
525 IN OUT EFI_STRING
*AltCfgResp
,
526 IN EFI_STRING DefaultAltCfgResp
529 EFI_STRING StringPtrDefault
;
530 EFI_STRING StringPtrEnd
;
532 EFI_STRING StringPtr
;
533 EFI_STRING AltConfigHdr
;
535 UINTN SizeAltCfgResp
;
537 if (*AltCfgResp
== NULL
) {
538 return EFI_INVALID_PARAMETER
;
542 // Get the requestr ConfigHdr
545 StringPtr
= *AltCfgResp
;
548 // Find <ConfigHdr> GUID=...&NAME=...&PATH=...
550 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
551 return EFI_INVALID_PARAMETER
;
553 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&NAME=", StrLen (L
"&NAME=")) != 0) {
556 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&PATH=", StrLen (L
"&PATH=")) != 0) {
559 if (*StringPtr
== L
'\0') {
560 return EFI_INVALID_PARAMETER
;
562 StringPtr
+= StrLen (L
"&PATH=");
563 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
566 HeaderLength
= StringPtr
- *AltCfgResp
;
569 // Construct AltConfigHdr string "&<ConfigHdr>&ALTCFG=XXXX\0"
570 // |1| StrLen (ConfigHdr) | 8 | 4 | 1 |
572 AltConfigHdr
= AllocateZeroPool ((1 + HeaderLength
+ 8 + 4 + 1) * sizeof (CHAR16
));
573 if (AltConfigHdr
== NULL
) {
574 return EFI_OUT_OF_RESOURCES
;
576 StrCpy (AltConfigHdr
, L
"&");
577 StrnCat (AltConfigHdr
, *AltCfgResp
, HeaderLength
);
578 StrCat (AltConfigHdr
, L
"&ALTCFG=");
579 HeaderLength
= StrLen (AltConfigHdr
);
581 StringPtrDefault
= StrStr (DefaultAltCfgResp
, AltConfigHdr
);
582 while (StringPtrDefault
!= NULL
) {
586 StrnCat (AltConfigHdr
, StringPtrDefault
+ HeaderLength
, 4);
587 StringPtr
= StrStr (*AltCfgResp
, AltConfigHdr
);
590 // Append the found default value string to the input AltCfgResp
592 if (StringPtr
== NULL
) {
593 StringPtrEnd
= StrStr (StringPtrDefault
+ 1, L
"&GUID");
594 SizeAltCfgResp
= StrSize (*AltCfgResp
);
595 if (StringPtrEnd
== NULL
) {
597 // No more default string is found.
599 *AltCfgResp
= (EFI_STRING
) ReallocatePool (
601 SizeAltCfgResp
+ StrSize (StringPtrDefault
),
602 (VOID
*) (*AltCfgResp
)
604 if (*AltCfgResp
== NULL
) {
605 FreePool (AltConfigHdr
);
606 return EFI_OUT_OF_RESOURCES
;
608 StrCat (*AltCfgResp
, StringPtrDefault
);
611 TempChar
= *StringPtrEnd
;
612 *StringPtrEnd
= L
'\0';
613 *AltCfgResp
= (EFI_STRING
) ReallocatePool (
615 SizeAltCfgResp
+ StrSize (StringPtrDefault
),
616 (VOID
*) (*AltCfgResp
)
618 if (*AltCfgResp
== NULL
) {
619 FreePool (AltConfigHdr
);
620 return EFI_OUT_OF_RESOURCES
;
622 StrCat (*AltCfgResp
, StringPtrDefault
);
623 *StringPtrEnd
= TempChar
;
628 // Find next AltCfg String
630 *(AltConfigHdr
+ HeaderLength
) = L
'\0';
631 StringPtrDefault
= StrStr (StringPtrDefault
+ 1, AltConfigHdr
);
634 FreePool (AltConfigHdr
);
639 This function inserts new DefaultValueData into the BlockData DefaultValue array.
641 @param BlockData The BlockData is updated to add new default value.
642 @param DefaultValueData The DefaultValue is added.
647 IN IFR_BLOCK_DATA
*BlockData
,
648 IN IFR_DEFAULT_DATA
*DefaultValueData
652 IFR_DEFAULT_DATA
*DefaultValueArray
;
654 for (Link
= BlockData
->DefaultValueEntry
.ForwardLink
; Link
!= &BlockData
->DefaultValueEntry
; Link
= Link
->ForwardLink
) {
655 DefaultValueArray
= BASE_CR (Link
, IFR_DEFAULT_DATA
, Entry
);
656 if (DefaultValueArray
->DefaultId
== DefaultValueData
->DefaultId
) {
658 // DEFAULT_VALUE_FROM_OPCODE has high priority, DEFAULT_VALUE_FROM_DEFAULT has low priority.
660 if (DefaultValueData
->Type
> DefaultValueArray
->Type
) {
662 // Update the default value array in BlockData.
664 CopyMem (&DefaultValueArray
->Value
, &DefaultValueData
->Value
, sizeof (EFI_IFR_TYPE_VALUE
));
665 DefaultValueArray
->Type
= DefaultValueData
->Type
;
666 DefaultValueArray
->Cleaned
= DefaultValueData
->Cleaned
;
673 // Insert new default value data in tail.
675 DefaultValueArray
= AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
676 ASSERT (DefaultValueArray
!= NULL
);
677 CopyMem (DefaultValueArray
, DefaultValueData
, sizeof (IFR_DEFAULT_DATA
));
678 InsertTailList (Link
, &DefaultValueArray
->Entry
);
682 This function inserts new BlockData into the block link
684 @param BlockLink The list entry points to block array.
685 @param BlockData The point to BlockData is added.
690 IN LIST_ENTRY
*BlockLink
,
691 IN IFR_BLOCK_DATA
**BlockData
695 IFR_BLOCK_DATA
*BlockArray
;
696 IFR_BLOCK_DATA
*BlockSingleData
;
698 BlockSingleData
= *BlockData
;
701 // Insert block data in its Offset and Width order.
703 for (Link
= BlockLink
->ForwardLink
; Link
!= BlockLink
; Link
= Link
->ForwardLink
) {
704 BlockArray
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
705 if (BlockArray
->Offset
== BlockSingleData
->Offset
) {
706 if (BlockArray
->Width
> BlockSingleData
->Width
) {
708 // Insert this block data in the front of block array
710 InsertTailList (Link
, &BlockSingleData
->Entry
);
714 if (BlockArray
->Width
== BlockSingleData
->Width
) {
716 // The same block array has been added.
718 FreePool (BlockSingleData
);
719 *BlockData
= BlockArray
;
722 } else if (BlockArray
->Offset
> BlockSingleData
->Offset
) {
724 // Insert new block data in the front of block array
726 InsertTailList (Link
, &BlockSingleData
->Entry
);
732 // Add new block data into the tail.
734 InsertTailList (Link
, &BlockSingleData
->Entry
);
739 This function checks VarOffset and VarWidth is in the block range.
741 @param RequestBlockArray The block array is to be checked.
742 @param VarOffset Offset of var to the structure
743 @param VarWidth Width of var.
745 @retval TRUE This Var is in the block range.
746 @retval FALSE This Var is not in the block range.
750 IN IFR_BLOCK_DATA
*RequestBlockArray
,
756 IFR_BLOCK_DATA
*BlockData
;
759 // No Request Block array, all vars are got.
761 if (RequestBlockArray
== NULL
) {
766 // Check the input var is in the request block range.
768 for (Link
= RequestBlockArray
->Entry
.ForwardLink
; Link
!= &RequestBlockArray
->Entry
; Link
= Link
->ForwardLink
) {
769 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
770 if ((VarOffset
>= BlockData
->Offset
) && ((VarOffset
+ VarWidth
) <= (BlockData
->Offset
+ BlockData
->Width
))) {
779 Get form package data from data base.
781 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
782 @param HiiFormPackage The buffer saves the package data.
783 @param PackageSize The buffer size of the package data.
788 IN HII_DATABASE_RECORD
*DataBaseRecord
,
789 IN OUT UINT8
**HiiFormPackage
,
790 OUT UINTN
*PackageSize
797 if (DataBaseRecord
== NULL
|| HiiFormPackage
== NULL
|| PackageSize
== NULL
) {
798 return EFI_INVALID_PARAMETER
;
804 // 0. Get Hii Form Package by HiiHandle
806 Status
= ExportFormPackages (
808 DataBaseRecord
->Handle
,
809 DataBaseRecord
->PackageList
,
815 if (EFI_ERROR (Status
)) {
819 (*HiiFormPackage
) = AllocatePool (ResultSize
);
820 if (*HiiFormPackage
== NULL
) {
821 Status
= EFI_OUT_OF_RESOURCES
;
826 // Get HiiFormPackage by HiiHandle
830 Status
= ExportFormPackages (
832 DataBaseRecord
->Handle
,
833 DataBaseRecord
->PackageList
,
839 if (EFI_ERROR (Status
)) {
840 FreePool (*HiiFormPackage
);
850 This function parses Form Package to get the efi varstore info according to the request ConfigHdr.
852 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
853 @param ConfigHdr Request string ConfigHdr. If it is NULL,
854 the first found varstore will be as ConfigHdr.
855 @param IsEfiVarstore Whether the request storage type is efi varstore type.
856 @param EfiVarStore The efi varstore info which will return.
860 IN HII_DATABASE_RECORD
*DataBaseRecord
,
861 IN EFI_STRING ConfigHdr
,
862 OUT BOOLEAN
*IsEfiVarstore
,
863 OUT EFI_IFR_VARSTORE_EFI
**EfiVarStore
869 EFI_IFR_OP_HEADER
*IfrOpHdr
;
870 CHAR16
*VarStoreName
;
875 UINT8
*HiiFormPackage
;
877 EFI_IFR_VARSTORE_EFI
*IfrEfiVarStore
;
879 HiiFormPackage
= NULL
;
881 Status
= EFI_SUCCESS
;
886 Status
= GetFormPackageData(DataBaseRecord
, &HiiFormPackage
, &PackageSize
);
887 if (EFI_ERROR (Status
)) {
891 IfrOffset
= sizeof (EFI_HII_PACKAGE_HEADER
);
892 while (IfrOffset
< PackageSize
) {
893 IfrOpHdr
= (EFI_IFR_OP_HEADER
*) (HiiFormPackage
+ IfrOffset
);
894 IfrOffset
+= IfrOpHdr
->Length
;
896 if (IfrOpHdr
->OpCode
== EFI_IFR_VARSTORE_EFI_OP
) {
897 IfrEfiVarStore
= (EFI_IFR_VARSTORE_EFI
*) IfrOpHdr
;
899 // If the length is small than the structure, this is from old efi
900 // varstore definition. Old efi varstore get config directly from
901 // GetVariable function.
903 if (IfrOpHdr
->Length
< sizeof (EFI_IFR_VARSTORE_EFI
)) {
907 VarStoreName
= AllocateZeroPool (AsciiStrSize ((CHAR8
*)IfrEfiVarStore
->Name
) * sizeof (CHAR16
));
908 if (VarStoreName
== NULL
) {
909 Status
= EFI_OUT_OF_RESOURCES
;
912 AsciiStrToUnicodeStr ((CHAR8
*) IfrEfiVarStore
->Name
, VarStoreName
);
914 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*) &IfrEfiVarStore
->Guid
, 1, &GuidStr
);
915 GenerateSubStr (L
"NAME=", StrLen (VarStoreName
) * sizeof (CHAR16
), (VOID
*) VarStoreName
, 2, &NameStr
);
916 LengthString
= StrLen (GuidStr
);
917 LengthString
= LengthString
+ StrLen (NameStr
) + 1;
918 TempStr
= AllocateZeroPool (LengthString
* sizeof (CHAR16
));
919 if (TempStr
== NULL
) {
922 FreePool (VarStoreName
);
923 Status
= EFI_OUT_OF_RESOURCES
;
926 StrCpy (TempStr
, GuidStr
);
927 StrCat (TempStr
, NameStr
);
928 if (ConfigHdr
== NULL
|| StrnCmp (ConfigHdr
, TempStr
, StrLen (TempStr
)) == 0) {
929 *EfiVarStore
= (EFI_IFR_VARSTORE_EFI
*) AllocateZeroPool (IfrOpHdr
->Length
);
930 if (*EfiVarStore
== NULL
) {
931 FreePool (VarStoreName
);
935 Status
= EFI_OUT_OF_RESOURCES
;
938 *IsEfiVarstore
= TRUE
;
939 CopyMem (*EfiVarStore
, IfrEfiVarStore
, IfrOpHdr
->Length
);
943 // Free alllocated temp string.
945 FreePool (VarStoreName
);
952 if (HiiFormPackage
!= NULL
) {
953 FreePool (HiiFormPackage
);
960 This function parses Form Package to get the block array and the default
961 value array according to the request ConfigHdr.
963 @param Package Pointer to the form package data.
964 @param PackageLength Length of the pacakge.
965 @param ConfigHdr Request string ConfigHdr. If it is NULL,
966 the first found varstore will be as ConfigHdr.
967 @param RequestBlockArray The block array is retrieved from the request string.
968 @param VarStorageData VarStorage structure contains the got block and default value.
969 @param PIfrDefaultIdArray Point to the got default id and default name array.
971 @retval EFI_SUCCESS The block array and the default value array are got.
972 @retval EFI_INVALID_PARAMETER The varstore defintion in the differnt form pacakges
974 @retval EFI_OUT_OF_RESOURCES No enough memory.
980 IN UINT32 PackageLength
,
981 IN EFI_STRING ConfigHdr
,
982 IN IFR_BLOCK_DATA
*RequestBlockArray
,
983 IN OUT IFR_VARSTORAGE_DATA
*VarStorageData
,
984 OUT IFR_DEFAULT_DATA
*DefaultIdArray
989 EFI_IFR_VARSTORE
*IfrVarStore
;
990 EFI_IFR_VARSTORE_EFI
*IfrEfiVarStore
;
991 EFI_IFR_OP_HEADER
*IfrOpHdr
;
992 EFI_IFR_ONE_OF
*IfrOneOf
;
993 EFI_IFR_REF4
*IfrRef
;
994 EFI_IFR_ONE_OF_OPTION
*IfrOneOfOption
;
995 EFI_IFR_DEFAULT
*IfrDefault
;
996 EFI_IFR_ORDERED_LIST
*IfrOrderedList
;
997 EFI_IFR_CHECKBOX
*IfrCheckBox
;
998 EFI_IFR_PASSWORD
*IfrPassword
;
999 EFI_IFR_STRING
*IfrString
;
1000 EFI_IFR_DATE
*IfrDate
;
1001 EFI_IFR_TIME
*IfrTime
;
1002 IFR_DEFAULT_DATA DefaultData
;
1003 IFR_DEFAULT_DATA
*DefaultDataPtr
;
1004 IFR_BLOCK_DATA
*BlockData
;
1005 CHAR16
*VarStoreName
;
1008 UINT16 VarDefaultId
;
1013 BOOLEAN FirstOneOfOption
;
1014 LIST_ENTRY
*LinkData
;
1015 LIST_ENTRY
*LinkDefault
;
1018 Status
= EFI_SUCCESS
;
1023 DefaultDataPtr
= NULL
;
1024 FirstOneOfOption
= FALSE
;
1025 ZeroMem (&DefaultData
, sizeof (IFR_DEFAULT_DATA
));
1028 // Go through the form package to parse OpCode one by one.
1030 IfrOffset
= sizeof (EFI_HII_PACKAGE_HEADER
);
1031 while (IfrOffset
< PackageLength
) {
1032 IfrOpHdr
= (EFI_IFR_OP_HEADER
*) (Package
+ IfrOffset
);
1034 switch (IfrOpHdr
->OpCode
) {
1035 case EFI_IFR_VARSTORE_OP
:
1037 // VarStore is found. Don't need to search any more.
1039 if (VarStorageData
->Size
!= 0) {
1044 // Get the requied varstore information
1045 // Add varstore by Guid and Name in ConfigHdr
1046 // Make sure Offset is in varstore size and varstoreid
1048 IfrVarStore
= (EFI_IFR_VARSTORE
*) IfrOpHdr
;
1049 VarStoreName
= AllocateZeroPool (AsciiStrSize ((CHAR8
*)IfrVarStore
->Name
) * sizeof (CHAR16
));
1050 if (VarStoreName
== NULL
) {
1051 Status
= EFI_OUT_OF_RESOURCES
;
1054 AsciiStrToUnicodeStr ((CHAR8
*) IfrVarStore
->Name
, VarStoreName
);
1056 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*) &IfrVarStore
->Guid
, 1, &GuidStr
);
1057 GenerateSubStr (L
"NAME=", StrLen (VarStoreName
) * sizeof (CHAR16
), (VOID
*) VarStoreName
, 2, &NameStr
);
1058 LengthString
= StrLen (GuidStr
);
1059 LengthString
= LengthString
+ StrLen (NameStr
) + 1;
1060 TempStr
= AllocateZeroPool (LengthString
* sizeof (CHAR16
));
1061 if (TempStr
== NULL
) {
1064 FreePool (VarStoreName
);
1065 Status
= EFI_OUT_OF_RESOURCES
;
1068 StrCpy (TempStr
, GuidStr
);
1069 StrCat (TempStr
, NameStr
);
1070 if (ConfigHdr
== NULL
|| StrnCmp (ConfigHdr
, TempStr
, StrLen (TempStr
)) == 0) {
1072 // Find the matched VarStore
1074 CopyGuid (&VarStorageData
->Guid
, (EFI_GUID
*) (VOID
*) &IfrVarStore
->Guid
);
1075 VarStorageData
->VarStoreId
= IfrVarStore
->VarStoreId
;
1076 VarStorageData
->Size
= IfrVarStore
->Size
;
1077 VarStorageData
->Name
= VarStoreName
;
1080 // No found, free the allocated memory
1082 FreePool (VarStoreName
);
1085 // Free alllocated temp string.
1092 case EFI_IFR_VARSTORE_EFI_OP
:
1094 // VarStore is found. Don't need to search any more.
1096 if (VarStorageData
->Size
!= 0) {
1101 // Get the requied varstore information
1102 // Add varstore by Guid and Name in ConfigHdr
1103 // Make sure Offset is in varstore size and varstoreid
1105 IfrEfiVarStore
= (EFI_IFR_VARSTORE_EFI
*) IfrOpHdr
;
1108 // If the length is small than the structure, this is from old efi
1109 // varstore definition. Old efi varstore get config directly from
1110 // GetVariable function.
1112 if (IfrOpHdr
->Length
< sizeof (EFI_IFR_VARSTORE_EFI
)) {
1116 VarStoreName
= AllocateZeroPool (AsciiStrSize ((CHAR8
*)IfrEfiVarStore
->Name
) * sizeof (CHAR16
));
1117 if (VarStoreName
== NULL
) {
1118 Status
= EFI_OUT_OF_RESOURCES
;
1121 AsciiStrToUnicodeStr ((CHAR8
*) IfrEfiVarStore
->Name
, VarStoreName
);
1123 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*) &IfrEfiVarStore
->Guid
, 1, &GuidStr
);
1124 GenerateSubStr (L
"NAME=", StrLen (VarStoreName
) * sizeof (CHAR16
), (VOID
*) VarStoreName
, 2, &NameStr
);
1125 LengthString
= StrLen (GuidStr
);
1126 LengthString
= LengthString
+ StrLen (NameStr
) + 1;
1127 TempStr
= AllocateZeroPool (LengthString
* sizeof (CHAR16
));
1128 if (TempStr
== NULL
) {
1131 FreePool (VarStoreName
);
1132 Status
= EFI_OUT_OF_RESOURCES
;
1135 StrCpy (TempStr
, GuidStr
);
1136 StrCat (TempStr
, NameStr
);
1137 if (ConfigHdr
== NULL
|| StrnCmp (ConfigHdr
, TempStr
, StrLen (TempStr
)) == 0) {
1139 // Find the matched VarStore
1141 CopyGuid (&VarStorageData
->Guid
, (EFI_GUID
*) (VOID
*) &IfrEfiVarStore
->Guid
);
1142 VarStorageData
->VarStoreId
= IfrEfiVarStore
->VarStoreId
;
1143 VarStorageData
->Size
= IfrEfiVarStore
->Size
;
1144 VarStorageData
->Name
= VarStoreName
;
1147 // No found, free the allocated memory
1149 FreePool (VarStoreName
);
1152 // Free alllocated temp string.
1159 case EFI_IFR_DEFAULTSTORE_OP
:
1161 // Add new the map between default id and default name.
1163 DefaultDataPtr
= (IFR_DEFAULT_DATA
*) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
1164 if (DefaultDataPtr
== NULL
) {
1165 Status
= EFI_OUT_OF_RESOURCES
;
1168 DefaultDataPtr
->DefaultId
= ((EFI_IFR_DEFAULTSTORE
*) IfrOpHdr
)->DefaultId
;
1169 InsertTailList (&DefaultIdArray
->Entry
, &DefaultDataPtr
->Entry
);
1170 DefaultDataPtr
= NULL
;
1173 case EFI_IFR_FORM_OP
:
1174 case EFI_IFR_FORM_MAP_OP
:
1176 // No matched varstore is found and directly return.
1178 if (VarStorageData
->Size
== 0) {
1179 Status
= EFI_SUCCESS
;
1184 case EFI_IFR_REF_OP
:
1186 // Ref question is not in IFR Form. This IFR form is not valid.
1188 if (VarStorageData
->Size
== 0) {
1189 Status
= EFI_INVALID_PARAMETER
;
1193 // Check whether this question is for the requested varstore.
1195 IfrRef
= (EFI_IFR_REF4
*) IfrOpHdr
;
1196 if (IfrRef
->Question
.VarStoreId
!= VarStorageData
->VarStoreId
) {
1201 // Get Offset/Width by Question header.
1203 VarOffset
= IfrRef
->Question
.VarStoreInfo
.VarOffset
;
1204 VarWidth
= (UINT16
) (sizeof (EFI_HII_REF
));
1206 // Check whether this question is in requested block array.
1208 if (!BlockArrayCheck (RequestBlockArray
, VarOffset
, VarWidth
)) {
1210 // This question is not in the requested string. Skip it.
1216 // Check this var question is in the var storage
1218 if ((VarOffset
+ VarWidth
) > VarStorageData
->Size
) {
1219 Status
= EFI_INVALID_PARAMETER
;
1226 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
1227 if (BlockData
== NULL
) {
1228 Status
= EFI_OUT_OF_RESOURCES
;
1231 BlockData
->Offset
= VarOffset
;
1232 BlockData
->Width
= VarWidth
;
1233 BlockData
->QuestionId
= IfrRef
->Question
.QuestionId
;
1234 BlockData
->OpCode
= IfrOpHdr
->OpCode
;
1235 BlockData
->Scope
= IfrOpHdr
->Scope
;
1236 InitializeListHead (&BlockData
->DefaultValueEntry
);
1238 // Add Block Data into VarStorageData BlockEntry
1240 InsertBlockData (&VarStorageData
->BlockEntry
, &BlockData
);
1243 case EFI_IFR_ONE_OF_OP
:
1244 case EFI_IFR_NUMERIC_OP
:
1246 // Numeric and OneOf has the same opcode structure.
1250 // Numeric and OneOf question is not in IFR Form. This IFR form is not valid.
1252 if (VarStorageData
->Size
== 0) {
1253 Status
= EFI_INVALID_PARAMETER
;
1257 // Check whether this question is for the requested varstore.
1259 IfrOneOf
= (EFI_IFR_ONE_OF
*) IfrOpHdr
;
1260 if (IfrOneOf
->Question
.VarStoreId
!= VarStorageData
->VarStoreId
) {
1265 // Get Offset/Width by Question header and OneOf Flags
1267 VarOffset
= IfrOneOf
->Question
.VarStoreInfo
.VarOffset
;
1268 VarWidth
= (UINT16
) (1 << (IfrOneOf
->Flags
& EFI_IFR_NUMERIC_SIZE
));
1270 // Check whether this question is in requested block array.
1272 if (!BlockArrayCheck (RequestBlockArray
, VarOffset
, VarWidth
)) {
1274 // This question is not in the requested string. Skip it.
1280 // Check this var question is in the var storage
1282 if ((VarOffset
+ VarWidth
) > VarStorageData
->Size
) {
1283 Status
= EFI_INVALID_PARAMETER
;
1290 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
1291 if (BlockData
== NULL
) {
1292 Status
= EFI_OUT_OF_RESOURCES
;
1295 BlockData
->Offset
= VarOffset
;
1296 BlockData
->Width
= VarWidth
;
1297 BlockData
->QuestionId
= IfrOneOf
->Question
.QuestionId
;
1298 BlockData
->OpCode
= IfrOpHdr
->OpCode
;
1299 BlockData
->Scope
= IfrOpHdr
->Scope
;
1300 InitializeListHead (&BlockData
->DefaultValueEntry
);
1302 // Add Block Data into VarStorageData BlockEntry
1304 InsertBlockData (&VarStorageData
->BlockEntry
, &BlockData
);
1306 if (IfrOpHdr
->OpCode
== EFI_IFR_ONE_OF_OP
) {
1308 // Set this flag to TRUE for the first oneof option.
1310 FirstOneOfOption
= TRUE
;
1311 } else if (IfrOpHdr
->OpCode
== EFI_IFR_NUMERIC_OP
) {
1313 // Numeric minimum value will be used as default value when no default is specified.
1315 DefaultData
.Type
= DefaultValueFromDefault
;
1316 switch (IfrOneOf
->Flags
& EFI_IFR_NUMERIC_SIZE
) {
1317 case EFI_IFR_NUMERIC_SIZE_1
:
1318 DefaultData
.Value
.u8
= IfrOneOf
->data
.u8
.MinValue
;
1321 case EFI_IFR_NUMERIC_SIZE_2
:
1322 CopyMem (&DefaultData
.Value
.u16
, &IfrOneOf
->data
.u16
.MinValue
, sizeof (UINT16
));
1325 case EFI_IFR_NUMERIC_SIZE_4
:
1326 CopyMem (&DefaultData
.Value
.u32
, &IfrOneOf
->data
.u32
.MinValue
, sizeof (UINT32
));
1329 case EFI_IFR_NUMERIC_SIZE_8
:
1330 CopyMem (&DefaultData
.Value
.u64
, &IfrOneOf
->data
.u64
.MinValue
, sizeof (UINT64
));
1334 // Set default value base on the DefaultId list get from IFR data.
1336 for (LinkData
= DefaultIdArray
->Entry
.ForwardLink
; LinkData
!= &DefaultIdArray
->Entry
; LinkData
= LinkData
->ForwardLink
) {
1337 DefaultDataPtr
= BASE_CR (LinkData
, IFR_DEFAULT_DATA
, Entry
);
1338 DefaultData
.DefaultId
= DefaultDataPtr
->DefaultId
;
1339 InsertDefaultValue (BlockData
, &DefaultData
);
1344 case EFI_IFR_ORDERED_LIST_OP
:
1346 // offset by question header
1347 // width by EFI_IFR_ORDERED_LIST MaxContainers * OneofOption Type
1348 // no default value and default id, how to define its default value?
1352 // OrderedList question is not in IFR Form. This IFR form is not valid.
1354 if (VarStorageData
->Size
== 0) {
1355 Status
= EFI_INVALID_PARAMETER
;
1359 // Check whether this question is for the requested varstore.
1361 IfrOrderedList
= (EFI_IFR_ORDERED_LIST
*) IfrOpHdr
;
1362 if (IfrOrderedList
->Question
.VarStoreId
!= VarStorageData
->VarStoreId
) {
1368 // Get Offset/Width by Question header and OneOf Flags
1370 VarOffset
= IfrOrderedList
->Question
.VarStoreInfo
.VarOffset
;
1371 VarWidth
= IfrOrderedList
->MaxContainers
;
1376 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
1377 if (BlockData
== NULL
) {
1378 Status
= EFI_OUT_OF_RESOURCES
;
1381 BlockData
->Offset
= VarOffset
;
1382 BlockData
->Width
= VarWidth
;
1383 BlockData
->QuestionId
= IfrOrderedList
->Question
.QuestionId
;
1384 BlockData
->OpCode
= IfrOpHdr
->OpCode
;
1385 BlockData
->Scope
= IfrOpHdr
->Scope
;
1386 InitializeListHead (&BlockData
->DefaultValueEntry
);
1389 case EFI_IFR_CHECKBOX_OP
:
1391 // EFI_IFR_DEFAULT_OP
1392 // offset by question header
1393 // width is 1 sizeof (BOOLEAN)
1394 // default id by CheckBox Flags if CheckBox flags (Default or Mau) is set, the default value is 1 to be set.
1395 // value by DefaultOption
1396 // default id by DeaultOption DefaultId can override CheckBox Flags and Default value.
1400 // CheckBox question is not in IFR Form. This IFR form is not valid.
1402 if (VarStorageData
->Size
== 0) {
1403 Status
= EFI_INVALID_PARAMETER
;
1407 // Check whether this question is for the requested varstore.
1409 IfrCheckBox
= (EFI_IFR_CHECKBOX
*) IfrOpHdr
;
1410 if (IfrCheckBox
->Question
.VarStoreId
!= VarStorageData
->VarStoreId
) {
1415 // Get Offset/Width by Question header and OneOf Flags
1417 VarOffset
= IfrCheckBox
->Question
.VarStoreInfo
.VarOffset
;
1418 VarWidth
= (UINT16
) sizeof (BOOLEAN
);
1421 // Check whether this question is in requested block array.
1423 if (!BlockArrayCheck (RequestBlockArray
, VarOffset
, VarWidth
)) {
1425 // This question is not in the requested string. Skip it.
1431 // Check this var question is in the var storage
1433 if ((VarOffset
+ VarWidth
) > VarStorageData
->Size
) {
1434 Status
= EFI_INVALID_PARAMETER
;
1441 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
1442 if (BlockData
== NULL
) {
1443 Status
= EFI_OUT_OF_RESOURCES
;
1446 BlockData
->Offset
= VarOffset
;
1447 BlockData
->Width
= VarWidth
;
1448 BlockData
->QuestionId
= IfrCheckBox
->Question
.QuestionId
;
1449 BlockData
->OpCode
= IfrOpHdr
->OpCode
;
1450 BlockData
->Scope
= IfrOpHdr
->Scope
;
1451 InitializeListHead (&BlockData
->DefaultValueEntry
);
1453 // Add Block Data into VarStorageData BlockEntry
1455 InsertBlockData (&VarStorageData
->BlockEntry
, &BlockData
);
1458 // Add default value for standard ID by CheckBox Flag
1460 VarDefaultId
= EFI_HII_DEFAULT_CLASS_STANDARD
;
1462 // Prepare new DefaultValue
1464 DefaultData
.DefaultId
= VarDefaultId
;
1465 if ((IfrCheckBox
->Flags
& EFI_IFR_CHECKBOX_DEFAULT
) == EFI_IFR_CHECKBOX_DEFAULT
) {
1467 // When flag is set, defautl value is TRUE.
1469 DefaultData
.Type
= DefaultValueFromFlag
;
1470 DefaultData
.Value
.b
= TRUE
;
1473 // When flag is not set, defautl value is FASLE.
1475 DefaultData
.Type
= DefaultValueFromDefault
;
1476 DefaultData
.Value
.b
= FALSE
;
1479 // Add DefaultValue into current BlockData
1481 InsertDefaultValue (BlockData
, &DefaultData
);
1484 // Add default value for Manufacture ID by CheckBox Flag
1486 VarDefaultId
= EFI_HII_DEFAULT_CLASS_MANUFACTURING
;
1488 // Prepare new DefaultValue
1490 DefaultData
.DefaultId
= VarDefaultId
;
1491 if ((IfrCheckBox
->Flags
& EFI_IFR_CHECKBOX_DEFAULT_MFG
) == EFI_IFR_CHECKBOX_DEFAULT_MFG
) {
1493 // When flag is set, defautl value is TRUE.
1495 DefaultData
.Type
= DefaultValueFromFlag
;
1496 DefaultData
.Value
.b
= TRUE
;
1499 // When flag is not set, defautl value is FASLE.
1501 DefaultData
.Type
= DefaultValueFromDefault
;
1502 DefaultData
.Value
.b
= FALSE
;
1505 // Add DefaultValue into current BlockData
1507 InsertDefaultValue (BlockData
, &DefaultData
);
1510 case EFI_IFR_DATE_OP
:
1512 // offset by question header
1513 // width MaxSize * sizeof (CHAR16)
1514 // no default value, only block array
1518 // Date question is not in IFR Form. This IFR form is not valid.
1520 if (VarStorageData
->Size
== 0) {
1521 Status
= EFI_INVALID_PARAMETER
;
1525 // Check whether this question is for the requested varstore.
1527 IfrDate
= (EFI_IFR_DATE
*) IfrOpHdr
;
1528 if (IfrDate
->Question
.VarStoreId
!= VarStorageData
->VarStoreId
) {
1533 // Get Offset/Width by Question header and OneOf Flags
1535 VarOffset
= IfrDate
->Question
.VarStoreInfo
.VarOffset
;
1536 VarWidth
= (UINT16
) sizeof (EFI_HII_DATE
);
1539 // Check whether this question is in requested block array.
1541 if (!BlockArrayCheck (RequestBlockArray
, VarOffset
, VarWidth
)) {
1543 // This question is not in the requested array. Skip it.
1549 // Check this var question is in the var storage
1551 if ((VarOffset
+ VarWidth
) > VarStorageData
->Size
) {
1552 Status
= EFI_INVALID_PARAMETER
;
1559 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
1560 if (BlockData
== NULL
) {
1561 Status
= EFI_OUT_OF_RESOURCES
;
1564 BlockData
->Offset
= VarOffset
;
1565 BlockData
->Width
= VarWidth
;
1566 BlockData
->QuestionId
= IfrDate
->Question
.QuestionId
;
1567 BlockData
->OpCode
= IfrOpHdr
->OpCode
;
1568 BlockData
->Scope
= IfrOpHdr
->Scope
;
1569 InitializeListHead (&BlockData
->DefaultValueEntry
);
1572 // Add Block Data into VarStorageData BlockEntry
1574 InsertBlockData (&VarStorageData
->BlockEntry
, &BlockData
);
1577 case EFI_IFR_TIME_OP
:
1579 // offset by question header
1580 // width MaxSize * sizeof (CHAR16)
1581 // no default value, only block array
1585 // Time question is not in IFR Form. This IFR form is not valid.
1587 if (VarStorageData
->Size
== 0) {
1588 Status
= EFI_INVALID_PARAMETER
;
1592 // Check whether this question is for the requested varstore.
1594 IfrTime
= (EFI_IFR_TIME
*) IfrOpHdr
;
1595 if (IfrTime
->Question
.VarStoreId
!= VarStorageData
->VarStoreId
) {
1600 // Get Offset/Width by Question header and OneOf Flags
1602 VarOffset
= IfrTime
->Question
.VarStoreInfo
.VarOffset
;
1603 VarWidth
= (UINT16
) sizeof (EFI_HII_TIME
);
1606 // Check whether this question is in requested block array.
1608 if (!BlockArrayCheck (RequestBlockArray
, VarOffset
, VarWidth
)) {
1610 // This question is not in the requested array. Skip it.
1616 // Check this var question is in the var storage
1618 if ((VarOffset
+ VarWidth
) > VarStorageData
->Size
) {
1619 Status
= EFI_INVALID_PARAMETER
;
1626 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
1627 if (BlockData
== NULL
) {
1628 Status
= EFI_OUT_OF_RESOURCES
;
1631 BlockData
->Offset
= VarOffset
;
1632 BlockData
->Width
= VarWidth
;
1633 BlockData
->QuestionId
= IfrTime
->Question
.QuestionId
;
1634 BlockData
->OpCode
= IfrOpHdr
->OpCode
;
1635 BlockData
->Scope
= IfrOpHdr
->Scope
;
1636 InitializeListHead (&BlockData
->DefaultValueEntry
);
1639 // Add Block Data into VarStorageData BlockEntry
1641 InsertBlockData (&VarStorageData
->BlockEntry
, &BlockData
);
1644 case EFI_IFR_STRING_OP
:
1646 // offset by question header
1647 // width MaxSize * sizeof (CHAR16)
1648 // no default value, only block array
1652 // String question is not in IFR Form. This IFR form is not valid.
1654 if (VarStorageData
->Size
== 0) {
1655 Status
= EFI_INVALID_PARAMETER
;
1659 // Check whether this question is for the requested varstore.
1661 IfrString
= (EFI_IFR_STRING
*) IfrOpHdr
;
1662 if (IfrString
->Question
.VarStoreId
!= VarStorageData
->VarStoreId
) {
1667 // Get Offset/Width by Question header and OneOf Flags
1669 VarOffset
= IfrString
->Question
.VarStoreInfo
.VarOffset
;
1670 VarWidth
= (UINT16
) (IfrString
->MaxSize
* sizeof (UINT16
));
1673 // Check whether this question is in requested block array.
1675 if (!BlockArrayCheck (RequestBlockArray
, VarOffset
, VarWidth
)) {
1677 // This question is not in the requested string. Skip it.
1683 // Check this var question is in the var storage
1685 if ((VarOffset
+ VarWidth
) > VarStorageData
->Size
) {
1686 Status
= EFI_INVALID_PARAMETER
;
1693 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
1694 if (BlockData
== NULL
) {
1695 Status
= EFI_OUT_OF_RESOURCES
;
1698 BlockData
->Offset
= VarOffset
;
1699 BlockData
->Width
= VarWidth
;
1700 BlockData
->QuestionId
= IfrString
->Question
.QuestionId
;
1701 BlockData
->OpCode
= IfrOpHdr
->OpCode
;
1702 InitializeListHead (&BlockData
->DefaultValueEntry
);
1705 // Add Block Data into VarStorageData BlockEntry
1707 InsertBlockData (&VarStorageData
->BlockEntry
, &BlockData
);
1710 // No default value for string.
1715 case EFI_IFR_PASSWORD_OP
:
1717 // offset by question header
1718 // width MaxSize * sizeof (CHAR16)
1719 // no default value, only block array
1723 // Password question is not in IFR Form. This IFR form is not valid.
1725 if (VarStorageData
->Size
== 0) {
1726 Status
= EFI_INVALID_PARAMETER
;
1730 // Check whether this question is for the requested varstore.
1732 IfrPassword
= (EFI_IFR_PASSWORD
*) IfrOpHdr
;
1733 if (IfrPassword
->Question
.VarStoreId
!= VarStorageData
->VarStoreId
) {
1738 // Get Offset/Width by Question header and OneOf Flags
1740 VarOffset
= IfrPassword
->Question
.VarStoreInfo
.VarOffset
;
1741 VarWidth
= (UINT16
) (IfrPassword
->MaxSize
* sizeof (UINT16
));
1744 // Check whether this question is in requested block array.
1746 if (!BlockArrayCheck (RequestBlockArray
, VarOffset
, VarWidth
)) {
1748 // This question is not in the requested string. Skip it.
1754 // Check this var question is in the var storage
1756 if ((VarOffset
+ VarWidth
) > VarStorageData
->Size
) {
1757 Status
= EFI_INVALID_PARAMETER
;
1764 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
1765 if (BlockData
== NULL
) {
1766 Status
= EFI_OUT_OF_RESOURCES
;
1769 BlockData
->Offset
= VarOffset
;
1770 BlockData
->Width
= VarWidth
;
1771 BlockData
->QuestionId
= IfrPassword
->Question
.QuestionId
;
1772 BlockData
->OpCode
= IfrOpHdr
->OpCode
;
1773 InitializeListHead (&BlockData
->DefaultValueEntry
);
1776 // Add Block Data into VarStorageData BlockEntry
1778 InsertBlockData (&VarStorageData
->BlockEntry
, &BlockData
);
1781 // No default value for string.
1786 case EFI_IFR_ONE_OF_OPTION_OP
:
1788 // No matched block data is ignored.
1790 if (BlockData
== NULL
|| BlockData
->Scope
== 0) {
1794 IfrOneOfOption
= (EFI_IFR_ONE_OF_OPTION
*) IfrOpHdr
;
1795 if (BlockData
->OpCode
== EFI_IFR_ORDERED_LIST_OP
) {
1797 // Get ordered list option data type.
1799 if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_8
|| IfrOneOfOption
->Type
== EFI_IFR_TYPE_BOOLEAN
) {
1801 } else if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_16
) {
1803 } else if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_32
) {
1805 } else if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_64
) {
1809 // Invalid ordered list option data type.
1811 Status
= EFI_INVALID_PARAMETER
;
1812 FreePool (BlockData
);
1817 // Calculate Ordered list QuestionId width.
1819 BlockData
->Width
= (UINT16
) (BlockData
->Width
* VarWidth
);
1821 // Check whether this question is in requested block array.
1823 if (!BlockArrayCheck (RequestBlockArray
, BlockData
->Offset
, BlockData
->Width
)) {
1825 // This question is not in the requested string. Skip it.
1827 FreePool (BlockData
);
1832 // Check this var question is in the var storage
1834 if ((BlockData
->Offset
+ BlockData
->Width
) > VarStorageData
->Size
) {
1835 Status
= EFI_INVALID_PARAMETER
;
1836 FreePool (BlockData
);
1840 // Add Block Data into VarStorageData BlockEntry
1842 InsertBlockData (&VarStorageData
->BlockEntry
, &BlockData
);
1844 // No default data for OrderedList.
1851 // 1. Set default value for OneOf option when flag field has default attribute.
1853 if (((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT
) == EFI_IFR_OPTION_DEFAULT
) ||
1854 ((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT_MFG
) == EFI_IFR_OPTION_DEFAULT_MFG
)) {
1856 // This flag is used to specify whether this option is the first. Set it to FALSE for the following options.
1857 // The first oneof option value will be used as default value when no default value is specified.
1859 FirstOneOfOption
= FALSE
;
1861 // Prepare new DefaultValue
1863 DefaultData
.Type
= DefaultValueFromFlag
;
1864 CopyMem (&DefaultData
.Value
.u64
, &IfrOneOfOption
->Value
.u64
, sizeof (UINT64
));
1865 if ((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT
) == EFI_IFR_OPTION_DEFAULT
) {
1866 DefaultData
.DefaultId
= EFI_HII_DEFAULT_CLASS_STANDARD
;
1867 InsertDefaultValue (BlockData
, &DefaultData
);
1869 if ((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT_MFG
) == EFI_IFR_OPTION_DEFAULT_MFG
) {
1870 DefaultData
.DefaultId
= EFI_HII_DEFAULT_CLASS_MANUFACTURING
;
1871 InsertDefaultValue (BlockData
, &DefaultData
);
1878 // 2. Set as the default value when this is the first option.
1879 // The first oneof option value will be used as default value when no default value is specified.
1881 if (FirstOneOfOption
) {
1882 // This flag is used to specify whether this option is the first. Set it to FALSE for the following options.
1883 FirstOneOfOption
= FALSE
;
1886 // Prepare new DefaultValue
1888 DefaultData
.Type
= DefaultValueFromDefault
;
1889 CopyMem (&DefaultData
.Value
.u64
, &IfrOneOfOption
->Value
.u64
, sizeof (UINT64
));
1890 for (LinkData
= DefaultIdArray
->Entry
.ForwardLink
; LinkData
!= &DefaultIdArray
->Entry
; LinkData
= LinkData
->ForwardLink
) {
1891 DefaultDataPtr
= BASE_CR (LinkData
, IFR_DEFAULT_DATA
, Entry
);
1892 DefaultData
.DefaultId
= DefaultDataPtr
->DefaultId
;
1893 InsertDefaultValue (BlockData
, &DefaultData
);
1898 case EFI_IFR_DEFAULT_OP
:
1900 // Update Current BlockData to the default value.
1902 if (BlockData
== NULL
|| BlockData
->Scope
== 0) {
1904 // No matched block data is ignored.
1909 if (BlockData
->OpCode
== EFI_IFR_ORDERED_LIST_OP
) {
1911 // OrderedList Opcode is no default value.
1916 // Get the DefaultId
1918 IfrDefault
= (EFI_IFR_DEFAULT
*) IfrOpHdr
;
1919 VarDefaultId
= IfrDefault
->DefaultId
;
1921 // Prepare new DefaultValue
1923 DefaultData
.Type
= DefaultValueFromOpcode
;
1924 DefaultData
.DefaultId
= VarDefaultId
;
1925 CopyMem (&DefaultData
.Value
, &IfrDefault
->Value
, IfrDefault
->Header
.Length
- OFFSET_OF (EFI_IFR_DEFAULT
, Value
));
1927 // If the value field is expression, set the cleaned flag.
1928 if (IfrDefault
->Type
== EFI_IFR_TYPE_OTHER
) {
1929 DefaultData
.Cleaned
= TRUE
;
1932 // Add DefaultValue into current BlockData
1934 InsertDefaultValue (BlockData
, &DefaultData
);
1937 // After insert the default value, reset the cleaned value for next
1938 // time used. If not set here, need to set the value before everytime
1941 DefaultData
.Cleaned
= FALSE
;
1943 case EFI_IFR_END_OP
:
1945 // End Opcode is for Var question.
1947 if (BlockData
!= NULL
&& BlockData
->Scope
> 0) {
1952 if (BlockData
!= NULL
&& BlockData
->Scope
> 0) {
1953 BlockData
->Scope
= (UINT8
) (BlockData
->Scope
+ IfrOpHdr
->Scope
);
1958 IfrOffset
+= IfrOpHdr
->Length
;
1962 for (LinkData
= VarStorageData
->BlockEntry
.ForwardLink
; LinkData
!= &VarStorageData
->BlockEntry
; LinkData
= LinkData
->ForwardLink
) {
1963 BlockData
= BASE_CR (LinkData
, IFR_BLOCK_DATA
, Entry
);
1964 for (LinkDefault
= BlockData
->DefaultValueEntry
.ForwardLink
; LinkDefault
!= &BlockData
->DefaultValueEntry
; ) {
1965 DefaultDataPtr
= BASE_CR (LinkDefault
, IFR_DEFAULT_DATA
, Entry
);
1966 LinkDefault
= LinkDefault
->ForwardLink
;
1967 if (DefaultDataPtr
->Cleaned
== TRUE
) {
1968 RemoveEntryList (&DefaultDataPtr
->Entry
);
1969 FreePool (DefaultDataPtr
);
1978 This function gets the full request string and full default value string by
1979 parsing IFR data in HII form packages.
1981 When Request points to NULL string, the request string and default value string
1982 for each varstore in form package will return.
1984 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
1985 @param DevicePath Device Path which Hii Config Access Protocol is registered.
1986 @param Request Pointer to a null-terminated Unicode string in
1987 <ConfigRequest> format. When it doesn't contain
1988 any RequestElement, it will be updated to return
1989 the full RequestElement retrieved from IFR data.
1990 If it points to NULL, the request string for the first
1991 varstore in form package will be merged into a
1992 <MultiConfigRequest> format string and return.
1993 @param AltCfgResp Pointer to a null-terminated Unicode string in
1994 <ConfigAltResp> format. When the pointer is to NULL,
1995 the full default value string retrieved from IFR data
1996 will return. When the pinter is to a string, the
1997 full default value string retrieved from IFR data
1998 will be merged into the input string and return.
1999 When Request points to NULL, the default value string
2000 for each varstore in form package will be merged into
2001 a <MultiConfigAltResp> format string and return.
2002 @param PointerProgress Optional parameter, it can be be NULL.
2003 When it is not NULL, if Request is NULL, it returns NULL.
2004 On return, points to a character in the Request
2005 string. Points to the string's null terminator if
2006 request was successful. Points to the most recent
2007 & before the first failing name / value pair (or
2008 the beginning of the string if the failure is in
2009 the first name / value pair) if the request was
2011 @retval EFI_SUCCESS The Results string is set to the full request string.
2012 And AltCfgResp contains all default value string.
2013 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
2014 @retval EFI_NOT_FOUND The varstore (Guid and Name) in Request string
2015 can't be found in Form package.
2016 @retval EFI_NOT_FOUND HiiPackage can't be got on the input HiiHandle.
2017 @retval EFI_INVALID_PARAMETER Request points to NULL.
2022 GetFullStringFromHiiFormPackages (
2023 IN HII_DATABASE_RECORD
*DataBaseRecord
,
2024 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
2025 IN OUT EFI_STRING
*Request
,
2026 IN OUT EFI_STRING
*AltCfgResp
,
2027 OUT EFI_STRING
*PointerProgress OPTIONAL
2031 UINT8
*HiiFormPackage
;
2033 IFR_BLOCK_DATA
*RequestBlockArray
;
2034 IFR_BLOCK_DATA
*BlockData
;
2035 IFR_BLOCK_DATA
*NextBlockData
;
2036 IFR_DEFAULT_DATA
*DefaultValueData
;
2037 IFR_DEFAULT_DATA
*DefaultId
;
2038 IFR_DEFAULT_DATA
*DefaultIdArray
;
2039 IFR_VARSTORAGE_DATA
*VarStorageData
;
2040 EFI_STRING DefaultAltCfgResp
;
2041 EFI_STRING FullConfigRequest
;
2042 EFI_STRING ConfigHdr
;
2046 EFI_STRING StringPtr
;
2047 EFI_STRING Progress
;
2053 LIST_ENTRY
*LinkData
;
2054 LIST_ENTRY
*LinkDefault
;
2057 if (DataBaseRecord
== NULL
|| DevicePath
== NULL
|| Request
== NULL
|| AltCfgResp
== NULL
) {
2058 return EFI_INVALID_PARAMETER
;
2062 // Initialize the local variables.
2064 RequestBlockArray
= NULL
;
2065 DefaultIdArray
= NULL
;
2066 VarStorageData
= NULL
;
2067 DefaultAltCfgResp
= NULL
;
2068 FullConfigRequest
= NULL
;
2073 HiiFormPackage
= NULL
;
2076 Progress
= *Request
;
2078 Status
= GetFormPackageData (DataBaseRecord
, &HiiFormPackage
, &PackageSize
);
2079 if (EFI_ERROR (Status
)) {
2084 // 1. Get the request block array by Request String when Request string containts the block array.
2087 if (*Request
!= NULL
) {
2088 StringPtr
= *Request
;
2092 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
2093 Status
= EFI_INVALID_PARAMETER
;
2096 StringPtr
+= StrLen (L
"GUID=");
2097 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&NAME=", StrLen (L
"&NAME=")) != 0) {
2100 if (*StringPtr
== L
'\0') {
2101 Status
= EFI_INVALID_PARAMETER
;
2104 StringPtr
+= StrLen (L
"&NAME=");
2105 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&PATH=", StrLen (L
"&PATH=")) != 0) {
2108 if (*StringPtr
== L
'\0') {
2109 Status
= EFI_INVALID_PARAMETER
;
2112 StringPtr
+= StrLen (L
"&PATH=");
2113 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
2117 // Check the following string &OFFSET=
2119 if (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) != 0) {
2120 Progress
= StringPtr
;
2121 Status
= EFI_INVALID_PARAMETER
;
2123 } else if (*StringPtr
== L
'\0') {
2125 // No request block is found.
2130 if (StringPtr
!= NULL
) {
2132 // Init RequestBlockArray
2134 RequestBlockArray
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
2135 if (RequestBlockArray
== NULL
) {
2136 Status
= EFI_OUT_OF_RESOURCES
;
2139 InitializeListHead (&RequestBlockArray
->Entry
);
2142 // Get the request Block array from the request string
2147 // Parse each <RequestElement> if exists
2148 // Only <BlockName> format is supported by this help function.
2149 // <BlockName> ::= &'OFFSET='<Number>&'WIDTH='<Number>
2151 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) == 0) {
2153 // Skip the OFFSET string
2155 Progress
= StringPtr
;
2156 StringPtr
+= StrLen (L
"&OFFSET=");
2160 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
2161 if (EFI_ERROR (Status
)) {
2168 (((Length
+ 1) / 2) < sizeof (UINT16
)) ? ((Length
+ 1) / 2) : sizeof (UINT16
)
2170 FreePool (TmpBuffer
);
2172 StringPtr
+= Length
;
2173 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
2174 Status
= EFI_INVALID_PARAMETER
;
2177 StringPtr
+= StrLen (L
"&WIDTH=");
2182 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
2183 if (EFI_ERROR (Status
)) {
2190 (((Length
+ 1) / 2) < sizeof (UINT16
)) ? ((Length
+ 1) / 2) : sizeof (UINT16
)
2192 FreePool (TmpBuffer
);
2194 StringPtr
+= Length
;
2195 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
2196 Status
= EFI_INVALID_PARAMETER
;
2203 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
2204 if (BlockData
== NULL
) {
2205 Status
= EFI_OUT_OF_RESOURCES
;
2208 BlockData
->Offset
= Offset
;
2209 BlockData
->Width
= Width
;
2210 InsertBlockData (&RequestBlockArray
->Entry
, &BlockData
);
2213 // Skip &VALUE string if &VALUE does exists.
2215 if (StrnCmp (StringPtr
, L
"&VALUE=", StrLen (L
"&VALUE=")) == 0) {
2216 StringPtr
+= StrLen (L
"&VALUE=");
2221 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
2222 if (EFI_ERROR (Status
)) {
2223 Status
= EFI_INVALID_PARAMETER
;
2227 StringPtr
+= Length
;
2228 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
2229 Status
= EFI_INVALID_PARAMETER
;
2234 // If '\0', parsing is finished.
2236 if (*StringPtr
== 0) {
2242 // Merge the requested block data.
2244 Link
= RequestBlockArray
->Entry
.ForwardLink
;
2245 while ((Link
!= &RequestBlockArray
->Entry
) && (Link
->ForwardLink
!= &RequestBlockArray
->Entry
)) {
2246 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
2247 NextBlockData
= BASE_CR (Link
->ForwardLink
, IFR_BLOCK_DATA
, Entry
);
2248 if ((NextBlockData
->Offset
>= BlockData
->Offset
) && (NextBlockData
->Offset
<= (BlockData
->Offset
+ BlockData
->Width
))) {
2249 if ((NextBlockData
->Offset
+ NextBlockData
->Width
) > (BlockData
->Offset
+ BlockData
->Width
)) {
2250 BlockData
->Width
= (UINT16
) (NextBlockData
->Offset
+ NextBlockData
->Width
- BlockData
->Offset
);
2252 RemoveEntryList (Link
->ForwardLink
);
2253 FreePool (NextBlockData
);
2256 Link
= Link
->ForwardLink
;
2261 // 2. Parse FormPackage to get BlockArray and DefaultId Array for the request BlockArray.
2265 // Initialize DefaultIdArray to store the map between DeaultId and DefaultName
2267 DefaultIdArray
= (IFR_DEFAULT_DATA
*) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
2268 if (DefaultIdArray
== NULL
) {
2269 Status
= EFI_OUT_OF_RESOURCES
;
2272 InitializeListHead (&DefaultIdArray
->Entry
);
2275 // Initialize VarStorageData to store the var store Block and Default value information.
2277 VarStorageData
= (IFR_VARSTORAGE_DATA
*) AllocateZeroPool (sizeof (IFR_VARSTORAGE_DATA
));
2278 if (VarStorageData
== NULL
) {
2279 Status
= EFI_OUT_OF_RESOURCES
;
2282 InitializeListHead (&VarStorageData
->Entry
);
2283 InitializeListHead (&VarStorageData
->BlockEntry
);
2286 // Parse the opcode in form pacakge to get the default setting.
2288 Status
= ParseIfrData (HiiFormPackage
, (UINT32
) PackageSize
, *Request
, RequestBlockArray
, VarStorageData
, DefaultIdArray
);
2289 if (EFI_ERROR (Status
)) {
2294 // No requested varstore in IFR data and directly return
2296 if (VarStorageData
->Size
== 0) {
2297 Status
= EFI_SUCCESS
;
2302 // 3. Construct Request Element (Block Name) for 2.1 and 2.2 case.
2306 // Construct <ConfigHdr> : "GUID=...&NAME=...&PATH=..." by VarStorageData Guid, Name and DriverHandle
2308 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*) &VarStorageData
->Guid
, 1, &GuidStr
);
2309 GenerateSubStr (L
"NAME=", StrLen (VarStorageData
->Name
) * sizeof (CHAR16
), (VOID
*) VarStorageData
->Name
, 2, &NameStr
);
2312 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) DevicePath
),
2313 (VOID
*) DevicePath
,
2317 Length
= StrLen (GuidStr
);
2318 Length
= Length
+ StrLen (NameStr
);
2319 Length
= Length
+ StrLen (PathStr
) + 1;
2320 ConfigHdr
= AllocateZeroPool (Length
* sizeof (CHAR16
));
2321 if (ConfigHdr
== NULL
) {
2322 Status
= EFI_OUT_OF_RESOURCES
;
2325 StrCpy (ConfigHdr
, GuidStr
);
2326 StrCat (ConfigHdr
, NameStr
);
2327 StrCat (ConfigHdr
, PathStr
);
2330 // Remove the last character L'&'
2332 *(ConfigHdr
+ StrLen (ConfigHdr
) - 1) = L
'\0';
2334 if (RequestBlockArray
== NULL
) {
2336 // Append VarStorageData BlockEntry into *Request string
2337 // Now support only one varstore in a form package.
2341 // Go through all VarStorageData Entry and get BlockEntry for each one for the multiple varstore in a single form package
2342 // Then construct them all to return MultiRequest string : ConfigHdr BlockConfig
2346 // Compute the length of the entire request starting with <ConfigHdr> and a
2350 Length
= StrLen (ConfigHdr
) + 1;
2352 for (Link
= VarStorageData
->BlockEntry
.ForwardLink
; Link
!= &VarStorageData
->BlockEntry
; Link
= Link
->ForwardLink
) {
2354 // Add <BlockName> length for each Offset/Width pair
2356 // <BlockName> ::= &OFFSET=1234&WIDTH=1234
2357 // | 8 | 4 | 7 | 4 |
2360 Length
= Length
+ (8 + 4 + 7 + 4);
2364 // No any request block data is found. The request string can't be constructed.
2367 Status
= EFI_SUCCESS
;
2372 // Allocate buffer for the entire <ConfigRequest>
2374 FullConfigRequest
= AllocateZeroPool (Length
* sizeof (CHAR16
));
2375 if (FullConfigRequest
== NULL
) {
2376 Status
= EFI_OUT_OF_RESOURCES
;
2379 StringPtr
= FullConfigRequest
;
2382 // Start with <ConfigHdr>
2384 StrCpy (StringPtr
, ConfigHdr
);
2385 StringPtr
+= StrLen (StringPtr
);
2388 // Loop through all the Offset/Width pairs and append them to ConfigRequest
2390 for (Link
= VarStorageData
->BlockEntry
.ForwardLink
; Link
!= &VarStorageData
->BlockEntry
; Link
= Link
->ForwardLink
) {
2391 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
2393 // Append &OFFSET=XXXX&WIDTH=YYYY\0
2397 (8 + 4 + 7 + 4 + 1) * sizeof (CHAR16
),
2398 L
"&OFFSET=%04X&WIDTH=%04X",
2402 StringPtr
+= StrLen (StringPtr
);
2405 // Set to the got full request string.
2407 HiiToLower (FullConfigRequest
);
2408 if (*Request
!= NULL
) {
2409 FreePool (*Request
);
2411 *Request
= FullConfigRequest
;
2415 // 4. Construct Default Value string in AltResp according to request element.
2416 // Go through all VarStorageData Entry and get the DefaultId array for each one
2417 // Then construct them all to : ConfigHdr AltConfigHdr ConfigBody AltConfigHdr ConfigBody
2421 // Add length for <ConfigHdr> + '\0'
2423 Length
= StrLen (ConfigHdr
) + 1;
2425 for (Link
= DefaultIdArray
->Entry
.ForwardLink
; Link
!= &DefaultIdArray
->Entry
; Link
= Link
->ForwardLink
) {
2426 DefaultId
= BASE_CR (Link
, IFR_DEFAULT_DATA
, Entry
);
2428 // Add length for "&<ConfigHdr>&ALTCFG=XXXX"
2429 // |1| StrLen (ConfigHdr) | 8 | 4 |
2431 Length
+= (1 + StrLen (ConfigHdr
) + 8 + 4);
2433 for (LinkData
= VarStorageData
->BlockEntry
.ForwardLink
; LinkData
!= &VarStorageData
->BlockEntry
; LinkData
= LinkData
->ForwardLink
) {
2434 BlockData
= BASE_CR (LinkData
, IFR_BLOCK_DATA
, Entry
);
2435 for (LinkDefault
= BlockData
->DefaultValueEntry
.ForwardLink
; LinkDefault
!= &BlockData
->DefaultValueEntry
; LinkDefault
= LinkDefault
->ForwardLink
) {
2436 DefaultValueData
= BASE_CR (LinkDefault
, IFR_DEFAULT_DATA
, Entry
);
2437 if (DefaultValueData
->DefaultId
== DefaultId
->DefaultId
) {
2439 // Add length for "&OFFSET=XXXX&WIDTH=YYYY&VALUE=zzzzzzzzzzzz"
2440 // | 8 | 4 | 7 | 4 | 7 | Width * 2 |
2442 Length
+= (8 + 4 + 7 + 4 + 7 + BlockData
->Width
* 2);
2450 // No default value is found. The default string doesn't exist.
2453 Status
= EFI_SUCCESS
;
2458 // Allocate buffer for the entire <DefaultAltCfgResp>
2460 DefaultAltCfgResp
= AllocateZeroPool (Length
* sizeof (CHAR16
));
2461 if (DefaultAltCfgResp
== NULL
) {
2462 Status
= EFI_OUT_OF_RESOURCES
;
2465 StringPtr
= DefaultAltCfgResp
;
2468 // Start with <ConfigHdr>
2470 StrCpy (StringPtr
, ConfigHdr
);
2471 StringPtr
+= StrLen (StringPtr
);
2473 for (Link
= DefaultIdArray
->Entry
.ForwardLink
; Link
!= &DefaultIdArray
->Entry
; Link
= Link
->ForwardLink
) {
2474 DefaultId
= BASE_CR (Link
, IFR_DEFAULT_DATA
, Entry
);
2476 // Add <AltConfigHdr> of the form "&<ConfigHdr>&ALTCFG=XXXX\0"
2477 // |1| StrLen (ConfigHdr) | 8 | 4 |
2481 (1 + StrLen (ConfigHdr
) + 8 + 4 + 1) * sizeof (CHAR16
),
2484 DefaultId
->DefaultId
2486 StringPtr
+= StrLen (StringPtr
);
2488 for (LinkData
= VarStorageData
->BlockEntry
.ForwardLink
; LinkData
!= &VarStorageData
->BlockEntry
; LinkData
= LinkData
->ForwardLink
) {
2489 BlockData
= BASE_CR (LinkData
, IFR_BLOCK_DATA
, Entry
);
2490 for (LinkDefault
= BlockData
->DefaultValueEntry
.ForwardLink
; LinkDefault
!= &BlockData
->DefaultValueEntry
; LinkDefault
= LinkDefault
->ForwardLink
) {
2491 DefaultValueData
= BASE_CR (LinkDefault
, IFR_DEFAULT_DATA
, Entry
);
2492 if (DefaultValueData
->DefaultId
== DefaultId
->DefaultId
) {
2494 // Add <BlockConfig>
2495 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>
2499 (8 + 4 + 7 + 4 + 7 + 1) * sizeof (CHAR16
),
2500 L
"&OFFSET=%04X&WIDTH=%04X&VALUE=",
2504 StringPtr
+= StrLen (StringPtr
);
2507 // Convert Value to a hex string in "%x" format
2508 // NOTE: This is in the opposite byte that GUID and PATH use
2510 Width
= BlockData
->Width
;
2511 TmpBuffer
= (UINT8
*) &(DefaultValueData
->Value
);
2512 for (; Width
> 0; Width
--) {
2513 StringPtr
+= UnicodeValueToString (StringPtr
, PREFIX_ZERO
| RADIX_HEX
, TmpBuffer
[Width
- 1], 2);
2519 HiiToLower (DefaultAltCfgResp
);
2522 // 5. Merge string into the input AltCfgResp if the iput *AltCfgResp is not NULL.
2524 if (*AltCfgResp
!= NULL
&& DefaultAltCfgResp
!= NULL
) {
2525 Status
= MergeDefaultString (AltCfgResp
, DefaultAltCfgResp
);
2526 FreePool (DefaultAltCfgResp
);
2527 } else if (*AltCfgResp
== NULL
) {
2528 *AltCfgResp
= DefaultAltCfgResp
;
2532 if (RequestBlockArray
!= NULL
) {
2534 // Free Link Array RequestBlockArray
2536 while (!IsListEmpty (&RequestBlockArray
->Entry
)) {
2537 BlockData
= BASE_CR (RequestBlockArray
->Entry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
2538 RemoveEntryList (&BlockData
->Entry
);
2539 FreePool (BlockData
);
2542 FreePool (RequestBlockArray
);
2545 if (VarStorageData
!= NULL
) {
2547 // Free link array VarStorageData
2549 while (!IsListEmpty (&VarStorageData
->BlockEntry
)) {
2550 BlockData
= BASE_CR (VarStorageData
->BlockEntry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
2551 RemoveEntryList (&BlockData
->Entry
);
2553 // Free default value link array
2555 while (!IsListEmpty (&BlockData
->DefaultValueEntry
)) {
2556 DefaultValueData
= BASE_CR (BlockData
->DefaultValueEntry
.ForwardLink
, IFR_DEFAULT_DATA
, Entry
);
2557 RemoveEntryList (&DefaultValueData
->Entry
);
2558 FreePool (DefaultValueData
);
2560 FreePool (BlockData
);
2562 FreePool (VarStorageData
);
2565 if (DefaultIdArray
!= NULL
) {
2567 // Free DefaultId Array
2569 while (!IsListEmpty (&DefaultIdArray
->Entry
)) {
2570 DefaultId
= BASE_CR (DefaultIdArray
->Entry
.ForwardLink
, IFR_DEFAULT_DATA
, Entry
);
2571 RemoveEntryList (&DefaultId
->Entry
);
2572 FreePool (DefaultId
);
2574 FreePool (DefaultIdArray
);
2578 // Free the allocated string
2580 if (GuidStr
!= NULL
) {
2583 if (NameStr
!= NULL
) {
2586 if (PathStr
!= NULL
) {
2589 if (ConfigHdr
!= NULL
) {
2590 FreePool (ConfigHdr
);
2594 // Free Pacakge data
2596 if (HiiFormPackage
!= NULL
) {
2597 FreePool (HiiFormPackage
);
2600 if (PointerProgress
!= NULL
) {
2601 if (*Request
== NULL
) {
2602 *PointerProgress
= NULL
;
2603 } else if (EFI_ERROR (Status
)) {
2604 *PointerProgress
= Progress
;
2606 *PointerProgress
= *Request
+ StrLen (*Request
);
2614 This function gets the full request resp string by
2615 parsing IFR data in HII form packages.
2617 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
2619 @param EfiVarStoreInfo The efi varstore info which is save in the EFI
2620 varstore data structure.
2621 @param Request Pointer to a null-terminated Unicode string in
2622 <ConfigRequest> format.
2623 @param RequestResp Pointer to a null-terminated Unicode string in
2624 <ConfigResp> format.
2625 @param AccessProgress On return, points to a character in the Request
2626 string. Points to the string's null terminator if
2627 request was successful. Points to the most recent
2628 & before the first failing name / value pair (or
2629 the beginning of the string if the failure is in
2630 the first name / value pair) if the request was
2633 @retval EFI_SUCCESS The Results string is set to the full request string.
2634 And AltCfgResp contains all default value string.
2635 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
2636 @retval EFI_INVALID_PARAMETER Request points to NULL.
2640 GetConfigRespFromEfiVarStore (
2641 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
2642 IN EFI_IFR_VARSTORE_EFI
*EfiVarStoreInfo
,
2643 IN EFI_STRING Request
,
2644 OUT EFI_STRING
*RequestResp
,
2645 OUT EFI_STRING
*AccessProgress
2649 EFI_STRING VarStoreName
;
2653 Status
= EFI_SUCCESS
;
2656 VarStoreName
= NULL
;
2658 VarStoreName
= AllocateZeroPool (AsciiStrSize ((CHAR8
*)EfiVarStoreInfo
->Name
) * sizeof (CHAR16
));
2659 if (VarStoreName
== NULL
) {
2660 Status
= EFI_OUT_OF_RESOURCES
;
2663 AsciiStrToUnicodeStr ((CHAR8
*) EfiVarStoreInfo
->Name
, VarStoreName
);
2666 Status
= gRT
->GetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, NULL
, &BufferSize
, NULL
);
2667 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
2671 VarStore
= AllocateZeroPool (BufferSize
);
2672 ASSERT (VarStore
!= NULL
);
2673 Status
= gRT
->GetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, NULL
, &BufferSize
, VarStore
);
2674 if (EFI_ERROR (Status
)) {
2678 Status
= HiiBlockToConfig(This
, Request
, VarStore
, BufferSize
, RequestResp
, AccessProgress
);
2679 if (EFI_ERROR (Status
)) {
2684 if (VarStoreName
!= NULL
) {
2685 FreePool (VarStoreName
);
2688 if (VarStore
!= NULL
) {
2689 FreePool (VarStore
);
2697 This function route the full request resp string for efi varstore.
2699 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
2701 @param EfiVarStoreInfo The efi varstore info which is save in the EFI
2702 varstore data structure.
2703 @param RequestResp Pointer to a null-terminated Unicode string in
2704 <ConfigResp> format.
2705 @param Result Pointer to a null-terminated Unicode string in
2706 <ConfigResp> format.
2708 @retval EFI_SUCCESS The Results string is set to the full request string.
2709 And AltCfgResp contains all default value string.
2710 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
2711 @retval EFI_INVALID_PARAMETER Request points to NULL.
2715 RouteConfigRespForEfiVarStore (
2716 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
2717 IN EFI_IFR_VARSTORE_EFI
*EfiVarStoreInfo
,
2718 IN EFI_STRING RequestResp
,
2719 OUT EFI_STRING
*Result
2723 EFI_STRING VarStoreName
;
2728 Status
= EFI_SUCCESS
;
2731 VarStoreName
= NULL
;
2733 VarStoreName
= AllocateZeroPool (AsciiStrSize ((CHAR8
*)EfiVarStoreInfo
->Name
) * sizeof (CHAR16
));
2734 if (VarStoreName
== NULL
) {
2735 Status
= EFI_OUT_OF_RESOURCES
;
2738 AsciiStrToUnicodeStr ((CHAR8
*) EfiVarStoreInfo
->Name
, VarStoreName
);
2740 Status
= gRT
->GetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, NULL
, &BufferSize
, NULL
);
2741 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
2745 BlockSize
= BufferSize
;
2746 VarStore
= AllocateZeroPool (BufferSize
);
2747 ASSERT (VarStore
!= NULL
);
2748 Status
= gRT
->GetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, NULL
, &BufferSize
, VarStore
);
2749 if (EFI_ERROR (Status
)) {
2753 Status
= HiiConfigToBlock(This
, RequestResp
, VarStore
, &BlockSize
, Result
);
2754 if (EFI_ERROR (Status
)) {
2758 Status
= gRT
->SetVariable (VarStoreName
, &EfiVarStoreInfo
->Guid
, EfiVarStoreInfo
->Attributes
, BufferSize
, VarStore
);
2759 if (EFI_ERROR (Status
)) {
2764 if (VarStoreName
!= NULL
) {
2765 FreePool (VarStoreName
);
2768 if (VarStore
!= NULL
) {
2769 FreePool (VarStore
);
2776 This function allows a caller to extract the current configuration
2777 for one or more named elements from one or more drivers.
2779 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
2781 @param Request A null-terminated Unicode string in
2782 <MultiConfigRequest> format.
2783 @param Progress On return, points to a character in the Request
2784 string. Points to the string's null terminator if
2785 request was successful. Points to the most recent
2786 & before the first failing name / value pair (or
2787 the beginning of the string if the failure is in
2788 the first name / value pair) if the request was
2790 @param Results Null-terminated Unicode string in
2791 <MultiConfigAltResp> format which has all values
2792 filled in for the names in the Request string.
2793 String to be allocated by the called function.
2795 @retval EFI_SUCCESS The Results string is filled with the values
2796 corresponding to all requested names.
2797 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
2798 results that must be stored awaiting possible
2800 @retval EFI_NOT_FOUND Routing data doesn't match any known driver.
2801 Progress set to the "G" in "GUID" of the routing
2802 header that doesn't match. Note: There is no
2803 requirement that all routing data be validated
2804 before any configuration extraction.
2805 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Request
2806 parameter would result in this type of error. The
2807 Progress parameter is set to NULL.
2808 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set to most recent &
2809 before the error or the beginning of the string.
2810 @retval EFI_INVALID_PARAMETER Unknown name. Progress points to the & before the
2816 HiiConfigRoutingExtractConfig (
2817 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
2818 IN CONST EFI_STRING Request
,
2819 OUT EFI_STRING
*Progress
,
2820 OUT EFI_STRING
*Results
2823 HII_DATABASE_PRIVATE_DATA
*Private
;
2824 EFI_STRING StringPtr
;
2825 EFI_STRING ConfigRequest
;
2827 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
2828 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
2831 HII_DATABASE_RECORD
*Database
;
2832 UINT8
*DevicePathPkg
;
2833 UINT8
*CurrentDevicePath
;
2834 EFI_HANDLE DriverHandle
;
2835 EFI_HII_HANDLE HiiHandle
;
2836 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
2837 EFI_STRING AccessProgress
;
2838 EFI_STRING AccessResults
;
2839 EFI_STRING DefaultResults
;
2840 BOOLEAN FirstElement
;
2841 BOOLEAN IfrDataParsedFlag
;
2842 BOOLEAN IsEfiVarStore
;
2843 EFI_IFR_VARSTORE_EFI
*EfiVarStoreInfo
;
2845 if (This
== NULL
|| Progress
== NULL
|| Results
== NULL
) {
2846 return EFI_INVALID_PARAMETER
;
2849 if (Request
== NULL
) {
2851 return EFI_INVALID_PARAMETER
;
2854 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
2855 StringPtr
= Request
;
2856 *Progress
= StringPtr
;
2857 DefaultResults
= NULL
;
2858 ConfigRequest
= NULL
;
2859 Status
= EFI_SUCCESS
;
2860 AccessResults
= NULL
;
2861 AccessProgress
= NULL
;
2863 IfrDataParsedFlag
= FALSE
;
2864 IsEfiVarStore
= FALSE
;
2865 EfiVarStoreInfo
= NULL
;
2868 // The first element of <MultiConfigRequest> should be
2869 // <GuidHdr>, which is in 'GUID='<Guid> syntax.
2871 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
2872 return EFI_INVALID_PARAMETER
;
2875 FirstElement
= TRUE
;
2878 // Allocate a fix length of memory to store Results. Reallocate memory for
2879 // Results if this fix length is insufficient.
2881 *Results
= (EFI_STRING
) AllocateZeroPool (MAX_STRING_LENGTH
);
2882 if (*Results
== NULL
) {
2883 return EFI_OUT_OF_RESOURCES
;
2886 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) == 0) {
2888 // If parsing error, set Progress to the beginning of the <MultiConfigRequest>
2889 // or most recent & before the error.
2891 if (StringPtr
== Request
) {
2892 *Progress
= StringPtr
;
2894 *Progress
= StringPtr
- 1;
2898 // Process each <ConfigRequest> of <MultiConfigRequest>
2900 Length
= CalculateConfigStringLen (StringPtr
);
2901 ConfigRequest
= AllocateCopyPool ((Length
+ 1) * sizeof (CHAR16
), StringPtr
);
2902 if (ConfigRequest
== NULL
) {
2903 Status
= EFI_OUT_OF_RESOURCES
;
2906 *(ConfigRequest
+ Length
) = 0;
2909 // Get the UEFI device path
2911 Status
= GetDevicePath (ConfigRequest
, (UINT8
**) &DevicePath
);
2912 if (EFI_ERROR (Status
)) {
2917 // Find driver which matches the routing data.
2919 DriverHandle
= NULL
;
2922 for (Link
= Private
->DatabaseList
.ForwardLink
;
2923 Link
!= &Private
->DatabaseList
;
2924 Link
= Link
->ForwardLink
2926 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
2927 if ((DevicePathPkg
= Database
->PackageList
->DevicePathPkg
) != NULL
) {
2928 CurrentDevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
2932 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) CurrentDevicePath
)
2934 DriverHandle
= Database
->DriverHandle
;
2935 HiiHandle
= Database
->Handle
;
2942 // Try to find driver handle by device path.
2944 if (DriverHandle
== NULL
) {
2945 TempDevicePath
= DevicePath
;
2946 Status
= gBS
->LocateDevicePath (
2947 &gEfiDevicePathProtocolGuid
,
2951 if (EFI_ERROR (Status
) || (DriverHandle
== NULL
)) {
2953 // Routing data does not match any known driver.
2954 // Set Progress to the 'G' in "GUID" of the routing header.
2956 *Progress
= StringPtr
;
2957 Status
= EFI_NOT_FOUND
;
2963 // Check whether ConfigRequest contains request string OFFSET/WIDTH
2965 IfrDataParsedFlag
= FALSE
;
2966 if ((HiiHandle
!= NULL
) && (StrStr (ConfigRequest
, L
"&OFFSET=") == NULL
)) {
2968 // Get the full request string from IFR when HiiPackage is registered to HiiHandle
2970 IfrDataParsedFlag
= TRUE
;
2971 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &ConfigRequest
, &DefaultResults
, &AccessProgress
);
2972 if (EFI_ERROR (Status
)) {
2974 // AccessProgress indicates the parsing progress on <ConfigRequest>.
2975 // Map it to the progress on <MultiConfigRequest> then return it.
2977 *Progress
= StrStr (StringPtr
, AccessProgress
);
2981 // Not any request block is found.
2983 if (StrStr (ConfigRequest
, L
"&OFFSET=") == NULL
) {
2984 AccessResults
= AllocateCopyPool (StrSize (ConfigRequest
), ConfigRequest
);
2985 goto NextConfigString
;
2990 // Check whether this ConfigRequest is search from Efi varstore type storage.
2992 Status
= GetVarStoreType(Database
, ConfigRequest
, &IsEfiVarStore
, &EfiVarStoreInfo
);
2993 if (EFI_ERROR (Status
)) {
2997 if (IsEfiVarStore
) {
2999 // Call the GetVariable function to extract settings.
3001 Status
= GetConfigRespFromEfiVarStore(This
, EfiVarStoreInfo
, ConfigRequest
, &AccessResults
, &AccessProgress
);
3002 FreePool (EfiVarStoreInfo
);
3005 // Call corresponding ConfigAccess protocol to extract settings
3007 Status
= gBS
->HandleProtocol (
3009 &gEfiHiiConfigAccessProtocolGuid
,
3010 (VOID
**) &ConfigAccess
3012 ASSERT_EFI_ERROR (Status
);
3014 Status
= ConfigAccess
->ExtractConfig (
3021 if (EFI_ERROR (Status
)) {
3023 // AccessProgress indicates the parsing progress on <ConfigRequest>.
3024 // Map it to the progress on <MultiConfigRequest> then return it.
3026 *Progress
= StrStr (StringPtr
, AccessProgress
);
3031 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'
3032 // which seperates the first <ConfigAltResp> and the following ones.
3034 ASSERT (*AccessProgress
== 0);
3037 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
3039 if (!IfrDataParsedFlag
&& HiiHandle
!= NULL
) {
3040 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &ConfigRequest
, &DefaultResults
, NULL
);
3041 ASSERT_EFI_ERROR (Status
);
3044 FreePool (DevicePath
);
3047 if (DefaultResults
!= NULL
) {
3048 Status
= MergeDefaultString (&AccessResults
, DefaultResults
);
3049 ASSERT_EFI_ERROR (Status
);
3050 FreePool (DefaultResults
);
3051 DefaultResults
= NULL
;
3055 if (!FirstElement
) {
3056 Status
= AppendToMultiString (Results
, L
"&");
3057 ASSERT_EFI_ERROR (Status
);
3060 Status
= AppendToMultiString (Results
, AccessResults
);
3061 ASSERT_EFI_ERROR (Status
);
3063 FirstElement
= FALSE
;
3065 FreePool (AccessResults
);
3066 AccessResults
= NULL
;
3067 FreePool (ConfigRequest
);
3068 ConfigRequest
= NULL
;
3071 // Go to next <ConfigRequest> (skip '&').
3073 StringPtr
+= Length
;
3074 if (*StringPtr
== 0) {
3075 *Progress
= StringPtr
;
3083 if (EFI_ERROR (Status
)) {
3084 FreePool (*Results
);
3088 if (ConfigRequest
!= NULL
) {
3089 FreePool (ConfigRequest
);
3092 if (AccessResults
!= NULL
) {
3093 FreePool (AccessResults
);
3096 if (DefaultResults
!= NULL
) {
3097 FreePool (DefaultResults
);
3100 if (DevicePath
!= NULL
) {
3101 FreePool (DevicePath
);
3109 This function allows the caller to request the current configuration for the
3110 entirety of the current HII database and returns the data in a
3111 null-terminated Unicode string.
3113 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
3115 @param Results Null-terminated Unicode string in
3116 <MultiConfigAltResp> format which has all values
3117 filled in for the names in the Request string.
3118 String to be allocated by the called function.
3119 De-allocation is up to the caller.
3121 @retval EFI_SUCCESS The Results string is filled with the values
3122 corresponding to all requested names.
3123 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
3124 results that must be stored awaiting possible
3126 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Results
3127 parameter would result in this type of error.
3132 HiiConfigRoutingExportConfig (
3133 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
3134 OUT EFI_STRING
*Results
3138 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
3139 EFI_STRING AccessResults
;
3140 EFI_STRING Progress
;
3141 EFI_STRING StringPtr
;
3142 EFI_STRING ConfigRequest
;
3144 EFI_HANDLE
*ConfigAccessHandles
;
3145 UINTN NumberConfigAccessHandles
;
3146 BOOLEAN FirstElement
;
3147 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
3148 EFI_HII_HANDLE HiiHandle
;
3149 EFI_STRING DefaultResults
;
3150 HII_DATABASE_PRIVATE_DATA
*Private
;
3152 HII_DATABASE_RECORD
*Database
;
3153 UINT8
*DevicePathPkg
;
3154 UINT8
*CurrentDevicePath
;
3155 BOOLEAN IfrDataParsedFlag
;
3157 if (This
== NULL
|| Results
== NULL
) {
3158 return EFI_INVALID_PARAMETER
;
3161 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
3164 // Allocate a fix length of memory to store Results. Reallocate memory for
3165 // Results if this fix length is insufficient.
3167 *Results
= (EFI_STRING
) AllocateZeroPool (MAX_STRING_LENGTH
);
3168 if (*Results
== NULL
) {
3169 return EFI_OUT_OF_RESOURCES
;
3172 NumberConfigAccessHandles
= 0;
3173 Status
= gBS
->LocateHandleBuffer (
3175 &gEfiHiiConfigAccessProtocolGuid
,
3177 &NumberConfigAccessHandles
,
3178 &ConfigAccessHandles
3180 if (EFI_ERROR (Status
)) {
3184 FirstElement
= TRUE
;
3186 for (Index
= 0; Index
< NumberConfigAccessHandles
; Index
++) {
3187 Status
= gBS
->HandleProtocol (
3188 ConfigAccessHandles
[Index
],
3189 &gEfiHiiConfigAccessProtocolGuid
,
3190 (VOID
**) &ConfigAccess
3192 if (EFI_ERROR (Status
)) {
3197 // Get DevicePath and HiiHandle for this ConfigAccess driver handle
3199 IfrDataParsedFlag
= FALSE
;
3202 DefaultResults
= NULL
;
3204 ConfigRequest
= NULL
;
3205 DevicePath
= DevicePathFromHandle (ConfigAccessHandles
[Index
]);
3206 if (DevicePath
!= NULL
) {
3207 for (Link
= Private
->DatabaseList
.ForwardLink
;
3208 Link
!= &Private
->DatabaseList
;
3209 Link
= Link
->ForwardLink
3211 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
3212 if ((DevicePathPkg
= Database
->PackageList
->DevicePathPkg
) != NULL
) {
3213 CurrentDevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
3217 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) CurrentDevicePath
)
3219 HiiHandle
= Database
->Handle
;
3226 Status
= ConfigAccess
->ExtractConfig (
3232 if (EFI_ERROR (Status
)) {
3234 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
3236 if (HiiHandle
!= NULL
&& DevicePath
!= NULL
) {
3237 IfrDataParsedFlag
= TRUE
;
3238 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &ConfigRequest
, &DefaultResults
, NULL
);
3240 // Get the full request string to get the Current setting again.
3242 if (!EFI_ERROR (Status
) && ConfigRequest
!= NULL
) {
3243 Status
= ConfigAccess
->ExtractConfig (
3249 FreePool (ConfigRequest
);
3251 Status
= EFI_NOT_FOUND
;
3256 if (!EFI_ERROR (Status
)) {
3258 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
3260 if (!IfrDataParsedFlag
&& HiiHandle
!= NULL
&& DevicePath
!= NULL
) {
3261 StringPtr
= StrStr (AccessResults
, L
"&GUID=");
3262 if (StringPtr
!= NULL
) {
3265 if (StrStr (AccessResults
, L
"&OFFSET=") != NULL
) {
3266 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &AccessResults
, &DefaultResults
, NULL
);
3267 ASSERT_EFI_ERROR (Status
);
3269 if (StringPtr
!= NULL
) {
3274 // Merge the default sting from IFR code into the got setting from driver.
3276 if (DefaultResults
!= NULL
) {
3277 Status
= MergeDefaultString (&AccessResults
, DefaultResults
);
3278 ASSERT_EFI_ERROR (Status
);
3279 FreePool (DefaultResults
);
3280 DefaultResults
= NULL
;
3284 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'
3285 // which seperates the first <ConfigAltResp> and the following ones.
3287 if (!FirstElement
) {
3288 Status
= AppendToMultiString (Results
, L
"&");
3289 ASSERT_EFI_ERROR (Status
);
3292 Status
= AppendToMultiString (Results
, AccessResults
);
3293 ASSERT_EFI_ERROR (Status
);
3295 FirstElement
= FALSE
;
3297 FreePool (AccessResults
);
3298 AccessResults
= NULL
;
3301 FreePool (ConfigAccessHandles
);
3308 This function processes the results of processing forms and routes it to the
3309 appropriate handlers or storage.
3311 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
3313 @param Configuration A null-terminated Unicode string in
3314 <MulltiConfigResp> format.
3315 @param Progress A pointer to a string filled in with the offset of
3316 the most recent & before the first failing name /
3317 value pair (or the beginning of the string if the
3318 failure is in the first name / value pair) or the
3319 terminating NULL if all was successful.
3321 @retval EFI_SUCCESS The results have been distributed or are awaiting
3323 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
3324 results that must be stored awaiting possible
3326 @retval EFI_INVALID_PARAMETER Passing in a NULL for the Configuration parameter
3327 would result in this type of error.
3328 @retval EFI_NOT_FOUND Target for the specified routing data was not
3334 HiiConfigRoutingRouteConfig (
3335 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
3336 IN CONST EFI_STRING Configuration
,
3337 OUT EFI_STRING
*Progress
3340 HII_DATABASE_PRIVATE_DATA
*Private
;
3341 EFI_STRING StringPtr
;
3342 EFI_STRING ConfigResp
;
3345 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
3346 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
3348 HII_DATABASE_RECORD
*Database
;
3349 UINT8
*DevicePathPkg
;
3350 UINT8
*CurrentDevicePath
;
3351 EFI_HANDLE DriverHandle
;
3352 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
3353 EFI_STRING AccessProgress
;
3354 EFI_IFR_VARSTORE_EFI
*EfiVarStoreInfo
;
3355 BOOLEAN IsEfiVarstore
;
3357 if (This
== NULL
|| Progress
== NULL
) {
3358 return EFI_INVALID_PARAMETER
;
3361 if (Configuration
== NULL
) {
3363 return EFI_INVALID_PARAMETER
;
3366 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
3367 StringPtr
= Configuration
;
3368 *Progress
= StringPtr
;
3370 AccessProgress
= NULL
;
3371 EfiVarStoreInfo
= NULL
;
3372 IsEfiVarstore
= FALSE
;
3375 // The first element of <MultiConfigResp> should be
3376 // <GuidHdr>, which is in 'GUID='<Guid> syntax.
3378 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
3379 return EFI_INVALID_PARAMETER
;
3382 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) == 0) {
3384 // If parsing error, set Progress to the beginning of the <MultiConfigResp>
3385 // or most recent & before the error.
3387 if (StringPtr
== Configuration
) {
3388 *Progress
= StringPtr
;
3390 *Progress
= StringPtr
- 1;
3394 // Process each <ConfigResp> of <MultiConfigResp>
3396 Length
= CalculateConfigStringLen (StringPtr
);
3397 ConfigResp
= AllocateCopyPool ((Length
+ 1) * sizeof (CHAR16
), StringPtr
);
3398 if (ConfigResp
== NULL
) {
3399 return EFI_OUT_OF_RESOURCES
;
3402 // Append '\0' to the end of ConfigRequest
3404 *(ConfigResp
+ Length
) = 0;
3407 // Get the UEFI device path
3409 Status
= GetDevicePath (ConfigResp
, (UINT8
**) &DevicePath
);
3410 if (EFI_ERROR (Status
)) {
3411 FreePool (ConfigResp
);
3416 // Find driver which matches the routing data.
3418 DriverHandle
= NULL
;
3419 for (Link
= Private
->DatabaseList
.ForwardLink
;
3420 Link
!= &Private
->DatabaseList
;
3421 Link
= Link
->ForwardLink
3423 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
3425 if ((DevicePathPkg
= Database
->PackageList
->DevicePathPkg
) != NULL
) {
3426 CurrentDevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
3430 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) CurrentDevicePath
)
3432 DriverHandle
= Database
->DriverHandle
;
3439 // Try to find driver handle by device path.
3441 if (DriverHandle
== NULL
) {
3442 TempDevicePath
= DevicePath
;
3443 Status
= gBS
->LocateDevicePath (
3444 &gEfiDevicePathProtocolGuid
,
3448 if (EFI_ERROR (Status
) || (DriverHandle
== NULL
)) {
3450 // Routing data does not match any known driver.
3451 // Set Progress to the 'G' in "GUID" of the routing header.
3453 FreePool (DevicePath
);
3454 *Progress
= StringPtr
;
3455 FreePool (ConfigResp
);
3456 return EFI_NOT_FOUND
;
3460 FreePool (DevicePath
);
3463 // Check whether this ConfigRequest is search from Efi varstore type storage.
3465 Status
= GetVarStoreType(Database
, ConfigResp
, &IsEfiVarstore
, &EfiVarStoreInfo
);
3466 if (EFI_ERROR (Status
)) {
3470 if (IsEfiVarstore
) {
3472 // Call the SetVariable function to route settings.
3474 Status
= RouteConfigRespForEfiVarStore(This
, EfiVarStoreInfo
, ConfigResp
, &AccessProgress
);
3475 FreePool (EfiVarStoreInfo
);
3478 // Call corresponding ConfigAccess protocol to route settings
3480 Status
= gBS
->HandleProtocol (
3482 &gEfiHiiConfigAccessProtocolGuid
,
3483 (VOID
**) &ConfigAccess
3485 ASSERT_EFI_ERROR (Status
);
3487 Status
= ConfigAccess
->RouteConfig (
3493 if (EFI_ERROR (Status
)) {
3495 // AccessProgress indicates the parsing progress on <ConfigResp>.
3496 // Map it to the progress on <MultiConfigResp> then return it.
3498 *Progress
= StrStr (StringPtr
, AccessProgress
);
3500 FreePool (ConfigResp
);
3504 FreePool (ConfigResp
);
3508 // Go to next <ConfigResp> (skip '&').
3510 StringPtr
+= Length
;
3511 if (*StringPtr
== 0) {
3512 *Progress
= StringPtr
;
3525 This helper function is to be called by drivers to map configuration data
3526 stored in byte array ("block") formats such as UEFI Variables into current
3527 configuration strings.
3529 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
3531 @param ConfigRequest A null-terminated Unicode string in
3532 <ConfigRequest> format.
3533 @param Block Array of bytes defining the block's configuration.
3534 @param BlockSize Length in bytes of Block.
3535 @param Config Filled-in configuration string. String allocated
3536 by the function. Returned only if call is
3537 successful. It is <ConfigResp> string format.
3538 @param Progress A pointer to a string filled in with the offset of
3539 the most recent & before the first failing
3540 name/value pair (or the beginning of the string if
3541 the failure is in the first name / value pair) or
3542 the terminating NULL if all was successful.
3544 @retval EFI_SUCCESS The request succeeded. Progress points to the null
3545 terminator at the end of the ConfigRequest
3547 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress
3548 points to the first character of ConfigRequest.
3549 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigRequest or
3550 Block parameter would result in this type of
3551 error. Progress points to the first character of
3553 @retval EFI_DEVICE_ERROR Block not large enough. Progress undefined.
3554 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted string.
3555 Block is left updated and Progress points at
3556 the "&" preceding the first non-<BlockName>.
3562 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
3563 IN CONST EFI_STRING ConfigRequest
,
3564 IN CONST UINT8
*Block
,
3565 IN CONST UINTN BlockSize
,
3566 OUT EFI_STRING
*Config
,
3567 OUT EFI_STRING
*Progress
3570 HII_DATABASE_PRIVATE_DATA
*Private
;
3571 EFI_STRING StringPtr
;
3579 EFI_STRING ValueStr
;
3580 EFI_STRING ConfigElement
;
3586 if (This
== NULL
|| Progress
== NULL
|| Config
== NULL
) {
3587 return EFI_INVALID_PARAMETER
;
3590 if (Block
== NULL
|| ConfigRequest
== NULL
) {
3591 *Progress
= ConfigRequest
;
3592 return EFI_INVALID_PARAMETER
;
3596 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
3597 ASSERT (Private
!= NULL
);
3599 StringPtr
= ConfigRequest
;
3602 ConfigElement
= NULL
;
3605 // Allocate a fix length of memory to store Results. Reallocate memory for
3606 // Results if this fix length is insufficient.
3608 *Config
= (EFI_STRING
) AllocateZeroPool (MAX_STRING_LENGTH
);
3609 if (*Config
== NULL
) {
3610 return EFI_OUT_OF_RESOURCES
;
3616 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
3617 *Progress
= StringPtr
;
3618 Status
= EFI_INVALID_PARAMETER
;
3621 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"PATH=", StrLen (L
"PATH=")) != 0) {
3624 if (*StringPtr
== 0) {
3625 *Progress
= StringPtr
- 1;
3626 Status
= EFI_INVALID_PARAMETER
;
3630 while (*StringPtr
!= L
'&' && *StringPtr
!= 0) {
3633 if (*StringPtr
== 0) {
3634 *Progress
= StringPtr
;
3635 Status
= EFI_SUCCESS
;
3637 AppendToMultiString(Config
, ConfigRequest
);
3638 HiiToLower (*Config
);
3648 // Copy <ConfigHdr> and an additional '&' to <ConfigResp>
3650 TemChar
= *StringPtr
;
3652 AppendToMultiString(Config
, ConfigRequest
);
3653 *StringPtr
= TemChar
;
3656 // Parse each <RequestElement> if exists
3657 // Only <BlockName> format is supported by this help function.
3658 // <BlockName> ::= 'OFFSET='<Number>&'WIDTH='<Number>
3660 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"OFFSET=", StrLen (L
"OFFSET=")) == 0) {
3662 // Back up the header of one <BlockName>
3666 StringPtr
+= StrLen (L
"OFFSET=");
3670 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
3671 if (EFI_ERROR (Status
)) {
3672 *Progress
= ConfigRequest
;
3679 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
3681 FreePool (TmpBuffer
);
3683 StringPtr
+= Length
;
3684 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
3685 *Progress
= StringPtr
- Length
- StrLen (L
"OFFSET=") - 1;
3686 Status
= EFI_INVALID_PARAMETER
;
3689 StringPtr
+= StrLen (L
"&WIDTH=");
3694 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
3695 if (EFI_ERROR (Status
)) {
3696 *Progress
= ConfigRequest
;
3703 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
3705 FreePool (TmpBuffer
);
3707 StringPtr
+= Length
;
3708 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
3709 *Progress
= StringPtr
- Length
- StrLen (L
"&WIDTH=");
3710 Status
= EFI_INVALID_PARAMETER
;
3715 // Calculate Value and convert it to hex string.
3717 if (Offset
+ Width
> BlockSize
) {
3718 *Progress
= StringPtr
;
3719 Status
= EFI_DEVICE_ERROR
;
3723 Value
= (UINT8
*) AllocateZeroPool (Width
);
3724 if (Value
== NULL
) {
3725 *Progress
= ConfigRequest
;
3726 Status
= EFI_OUT_OF_RESOURCES
;
3730 CopyMem (Value
, (UINT8
*) Block
+ Offset
, Width
);
3732 Length
= Width
* 2 + 1;
3733 ValueStr
= (EFI_STRING
) AllocateZeroPool (Length
* sizeof (CHAR16
));
3734 if (ValueStr
== NULL
) {
3735 *Progress
= ConfigRequest
;
3736 Status
= EFI_OUT_OF_RESOURCES
;
3740 TemString
= ValueStr
;
3741 TemBuffer
= Value
+ Width
- 1;
3742 for (Index
= 0; Index
< Width
; Index
++, TemBuffer
--) {
3743 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
3750 // Build a ConfigElement
3752 Length
+= StringPtr
- TmpPtr
+ 1 + StrLen (L
"VALUE=");
3753 ConfigElement
= (EFI_STRING
) AllocateZeroPool (Length
* sizeof (CHAR16
));
3754 if (ConfigElement
== NULL
) {
3755 Status
= EFI_OUT_OF_RESOURCES
;
3758 CopyMem (ConfigElement
, TmpPtr
, (StringPtr
- TmpPtr
+ 1) * sizeof (CHAR16
));
3759 if (*StringPtr
== 0) {
3760 *(ConfigElement
+ (StringPtr
- TmpPtr
)) = L
'&';
3762 *(ConfigElement
+ (StringPtr
- TmpPtr
) + 1) = 0;
3763 StrCat (ConfigElement
, L
"VALUE=");
3764 StrCat (ConfigElement
, ValueStr
);
3766 AppendToMultiString (Config
, ConfigElement
);
3768 FreePool (ConfigElement
);
3769 FreePool (ValueStr
);
3770 ConfigElement
= NULL
;
3774 // If '\0', parsing is finished. Otherwise skip '&' to continue
3776 if (*StringPtr
== 0) {
3779 AppendToMultiString (Config
, L
"&");
3784 if (*StringPtr
!= 0) {
3785 *Progress
= StringPtr
- 1;
3786 Status
= EFI_INVALID_PARAMETER
;
3790 HiiToLower (*Config
);
3791 *Progress
= StringPtr
;
3795 if (*Config
!= NULL
) {
3799 if (ValueStr
!= NULL
) {
3800 FreePool (ValueStr
);
3802 if (Value
!= NULL
) {
3805 if (ConfigElement
!= NULL
) {
3806 FreePool (ConfigElement
);
3815 This helper function is to be called by drivers to map configuration strings
3816 to configurations stored in byte array ("block") formats such as UEFI Variables.
3818 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
3820 @param ConfigResp A null-terminated Unicode string in <ConfigResp>
3822 @param Block A possibly null array of bytes representing the
3823 current block. Only bytes referenced in the
3824 ConfigResp string in the block are modified. If
3825 this parameter is null or if the *BlockSize
3826 parameter is (on input) shorter than required by
3827 the Configuration string, only the BlockSize
3828 parameter is updated and an appropriate status
3829 (see below) is returned.
3830 @param BlockSize The length of the Block in units of UINT8. On
3831 input, this is the size of the Block. On output,
3832 if successful, contains the index of the last
3833 modified byte in the Block.
3834 @param Progress On return, points to an element of the ConfigResp
3835 string filled in with the offset of the most
3836 recent '&' before the first failing name / value
3837 pair (or the beginning of the string if the
3838 failure is in the first name / value pair) or the
3839 terminating NULL if all was successful.
3841 @retval EFI_SUCCESS The request succeeded. Progress points to the null
3842 terminator at the end of the ConfigResp string.
3843 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress
3844 points to the first character of ConfigResp.
3845 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigResp or
3846 Block parameter would result in this type of
3847 error. Progress points to the first character of
3849 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted name /
3850 value pair. Block is left updated and
3851 Progress points at the '&' preceding the first
3853 @retval EFI_DEVICE_ERROR Block not large enough. Progress undefined.
3854 @retval EFI_NOT_FOUND Target for the specified routing data was not found.
3855 Progress points to the "G" in "GUID" of the errant
3862 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
3863 IN CONST EFI_STRING ConfigResp
,
3864 IN OUT UINT8
*Block
,
3865 IN OUT UINTN
*BlockSize
,
3866 OUT EFI_STRING
*Progress
3869 HII_DATABASE_PRIVATE_DATA
*Private
;
3870 EFI_STRING StringPtr
;
3880 if (This
== NULL
|| BlockSize
== NULL
|| Progress
== NULL
) {
3881 return EFI_INVALID_PARAMETER
;
3884 *Progress
= ConfigResp
;
3885 if (ConfigResp
== NULL
) {
3886 return EFI_INVALID_PARAMETER
;
3889 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
3890 ASSERT (Private
!= NULL
);
3892 StringPtr
= ConfigResp
;
3893 BufferSize
= *BlockSize
;
3900 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
3901 *Progress
= StringPtr
;
3902 Status
= EFI_INVALID_PARAMETER
;
3905 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"PATH=", StrLen (L
"PATH=")) != 0) {
3908 if (*StringPtr
== 0) {
3909 *Progress
= StringPtr
;
3910 Status
= EFI_INVALID_PARAMETER
;
3914 while (*StringPtr
!= L
'&' && *StringPtr
!= 0) {
3917 if (*StringPtr
== 0) {
3918 *Progress
= StringPtr
;
3919 Status
= EFI_INVALID_PARAMETER
;
3924 // Parse each <ConfigElement> if exists
3925 // Only '&'<BlockConfig> format is supported by this help function.
3926 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE='<Number>
3928 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) == 0) {
3929 StringPtr
+= StrLen (L
"&OFFSET=");
3933 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
3934 if (EFI_ERROR (Status
)) {
3935 *Progress
= ConfigResp
;
3942 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
3944 FreePool (TmpBuffer
);
3946 StringPtr
+= Length
;
3947 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
3948 *Progress
= StringPtr
- Length
- StrLen (L
"&OFFSET=");
3949 Status
= EFI_INVALID_PARAMETER
;
3952 StringPtr
+= StrLen (L
"&WIDTH=");
3957 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
3958 if (EFI_ERROR (Status
)) {
3959 *Progress
= ConfigResp
;
3966 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
3968 FreePool (TmpBuffer
);
3970 StringPtr
+= Length
;
3971 if (StrnCmp (StringPtr
, L
"&VALUE=", StrLen (L
"&VALUE=")) != 0) {
3972 *Progress
= StringPtr
- Length
- StrLen (L
"&WIDTH=");
3973 Status
= EFI_INVALID_PARAMETER
;
3976 StringPtr
+= StrLen (L
"&VALUE=");
3981 Status
= GetValueOfNumber (StringPtr
, &Value
, &Length
);
3982 if (EFI_ERROR (Status
)) {
3983 *Progress
= ConfigResp
;
3987 StringPtr
+= Length
;
3988 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
3989 *Progress
= StringPtr
- Length
- StrLen (L
"&VALUE=");
3990 Status
= EFI_INVALID_PARAMETER
;
3995 // Update the Block with configuration info
3997 if ((Block
!= NULL
) && (Offset
+ Width
<= BufferSize
)) {
3998 CopyMem (Block
+ Offset
, Value
, Width
);
4000 if (Offset
+ Width
> MaxBlockSize
) {
4001 MaxBlockSize
= Offset
+ Width
;
4008 // If '\0', parsing is finished.
4010 if (*StringPtr
== 0) {
4016 // The input string is not ConfigResp format, return error.
4018 if (*StringPtr
!= 0) {
4019 *Progress
= StringPtr
;
4020 Status
= EFI_INVALID_PARAMETER
;
4024 *Progress
= StringPtr
+ StrLen (StringPtr
);
4025 *BlockSize
= MaxBlockSize
- 1;
4027 if (MaxBlockSize
> BufferSize
) {
4028 *BlockSize
= MaxBlockSize
;
4029 if (Block
!= NULL
) {
4030 return EFI_DEVICE_ERROR
;
4034 if (Block
== NULL
) {
4035 *Progress
= ConfigResp
;
4036 return EFI_INVALID_PARAMETER
;
4043 if (Value
!= NULL
) {
4051 This helper function is to be called by drivers to extract portions of
4052 a larger configuration string.
4054 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
4056 @param Configuration A null-terminated Unicode string in
4057 <MultiConfigAltResp> format.
4058 @param Guid A pointer to the GUID value to search for in the
4059 routing portion of the ConfigResp string when
4060 retrieving the requested data. If Guid is NULL,
4061 then all GUID values will be searched for.
4062 @param Name A pointer to the NAME value to search for in the
4063 routing portion of the ConfigResp string when
4064 retrieving the requested data. If Name is NULL,
4065 then all Name values will be searched for.
4066 @param DevicePath A pointer to the PATH value to search for in the
4067 routing portion of the ConfigResp string when
4068 retrieving the requested data. If DevicePath is
4069 NULL, then all DevicePath values will be searched
4071 @param AltCfgId A pointer to the ALTCFG value to search for in the
4072 routing portion of the ConfigResp string when
4073 retrieving the requested data. If this parameter
4074 is NULL, then the current setting will be
4076 @param AltCfgResp A pointer to a buffer which will be allocated by
4077 the function which contains the retrieved string
4078 as requested. This buffer is only allocated if
4079 the call was successful. It is <ConfigResp> format.
4081 @retval EFI_SUCCESS The request succeeded. The requested data was
4082 extracted and placed in the newly allocated
4084 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate AltCfgResp.
4085 @retval EFI_INVALID_PARAMETER Any parameter is invalid.
4086 @retval EFI_NOT_FOUND Target for the specified routing data was not
4093 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
4094 IN CONST EFI_STRING Configuration
,
4095 IN CONST EFI_GUID
*Guid
,
4096 IN CONST EFI_STRING Name
,
4097 IN CONST EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
4098 IN CONST UINT16
*AltCfgId
,
4099 OUT EFI_STRING
*AltCfgResp
4103 EFI_STRING StringPtr
;
4104 EFI_STRING HdrStart
;
4111 EFI_STRING AltIdStr
;
4128 if (This
== NULL
|| Configuration
== NULL
|| AltCfgResp
== NULL
) {
4129 return EFI_INVALID_PARAMETER
;
4132 StringPtr
= Configuration
;
4133 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
4134 return EFI_INVALID_PARAMETER
;
4138 // Generate the sub string for later matching.
4140 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*) Guid
, 1, &GuidStr
);
4143 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) DevicePath
),
4144 (VOID
*) DevicePath
,
4148 if (AltCfgId
!= NULL
) {
4149 GenerateSubStr (L
"ALTCFG=", sizeof (UINT16
), (VOID
*) AltCfgId
, 3, &AltIdStr
);
4152 GenerateSubStr (L
"NAME=", StrLen (Name
) * sizeof (CHAR16
), (VOID
*) Name
, 2, &NameStr
);
4154 GenerateSubStr (L
"NAME=", 0, NULL
, 2, &NameStr
);
4157 while (*StringPtr
!= 0) {
4159 // Try to match the GUID
4162 TmpPtr
= StrStr (StringPtr
, GuidStr
);
4163 if (TmpPtr
== NULL
) {
4164 Status
= EFI_NOT_FOUND
;
4170 // Jump to <NameHdr>
4173 StringPtr
= TmpPtr
+ StrLen (GuidStr
);
4175 StringPtr
= StrStr (TmpPtr
, L
"NAME=");
4176 if (StringPtr
== NULL
) {
4177 Status
= EFI_NOT_FOUND
;
4185 // Try to match the NAME
4187 if (GuidFlag
&& !NameFlag
) {
4188 if (StrnCmp (StringPtr
, NameStr
, StrLen (NameStr
)) != 0) {
4192 // Jump to <PathHdr>
4195 StringPtr
+= StrLen (NameStr
);
4197 StringPtr
= StrStr (StringPtr
, L
"PATH=");
4198 if (StringPtr
== NULL
) {
4199 Status
= EFI_NOT_FOUND
;
4208 // Try to match the DevicePath
4210 if (GuidFlag
&& NameFlag
&& !PathFlag
) {
4211 if (StrnCmp (StringPtr
, PathStr
, StrLen (PathStr
)) != 0) {
4216 // Jump to '&' before <DescHdr> or <ConfigBody>
4218 if (DevicePath
!= NULL
) {
4219 StringPtr
+= StrLen (PathStr
);
4221 StringPtr
= StrStr (StringPtr
, L
"&");
4222 if (StringPtr
== NULL
) {
4223 Status
= EFI_NOT_FOUND
;
4234 // Try to match the AltCfgId
4236 if (GuidFlag
&& NameFlag
&& PathFlag
) {
4237 if (AltCfgId
== NULL
) {
4239 // Return Current Setting when AltCfgId is NULL.
4241 Status
= OutputConfigBody (StringPtr
, &Result
);
4245 // Search the <ConfigAltResp> to get the <AltResp> with AltCfgId.
4247 if (StrnCmp (StringPtr
, AltIdStr
, StrLen (AltIdStr
)) != 0) {
4253 // Skip AltIdStr and &
4255 StringPtr
= StringPtr
+ StrLen (AltIdStr
);
4256 Status
= OutputConfigBody (StringPtr
, &Result
);
4262 Status
= EFI_NOT_FOUND
;
4266 if (!EFI_ERROR (Status
) && (Result
!= NULL
)) {
4268 // Copy the <ConfigHdr> and <ConfigBody>
4270 Length
= HdrEnd
- HdrStart
+ StrLen (Result
) + 1;
4271 *AltCfgResp
= AllocateZeroPool (Length
* sizeof (CHAR16
));
4272 if (*AltCfgResp
== NULL
) {
4273 Status
= EFI_OUT_OF_RESOURCES
;
4275 StrnCpy (*AltCfgResp
, HdrStart
, HdrEnd
- HdrStart
);
4276 StrCat (*AltCfgResp
, Result
);
4277 Status
= EFI_SUCCESS
;
4281 if (GuidStr
!= NULL
) {
4284 if (NameStr
!= NULL
) {
4287 if (PathStr
!= NULL
) {
4290 if (AltIdStr
!= NULL
) {
4291 FreePool (AltIdStr
);
4293 if (Result
!= NULL
) {