2 Implementation of interfaces function for EFI_HII_CONFIG_ROUTING_PROTOCOL.
4 Copyright (c) 2007 - 2008, Intel Corporation
5 All rights reserved. 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 Str 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 BlockArray 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 PackageLenth
,
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
< PackageLenth
) {
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
:
955 // No matched varstore is found and directly return.
957 if (VarStorageData
->Size
== 0) {
958 Status
= EFI_SUCCESS
;
963 case EFI_IFR_ONE_OF_OP
:
964 case EFI_IFR_NUMERIC_OP
:
966 // Numeric and OneOf has the same opcode structure.
970 // Numeric and OneOf question is not in IFR Form. This IFR form is not valid.
972 if (VarStorageData
->Size
== 0) {
973 Status
= EFI_INVALID_PARAMETER
;
977 // Check whether this question is for the requested varstore.
979 IfrOneOf
= (EFI_IFR_ONE_OF
*) IfrOpHdr
;
980 if (IfrOneOf
->Question
.VarStoreId
!= VarStorageData
->VarStoreId
) {
985 // Get Offset/Width by Question header and OneOf Flags
987 VarOffset
= IfrOneOf
->Question
.VarStoreInfo
.VarOffset
;
988 VarWidth
= (UINT16
) (1 << (IfrOneOf
->Flags
& EFI_IFR_NUMERIC_SIZE
));
990 // Check whether this question is in requested block array.
992 if (!BlockArrayCheck (RequestBlockArray
, VarOffset
, VarWidth
)) {
994 // This question is not in the requested string. Skip it.
1000 // Check this var question is in the var storage
1002 if ((VarOffset
+ VarWidth
) > VarStorageData
->Size
) {
1003 Status
= EFI_INVALID_PARAMETER
;
1010 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
1011 if (BlockData
== NULL
) {
1012 Status
= EFI_OUT_OF_RESOURCES
;
1015 BlockData
->Offset
= VarOffset
;
1016 BlockData
->Width
= VarWidth
;
1017 BlockData
->QuestionId
= IfrOneOf
->Question
.QuestionId
;
1018 BlockData
->OpCode
= IfrOpHdr
->OpCode
;
1019 BlockData
->Scope
= IfrOpHdr
->Scope
;
1020 InitializeListHead (&BlockData
->DefaultValueEntry
);
1022 // Add Block Data into VarStorageData BlockEntry
1024 InsertBlockData (&VarStorageData
->BlockEntry
, &BlockData
);
1027 case EFI_IFR_ORDERED_LIST_OP
:
1029 // offset by question header
1030 // width by EFI_IFR_ORDERED_LIST MaxContainers * OneofOption Type
1031 // no default value and default id, how to define its default value?
1035 // OrderedList question is not in IFR Form. This IFR form is not valid.
1037 if (VarStorageData
->Size
== 0) {
1038 Status
= EFI_INVALID_PARAMETER
;
1042 // Check whether this question is for the requested varstore.
1044 IfrOrderedList
= (EFI_IFR_ORDERED_LIST
*) IfrOpHdr
;
1045 if (IfrOrderedList
->Question
.VarStoreId
!= VarStorageData
->VarStoreId
) {
1051 // Get Offset/Width by Question header and OneOf Flags
1053 VarOffset
= IfrOrderedList
->Question
.VarStoreInfo
.VarOffset
;
1054 VarWidth
= IfrOrderedList
->MaxContainers
;
1059 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
1060 if (BlockData
== NULL
) {
1061 Status
= EFI_OUT_OF_RESOURCES
;
1064 BlockData
->Offset
= VarOffset
;
1065 BlockData
->Width
= VarWidth
;
1066 BlockData
->QuestionId
= IfrOrderedList
->Question
.QuestionId
;
1067 BlockData
->OpCode
= IfrOpHdr
->OpCode
;
1068 BlockData
->Scope
= IfrOpHdr
->Scope
;
1069 InitializeListHead (&BlockData
->DefaultValueEntry
);
1072 case EFI_IFR_CHECKBOX_OP
:
1074 // EFI_IFR_DEFAULT_OP
1075 // offset by question header
1076 // width is 1 sizeof (BOOLEAN)
1077 // default id by CheckBox Flags if CheckBox flags (Default or Mau) is set, the default value is 1 to be set.
1078 // value by DefaultOption
1079 // default id by DeaultOption DefaultId can override CheckBox Flags and Default value.
1083 // CheckBox question is not in IFR Form. This IFR form is not valid.
1085 if (VarStorageData
->Size
== 0) {
1086 Status
= EFI_INVALID_PARAMETER
;
1090 // Check whether this question is for the requested varstore.
1092 IfrCheckBox
= (EFI_IFR_CHECKBOX
*) IfrOpHdr
;
1093 if (IfrCheckBox
->Question
.VarStoreId
!= VarStorageData
->VarStoreId
) {
1098 // Get Offset/Width by Question header and OneOf Flags
1100 VarOffset
= IfrCheckBox
->Question
.VarStoreInfo
.VarOffset
;
1101 VarWidth
= sizeof (BOOLEAN
);
1104 // Check whether this question is in requested block array.
1106 if (!BlockArrayCheck (RequestBlockArray
, VarOffset
, VarWidth
)) {
1108 // This question is not in the requested string. Skip it.
1114 // Check this var question is in the var storage
1116 if ((VarOffset
+ VarWidth
) > VarStorageData
->Size
) {
1117 Status
= EFI_INVALID_PARAMETER
;
1124 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
1125 if (BlockData
== NULL
) {
1126 Status
= EFI_OUT_OF_RESOURCES
;
1129 BlockData
->Offset
= VarOffset
;
1130 BlockData
->Width
= VarWidth
;
1131 BlockData
->QuestionId
= IfrCheckBox
->Question
.QuestionId
;
1132 BlockData
->OpCode
= IfrOpHdr
->OpCode
;
1133 BlockData
->Scope
= IfrOpHdr
->Scope
;
1134 InitializeListHead (&BlockData
->DefaultValueEntry
);
1136 // Add Block Data into VarStorageData BlockEntry
1138 InsertBlockData (&VarStorageData
->BlockEntry
, &BlockData
);
1141 // Add default value by CheckBox Flags
1143 if ((IfrCheckBox
->Flags
& EFI_IFR_CHECKBOX_DEFAULT
) == EFI_IFR_CHECKBOX_DEFAULT
) {
1145 // Set standard ID to Manufacture ID and Get DefaultName String ID
1147 VarDefaultId
= EFI_HII_DEFAULT_CLASS_STANDARD
;
1148 Status
= FindDefaultName (DefaultIdArray
, VarDefaultId
, &VarDefaultName
);
1149 if (EFI_ERROR (Status
)) {
1153 // Prepare new DefaultValue
1155 DefaultData
= (IFR_DEFAULT_DATA
*) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
1156 if (DefaultData
== NULL
) {
1157 Status
= EFI_OUT_OF_RESOURCES
;
1160 DefaultData
->OpCode
= IfrOpHdr
->OpCode
;
1161 DefaultData
->DefaultId
= VarDefaultId
;
1162 DefaultData
->DefaultName
= VarDefaultName
;
1163 DefaultData
->Value
= 1;
1165 // Add DefaultValue into current BlockData
1167 InsertDefaultValue (BlockData
, DefaultData
);
1170 if ((IfrCheckBox
->Flags
& EFI_IFR_CHECKBOX_DEFAULT_MFG
) == EFI_IFR_CHECKBOX_DEFAULT_MFG
) {
1172 // Set standard ID to Manufacture ID and Get DefaultName String ID
1174 VarDefaultId
= EFI_HII_DEFAULT_CLASS_MANUFACTURING
;
1175 Status
= FindDefaultName (DefaultIdArray
, VarDefaultId
, &VarDefaultName
);
1176 if (EFI_ERROR (Status
)) {
1180 // Prepare new DefaultValue
1182 DefaultData
= (IFR_DEFAULT_DATA
*) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
1183 if (DefaultData
== NULL
) {
1184 Status
= EFI_OUT_OF_RESOURCES
;
1187 DefaultData
->OpCode
= IfrOpHdr
->OpCode
;
1188 DefaultData
->DefaultId
= VarDefaultId
;
1189 DefaultData
->DefaultName
= VarDefaultName
;
1190 DefaultData
->Value
= 1;
1192 // Add DefaultValue into current BlockData
1194 InsertDefaultValue (BlockData
, DefaultData
);
1198 case EFI_IFR_STRING_OP
:
1200 // offset by question header
1201 // width MaxSize * sizeof (CHAR16)
1202 // no default value, only block array
1206 // String question is not in IFR Form. This IFR form is not valid.
1208 if (VarStorageData
->Size
== 0) {
1209 Status
= EFI_INVALID_PARAMETER
;
1213 // Check whether this question is for the requested varstore.
1215 IfrString
= (EFI_IFR_STRING
*) IfrOpHdr
;
1216 if (IfrString
->Question
.VarStoreId
!= VarStorageData
->VarStoreId
) {
1221 // Get Offset/Width by Question header and OneOf Flags
1223 VarOffset
= IfrString
->Question
.VarStoreInfo
.VarOffset
;
1224 VarWidth
= (UINT16
) (IfrString
->MaxSize
* sizeof (UINT16
));
1227 // Check whether this question is in requested block array.
1229 if (!BlockArrayCheck (RequestBlockArray
, VarOffset
, VarWidth
)) {
1231 // This question is not in the requested string. Skip it.
1237 // Check this var question is in the var storage
1239 if ((VarOffset
+ VarWidth
) > VarStorageData
->Size
) {
1240 Status
= EFI_INVALID_PARAMETER
;
1247 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
1248 if (BlockData
== NULL
) {
1249 Status
= EFI_OUT_OF_RESOURCES
;
1252 BlockData
->Offset
= VarOffset
;
1253 BlockData
->Width
= VarWidth
;
1254 BlockData
->QuestionId
= IfrString
->Question
.QuestionId
;
1255 BlockData
->OpCode
= IfrOpHdr
->OpCode
;
1256 InitializeListHead (&BlockData
->DefaultValueEntry
);
1259 // Add Block Data into VarStorageData BlockEntry
1261 InsertBlockData (&VarStorageData
->BlockEntry
, &BlockData
);
1264 // No default value for string.
1269 case EFI_IFR_PASSWORD_OP
:
1271 // offset by question header
1272 // width MaxSize * sizeof (CHAR16)
1273 // no default value, only block array
1277 // Password question is not in IFR Form. This IFR form is not valid.
1279 if (VarStorageData
->Size
== 0) {
1280 Status
= EFI_INVALID_PARAMETER
;
1284 // Check whether this question is for the requested varstore.
1286 IfrPassword
= (EFI_IFR_PASSWORD
*) IfrOpHdr
;
1287 if (IfrPassword
->Question
.VarStoreId
!= VarStorageData
->VarStoreId
) {
1292 // Get Offset/Width by Question header and OneOf Flags
1294 VarOffset
= IfrPassword
->Question
.VarStoreInfo
.VarOffset
;
1295 VarWidth
= (UINT16
) (IfrPassword
->MaxSize
* sizeof (UINT16
));
1298 // Check whether this question is in requested block array.
1300 if (!BlockArrayCheck (RequestBlockArray
, VarOffset
, VarWidth
)) {
1302 // This question is not in the requested string. Skip it.
1308 // Check this var question is in the var storage
1310 if ((VarOffset
+ VarWidth
) > VarStorageData
->Size
) {
1311 Status
= EFI_INVALID_PARAMETER
;
1318 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
1319 if (BlockData
== NULL
) {
1320 Status
= EFI_OUT_OF_RESOURCES
;
1323 BlockData
->Offset
= VarOffset
;
1324 BlockData
->Width
= VarWidth
;
1325 BlockData
->QuestionId
= IfrPassword
->Question
.QuestionId
;
1326 BlockData
->OpCode
= IfrOpHdr
->OpCode
;
1327 InitializeListHead (&BlockData
->DefaultValueEntry
);
1330 // Add Block Data into VarStorageData BlockEntry
1332 InsertBlockData (&VarStorageData
->BlockEntry
, &BlockData
);
1335 // No default value for string.
1340 case EFI_IFR_ONE_OF_OPTION_OP
:
1342 // No matched block data is ignored.
1344 if (BlockData
== NULL
|| BlockData
->Scope
== 0) {
1348 IfrOneOfOption
= (EFI_IFR_ONE_OF_OPTION
*) IfrOpHdr
;
1349 if (BlockData
->OpCode
== EFI_IFR_ORDERED_LIST_OP
) {
1351 // Get ordered list option data type.
1353 if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_8
|| IfrOneOfOption
->Type
== EFI_IFR_TYPE_BOOLEAN
) {
1355 } else if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_16
) {
1357 } else if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_32
) {
1359 } else if (IfrOneOfOption
->Type
== EFI_IFR_TYPE_NUM_SIZE_64
) {
1363 // Invalid ordered list option data type.
1365 Status
= EFI_INVALID_PARAMETER
;
1366 FreePool (BlockData
);
1371 // Calculate Ordered list QuestionId width.
1373 BlockData
->Width
= (UINT16
) (BlockData
->Width
* VarWidth
);
1375 // Check whether this question is in requested block array.
1377 if (!BlockArrayCheck (RequestBlockArray
, BlockData
->Offset
, BlockData
->Width
)) {
1379 // This question is not in the requested string. Skip it.
1381 FreePool (BlockData
);
1386 // Check this var question is in the var storage
1388 if ((BlockData
->Offset
+ BlockData
->Width
) > VarStorageData
->Size
) {
1389 Status
= EFI_INVALID_PARAMETER
;
1390 FreePool (BlockData
);
1394 // Add Block Data into VarStorageData BlockEntry
1396 InsertBlockData (&VarStorageData
->BlockEntry
, &BlockData
);
1398 // No default data for OrderedList.
1404 if ((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT
) == EFI_IFR_OPTION_DEFAULT
) {
1406 // Set standard ID to Manufacture ID and Get DefaultName String ID
1408 VarDefaultId
= EFI_HII_DEFAULT_CLASS_STANDARD
;
1409 Status
= FindDefaultName (DefaultIdArray
, VarDefaultId
, &VarDefaultName
);
1410 if (EFI_ERROR (Status
)) {
1414 // Prepare new DefaultValue
1416 DefaultData
= (IFR_DEFAULT_DATA
*) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
1417 if (DefaultData
== NULL
) {
1418 Status
= EFI_OUT_OF_RESOURCES
;
1421 DefaultData
->OpCode
= IfrOpHdr
->OpCode
;
1422 DefaultData
->DefaultId
= VarDefaultId
;
1423 DefaultData
->DefaultName
= VarDefaultName
;
1424 DefaultData
->Value
= IfrOneOfOption
->Value
.u64
;
1426 // Add DefaultValue into current BlockData
1428 InsertDefaultValue (BlockData
, DefaultData
);
1431 if ((IfrOneOfOption
->Flags
& EFI_IFR_OPTION_DEFAULT_MFG
) == EFI_IFR_OPTION_DEFAULT_MFG
) {
1433 // Set default ID to Manufacture ID and Get DefaultName String ID
1435 VarDefaultId
= EFI_HII_DEFAULT_CLASS_MANUFACTURING
;
1436 Status
= FindDefaultName (DefaultIdArray
, VarDefaultId
, &VarDefaultName
);
1437 if (EFI_ERROR (Status
)) {
1441 // Prepare new DefaultValue
1443 DefaultData
= (IFR_DEFAULT_DATA
*) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
1444 if (DefaultData
== NULL
) {
1445 Status
= EFI_OUT_OF_RESOURCES
;
1448 DefaultData
->OpCode
= IfrOpHdr
->OpCode
;
1449 DefaultData
->DefaultId
= VarDefaultId
;
1450 DefaultData
->DefaultName
= VarDefaultName
;
1451 DefaultData
->Value
= IfrOneOfOption
->Value
.u64
;
1453 // Add DefaultValue into current BlockData
1455 InsertDefaultValue (BlockData
, DefaultData
);
1459 case EFI_IFR_DEFAULT_OP
:
1461 // Update Current BlockData to the default value.
1463 if (BlockData
== NULL
|| BlockData
->Scope
== 0) {
1465 // No matched block data is ignored.
1470 if (BlockData
->OpCode
== EFI_IFR_ORDERED_LIST_OP
) {
1472 // OrderedList Opcode is no default value.
1477 // Get the DefaultId and DefaultName String ID
1479 IfrDefault
= (EFI_IFR_DEFAULT
*) IfrOpHdr
;
1480 VarDefaultId
= IfrDefault
->DefaultId
;
1481 Status
= FindDefaultName (DefaultIdArray
, VarDefaultId
, &VarDefaultName
);
1482 if (EFI_ERROR (Status
)) {
1486 // Prepare new DefaultValue
1488 DefaultData
= (IFR_DEFAULT_DATA
*) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
1489 if (DefaultData
== NULL
) {
1490 Status
= EFI_OUT_OF_RESOURCES
;
1493 DefaultData
->OpCode
= IfrOpHdr
->OpCode
;
1494 DefaultData
->DefaultId
= VarDefaultId
;
1495 DefaultData
->DefaultName
= VarDefaultName
;
1496 DefaultData
->Value
= IfrDefault
->Value
.u64
;
1498 // Add DefaultValue into current BlockData
1500 InsertDefaultValue (BlockData
, DefaultData
);
1502 case EFI_IFR_END_OP
:
1504 // End Opcode is for Var question.
1506 if (BlockData
!= NULL
&& BlockData
->Scope
> 0) {
1511 if (BlockData
!= NULL
&& BlockData
->Scope
> 0) {
1512 BlockData
->Scope
= (UINT8
) (BlockData
->Scope
+ IfrOpHdr
->Scope
);
1517 IfrOffset
+= IfrOpHdr
->Length
;
1525 This function gets the full request string and full default value string by
1526 parsing IFR data in HII form packages.
1528 When Request points to NULL string, the request string and default value string
1529 for each varstore in form package will return.
1531 @param DataBaseRecord The DataBaseRecord instance contains the found Hii handle and package.
1532 @param DevicePath Device Path which Hii Config Access Protocol is registered.
1533 @param Request Pointer to a null-terminated Unicode string in
1534 <ConfigRequest> format. When it doesn't contain
1535 any RequestElement, it will be updated to return
1536 the full RequestElement retrieved from IFR data.
1537 If it points to NULL, the request string for the first
1538 varstore in form package will be merged into a
1539 <MultiConfigRequest> format string and return.
1540 @param AltCfgResp Pointer to a null-terminated Unicode string in
1541 <ConfigAltResp> format. When the pointer is to NULL,
1542 the full default value string retrieved from IFR data
1543 will return. When the pinter is to a string, the
1544 full default value string retrieved from IFR data
1545 will be merged into the input string and return.
1546 When Request points to NULL, the default value string
1547 for each varstore in form package will be merged into
1548 a <MultiConfigAltResp> format string and return.
1549 @param PointerProgress Optional parameter, it can be be NULL.
1550 When it is not NULL, if Request is NULL, it returns NULL.
1551 On return, points to a character in the Request
1552 string. Points to the string's null terminator if
1553 request was successful. Points to the most recent
1554 & before the first failing name / value pair (or
1555 the beginning of the string if the failure is in
1556 the first name / value pair) if the request was
1558 @retval EFI_SUCCESS The Results string is set to the full request string.
1559 And AltCfgResp contains all default value string.
1560 @retval EFI_OUT_OF_RESOURCES Not enough memory for the return string.
1561 @retval EFI_NOT_FOUND The varstore (Guid and Name) in Request string
1562 can't be found in Form package.
1563 @retval EFI_NOT_FOUND HiiPackage can't be got on the input HiiHandle.
1564 @retval EFI_INVALID_PARAMETER Request points to NULL.
1569 GetFullStringFromHiiFormPackages (
1570 IN HII_DATABASE_RECORD
*DataBaseRecord
,
1571 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
1572 IN OUT EFI_STRING
*Request
,
1573 IN OUT EFI_STRING
*AltCfgResp
,
1574 OUT EFI_STRING
*PointerProgress OPTIONAL
1578 UINT8
*HiiFormPackage
;
1581 IFR_BLOCK_DATA
*RequestBlockArray
;
1582 IFR_BLOCK_DATA
*BlockData
;
1583 IFR_BLOCK_DATA
*NextBlockData
;
1584 IFR_DEFAULT_DATA
*DefaultValueData
;
1585 IFR_DEFAULT_DATA
*DefaultId
;
1586 IFR_DEFAULT_DATA
*DefaultIdArray
;
1587 IFR_VARSTORAGE_DATA
*VarStorageData
;
1588 EFI_STRING DefaultAltCfgResp
;
1589 EFI_STRING FullConfigRequest
;
1590 EFI_STRING ConfigHdr
;
1594 EFI_STRING StringPtr
;
1595 EFI_STRING Progress
;
1601 LIST_ENTRY
*LinkData
;
1602 LIST_ENTRY
*LinkDefault
;
1605 if (DataBaseRecord
== NULL
|| DevicePath
== NULL
|| Request
== NULL
|| AltCfgResp
== NULL
) {
1606 return EFI_INVALID_PARAMETER
;
1610 // Initialize the local variables.
1612 RequestBlockArray
= NULL
;
1613 DefaultIdArray
= NULL
;
1614 VarStorageData
= NULL
;
1615 DefaultAltCfgResp
= NULL
;
1616 FullConfigRequest
= NULL
;
1621 HiiFormPackage
= NULL
;
1625 Progress
= *Request
;
1628 // 0. Get Hii Form Package by HiiHandle
1630 Status
= ExportFormPackages (
1632 DataBaseRecord
->Handle
,
1633 DataBaseRecord
->PackageList
,
1639 if (EFI_ERROR (Status
)) {
1643 HiiFormPackage
= AllocatePool (ResultSize
);
1644 if (HiiFormPackage
== NULL
) {
1645 Status
= EFI_OUT_OF_RESOURCES
;
1650 // Get HiiFormPackage by HiiHandle
1652 PackageSize
= ResultSize
;
1654 Status
= ExportFormPackages (
1656 DataBaseRecord
->Handle
,
1657 DataBaseRecord
->PackageList
,
1663 if (EFI_ERROR (Status
)) {
1668 // 1. Get the request block array by Request String when Request string containts the block array.
1671 if (*Request
!= NULL
) {
1672 StringPtr
= *Request
;
1676 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
1677 Status
= EFI_INVALID_PARAMETER
;
1680 StringPtr
+= StrLen (L
"GUID=");
1681 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&NAME=", StrLen (L
"&NAME=")) != 0) {
1684 if (*StringPtr
== L
'\0') {
1685 Status
= EFI_INVALID_PARAMETER
;
1688 StringPtr
+= StrLen (L
"&NAME=");
1689 while (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&PATH=", StrLen (L
"&PATH=")) != 0) {
1692 if (*StringPtr
== L
'\0') {
1693 Status
= EFI_INVALID_PARAMETER
;
1696 StringPtr
+= StrLen (L
"&PATH=");
1697 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
1701 // Check the following string &OFFSET=
1703 if (*StringPtr
!= L
'\0' && StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) != 0) {
1704 Progress
= StringPtr
;
1705 Status
= EFI_INVALID_PARAMETER
;
1707 } else if (*StringPtr
== L
'\0') {
1709 // No request block is found.
1714 if (StringPtr
!= NULL
) {
1716 // Init RequestBlockArray
1718 RequestBlockArray
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
1719 if (RequestBlockArray
== NULL
) {
1720 Status
= EFI_OUT_OF_RESOURCES
;
1723 InitializeListHead (&RequestBlockArray
->Entry
);
1726 // Get the request Block array from the request string
1731 // Parse each <RequestElement> if exists
1732 // Only <BlockName> format is supported by this help function.
1733 // <BlockName> ::= &'OFFSET='<Number>&'WIDTH='<Number>
1735 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"&OFFSET=", StrLen (L
"&OFFSET=")) == 0) {
1737 // Skip the OFFSET string
1739 Progress
= StringPtr
;
1740 StringPtr
+= StrLen (L
"&OFFSET=");
1744 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
1745 if (EFI_ERROR (Status
)) {
1752 (((Length
+ 1) / 2) < sizeof (UINT16
)) ? ((Length
+ 1) / 2) : sizeof (UINT16
)
1754 FreePool (TmpBuffer
);
1756 StringPtr
+= Length
;
1757 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
1758 Status
= EFI_INVALID_PARAMETER
;
1761 StringPtr
+= StrLen (L
"&WIDTH=");
1766 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
1767 if (EFI_ERROR (Status
)) {
1774 (((Length
+ 1) / 2) < sizeof (UINT16
)) ? ((Length
+ 1) / 2) : sizeof (UINT16
)
1776 FreePool (TmpBuffer
);
1778 StringPtr
+= Length
;
1779 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
1780 Status
= EFI_INVALID_PARAMETER
;
1787 BlockData
= (IFR_BLOCK_DATA
*) AllocateZeroPool (sizeof (IFR_BLOCK_DATA
));
1788 if (BlockData
== NULL
) {
1789 Status
= EFI_OUT_OF_RESOURCES
;
1792 BlockData
->Offset
= Offset
;
1793 BlockData
->Width
= Width
;
1794 InsertBlockData (&RequestBlockArray
->Entry
, &BlockData
);
1797 // Skip &VALUE string if &VALUE does exists.
1799 if (StrnCmp (StringPtr
, L
"&VALUE=", StrLen (L
"&VALUE=")) == 0) {
1800 StringPtr
+= StrLen (L
"&VALUE=");
1805 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
1806 if (EFI_ERROR (Status
)) {
1807 Status
= EFI_INVALID_PARAMETER
;
1811 StringPtr
+= Length
;
1812 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
1813 Status
= EFI_INVALID_PARAMETER
;
1818 // If '\0', parsing is finished.
1820 if (*StringPtr
== 0) {
1826 // Merge the requested block data.
1828 Link
= RequestBlockArray
->Entry
.ForwardLink
;
1829 while ((Link
!= &RequestBlockArray
->Entry
) && (Link
->ForwardLink
!= &RequestBlockArray
->Entry
)) {
1830 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
1831 NextBlockData
= BASE_CR (Link
->ForwardLink
, IFR_BLOCK_DATA
, Entry
);
1832 if ((NextBlockData
->Offset
>= BlockData
->Offset
) && (NextBlockData
->Offset
<= (BlockData
->Offset
+ BlockData
->Width
))) {
1833 if ((NextBlockData
->Offset
+ NextBlockData
->Width
) > (BlockData
->Offset
+ BlockData
->Width
)) {
1834 BlockData
->Width
= (UINT16
) (NextBlockData
->Offset
+ NextBlockData
->Width
- BlockData
->Offset
);
1836 RemoveEntryList (Link
->ForwardLink
);
1837 FreePool (NextBlockData
);
1840 Link
= Link
->ForwardLink
;
1845 // 2. Parse FormPackage to get BlockArray and DefaultId Array for the request BlockArray.
1849 // Initialize DefaultIdArray to store the map between DeaultId and DefaultName
1851 DefaultIdArray
= (IFR_DEFAULT_DATA
*) AllocateZeroPool (sizeof (IFR_DEFAULT_DATA
));
1852 if (DefaultIdArray
== NULL
) {
1853 Status
= EFI_OUT_OF_RESOURCES
;
1856 InitializeListHead (&DefaultIdArray
->Entry
);
1859 // Initialize VarStorageData to store the var store Block and Default value information.
1861 VarStorageData
= (IFR_VARSTORAGE_DATA
*) AllocateZeroPool (sizeof (IFR_VARSTORAGE_DATA
));
1862 if (VarStorageData
== NULL
) {
1863 Status
= EFI_OUT_OF_RESOURCES
;
1866 InitializeListHead (&VarStorageData
->Entry
);
1867 InitializeListHead (&VarStorageData
->BlockEntry
);
1870 // Parse the opcode in form pacakge to get the default setting.
1872 Status
= ParseIfrData (HiiFormPackage
, (UINT32
) PackageSize
, *Request
, RequestBlockArray
, VarStorageData
, DefaultIdArray
);
1873 if (EFI_ERROR (Status
)) {
1878 // No requested varstore in IFR data and directly return
1880 if (VarStorageData
->Size
== 0) {
1881 Status
= EFI_SUCCESS
;
1886 // 3. Construct Request Element (Block Name) for 2.1 and 2.2 case.
1890 // Construct <ConfigHdr> : "GUID=...&NAME=...&PATH=..." by VarStorageData Guid, Name and DriverHandle
1892 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*) &VarStorageData
->Guid
, 1, &GuidStr
);
1893 GenerateSubStr (L
"NAME=", StrLen (VarStorageData
->Name
) * sizeof (CHAR16
), (VOID
*) VarStorageData
->Name
, 2, &NameStr
);
1896 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) DevicePath
),
1897 (VOID
*) DevicePath
,
1901 Length
= StrLen (GuidStr
);
1902 Length
= Length
+ StrLen (NameStr
);
1903 Length
= Length
+ StrLen (PathStr
) + 1;
1904 ConfigHdr
= AllocateZeroPool (Length
* sizeof (CHAR16
));
1905 if (ConfigHdr
== NULL
) {
1906 Status
= EFI_OUT_OF_RESOURCES
;
1909 StrCpy (ConfigHdr
, GuidStr
);
1910 StrCat (ConfigHdr
, NameStr
);
1911 StrCat (ConfigHdr
, PathStr
);
1914 // Remove the last character L'&'
1916 *(ConfigHdr
+ StrLen (ConfigHdr
) - 1) = L
'\0';
1918 if (RequestBlockArray
== NULL
) {
1920 // Append VarStorageData BlockEntry into *Request string
1921 // Now support only one varstore in a form package.
1925 // Go through all VarStorageData Entry and get BlockEntry for each one for the multiple varstore in a single form package
1926 // Then construct them all to return MultiRequest string : ConfigHdr BlockConfig
1930 // Compute the length of the entire request starting with <ConfigHdr> and a
1934 Length
= StrLen (ConfigHdr
) + 1;
1936 for (Link
= VarStorageData
->BlockEntry
.ForwardLink
; Link
!= &VarStorageData
->BlockEntry
; Link
= Link
->ForwardLink
) {
1938 // Add <BlockName> length for each Offset/Width pair
1940 // <BlockName> ::= &OFFSET=1234&WIDTH=1234
1941 // | 8 | 4 | 7 | 4 |
1944 Length
= Length
+ (8 + 4 + 7 + 4);
1948 // No any request block data is found. The request string can't be constructed.
1951 Status
= EFI_SUCCESS
;
1956 // Allocate buffer for the entire <ConfigRequest>
1958 FullConfigRequest
= AllocateZeroPool (Length
* sizeof (CHAR16
));
1959 if (FullConfigRequest
== NULL
) {
1960 Status
= EFI_OUT_OF_RESOURCES
;
1963 StringPtr
= FullConfigRequest
;
1966 // Start with <ConfigHdr>
1968 StrCpy (StringPtr
, ConfigHdr
);
1969 StringPtr
+= StrLen (StringPtr
);
1972 // Loop through all the Offset/Width pairs and append them to ConfigRequest
1974 for (Link
= VarStorageData
->BlockEntry
.ForwardLink
; Link
!= &VarStorageData
->BlockEntry
; Link
= Link
->ForwardLink
) {
1975 BlockData
= BASE_CR (Link
, IFR_BLOCK_DATA
, Entry
);
1977 // Append &OFFSET=XXXX&WIDTH=YYYY\0
1981 (8 + 4 + 7 + 4 + 1) * sizeof (CHAR16
),
1982 L
"&OFFSET=%04X&WIDTH=%04X",
1986 StringPtr
+= StrLen (StringPtr
);
1989 // Set to the got full request string.
1991 HiiToLower (FullConfigRequest
);
1992 if (*Request
!= NULL
) {
1993 FreePool (*Request
);
1995 *Request
= FullConfigRequest
;
1999 // 4. Construct Default Value string in AltResp according to request element.
2000 // Go through all VarStorageData Entry and get the DefaultId array for each one
2001 // Then construct them all to : ConfigHdr AltConfigHdr ConfigBody AltConfigHdr ConfigBody
2005 // Add length for <ConfigHdr> + '\0'
2007 Length
= StrLen (ConfigHdr
) + 1;
2009 for (Link
= DefaultIdArray
->Entry
.ForwardLink
; Link
!= &DefaultIdArray
->Entry
; Link
= Link
->ForwardLink
) {
2010 DefaultId
= BASE_CR (Link
, IFR_DEFAULT_DATA
, Entry
);
2012 // Add length for "&<ConfigHdr>&ALTCFG=XXXX"
2013 // |1| StrLen (ConfigHdr) | 8 | 4 |
2015 Length
+= (1 + StrLen (ConfigHdr
) + 8 + 4);
2017 for (LinkData
= VarStorageData
->BlockEntry
.ForwardLink
; LinkData
!= &VarStorageData
->BlockEntry
; LinkData
= LinkData
->ForwardLink
) {
2018 BlockData
= BASE_CR (LinkData
, IFR_BLOCK_DATA
, Entry
);
2019 for (LinkDefault
= BlockData
->DefaultValueEntry
.ForwardLink
; LinkDefault
!= &BlockData
->DefaultValueEntry
; LinkDefault
= LinkDefault
->ForwardLink
) {
2020 DefaultValueData
= BASE_CR (LinkDefault
, IFR_DEFAULT_DATA
, Entry
);
2021 if (DefaultValueData
->DefaultId
== DefaultId
->DefaultId
) {
2023 // Add length for "&OFFSET=XXXX&WIDTH=YYYY&VALUE=zzzzzzzzzzzz"
2024 // | 8 | 4 | 7 | 4 | 7 | Width * 2 |
2026 Length
+= (8 + 4 + 7 + 4 + 7 + BlockData
->Width
* 2);
2034 // No default value is found. The default string doesn't exist.
2037 Status
= EFI_SUCCESS
;
2042 // Allocate buffer for the entire <DefaultAltCfgResp>
2044 DefaultAltCfgResp
= AllocateZeroPool (Length
* sizeof (CHAR16
));
2045 if (DefaultAltCfgResp
== NULL
) {
2046 Status
= EFI_OUT_OF_RESOURCES
;
2049 StringPtr
= DefaultAltCfgResp
;
2052 // Start with <ConfigHdr>
2054 StrCpy (StringPtr
, ConfigHdr
);
2055 StringPtr
+= StrLen (StringPtr
);
2057 for (Link
= DefaultIdArray
->Entry
.ForwardLink
; Link
!= &DefaultIdArray
->Entry
; Link
= Link
->ForwardLink
) {
2058 DefaultId
= BASE_CR (Link
, IFR_DEFAULT_DATA
, Entry
);
2060 // Add <AltConfigHdr> of the form "&<ConfigHdr>&ALTCFG=XXXX\0"
2061 // |1| StrLen (ConfigHdr) | 8 | 4 |
2065 (1 + StrLen (ConfigHdr
) + 8 + 4 + 1) * sizeof (CHAR16
),
2068 DefaultId
->DefaultName
2070 StringPtr
+= StrLen (StringPtr
);
2072 for (LinkData
= VarStorageData
->BlockEntry
.ForwardLink
; LinkData
!= &VarStorageData
->BlockEntry
; LinkData
= LinkData
->ForwardLink
) {
2073 BlockData
= BASE_CR (LinkData
, IFR_BLOCK_DATA
, Entry
);
2074 for (LinkDefault
= BlockData
->DefaultValueEntry
.ForwardLink
; LinkDefault
!= &BlockData
->DefaultValueEntry
; LinkDefault
= LinkDefault
->ForwardLink
) {
2075 DefaultValueData
= BASE_CR (LinkDefault
, IFR_DEFAULT_DATA
, Entry
);
2076 if (DefaultValueData
->DefaultId
== DefaultId
->DefaultId
) {
2078 // Add <BlockConfig>
2079 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>
2083 (8 + 4 + 7 + 4 + 7 + 1) * sizeof (CHAR16
),
2084 L
"&OFFSET=%04X&WIDTH=%04X&VALUE=",
2088 StringPtr
+= StrLen (StringPtr
);
2091 // Convert Value to a hex string in "%x" format
2092 // NOTE: This is in the opposite byte that GUID and PATH use
2094 Width
= BlockData
->Width
;
2095 TmpBuffer
= (UINT8
*) &(DefaultValueData
->Value
);
2096 for (; Width
> 0; Width
--) {
2097 StringPtr
+= UnicodeValueToString (StringPtr
, PREFIX_ZERO
| RADIX_HEX
, TmpBuffer
[Width
- 1], 2);
2103 HiiToLower (DefaultAltCfgResp
);
2106 // 5. Merge string into the input AltCfgResp if the iput *AltCfgResp is not NULL.
2108 if (*AltCfgResp
!= NULL
&& DefaultAltCfgResp
!= NULL
) {
2109 Status
= MergeDefaultString (AltCfgResp
, DefaultAltCfgResp
);
2110 FreePool (DefaultAltCfgResp
);
2111 } else if (*AltCfgResp
== NULL
) {
2112 *AltCfgResp
= DefaultAltCfgResp
;
2116 if (RequestBlockArray
!= NULL
) {
2118 // Free Link Array RequestBlockArray
2120 while (!IsListEmpty (&RequestBlockArray
->Entry
)) {
2121 BlockData
= BASE_CR (RequestBlockArray
->Entry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
2122 RemoveEntryList (&BlockData
->Entry
);
2123 FreePool (BlockData
);
2126 FreePool (RequestBlockArray
);
2129 if (VarStorageData
!= NULL
) {
2131 // Free link array VarStorageData
2133 while (!IsListEmpty (&VarStorageData
->BlockEntry
)) {
2134 BlockData
= BASE_CR (VarStorageData
->BlockEntry
.ForwardLink
, IFR_BLOCK_DATA
, Entry
);
2135 RemoveEntryList (&BlockData
->Entry
);
2137 // Free default value link array
2139 while (!IsListEmpty (&BlockData
->DefaultValueEntry
)) {
2140 DefaultValueData
= BASE_CR (BlockData
->DefaultValueEntry
.ForwardLink
, IFR_DEFAULT_DATA
, Entry
);
2141 RemoveEntryList (&DefaultValueData
->Entry
);
2142 FreePool (DefaultValueData
);
2144 FreePool (BlockData
);
2146 FreePool (VarStorageData
);
2149 if (DefaultIdArray
!= NULL
) {
2151 // Free DefaultId Array
2153 while (!IsListEmpty (&DefaultIdArray
->Entry
)) {
2154 DefaultId
= BASE_CR (DefaultIdArray
->Entry
.ForwardLink
, IFR_DEFAULT_DATA
, Entry
);
2155 RemoveEntryList (&DefaultId
->Entry
);
2156 FreePool (DefaultId
);
2158 FreePool (DefaultIdArray
);
2162 // Free the allocated string
2164 if (GuidStr
!= NULL
) {
2167 if (NameStr
!= NULL
) {
2170 if (PathStr
!= NULL
) {
2173 if (ConfigHdr
!= NULL
) {
2174 FreePool (ConfigHdr
);
2178 // Free Pacakge data
2180 if (HiiFormPackage
!= NULL
) {
2181 FreePool (HiiFormPackage
);
2184 if (PointerProgress
!= NULL
) {
2185 if (*Request
== NULL
) {
2186 *PointerProgress
= NULL
;
2187 } else if (EFI_ERROR (Status
)) {
2188 *PointerProgress
= Progress
;
2190 *PointerProgress
= *Request
+ StrLen (*Request
);
2198 This function allows a caller to extract the current configuration
2199 for one or more named elements from one or more drivers.
2201 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
2203 @param Request A null-terminated Unicode string in
2204 <MultiConfigRequest> format.
2205 @param Progress On return, points to a character in the Request
2206 string. Points to the string's null terminator if
2207 request was successful. Points to the most recent
2208 & before the first failing name / value pair (or
2209 the beginning of the string if the failure is in
2210 the first name / value pair) if the request was
2212 @param Results Null-terminated Unicode string in
2213 <MultiConfigAltResp> format which has all values
2214 filled in for the names in the Request string.
2215 String to be allocated by the called function.
2217 @retval EFI_SUCCESS The Results string is filled with the values
2218 corresponding to all requested names.
2219 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
2220 results that must be stored awaiting possible
2222 @retval EFI_NOT_FOUND Routing data doesn't match any known driver.
2223 Progress set to the "G" in "GUID" of the routing
2224 header that doesn't match. Note: There is no
2225 requirement that all routing data be validated
2226 before any configuration extraction.
2227 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Request
2228 parameter would result in this type of error. The
2229 Progress parameter is set to NULL.
2230 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set to most recent &
2231 before the error or the beginning of the string.
2232 @retval EFI_INVALID_PARAMETER Unknown name. Progress points to the & before the
2238 HiiConfigRoutingExtractConfig (
2239 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
2240 IN CONST EFI_STRING Request
,
2241 OUT EFI_STRING
*Progress
,
2242 OUT EFI_STRING
*Results
2245 HII_DATABASE_PRIVATE_DATA
*Private
;
2246 EFI_STRING StringPtr
;
2247 EFI_STRING ConfigRequest
;
2249 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
2250 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
2253 HII_DATABASE_RECORD
*Database
;
2254 UINT8
*DevicePathPkg
;
2255 UINT8
*CurrentDevicePath
;
2256 EFI_HANDLE DriverHandle
;
2257 EFI_HII_HANDLE HiiHandle
;
2258 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
2259 EFI_STRING AccessProgress
;
2260 EFI_STRING AccessResults
;
2261 EFI_STRING DefaultResults
;
2262 BOOLEAN FirstElement
;
2263 BOOLEAN IfrDataParsedFlag
;
2265 if (This
== NULL
|| Progress
== NULL
|| Results
== NULL
) {
2266 return EFI_INVALID_PARAMETER
;
2269 if (Request
== NULL
) {
2271 return EFI_INVALID_PARAMETER
;
2274 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
2275 StringPtr
= Request
;
2276 *Progress
= StringPtr
;
2277 DefaultResults
= NULL
;
2278 ConfigRequest
= NULL
;
2279 Status
= EFI_SUCCESS
;
2280 AccessResults
= NULL
;
2282 IfrDataParsedFlag
= FALSE
;
2285 // The first element of <MultiConfigRequest> should be
2286 // <GuidHdr>, which is in 'GUID='<Guid> syntax.
2288 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
2289 return EFI_INVALID_PARAMETER
;
2292 FirstElement
= TRUE
;
2295 // Allocate a fix length of memory to store Results. Reallocate memory for
2296 // Results if this fix length is insufficient.
2298 *Results
= (EFI_STRING
) AllocateZeroPool (MAX_STRING_LENGTH
);
2299 if (*Results
== NULL
) {
2300 return EFI_OUT_OF_RESOURCES
;
2303 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) == 0) {
2305 // If parsing error, set Progress to the beginning of the <MultiConfigRequest>
2306 // or most recent & before the error.
2308 if (StringPtr
== Request
) {
2309 *Progress
= StringPtr
;
2311 *Progress
= StringPtr
- 1;
2315 // Process each <ConfigRequest> of <MultiConfigRequest>
2317 Length
= CalculateConfigStringLen (StringPtr
);
2318 ConfigRequest
= AllocateCopyPool ((Length
+ 1) * sizeof (CHAR16
), StringPtr
);
2319 if (ConfigRequest
== NULL
) {
2320 Status
= EFI_OUT_OF_RESOURCES
;
2323 *(ConfigRequest
+ Length
) = 0;
2326 // Get the UEFI device path
2328 Status
= GetDevicePath (ConfigRequest
, (UINT8
**) &DevicePath
);
2329 if (EFI_ERROR (Status
)) {
2334 // Find driver which matches the routing data.
2336 DriverHandle
= NULL
;
2339 for (Link
= Private
->DatabaseList
.ForwardLink
;
2340 Link
!= &Private
->DatabaseList
;
2341 Link
= Link
->ForwardLink
2343 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
2344 if ((DevicePathPkg
= Database
->PackageList
->DevicePathPkg
) != NULL
) {
2345 CurrentDevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
2349 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) CurrentDevicePath
)
2351 DriverHandle
= Database
->DriverHandle
;
2352 HiiHandle
= Database
->Handle
;
2359 // Try to find driver handle by device path.
2361 if (DriverHandle
== NULL
) {
2362 TempDevicePath
= DevicePath
;
2363 Status
= gBS
->LocateDevicePath (
2364 &gEfiDevicePathProtocolGuid
,
2368 if (EFI_ERROR (Status
) || (DriverHandle
== NULL
)) {
2370 // Routing data does not match any known driver.
2371 // Set Progress to the 'G' in "GUID" of the routing header.
2373 *Progress
= StringPtr
;
2374 Status
= EFI_NOT_FOUND
;
2380 // Check whether ConfigRequest contains request string OFFSET/WIDTH
2382 IfrDataParsedFlag
= FALSE
;
2383 if ((HiiHandle
!= NULL
) && (StrStr (ConfigRequest
, L
"&OFFSET=") == NULL
)) {
2385 // Get the full request string from IFR when HiiPackage is registered to HiiHandle
2387 IfrDataParsedFlag
= TRUE
;
2388 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &ConfigRequest
, &DefaultResults
, &AccessProgress
);
2389 if (EFI_ERROR (Status
)) {
2391 // AccessProgress indicates the parsing progress on <ConfigRequest>.
2392 // Map it to the progress on <MultiConfigRequest> then return it.
2394 *Progress
= StrStr (StringPtr
, AccessProgress
);
2398 // Not any request block is found.
2400 if (StrStr (ConfigRequest
, L
"&OFFSET=") == NULL
) {
2401 AccessResults
= AllocateCopyPool (StrSize (ConfigRequest
), ConfigRequest
);
2402 goto NextConfigString
;
2407 // Call corresponding ConfigAccess protocol to extract settings
2409 Status
= gBS
->HandleProtocol (
2411 &gEfiHiiConfigAccessProtocolGuid
,
2412 (VOID
**) &ConfigAccess
2414 ASSERT_EFI_ERROR (Status
);
2416 Status
= ConfigAccess
->ExtractConfig (
2422 if (EFI_ERROR (Status
)) {
2424 // AccessProgress indicates the parsing progress on <ConfigRequest>.
2425 // Map it to the progress on <MultiConfigRequest> then return it.
2427 *Progress
= StrStr (StringPtr
, AccessProgress
);
2432 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'
2433 // which seperates the first <ConfigAltResp> and the following ones.
2435 ASSERT (*AccessProgress
== 0);
2438 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
2440 if (!IfrDataParsedFlag
&& HiiHandle
!= NULL
) {
2441 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &ConfigRequest
, &DefaultResults
, NULL
);
2442 ASSERT_EFI_ERROR (Status
);
2445 FreePool (DevicePath
);
2448 if (DefaultResults
!= NULL
) {
2449 Status
= MergeDefaultString (&AccessResults
, DefaultResults
);
2450 ASSERT_EFI_ERROR (Status
);
2451 FreePool (DefaultResults
);
2452 DefaultResults
= NULL
;
2456 if (!FirstElement
) {
2457 Status
= AppendToMultiString (Results
, L
"&");
2458 ASSERT_EFI_ERROR (Status
);
2461 Status
= AppendToMultiString (Results
, AccessResults
);
2462 ASSERT_EFI_ERROR (Status
);
2464 FirstElement
= FALSE
;
2466 FreePool (AccessResults
);
2467 AccessResults
= NULL
;
2468 FreePool (ConfigRequest
);
2469 ConfigRequest
= NULL
;
2472 // Go to next <ConfigRequest> (skip '&').
2474 StringPtr
+= Length
;
2475 if (*StringPtr
== 0) {
2476 *Progress
= StringPtr
;
2484 if (EFI_ERROR (Status
)) {
2485 FreePool (*Results
);
2489 if (ConfigRequest
!= NULL
) {
2490 FreePool (ConfigRequest
);
2493 if (AccessResults
!= NULL
) {
2494 FreePool (AccessResults
);
2497 if (DefaultResults
!= NULL
) {
2498 FreePool (DefaultResults
);
2501 if (DevicePath
!= NULL
) {
2502 FreePool (DevicePath
);
2510 This function allows the caller to request the current configuration for the
2511 entirety of the current HII database and returns the data in a
2512 null-terminated Unicode string.
2514 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
2516 @param Results Null-terminated Unicode string in
2517 <MultiConfigAltResp> format which has all values
2518 filled in for the names in the Request string.
2519 String to be allocated by the called function.
2520 De-allocation is up to the caller.
2522 @retval EFI_SUCCESS The Results string is filled with the values
2523 corresponding to all requested names.
2524 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
2525 results that must be stored awaiting possible
2527 @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Results
2528 parameter would result in this type of error.
2533 HiiConfigRoutingExportConfig (
2534 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
2535 OUT EFI_STRING
*Results
2539 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
2540 EFI_STRING AccessResults
;
2541 EFI_STRING Progress
;
2542 EFI_STRING StringPtr
;
2543 EFI_STRING ConfigRequest
;
2545 EFI_HANDLE
*ConfigAccessHandles
;
2546 UINTN NumberConfigAccessHandles
;
2547 BOOLEAN FirstElement
;
2548 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
2549 EFI_HII_HANDLE HiiHandle
;
2550 EFI_STRING DefaultResults
;
2551 HII_DATABASE_PRIVATE_DATA
*Private
;
2553 HII_DATABASE_RECORD
*Database
;
2554 UINT8
*DevicePathPkg
;
2555 UINT8
*CurrentDevicePath
;
2556 BOOLEAN IfrDataParsedFlag
;
2558 if (This
== NULL
|| Results
== NULL
) {
2559 return EFI_INVALID_PARAMETER
;
2562 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
2565 // Allocate a fix length of memory to store Results. Reallocate memory for
2566 // Results if this fix length is insufficient.
2568 *Results
= (EFI_STRING
) AllocateZeroPool (MAX_STRING_LENGTH
);
2569 if (*Results
== NULL
) {
2570 return EFI_OUT_OF_RESOURCES
;
2573 NumberConfigAccessHandles
= 0;
2574 Status
= gBS
->LocateHandleBuffer (
2576 &gEfiHiiConfigAccessProtocolGuid
,
2578 &NumberConfigAccessHandles
,
2579 &ConfigAccessHandles
2581 if (EFI_ERROR (Status
)) {
2585 FirstElement
= TRUE
;
2587 for (Index
= 0; Index
< NumberConfigAccessHandles
; Index
++) {
2588 Status
= gBS
->HandleProtocol (
2589 ConfigAccessHandles
[Index
],
2590 &gEfiHiiConfigAccessProtocolGuid
,
2591 (VOID
**) &ConfigAccess
2593 if (EFI_ERROR (Status
)) {
2598 // Get DevicePath and HiiHandle for this ConfigAccess driver handle
2600 IfrDataParsedFlag
= FALSE
;
2603 DefaultResults
= NULL
;
2605 ConfigRequest
= NULL
;
2606 DevicePath
= DevicePathFromHandle (ConfigAccessHandles
[Index
]);
2607 if (DevicePath
!= NULL
) {
2608 for (Link
= Private
->DatabaseList
.ForwardLink
;
2609 Link
!= &Private
->DatabaseList
;
2610 Link
= Link
->ForwardLink
2612 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
2613 if ((DevicePathPkg
= Database
->PackageList
->DevicePathPkg
) != NULL
) {
2614 CurrentDevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
2618 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) CurrentDevicePath
)
2620 HiiHandle
= Database
->Handle
;
2627 Status
= ConfigAccess
->ExtractConfig (
2633 if (EFI_ERROR (Status
)) {
2635 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
2637 if (HiiHandle
!= NULL
&& DevicePath
!= NULL
) {
2638 IfrDataParsedFlag
= TRUE
;
2639 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &ConfigRequest
, &DefaultResults
, NULL
);
2641 // Get the full request string to get the Current setting again.
2643 if (!EFI_ERROR (Status
) && ConfigRequest
!= NULL
) {
2644 Status
= ConfigAccess
->ExtractConfig (
2650 FreePool (ConfigRequest
);
2652 Status
= EFI_NOT_FOUND
;
2657 if (!EFI_ERROR (Status
)) {
2659 // Update AccessResults by getting default setting from IFR when HiiPackage is registered to HiiHandle
2661 if (!IfrDataParsedFlag
&& HiiHandle
!= NULL
&& DevicePath
!= NULL
) {
2662 StringPtr
= StrStr (AccessResults
, L
"&GUID=");
2663 if (StringPtr
!= NULL
) {
2666 if (StrStr (AccessResults
, L
"&OFFSET=") != NULL
) {
2667 Status
= GetFullStringFromHiiFormPackages (Database
, DevicePath
, &AccessResults
, &DefaultResults
, NULL
);
2668 ASSERT_EFI_ERROR (Status
);
2670 if (StringPtr
!= NULL
) {
2675 // Merge the default sting from IFR code into the got setting from driver.
2677 if (DefaultResults
!= NULL
) {
2678 Status
= MergeDefaultString (&AccessResults
, DefaultResults
);
2679 ASSERT_EFI_ERROR (Status
);
2680 FreePool (DefaultResults
);
2681 DefaultResults
= NULL
;
2685 // Attach this <ConfigAltResp> to a <MultiConfigAltResp>. There is a '&'
2686 // which seperates the first <ConfigAltResp> and the following ones.
2688 if (!FirstElement
) {
2689 Status
= AppendToMultiString (Results
, L
"&");
2690 ASSERT_EFI_ERROR (Status
);
2693 Status
= AppendToMultiString (Results
, AccessResults
);
2694 ASSERT_EFI_ERROR (Status
);
2696 FirstElement
= FALSE
;
2698 FreePool (AccessResults
);
2699 AccessResults
= NULL
;
2702 FreePool (ConfigAccessHandles
);
2709 This function processes the results of processing forms and routes it to the
2710 appropriate handlers or storage.
2712 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
2714 @param Configuration A null-terminated Unicode string in
2715 <MulltiConfigResp> format.
2716 @param Progress A pointer to a string filled in with the offset of
2717 the most recent & before the first failing name /
2718 value pair (or the beginning of the string if the
2719 failure is in the first name / value pair) or the
2720 terminating NULL if all was successful.
2722 @retval EFI_SUCCESS The results have been distributed or are awaiting
2724 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the
2725 results that must be stored awaiting possible
2727 @retval EFI_INVALID_PARAMETER Passing in a NULL for the Configuration parameter
2728 would result in this type of error.
2729 @retval EFI_NOT_FOUND Target for the specified routing data was not
2735 HiiConfigRoutingRouteConfig (
2736 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
2737 IN CONST EFI_STRING Configuration
,
2738 OUT EFI_STRING
*Progress
2741 HII_DATABASE_PRIVATE_DATA
*Private
;
2742 EFI_STRING StringPtr
;
2743 EFI_STRING ConfigResp
;
2746 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
2747 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
2749 HII_DATABASE_RECORD
*Database
;
2750 UINT8
*DevicePathPkg
;
2751 UINT8
*CurrentDevicePath
;
2752 EFI_HANDLE DriverHandle
;
2753 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
2754 EFI_STRING AccessProgress
;
2756 if (This
== NULL
|| Progress
== NULL
) {
2757 return EFI_INVALID_PARAMETER
;
2760 if (Configuration
== NULL
) {
2762 return EFI_INVALID_PARAMETER
;
2765 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
2766 StringPtr
= Configuration
;
2767 *Progress
= StringPtr
;
2770 // The first element of <MultiConfigResp> should be
2771 // <GuidHdr>, which is in 'GUID='<Guid> syntax.
2773 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
2774 return EFI_INVALID_PARAMETER
;
2777 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) == 0) {
2779 // If parsing error, set Progress to the beginning of the <MultiConfigResp>
2780 // or most recent & before the error.
2782 if (StringPtr
== Configuration
) {
2783 *Progress
= StringPtr
;
2785 *Progress
= StringPtr
- 1;
2789 // Process each <ConfigResp> of <MultiConfigResp>
2791 Length
= CalculateConfigStringLen (StringPtr
);
2792 ConfigResp
= AllocateCopyPool ((Length
+ 1) * sizeof (CHAR16
), StringPtr
);
2793 if (ConfigResp
== NULL
) {
2794 return EFI_OUT_OF_RESOURCES
;
2797 // Append '\0' to the end of ConfigRequest
2799 *(ConfigResp
+ Length
) = 0;
2802 // Get the UEFI device path
2804 Status
= GetDevicePath (ConfigResp
, (UINT8
**) &DevicePath
);
2805 if (EFI_ERROR (Status
)) {
2806 FreePool (ConfigResp
);
2811 // Find driver which matches the routing data.
2813 DriverHandle
= NULL
;
2814 for (Link
= Private
->DatabaseList
.ForwardLink
;
2815 Link
!= &Private
->DatabaseList
;
2816 Link
= Link
->ForwardLink
2818 Database
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
2820 if ((DevicePathPkg
= Database
->PackageList
->DevicePathPkg
) != NULL
) {
2821 CurrentDevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
2825 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) CurrentDevicePath
)
2827 DriverHandle
= Database
->DriverHandle
;
2834 // Try to find driver handle by device path.
2836 if (DriverHandle
== NULL
) {
2837 TempDevicePath
= DevicePath
;
2838 Status
= gBS
->LocateDevicePath (
2839 &gEfiDevicePathProtocolGuid
,
2843 if (EFI_ERROR (Status
) || (DriverHandle
== NULL
)) {
2845 // Routing data does not match any known driver.
2846 // Set Progress to the 'G' in "GUID" of the routing header.
2848 FreePool (DevicePath
);
2849 *Progress
= StringPtr
;
2850 FreePool (ConfigResp
);
2851 return EFI_NOT_FOUND
;
2855 FreePool (DevicePath
);
2858 // Call corresponding ConfigAccess protocol to route settings
2860 Status
= gBS
->HandleProtocol (
2862 &gEfiHiiConfigAccessProtocolGuid
,
2863 (VOID
**) &ConfigAccess
2865 ASSERT_EFI_ERROR (Status
);
2867 Status
= ConfigAccess
->RouteConfig (
2873 if (EFI_ERROR (Status
)) {
2875 // AccessProgress indicates the parsing progress on <ConfigResp>.
2876 // Map it to the progress on <MultiConfigResp> then return it.
2878 *Progress
= StrStr (StringPtr
, AccessProgress
);
2880 FreePool (ConfigResp
);
2884 FreePool (ConfigResp
);
2888 // Go to next <ConfigResp> (skip '&').
2890 StringPtr
+= Length
;
2891 if (*StringPtr
== 0) {
2892 *Progress
= StringPtr
;
2905 This helper function is to be called by drivers to map configuration data
2906 stored in byte array ("block") formats such as UEFI Variables into current
2907 configuration strings.
2909 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
2911 @param ConfigRequest A null-terminated Unicode string in
2912 <ConfigRequest> format.
2913 @param Block Array of bytes defining the block's configuration.
2914 @param BlockSize Length in bytes of Block.
2915 @param Config Filled-in configuration string. String allocated
2916 by the function. Returned only if call is
2917 successful. It is <ConfigResp> string format.
2918 @param Progress A pointer to a string filled in with the offset of
2919 the most recent & before the first failing
2920 name/value pair (or the beginning of the string if
2921 the failure is in the first name / value pair) or
2922 the terminating NULL if all was successful.
2924 @retval EFI_SUCCESS The request succeeded. Progress points to the null
2925 terminator at the end of the ConfigRequest
2927 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress
2928 points to the first character of ConfigRequest.
2929 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigRequest or
2930 Block parameter would result in this type of
2931 error. Progress points to the first character of
2933 @retval EFI_DEVICE_ERROR Block not large enough. Progress undefined.
2934 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted string.
2935 Block is left updated and Progress points at
2936 the "&" preceding the first non-<BlockName>.
2942 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
2943 IN CONST EFI_STRING ConfigRequest
,
2944 IN CONST UINT8
*Block
,
2945 IN CONST UINTN BlockSize
,
2946 OUT EFI_STRING
*Config
,
2947 OUT EFI_STRING
*Progress
2950 HII_DATABASE_PRIVATE_DATA
*Private
;
2951 EFI_STRING StringPtr
;
2959 EFI_STRING ValueStr
;
2960 EFI_STRING ConfigElement
;
2965 if (This
== NULL
|| Progress
== NULL
|| Config
== NULL
) {
2966 return EFI_INVALID_PARAMETER
;
2969 if (Block
== NULL
|| ConfigRequest
== NULL
) {
2970 *Progress
= ConfigRequest
;
2971 return EFI_INVALID_PARAMETER
;
2975 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
2976 ASSERT (Private
!= NULL
);
2978 StringPtr
= ConfigRequest
;
2981 ConfigElement
= NULL
;
2984 // Allocate a fix length of memory to store Results. Reallocate memory for
2985 // Results if this fix length is insufficient.
2987 *Config
= (EFI_STRING
) AllocateZeroPool (MAX_STRING_LENGTH
);
2988 if (*Config
== NULL
) {
2989 return EFI_OUT_OF_RESOURCES
;
2995 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
2996 *Progress
= StringPtr
;
2997 Status
= EFI_INVALID_PARAMETER
;
3000 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"PATH=", StrLen (L
"PATH=")) != 0) {
3003 if (*StringPtr
== 0) {
3004 *Progress
= StringPtr
- 1;
3005 Status
= EFI_INVALID_PARAMETER
;
3009 while (*StringPtr
!= L
'&' && *StringPtr
!= 0) {
3012 if (*StringPtr
== 0) {
3013 *Progress
= StringPtr
- 1;
3014 Status
= EFI_INVALID_PARAMETER
;
3023 // Copy <ConfigHdr> and an additional '&' to <ConfigResp>
3025 Length
= StringPtr
- ConfigRequest
;
3026 CopyMem (*Config
, ConfigRequest
, Length
* sizeof (CHAR16
));
3029 // Parse each <RequestElement> if exists
3030 // Only <BlockName> format is supported by this help function.
3031 // <BlockName> ::= 'OFFSET='<Number>&'WIDTH='<Number>
3033 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"OFFSET=", StrLen (L
"OFFSET=")) == 0) {
3035 // Back up the header of one <BlockName>
3039 StringPtr
+= StrLen (L
"OFFSET=");
3043 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
3044 if (Status
== EFI_OUT_OF_RESOURCES
) {
3045 *Progress
= ConfigRequest
;
3052 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
3054 FreePool (TmpBuffer
);
3056 StringPtr
+= Length
;
3057 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
3058 *Progress
= StringPtr
- Length
- StrLen (L
"OFFSET=") - 1;
3059 Status
= EFI_INVALID_PARAMETER
;
3062 StringPtr
+= StrLen (L
"&WIDTH=");
3067 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
3068 if (Status
== EFI_OUT_OF_RESOURCES
) {
3069 *Progress
= ConfigRequest
;
3076 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
3078 FreePool (TmpBuffer
);
3080 StringPtr
+= Length
;
3081 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
3082 *Progress
= StringPtr
- Length
- StrLen (L
"&WIDTH=");
3083 Status
= EFI_INVALID_PARAMETER
;
3088 // Calculate Value and convert it to hex string.
3090 if (Offset
+ Width
> BlockSize
) {
3091 *Progress
= StringPtr
;
3092 Status
= EFI_DEVICE_ERROR
;
3096 Value
= (UINT8
*) AllocateZeroPool (Width
);
3097 if (Value
== NULL
) {
3098 *Progress
= ConfigRequest
;
3099 Status
= EFI_OUT_OF_RESOURCES
;
3103 CopyMem (Value
, (UINT8
*) Block
+ Offset
, Width
);
3105 Length
= Width
* 2 + 1;
3106 ValueStr
= (EFI_STRING
) AllocateZeroPool (Length
* sizeof (CHAR16
));
3107 if (ValueStr
== NULL
) {
3108 *Progress
= ConfigRequest
;
3109 Status
= EFI_OUT_OF_RESOURCES
;
3113 TemString
= ValueStr
;
3114 TemBuffer
= Value
+ Width
- 1;
3115 for (Index
= 0; Index
< Width
; Index
++, TemBuffer
--) {
3116 TemString
+= UnicodeValueToString (TemString
, PREFIX_ZERO
| RADIX_HEX
, *TemBuffer
, 2);
3123 // Build a ConfigElement
3125 Length
+= StringPtr
- TmpPtr
+ 1 + StrLen (L
"VALUE=");
3126 ConfigElement
= (EFI_STRING
) AllocateZeroPool (Length
* sizeof (CHAR16
));
3127 if (ConfigElement
== NULL
) {
3128 Status
= EFI_OUT_OF_RESOURCES
;
3131 CopyMem (ConfigElement
, TmpPtr
, (StringPtr
- TmpPtr
+ 1) * sizeof (CHAR16
));
3132 if (*StringPtr
== 0) {
3133 *(ConfigElement
+ (StringPtr
- TmpPtr
)) = L
'&';
3135 *(ConfigElement
+ (StringPtr
- TmpPtr
) + 1) = 0;
3136 StrCat (ConfigElement
, L
"VALUE=");
3137 StrCat (ConfigElement
, ValueStr
);
3139 AppendToMultiString (Config
, ConfigElement
);
3141 FreePool (ConfigElement
);
3142 FreePool (ValueStr
);
3143 ConfigElement
= NULL
;
3147 // If '\0', parsing is finished. Otherwise skip '&' to continue
3149 if (*StringPtr
== 0) {
3152 AppendToMultiString (Config
, L
"&");
3157 if (*StringPtr
!= 0) {
3158 *Progress
= StringPtr
- 1;
3159 Status
= EFI_INVALID_PARAMETER
;
3163 HiiToLower (*Config
);
3164 *Progress
= StringPtr
;
3168 if (*Config
!= NULL
) {
3172 if (ValueStr
!= NULL
) {
3173 FreePool (ValueStr
);
3175 if (Value
!= NULL
) {
3178 if (ConfigElement
!= NULL
) {
3179 FreePool (ConfigElement
);
3188 This helper function is to be called by drivers to map configuration strings
3189 to configurations stored in byte array ("block") formats such as UEFI Variables.
3191 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
3193 @param ConfigResp A null-terminated Unicode string in <ConfigResp>
3194 format. It can be ConfigAltResp format string.
3195 @param Block A possibly null array of bytes representing the
3196 current block. Only bytes referenced in the
3197 ConfigResp string in the block are modified. If
3198 this parameter is null or if the *BlockSize
3199 parameter is (on input) shorter than required by
3200 the Configuration string, only the BlockSize
3201 parameter is updated and an appropriate status
3202 (see below) is returned.
3203 @param BlockSize The length of the Block in units of UINT8. On
3204 input, this is the size of the Block. On output,
3205 if successful, contains the index of the last
3206 modified byte in the Block.
3207 @param Progress On return, points to an element of the ConfigResp
3208 string filled in with the offset of the most
3209 recent '&' before the first failing name / value
3210 pair (or the beginning of the string if the
3211 failure is in the first name / value pair) or the
3212 terminating NULL if all was successful.
3214 @retval EFI_SUCCESS The request succeeded. Progress points to the null
3215 terminator at the end of the ConfigResp string.
3216 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress
3217 points to the first character of ConfigResp.
3218 @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigResp or
3219 Block parameter would result in this type of
3220 error. Progress points to the first character of
3222 @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted name /
3223 value pair. Block is left updated and
3224 Progress points at the '&' preceding the first
3231 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
3232 IN CONST EFI_STRING ConfigResp
,
3233 IN OUT UINT8
*Block
,
3234 IN OUT UINTN
*BlockSize
,
3235 OUT EFI_STRING
*Progress
3238 HII_DATABASE_PRIVATE_DATA
*Private
;
3239 EFI_STRING StringPtr
;
3248 if (This
== NULL
|| BlockSize
== NULL
|| Progress
== NULL
) {
3249 return EFI_INVALID_PARAMETER
;
3252 if (ConfigResp
== NULL
|| Block
== NULL
) {
3253 *Progress
= ConfigResp
;
3254 return EFI_INVALID_PARAMETER
;
3257 Private
= CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This
);
3258 ASSERT (Private
!= NULL
);
3260 StringPtr
= ConfigResp
;
3261 BufferSize
= *BlockSize
;
3267 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
3268 *Progress
= StringPtr
;
3269 Status
= EFI_INVALID_PARAMETER
;
3272 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"PATH=", StrLen (L
"PATH=")) != 0) {
3275 if (*StringPtr
== 0) {
3276 *Progress
= StringPtr
;
3277 Status
= EFI_INVALID_PARAMETER
;
3281 while (*StringPtr
!= L
'&' && *StringPtr
!= 0) {
3284 if (*StringPtr
== 0) {
3285 *Progress
= StringPtr
;
3286 Status
= EFI_INVALID_PARAMETER
;
3295 // Parse each <ConfigElement> if exists
3296 // Only <BlockConfig> format is supported by this help function.
3297 // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE='<Number>
3299 while (*StringPtr
!= 0 && StrnCmp (StringPtr
, L
"OFFSET=", StrLen (L
"OFFSET=")) == 0) {
3300 StringPtr
+= StrLen (L
"OFFSET=");
3304 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
3305 if (EFI_ERROR (Status
)) {
3306 *Progress
= ConfigResp
;
3313 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
3315 FreePool (TmpBuffer
);
3317 StringPtr
+= Length
;
3318 if (StrnCmp (StringPtr
, L
"&WIDTH=", StrLen (L
"&WIDTH=")) != 0) {
3319 *Progress
= StringPtr
- Length
- StrLen (L
"OFFSET=") - 1;
3320 Status
= EFI_INVALID_PARAMETER
;
3323 StringPtr
+= StrLen (L
"&WIDTH=");
3328 Status
= GetValueOfNumber (StringPtr
, &TmpBuffer
, &Length
);
3329 if (Status
== EFI_OUT_OF_RESOURCES
) {
3330 *Progress
= ConfigResp
;
3337 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
3339 FreePool (TmpBuffer
);
3341 StringPtr
+= Length
;
3342 if (StrnCmp (StringPtr
, L
"&VALUE=", StrLen (L
"&VALUE=")) != 0) {
3343 *Progress
= StringPtr
- Length
- StrLen (L
"&WIDTH=");
3344 Status
= EFI_INVALID_PARAMETER
;
3347 StringPtr
+= StrLen (L
"&VALUE=");
3352 Status
= GetValueOfNumber (StringPtr
, &Value
, &Length
);
3353 if (EFI_ERROR (Status
)) {
3354 *Progress
= ConfigResp
;
3358 StringPtr
+= Length
;
3359 if (*StringPtr
!= 0 && *StringPtr
!= L
'&') {
3360 *Progress
= StringPtr
- Length
- 7;
3361 Status
= EFI_INVALID_PARAMETER
;
3366 // Update the Block with configuration info
3369 if (Offset
+ Width
> BufferSize
) {
3370 return EFI_DEVICE_ERROR
;
3373 CopyMem (Block
+ Offset
, Value
, Width
);
3374 *BlockSize
= Offset
+ Width
- 1;
3380 // If '\0', parsing is finished. Otherwise skip '&' to continue
3382 if (*StringPtr
== 0) {
3390 // The input string is ConfigAltResp format.
3392 if ((*StringPtr
!= 0) && (StrnCmp (StringPtr
, L
"&GUID=", StrLen (L
"&GUID=")) != 0)) {
3393 *Progress
= StringPtr
- 1;
3394 Status
= EFI_INVALID_PARAMETER
;
3398 *Progress
= StringPtr
+ StrLen (StringPtr
);
3403 if (Value
!= NULL
) {
3411 This helper function is to be called by drivers to extract portions of
3412 a larger configuration string.
3414 @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
3416 @param Configuration A null-terminated Unicode string in
3417 <MultiConfigAltResp> format. It is <ConfigAltResp> format.
3418 @param Guid A pointer to the GUID value to search for in the
3419 routing portion of the ConfigResp string when
3420 retrieving the requested data. If Guid is NULL,
3421 then all GUID values will be searched for.
3422 @param Name A pointer to the NAME value to search for in the
3423 routing portion of the ConfigResp string when
3424 retrieving the requested data. If Name is NULL,
3425 then all Name values will be searched for.
3426 @param DevicePath A pointer to the PATH value to search for in the
3427 routing portion of the ConfigResp string when
3428 retrieving the requested data. If DevicePath is
3429 NULL, then all DevicePath values will be searched
3431 @param AltCfgId A pointer to the ALTCFG value to search for in the
3432 routing portion of the ConfigResp string when
3433 retrieving the requested data. If this parameter
3434 is NULL, then the current setting will be
3436 @param AltCfgResp A pointer to a buffer which will be allocated by
3437 the function which contains the retrieved string
3438 as requested. This buffer is only allocated if
3439 the call was successful. It is <ConfigResp> format.
3441 @retval EFI_SUCCESS The request succeeded. The requested data was
3442 extracted and placed in the newly allocated
3444 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate AltCfgResp.
3445 @retval EFI_INVALID_PARAMETER Any parameter is invalid.
3446 @retval EFI_NOT_FOUND Target for the specified routing data was not
3453 IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL
*This
,
3454 IN CONST EFI_STRING Configuration
,
3455 IN CONST EFI_GUID
*Guid
,
3456 IN CONST EFI_STRING Name
,
3457 IN CONST EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
3458 IN CONST UINT16
*AltCfgId
,
3459 OUT EFI_STRING
*AltCfgResp
3463 EFI_STRING StringPtr
;
3464 EFI_STRING HdrStart
;
3471 EFI_STRING AltIdStr
;
3488 if (This
== NULL
|| Configuration
== NULL
|| AltCfgResp
== NULL
) {
3489 return EFI_INVALID_PARAMETER
;
3492 StringPtr
= Configuration
;
3493 if (StrnCmp (StringPtr
, L
"GUID=", StrLen (L
"GUID=")) != 0) {
3494 return EFI_INVALID_PARAMETER
;
3498 // Generate the sub string for later matching.
3500 GenerateSubStr (L
"GUID=", sizeof (EFI_GUID
), (VOID
*) Guid
, 1, &GuidStr
);
3503 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) DevicePath
),
3504 (VOID
*) DevicePath
,
3508 if (AltCfgId
!= NULL
) {
3509 GenerateSubStr (L
"ALTCFG=", sizeof (UINT16
), (VOID
*) AltCfgId
, 3, &AltIdStr
);
3512 GenerateSubStr (L
"NAME=", StrLen (Name
) * sizeof (CHAR16
), (VOID
*) Name
, 2, &NameStr
);
3514 GenerateSubStr (L
"NAME=", 0, NULL
, 2, &NameStr
);
3517 while (*StringPtr
!= 0) {
3519 // Try to match the GUID
3522 TmpPtr
= StrStr (StringPtr
, GuidStr
);
3523 if (TmpPtr
== NULL
) {
3524 Status
= EFI_NOT_FOUND
;
3530 // Jump to <NameHdr>
3533 StringPtr
= TmpPtr
+ StrLen (GuidStr
);
3535 StringPtr
= StrStr (TmpPtr
, L
"NAME=");
3536 if (StringPtr
== NULL
) {
3537 Status
= EFI_NOT_FOUND
;
3545 // Try to match the NAME
3547 if (GuidFlag
&& !NameFlag
) {
3548 if (StrnCmp (StringPtr
, NameStr
, StrLen (NameStr
)) != 0) {
3552 // Jump to <PathHdr>
3555 StringPtr
+= StrLen (NameStr
);
3557 StringPtr
= StrStr (StringPtr
, L
"PATH=");
3558 if (StringPtr
== NULL
) {
3559 Status
= EFI_NOT_FOUND
;
3568 // Try to match the DevicePath
3570 if (GuidFlag
&& NameFlag
&& !PathFlag
) {
3571 if (StrnCmp (StringPtr
, PathStr
, StrLen (PathStr
)) != 0) {
3576 // Jump to '&' before <DescHdr> or <ConfigBody>
3578 if (DevicePath
!= NULL
) {
3579 StringPtr
+= StrLen (PathStr
);
3581 StringPtr
= StrStr (StringPtr
, L
"&");
3582 if (StringPtr
== NULL
) {
3583 Status
= EFI_NOT_FOUND
;
3594 // Try to match the AltCfgId
3596 if (GuidFlag
&& NameFlag
&& PathFlag
) {
3597 if (AltCfgId
== NULL
) {
3599 // Return Current Setting when AltCfgId is NULL.
3601 Status
= OutputConfigBody (StringPtr
, &Result
);
3605 // Search the <ConfigAltResp> to get the <AltResp> with AltCfgId.
3607 if (StrnCmp (StringPtr
, AltIdStr
, StrLen (AltIdStr
)) != 0) {
3613 // Skip AltIdStr and &
3615 StringPtr
= StringPtr
+ StrLen (AltIdStr
);
3616 Status
= OutputConfigBody (StringPtr
, &Result
);
3622 Status
= EFI_NOT_FOUND
;
3626 if (!EFI_ERROR (Status
) && (Result
!= NULL
)) {
3628 // Copy the <ConfigHdr> and <ConfigBody>
3630 Length
= HdrEnd
- HdrStart
+ StrLen (Result
) + 1;
3631 *AltCfgResp
= AllocateZeroPool (Length
* sizeof (CHAR16
));
3632 if (*AltCfgResp
== NULL
) {
3633 Status
= EFI_OUT_OF_RESOURCES
;
3635 StrnCpy (*AltCfgResp
, HdrStart
, HdrEnd
- HdrStart
);
3636 StrCat (*AltCfgResp
, Result
);
3637 Status
= EFI_SUCCESS
;
3641 if (GuidStr
!= NULL
) {
3644 if (NameStr
!= NULL
) {
3647 if (PathStr
!= NULL
) {
3650 if (AltIdStr
!= NULL
) {
3651 FreePool (AltIdStr
);
3653 if (Result
!= NULL
) {