2 Implementation of interfaces function for EFI_HII_CONFIG_ROUTING_PROTOCOL.
4 Copyright (c) 2007 - 2010, 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
;
865 Status
= EFI_SUCCESS
;
874 // Go through the form package to parse OpCode one by one.
876 IfrOffset
= sizeof (EFI_HII_PACKAGE_HEADER
);
877 while (IfrOffset
< PackageLength
) {
878 IfrOpHdr
= (EFI_IFR_OP_HEADER
*) (Package
+ IfrOffset
);
880 switch (IfrOpHdr
->OpCode
) {
881 case EFI_IFR_VARSTORE_OP
:
883 // VarStore is found. Don't need to search any more.
885 if (VarStorageData
->Size
!= 0) {
890 // Get the requied varstore information
891 // Add varstore by Guid and Name in ConfigHdr
892 // Make sure Offset is in varstore size and varstoreid
894 IfrVarStore
= (EFI_IFR_VARSTORE
*) IfrOpHdr
;
895 VarStoreName
= AllocateZeroPool (AsciiStrSize ((CHAR8
*)IfrVarStore
->Name
) * sizeof (CHAR16
));
896 if (VarStoreName
== NULL
) {
897 Status
= EFI_OUT_OF_RESOURCES
;
900 AsciiStrToUnicodeStr ((CHAR8
*) IfrVarStore
->Name
, VarStoreName
);
902 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*) &IfrVarStore
->Guid
, 1, &GuidStr
);
903 GenerateSubStr (L
"NAME=", StrLen (VarStoreName
) * sizeof (CHAR16
), (VOID
*) VarStoreName
, 2, &NameStr
);
904 LengthString
= StrLen (GuidStr
);
905 LengthString
= LengthString
+ StrLen (NameStr
) + 1;
906 TempStr
= AllocateZeroPool (LengthString
* sizeof (CHAR16
));
907 if (TempStr
== NULL
) {
910 FreePool (VarStoreName
);
911 Status
= EFI_OUT_OF_RESOURCES
;
914 StrCpy (TempStr
, GuidStr
);
915 StrCat (TempStr
, NameStr
);
916 if (ConfigHdr
== NULL
|| StrnCmp (ConfigHdr
, TempStr
, StrLen (TempStr
)) == 0) {
918 // Find the matched VarStore
920 CopyGuid (&VarStorageData
->Guid
, (EFI_GUID
*) (VOID
*) &IfrVarStore
->Guid
);
921 VarStorageData
->VarStoreId
= IfrVarStore
->VarStoreId
;
922 VarStorageData
->Size
= IfrVarStore
->Size
;
923 VarStorageData
->Name
= VarStoreName
;
926 // No found, free the allocated memory
928 FreePool (VarStoreName
);
931 // Free alllocated temp string.
938 case EFI_IFR_DEFAULTSTORE_OP
:
940 // Add new the map between default id and default name.
942 DefaultData
= (IFR_DEFAULT_DATA
*) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
943 if (DefaultData
== NULL
) {
944 Status
= EFI_OUT_OF_RESOURCES
;
947 DefaultData
->DefaultId
= ((EFI_IFR_DEFAULTSTORE
*) IfrOpHdr
)->DefaultId
;
948 DefaultData
->DefaultName
= ((EFI_IFR_DEFAULTSTORE
*) IfrOpHdr
)->DefaultName
;
949 InsertTailList (&DefaultIdArray
->Entry
, &DefaultData
->Entry
);
953 case EFI_IFR_FORM_OP
:
954 case EFI_IFR_FORM_MAP_OP
:
956 // No matched varstore is found and directly return.
958 if (VarStorageData
->Size
== 0) {
959 Status
= EFI_SUCCESS
;
964 case EFI_IFR_ONE_OF_OP
:
965 case EFI_IFR_NUMERIC_OP
:
967 // Numeric and OneOf has the same opcode structure.
971 // Numeric and OneOf question is not in IFR Form. This IFR form is not valid.
973 if (VarStorageData
->Size
== 0) {
974 Status
= EFI_INVALID_PARAMETER
;
978 // Check whether this question is for the requested varstore.
980 IfrOneOf
= (EFI_IFR_ONE_OF
*) IfrOpHdr
;
981 if (IfrOneOf
->Question
.VarStoreId
!= VarStorageData
->VarStoreId
) {
986 // Get Offset/Width by Question header and OneOf Flags
988 VarOffset
= IfrOneOf
->Question
.VarStoreInfo
.VarOffset
;
989 VarWidth
= (UINT16
) (1 << (IfrOneOf
->Flags
& EFI_IFR_NUMERIC_SIZE
));
991 // Check whether this question is in requested block array.
993 if (!BlockArrayCheck (RequestBlockArray
, VarOffset
, VarWidth
)) {
995 // This question is not in the requested string. Skip it.
1001 // Check this var question is in the var storage
1003 if ((VarOffset
+ VarWidth
) > VarStorageData
->Size
) {
1004 Status
= EFI_INVALID_PARAMETER
;
1011 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
1012 if (BlockData
== NULL
) {
1013 Status
= EFI_OUT_OF_RESOURCES
;
1016 BlockData
->Offset
= VarOffset
;
1017 BlockData
->Width
= VarWidth
;
1018 BlockData
->QuestionId
= IfrOneOf
->Question
.QuestionId
;
1019 BlockData
->OpCode
= IfrOpHdr
->OpCode
;
1020 BlockData
->Scope
= IfrOpHdr
->Scope
;
1021 InitializeListHead (&BlockData
->DefaultValueEntry
);
1023 // Add Block Data into VarStorageData BlockEntry
1025 InsertBlockData (&VarStorageData
->BlockEntry
, &BlockData
);
1028 case EFI_IFR_ORDERED_LIST_OP
:
1030 // offset by question header
1031 // width by EFI_IFR_ORDERED_LIST MaxContainers * OneofOption Type
1032 // no default value and default id, how to define its default value?
1036 // OrderedList question is not in IFR Form. This IFR form is not valid.
1038 if (VarStorageData
->Size
== 0) {
1039 Status
= EFI_INVALID_PARAMETER
;
1043 // Check whether this question is for the requested varstore.
1045 IfrOrderedList
= (EFI_IFR_ORDERED_LIST
*) IfrOpHdr
;
1046 if (IfrOrderedList
->Question
.VarStoreId
!= VarStorageData
->VarStoreId
) {
1052 // Get Offset/Width by Question header and OneOf Flags
1054 VarOffset
= IfrOrderedList
->Question
.VarStoreInfo
.VarOffset
;
1055 VarWidth
= IfrOrderedList
->MaxContainers
;
1060 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
1061 if (BlockData
== NULL
) {
1062 Status
= EFI_OUT_OF_RESOURCES
;
1065 BlockData
->Offset
= VarOffset
;
1066 BlockData
->Width
= VarWidth
;
1067 BlockData
->QuestionId
= IfrOrderedList
->Question
.QuestionId
;
1068 BlockData
->OpCode
= IfrOpHdr
->OpCode
;
1069 BlockData
->Scope
= IfrOpHdr
->Scope
;
1070 InitializeListHead (&BlockData
->DefaultValueEntry
);
1073 case EFI_IFR_CHECKBOX_OP
:
1075 // EFI_IFR_DEFAULT_OP
1076 // offset by question header
1077 // width is 1 sizeof (BOOLEAN)
1078 // default id by CheckBox Flags if CheckBox flags (Default or Mau) is set, the default value is 1 to be set.
1079 // value by DefaultOption
1080 // default id by DeaultOption DefaultId can override CheckBox Flags and Default value.
1084 // CheckBox question is not in IFR Form. This IFR form is not valid.
1086 if (VarStorageData
->Size
== 0) {
1087 Status
= EFI_INVALID_PARAMETER
;
1091 // Check whether this question is for the requested varstore.
1093 IfrCheckBox
= (EFI_IFR_CHECKBOX
*) IfrOpHdr
;
1094 if (IfrCheckBox
->Question
.VarStoreId
!= VarStorageData
->VarStoreId
) {
1099 // Get Offset/Width by Question header and OneOf Flags
1101 VarOffset
= IfrCheckBox
->Question
.VarStoreInfo
.VarOffset
;
1102 VarWidth
= sizeof (BOOLEAN
);
1105 // Check whether this question is in requested block array.
1107 if (!BlockArrayCheck (RequestBlockArray
, VarOffset
, VarWidth
)) {
1109 // This question is not in the requested string. Skip it.
1115 // Check this var question is in the var storage
1117 if ((VarOffset
+ VarWidth
) > VarStorageData
->Size
) {
1118 Status
= EFI_INVALID_PARAMETER
;
1125 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
1126 if (BlockData
== NULL
) {
1127 Status
= EFI_OUT_OF_RESOURCES
;
1130 BlockData
->Offset
= VarOffset
;
1131 BlockData
->Width
= VarWidth
;
1132 BlockData
->QuestionId
= IfrCheckBox
->Question
.QuestionId
;
1133 BlockData
->OpCode
= IfrOpHdr
->OpCode
;
1134 BlockData
->Scope
= IfrOpHdr
->Scope
;
1135 InitializeListHead (&BlockData
->DefaultValueEntry
);
1137 // Add Block Data into VarStorageData BlockEntry
1139 InsertBlockData (&VarStorageData
->BlockEntry
, &BlockData
);
1142 // Add default value by CheckBox Flags
1144 if ((IfrCheckBox
->Flags
& EFI_IFR_CHECKBOX_DEFAULT
) == EFI_IFR_CHECKBOX_DEFAULT
) {
1146 // Set standard ID to Manufacture ID and Get DefaultName String ID
1148 VarDefaultId
= EFI_HII_DEFAULT_CLASS_STANDARD
;
1149 Status
= FindDefaultName (DefaultIdArray
, VarDefaultId
, &VarDefaultName
);
1150 if (EFI_ERROR (Status
)) {
1154 // Prepare new DefaultValue
1156 DefaultData
= (IFR_DEFAULT_DATA
*) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
1157 if (DefaultData
== NULL
) {
1158 Status
= EFI_OUT_OF_RESOURCES
;
1161 DefaultData
->OpCode
= IfrOpHdr
->OpCode
;
1162 DefaultData
->DefaultId
= VarDefaultId
;
1163 DefaultData
->DefaultName
= VarDefaultName
;
1164 DefaultData
->Value
= 1;
1166 // Add DefaultValue into current BlockData
1168 InsertDefaultValue (BlockData
, DefaultData
);
1171 if ((IfrCheckBox
->Flags
& EFI_IFR_CHECKBOX_DEFAULT_MFG
) == EFI_IFR_CHECKBOX_DEFAULT_MFG
) {
1173 // Set standard ID to Manufacture ID and Get DefaultName String ID
1175 VarDefaultId
= EFI_HII_DEFAULT_CLASS_MANUFACTURING
;
1176 Status
= FindDefaultName (DefaultIdArray
, VarDefaultId
, &VarDefaultName
);
1177 if (EFI_ERROR (Status
)) {
1181 // Prepare new DefaultValue
1183 DefaultData
= (IFR_DEFAULT_DATA
*) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
1184 if (DefaultData
== NULL
) {
1185 Status
= EFI_OUT_OF_RESOURCES
;
1188 DefaultData
->OpCode
= IfrOpHdr
->OpCode
;
1189 DefaultData
->DefaultId
= VarDefaultId
;
1190 DefaultData
->DefaultName
= VarDefaultName
;
1191 DefaultData
->Value
= 1;
1193 // Add DefaultValue into current BlockData
1195 InsertDefaultValue (BlockData
, DefaultData
);
1199 case EFI_IFR_STRING_OP
:
1201 // offset by question header
1202 // width MaxSize * sizeof (CHAR16)
1203 // no default value, only block array
1207 // String question is not in IFR Form. This IFR form is not valid.
1209 if (VarStorageData
->Size
== 0) {
1210 Status
= EFI_INVALID_PARAMETER
;
1214 // Check whether this question is for the requested varstore.
1216 IfrString
= (EFI_IFR_STRING
*) IfrOpHdr
;
1217 if (IfrString
->Question
.VarStoreId
!= VarStorageData
->VarStoreId
) {
1222 // Get Offset/Width by Question header and OneOf Flags
1224 VarOffset
= IfrString
->Question
.VarStoreInfo
.VarOffset
;
1225 VarWidth
= (UINT16
) (IfrString
->MaxSize
* sizeof (UINT16
));
1228 // Check whether this question is in requested block array.
1230 if (!BlockArrayCheck (RequestBlockArray
, VarOffset
, VarWidth
)) {
1232 // This question is not in the requested string. Skip it.
1238 // Check this var question is in the var storage
1240 if ((VarOffset
+ VarWidth
) > VarStorageData
->Size
) {
1241 Status
= EFI_INVALID_PARAMETER
;
1248 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
1249 if (BlockData
== NULL
) {
1250 Status
= EFI_OUT_OF_RESOURCES
;
1253 BlockData
->Offset
= VarOffset
;
1254 BlockData
->Width
= VarWidth
;
1255 BlockData
->QuestionId
= IfrString
->Question
.QuestionId
;
1256 BlockData
->OpCode
= IfrOpHdr
->OpCode
;
1257 InitializeListHead (&BlockData
->DefaultValueEntry
);
1260 // Add Block Data into VarStorageData BlockEntry
1262 InsertBlockData (&VarStorageData
->BlockEntry
, &BlockData
);
1265 // No default value for string.
1270 case EFI_IFR_PASSWORD_OP
:
1272 // offset by question header
1273 // width MaxSize * sizeof (CHAR16)
1274 // no default value, only block array
1278 // Password question is not in IFR Form. This IFR form is not valid.
1280 if (VarStorageData
->Size
== 0) {
1281 Status
= EFI_INVALID_PARAMETER
;
1285 // Check whether this question is for the requested varstore.
1287 IfrPassword
= (EFI_IFR_PASSWORD
*) IfrOpHdr
;
1288 if (IfrPassword
->Question
.VarStoreId
!= VarStorageData
->VarStoreId
) {
1293 // Get Offset/Width by Question header and OneOf Flags
1295 VarOffset
= IfrPassword
->Question
.VarStoreInfo
.VarOffset
;
1296 VarWidth
= (UINT16
) (IfrPassword
->MaxSize
* sizeof (UINT16
));
1299 // Check whether this question is in requested block array.
1301 if (!BlockArrayCheck (RequestBlockArray
, VarOffset
, VarWidth
)) {
1303 // This question is not in the requested string. Skip it.
1309 // Check this var question is in the var storage
1311 if ((VarOffset
+ VarWidth
) > VarStorageData
->Size
) {
1312 Status
= EFI_INVALID_PARAMETER
;
1319 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
1320 if (BlockData
== NULL
) {
1321 Status
= EFI_OUT_OF_RESOURCES
;
1324 BlockData
->Offset
= VarOffset
;
1325 BlockData
->Width
= VarWidth
;
1326 BlockData
->QuestionId
= IfrPassword
->Question
.QuestionId
;
1327 BlockData
->OpCode
= IfrOpHdr
->OpCode
;
1328 InitializeListHead (&BlockData
->DefaultValueEntry
);
1331 // Add Block Data into VarStorageData BlockEntry
1333 InsertBlockData (&VarStorageData
->BlockEntry
, &BlockData
);
1336 // No default value for string.
1341 case EFI_IFR_ONE_OF_OPTION_OP
:
1343 // No matched block data is ignored.
1345 if (BlockData
== NULL
|| BlockData
->Scope
== 0) {
1349 IfrOneOfOption
= (EFI_IFR_ONE_OF_OPTION
*) IfrOpHdr
;
1350 if (BlockData
->OpCode
== EFI_IFR_ORDERED_LIST_OP
) {
1352 // Get ordered list option data type.
1354 if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_8
|| IfrOneOfOption
->Type
== EFI_IFR_TYPE_BOOLEAN
) {
1356 } else if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_16
) {
1358 } else if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_32
) {
1360 } else if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_64
) {
1364 // Invalid ordered list option data type.
1366 Status
= EFI_INVALID_PARAMETER
;
1367 FreePool (BlockData
);
1372 // Calculate Ordered list QuestionId width.
1374 BlockData
->Width
= (UINT16
) (BlockData
->Width
* VarWidth
);
1376 // Check whether this question is in requested block array.
1378 if (!BlockArrayCheck (RequestBlockArray
, BlockData
->Offset
, BlockData
->Width
)) {
1380 // This question is not in the requested string. Skip it.
1382 FreePool (BlockData
);
1387 // Check this var question is in the var storage
1389 if ((BlockData
->Offset
+ BlockData
->Width
) > VarStorageData
->Size
) {
1390 Status
= EFI_INVALID_PARAMETER
;
1391 FreePool (BlockData
);
1395 // Add Block Data into VarStorageData BlockEntry
1397 InsertBlockData (&VarStorageData
->BlockEntry
, &BlockData
);
1399 // No default data for OrderedList.
1405 if ((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT
) == EFI_IFR_OPTION_DEFAULT
) {
1407 // Set standard ID to Manufacture ID and Get DefaultName String ID
1409 VarDefaultId
= EFI_HII_DEFAULT_CLASS_STANDARD
;
1410 Status
= FindDefaultName (DefaultIdArray
, VarDefaultId
, &VarDefaultName
);
1411 if (EFI_ERROR (Status
)) {
1415 // Prepare new DefaultValue
1417 DefaultData
= (IFR_DEFAULT_DATA
*) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
1418 if (DefaultData
== NULL
) {
1419 Status
= EFI_OUT_OF_RESOURCES
;
1422 DefaultData
->OpCode
= IfrOpHdr
->OpCode
;
1423 DefaultData
->DefaultId
= VarDefaultId
;
1424 DefaultData
->DefaultName
= VarDefaultName
;
1425 DefaultData
->Value
= IfrOneOfOption
->Value
.u64
;
1427 // Add DefaultValue into current BlockData
1429 InsertDefaultValue (BlockData
, DefaultData
);
1432 if ((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT_MFG
) == EFI_IFR_OPTION_DEFAULT_MFG
) {
1434 // Set default ID to Manufacture ID and Get DefaultName String ID
1436 VarDefaultId
= EFI_HII_DEFAULT_CLASS_MANUFACTURING
;
1437 Status
= FindDefaultName (DefaultIdArray
, VarDefaultId
, &VarDefaultName
);
1438 if (EFI_ERROR (Status
)) {
1442 // Prepare new DefaultValue
1444 DefaultData
= (IFR_DEFAULT_DATA
*) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
1445 if (DefaultData
== NULL
) {
1446 Status
= EFI_OUT_OF_RESOURCES
;
1449 DefaultData
->OpCode
= IfrOpHdr
->OpCode
;
1450 DefaultData
->DefaultId
= VarDefaultId
;
1451 DefaultData
->DefaultName
= VarDefaultName
;
1452 DefaultData
->Value
= IfrOneOfOption
->Value
.u64
;
1454 // Add DefaultValue into current BlockData
1456 InsertDefaultValue (BlockData
, DefaultData
);
1460 case EFI_IFR_DEFAULT_OP
:
1462 // Update Current BlockData to the default value.
1464 if (BlockData
== NULL
|| BlockData
->Scope
== 0) {
1466 // No matched block data is ignored.
1471 if (BlockData
->OpCode
== EFI_IFR_ORDERED_LIST_OP
) {
1473 // OrderedList Opcode is no default value.
1478 // Get the DefaultId and DefaultName String ID
1480 IfrDefault
= (EFI_IFR_DEFAULT
*) IfrOpHdr
;
1481 VarDefaultId
= IfrDefault
->DefaultId
;
1482 Status
= FindDefaultName (DefaultIdArray
, VarDefaultId
, &VarDefaultName
);
1483 if (EFI_ERROR (Status
)) {
1487 // Prepare new DefaultValue
1489 DefaultData
= (IFR_DEFAULT_DATA
*) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
1490 if (DefaultData
== NULL
) {
1491 Status
= EFI_OUT_OF_RESOURCES
;
1494 DefaultData
->OpCode
= IfrOpHdr
->OpCode
;
1495 DefaultData
->DefaultId
= VarDefaultId
;
1496 DefaultData
->DefaultName
= VarDefaultName
;
1497 DefaultData
->Value
= IfrDefault
->Value
.u64
;
1499 // Add DefaultValue into current BlockData
1501 InsertDefaultValue (BlockData
, DefaultData
);
1503 case EFI_IFR_END_OP
:
1505 // End Opcode is for Var question.
1507 if (BlockData
!= NULL
&& BlockData
->Scope
> 0) {
1512 if (BlockData
!= NULL
&& BlockData
->Scope
> 0) {
1513 BlockData
->Scope
= (UINT8
) (BlockData
->Scope
+ IfrOpHdr
->Scope
);
1518 IfrOffset
+= IfrOpHdr
->Length
;
1526 This function gets the full request string and full default value string by
1527 parsing IFR data in HII form packages.
1529 When Request points to NULL string, the request string and default value string
1530 for each varstore in form package will return.
1532 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
1533 @param DevicePath Device Path which Hii Config Access Protocol is registered.
1534 @param Request Pointer to a null-terminated Unicode string in
1535 <ConfigRequest> format. When it doesn't contain
1536 any RequestElement, it will be updated to return
1537 the full RequestElement retrieved from IFR data.
1538 If it points to NULL, the request string for the first
1539 varstore in form package will be merged into a
1540 <MultiConfigRequest> format string and return.
1541 @param AltCfgResp Pointer to a null-terminated Unicode string in
1542 <ConfigAltResp> format. When the pointer is to NULL,
1543 the full default value string retrieved from IFR data
1544 will return. When the pinter is to a string, the
1545 full default value string retrieved from IFR data
1546 will be merged into the input string and return.
1547 When Request points to NULL, the default value string
1548 for each varstore in form package will be merged into
1549 a <MultiConfigAltResp> format string and return.
1550 @param PointerProgress Optional parameter, it can be be NULL.
1551 When it is not NULL, if Request is NULL, it returns NULL.
1552 On return, points to a character in the Request
1553 string. Points to the string's null terminator if
1554 request was successful. Points to the most recent
1555 & before the first failing name / value pair (or
1556 the beginning of the string if the failure is in
1557 the first name / value pair) if the request was
1559 @retval EFI_SUCCESS The Results string is set to the full request string.
1560 And AltCfgResp contains all default value string.
1561 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
1562 @retval EFI_NOT_FOUND The varstore (Guid and Name) in Request string
1563 can't be found in Form package.
1564 @retval EFI_NOT_FOUND HiiPackage can't be got on the input HiiHandle.
1565 @retval EFI_INVALID_PARAMETER Request points to NULL.
1570 GetFullStringFromHiiFormPackages (
1571 IN HII_DATABASE_RECORD
*DataBaseRecord
,
1572 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
1573 IN OUT EFI_STRING
*Request
,
1574 IN OUT EFI_STRING
*AltCfgResp
,
1575 OUT EFI_STRING
*PointerProgress OPTIONAL
1579 UINT8
*HiiFormPackage
;
1582 IFR_BLOCK_DATA
*RequestBlockArray
;
1583 IFR_BLOCK_DATA
*BlockData
;
1584 IFR_BLOCK_DATA
*NextBlockData
;
1585 IFR_DEFAULT_DATA
*DefaultValueData
;
1586 IFR_DEFAULT_DATA
*DefaultId
;
1587 IFR_DEFAULT_DATA
*DefaultIdArray
;
1588 IFR_VARSTORAGE_DATA
*VarStorageData
;
1589 EFI_STRING DefaultAltCfgResp
;
1590 EFI_STRING FullConfigRequest
;
1591 EFI_STRING ConfigHdr
;
1595 EFI_STRING StringPtr
;
1596 EFI_STRING Progress
;
1602 LIST_ENTRY
*LinkData
;
1603 LIST_ENTRY
*LinkDefault
;
1606 if (DataBaseRecord
== NULL
|| DevicePath
== NULL
|| Request
== NULL
|| AltCfgResp
== NULL
) {
1607 return EFI_INVALID_PARAMETER
;
1611 // Initialize the local variables.
1613 RequestBlockArray
= NULL
;
1614 DefaultIdArray
= NULL
;
1615 VarStorageData
= NULL
;
1616 DefaultAltCfgResp
= NULL
;
1617 FullConfigRequest
= NULL
;
1622 HiiFormPackage
= NULL
;
1626 Progress
= *Request
;
1629 // 0. Get Hii Form Package by HiiHandle
1631 Status
= ExportFormPackages (
1633 DataBaseRecord
->Handle
,
1634 DataBaseRecord
->PackageList
,
1640 if (EFI_ERROR (Status
)) {
1644 HiiFormPackage
= AllocatePool (ResultSize
);
1645 if (HiiFormPackage
== NULL
) {
1646 Status
= EFI_OUT_OF_RESOURCES
;
1651 // Get HiiFormPackage by HiiHandle
1653 PackageSize
= ResultSize
;
1655 Status
= ExportFormPackages (
1657 DataBaseRecord
->Handle
,
1658 DataBaseRecord
->PackageList
,
1664 if (EFI_ERROR (Status
)) {
1669 // 1. Get the request block array by Request String when Request string containts the block array.
1672 if (*Request
!= NULL
) {
1673 StringPtr
= *Request
;
1677 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
1678 Status
= EFI_INVALID_PARAMETER
;
1681 StringPtr
+= StrLen (L
"GUID=");
1682 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&NAME=", StrLen (L
"&NAME=")) != 0) {
1685 if (*StringPtr
== L
'\0') {
1686 Status
= EFI_INVALID_PARAMETER
;
1689 StringPtr
+= StrLen (L
"&NAME=");
1690 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&PATH=", StrLen (L
"&PATH=")) != 0) {
1693 if (*StringPtr
== L
'\0') {
1694 Status
= EFI_INVALID_PARAMETER
;
1697 StringPtr
+= StrLen (L
"&PATH=");
1698 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
1702 // Check the following string &OFFSET=
1704 if (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) != 0) {
1705 Progress
= StringPtr
;
1706 Status
= EFI_INVALID_PARAMETER
;
1708 } else if (*StringPtr
== L
'\0') {
1710 // No request block is found.
1715 if (StringPtr
!= NULL
) {
1717 // Init RequestBlockArray
1719 RequestBlockArray
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
1720 if (RequestBlockArray
== NULL
) {
1721 Status
= EFI_OUT_OF_RESOURCES
;
1724 InitializeListHead (&RequestBlockArray
->Entry
);
1727 // Get the request Block array from the request string
1732 // Parse each <RequestElement> if exists
1733 // Only <BlockName> format is supported by this help function.
1734 // <BlockName> ::= &'OFFSET='<Number>&'WIDTH='<Number>
1736 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) == 0) {
1738 // Skip the OFFSET string
1740 Progress
= StringPtr
;
1741 StringPtr
+= StrLen (L
"&OFFSET=");
1745 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
1746 if (EFI_ERROR (Status
)) {
1753 (((Length
+ 1) / 2) < sizeof (UINT16
)) ? ((Length
+ 1) / 2) : sizeof (UINT16
)
1755 FreePool (TmpBuffer
);
1757 StringPtr
+= Length
;
1758 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
1759 Status
= EFI_INVALID_PARAMETER
;
1762 StringPtr
+= StrLen (L
"&WIDTH=");
1767 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
1768 if (EFI_ERROR (Status
)) {
1775 (((Length
+ 1) / 2) < sizeof (UINT16
)) ? ((Length
+ 1) / 2) : sizeof (UINT16
)
1777 FreePool (TmpBuffer
);
1779 StringPtr
+= Length
;
1780 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
1781 Status
= EFI_INVALID_PARAMETER
;
1788 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
1789 if (BlockData
== NULL
) {
1790 Status
= EFI_OUT_OF_RESOURCES
;
1793 BlockData
->Offset
= Offset
;
1794 BlockData
->Width
= Width
;
1795 InsertBlockData (&RequestBlockArray
->Entry
, &BlockData
);
1798 // Skip &VALUE string if &VALUE does exists.
1800 if (StrnCmp (StringPtr
, L
"&VALUE=", StrLen (L
"&VALUE=")) == 0) {
1801 StringPtr
+= StrLen (L
"&VALUE=");
1806 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
1807 if (EFI_ERROR (Status
)) {
1808 Status
= EFI_INVALID_PARAMETER
;
1812 StringPtr
+= Length
;
1813 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
1814 Status
= EFI_INVALID_PARAMETER
;
1819 // If '\0', parsing is finished.
1821 if (*StringPtr
== 0) {
1827 // Merge the requested block data.
1829 Link
= RequestBlockArray
->Entry
.ForwardLink
;
1830 while ((Link
!= &RequestBlockArray
->Entry
) && (Link
->ForwardLink
!= &RequestBlockArray
->Entry
)) {
1831 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
1832 NextBlockData
= BASE_CR (Link
->ForwardLink
, IFR_BLOCK_DATA
, Entry
);
1833 if ((NextBlockData
->Offset
>= BlockData
->Offset
) && (NextBlockData
->Offset
<= (BlockData
->Offset
+ BlockData
->Width
))) {
1834 if ((NextBlockData
->Offset
+ NextBlockData
->Width
) > (BlockData
->Offset
+ BlockData
->Width
)) {
1835 BlockData
->Width
= (UINT16
) (NextBlockData
->Offset
+ NextBlockData
->Width
- BlockData
->Offset
);
1837 RemoveEntryList (Link
->ForwardLink
);
1838 FreePool (NextBlockData
);
1841 Link
= Link
->ForwardLink
;
1846 // 2. Parse FormPackage to get BlockArray and DefaultId Array for the request BlockArray.
1850 // Initialize DefaultIdArray to store the map between DeaultId and DefaultName
1852 DefaultIdArray
= (IFR_DEFAULT_DATA
*) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
1853 if (DefaultIdArray
== NULL
) {
1854 Status
= EFI_OUT_OF_RESOURCES
;
1857 InitializeListHead (&DefaultIdArray
->Entry
);
1860 // Initialize VarStorageData to store the var store Block and Default value information.
1862 VarStorageData
= (IFR_VARSTORAGE_DATA
*) AllocateZeroPool (sizeof (IFR_VARSTORAGE_DATA
));
1863 if (VarStorageData
== NULL
) {
1864 Status
= EFI_OUT_OF_RESOURCES
;
1867 InitializeListHead (&VarStorageData
->Entry
);
1868 InitializeListHead (&VarStorageData
->BlockEntry
);
1871 // Parse the opcode in form pacakge to get the default setting.
1873 Status
= ParseIfrData (HiiFormPackage
, (UINT32
) PackageSize
, *Request
, RequestBlockArray
, VarStorageData
, DefaultIdArray
);
1874 if (EFI_ERROR (Status
)) {
1879 // No requested varstore in IFR data and directly return
1881 if (VarStorageData
->Size
== 0) {
1882 Status
= EFI_SUCCESS
;
1887 // 3. Construct Request Element (Block Name) for 2.1 and 2.2 case.
1891 // Construct <ConfigHdr> : "GUID=...&NAME=...&PATH=..." by VarStorageData Guid, Name and DriverHandle
1893 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*) &VarStorageData
->Guid
, 1, &GuidStr
);
1894 GenerateSubStr (L
"NAME=", StrLen (VarStorageData
->Name
) * sizeof (CHAR16
), (VOID
*) VarStorageData
->Name
, 2, &NameStr
);
1897 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) DevicePath
),
1898 (VOID
*) DevicePath
,
1902 Length
= StrLen (GuidStr
);
1903 Length
= Length
+ StrLen (NameStr
);
1904 Length
= Length
+ StrLen (PathStr
) + 1;
1905 ConfigHdr
= AllocateZeroPool (Length
* sizeof (CHAR16
));
1906 if (ConfigHdr
== NULL
) {
1907 Status
= EFI_OUT_OF_RESOURCES
;
1910 StrCpy (ConfigHdr
, GuidStr
);
1911 StrCat (ConfigHdr
, NameStr
);
1912 StrCat (ConfigHdr
, PathStr
);
1915 // Remove the last character L'&'
1917 *(ConfigHdr
+ StrLen (ConfigHdr
) - 1) = L
'\0';
1919 if (RequestBlockArray
== NULL
) {
1921 // Append VarStorageData BlockEntry into *Request string
1922 // Now support only one varstore in a form package.
1926 // Go through all VarStorageData Entry and get BlockEntry for each one for the multiple varstore in a single form package
1927 // Then construct them all to return MultiRequest string : ConfigHdr BlockConfig
1931 // Compute the length of the entire request starting with <ConfigHdr> and a
1935 Length
= StrLen (ConfigHdr
) + 1;
1937 for (Link
= VarStorageData
->BlockEntry
.ForwardLink
; Link
!= &VarStorageData
->BlockEntry
; Link
= Link
->ForwardLink
) {
1939 // Add <BlockName> length for each Offset/Width pair
1941 // <BlockName> ::= &OFFSET=1234&WIDTH=1234
1942 // | 8 | 4 | 7 | 4 |
1945 Length
= Length
+ (8 + 4 + 7 + 4);
1949 // No any request block data is found. The request string can't be constructed.
1952 Status
= EFI_SUCCESS
;
1957 // Allocate buffer for the entire <ConfigRequest>
1959 FullConfigRequest
= AllocateZeroPool (Length
* sizeof (CHAR16
));
1960 if (FullConfigRequest
== NULL
) {
1961 Status
= EFI_OUT_OF_RESOURCES
;
1964 StringPtr
= FullConfigRequest
;
1967 // Start with <ConfigHdr>
1969 StrCpy (StringPtr
, ConfigHdr
);
1970 StringPtr
+= StrLen (StringPtr
);
1973 // Loop through all the Offset/Width pairs and append them to ConfigRequest
1975 for (Link
= VarStorageData
->BlockEntry
.ForwardLink
; Link
!= &VarStorageData
->BlockEntry
; Link
= Link
->ForwardLink
) {
1976 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
1978 // Append &OFFSET=XXXX&WIDTH=YYYY\0
1982 (8 + 4 + 7 + 4 + 1) * sizeof (CHAR16
),
1983 L
"&OFFSET=%04X&WIDTH=%04X",
1987 StringPtr
+= StrLen (StringPtr
);
1990 // Set to the got full request string.
1992 HiiToLower (FullConfigRequest
);
1993 if (*Request
!= NULL
) {
1994 FreePool (*Request
);
1996 *Request
= FullConfigRequest
;
2000 // 4. Construct Default Value string in AltResp according to request element.
2001 // Go through all VarStorageData Entry and get the DefaultId array for each one
2002 // Then construct them all to : ConfigHdr AltConfigHdr ConfigBody AltConfigHdr ConfigBody
2006 // Add length for <ConfigHdr> + '\0'
2008 Length
= StrLen (ConfigHdr
) + 1;
2010 for (Link
= DefaultIdArray
->Entry
.ForwardLink
; Link
!= &DefaultIdArray
->Entry
; Link
= Link
->ForwardLink
) {
2011 DefaultId
= BASE_CR (Link
, IFR_DEFAULT_DATA
, Entry
);
2013 // Add length for "&<ConfigHdr>&ALTCFG=XXXX"
2014 // |1| StrLen (ConfigHdr) | 8 | 4 |
2016 Length
+= (1 + StrLen (ConfigHdr
) + 8 + 4);
2018 for (LinkData
= VarStorageData
->BlockEntry
.ForwardLink
; LinkData
!= &VarStorageData
->BlockEntry
; LinkData
= LinkData
->ForwardLink
) {
2019 BlockData
= BASE_CR (LinkData
, IFR_BLOCK_DATA
, Entry
);
2020 for (LinkDefault
= BlockData
->DefaultValueEntry
.ForwardLink
; LinkDefault
!= &BlockData
->DefaultValueEntry
; LinkDefault
= LinkDefault
->ForwardLink
) {
2021 DefaultValueData
= BASE_CR (LinkDefault
, IFR_DEFAULT_DATA
, Entry
);
2022 if (DefaultValueData
->DefaultId
== DefaultId
->DefaultId
) {
2024 // Add length for "&OFFSET=XXXX&WIDTH=YYYY&VALUE=zzzzzzzzzzzz"
2025 // | 8 | 4 | 7 | 4 | 7 | Width * 2 |
2027 Length
+= (8 + 4 + 7 + 4 + 7 + BlockData
->Width
* 2);
2035 // No default value is found. The default string doesn't exist.
2038 Status
= EFI_SUCCESS
;
2043 // Allocate buffer for the entire <DefaultAltCfgResp>
2045 DefaultAltCfgResp
= AllocateZeroPool (Length
* sizeof (CHAR16
));
2046 if (DefaultAltCfgResp
== NULL
) {
2047 Status
= EFI_OUT_OF_RESOURCES
;
2050 StringPtr
= DefaultAltCfgResp
;
2053 // Start with <ConfigHdr>
2055 StrCpy (StringPtr
, ConfigHdr
);
2056 StringPtr
+= StrLen (StringPtr
);
2058 for (Link
= DefaultIdArray
->Entry
.ForwardLink
; Link
!= &DefaultIdArray
->Entry
; Link
= Link
->ForwardLink
) {
2059 DefaultId
= BASE_CR (Link
, IFR_DEFAULT_DATA
, Entry
);
2061 // Add <AltConfigHdr> of the form "&<ConfigHdr>&ALTCFG=XXXX\0"
2062 // |1| StrLen (ConfigHdr) | 8 | 4 |
2066 (1 + StrLen (ConfigHdr
) + 8 + 4 + 1) * sizeof (CHAR16
),
2069 DefaultId
->DefaultName
2071 StringPtr
+= StrLen (StringPtr
);
2073 for (LinkData
= VarStorageData
->BlockEntry
.ForwardLink
; LinkData
!= &VarStorageData
->BlockEntry
; LinkData
= LinkData
->ForwardLink
) {
2074 BlockData
= BASE_CR (LinkData
, IFR_BLOCK_DATA
, Entry
);
2075 for (LinkDefault
= BlockData
->DefaultValueEntry
.ForwardLink
; LinkDefault
!= &BlockData
->DefaultValueEntry
; LinkDefault
= LinkDefault
->ForwardLink
) {
2076 DefaultValueData
= BASE_CR (LinkDefault
, IFR_DEFAULT_DATA
, Entry
);
2077 if (DefaultValueData
->DefaultId
== DefaultId
->DefaultId
) {
2079 // Add <BlockConfig>
2080 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>
2084 (8 + 4 + 7 + 4 + 7 + 1) * sizeof (CHAR16
),
2085 L
"&OFFSET=%04X&WIDTH=%04X&VALUE=",
2089 StringPtr
+= StrLen (StringPtr
);
2092 // Convert Value to a hex string in "%x" format
2093 // NOTE: This is in the opposite byte that GUID and PATH use
2095 Width
= BlockData
->Width
;
2096 TmpBuffer
= (UINT8
*) &(DefaultValueData
->Value
);
2097 for (; Width
> 0; Width
--) {
2098 StringPtr
+= UnicodeValueToString (StringPtr
, PREFIX_ZERO
| RADIX_HEX
, TmpBuffer
[Width
- 1], 2);
2104 HiiToLower (DefaultAltCfgResp
);
2107 // 5. Merge string into the input AltCfgResp if the iput *AltCfgResp is not NULL.
2109 if (*AltCfgResp
!= NULL
&& DefaultAltCfgResp
!= NULL
) {
2110 Status
= MergeDefaultString (AltCfgResp
, DefaultAltCfgResp
);
2111 FreePool (DefaultAltCfgResp
);
2112 } else if (*AltCfgResp
== NULL
) {
2113 *AltCfgResp
= DefaultAltCfgResp
;
2117 if (RequestBlockArray
!= NULL
) {
2119 // Free Link Array RequestBlockArray
2121 while (!IsListEmpty (&RequestBlockArray
->Entry
)) {
2122 BlockData
= BASE_CR (RequestBlockArray
->Entry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
2123 RemoveEntryList (&BlockData
->Entry
);
2124 FreePool (BlockData
);
2127 FreePool (RequestBlockArray
);
2130 if (VarStorageData
!= NULL
) {
2132 // Free link array VarStorageData
2134 while (!IsListEmpty (&VarStorageData
->BlockEntry
)) {
2135 BlockData
= BASE_CR (VarStorageData
->BlockEntry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
2136 RemoveEntryList (&BlockData
->Entry
);
2138 // Free default value link array
2140 while (!IsListEmpty (&BlockData
->DefaultValueEntry
)) {
2141 DefaultValueData
= BASE_CR (BlockData
->DefaultValueEntry
.ForwardLink
, IFR_DEFAULT_DATA
, Entry
);
2142 RemoveEntryList (&DefaultValueData
->Entry
);
2143 FreePool (DefaultValueData
);
2145 FreePool (BlockData
);
2147 FreePool (VarStorageData
);
2150 if (DefaultIdArray
!= NULL
) {
2152 // Free DefaultId Array
2154 while (!IsListEmpty (&DefaultIdArray
->Entry
)) {
2155 DefaultId
= BASE_CR (DefaultIdArray
->Entry
.ForwardLink
, IFR_DEFAULT_DATA
, Entry
);
2156 RemoveEntryList (&DefaultId
->Entry
);
2157 FreePool (DefaultId
);
2159 FreePool (DefaultIdArray
);
2163 // Free the allocated string
2165 if (GuidStr
!= NULL
) {
2168 if (NameStr
!= NULL
) {
2171 if (PathStr
!= NULL
) {
2174 if (ConfigHdr
!= NULL
) {
2175 FreePool (ConfigHdr
);
2179 // Free Pacakge data
2181 if (HiiFormPackage
!= NULL
) {
2182 FreePool (HiiFormPackage
);
2185 if (PointerProgress
!= NULL
) {
2186 if (*Request
== NULL
) {
2187 *PointerProgress
= NULL
;
2188 } else if (EFI_ERROR (Status
)) {
2189 *PointerProgress
= Progress
;
2191 *PointerProgress
= *Request
+ StrLen (*Request
);
2199 This function allows a caller to extract the current configuration
2200 for one or more named elements from one or more drivers.
2202 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
2204 @param Request A null-terminated Unicode string in
2205 <MultiConfigRequest> format.
2206 @param Progress On return, points to a character in the Request
2207 string. Points to the string's null terminator if
2208 request was successful. Points to the most recent
2209 & before the first failing name / value pair (or
2210 the beginning of the string if the failure is in
2211 the first name / value pair) if the request was
2213 @param Results Null-terminated Unicode string in
2214 <MultiConfigAltResp> format which has all values
2215 filled in for the names in the Request string.
2216 String to be allocated by the called function.
2218 @retval EFI_SUCCESS The Results string is filled with the values
2219 corresponding to all requested names.
2220 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
2221 results that must be stored awaiting possible
2223 @retval EFI_NOT_FOUND Routing data doesn't match any known driver.
2224 Progress set to the "G" in "GUID" of the routing
2225 header that doesn't match. Note: There is no
2226 requirement that all routing data be validated
2227 before any configuration extraction.
2228 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Request
2229 parameter would result in this type of error. The
2230 Progress parameter is set to NULL.
2231 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set to most recent &
2232 before the error or the beginning of the string.
2233 @retval EFI_INVALID_PARAMETER Unknown name. Progress points to the & before the
2239 HiiConfigRoutingExtractConfig (
2240 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
2241 IN CONST EFI_STRING Request
,
2242 OUT EFI_STRING
*Progress
,
2243 OUT EFI_STRING
*Results
2246 HII_DATABASE_PRIVATE_DATA
*Private
;
2247 EFI_STRING StringPtr
;
2248 EFI_STRING ConfigRequest
;
2250 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
2251 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
2254 HII_DATABASE_RECORD
*Database
;
2255 UINT8
*DevicePathPkg
;
2256 UINT8
*CurrentDevicePath
;
2257 EFI_HANDLE DriverHandle
;
2258 EFI_HII_HANDLE HiiHandle
;
2259 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
2260 EFI_STRING AccessProgress
;
2261 EFI_STRING AccessResults
;
2262 EFI_STRING DefaultResults
;
2263 BOOLEAN FirstElement
;
2264 BOOLEAN IfrDataParsedFlag
;
2266 if (This
== NULL
|| Progress
== NULL
|| Results
== NULL
) {
2267 return EFI_INVALID_PARAMETER
;
2270 if (Request
== NULL
) {
2272 return EFI_INVALID_PARAMETER
;
2275 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
2276 StringPtr
= Request
;
2277 *Progress
= StringPtr
;
2278 DefaultResults
= NULL
;
2279 ConfigRequest
= NULL
;
2280 Status
= EFI_SUCCESS
;
2281 AccessResults
= NULL
;
2283 IfrDataParsedFlag
= FALSE
;
2286 // The first element of <MultiConfigRequest> should be
2287 // <GuidHdr>, which is in 'GUID='<Guid> syntax.
2289 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
2290 return EFI_INVALID_PARAMETER
;
2293 FirstElement
= TRUE
;
2296 // Allocate a fix length of memory to store Results. Reallocate memory for
2297 // Results if this fix length is insufficient.
2299 *Results
= (EFI_STRING
) AllocateZeroPool (MAX_STRING_LENGTH
);
2300 if (*Results
== NULL
) {
2301 return EFI_OUT_OF_RESOURCES
;
2304 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) == 0) {
2306 // If parsing error, set Progress to the beginning of the <MultiConfigRequest>
2307 // or most recent & before the error.
2309 if (StringPtr
== Request
) {
2310 *Progress
= StringPtr
;
2312 *Progress
= StringPtr
- 1;
2316 // Process each <ConfigRequest> of <MultiConfigRequest>
2318 Length
= CalculateConfigStringLen (StringPtr
);
2319 ConfigRequest
= AllocateCopyPool ((Length
+ 1) * sizeof (CHAR16
), StringPtr
);
2320 if (ConfigRequest
== NULL
) {
2321 Status
= EFI_OUT_OF_RESOURCES
;
2324 *(ConfigRequest
+ Length
) = 0;
2327 // Get the UEFI device path
2329 Status
= GetDevicePath (ConfigRequest
, (UINT8
**) &DevicePath
);
2330 if (EFI_ERROR (Status
)) {
2335 // Find driver which matches the routing data.
2337 DriverHandle
= NULL
;
2340 for (Link
= Private
->DatabaseList
.ForwardLink
;
2341 Link
!= &Private
->DatabaseList
;
2342 Link
= Link
->ForwardLink
2344 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
2345 if ((DevicePathPkg
= Database
->PackageList
->DevicePathPkg
) != NULL
) {
2346 CurrentDevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
2350 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) CurrentDevicePath
)
2352 DriverHandle
= Database
->DriverHandle
;
2353 HiiHandle
= Database
->Handle
;
2360 // Try to find driver handle by device path.
2362 if (DriverHandle
== NULL
) {
2363 TempDevicePath
= DevicePath
;
2364 Status
= gBS
->LocateDevicePath (
2365 &gEfiDevicePathProtocolGuid
,
2369 if (EFI_ERROR (Status
) || (DriverHandle
== NULL
)) {
2371 // Routing data does not match any known driver.
2372 // Set Progress to the 'G' in "GUID" of the routing header.
2374 *Progress
= StringPtr
;
2375 Status
= EFI_NOT_FOUND
;
2381 // Check whether ConfigRequest contains request string OFFSET/WIDTH
2383 IfrDataParsedFlag
= FALSE
;
2384 if ((HiiHandle
!= NULL
) && (StrStr (ConfigRequest
, L
"&OFFSET=") == NULL
)) {
2386 // Get the full request string from IFR when HiiPackage is registered to HiiHandle
2388 IfrDataParsedFlag
= TRUE
;
2389 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &ConfigRequest
, &DefaultResults
, &AccessProgress
);
2390 if (EFI_ERROR (Status
)) {
2392 // AccessProgress indicates the parsing progress on <ConfigRequest>.
2393 // Map it to the progress on <MultiConfigRequest> then return it.
2395 *Progress
= StrStr (StringPtr
, AccessProgress
);
2399 // Not any request block is found.
2401 if (StrStr (ConfigRequest
, L
"&OFFSET=") == NULL
) {
2402 AccessResults
= AllocateCopyPool (StrSize (ConfigRequest
), ConfigRequest
);
2403 goto NextConfigString
;
2408 // Call corresponding ConfigAccess protocol to extract settings
2410 Status
= gBS
->HandleProtocol (
2412 &gEfiHiiConfigAccessProtocolGuid
,
2413 (VOID
**) &ConfigAccess
2415 ASSERT_EFI_ERROR (Status
);
2417 Status
= ConfigAccess
->ExtractConfig (
2423 if (EFI_ERROR (Status
)) {
2425 // AccessProgress indicates the parsing progress on <ConfigRequest>.
2426 // Map it to the progress on <MultiConfigRequest> then return it.
2428 *Progress
= StrStr (StringPtr
, AccessProgress
);
2433 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'
2434 // which seperates the first <ConfigAltResp> and the following ones.
2436 ASSERT (*AccessProgress
== 0);
2439 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
2441 if (!IfrDataParsedFlag
&& HiiHandle
!= NULL
) {
2442 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &ConfigRequest
, &DefaultResults
, NULL
);
2443 ASSERT_EFI_ERROR (Status
);
2446 FreePool (DevicePath
);
2449 if (DefaultResults
!= NULL
) {
2450 Status
= MergeDefaultString (&AccessResults
, DefaultResults
);
2451 ASSERT_EFI_ERROR (Status
);
2452 FreePool (DefaultResults
);
2453 DefaultResults
= NULL
;
2457 if (!FirstElement
) {
2458 Status
= AppendToMultiString (Results
, L
"&");
2459 ASSERT_EFI_ERROR (Status
);
2462 Status
= AppendToMultiString (Results
, AccessResults
);
2463 ASSERT_EFI_ERROR (Status
);
2465 FirstElement
= FALSE
;
2467 FreePool (AccessResults
);
2468 AccessResults
= NULL
;
2469 FreePool (ConfigRequest
);
2470 ConfigRequest
= NULL
;
2473 // Go to next <ConfigRequest> (skip '&').
2475 StringPtr
+= Length
;
2476 if (*StringPtr
== 0) {
2477 *Progress
= StringPtr
;
2485 if (EFI_ERROR (Status
)) {
2486 FreePool (*Results
);
2490 if (ConfigRequest
!= NULL
) {
2491 FreePool (ConfigRequest
);
2494 if (AccessResults
!= NULL
) {
2495 FreePool (AccessResults
);
2498 if (DefaultResults
!= NULL
) {
2499 FreePool (DefaultResults
);
2502 if (DevicePath
!= NULL
) {
2503 FreePool (DevicePath
);
2511 This function allows the caller to request the current configuration for the
2512 entirety of the current HII database and returns the data in a
2513 null-terminated Unicode string.
2515 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
2517 @param Results Null-terminated Unicode string in
2518 <MultiConfigAltResp> format which has all values
2519 filled in for the names in the Request string.
2520 String to be allocated by the called function.
2521 De-allocation is up to the caller.
2523 @retval EFI_SUCCESS The Results string is filled with the values
2524 corresponding to all requested names.
2525 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
2526 results that must be stored awaiting possible
2528 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Results
2529 parameter would result in this type of error.
2534 HiiConfigRoutingExportConfig (
2535 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
2536 OUT EFI_STRING
*Results
2540 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
2541 EFI_STRING AccessResults
;
2542 EFI_STRING Progress
;
2543 EFI_STRING StringPtr
;
2544 EFI_STRING ConfigRequest
;
2546 EFI_HANDLE
*ConfigAccessHandles
;
2547 UINTN NumberConfigAccessHandles
;
2548 BOOLEAN FirstElement
;
2549 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
2550 EFI_HII_HANDLE HiiHandle
;
2551 EFI_STRING DefaultResults
;
2552 HII_DATABASE_PRIVATE_DATA
*Private
;
2554 HII_DATABASE_RECORD
*Database
;
2555 UINT8
*DevicePathPkg
;
2556 UINT8
*CurrentDevicePath
;
2557 BOOLEAN IfrDataParsedFlag
;
2559 if (This
== NULL
|| Results
== NULL
) {
2560 return EFI_INVALID_PARAMETER
;
2563 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
2566 // Allocate a fix length of memory to store Results. Reallocate memory for
2567 // Results if this fix length is insufficient.
2569 *Results
= (EFI_STRING
) AllocateZeroPool (MAX_STRING_LENGTH
);
2570 if (*Results
== NULL
) {
2571 return EFI_OUT_OF_RESOURCES
;
2574 NumberConfigAccessHandles
= 0;
2575 Status
= gBS
->LocateHandleBuffer (
2577 &gEfiHiiConfigAccessProtocolGuid
,
2579 &NumberConfigAccessHandles
,
2580 &ConfigAccessHandles
2582 if (EFI_ERROR (Status
)) {
2586 FirstElement
= TRUE
;
2588 for (Index
= 0; Index
< NumberConfigAccessHandles
; Index
++) {
2589 Status
= gBS
->HandleProtocol (
2590 ConfigAccessHandles
[Index
],
2591 &gEfiHiiConfigAccessProtocolGuid
,
2592 (VOID
**) &ConfigAccess
2594 if (EFI_ERROR (Status
)) {
2599 // Get DevicePath and HiiHandle for this ConfigAccess driver handle
2601 IfrDataParsedFlag
= FALSE
;
2604 DefaultResults
= NULL
;
2606 ConfigRequest
= NULL
;
2607 DevicePath
= DevicePathFromHandle (ConfigAccessHandles
[Index
]);
2608 if (DevicePath
!= NULL
) {
2609 for (Link
= Private
->DatabaseList
.ForwardLink
;
2610 Link
!= &Private
->DatabaseList
;
2611 Link
= Link
->ForwardLink
2613 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
2614 if ((DevicePathPkg
= Database
->PackageList
->DevicePathPkg
) != NULL
) {
2615 CurrentDevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
2619 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) CurrentDevicePath
)
2621 HiiHandle
= Database
->Handle
;
2628 Status
= ConfigAccess
->ExtractConfig (
2634 if (EFI_ERROR (Status
)) {
2636 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
2638 if (HiiHandle
!= NULL
&& DevicePath
!= NULL
) {
2639 IfrDataParsedFlag
= TRUE
;
2640 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &ConfigRequest
, &DefaultResults
, NULL
);
2642 // Get the full request string to get the Current setting again.
2644 if (!EFI_ERROR (Status
) && ConfigRequest
!= NULL
) {
2645 Status
= ConfigAccess
->ExtractConfig (
2651 FreePool (ConfigRequest
);
2653 Status
= EFI_NOT_FOUND
;
2658 if (!EFI_ERROR (Status
)) {
2660 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
2662 if (!IfrDataParsedFlag
&& HiiHandle
!= NULL
&& DevicePath
!= NULL
) {
2663 StringPtr
= StrStr (AccessResults
, L
"&GUID=");
2664 if (StringPtr
!= NULL
) {
2667 if (StrStr (AccessResults
, L
"&OFFSET=") != NULL
) {
2668 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &AccessResults
, &DefaultResults
, NULL
);
2669 ASSERT_EFI_ERROR (Status
);
2671 if (StringPtr
!= NULL
) {
2676 // Merge the default sting from IFR code into the got setting from driver.
2678 if (DefaultResults
!= NULL
) {
2679 Status
= MergeDefaultString (&AccessResults
, DefaultResults
);
2680 ASSERT_EFI_ERROR (Status
);
2681 FreePool (DefaultResults
);
2682 DefaultResults
= NULL
;
2686 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'
2687 // which seperates the first <ConfigAltResp> and the following ones.
2689 if (!FirstElement
) {
2690 Status
= AppendToMultiString (Results
, L
"&");
2691 ASSERT_EFI_ERROR (Status
);
2694 Status
= AppendToMultiString (Results
, AccessResults
);
2695 ASSERT_EFI_ERROR (Status
);
2697 FirstElement
= FALSE
;
2699 FreePool (AccessResults
);
2700 AccessResults
= NULL
;
2703 FreePool (ConfigAccessHandles
);
2710 This function processes the results of processing forms and routes it to the
2711 appropriate handlers or storage.
2713 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
2715 @param Configuration A null-terminated Unicode string in
2716 <MulltiConfigResp> format.
2717 @param Progress A pointer to a string filled in with the offset of
2718 the most recent & before the first failing name /
2719 value pair (or the beginning of the string if the
2720 failure is in the first name / value pair) or the
2721 terminating NULL if all was successful.
2723 @retval EFI_SUCCESS The results have been distributed or are awaiting
2725 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
2726 results that must be stored awaiting possible
2728 @retval EFI_INVALID_PARAMETER Passing in a NULL for the Configuration parameter
2729 would result in this type of error.
2730 @retval EFI_NOT_FOUND Target for the specified routing data was not
2736 HiiConfigRoutingRouteConfig (
2737 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
2738 IN CONST EFI_STRING Configuration
,
2739 OUT EFI_STRING
*Progress
2742 HII_DATABASE_PRIVATE_DATA
*Private
;
2743 EFI_STRING StringPtr
;
2744 EFI_STRING ConfigResp
;
2747 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
2748 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
2750 HII_DATABASE_RECORD
*Database
;
2751 UINT8
*DevicePathPkg
;
2752 UINT8
*CurrentDevicePath
;
2753 EFI_HANDLE DriverHandle
;
2754 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
2755 EFI_STRING AccessProgress
;
2757 if (This
== NULL
|| Progress
== NULL
) {
2758 return EFI_INVALID_PARAMETER
;
2761 if (Configuration
== NULL
) {
2763 return EFI_INVALID_PARAMETER
;
2766 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
2767 StringPtr
= Configuration
;
2768 *Progress
= StringPtr
;
2771 // The first element of <MultiConfigResp> should be
2772 // <GuidHdr>, which is in 'GUID='<Guid> syntax.
2774 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
2775 return EFI_INVALID_PARAMETER
;
2778 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) == 0) {
2780 // If parsing error, set Progress to the beginning of the <MultiConfigResp>
2781 // or most recent & before the error.
2783 if (StringPtr
== Configuration
) {
2784 *Progress
= StringPtr
;
2786 *Progress
= StringPtr
- 1;
2790 // Process each <ConfigResp> of <MultiConfigResp>
2792 Length
= CalculateConfigStringLen (StringPtr
);
2793 ConfigResp
= AllocateCopyPool ((Length
+ 1) * sizeof (CHAR16
), StringPtr
);
2794 if (ConfigResp
== NULL
) {
2795 return EFI_OUT_OF_RESOURCES
;
2798 // Append '\0' to the end of ConfigRequest
2800 *(ConfigResp
+ Length
) = 0;
2803 // Get the UEFI device path
2805 Status
= GetDevicePath (ConfigResp
, (UINT8
**) &DevicePath
);
2806 if (EFI_ERROR (Status
)) {
2807 FreePool (ConfigResp
);
2812 // Find driver which matches the routing data.
2814 DriverHandle
= NULL
;
2815 for (Link
= Private
->DatabaseList
.ForwardLink
;
2816 Link
!= &Private
->DatabaseList
;
2817 Link
= Link
->ForwardLink
2819 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
2821 if ((DevicePathPkg
= Database
->PackageList
->DevicePathPkg
) != NULL
) {
2822 CurrentDevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
2826 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) CurrentDevicePath
)
2828 DriverHandle
= Database
->DriverHandle
;
2835 // Try to find driver handle by device path.
2837 if (DriverHandle
== NULL
) {
2838 TempDevicePath
= DevicePath
;
2839 Status
= gBS
->LocateDevicePath (
2840 &gEfiDevicePathProtocolGuid
,
2844 if (EFI_ERROR (Status
) || (DriverHandle
== NULL
)) {
2846 // Routing data does not match any known driver.
2847 // Set Progress to the 'G' in "GUID" of the routing header.
2849 FreePool (DevicePath
);
2850 *Progress
= StringPtr
;
2851 FreePool (ConfigResp
);
2852 return EFI_NOT_FOUND
;
2856 FreePool (DevicePath
);
2859 // Call corresponding ConfigAccess protocol to route settings
2861 Status
= gBS
->HandleProtocol (
2863 &gEfiHiiConfigAccessProtocolGuid
,
2864 (VOID
**) &ConfigAccess
2866 ASSERT_EFI_ERROR (Status
);
2868 Status
= ConfigAccess
->RouteConfig (
2874 if (EFI_ERROR (Status
)) {
2876 // AccessProgress indicates the parsing progress on <ConfigResp>.
2877 // Map it to the progress on <MultiConfigResp> then return it.
2879 *Progress
= StrStr (StringPtr
, AccessProgress
);
2881 FreePool (ConfigResp
);
2885 FreePool (ConfigResp
);
2889 // Go to next <ConfigResp> (skip '&').
2891 StringPtr
+= Length
;
2892 if (*StringPtr
== 0) {
2893 *Progress
= StringPtr
;
2906 This helper function is to be called by drivers to map configuration data
2907 stored in byte array ("block") formats such as UEFI Variables into current
2908 configuration strings.
2910 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
2912 @param ConfigRequest A null-terminated Unicode string in
2913 <ConfigRequest> format.
2914 @param Block Array of bytes defining the block's configuration.
2915 @param BlockSize Length in bytes of Block.
2916 @param Config Filled-in configuration string. String allocated
2917 by the function. Returned only if call is
2918 successful. It is <ConfigResp> string format.
2919 @param Progress A pointer to a string filled in with the offset of
2920 the most recent & before the first failing
2921 name/value pair (or the beginning of the string if
2922 the failure is in the first name / value pair) or
2923 the terminating NULL if all was successful.
2925 @retval EFI_SUCCESS The request succeeded. Progress points to the null
2926 terminator at the end of the ConfigRequest
2928 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress
2929 points to the first character of ConfigRequest.
2930 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigRequest or
2931 Block parameter would result in this type of
2932 error. Progress points to the first character of
2934 @retval EFI_DEVICE_ERROR Block not large enough. Progress undefined.
2935 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted string.
2936 Block is left updated and Progress points at
2937 the "&" preceding the first non-<BlockName>.
2943 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
2944 IN CONST EFI_STRING ConfigRequest
,
2945 IN CONST UINT8
*Block
,
2946 IN CONST UINTN BlockSize
,
2947 OUT EFI_STRING
*Config
,
2948 OUT EFI_STRING
*Progress
2951 HII_DATABASE_PRIVATE_DATA
*Private
;
2952 EFI_STRING StringPtr
;
2960 EFI_STRING ValueStr
;
2961 EFI_STRING ConfigElement
;
2966 if (This
== NULL
|| Progress
== NULL
|| Config
== NULL
) {
2967 return EFI_INVALID_PARAMETER
;
2970 if (Block
== NULL
|| ConfigRequest
== NULL
) {
2971 *Progress
= ConfigRequest
;
2972 return EFI_INVALID_PARAMETER
;
2976 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
2977 ASSERT (Private
!= NULL
);
2979 StringPtr
= ConfigRequest
;
2982 ConfigElement
= NULL
;
2985 // Allocate a fix length of memory to store Results. Reallocate memory for
2986 // Results if this fix length is insufficient.
2988 *Config
= (EFI_STRING
) AllocateZeroPool (MAX_STRING_LENGTH
);
2989 if (*Config
== NULL
) {
2990 return EFI_OUT_OF_RESOURCES
;
2996 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
2997 *Progress
= StringPtr
;
2998 Status
= EFI_INVALID_PARAMETER
;
3001 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"PATH=", StrLen (L
"PATH=")) != 0) {
3004 if (*StringPtr
== 0) {
3005 *Progress
= StringPtr
- 1;
3006 Status
= EFI_INVALID_PARAMETER
;
3010 while (*StringPtr
!= L
'&' && *StringPtr
!= 0) {
3013 if (*StringPtr
== 0) {
3014 *Progress
= StringPtr
- 1;
3015 Status
= EFI_INVALID_PARAMETER
;
3024 // Copy <ConfigHdr> and an additional '&' to <ConfigResp>
3026 Length
= StringPtr
- ConfigRequest
;
3027 CopyMem (*Config
, ConfigRequest
, Length
* sizeof (CHAR16
));
3030 // Parse each <RequestElement> if exists
3031 // Only <BlockName> format is supported by this help function.
3032 // <BlockName> ::= 'OFFSET='<Number>&'WIDTH='<Number>
3034 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"OFFSET=", StrLen (L
"OFFSET=")) == 0) {
3036 // Back up the header of one <BlockName>
3040 StringPtr
+= StrLen (L
"OFFSET=");
3044 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
3045 if (Status
== EFI_OUT_OF_RESOURCES
) {
3046 *Progress
= ConfigRequest
;
3053 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
3055 FreePool (TmpBuffer
);
3057 StringPtr
+= Length
;
3058 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
3059 *Progress
= StringPtr
- Length
- StrLen (L
"OFFSET=") - 1;
3060 Status
= EFI_INVALID_PARAMETER
;
3063 StringPtr
+= StrLen (L
"&WIDTH=");
3068 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
3069 if (Status
== EFI_OUT_OF_RESOURCES
) {
3070 *Progress
= ConfigRequest
;
3077 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
3079 FreePool (TmpBuffer
);
3081 StringPtr
+= Length
;
3082 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
3083 *Progress
= StringPtr
- Length
- StrLen (L
"&WIDTH=");
3084 Status
= EFI_INVALID_PARAMETER
;
3089 // Calculate Value and convert it to hex string.
3091 if (Offset
+ Width
> BlockSize
) {
3092 *Progress
= StringPtr
;
3093 Status
= EFI_DEVICE_ERROR
;
3097 Value
= (UINT8
*) AllocateZeroPool (Width
);
3098 if (Value
== NULL
) {
3099 *Progress
= ConfigRequest
;
3100 Status
= EFI_OUT_OF_RESOURCES
;
3104 CopyMem (Value
, (UINT8
*) Block
+ Offset
, Width
);
3106 Length
= Width
* 2 + 1;
3107 ValueStr
= (EFI_STRING
) AllocateZeroPool (Length
* sizeof (CHAR16
));
3108 if (ValueStr
== NULL
) {
3109 *Progress
= ConfigRequest
;
3110 Status
= EFI_OUT_OF_RESOURCES
;
3114 TemString
= ValueStr
;
3115 TemBuffer
= Value
+ Width
- 1;
3116 for (Index
= 0; Index
< Width
; Index
++, TemBuffer
--) {
3117 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
3124 // Build a ConfigElement
3126 Length
+= StringPtr
- TmpPtr
+ 1 + StrLen (L
"VALUE=");
3127 ConfigElement
= (EFI_STRING
) AllocateZeroPool (Length
* sizeof (CHAR16
));
3128 if (ConfigElement
== NULL
) {
3129 Status
= EFI_OUT_OF_RESOURCES
;
3132 CopyMem (ConfigElement
, TmpPtr
, (StringPtr
- TmpPtr
+ 1) * sizeof (CHAR16
));
3133 if (*StringPtr
== 0) {
3134 *(ConfigElement
+ (StringPtr
- TmpPtr
)) = L
'&';
3136 *(ConfigElement
+ (StringPtr
- TmpPtr
) + 1) = 0;
3137 StrCat (ConfigElement
, L
"VALUE=");
3138 StrCat (ConfigElement
, ValueStr
);
3140 AppendToMultiString (Config
, ConfigElement
);
3142 FreePool (ConfigElement
);
3143 FreePool (ValueStr
);
3144 ConfigElement
= NULL
;
3148 // If '\0', parsing is finished. Otherwise skip '&' to continue
3150 if (*StringPtr
== 0) {
3153 AppendToMultiString (Config
, L
"&");
3158 if (*StringPtr
!= 0) {
3159 *Progress
= StringPtr
- 1;
3160 Status
= EFI_INVALID_PARAMETER
;
3164 HiiToLower (*Config
);
3165 *Progress
= StringPtr
;
3169 if (*Config
!= NULL
) {
3173 if (ValueStr
!= NULL
) {
3174 FreePool (ValueStr
);
3176 if (Value
!= NULL
) {
3179 if (ConfigElement
!= NULL
) {
3180 FreePool (ConfigElement
);
3189 This helper function is to be called by drivers to map configuration strings
3190 to configurations stored in byte array ("block") formats such as UEFI Variables.
3192 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
3194 @param ConfigResp A null-terminated Unicode string in <ConfigResp>
3196 @param Block A possibly null array of bytes representing the
3197 current block. Only bytes referenced in the
3198 ConfigResp string in the block are modified. If
3199 this parameter is null or if the *BlockSize
3200 parameter is (on input) shorter than required by
3201 the Configuration string, only the BlockSize
3202 parameter is updated and an appropriate status
3203 (see below) is returned.
3204 @param BlockSize The length of the Block in units of UINT8. On
3205 input, this is the size of the Block. On output,
3206 if successful, contains the index of the last
3207 modified byte in the Block.
3208 @param Progress On return, points to an element of the ConfigResp
3209 string filled in with the offset of the most
3210 recent '&' before the first failing name / value
3211 pair (or the beginning of the string if the
3212 failure is in the first name / value pair) or the
3213 terminating NULL if all was successful.
3215 @retval EFI_SUCCESS The request succeeded. Progress points to the null
3216 terminator at the end of the ConfigResp string.
3217 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress
3218 points to the first character of ConfigResp.
3219 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigResp or
3220 Block parameter would result in this type of
3221 error. Progress points to the first character of
3223 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted name /
3224 value pair. Block is left updated and
3225 Progress points at the '&' preceding the first
3232 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
3233 IN CONST EFI_STRING ConfigResp
,
3234 IN OUT UINT8
*Block
,
3235 IN OUT UINTN
*BlockSize
,
3236 OUT EFI_STRING
*Progress
3239 HII_DATABASE_PRIVATE_DATA
*Private
;
3240 EFI_STRING StringPtr
;
3249 if (This
== NULL
|| BlockSize
== NULL
|| Progress
== NULL
) {
3250 return EFI_INVALID_PARAMETER
;
3253 if (ConfigResp
== NULL
|| Block
== NULL
) {
3254 *Progress
= ConfigResp
;
3255 return EFI_INVALID_PARAMETER
;
3258 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
3259 ASSERT (Private
!= NULL
);
3261 StringPtr
= ConfigResp
;
3262 BufferSize
= *BlockSize
;
3268 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
3269 *Progress
= StringPtr
;
3270 Status
= EFI_INVALID_PARAMETER
;
3273 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"PATH=", StrLen (L
"PATH=")) != 0) {
3276 if (*StringPtr
== 0) {
3277 *Progress
= StringPtr
;
3278 Status
= EFI_INVALID_PARAMETER
;
3282 while (*StringPtr
!= L
'&' && *StringPtr
!= 0) {
3285 if (*StringPtr
== 0) {
3286 *Progress
= StringPtr
;
3287 Status
= EFI_INVALID_PARAMETER
;
3296 // Parse each <ConfigElement> if exists
3297 // Only <BlockConfig> format is supported by this help function.
3298 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE='<Number>
3300 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"OFFSET=", StrLen (L
"OFFSET=")) == 0) {
3301 StringPtr
+= StrLen (L
"OFFSET=");
3305 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
3306 if (EFI_ERROR (Status
)) {
3307 *Progress
= ConfigResp
;
3314 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
3316 FreePool (TmpBuffer
);
3318 StringPtr
+= Length
;
3319 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
3320 *Progress
= StringPtr
- Length
- StrLen (L
"OFFSET=") - 1;
3321 Status
= EFI_INVALID_PARAMETER
;
3324 StringPtr
+= StrLen (L
"&WIDTH=");
3329 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
3330 if (Status
== EFI_OUT_OF_RESOURCES
) {
3331 *Progress
= ConfigResp
;
3338 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
3340 FreePool (TmpBuffer
);
3342 StringPtr
+= Length
;
3343 if (StrnCmp (StringPtr
, L
"&VALUE=", StrLen (L
"&VALUE=")) != 0) {
3344 *Progress
= StringPtr
- Length
- StrLen (L
"&WIDTH=");
3345 Status
= EFI_INVALID_PARAMETER
;
3348 StringPtr
+= StrLen (L
"&VALUE=");
3353 Status
= GetValueOfNumber (StringPtr
, &Value
, &Length
);
3354 if (EFI_ERROR (Status
)) {
3355 *Progress
= ConfigResp
;
3359 StringPtr
+= Length
;
3360 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
3361 *Progress
= StringPtr
- Length
- 7;
3362 Status
= EFI_INVALID_PARAMETER
;
3367 // Update the Block with configuration info
3370 if (Offset
+ Width
> BufferSize
) {
3371 return EFI_DEVICE_ERROR
;
3374 CopyMem (Block
+ Offset
, Value
, Width
);
3375 *BlockSize
= Offset
+ Width
- 1;
3381 // If '\0', parsing is finished. Otherwise skip '&' to continue
3383 if (*StringPtr
== 0) {
3391 // The input string is ConfigAltResp format.
3393 if ((*StringPtr
!= 0) && (StrnCmp (StringPtr
, L
"&GUID=", StrLen (L
"&GUID=")) != 0)) {
3394 *Progress
= StringPtr
- 1;
3395 Status
= EFI_INVALID_PARAMETER
;
3399 *Progress
= StringPtr
+ StrLen (StringPtr
);
3404 if (Value
!= NULL
) {
3412 This helper function is to be called by drivers to extract portions of
3413 a larger configuration string.
3415 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
3417 @param Configuration A null-terminated Unicode string in
3418 <MultiConfigAltResp> format.
3419 @param Guid A pointer to the GUID value to search for in the
3420 routing portion of the ConfigResp string when
3421 retrieving the requested data. If Guid is NULL,
3422 then all GUID values will be searched for.
3423 @param Name A pointer to the NAME value to search for in the
3424 routing portion of the ConfigResp string when
3425 retrieving the requested data. If Name is NULL,
3426 then all Name values will be searched for.
3427 @param DevicePath A pointer to the PATH value to search for in the
3428 routing portion of the ConfigResp string when
3429 retrieving the requested data. If DevicePath is
3430 NULL, then all DevicePath values will be searched
3432 @param AltCfgId A pointer to the ALTCFG value to search for in the
3433 routing portion of the ConfigResp string when
3434 retrieving the requested data. If this parameter
3435 is NULL, then the current setting will be
3437 @param AltCfgResp A pointer to a buffer which will be allocated by
3438 the function which contains the retrieved string
3439 as requested. This buffer is only allocated if
3440 the call was successful. It is <ConfigResp> format.
3442 @retval EFI_SUCCESS The request succeeded. The requested data was
3443 extracted and placed in the newly allocated
3445 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate AltCfgResp.
3446 @retval EFI_INVALID_PARAMETER Any parameter is invalid.
3447 @retval EFI_NOT_FOUND Target for the specified routing data was not
3454 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
3455 IN CONST EFI_STRING Configuration
,
3456 IN CONST EFI_GUID
*Guid
,
3457 IN CONST EFI_STRING Name
,
3458 IN CONST EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
3459 IN CONST UINT16
*AltCfgId
,
3460 OUT EFI_STRING
*AltCfgResp
3464 EFI_STRING StringPtr
;
3465 EFI_STRING HdrStart
;
3472 EFI_STRING AltIdStr
;
3489 if (This
== NULL
|| Configuration
== NULL
|| AltCfgResp
== NULL
) {
3490 return EFI_INVALID_PARAMETER
;
3493 StringPtr
= Configuration
;
3494 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
3495 return EFI_INVALID_PARAMETER
;
3499 // Generate the sub string for later matching.
3501 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*) Guid
, 1, &GuidStr
);
3504 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) DevicePath
),
3505 (VOID
*) DevicePath
,
3509 if (AltCfgId
!= NULL
) {
3510 GenerateSubStr (L
"ALTCFG=", sizeof (UINT16
), (VOID
*) AltCfgId
, 3, &AltIdStr
);
3513 GenerateSubStr (L
"NAME=", StrLen (Name
) * sizeof (CHAR16
), (VOID
*) Name
, 2, &NameStr
);
3515 GenerateSubStr (L
"NAME=", 0, NULL
, 2, &NameStr
);
3518 while (*StringPtr
!= 0) {
3520 // Try to match the GUID
3523 TmpPtr
= StrStr (StringPtr
, GuidStr
);
3524 if (TmpPtr
== NULL
) {
3525 Status
= EFI_NOT_FOUND
;
3531 // Jump to <NameHdr>
3534 StringPtr
= TmpPtr
+ StrLen (GuidStr
);
3536 StringPtr
= StrStr (TmpPtr
, L
"NAME=");
3537 if (StringPtr
== NULL
) {
3538 Status
= EFI_NOT_FOUND
;
3546 // Try to match the NAME
3548 if (GuidFlag
&& !NameFlag
) {
3549 if (StrnCmp (StringPtr
, NameStr
, StrLen (NameStr
)) != 0) {
3553 // Jump to <PathHdr>
3556 StringPtr
+= StrLen (NameStr
);
3558 StringPtr
= StrStr (StringPtr
, L
"PATH=");
3559 if (StringPtr
== NULL
) {
3560 Status
= EFI_NOT_FOUND
;
3569 // Try to match the DevicePath
3571 if (GuidFlag
&& NameFlag
&& !PathFlag
) {
3572 if (StrnCmp (StringPtr
, PathStr
, StrLen (PathStr
)) != 0) {
3577 // Jump to '&' before <DescHdr> or <ConfigBody>
3579 if (DevicePath
!= NULL
) {
3580 StringPtr
+= StrLen (PathStr
);
3582 StringPtr
= StrStr (StringPtr
, L
"&");
3583 if (StringPtr
== NULL
) {
3584 Status
= EFI_NOT_FOUND
;
3595 // Try to match the AltCfgId
3597 if (GuidFlag
&& NameFlag
&& PathFlag
) {
3598 if (AltCfgId
== NULL
) {
3600 // Return Current Setting when AltCfgId is NULL.
3602 Status
= OutputConfigBody (StringPtr
, &Result
);
3606 // Search the <ConfigAltResp> to get the <AltResp> with AltCfgId.
3608 if (StrnCmp (StringPtr
, AltIdStr
, StrLen (AltIdStr
)) != 0) {
3614 // Skip AltIdStr and &
3616 StringPtr
= StringPtr
+ StrLen (AltIdStr
);
3617 Status
= OutputConfigBody (StringPtr
, &Result
);
3623 Status
= EFI_NOT_FOUND
;
3627 if (!EFI_ERROR (Status
) && (Result
!= NULL
)) {
3629 // Copy the <ConfigHdr> and <ConfigBody>
3631 Length
= HdrEnd
- HdrStart
+ StrLen (Result
) + 1;
3632 *AltCfgResp
= AllocateZeroPool (Length
* sizeof (CHAR16
));
3633 if (*AltCfgResp
== NULL
) {
3634 Status
= EFI_OUT_OF_RESOURCES
;
3636 StrnCpy (*AltCfgResp
, HdrStart
, HdrEnd
- HdrStart
);
3637 StrCat (*AltCfgResp
, Result
);
3638 Status
= EFI_SUCCESS
;
3642 if (GuidStr
!= NULL
) {
3645 if (NameStr
!= NULL
) {
3648 if (PathStr
!= NULL
) {
3651 if (AltIdStr
!= NULL
) {
3652 FreePool (AltIdStr
);
3654 if (Result
!= NULL
) {