2 Implementation of interfaces function for EFI_HII_CONFIG_ROUTING_PROTOCOL.
4 Copyright (c) 2007 - 2011, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 #include "HiiDatabase.h"
17 extern HII_DATABASE_PRIVATE_DATA mPrivate
;
20 Calculate the number of Unicode characters of the incoming Configuration string,
21 not including NULL terminator.
23 This is a internal function.
25 @param String String in <MultiConfigRequest> or
26 <MultiConfigResp> format.
28 @return The number of Unicode characters.
32 CalculateConfigStringLen (
39 // "GUID=" should be the first element of incoming string.
41 ASSERT (String
!= NULL
);
42 ASSERT (StrnCmp (String
, L
"GUID=", StrLen (L
"GUID=")) == 0);
45 // The beginning of next <ConfigRequest>/<ConfigResp> should be "&GUID=".
46 // Will meet '\0' if there is only one <ConfigRequest>/<ConfigResp>.
48 TmpPtr
= StrStr (String
, L
"&GUID=");
50 return StrLen (String
);
53 return (TmpPtr
- String
);
58 Convert the hex UNICODE %02x encoding of a UEFI device path to binary
59 from <PathHdr> of <ConfigHdr>.
61 This is a internal function.
63 @param String UEFI configuration string
64 @param DevicePathData Binary of a UEFI device path.
66 @retval EFI_NOT_FOUND The device path is not invalid.
67 @retval EFI_INVALID_PARAMETER Any incoming parameter is invalid.
68 @retval EFI_OUT_OF_RESOURCES Lake of resources to store neccesary structures.
69 @retval EFI_SUCCESS The device path is retrieved and translated to
76 OUT UINT8
**DevicePathData
81 UINT8
*DevicePathBuffer
;
85 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
88 if (String
== NULL
|| DevicePathData
== NULL
) {
89 return EFI_INVALID_PARAMETER
;
93 // Find the 'PATH=' of <PathHdr> and skip it.
95 for (; (*String
!= 0 && StrnCmp (String
, L
"PATH=", StrLen (L
"PATH=")) != 0); String
++);
97 return EFI_INVALID_PARAMETER
;
100 // Check whether path data does exist.
102 String
+= StrLen (L
"PATH=");
104 return EFI_INVALID_PARAMETER
;
109 // The content between 'PATH=' of <ConfigHdr> and '&' of next element
110 // or '\0' (end of configuration string) is the UNICODE %02x bytes encoding
111 // of UEFI device path.
113 for (Length
= 0; *String
!= 0 && *String
!= L
'&'; String
++, Length
++);
115 // Check DevicePath Length
117 if (((Length
+ 1) / 2) < sizeof (EFI_DEVICE_PATH_PROTOCOL
)) {
118 return EFI_NOT_FOUND
;
122 // The data in <PathHdr> is encoded as hex UNICODE %02x bytes in the same order
123 // as the device path resides in RAM memory.
124 // Translate the data into binary.
126 DevicePathBuffer
= (UINT8
*) AllocateZeroPool ((Length
+ 1) / 2);
127 if (DevicePathBuffer
== NULL
) {
128 return EFI_OUT_OF_RESOURCES
;
132 // Convert DevicePath
134 ZeroMem (TemStr
, sizeof (TemStr
));
135 for (Index
= 0; Index
< Length
; Index
++) {
136 TemStr
[0] = PathHdr
[Index
];
137 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
138 if ((Index
& 1) == 0) {
139 DevicePathBuffer
[Index
/2] = DigitUint8
;
141 DevicePathBuffer
[Index
/2] = (UINT8
) ((DevicePathBuffer
[Index
/2] << 4) + DigitUint8
);
146 // Validate DevicePath
148 DevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) DevicePathBuffer
;
149 while (!IsDevicePathEnd (DevicePath
)) {
150 if ((DevicePath
->Type
== 0) || (DevicePath
->SubType
== 0) || (DevicePathNodeLength (DevicePath
) < sizeof (EFI_DEVICE_PATH_PROTOCOL
))) {
152 // Invalid device path
154 FreePool (DevicePathBuffer
);
155 return EFI_NOT_FOUND
;
157 DevicePath
= NextDevicePathNode (DevicePath
);
161 // return the device path
163 *DevicePathData
= DevicePathBuffer
;
168 Converts the unicode character of the string from uppercase to lowercase.
169 This is a internal function.
171 @param ConfigString String to be converted
177 IN EFI_STRING ConfigString
183 ASSERT (ConfigString
!= NULL
);
186 // Convert all hex digits in range [A-F] in the configuration header to [a-f]
188 for (String
= ConfigString
, Lower
= FALSE
; *String
!= L
'\0'; String
++) {
189 if (*String
== L
'=') {
191 } else if (*String
== L
'&') {
193 } else if (Lower
&& *String
>= L
'A' && *String
<= L
'F') {
194 *String
= (CHAR16
) (*String
- L
'A' + L
'a');
202 Generate a sub string then output it.
204 This is a internal function.
206 @param String A constant string which is the prefix of the to be
207 generated string, e.g. GUID=
209 @param BufferLen The length of the Buffer in bytes.
211 @param Buffer Points to a buffer which will be converted to be the
212 content of the generated string.
214 @param Flag If 1, the buffer contains data for the value of GUID or PATH stored in
215 UINT8 *; if 2, the buffer contains unicode string for the value of NAME;
216 if 3, the buffer contains other data.
218 @param SubStr Points to the output string. It's caller's
219 responsibility to free this buffer.
225 IN CONST EFI_STRING String
,
229 OUT EFI_STRING
*SubStr
234 EFI_STRING StringHeader
;
240 ASSERT (String
!= NULL
&& SubStr
!= NULL
);
242 if (Buffer
== NULL
) {
243 *SubStr
= AllocateCopyPool (StrSize (String
), String
);
244 ASSERT (*SubStr
!= NULL
);
249 // Header + Data + '&' + '\0'
251 Length
= StrLen (String
) + BufferLen
* 2 + 1 + 1;
252 Str
= AllocateZeroPool (Length
* sizeof (CHAR16
));
253 ASSERT (Str
!= NULL
);
255 StrCpy (Str
, String
);
256 Length
= (BufferLen
* 2 + 1) * sizeof (CHAR16
);
258 StringHeader
= Str
+ StrLen (String
);
259 TemString
= (CHAR16
*) StringHeader
;
264 // Convert Buffer to Hex String in reverse order
266 TemBuffer
= ((UINT8
*) Buffer
);
267 for (Index
= 0; Index
< BufferLen
; Index
++, TemBuffer
++) {
268 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
273 // Check buffer is enough
275 TemName
= (CHAR16
*) Buffer
;
276 ASSERT ((BufferLen
* 2 + 1) >= (StrLen (TemName
) * 4 + 1));
278 // Convert Unicode String to Config String, e.g. "ABCD" => "0041004200430044"
280 for (; *TemName
!= L
'\0'; TemName
++) {
281 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemName
, 4);
286 // Convert Buffer to Hex String
288 TemBuffer
= ((UINT8
*) Buffer
) + BufferLen
- 1;
289 for (Index
= 0; Index
< BufferLen
; Index
++, TemBuffer
--) {
290 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
298 // Convert the uppercase to lowercase since <HexAf> is defined in lowercase format.
308 Retrieve the <ConfigBody> from String then output it.
310 This is a internal function.
312 @param String A sub string of a configuration string in
313 <MultiConfigAltResp> format.
314 @param ConfigBody Points to the output string. It's caller's
315 responsibility to free this buffer.
317 @retval EFI_INVALID_PARAMETER There is no form package in current hii database.
318 @retval EFI_OUT_OF_RESOURCES Not enough memory to finish this operation.
319 @retval EFI_SUCCESS All existing storage is exported.
324 IN EFI_STRING String
,
325 OUT EFI_STRING
*ConfigBody
332 if (String
== NULL
|| ConfigBody
== NULL
) {
333 return EFI_INVALID_PARAMETER
;
337 // The setting information should start OFFSET, not ALTCFG.
339 if (StrnCmp (String
, L
"&ALTCFG=", StrLen (L
"&ALTCFG=")) == 0) {
340 return EFI_INVALID_PARAMETER
;
343 TmpPtr
= StrStr (String
, L
"GUID=");
344 if (TmpPtr
== NULL
) {
346 // It is the last <ConfigResp> of the incoming configuration string.
348 Result
= AllocateCopyPool (StrSize (String
), String
);
349 if (Result
== NULL
) {
350 return EFI_OUT_OF_RESOURCES
;
352 *ConfigBody
= Result
;
357 Length
= TmpPtr
- String
;
358 Result
= AllocateCopyPool (Length
* sizeof (CHAR16
), String
);
359 if (Result
== NULL
) {
360 return EFI_OUT_OF_RESOURCES
;
363 *(Result
+ Length
- 1) = 0;
364 *ConfigBody
= Result
;
369 Append a string to a multi-string format.
371 This is a internal function.
373 @param MultiString String in <MultiConfigRequest>,
374 <MultiConfigAltResp>, or <MultiConfigResp>. On
375 input, the buffer length of this string is
376 MAX_STRING_LENGTH. On output, the buffer length
378 @param AppendString NULL-terminated Unicode string.
380 @retval EFI_INVALID_PARAMETER Any incoming parameter is invalid.
381 @retval EFI_SUCCESS AppendString is append to the end of MultiString
385 AppendToMultiString (
386 IN OUT EFI_STRING
*MultiString
,
387 IN EFI_STRING AppendString
390 UINTN AppendStringSize
;
391 UINTN MultiStringSize
;
393 if (MultiString
== NULL
|| *MultiString
== NULL
|| AppendString
== NULL
) {
394 return EFI_INVALID_PARAMETER
;
397 AppendStringSize
= StrSize (AppendString
);
398 MultiStringSize
= StrSize (*MultiString
);
401 // Enlarge the buffer each time when length exceeds MAX_STRING_LENGTH.
403 if (MultiStringSize
+ AppendStringSize
> MAX_STRING_LENGTH
||
404 MultiStringSize
> MAX_STRING_LENGTH
) {
405 *MultiString
= (EFI_STRING
) ReallocatePool (
407 MultiStringSize
+ AppendStringSize
,
408 (VOID
*) (*MultiString
)
410 ASSERT (*MultiString
!= NULL
);
413 // Append the incoming string
415 StrCat (*MultiString
, AppendString
);
422 Get the value of <Number> in <BlockConfig> format, i.e. the value of OFFSET
424 <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>
426 This is a internal function.
428 @param StringPtr String in <BlockConfig> format and points to the
429 first character of <Number>.
430 @param Number The output value. Caller takes the responsibility
432 @param Len Length of the <Number>, in characters.
434 @retval EFI_OUT_OF_RESOURCES Insufficient resources to store neccessary
436 @retval EFI_SUCCESS Value of <Number> is outputted in Number
442 IN EFI_STRING StringPtr
,
456 ASSERT (StringPtr
!= NULL
&& Number
!= NULL
&& Len
!= NULL
);
457 ASSERT (*StringPtr
!= L
'\0');
462 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
465 *Len
= StringPtr
- TmpPtr
;
468 Str
= (EFI_STRING
) AllocateZeroPool (Length
* sizeof (CHAR16
));
470 Status
= EFI_OUT_OF_RESOURCES
;
473 CopyMem (Str
, TmpPtr
, *Len
* sizeof (CHAR16
));
474 *(Str
+ *Len
) = L
'\0';
476 Length
= (Length
+ 1) / 2;
477 Buf
= (UINT8
*) AllocateZeroPool (Length
);
479 Status
= EFI_OUT_OF_RESOURCES
;
484 ZeroMem (TemStr
, sizeof (TemStr
));
485 for (Index
= 0; Index
< Length
; Index
++) {
486 TemStr
[0] = Str
[Length
- Index
- 1];
487 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
488 if ((Index
& 1) == 0) {
489 Buf
[Index
/2] = DigitUint8
;
491 Buf
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Buf
[Index
/2]);
496 Status
= EFI_SUCCESS
;
507 This function merges DefaultAltCfgResp string into AltCfgResp string for
508 the missing AltCfgId in AltCfgResq.
510 @param AltCfgResp Pointer to a null-terminated Unicode string in
511 <ConfigAltResp> format. The default value string
512 will be merged into it.
513 @param DefaultAltCfgResp Pointer to a null-terminated Unicode string in
514 <MultiConfigAltResp> format. The default value
515 string may contain more than one ConfigAltResp
516 string for the different varstore buffer.
518 @retval EFI_SUCCESS The merged string returns.
519 @retval EFI_INVALID_PARAMETER *AltCfgResp is to NULL.
524 IN OUT EFI_STRING
*AltCfgResp
,
525 IN EFI_STRING DefaultAltCfgResp
528 EFI_STRING StringPtrDefault
;
529 EFI_STRING StringPtrEnd
;
531 EFI_STRING StringPtr
;
532 EFI_STRING AltConfigHdr
;
534 UINTN SizeAltCfgResp
;
536 if (*AltCfgResp
== NULL
) {
537 return EFI_INVALID_PARAMETER
;
541 // Get the requestr ConfigHdr
544 StringPtr
= *AltCfgResp
;
547 // Find <ConfigHdr> GUID=...&NAME=...&PATH=...
549 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
550 return EFI_INVALID_PARAMETER
;
552 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&NAME=", StrLen (L
"&NAME=")) != 0) {
555 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&PATH=", StrLen (L
"&PATH=")) != 0) {
558 if (*StringPtr
== L
'\0') {
559 return EFI_INVALID_PARAMETER
;
561 StringPtr
+= StrLen (L
"&PATH=");
562 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
565 HeaderLength
= StringPtr
- *AltCfgResp
;
568 // Construct AltConfigHdr string "&<ConfigHdr>&ALTCFG=XXXX\0"
569 // |1| StrLen (ConfigHdr) | 8 | 4 | 1 |
571 AltConfigHdr
= AllocateZeroPool ((1 + HeaderLength
+ 8 + 4 + 1) * sizeof (CHAR16
));
572 if (AltConfigHdr
== NULL
) {
573 return EFI_OUT_OF_RESOURCES
;
575 StrCpy (AltConfigHdr
, L
"&");
576 StrnCat (AltConfigHdr
, *AltCfgResp
, HeaderLength
);
577 StrCat (AltConfigHdr
, L
"&ALTCFG=");
578 HeaderLength
= StrLen (AltConfigHdr
);
580 StringPtrDefault
= StrStr (DefaultAltCfgResp
, AltConfigHdr
);
581 while (StringPtrDefault
!= NULL
) {
585 StrnCat (AltConfigHdr
, StringPtrDefault
+ HeaderLength
, 4);
586 StringPtr
= StrStr (*AltCfgResp
, AltConfigHdr
);
589 // Append the found default value string to the input AltCfgResp
591 if (StringPtr
== NULL
) {
592 StringPtrEnd
= StrStr (StringPtrDefault
+ 1, L
"&GUID");
593 SizeAltCfgResp
= StrSize (*AltCfgResp
);
594 if (StringPtrEnd
== NULL
) {
596 // No more default string is found.
598 *AltCfgResp
= (EFI_STRING
) ReallocatePool (
600 SizeAltCfgResp
+ StrSize (StringPtrDefault
),
601 (VOID
*) (*AltCfgResp
)
603 if (*AltCfgResp
== NULL
) {
604 FreePool (AltConfigHdr
);
605 return EFI_OUT_OF_RESOURCES
;
607 StrCat (*AltCfgResp
, StringPtrDefault
);
610 TempChar
= *StringPtrEnd
;
611 *StringPtrEnd
= L
'\0';
612 *AltCfgResp
= (EFI_STRING
) ReallocatePool (
614 SizeAltCfgResp
+ StrSize (StringPtrDefault
),
615 (VOID
*) (*AltCfgResp
)
617 if (*AltCfgResp
== NULL
) {
618 FreePool (AltConfigHdr
);
619 return EFI_OUT_OF_RESOURCES
;
621 StrCat (*AltCfgResp
, StringPtrDefault
);
622 *StringPtrEnd
= TempChar
;
627 // Find next AltCfg String
629 *(AltConfigHdr
+ HeaderLength
) = L
'\0';
630 StringPtrDefault
= StrStr (StringPtrDefault
+ 1, AltConfigHdr
);
633 FreePool (AltConfigHdr
);
638 This function finds the matched DefaultName for the input DefaultId
640 @param DefaultIdArray Array stores the map table between DefaultId and DefaultName.
641 @param VarDefaultId Default Id
642 @param VarDefaultName Default Name string ID for the input default ID.
644 @retval EFI_SUCCESS The mapped default name string ID is found.
645 @retval EFI_NOT_FOUND The mapped default name string ID is not found.
649 IN IFR_DEFAULT_DATA
*DefaultIdArray
,
650 IN UINT16 VarDefaultId
,
651 OUT EFI_STRING_ID
*VarDefaultName
655 IFR_DEFAULT_DATA
*DefaultData
;
657 for (Link
= DefaultIdArray
->Entry
.ForwardLink
; Link
!= &DefaultIdArray
->Entry
; Link
= Link
->ForwardLink
) {
658 DefaultData
= BASE_CR (Link
, IFR_DEFAULT_DATA
, Entry
);
659 if (DefaultData
->DefaultId
== VarDefaultId
) {
660 *VarDefaultName
= DefaultData
->DefaultName
;
665 return EFI_NOT_FOUND
;
669 This function inserts new DefaultValueData into the BlockData DefaultValue array.
671 @param BlockData The BlockData is updated to add new default value.
672 @param DefaultValueData The DefaultValue is added.
677 IN IFR_BLOCK_DATA
*BlockData
,
678 IN IFR_DEFAULT_DATA
*DefaultValueData
682 IFR_DEFAULT_DATA
*DefaultValueArray
;
684 for (Link
= BlockData
->DefaultValueEntry
.ForwardLink
; Link
!= &BlockData
->DefaultValueEntry
; Link
= Link
->ForwardLink
) {
685 DefaultValueArray
= BASE_CR (Link
, IFR_DEFAULT_DATA
, Entry
);
686 if (DefaultValueArray
->DefaultId
== DefaultValueData
->DefaultId
) {
687 if (DefaultValueData
->OpCode
== EFI_IFR_DEFAULT_OP
) {
689 // Update the default value array in BlockData.
691 DefaultValueArray
->Value
= DefaultValueData
->Value
;
692 } else if (DefaultValueArray
->OpCode
!= EFI_IFR_DEFAULT_OP
) {
694 // Update the default value array in BlockData.
696 DefaultValueArray
->Value
= DefaultValueData
->Value
;
698 FreePool (DefaultValueData
);
700 } else if (DefaultValueArray
->DefaultId
> DefaultValueData
->DefaultId
) {
702 // Insert new default value data in the front of this default value array.
704 InsertTailList (Link
, &DefaultValueData
->Entry
);
710 // Insert new default value data in tail.
712 InsertTailList (Link
, &DefaultValueData
->Entry
);
717 This function inserts new BlockData into the block link
719 @param BlockLink The list entry points to block array.
720 @param BlockData The point to BlockData is added.
725 IN LIST_ENTRY
*BlockLink
,
726 IN IFR_BLOCK_DATA
**BlockData
730 IFR_BLOCK_DATA
*BlockArray
;
731 IFR_BLOCK_DATA
*BlockSingleData
;
733 BlockSingleData
= *BlockData
;
736 // Insert block data in its Offset and Width order.
738 for (Link
= BlockLink
->ForwardLink
; Link
!= BlockLink
; Link
= Link
->ForwardLink
) {
739 BlockArray
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
740 if (BlockArray
->Offset
== BlockSingleData
->Offset
) {
741 if (BlockArray
->Width
> BlockSingleData
->Width
) {
743 // Insert this block data in the front of block array
745 InsertTailList (Link
, &BlockSingleData
->Entry
);
749 if (BlockArray
->Width
== BlockSingleData
->Width
) {
751 // The same block array has been added.
753 FreePool (BlockSingleData
);
754 *BlockData
= BlockArray
;
757 } else if (BlockArray
->Offset
> BlockSingleData
->Offset
) {
759 // Insert new block data in the front of block array
761 InsertTailList (Link
, &BlockSingleData
->Entry
);
767 // Add new block data into the tail.
769 InsertTailList (Link
, &BlockSingleData
->Entry
);
774 This function checks VarOffset and VarWidth is in the block range.
776 @param RequestBlockArray The block array is to be checked.
777 @param VarOffset Offset of var to the structure
778 @param VarWidth Width of var.
780 @retval TRUE This Var is in the block range.
781 @retval FALSE This Var is not in the block range.
785 IN IFR_BLOCK_DATA
*RequestBlockArray
,
791 IFR_BLOCK_DATA
*BlockData
;
794 // No Request Block array, all vars are got.
796 if (RequestBlockArray
== NULL
) {
801 // Check the input var is in the request block range.
803 for (Link
= RequestBlockArray
->Entry
.ForwardLink
; Link
!= &RequestBlockArray
->Entry
; Link
= Link
->ForwardLink
) {
804 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
805 if ((VarOffset
>= BlockData
->Offset
) && ((VarOffset
+ VarWidth
) <= (BlockData
->Offset
+ BlockData
->Width
))) {
814 This function parses Form Package to get the block array and the default
815 value array according to the request ConfigHdr.
817 @param Package Pointer to the form package data.
818 @param PackageLength Length of the pacakge.
819 @param ConfigHdr Request string ConfigHdr. If it is NULL,
820 the first found varstore will be as ConfigHdr.
821 @param RequestBlockArray The block array is retrieved from the request string.
822 @param VarStorageData VarStorage structure contains the got block and default value.
823 @param PIfrDefaultIdArray Point to the got default id and default name array.
825 @retval EFI_SUCCESS The block array and the default value array are got.
826 @retval EFI_INVALID_PARAMETER The varstore defintion in the differnt form pacakges
828 @retval EFI_OUT_OF_RESOURCES No enough memory.
834 IN UINT32 PackageLength
,
835 IN EFI_STRING ConfigHdr
,
836 IN IFR_BLOCK_DATA
*RequestBlockArray
,
837 IN OUT IFR_VARSTORAGE_DATA
*VarStorageData
,
838 OUT IFR_DEFAULT_DATA
*DefaultIdArray
843 EFI_IFR_VARSTORE
*IfrVarStore
;
844 EFI_IFR_OP_HEADER
*IfrOpHdr
;
845 EFI_IFR_ONE_OF
*IfrOneOf
;
846 EFI_IFR_ONE_OF_OPTION
*IfrOneOfOption
;
847 EFI_IFR_DEFAULT
*IfrDefault
;
848 EFI_IFR_ORDERED_LIST
*IfrOrderedList
;
849 EFI_IFR_CHECKBOX
*IfrCheckBox
;
850 EFI_IFR_PASSWORD
*IfrPassword
;
851 EFI_IFR_STRING
*IfrString
;
852 IFR_DEFAULT_DATA
*DefaultData
;
853 IFR_BLOCK_DATA
*BlockData
;
854 CHAR16
*VarStoreName
;
857 EFI_STRING_ID VarDefaultName
;
863 BOOLEAN FirstOneOfOption
;
866 Status
= EFI_SUCCESS
;
873 FirstOneOfOption
= FALSE
;
876 // Go through the form package to parse OpCode one by one.
878 IfrOffset
= sizeof (EFI_HII_PACKAGE_HEADER
);
879 while (IfrOffset
< PackageLength
) {
880 IfrOpHdr
= (EFI_IFR_OP_HEADER
*) (Package
+ IfrOffset
);
882 switch (IfrOpHdr
->OpCode
) {
883 case EFI_IFR_VARSTORE_OP
:
885 // VarStore is found. Don't need to search any more.
887 if (VarStorageData
->Size
!= 0) {
892 // Get the requied varstore information
893 // Add varstore by Guid and Name in ConfigHdr
894 // Make sure Offset is in varstore size and varstoreid
896 IfrVarStore
= (EFI_IFR_VARSTORE
*) IfrOpHdr
;
897 VarStoreName
= AllocateZeroPool (AsciiStrSize ((CHAR8
*)IfrVarStore
->Name
) * sizeof (CHAR16
));
898 if (VarStoreName
== NULL
) {
899 Status
= EFI_OUT_OF_RESOURCES
;
902 AsciiStrToUnicodeStr ((CHAR8
*) IfrVarStore
->Name
, VarStoreName
);
904 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*) &IfrVarStore
->Guid
, 1, &GuidStr
);
905 GenerateSubStr (L
"NAME=", StrLen (VarStoreName
) * sizeof (CHAR16
), (VOID
*) VarStoreName
, 2, &NameStr
);
906 LengthString
= StrLen (GuidStr
);
907 LengthString
= LengthString
+ StrLen (NameStr
) + 1;
908 TempStr
= AllocateZeroPool (LengthString
* sizeof (CHAR16
));
909 if (TempStr
== NULL
) {
912 FreePool (VarStoreName
);
913 Status
= EFI_OUT_OF_RESOURCES
;
916 StrCpy (TempStr
, GuidStr
);
917 StrCat (TempStr
, NameStr
);
918 if (ConfigHdr
== NULL
|| StrnCmp (ConfigHdr
, TempStr
, StrLen (TempStr
)) == 0) {
920 // Find the matched VarStore
922 CopyGuid (&VarStorageData
->Guid
, (EFI_GUID
*) (VOID
*) &IfrVarStore
->Guid
);
923 VarStorageData
->VarStoreId
= IfrVarStore
->VarStoreId
;
924 VarStorageData
->Size
= IfrVarStore
->Size
;
925 VarStorageData
->Name
= VarStoreName
;
928 // No found, free the allocated memory
930 FreePool (VarStoreName
);
933 // Free alllocated temp string.
940 case EFI_IFR_DEFAULTSTORE_OP
:
942 // Add new the map between default id and default name.
944 DefaultData
= (IFR_DEFAULT_DATA
*) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
945 if (DefaultData
== NULL
) {
946 Status
= EFI_OUT_OF_RESOURCES
;
949 DefaultData
->DefaultId
= ((EFI_IFR_DEFAULTSTORE
*) IfrOpHdr
)->DefaultId
;
950 DefaultData
->DefaultName
= ((EFI_IFR_DEFAULTSTORE
*) IfrOpHdr
)->DefaultName
;
951 InsertTailList (&DefaultIdArray
->Entry
, &DefaultData
->Entry
);
955 case EFI_IFR_FORM_OP
:
956 case EFI_IFR_FORM_MAP_OP
:
958 // No matched varstore is found and directly return.
960 if (VarStorageData
->Size
== 0) {
961 Status
= EFI_SUCCESS
;
966 case EFI_IFR_ONE_OF_OP
:
967 case EFI_IFR_NUMERIC_OP
:
969 // Numeric and OneOf has the same opcode structure.
973 // Numeric and OneOf question is not in IFR Form. This IFR form is not valid.
975 if (VarStorageData
->Size
== 0) {
976 Status
= EFI_INVALID_PARAMETER
;
980 // Check whether this question is for the requested varstore.
982 IfrOneOf
= (EFI_IFR_ONE_OF
*) IfrOpHdr
;
983 if (IfrOneOf
->Question
.VarStoreId
!= VarStorageData
->VarStoreId
) {
988 // Get Offset/Width by Question header and OneOf Flags
990 VarOffset
= IfrOneOf
->Question
.VarStoreInfo
.VarOffset
;
991 VarWidth
= (UINT16
) (1 << (IfrOneOf
->Flags
& EFI_IFR_NUMERIC_SIZE
));
993 // Check whether this question is in requested block array.
995 if (!BlockArrayCheck (RequestBlockArray
, VarOffset
, VarWidth
)) {
997 // This question is not in the requested string. Skip it.
1003 // Check this var question is in the var storage
1005 if ((VarOffset
+ VarWidth
) > VarStorageData
->Size
) {
1006 Status
= EFI_INVALID_PARAMETER
;
1013 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
1014 if (BlockData
== NULL
) {
1015 Status
= EFI_OUT_OF_RESOURCES
;
1018 BlockData
->Offset
= VarOffset
;
1019 BlockData
->Width
= VarWidth
;
1020 BlockData
->QuestionId
= IfrOneOf
->Question
.QuestionId
;
1021 BlockData
->OpCode
= IfrOpHdr
->OpCode
;
1022 BlockData
->Scope
= IfrOpHdr
->Scope
;
1023 InitializeListHead (&BlockData
->DefaultValueEntry
);
1025 // Add Block Data into VarStorageData BlockEntry
1027 InsertBlockData (&VarStorageData
->BlockEntry
, &BlockData
);
1029 if (IfrOpHdr
->OpCode
== EFI_IFR_ONE_OF_OP
) {
1031 // Set this flag to TRUE for the first oneof option.
1033 FirstOneOfOption
= TRUE
;
1034 } else if (IfrOpHdr
->OpCode
== EFI_IFR_NUMERIC_OP
) {
1036 // Numeric minimum value will be used as default value when no default is specified.
1040 // Set standard ID and Get DefaultName String ID
1042 VarDefaultId
= EFI_HII_DEFAULT_CLASS_STANDARD
;
1043 Status
= FindDefaultName (DefaultIdArray
, VarDefaultId
, &VarDefaultName
);
1044 if (EFI_ERROR (Status
)) {
1048 // Prepare new DefaultValue
1050 DefaultData
= (IFR_DEFAULT_DATA
*) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
1051 if (DefaultData
== NULL
) {
1052 Status
= EFI_OUT_OF_RESOURCES
;
1055 DefaultData
->OpCode
= IfrOpHdr
->OpCode
;
1056 DefaultData
->DefaultId
= VarDefaultId
;
1057 DefaultData
->DefaultName
= VarDefaultName
;
1059 switch (IfrOneOf
->Flags
& EFI_IFR_NUMERIC_SIZE
) {
1060 case EFI_IFR_NUMERIC_SIZE_1
:
1061 DefaultData
->Value
= (UINT64
) IfrOneOf
->data
.u8
.MinValue
;
1064 case EFI_IFR_NUMERIC_SIZE_2
:
1065 CopyMem (&DefaultData
->Value
, &IfrOneOf
->data
.u16
.MinValue
, sizeof (UINT16
));
1068 case EFI_IFR_NUMERIC_SIZE_4
:
1069 CopyMem (&DefaultData
->Value
, &IfrOneOf
->data
.u32
.MinValue
, sizeof (UINT32
));
1072 case EFI_IFR_NUMERIC_SIZE_8
:
1073 CopyMem (&DefaultData
->Value
, &IfrOneOf
->data
.u64
.MinValue
, sizeof (UINT64
));
1077 // Add DefaultValue into current BlockData
1079 InsertDefaultValue (BlockData
, DefaultData
);
1083 case EFI_IFR_ORDERED_LIST_OP
:
1085 // offset by question header
1086 // width by EFI_IFR_ORDERED_LIST MaxContainers * OneofOption Type
1087 // no default value and default id, how to define its default value?
1091 // OrderedList question is not in IFR Form. This IFR form is not valid.
1093 if (VarStorageData
->Size
== 0) {
1094 Status
= EFI_INVALID_PARAMETER
;
1098 // Check whether this question is for the requested varstore.
1100 IfrOrderedList
= (EFI_IFR_ORDERED_LIST
*) IfrOpHdr
;
1101 if (IfrOrderedList
->Question
.VarStoreId
!= VarStorageData
->VarStoreId
) {
1107 // Get Offset/Width by Question header and OneOf Flags
1109 VarOffset
= IfrOrderedList
->Question
.VarStoreInfo
.VarOffset
;
1110 VarWidth
= IfrOrderedList
->MaxContainers
;
1115 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
1116 if (BlockData
== NULL
) {
1117 Status
= EFI_OUT_OF_RESOURCES
;
1120 BlockData
->Offset
= VarOffset
;
1121 BlockData
->Width
= VarWidth
;
1122 BlockData
->QuestionId
= IfrOrderedList
->Question
.QuestionId
;
1123 BlockData
->OpCode
= IfrOpHdr
->OpCode
;
1124 BlockData
->Scope
= IfrOpHdr
->Scope
;
1125 InitializeListHead (&BlockData
->DefaultValueEntry
);
1128 case EFI_IFR_CHECKBOX_OP
:
1130 // EFI_IFR_DEFAULT_OP
1131 // offset by question header
1132 // width is 1 sizeof (BOOLEAN)
1133 // default id by CheckBox Flags if CheckBox flags (Default or Mau) is set, the default value is 1 to be set.
1134 // value by DefaultOption
1135 // default id by DeaultOption DefaultId can override CheckBox Flags and Default value.
1139 // CheckBox question is not in IFR Form. This IFR form is not valid.
1141 if (VarStorageData
->Size
== 0) {
1142 Status
= EFI_INVALID_PARAMETER
;
1146 // Check whether this question is for the requested varstore.
1148 IfrCheckBox
= (EFI_IFR_CHECKBOX
*) IfrOpHdr
;
1149 if (IfrCheckBox
->Question
.VarStoreId
!= VarStorageData
->VarStoreId
) {
1154 // Get Offset/Width by Question header and OneOf Flags
1156 VarOffset
= IfrCheckBox
->Question
.VarStoreInfo
.VarOffset
;
1157 VarWidth
= (UINT16
) sizeof (BOOLEAN
);
1160 // Check whether this question is in requested block array.
1162 if (!BlockArrayCheck (RequestBlockArray
, VarOffset
, VarWidth
)) {
1164 // This question is not in the requested string. Skip it.
1170 // Check this var question is in the var storage
1172 if ((VarOffset
+ VarWidth
) > VarStorageData
->Size
) {
1173 Status
= EFI_INVALID_PARAMETER
;
1180 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
1181 if (BlockData
== NULL
) {
1182 Status
= EFI_OUT_OF_RESOURCES
;
1185 BlockData
->Offset
= VarOffset
;
1186 BlockData
->Width
= VarWidth
;
1187 BlockData
->QuestionId
= IfrCheckBox
->Question
.QuestionId
;
1188 BlockData
->OpCode
= IfrOpHdr
->OpCode
;
1189 BlockData
->Scope
= IfrOpHdr
->Scope
;
1190 InitializeListHead (&BlockData
->DefaultValueEntry
);
1192 // Add Block Data into VarStorageData BlockEntry
1194 InsertBlockData (&VarStorageData
->BlockEntry
, &BlockData
);
1197 // Add default value by CheckBox Flags
1199 if ((IfrCheckBox
->Flags
& EFI_IFR_CHECKBOX_DEFAULT
) == EFI_IFR_CHECKBOX_DEFAULT
) {
1201 // Set standard ID to Manufacture ID and Get DefaultName String ID
1203 VarDefaultId
= EFI_HII_DEFAULT_CLASS_STANDARD
;
1204 Status
= FindDefaultName (DefaultIdArray
, VarDefaultId
, &VarDefaultName
);
1205 if (EFI_ERROR (Status
)) {
1209 // Prepare new DefaultValue
1211 DefaultData
= (IFR_DEFAULT_DATA
*) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
1212 if (DefaultData
== NULL
) {
1213 Status
= EFI_OUT_OF_RESOURCES
;
1216 DefaultData
->OpCode
= IfrOpHdr
->OpCode
;
1217 DefaultData
->DefaultId
= VarDefaultId
;
1218 DefaultData
->DefaultName
= VarDefaultName
;
1219 DefaultData
->Value
= 1;
1221 // Add DefaultValue into current BlockData
1223 InsertDefaultValue (BlockData
, DefaultData
);
1226 if ((IfrCheckBox
->Flags
& EFI_IFR_CHECKBOX_DEFAULT_MFG
) == EFI_IFR_CHECKBOX_DEFAULT_MFG
) {
1228 // Set standard ID to Manufacture ID and Get DefaultName String ID
1230 VarDefaultId
= EFI_HII_DEFAULT_CLASS_MANUFACTURING
;
1231 Status
= FindDefaultName (DefaultIdArray
, VarDefaultId
, &VarDefaultName
);
1232 if (EFI_ERROR (Status
)) {
1236 // Prepare new DefaultValue
1238 DefaultData
= (IFR_DEFAULT_DATA
*) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
1239 if (DefaultData
== NULL
) {
1240 Status
= EFI_OUT_OF_RESOURCES
;
1243 DefaultData
->OpCode
= IfrOpHdr
->OpCode
;
1244 DefaultData
->DefaultId
= VarDefaultId
;
1245 DefaultData
->DefaultName
= VarDefaultName
;
1246 DefaultData
->Value
= 1;
1248 // Add DefaultValue into current BlockData
1250 InsertDefaultValue (BlockData
, DefaultData
);
1254 case EFI_IFR_STRING_OP
:
1256 // offset by question header
1257 // width MaxSize * sizeof (CHAR16)
1258 // no default value, only block array
1262 // String question is not in IFR Form. This IFR form is not valid.
1264 if (VarStorageData
->Size
== 0) {
1265 Status
= EFI_INVALID_PARAMETER
;
1269 // Check whether this question is for the requested varstore.
1271 IfrString
= (EFI_IFR_STRING
*) IfrOpHdr
;
1272 if (IfrString
->Question
.VarStoreId
!= VarStorageData
->VarStoreId
) {
1277 // Get Offset/Width by Question header and OneOf Flags
1279 VarOffset
= IfrString
->Question
.VarStoreInfo
.VarOffset
;
1280 VarWidth
= (UINT16
) (IfrString
->MaxSize
* sizeof (UINT16
));
1283 // Check whether this question is in requested block array.
1285 if (!BlockArrayCheck (RequestBlockArray
, VarOffset
, VarWidth
)) {
1287 // This question is not in the requested string. Skip it.
1293 // Check this var question is in the var storage
1295 if ((VarOffset
+ VarWidth
) > VarStorageData
->Size
) {
1296 Status
= EFI_INVALID_PARAMETER
;
1303 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
1304 if (BlockData
== NULL
) {
1305 Status
= EFI_OUT_OF_RESOURCES
;
1308 BlockData
->Offset
= VarOffset
;
1309 BlockData
->Width
= VarWidth
;
1310 BlockData
->QuestionId
= IfrString
->Question
.QuestionId
;
1311 BlockData
->OpCode
= IfrOpHdr
->OpCode
;
1312 InitializeListHead (&BlockData
->DefaultValueEntry
);
1315 // Add Block Data into VarStorageData BlockEntry
1317 InsertBlockData (&VarStorageData
->BlockEntry
, &BlockData
);
1320 // No default value for string.
1325 case EFI_IFR_PASSWORD_OP
:
1327 // offset by question header
1328 // width MaxSize * sizeof (CHAR16)
1329 // no default value, only block array
1333 // Password question is not in IFR Form. This IFR form is not valid.
1335 if (VarStorageData
->Size
== 0) {
1336 Status
= EFI_INVALID_PARAMETER
;
1340 // Check whether this question is for the requested varstore.
1342 IfrPassword
= (EFI_IFR_PASSWORD
*) IfrOpHdr
;
1343 if (IfrPassword
->Question
.VarStoreId
!= VarStorageData
->VarStoreId
) {
1348 // Get Offset/Width by Question header and OneOf Flags
1350 VarOffset
= IfrPassword
->Question
.VarStoreInfo
.VarOffset
;
1351 VarWidth
= (UINT16
) (IfrPassword
->MaxSize
* sizeof (UINT16
));
1354 // Check whether this question is in requested block array.
1356 if (!BlockArrayCheck (RequestBlockArray
, VarOffset
, VarWidth
)) {
1358 // This question is not in the requested string. Skip it.
1364 // Check this var question is in the var storage
1366 if ((VarOffset
+ VarWidth
) > VarStorageData
->Size
) {
1367 Status
= EFI_INVALID_PARAMETER
;
1374 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
1375 if (BlockData
== NULL
) {
1376 Status
= EFI_OUT_OF_RESOURCES
;
1379 BlockData
->Offset
= VarOffset
;
1380 BlockData
->Width
= VarWidth
;
1381 BlockData
->QuestionId
= IfrPassword
->Question
.QuestionId
;
1382 BlockData
->OpCode
= IfrOpHdr
->OpCode
;
1383 InitializeListHead (&BlockData
->DefaultValueEntry
);
1386 // Add Block Data into VarStorageData BlockEntry
1388 InsertBlockData (&VarStorageData
->BlockEntry
, &BlockData
);
1391 // No default value for string.
1396 case EFI_IFR_ONE_OF_OPTION_OP
:
1398 // No matched block data is ignored.
1400 if (BlockData
== NULL
|| BlockData
->Scope
== 0) {
1404 IfrOneOfOption
= (EFI_IFR_ONE_OF_OPTION
*) IfrOpHdr
;
1405 if (BlockData
->OpCode
== EFI_IFR_ORDERED_LIST_OP
) {
1407 // Get ordered list option data type.
1409 if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_8
|| IfrOneOfOption
->Type
== EFI_IFR_TYPE_BOOLEAN
) {
1411 } else if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_16
) {
1413 } else if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_32
) {
1415 } else if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_64
) {
1419 // Invalid ordered list option data type.
1421 Status
= EFI_INVALID_PARAMETER
;
1422 FreePool (BlockData
);
1427 // Calculate Ordered list QuestionId width.
1429 BlockData
->Width
= (UINT16
) (BlockData
->Width
* VarWidth
);
1431 // Check whether this question is in requested block array.
1433 if (!BlockArrayCheck (RequestBlockArray
, BlockData
->Offset
, BlockData
->Width
)) {
1435 // This question is not in the requested string. Skip it.
1437 FreePool (BlockData
);
1442 // Check this var question is in the var storage
1444 if ((BlockData
->Offset
+ BlockData
->Width
) > VarStorageData
->Size
) {
1445 Status
= EFI_INVALID_PARAMETER
;
1446 FreePool (BlockData
);
1450 // Add Block Data into VarStorageData BlockEntry
1452 InsertBlockData (&VarStorageData
->BlockEntry
, &BlockData
);
1454 // No default data for OrderedList.
1460 if (((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT
) == EFI_IFR_OPTION_DEFAULT
) ||
1461 (BlockData
->OpCode
== EFI_IFR_ONE_OF_OP
&& FirstOneOfOption
)) {
1463 // This flag is used to specify whether this option is the first. Set it to FALSE for the following options.
1464 // The first oneof option value will be used as default value when no default value is specified.
1466 FirstOneOfOption
= FALSE
;
1468 // Set standard ID to Manufacture ID and Get DefaultName String ID
1470 VarDefaultId
= EFI_HII_DEFAULT_CLASS_STANDARD
;
1471 Status
= FindDefaultName (DefaultIdArray
, VarDefaultId
, &VarDefaultName
);
1472 if (EFI_ERROR (Status
)) {
1476 // Prepare new DefaultValue
1478 DefaultData
= (IFR_DEFAULT_DATA
*) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
1479 if (DefaultData
== NULL
) {
1480 Status
= EFI_OUT_OF_RESOURCES
;
1483 DefaultData
->OpCode
= IfrOpHdr
->OpCode
;
1484 DefaultData
->DefaultId
= VarDefaultId
;
1485 DefaultData
->DefaultName
= VarDefaultName
;
1486 DefaultData
->Value
= IfrOneOfOption
->Value
.u64
;
1488 // Add DefaultValue into current BlockData
1490 InsertDefaultValue (BlockData
, DefaultData
);
1493 if ((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT_MFG
) == EFI_IFR_OPTION_DEFAULT_MFG
) {
1495 // Set default ID to Manufacture ID and Get DefaultName String ID
1497 VarDefaultId
= EFI_HII_DEFAULT_CLASS_MANUFACTURING
;
1498 Status
= FindDefaultName (DefaultIdArray
, VarDefaultId
, &VarDefaultName
);
1499 if (EFI_ERROR (Status
)) {
1503 // Prepare new DefaultValue
1505 DefaultData
= (IFR_DEFAULT_DATA
*) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
1506 if (DefaultData
== NULL
) {
1507 Status
= EFI_OUT_OF_RESOURCES
;
1510 DefaultData
->OpCode
= IfrOpHdr
->OpCode
;
1511 DefaultData
->DefaultId
= VarDefaultId
;
1512 DefaultData
->DefaultName
= VarDefaultName
;
1513 DefaultData
->Value
= IfrOneOfOption
->Value
.u64
;
1515 // Add DefaultValue into current BlockData
1517 InsertDefaultValue (BlockData
, DefaultData
);
1521 case EFI_IFR_DEFAULT_OP
:
1523 // Update Current BlockData to the default value.
1525 if (BlockData
== NULL
|| BlockData
->Scope
== 0) {
1527 // No matched block data is ignored.
1532 if (BlockData
->OpCode
== EFI_IFR_ORDERED_LIST_OP
) {
1534 // OrderedList Opcode is no default value.
1539 // Get the DefaultId and DefaultName String ID
1541 IfrDefault
= (EFI_IFR_DEFAULT
*) IfrOpHdr
;
1542 VarDefaultId
= IfrDefault
->DefaultId
;
1543 Status
= FindDefaultName (DefaultIdArray
, VarDefaultId
, &VarDefaultName
);
1544 if (EFI_ERROR (Status
)) {
1548 // Prepare new DefaultValue
1550 DefaultData
= (IFR_DEFAULT_DATA
*) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
1551 if (DefaultData
== NULL
) {
1552 Status
= EFI_OUT_OF_RESOURCES
;
1555 DefaultData
->OpCode
= IfrOpHdr
->OpCode
;
1556 DefaultData
->DefaultId
= VarDefaultId
;
1557 DefaultData
->DefaultName
= VarDefaultName
;
1558 DefaultData
->Value
= IfrDefault
->Value
.u64
;
1560 // Add DefaultValue into current BlockData
1562 InsertDefaultValue (BlockData
, DefaultData
);
1564 case EFI_IFR_END_OP
:
1566 // End Opcode is for Var question.
1568 if (BlockData
!= NULL
&& BlockData
->Scope
> 0) {
1573 if (BlockData
!= NULL
&& BlockData
->Scope
> 0) {
1574 BlockData
->Scope
= (UINT8
) (BlockData
->Scope
+ IfrOpHdr
->Scope
);
1579 IfrOffset
+= IfrOpHdr
->Length
;
1587 This function gets the full request string and full default value string by
1588 parsing IFR data in HII form packages.
1590 When Request points to NULL string, the request string and default value string
1591 for each varstore in form package will return.
1593 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
1594 @param DevicePath Device Path which Hii Config Access Protocol is registered.
1595 @param Request Pointer to a null-terminated Unicode string in
1596 <ConfigRequest> format. When it doesn't contain
1597 any RequestElement, it will be updated to return
1598 the full RequestElement retrieved from IFR data.
1599 If it points to NULL, the request string for the first
1600 varstore in form package will be merged into a
1601 <MultiConfigRequest> format string and return.
1602 @param AltCfgResp Pointer to a null-terminated Unicode string in
1603 <ConfigAltResp> format. When the pointer is to NULL,
1604 the full default value string retrieved from IFR data
1605 will return. When the pinter is to a string, the
1606 full default value string retrieved from IFR data
1607 will be merged into the input string and return.
1608 When Request points to NULL, the default value string
1609 for each varstore in form package will be merged into
1610 a <MultiConfigAltResp> format string and return.
1611 @param PointerProgress Optional parameter, it can be be NULL.
1612 When it is not NULL, if Request is NULL, it returns NULL.
1613 On return, points to a character in the Request
1614 string. Points to the string's null terminator if
1615 request was successful. Points to the most recent
1616 & before the first failing name / value pair (or
1617 the beginning of the string if the failure is in
1618 the first name / value pair) if the request was
1620 @retval EFI_SUCCESS The Results string is set to the full request string.
1621 And AltCfgResp contains all default value string.
1622 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
1623 @retval EFI_NOT_FOUND The varstore (Guid and Name) in Request string
1624 can't be found in Form package.
1625 @retval EFI_NOT_FOUND HiiPackage can't be got on the input HiiHandle.
1626 @retval EFI_INVALID_PARAMETER Request points to NULL.
1631 GetFullStringFromHiiFormPackages (
1632 IN HII_DATABASE_RECORD
*DataBaseRecord
,
1633 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
1634 IN OUT EFI_STRING
*Request
,
1635 IN OUT EFI_STRING
*AltCfgResp
,
1636 OUT EFI_STRING
*PointerProgress OPTIONAL
1640 UINT8
*HiiFormPackage
;
1643 IFR_BLOCK_DATA
*RequestBlockArray
;
1644 IFR_BLOCK_DATA
*BlockData
;
1645 IFR_BLOCK_DATA
*NextBlockData
;
1646 IFR_DEFAULT_DATA
*DefaultValueData
;
1647 IFR_DEFAULT_DATA
*DefaultId
;
1648 IFR_DEFAULT_DATA
*DefaultIdArray
;
1649 IFR_VARSTORAGE_DATA
*VarStorageData
;
1650 EFI_STRING DefaultAltCfgResp
;
1651 EFI_STRING FullConfigRequest
;
1652 EFI_STRING ConfigHdr
;
1656 EFI_STRING StringPtr
;
1657 EFI_STRING Progress
;
1663 LIST_ENTRY
*LinkData
;
1664 LIST_ENTRY
*LinkDefault
;
1667 if (DataBaseRecord
== NULL
|| DevicePath
== NULL
|| Request
== NULL
|| AltCfgResp
== NULL
) {
1668 return EFI_INVALID_PARAMETER
;
1672 // Initialize the local variables.
1674 RequestBlockArray
= NULL
;
1675 DefaultIdArray
= NULL
;
1676 VarStorageData
= NULL
;
1677 DefaultAltCfgResp
= NULL
;
1678 FullConfigRequest
= NULL
;
1683 HiiFormPackage
= NULL
;
1687 Progress
= *Request
;
1690 // 0. Get Hii Form Package by HiiHandle
1692 Status
= ExportFormPackages (
1694 DataBaseRecord
->Handle
,
1695 DataBaseRecord
->PackageList
,
1701 if (EFI_ERROR (Status
)) {
1705 HiiFormPackage
= AllocatePool (ResultSize
);
1706 if (HiiFormPackage
== NULL
) {
1707 Status
= EFI_OUT_OF_RESOURCES
;
1712 // Get HiiFormPackage by HiiHandle
1714 PackageSize
= ResultSize
;
1716 Status
= ExportFormPackages (
1718 DataBaseRecord
->Handle
,
1719 DataBaseRecord
->PackageList
,
1725 if (EFI_ERROR (Status
)) {
1730 // 1. Get the request block array by Request String when Request string containts the block array.
1733 if (*Request
!= NULL
) {
1734 StringPtr
= *Request
;
1738 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
1739 Status
= EFI_INVALID_PARAMETER
;
1742 StringPtr
+= StrLen (L
"GUID=");
1743 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&NAME=", StrLen (L
"&NAME=")) != 0) {
1746 if (*StringPtr
== L
'\0') {
1747 Status
= EFI_INVALID_PARAMETER
;
1750 StringPtr
+= StrLen (L
"&NAME=");
1751 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&PATH=", StrLen (L
"&PATH=")) != 0) {
1754 if (*StringPtr
== L
'\0') {
1755 Status
= EFI_INVALID_PARAMETER
;
1758 StringPtr
+= StrLen (L
"&PATH=");
1759 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
1763 // Check the following string &OFFSET=
1765 if (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) != 0) {
1766 Progress
= StringPtr
;
1767 Status
= EFI_INVALID_PARAMETER
;
1769 } else if (*StringPtr
== L
'\0') {
1771 // No request block is found.
1776 if (StringPtr
!= NULL
) {
1778 // Init RequestBlockArray
1780 RequestBlockArray
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
1781 if (RequestBlockArray
== NULL
) {
1782 Status
= EFI_OUT_OF_RESOURCES
;
1785 InitializeListHead (&RequestBlockArray
->Entry
);
1788 // Get the request Block array from the request string
1793 // Parse each <RequestElement> if exists
1794 // Only <BlockName> format is supported by this help function.
1795 // <BlockName> ::= &'OFFSET='<Number>&'WIDTH='<Number>
1797 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) == 0) {
1799 // Skip the OFFSET string
1801 Progress
= StringPtr
;
1802 StringPtr
+= StrLen (L
"&OFFSET=");
1806 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
1807 if (EFI_ERROR (Status
)) {
1814 (((Length
+ 1) / 2) < sizeof (UINT16
)) ? ((Length
+ 1) / 2) : sizeof (UINT16
)
1816 FreePool (TmpBuffer
);
1818 StringPtr
+= Length
;
1819 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
1820 Status
= EFI_INVALID_PARAMETER
;
1823 StringPtr
+= StrLen (L
"&WIDTH=");
1828 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
1829 if (EFI_ERROR (Status
)) {
1836 (((Length
+ 1) / 2) < sizeof (UINT16
)) ? ((Length
+ 1) / 2) : sizeof (UINT16
)
1838 FreePool (TmpBuffer
);
1840 StringPtr
+= Length
;
1841 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
1842 Status
= EFI_INVALID_PARAMETER
;
1849 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
1850 if (BlockData
== NULL
) {
1851 Status
= EFI_OUT_OF_RESOURCES
;
1854 BlockData
->Offset
= Offset
;
1855 BlockData
->Width
= Width
;
1856 InsertBlockData (&RequestBlockArray
->Entry
, &BlockData
);
1859 // Skip &VALUE string if &VALUE does exists.
1861 if (StrnCmp (StringPtr
, L
"&VALUE=", StrLen (L
"&VALUE=")) == 0) {
1862 StringPtr
+= StrLen (L
"&VALUE=");
1867 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
1868 if (EFI_ERROR (Status
)) {
1869 Status
= EFI_INVALID_PARAMETER
;
1873 StringPtr
+= Length
;
1874 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
1875 Status
= EFI_INVALID_PARAMETER
;
1880 // If '\0', parsing is finished.
1882 if (*StringPtr
== 0) {
1888 // Merge the requested block data.
1890 Link
= RequestBlockArray
->Entry
.ForwardLink
;
1891 while ((Link
!= &RequestBlockArray
->Entry
) && (Link
->ForwardLink
!= &RequestBlockArray
->Entry
)) {
1892 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
1893 NextBlockData
= BASE_CR (Link
->ForwardLink
, IFR_BLOCK_DATA
, Entry
);
1894 if ((NextBlockData
->Offset
>= BlockData
->Offset
) && (NextBlockData
->Offset
<= (BlockData
->Offset
+ BlockData
->Width
))) {
1895 if ((NextBlockData
->Offset
+ NextBlockData
->Width
) > (BlockData
->Offset
+ BlockData
->Width
)) {
1896 BlockData
->Width
= (UINT16
) (NextBlockData
->Offset
+ NextBlockData
->Width
- BlockData
->Offset
);
1898 RemoveEntryList (Link
->ForwardLink
);
1899 FreePool (NextBlockData
);
1902 Link
= Link
->ForwardLink
;
1907 // 2. Parse FormPackage to get BlockArray and DefaultId Array for the request BlockArray.
1911 // Initialize DefaultIdArray to store the map between DeaultId and DefaultName
1913 DefaultIdArray
= (IFR_DEFAULT_DATA
*) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
1914 if (DefaultIdArray
== NULL
) {
1915 Status
= EFI_OUT_OF_RESOURCES
;
1918 InitializeListHead (&DefaultIdArray
->Entry
);
1921 // Initialize VarStorageData to store the var store Block and Default value information.
1923 VarStorageData
= (IFR_VARSTORAGE_DATA
*) AllocateZeroPool (sizeof (IFR_VARSTORAGE_DATA
));
1924 if (VarStorageData
== NULL
) {
1925 Status
= EFI_OUT_OF_RESOURCES
;
1928 InitializeListHead (&VarStorageData
->Entry
);
1929 InitializeListHead (&VarStorageData
->BlockEntry
);
1932 // Parse the opcode in form pacakge to get the default setting.
1934 Status
= ParseIfrData (HiiFormPackage
, (UINT32
) PackageSize
, *Request
, RequestBlockArray
, VarStorageData
, DefaultIdArray
);
1935 if (EFI_ERROR (Status
)) {
1940 // No requested varstore in IFR data and directly return
1942 if (VarStorageData
->Size
== 0) {
1943 Status
= EFI_SUCCESS
;
1948 // 3. Construct Request Element (Block Name) for 2.1 and 2.2 case.
1952 // Construct <ConfigHdr> : "GUID=...&NAME=...&PATH=..." by VarStorageData Guid, Name and DriverHandle
1954 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*) &VarStorageData
->Guid
, 1, &GuidStr
);
1955 GenerateSubStr (L
"NAME=", StrLen (VarStorageData
->Name
) * sizeof (CHAR16
), (VOID
*) VarStorageData
->Name
, 2, &NameStr
);
1958 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) DevicePath
),
1959 (VOID
*) DevicePath
,
1963 Length
= StrLen (GuidStr
);
1964 Length
= Length
+ StrLen (NameStr
);
1965 Length
= Length
+ StrLen (PathStr
) + 1;
1966 ConfigHdr
= AllocateZeroPool (Length
* sizeof (CHAR16
));
1967 if (ConfigHdr
== NULL
) {
1968 Status
= EFI_OUT_OF_RESOURCES
;
1971 StrCpy (ConfigHdr
, GuidStr
);
1972 StrCat (ConfigHdr
, NameStr
);
1973 StrCat (ConfigHdr
, PathStr
);
1976 // Remove the last character L'&'
1978 *(ConfigHdr
+ StrLen (ConfigHdr
) - 1) = L
'\0';
1980 if (RequestBlockArray
== NULL
) {
1982 // Append VarStorageData BlockEntry into *Request string
1983 // Now support only one varstore in a form package.
1987 // Go through all VarStorageData Entry and get BlockEntry for each one for the multiple varstore in a single form package
1988 // Then construct them all to return MultiRequest string : ConfigHdr BlockConfig
1992 // Compute the length of the entire request starting with <ConfigHdr> and a
1996 Length
= StrLen (ConfigHdr
) + 1;
1998 for (Link
= VarStorageData
->BlockEntry
.ForwardLink
; Link
!= &VarStorageData
->BlockEntry
; Link
= Link
->ForwardLink
) {
2000 // Add <BlockName> length for each Offset/Width pair
2002 // <BlockName> ::= &OFFSET=1234&WIDTH=1234
2003 // | 8 | 4 | 7 | 4 |
2006 Length
= Length
+ (8 + 4 + 7 + 4);
2010 // No any request block data is found. The request string can't be constructed.
2013 Status
= EFI_SUCCESS
;
2018 // Allocate buffer for the entire <ConfigRequest>
2020 FullConfigRequest
= AllocateZeroPool (Length
* sizeof (CHAR16
));
2021 if (FullConfigRequest
== NULL
) {
2022 Status
= EFI_OUT_OF_RESOURCES
;
2025 StringPtr
= FullConfigRequest
;
2028 // Start with <ConfigHdr>
2030 StrCpy (StringPtr
, ConfigHdr
);
2031 StringPtr
+= StrLen (StringPtr
);
2034 // Loop through all the Offset/Width pairs and append them to ConfigRequest
2036 for (Link
= VarStorageData
->BlockEntry
.ForwardLink
; Link
!= &VarStorageData
->BlockEntry
; Link
= Link
->ForwardLink
) {
2037 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
2039 // Append &OFFSET=XXXX&WIDTH=YYYY\0
2043 (8 + 4 + 7 + 4 + 1) * sizeof (CHAR16
),
2044 L
"&OFFSET=%04X&WIDTH=%04X",
2048 StringPtr
+= StrLen (StringPtr
);
2051 // Set to the got full request string.
2053 HiiToLower (FullConfigRequest
);
2054 if (*Request
!= NULL
) {
2055 FreePool (*Request
);
2057 *Request
= FullConfigRequest
;
2061 // 4. Construct Default Value string in AltResp according to request element.
2062 // Go through all VarStorageData Entry and get the DefaultId array for each one
2063 // Then construct them all to : ConfigHdr AltConfigHdr ConfigBody AltConfigHdr ConfigBody
2067 // Add length for <ConfigHdr> + '\0'
2069 Length
= StrLen (ConfigHdr
) + 1;
2071 for (Link
= DefaultIdArray
->Entry
.ForwardLink
; Link
!= &DefaultIdArray
->Entry
; Link
= Link
->ForwardLink
) {
2072 DefaultId
= BASE_CR (Link
, IFR_DEFAULT_DATA
, Entry
);
2074 // Add length for "&<ConfigHdr>&ALTCFG=XXXX"
2075 // |1| StrLen (ConfigHdr) | 8 | 4 |
2077 Length
+= (1 + StrLen (ConfigHdr
) + 8 + 4);
2079 for (LinkData
= VarStorageData
->BlockEntry
.ForwardLink
; LinkData
!= &VarStorageData
->BlockEntry
; LinkData
= LinkData
->ForwardLink
) {
2080 BlockData
= BASE_CR (LinkData
, IFR_BLOCK_DATA
, Entry
);
2081 for (LinkDefault
= BlockData
->DefaultValueEntry
.ForwardLink
; LinkDefault
!= &BlockData
->DefaultValueEntry
; LinkDefault
= LinkDefault
->ForwardLink
) {
2082 DefaultValueData
= BASE_CR (LinkDefault
, IFR_DEFAULT_DATA
, Entry
);
2083 if (DefaultValueData
->DefaultId
== DefaultId
->DefaultId
) {
2085 // Add length for "&OFFSET=XXXX&WIDTH=YYYY&VALUE=zzzzzzzzzzzz"
2086 // | 8 | 4 | 7 | 4 | 7 | Width * 2 |
2088 Length
+= (8 + 4 + 7 + 4 + 7 + BlockData
->Width
* 2);
2096 // No default value is found. The default string doesn't exist.
2099 Status
= EFI_SUCCESS
;
2104 // Allocate buffer for the entire <DefaultAltCfgResp>
2106 DefaultAltCfgResp
= AllocateZeroPool (Length
* sizeof (CHAR16
));
2107 if (DefaultAltCfgResp
== NULL
) {
2108 Status
= EFI_OUT_OF_RESOURCES
;
2111 StringPtr
= DefaultAltCfgResp
;
2114 // Start with <ConfigHdr>
2116 StrCpy (StringPtr
, ConfigHdr
);
2117 StringPtr
+= StrLen (StringPtr
);
2119 for (Link
= DefaultIdArray
->Entry
.ForwardLink
; Link
!= &DefaultIdArray
->Entry
; Link
= Link
->ForwardLink
) {
2120 DefaultId
= BASE_CR (Link
, IFR_DEFAULT_DATA
, Entry
);
2122 // Add <AltConfigHdr> of the form "&<ConfigHdr>&ALTCFG=XXXX\0"
2123 // |1| StrLen (ConfigHdr) | 8 | 4 |
2127 (1 + StrLen (ConfigHdr
) + 8 + 4 + 1) * sizeof (CHAR16
),
2130 DefaultId
->DefaultName
2132 StringPtr
+= StrLen (StringPtr
);
2134 for (LinkData
= VarStorageData
->BlockEntry
.ForwardLink
; LinkData
!= &VarStorageData
->BlockEntry
; LinkData
= LinkData
->ForwardLink
) {
2135 BlockData
= BASE_CR (LinkData
, IFR_BLOCK_DATA
, Entry
);
2136 for (LinkDefault
= BlockData
->DefaultValueEntry
.ForwardLink
; LinkDefault
!= &BlockData
->DefaultValueEntry
; LinkDefault
= LinkDefault
->ForwardLink
) {
2137 DefaultValueData
= BASE_CR (LinkDefault
, IFR_DEFAULT_DATA
, Entry
);
2138 if (DefaultValueData
->DefaultId
== DefaultId
->DefaultId
) {
2140 // Add <BlockConfig>
2141 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>
2145 (8 + 4 + 7 + 4 + 7 + 1) * sizeof (CHAR16
),
2146 L
"&OFFSET=%04X&WIDTH=%04X&VALUE=",
2150 StringPtr
+= StrLen (StringPtr
);
2153 // Convert Value to a hex string in "%x" format
2154 // NOTE: This is in the opposite byte that GUID and PATH use
2156 Width
= BlockData
->Width
;
2157 TmpBuffer
= (UINT8
*) &(DefaultValueData
->Value
);
2158 for (; Width
> 0; Width
--) {
2159 StringPtr
+= UnicodeValueToString (StringPtr
, PREFIX_ZERO
| RADIX_HEX
, TmpBuffer
[Width
- 1], 2);
2165 HiiToLower (DefaultAltCfgResp
);
2168 // 5. Merge string into the input AltCfgResp if the iput *AltCfgResp is not NULL.
2170 if (*AltCfgResp
!= NULL
&& DefaultAltCfgResp
!= NULL
) {
2171 Status
= MergeDefaultString (AltCfgResp
, DefaultAltCfgResp
);
2172 FreePool (DefaultAltCfgResp
);
2173 } else if (*AltCfgResp
== NULL
) {
2174 *AltCfgResp
= DefaultAltCfgResp
;
2178 if (RequestBlockArray
!= NULL
) {
2180 // Free Link Array RequestBlockArray
2182 while (!IsListEmpty (&RequestBlockArray
->Entry
)) {
2183 BlockData
= BASE_CR (RequestBlockArray
->Entry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
2184 RemoveEntryList (&BlockData
->Entry
);
2185 FreePool (BlockData
);
2188 FreePool (RequestBlockArray
);
2191 if (VarStorageData
!= NULL
) {
2193 // Free link array VarStorageData
2195 while (!IsListEmpty (&VarStorageData
->BlockEntry
)) {
2196 BlockData
= BASE_CR (VarStorageData
->BlockEntry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
2197 RemoveEntryList (&BlockData
->Entry
);
2199 // Free default value link array
2201 while (!IsListEmpty (&BlockData
->DefaultValueEntry
)) {
2202 DefaultValueData
= BASE_CR (BlockData
->DefaultValueEntry
.ForwardLink
, IFR_DEFAULT_DATA
, Entry
);
2203 RemoveEntryList (&DefaultValueData
->Entry
);
2204 FreePool (DefaultValueData
);
2206 FreePool (BlockData
);
2208 FreePool (VarStorageData
);
2211 if (DefaultIdArray
!= NULL
) {
2213 // Free DefaultId Array
2215 while (!IsListEmpty (&DefaultIdArray
->Entry
)) {
2216 DefaultId
= BASE_CR (DefaultIdArray
->Entry
.ForwardLink
, IFR_DEFAULT_DATA
, Entry
);
2217 RemoveEntryList (&DefaultId
->Entry
);
2218 FreePool (DefaultId
);
2220 FreePool (DefaultIdArray
);
2224 // Free the allocated string
2226 if (GuidStr
!= NULL
) {
2229 if (NameStr
!= NULL
) {
2232 if (PathStr
!= NULL
) {
2235 if (ConfigHdr
!= NULL
) {
2236 FreePool (ConfigHdr
);
2240 // Free Pacakge data
2242 if (HiiFormPackage
!= NULL
) {
2243 FreePool (HiiFormPackage
);
2246 if (PointerProgress
!= NULL
) {
2247 if (*Request
== NULL
) {
2248 *PointerProgress
= NULL
;
2249 } else if (EFI_ERROR (Status
)) {
2250 *PointerProgress
= Progress
;
2252 *PointerProgress
= *Request
+ StrLen (*Request
);
2260 This function allows a caller to extract the current configuration
2261 for one or more named elements from one or more drivers.
2263 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
2265 @param Request A null-terminated Unicode string in
2266 <MultiConfigRequest> format.
2267 @param Progress On return, points to a character in the Request
2268 string. Points to the string's null terminator if
2269 request was successful. Points to the most recent
2270 & before the first failing name / value pair (or
2271 the beginning of the string if the failure is in
2272 the first name / value pair) if the request was
2274 @param Results Null-terminated Unicode string in
2275 <MultiConfigAltResp> format which has all values
2276 filled in for the names in the Request string.
2277 String to be allocated by the called function.
2279 @retval EFI_SUCCESS The Results string is filled with the values
2280 corresponding to all requested names.
2281 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
2282 results that must be stored awaiting possible
2284 @retval EFI_NOT_FOUND Routing data doesn't match any known driver.
2285 Progress set to the "G" in "GUID" of the routing
2286 header that doesn't match. Note: There is no
2287 requirement that all routing data be validated
2288 before any configuration extraction.
2289 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Request
2290 parameter would result in this type of error. The
2291 Progress parameter is set to NULL.
2292 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set to most recent &
2293 before the error or the beginning of the string.
2294 @retval EFI_INVALID_PARAMETER Unknown name. Progress points to the & before the
2300 HiiConfigRoutingExtractConfig (
2301 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
2302 IN CONST EFI_STRING Request
,
2303 OUT EFI_STRING
*Progress
,
2304 OUT EFI_STRING
*Results
2307 HII_DATABASE_PRIVATE_DATA
*Private
;
2308 EFI_STRING StringPtr
;
2309 EFI_STRING ConfigRequest
;
2311 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
2312 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
2315 HII_DATABASE_RECORD
*Database
;
2316 UINT8
*DevicePathPkg
;
2317 UINT8
*CurrentDevicePath
;
2318 EFI_HANDLE DriverHandle
;
2319 EFI_HII_HANDLE HiiHandle
;
2320 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
2321 EFI_STRING AccessProgress
;
2322 EFI_STRING AccessResults
;
2323 EFI_STRING DefaultResults
;
2324 BOOLEAN FirstElement
;
2325 BOOLEAN IfrDataParsedFlag
;
2327 if (This
== NULL
|| Progress
== NULL
|| Results
== NULL
) {
2328 return EFI_INVALID_PARAMETER
;
2331 if (Request
== NULL
) {
2333 return EFI_INVALID_PARAMETER
;
2336 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
2337 StringPtr
= Request
;
2338 *Progress
= StringPtr
;
2339 DefaultResults
= NULL
;
2340 ConfigRequest
= NULL
;
2341 Status
= EFI_SUCCESS
;
2342 AccessResults
= NULL
;
2344 IfrDataParsedFlag
= FALSE
;
2347 // The first element of <MultiConfigRequest> should be
2348 // <GuidHdr>, which is in 'GUID='<Guid> syntax.
2350 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
2351 return EFI_INVALID_PARAMETER
;
2354 FirstElement
= TRUE
;
2357 // Allocate a fix length of memory to store Results. Reallocate memory for
2358 // Results if this fix length is insufficient.
2360 *Results
= (EFI_STRING
) AllocateZeroPool (MAX_STRING_LENGTH
);
2361 if (*Results
== NULL
) {
2362 return EFI_OUT_OF_RESOURCES
;
2365 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) == 0) {
2367 // If parsing error, set Progress to the beginning of the <MultiConfigRequest>
2368 // or most recent & before the error.
2370 if (StringPtr
== Request
) {
2371 *Progress
= StringPtr
;
2373 *Progress
= StringPtr
- 1;
2377 // Process each <ConfigRequest> of <MultiConfigRequest>
2379 Length
= CalculateConfigStringLen (StringPtr
);
2380 ConfigRequest
= AllocateCopyPool ((Length
+ 1) * sizeof (CHAR16
), StringPtr
);
2381 if (ConfigRequest
== NULL
) {
2382 Status
= EFI_OUT_OF_RESOURCES
;
2385 *(ConfigRequest
+ Length
) = 0;
2388 // Get the UEFI device path
2390 Status
= GetDevicePath (ConfigRequest
, (UINT8
**) &DevicePath
);
2391 if (EFI_ERROR (Status
)) {
2396 // Find driver which matches the routing data.
2398 DriverHandle
= NULL
;
2401 for (Link
= Private
->DatabaseList
.ForwardLink
;
2402 Link
!= &Private
->DatabaseList
;
2403 Link
= Link
->ForwardLink
2405 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
2406 if ((DevicePathPkg
= Database
->PackageList
->DevicePathPkg
) != NULL
) {
2407 CurrentDevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
2411 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) CurrentDevicePath
)
2413 DriverHandle
= Database
->DriverHandle
;
2414 HiiHandle
= Database
->Handle
;
2421 // Try to find driver handle by device path.
2423 if (DriverHandle
== NULL
) {
2424 TempDevicePath
= DevicePath
;
2425 Status
= gBS
->LocateDevicePath (
2426 &gEfiDevicePathProtocolGuid
,
2430 if (EFI_ERROR (Status
) || (DriverHandle
== NULL
)) {
2432 // Routing data does not match any known driver.
2433 // Set Progress to the 'G' in "GUID" of the routing header.
2435 *Progress
= StringPtr
;
2436 Status
= EFI_NOT_FOUND
;
2442 // Check whether ConfigRequest contains request string OFFSET/WIDTH
2444 IfrDataParsedFlag
= FALSE
;
2445 if ((HiiHandle
!= NULL
) && (StrStr (ConfigRequest
, L
"&OFFSET=") == NULL
)) {
2447 // Get the full request string from IFR when HiiPackage is registered to HiiHandle
2449 IfrDataParsedFlag
= TRUE
;
2450 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &ConfigRequest
, &DefaultResults
, &AccessProgress
);
2451 if (EFI_ERROR (Status
)) {
2453 // AccessProgress indicates the parsing progress on <ConfigRequest>.
2454 // Map it to the progress on <MultiConfigRequest> then return it.
2456 *Progress
= StrStr (StringPtr
, AccessProgress
);
2460 // Not any request block is found.
2462 if (StrStr (ConfigRequest
, L
"&OFFSET=") == NULL
) {
2463 AccessResults
= AllocateCopyPool (StrSize (ConfigRequest
), ConfigRequest
);
2464 goto NextConfigString
;
2469 // Call corresponding ConfigAccess protocol to extract settings
2471 Status
= gBS
->HandleProtocol (
2473 &gEfiHiiConfigAccessProtocolGuid
,
2474 (VOID
**) &ConfigAccess
2476 ASSERT_EFI_ERROR (Status
);
2478 Status
= ConfigAccess
->ExtractConfig (
2484 if (EFI_ERROR (Status
)) {
2486 // AccessProgress indicates the parsing progress on <ConfigRequest>.
2487 // Map it to the progress on <MultiConfigRequest> then return it.
2489 *Progress
= StrStr (StringPtr
, AccessProgress
);
2494 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'
2495 // which seperates the first <ConfigAltResp> and the following ones.
2497 ASSERT (*AccessProgress
== 0);
2500 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
2502 if (!IfrDataParsedFlag
&& HiiHandle
!= NULL
) {
2503 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &ConfigRequest
, &DefaultResults
, NULL
);
2504 ASSERT_EFI_ERROR (Status
);
2507 FreePool (DevicePath
);
2510 if (DefaultResults
!= NULL
) {
2511 Status
= MergeDefaultString (&AccessResults
, DefaultResults
);
2512 ASSERT_EFI_ERROR (Status
);
2513 FreePool (DefaultResults
);
2514 DefaultResults
= NULL
;
2518 if (!FirstElement
) {
2519 Status
= AppendToMultiString (Results
, L
"&");
2520 ASSERT_EFI_ERROR (Status
);
2523 Status
= AppendToMultiString (Results
, AccessResults
);
2524 ASSERT_EFI_ERROR (Status
);
2526 FirstElement
= FALSE
;
2528 FreePool (AccessResults
);
2529 AccessResults
= NULL
;
2530 FreePool (ConfigRequest
);
2531 ConfigRequest
= NULL
;
2534 // Go to next <ConfigRequest> (skip '&').
2536 StringPtr
+= Length
;
2537 if (*StringPtr
== 0) {
2538 *Progress
= StringPtr
;
2546 if (EFI_ERROR (Status
)) {
2547 FreePool (*Results
);
2551 if (ConfigRequest
!= NULL
) {
2552 FreePool (ConfigRequest
);
2555 if (AccessResults
!= NULL
) {
2556 FreePool (AccessResults
);
2559 if (DefaultResults
!= NULL
) {
2560 FreePool (DefaultResults
);
2563 if (DevicePath
!= NULL
) {
2564 FreePool (DevicePath
);
2572 This function allows the caller to request the current configuration for the
2573 entirety of the current HII database and returns the data in a
2574 null-terminated Unicode string.
2576 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
2578 @param Results Null-terminated Unicode string in
2579 <MultiConfigAltResp> format which has all values
2580 filled in for the names in the Request string.
2581 String to be allocated by the called function.
2582 De-allocation is up to the caller.
2584 @retval EFI_SUCCESS The Results string is filled with the values
2585 corresponding to all requested names.
2586 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
2587 results that must be stored awaiting possible
2589 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Results
2590 parameter would result in this type of error.
2595 HiiConfigRoutingExportConfig (
2596 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
2597 OUT EFI_STRING
*Results
2601 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
2602 EFI_STRING AccessResults
;
2603 EFI_STRING Progress
;
2604 EFI_STRING StringPtr
;
2605 EFI_STRING ConfigRequest
;
2607 EFI_HANDLE
*ConfigAccessHandles
;
2608 UINTN NumberConfigAccessHandles
;
2609 BOOLEAN FirstElement
;
2610 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
2611 EFI_HII_HANDLE HiiHandle
;
2612 EFI_STRING DefaultResults
;
2613 HII_DATABASE_PRIVATE_DATA
*Private
;
2615 HII_DATABASE_RECORD
*Database
;
2616 UINT8
*DevicePathPkg
;
2617 UINT8
*CurrentDevicePath
;
2618 BOOLEAN IfrDataParsedFlag
;
2620 if (This
== NULL
|| Results
== NULL
) {
2621 return EFI_INVALID_PARAMETER
;
2624 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
2627 // Allocate a fix length of memory to store Results. Reallocate memory for
2628 // Results if this fix length is insufficient.
2630 *Results
= (EFI_STRING
) AllocateZeroPool (MAX_STRING_LENGTH
);
2631 if (*Results
== NULL
) {
2632 return EFI_OUT_OF_RESOURCES
;
2635 NumberConfigAccessHandles
= 0;
2636 Status
= gBS
->LocateHandleBuffer (
2638 &gEfiHiiConfigAccessProtocolGuid
,
2640 &NumberConfigAccessHandles
,
2641 &ConfigAccessHandles
2643 if (EFI_ERROR (Status
)) {
2647 FirstElement
= TRUE
;
2649 for (Index
= 0; Index
< NumberConfigAccessHandles
; Index
++) {
2650 Status
= gBS
->HandleProtocol (
2651 ConfigAccessHandles
[Index
],
2652 &gEfiHiiConfigAccessProtocolGuid
,
2653 (VOID
**) &ConfigAccess
2655 if (EFI_ERROR (Status
)) {
2660 // Get DevicePath and HiiHandle for this ConfigAccess driver handle
2662 IfrDataParsedFlag
= FALSE
;
2665 DefaultResults
= NULL
;
2667 ConfigRequest
= NULL
;
2668 DevicePath
= DevicePathFromHandle (ConfigAccessHandles
[Index
]);
2669 if (DevicePath
!= NULL
) {
2670 for (Link
= Private
->DatabaseList
.ForwardLink
;
2671 Link
!= &Private
->DatabaseList
;
2672 Link
= Link
->ForwardLink
2674 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
2675 if ((DevicePathPkg
= Database
->PackageList
->DevicePathPkg
) != NULL
) {
2676 CurrentDevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
2680 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) CurrentDevicePath
)
2682 HiiHandle
= Database
->Handle
;
2689 Status
= ConfigAccess
->ExtractConfig (
2695 if (EFI_ERROR (Status
)) {
2697 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
2699 if (HiiHandle
!= NULL
&& DevicePath
!= NULL
) {
2700 IfrDataParsedFlag
= TRUE
;
2701 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &ConfigRequest
, &DefaultResults
, NULL
);
2703 // Get the full request string to get the Current setting again.
2705 if (!EFI_ERROR (Status
) && ConfigRequest
!= NULL
) {
2706 Status
= ConfigAccess
->ExtractConfig (
2712 FreePool (ConfigRequest
);
2714 Status
= EFI_NOT_FOUND
;
2719 if (!EFI_ERROR (Status
)) {
2721 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
2723 if (!IfrDataParsedFlag
&& HiiHandle
!= NULL
&& DevicePath
!= NULL
) {
2724 StringPtr
= StrStr (AccessResults
, L
"&GUID=");
2725 if (StringPtr
!= NULL
) {
2728 if (StrStr (AccessResults
, L
"&OFFSET=") != NULL
) {
2729 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &AccessResults
, &DefaultResults
, NULL
);
2730 ASSERT_EFI_ERROR (Status
);
2732 if (StringPtr
!= NULL
) {
2737 // Merge the default sting from IFR code into the got setting from driver.
2739 if (DefaultResults
!= NULL
) {
2740 Status
= MergeDefaultString (&AccessResults
, DefaultResults
);
2741 ASSERT_EFI_ERROR (Status
);
2742 FreePool (DefaultResults
);
2743 DefaultResults
= NULL
;
2747 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'
2748 // which seperates the first <ConfigAltResp> and the following ones.
2750 if (!FirstElement
) {
2751 Status
= AppendToMultiString (Results
, L
"&");
2752 ASSERT_EFI_ERROR (Status
);
2755 Status
= AppendToMultiString (Results
, AccessResults
);
2756 ASSERT_EFI_ERROR (Status
);
2758 FirstElement
= FALSE
;
2760 FreePool (AccessResults
);
2761 AccessResults
= NULL
;
2764 FreePool (ConfigAccessHandles
);
2771 This function processes the results of processing forms and routes it to the
2772 appropriate handlers or storage.
2774 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
2776 @param Configuration A null-terminated Unicode string in
2777 <MulltiConfigResp> format.
2778 @param Progress A pointer to a string filled in with the offset of
2779 the most recent & before the first failing name /
2780 value pair (or the beginning of the string if the
2781 failure is in the first name / value pair) or the
2782 terminating NULL if all was successful.
2784 @retval EFI_SUCCESS The results have been distributed or are awaiting
2786 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
2787 results that must be stored awaiting possible
2789 @retval EFI_INVALID_PARAMETER Passing in a NULL for the Configuration parameter
2790 would result in this type of error.
2791 @retval EFI_NOT_FOUND Target for the specified routing data was not
2797 HiiConfigRoutingRouteConfig (
2798 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
2799 IN CONST EFI_STRING Configuration
,
2800 OUT EFI_STRING
*Progress
2803 HII_DATABASE_PRIVATE_DATA
*Private
;
2804 EFI_STRING StringPtr
;
2805 EFI_STRING ConfigResp
;
2808 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
2809 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
2811 HII_DATABASE_RECORD
*Database
;
2812 UINT8
*DevicePathPkg
;
2813 UINT8
*CurrentDevicePath
;
2814 EFI_HANDLE DriverHandle
;
2815 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
2816 EFI_STRING AccessProgress
;
2818 if (This
== NULL
|| Progress
== NULL
) {
2819 return EFI_INVALID_PARAMETER
;
2822 if (Configuration
== NULL
) {
2824 return EFI_INVALID_PARAMETER
;
2827 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
2828 StringPtr
= Configuration
;
2829 *Progress
= StringPtr
;
2832 // The first element of <MultiConfigResp> should be
2833 // <GuidHdr>, which is in 'GUID='<Guid> syntax.
2835 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
2836 return EFI_INVALID_PARAMETER
;
2839 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) == 0) {
2841 // If parsing error, set Progress to the beginning of the <MultiConfigResp>
2842 // or most recent & before the error.
2844 if (StringPtr
== Configuration
) {
2845 *Progress
= StringPtr
;
2847 *Progress
= StringPtr
- 1;
2851 // Process each <ConfigResp> of <MultiConfigResp>
2853 Length
= CalculateConfigStringLen (StringPtr
);
2854 ConfigResp
= AllocateCopyPool ((Length
+ 1) * sizeof (CHAR16
), StringPtr
);
2855 if (ConfigResp
== NULL
) {
2856 return EFI_OUT_OF_RESOURCES
;
2859 // Append '\0' to the end of ConfigRequest
2861 *(ConfigResp
+ Length
) = 0;
2864 // Get the UEFI device path
2866 Status
= GetDevicePath (ConfigResp
, (UINT8
**) &DevicePath
);
2867 if (EFI_ERROR (Status
)) {
2868 FreePool (ConfigResp
);
2873 // Find driver which matches the routing data.
2875 DriverHandle
= NULL
;
2876 for (Link
= Private
->DatabaseList
.ForwardLink
;
2877 Link
!= &Private
->DatabaseList
;
2878 Link
= Link
->ForwardLink
2880 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
2882 if ((DevicePathPkg
= Database
->PackageList
->DevicePathPkg
) != NULL
) {
2883 CurrentDevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
2887 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) CurrentDevicePath
)
2889 DriverHandle
= Database
->DriverHandle
;
2896 // Try to find driver handle by device path.
2898 if (DriverHandle
== NULL
) {
2899 TempDevicePath
= DevicePath
;
2900 Status
= gBS
->LocateDevicePath (
2901 &gEfiDevicePathProtocolGuid
,
2905 if (EFI_ERROR (Status
) || (DriverHandle
== NULL
)) {
2907 // Routing data does not match any known driver.
2908 // Set Progress to the 'G' in "GUID" of the routing header.
2910 FreePool (DevicePath
);
2911 *Progress
= StringPtr
;
2912 FreePool (ConfigResp
);
2913 return EFI_NOT_FOUND
;
2917 FreePool (DevicePath
);
2920 // Call corresponding ConfigAccess protocol to route settings
2922 Status
= gBS
->HandleProtocol (
2924 &gEfiHiiConfigAccessProtocolGuid
,
2925 (VOID
**) &ConfigAccess
2927 ASSERT_EFI_ERROR (Status
);
2929 Status
= ConfigAccess
->RouteConfig (
2935 if (EFI_ERROR (Status
)) {
2937 // AccessProgress indicates the parsing progress on <ConfigResp>.
2938 // Map it to the progress on <MultiConfigResp> then return it.
2940 *Progress
= StrStr (StringPtr
, AccessProgress
);
2942 FreePool (ConfigResp
);
2946 FreePool (ConfigResp
);
2950 // Go to next <ConfigResp> (skip '&').
2952 StringPtr
+= Length
;
2953 if (*StringPtr
== 0) {
2954 *Progress
= StringPtr
;
2967 This helper function is to be called by drivers to map configuration data
2968 stored in byte array ("block") formats such as UEFI Variables into current
2969 configuration strings.
2971 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
2973 @param ConfigRequest A null-terminated Unicode string in
2974 <ConfigRequest> format.
2975 @param Block Array of bytes defining the block's configuration.
2976 @param BlockSize Length in bytes of Block.
2977 @param Config Filled-in configuration string. String allocated
2978 by the function. Returned only if call is
2979 successful. It is <ConfigResp> string format.
2980 @param Progress A pointer to a string filled in with the offset of
2981 the most recent & before the first failing
2982 name/value pair (or the beginning of the string if
2983 the failure is in the first name / value pair) or
2984 the terminating NULL if all was successful.
2986 @retval EFI_SUCCESS The request succeeded. Progress points to the null
2987 terminator at the end of the ConfigRequest
2989 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress
2990 points to the first character of ConfigRequest.
2991 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigRequest or
2992 Block parameter would result in this type of
2993 error. Progress points to the first character of
2995 @retval EFI_DEVICE_ERROR Block not large enough. Progress undefined.
2996 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted string.
2997 Block is left updated and Progress points at
2998 the "&" preceding the first non-<BlockName>.
3004 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
3005 IN CONST EFI_STRING ConfigRequest
,
3006 IN CONST UINT8
*Block
,
3007 IN CONST UINTN BlockSize
,
3008 OUT EFI_STRING
*Config
,
3009 OUT EFI_STRING
*Progress
3012 HII_DATABASE_PRIVATE_DATA
*Private
;
3013 EFI_STRING StringPtr
;
3021 EFI_STRING ValueStr
;
3022 EFI_STRING ConfigElement
;
3027 if (This
== NULL
|| Progress
== NULL
|| Config
== NULL
) {
3028 return EFI_INVALID_PARAMETER
;
3031 if (Block
== NULL
|| ConfigRequest
== NULL
) {
3032 *Progress
= ConfigRequest
;
3033 return EFI_INVALID_PARAMETER
;
3037 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
3038 ASSERT (Private
!= NULL
);
3040 StringPtr
= ConfigRequest
;
3043 ConfigElement
= NULL
;
3046 // Allocate a fix length of memory to store Results. Reallocate memory for
3047 // Results if this fix length is insufficient.
3049 *Config
= (EFI_STRING
) AllocateZeroPool (MAX_STRING_LENGTH
);
3050 if (*Config
== NULL
) {
3051 return EFI_OUT_OF_RESOURCES
;
3057 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
3058 *Progress
= StringPtr
;
3059 Status
= EFI_INVALID_PARAMETER
;
3062 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"PATH=", StrLen (L
"PATH=")) != 0) {
3065 if (*StringPtr
== 0) {
3066 *Progress
= StringPtr
- 1;
3067 Status
= EFI_INVALID_PARAMETER
;
3071 while (*StringPtr
!= L
'&' && *StringPtr
!= 0) {
3074 if (*StringPtr
== 0) {
3075 *Progress
= StringPtr
- 1;
3076 Status
= EFI_INVALID_PARAMETER
;
3085 // Copy <ConfigHdr> and an additional '&' to <ConfigResp>
3087 Length
= StringPtr
- ConfigRequest
;
3088 CopyMem (*Config
, ConfigRequest
, Length
* sizeof (CHAR16
));
3091 // Parse each <RequestElement> if exists
3092 // Only <BlockName> format is supported by this help function.
3093 // <BlockName> ::= 'OFFSET='<Number>&'WIDTH='<Number>
3095 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"OFFSET=", StrLen (L
"OFFSET=")) == 0) {
3097 // Back up the header of one <BlockName>
3101 StringPtr
+= StrLen (L
"OFFSET=");
3105 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
3106 if (Status
== EFI_OUT_OF_RESOURCES
) {
3107 *Progress
= ConfigRequest
;
3114 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
3116 FreePool (TmpBuffer
);
3118 StringPtr
+= Length
;
3119 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
3120 *Progress
= StringPtr
- Length
- StrLen (L
"OFFSET=") - 1;
3121 Status
= EFI_INVALID_PARAMETER
;
3124 StringPtr
+= StrLen (L
"&WIDTH=");
3129 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
3130 if (Status
== EFI_OUT_OF_RESOURCES
) {
3131 *Progress
= ConfigRequest
;
3138 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
3140 FreePool (TmpBuffer
);
3142 StringPtr
+= Length
;
3143 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
3144 *Progress
= StringPtr
- Length
- StrLen (L
"&WIDTH=");
3145 Status
= EFI_INVALID_PARAMETER
;
3150 // Calculate Value and convert it to hex string.
3152 if (Offset
+ Width
> BlockSize
) {
3153 *Progress
= StringPtr
;
3154 Status
= EFI_DEVICE_ERROR
;
3158 Value
= (UINT8
*) AllocateZeroPool (Width
);
3159 if (Value
== NULL
) {
3160 *Progress
= ConfigRequest
;
3161 Status
= EFI_OUT_OF_RESOURCES
;
3165 CopyMem (Value
, (UINT8
*) Block
+ Offset
, Width
);
3167 Length
= Width
* 2 + 1;
3168 ValueStr
= (EFI_STRING
) AllocateZeroPool (Length
* sizeof (CHAR16
));
3169 if (ValueStr
== NULL
) {
3170 *Progress
= ConfigRequest
;
3171 Status
= EFI_OUT_OF_RESOURCES
;
3175 TemString
= ValueStr
;
3176 TemBuffer
= Value
+ Width
- 1;
3177 for (Index
= 0; Index
< Width
; Index
++, TemBuffer
--) {
3178 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
3185 // Build a ConfigElement
3187 Length
+= StringPtr
- TmpPtr
+ 1 + StrLen (L
"VALUE=");
3188 ConfigElement
= (EFI_STRING
) AllocateZeroPool (Length
* sizeof (CHAR16
));
3189 if (ConfigElement
== NULL
) {
3190 Status
= EFI_OUT_OF_RESOURCES
;
3193 CopyMem (ConfigElement
, TmpPtr
, (StringPtr
- TmpPtr
+ 1) * sizeof (CHAR16
));
3194 if (*StringPtr
== 0) {
3195 *(ConfigElement
+ (StringPtr
- TmpPtr
)) = L
'&';
3197 *(ConfigElement
+ (StringPtr
- TmpPtr
) + 1) = 0;
3198 StrCat (ConfigElement
, L
"VALUE=");
3199 StrCat (ConfigElement
, ValueStr
);
3201 AppendToMultiString (Config
, ConfigElement
);
3203 FreePool (ConfigElement
);
3204 FreePool (ValueStr
);
3205 ConfigElement
= NULL
;
3209 // If '\0', parsing is finished. Otherwise skip '&' to continue
3211 if (*StringPtr
== 0) {
3214 AppendToMultiString (Config
, L
"&");
3219 if (*StringPtr
!= 0) {
3220 *Progress
= StringPtr
- 1;
3221 Status
= EFI_INVALID_PARAMETER
;
3225 HiiToLower (*Config
);
3226 *Progress
= StringPtr
;
3230 if (*Config
!= NULL
) {
3234 if (ValueStr
!= NULL
) {
3235 FreePool (ValueStr
);
3237 if (Value
!= NULL
) {
3240 if (ConfigElement
!= NULL
) {
3241 FreePool (ConfigElement
);
3250 This helper function is to be called by drivers to map configuration strings
3251 to configurations stored in byte array ("block") formats such as UEFI Variables.
3253 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
3255 @param ConfigResp A null-terminated Unicode string in <ConfigResp>
3257 @param Block A possibly null array of bytes representing the
3258 current block. Only bytes referenced in the
3259 ConfigResp string in the block are modified. If
3260 this parameter is null or if the *BlockSize
3261 parameter is (on input) shorter than required by
3262 the Configuration string, only the BlockSize
3263 parameter is updated and an appropriate status
3264 (see below) is returned.
3265 @param BlockSize The length of the Block in units of UINT8. On
3266 input, this is the size of the Block. On output,
3267 if successful, contains the index of the last
3268 modified byte in the Block.
3269 @param Progress On return, points to an element of the ConfigResp
3270 string filled in with the offset of the most
3271 recent '&' before the first failing name / value
3272 pair (or the beginning of the string if the
3273 failure is in the first name / value pair) or the
3274 terminating NULL if all was successful.
3276 @retval EFI_SUCCESS The request succeeded. Progress points to the null
3277 terminator at the end of the ConfigResp string.
3278 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress
3279 points to the first character of ConfigResp.
3280 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigResp or
3281 Block parameter would result in this type of
3282 error. Progress points to the first character of
3284 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted name /
3285 value pair. Block is left updated and
3286 Progress points at the '&' preceding the first
3288 @retval EFI_DEVICE_ERROR Block not large enough. Progress undefined.
3289 @retval EFI_NOT_FOUND Target for the specified routing data was not found.
3290 Progress points to the "G" in "GUID" of the errant
3297 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
3298 IN CONST EFI_STRING ConfigResp
,
3299 IN OUT UINT8
*Block
,
3300 IN OUT UINTN
*BlockSize
,
3301 OUT EFI_STRING
*Progress
3304 HII_DATABASE_PRIVATE_DATA
*Private
;
3305 EFI_STRING StringPtr
;
3315 if (This
== NULL
|| BlockSize
== NULL
|| Progress
== NULL
) {
3316 return EFI_INVALID_PARAMETER
;
3319 *Progress
= ConfigResp
;
3320 if (ConfigResp
== NULL
) {
3321 return EFI_INVALID_PARAMETER
;
3324 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
3325 ASSERT (Private
!= NULL
);
3327 StringPtr
= ConfigResp
;
3328 BufferSize
= *BlockSize
;
3335 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
3336 *Progress
= StringPtr
;
3337 Status
= EFI_INVALID_PARAMETER
;
3340 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"PATH=", StrLen (L
"PATH=")) != 0) {
3343 if (*StringPtr
== 0) {
3344 *Progress
= StringPtr
;
3345 Status
= EFI_INVALID_PARAMETER
;
3349 while (*StringPtr
!= L
'&' && *StringPtr
!= 0) {
3352 if (*StringPtr
== 0) {
3353 *Progress
= StringPtr
;
3354 Status
= EFI_INVALID_PARAMETER
;
3363 // Parse each <ConfigElement> if exists
3364 // Only <BlockConfig> format is supported by this help function.
3365 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE='<Number>
3367 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"OFFSET=", StrLen (L
"OFFSET=")) == 0) {
3368 StringPtr
+= StrLen (L
"OFFSET=");
3372 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
3373 if (EFI_ERROR (Status
)) {
3374 *Progress
= ConfigResp
;
3381 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
3383 FreePool (TmpBuffer
);
3385 StringPtr
+= Length
;
3386 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
3387 *Progress
= StringPtr
- Length
- StrLen (L
"OFFSET=") - 1;
3388 Status
= EFI_INVALID_PARAMETER
;
3391 StringPtr
+= StrLen (L
"&WIDTH=");
3396 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
3397 if (Status
== EFI_OUT_OF_RESOURCES
) {
3398 *Progress
= ConfigResp
;
3405 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
3407 FreePool (TmpBuffer
);
3409 StringPtr
+= Length
;
3410 if (StrnCmp (StringPtr
, L
"&VALUE=", StrLen (L
"&VALUE=")) != 0) {
3411 *Progress
= StringPtr
- Length
- StrLen (L
"&WIDTH=");
3412 Status
= EFI_INVALID_PARAMETER
;
3415 StringPtr
+= StrLen (L
"&VALUE=");
3420 Status
= GetValueOfNumber (StringPtr
, &Value
, &Length
);
3421 if (EFI_ERROR (Status
)) {
3422 *Progress
= ConfigResp
;
3426 StringPtr
+= Length
;
3427 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
3428 *Progress
= StringPtr
- Length
- 7;
3429 Status
= EFI_INVALID_PARAMETER
;
3434 // Update the Block with configuration info
3436 if ((Block
!= NULL
) && (Offset
+ Width
<= BufferSize
)) {
3437 CopyMem (Block
+ Offset
, Value
, Width
);
3439 if (Offset
+ Width
> MaxBlockSize
) {
3440 MaxBlockSize
= Offset
+ Width
;
3447 // If '\0', parsing is finished. Otherwise skip '&' to continue
3449 if (*StringPtr
== 0) {
3457 // The input string is ConfigAltResp format.
3459 if ((*StringPtr
!= 0) && (StrnCmp (StringPtr
, L
"&GUID=", StrLen (L
"&GUID=")) != 0)) {
3460 *Progress
= StringPtr
- 1;
3461 Status
= EFI_INVALID_PARAMETER
;
3465 *Progress
= StringPtr
+ StrLen (StringPtr
);
3466 *BlockSize
= MaxBlockSize
- 1;
3468 if (MaxBlockSize
> BufferSize
) {
3469 *BlockSize
= MaxBlockSize
;
3470 if (Block
!= NULL
) {
3471 return EFI_DEVICE_ERROR
;
3475 if (Block
== NULL
) {
3476 *Progress
= ConfigResp
;
3477 return EFI_INVALID_PARAMETER
;
3484 if (Value
!= NULL
) {
3492 This helper function is to be called by drivers to extract portions of
3493 a larger configuration string.
3495 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
3497 @param Configuration A null-terminated Unicode string in
3498 <MultiConfigAltResp> format.
3499 @param Guid A pointer to the GUID value to search for in the
3500 routing portion of the ConfigResp string when
3501 retrieving the requested data. If Guid is NULL,
3502 then all GUID values will be searched for.
3503 @param Name A pointer to the NAME value to search for in the
3504 routing portion of the ConfigResp string when
3505 retrieving the requested data. If Name is NULL,
3506 then all Name values will be searched for.
3507 @param DevicePath A pointer to the PATH value to search for in the
3508 routing portion of the ConfigResp string when
3509 retrieving the requested data. If DevicePath is
3510 NULL, then all DevicePath values will be searched
3512 @param AltCfgId A pointer to the ALTCFG value to search for in the
3513 routing portion of the ConfigResp string when
3514 retrieving the requested data. If this parameter
3515 is NULL, then the current setting will be
3517 @param AltCfgResp A pointer to a buffer which will be allocated by
3518 the function which contains the retrieved string
3519 as requested. This buffer is only allocated if
3520 the call was successful. It is <ConfigResp> format.
3522 @retval EFI_SUCCESS The request succeeded. The requested data was
3523 extracted and placed in the newly allocated
3525 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate AltCfgResp.
3526 @retval EFI_INVALID_PARAMETER Any parameter is invalid.
3527 @retval EFI_NOT_FOUND Target for the specified routing data was not
3534 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
3535 IN CONST EFI_STRING Configuration
,
3536 IN CONST EFI_GUID
*Guid
,
3537 IN CONST EFI_STRING Name
,
3538 IN CONST EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
3539 IN CONST UINT16
*AltCfgId
,
3540 OUT EFI_STRING
*AltCfgResp
3544 EFI_STRING StringPtr
;
3545 EFI_STRING HdrStart
;
3552 EFI_STRING AltIdStr
;
3569 if (This
== NULL
|| Configuration
== NULL
|| AltCfgResp
== NULL
) {
3570 return EFI_INVALID_PARAMETER
;
3573 StringPtr
= Configuration
;
3574 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
3575 return EFI_INVALID_PARAMETER
;
3579 // Generate the sub string for later matching.
3581 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*) Guid
, 1, &GuidStr
);
3584 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) DevicePath
),
3585 (VOID
*) DevicePath
,
3589 if (AltCfgId
!= NULL
) {
3590 GenerateSubStr (L
"ALTCFG=", sizeof (UINT16
), (VOID
*) AltCfgId
, 3, &AltIdStr
);
3593 GenerateSubStr (L
"NAME=", StrLen (Name
) * sizeof (CHAR16
), (VOID
*) Name
, 2, &NameStr
);
3595 GenerateSubStr (L
"NAME=", 0, NULL
, 2, &NameStr
);
3598 while (*StringPtr
!= 0) {
3600 // Try to match the GUID
3603 TmpPtr
= StrStr (StringPtr
, GuidStr
);
3604 if (TmpPtr
== NULL
) {
3605 Status
= EFI_NOT_FOUND
;
3611 // Jump to <NameHdr>
3614 StringPtr
= TmpPtr
+ StrLen (GuidStr
);
3616 StringPtr
= StrStr (TmpPtr
, L
"NAME=");
3617 if (StringPtr
== NULL
) {
3618 Status
= EFI_NOT_FOUND
;
3626 // Try to match the NAME
3628 if (GuidFlag
&& !NameFlag
) {
3629 if (StrnCmp (StringPtr
, NameStr
, StrLen (NameStr
)) != 0) {
3633 // Jump to <PathHdr>
3636 StringPtr
+= StrLen (NameStr
);
3638 StringPtr
= StrStr (StringPtr
, L
"PATH=");
3639 if (StringPtr
== NULL
) {
3640 Status
= EFI_NOT_FOUND
;
3649 // Try to match the DevicePath
3651 if (GuidFlag
&& NameFlag
&& !PathFlag
) {
3652 if (StrnCmp (StringPtr
, PathStr
, StrLen (PathStr
)) != 0) {
3657 // Jump to '&' before <DescHdr> or <ConfigBody>
3659 if (DevicePath
!= NULL
) {
3660 StringPtr
+= StrLen (PathStr
);
3662 StringPtr
= StrStr (StringPtr
, L
"&");
3663 if (StringPtr
== NULL
) {
3664 Status
= EFI_NOT_FOUND
;
3675 // Try to match the AltCfgId
3677 if (GuidFlag
&& NameFlag
&& PathFlag
) {
3678 if (AltCfgId
== NULL
) {
3680 // Return Current Setting when AltCfgId is NULL.
3682 Status
= OutputConfigBody (StringPtr
, &Result
);
3686 // Search the <ConfigAltResp> to get the <AltResp> with AltCfgId.
3688 if (StrnCmp (StringPtr
, AltIdStr
, StrLen (AltIdStr
)) != 0) {
3694 // Skip AltIdStr and &
3696 StringPtr
= StringPtr
+ StrLen (AltIdStr
);
3697 Status
= OutputConfigBody (StringPtr
, &Result
);
3703 Status
= EFI_NOT_FOUND
;
3707 if (!EFI_ERROR (Status
) && (Result
!= NULL
)) {
3709 // Copy the <ConfigHdr> and <ConfigBody>
3711 Length
= HdrEnd
- HdrStart
+ StrLen (Result
) + 1;
3712 *AltCfgResp
= AllocateZeroPool (Length
* sizeof (CHAR16
));
3713 if (*AltCfgResp
== NULL
) {
3714 Status
= EFI_OUT_OF_RESOURCES
;
3716 StrnCpy (*AltCfgResp
, HdrStart
, HdrEnd
- HdrStart
);
3717 StrCat (*AltCfgResp
, Result
);
3718 Status
= EFI_SUCCESS
;
3722 if (GuidStr
!= NULL
) {
3725 if (NameStr
!= NULL
) {
3728 if (PathStr
!= NULL
) {
3731 if (AltIdStr
!= NULL
) {
3732 FreePool (AltIdStr
);
3734 if (Result
!= NULL
) {