2 Implementation of interfaces function for EFI_CONFIG_KEYWORD_HANDLER_PROTOCOL.
4 Copyright (c) 2015, 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"
18 extern HII_DATABASE_PRIVATE_DATA mPrivate
;
21 Convert the hex UNICODE %02x encoding of a UEFI device path to binary
22 from <PathHdr> of <MultiKeywordRequest>.
24 This is a internal function.
26 @param String MultiKeywordRequest string.
27 @param DevicePathData Binary of a UEFI device path.
28 @param NextString string follow the possible PathHdr string.
30 @retval EFI_INVALID_PARAMETER The device path is not valid or the incoming parameter is invalid.
31 @retval EFI_OUT_OF_RESOURCES Lake of resources to store neccesary structures.
32 @retval EFI_SUCCESS The device path is retrieved and translated to binary format.
33 The Input string not include PathHdr section.
39 OUT UINT8
**DevicePathData
,
40 OUT EFI_STRING
*NextString
45 UINT8
*DevicePathBuffer
;
49 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
51 ASSERT (NextString
!= NULL
&& DevicePathData
!= NULL
);
54 // KeywordRequest == NULL case.
57 *DevicePathData
= NULL
;
65 if (*String
== L
'&') {
70 // Find the 'PATH=' of <PathHdr>.
72 if (StrnCmp (String
, L
"PATH=", StrLen (L
"PATH=")) != 0) {
73 if (StrnCmp (String
, L
"KEYWORD=", StrLen (L
"KEYWORD=")) != 0) {
74 return EFI_INVALID_PARAMETER
;
77 // Not include PathHdr, return success and DevicePath = NULL.
79 *DevicePathData
= NULL
;
86 // Check whether path data does exist.
88 String
+= StrLen (L
"PATH=");
90 return EFI_INVALID_PARAMETER
;
95 // The content between 'PATH=' of <ConfigHdr> and '&' of next element
96 // or '\0' (end of configuration string) is the UNICODE %02x bytes encoding
97 // of UEFI device path.
99 for (Length
= 0; *String
!= 0 && *String
!= L
'&'; String
++, Length
++);
102 // Save the return next keyword string value.
104 *NextString
= String
;
107 // Check DevicePath Length
109 if (((Length
+ 1) / 2) < sizeof (EFI_DEVICE_PATH_PROTOCOL
)) {
110 return EFI_INVALID_PARAMETER
;
114 // The data in <PathHdr> is encoded as hex UNICODE %02x bytes in the same order
115 // as the device path resides in RAM memory.
116 // Translate the data into binary.
118 DevicePathBuffer
= (UINT8
*) AllocateZeroPool ((Length
+ 1) / 2);
119 if (DevicePathBuffer
== NULL
) {
120 return EFI_OUT_OF_RESOURCES
;
124 // Convert DevicePath
126 ZeroMem (TemStr
, sizeof (TemStr
));
127 for (Index
= 0; Index
< Length
; Index
++) {
128 TemStr
[0] = PathHdr
[Index
];
129 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
130 if ((Index
& 1) == 0) {
131 DevicePathBuffer
[Index
/2] = DigitUint8
;
133 DevicePathBuffer
[Index
/2] = (UINT8
) ((DevicePathBuffer
[Index
/2] << 4) + DigitUint8
);
138 // Validate DevicePath
140 DevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) DevicePathBuffer
;
141 while (!IsDevicePathEnd (DevicePath
)) {
142 if ((DevicePath
->Type
== 0) || (DevicePath
->SubType
== 0) || (DevicePathNodeLength (DevicePath
) < sizeof (EFI_DEVICE_PATH_PROTOCOL
))) {
144 // Invalid device path
146 FreePool (DevicePathBuffer
);
147 return EFI_INVALID_PARAMETER
;
149 DevicePath
= NextDevicePathNode (DevicePath
);
153 // return the device path
155 *DevicePathData
= DevicePathBuffer
;
161 Get NameSpace from the input NameSpaceId string.
163 This is a internal function.
165 @param String <NameSpaceId> format string.
166 @param NameSpace Return the name space string.
167 @param NextString Return the next string follow namespace.
169 @retval EFI_SUCCESS Get the namespace string success.
170 @retval EFI_INVALID_PARAMETER The NameSpaceId string not follow spec definition.
175 IN EFI_STRING String
,
176 OUT CHAR8
**NameSpace
,
177 OUT EFI_STRING
*NextString
182 ASSERT (NameSpace
!= NULL
);
187 // Input NameSpaceId == NULL
189 if (String
== NULL
) {
191 if (NextString
!= NULL
) {
198 // Skip '&' if exist.
200 if (*String
== L
'&') {
204 if (StrnCmp (String
, L
"NAMESPACE=", StrLen (L
"NAMESPACE=")) != 0) {
205 return EFI_INVALID_PARAMETER
;
207 String
+= StrLen (L
"NAMESPACE=");
209 TmpPtr
= StrStr (String
, L
"&");
210 if (TmpPtr
!= NULL
) {
213 if (NextString
!= NULL
) {
214 *NextString
= String
+ StrLen (String
);
218 // Input NameSpace is unicode string. The language in String package is ascii string.
219 // Here will convert the unicode string to ascii and save it.
221 *NameSpace
= AllocatePool (StrLen (String
) + 1);
222 if (*NameSpace
== NULL
) {
223 return EFI_OUT_OF_RESOURCES
;
225 UnicodeStrToAsciiStr (String
, *NameSpace
);
227 if (TmpPtr
!= NULL
) {
235 Get Keyword from the input KeywordRequest string.
237 This is a internal function.
239 @param String KeywordRequestformat string.
240 @param Keyword return the extract keyword string.
241 @param NextString return the next string follow this keyword sectin.
243 @retval EFI_SUCCESS Success to get the keyword string.
244 @retval EFI_INVALID_PARAMETER Parsr the input string return error.
249 IN EFI_STRING String
,
250 OUT EFI_STRING
*Keyword
,
251 OUT EFI_STRING
*NextString
256 ASSERT ((Keyword
!= NULL
) && (NextString
!= NULL
));
261 // KeywordRequest == NULL case.
263 if (String
== NULL
) {
270 // Skip '&' if exist.
272 if (*String
== L
'&') {
276 if (StrnCmp (String
, L
"KEYWORD=", StrLen (L
"KEYWORD=")) != 0) {
277 return EFI_INVALID_PARAMETER
;
280 String
+= StrLen (L
"KEYWORD=");
282 TmpPtr
= StrStr (String
, L
"&");
283 if (TmpPtr
!= NULL
) {
286 *NextString
= String
+ StrLen (String
);
288 *Keyword
= AllocateCopyPool (StrSize (String
), String
);
289 if (*Keyword
== NULL
) {
290 return EFI_OUT_OF_RESOURCES
;
293 if (TmpPtr
!= NULL
) {
301 Get value from the input KeywordRequest string.
303 This is a internal function.
305 @param String KeywordRequestformat string.
306 @param Value return the extract value string.
307 @param NextString return the next string follow this keyword sectin.
309 @retval EFI_SUCCESS Success to get the keyword string.
310 @retval EFI_INVALID_PARAMETER Parsr the input string return error.
315 IN EFI_STRING String
,
316 OUT EFI_STRING
*Value
,
317 OUT EFI_STRING
*NextString
322 ASSERT ((Value
!= NULL
) && (NextString
!= NULL
) && (String
!= NULL
));
325 // Skip '&' if exist.
327 if (*String
== L
'&') {
331 if (StrnCmp (String
, L
"VALUE=", StrLen (L
"VALUE=")) != 0) {
332 return EFI_INVALID_PARAMETER
;
335 String
+= StrLen (L
"VALUE=");
337 TmpPtr
= StrStr (String
, L
"&");
338 if (TmpPtr
!= NULL
) {
341 *NextString
= String
+ StrLen (String
);
343 *Value
= AllocateCopyPool (StrSize (String
), String
);
344 if (*Value
== NULL
) {
345 return EFI_OUT_OF_RESOURCES
;
348 if (TmpPtr
!= NULL
) {
356 Get filter from the input KeywordRequest string.
358 This is a internal function.
360 @param String KeywordRequestformat string.
361 @param FilterFlags return the filter condition.
362 @param NextString return the next string follow this keyword sectin.
364 @retval EFI_SUCCESS Success to get the keyword string.
365 @retval EFI_INVALID_PARAMETER Parsr the input string return error.
370 IN EFI_STRING String
,
371 OUT UINT8
*FilterFlags
,
372 OUT EFI_STRING
*NextString
379 ASSERT ((FilterFlags
!= NULL
) && (NextString
!= NULL
));
382 // String end, no filter section.
384 if (String
== NULL
) {
393 // Skip '&' if exist.
395 if (*String
== L
'&') {
399 if (StrnCmp (String
, L
"ReadOnly", StrLen (L
"ReadOnly")) == 0) {
401 // Find ReadOnly filter.
403 *FilterFlags
|= EFI_KEYWORD_FILTER_READONY
;
404 String
+= StrLen (L
"ReadOnly");
405 } else if (StrnCmp (String
, L
"ReadWrite", StrLen (L
"ReadWrite")) == 0) {
407 // Find ReadWrite filter.
409 *FilterFlags
|= EFI_KEYWORD_FILTER_REAWRITE
;
410 String
+= StrLen (L
"ReadWrite");
411 } else if (StrnCmp (String
, L
"Buffer", StrLen (L
"Buffer")) == 0) {
413 // Find Buffer Filter.
415 *FilterFlags
|= EFI_KEYWORD_FILTER_BUFFER
;
416 String
+= StrLen (L
"Buffer");
417 } else if (StrnCmp (String
, L
"Numeric", StrLen (L
"Numeric")) == 0) {
419 // Find Numeric Filter
421 String
+= StrLen (L
"Numeric");
422 if (*String
!= L
':') {
423 *FilterFlags
|= EFI_KEYWORD_FILTER_NUMERIC
;
428 *FilterFlags
|= EFI_KEYWORD_FILTER_NUMERIC_1
;
431 *FilterFlags
|= EFI_KEYWORD_FILTER_NUMERIC_2
;
434 *FilterFlags
|= EFI_KEYWORD_FILTER_NUMERIC_4
;
437 *FilterFlags
|= EFI_KEYWORD_FILTER_NUMERIC_8
;
447 // Check whether other filter item defined by Platform.
449 if ((StrnCmp (String
, L
"&PATH", StrLen (L
"&PATH")) == 0) ||
450 (StrnCmp (String
, L
"&KEYWORD", StrLen (L
"&KEYWORD")) == 0)) {
452 // New KeywordRequest start, no platform defined filter.
456 // Platform defined filter rule.
457 // Just skip platform defined filter rule, return success.
459 PathPtr
= StrStr(String
, L
"&PATH");
460 KeywordPtr
= StrStr(String
, L
"&KEYWORD");
461 if (PathPtr
!= NULL
&& KeywordPtr
!= NULL
) {
463 // If both sections exist, return the first follow string.
465 String
= KeywordPtr
> PathPtr
? PathPtr
: KeywordPtr
;
466 } else if (PathPtr
!= NULL
) {
468 // Should not exist PathPtr != NULL && KeywordPtr == NULL case.
471 } else if (KeywordPtr
!= NULL
) {
473 // Just to the next keyword section.
478 // Only has paltform defined filter section, just skip it.
480 String
+= StrLen (String
);
486 *NextString
= String
;
492 Extract Readonly flag from opcode.
494 This is a internal function.
496 @param OpCodeData Input opcode for this question.
498 @retval TRUE This question is readonly.
499 @retval FALSE This question is not readonly.
503 ExtractReadOnlyFromOpCode (
507 EFI_IFR_QUESTION_HEADER
*QuestionHdr
;
509 ASSERT (OpCodeData
!= NULL
);
511 QuestionHdr
= (EFI_IFR_QUESTION_HEADER
*) (OpCodeData
+ sizeof (EFI_IFR_OP_HEADER
));
513 return (QuestionHdr
->Flags
& EFI_IFR_FLAG_READ_ONLY
) != 0;
517 Create a circuit to check the filter section.
519 This is a internal function.
521 @param OpCodeData The questin binary ifr data.
522 @param KeywordRequest KeywordRequestformat string.
523 @param NextString return the next string follow this keyword sectin.
524 @param ReadOnly Return whether this question is read only.
526 @retval KEYWORD_HANDLER_NO_ERROR Success validate.
527 @retval KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED Validate fail.
532 IN UINT8
*OpCodeData
,
533 IN CHAR16
*KeywordRequest
,
534 OUT CHAR16
**NextString
,
535 OUT BOOLEAN
*ReadOnly
541 EFI_IFR_QUESTION_HEADER
*QuestionHdr
;
542 EFI_IFR_OP_HEADER
*OpCodeHdr
;
546 RetVal
= KEYWORD_HANDLER_NO_ERROR
;
547 StringPtr
= KeywordRequest
;
549 OpCodeHdr
= (EFI_IFR_OP_HEADER
*) OpCodeData
;
550 QuestionHdr
= (EFI_IFR_QUESTION_HEADER
*) (OpCodeData
+ sizeof (EFI_IFR_OP_HEADER
));
551 if (OpCodeHdr
->OpCode
== EFI_IFR_ONE_OF_OP
|| OpCodeHdr
->OpCode
== EFI_IFR_NUMERIC_OP
) {
552 Flags
= *(OpCodeData
+ sizeof (EFI_IFR_OP_HEADER
) + sizeof (EFI_IFR_QUESTION_HEADER
));
558 // Get ReadOnly flag from Question.
560 *ReadOnly
= ExtractReadOnlyFromOpCode(OpCodeData
);
562 while (ExtractFilter (StringPtr
, &FilterFlags
, &NextFilter
)) {
563 switch (FilterFlags
) {
564 case EFI_KEYWORD_FILTER_READONY
:
565 if ((QuestionHdr
->Flags
& EFI_IFR_FLAG_READ_ONLY
) == 0) {
566 RetVal
= KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED
;
571 case EFI_KEYWORD_FILTER_REAWRITE
:
572 if ((QuestionHdr
->Flags
& EFI_IFR_FLAG_READ_ONLY
) != 0) {
573 RetVal
= KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED
;
578 case EFI_KEYWORD_FILTER_BUFFER
:
580 // Only these three opcode use numeric value type.
582 if (OpCodeHdr
->OpCode
== EFI_IFR_ONE_OF_OP
|| OpCodeHdr
->OpCode
== EFI_IFR_NUMERIC_OP
|| OpCodeHdr
->OpCode
== EFI_IFR_CHECKBOX_OP
) {
583 RetVal
= KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED
;
588 case EFI_KEYWORD_FILTER_NUMERIC
:
589 if (OpCodeHdr
->OpCode
!= EFI_IFR_ONE_OF_OP
&& OpCodeHdr
->OpCode
!= EFI_IFR_NUMERIC_OP
&& OpCodeHdr
->OpCode
!= EFI_IFR_CHECKBOX_OP
) {
590 RetVal
= KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED
;
595 case EFI_KEYWORD_FILTER_NUMERIC_1
:
596 case EFI_KEYWORD_FILTER_NUMERIC_2
:
597 case EFI_KEYWORD_FILTER_NUMERIC_4
:
598 case EFI_KEYWORD_FILTER_NUMERIC_8
:
599 if (OpCodeHdr
->OpCode
!= EFI_IFR_ONE_OF_OP
&& OpCodeHdr
->OpCode
!= EFI_IFR_NUMERIC_OP
&& OpCodeHdr
->OpCode
!= EFI_IFR_CHECKBOX_OP
) {
600 RetVal
= KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED
;
605 // For numeric and oneof, it has flags field to specify the detail numeric type.
607 if (OpCodeHdr
->OpCode
== EFI_IFR_ONE_OF_OP
|| OpCodeHdr
->OpCode
== EFI_IFR_NUMERIC_OP
) {
608 switch (Flags
& EFI_IFR_NUMERIC_SIZE
) {
609 case EFI_IFR_NUMERIC_SIZE_1
:
610 if (FilterFlags
!= EFI_KEYWORD_FILTER_NUMERIC_1
) {
611 RetVal
= KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED
;
616 case EFI_IFR_NUMERIC_SIZE_2
:
617 if (FilterFlags
!= EFI_KEYWORD_FILTER_NUMERIC_2
) {
618 RetVal
= KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED
;
623 case EFI_IFR_NUMERIC_SIZE_4
:
624 if (FilterFlags
!= EFI_KEYWORD_FILTER_NUMERIC_4
) {
625 RetVal
= KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED
;
630 case EFI_IFR_NUMERIC_SIZE_8
:
631 if (FilterFlags
!= EFI_KEYWORD_FILTER_NUMERIC_8
) {
632 RetVal
= KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED
;
650 // Jump to the next filter.
652 StringPtr
= NextFilter
;
657 // The current filter which is processing.
659 *NextString
= StringPtr
;
665 Get HII_DATABASE_RECORD from the input device path info.
667 This is a internal function.
669 @param DevicePath UEFI device path protocol.
671 @retval Internal data base record.
674 HII_DATABASE_RECORD
*
675 GetRecordFromDevicePath (
676 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
680 UINT8
*DevicePathPkg
;
681 UINT8
*CurrentDevicePath
;
682 UINTN DevicePathSize
;
683 HII_DATABASE_RECORD
*TempDatabase
;
685 ASSERT (DevicePath
!= NULL
);
687 for (Link
= mPrivate
.DatabaseList
.ForwardLink
; Link
!= &mPrivate
.DatabaseList
; Link
= Link
->ForwardLink
) {
688 TempDatabase
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
689 DevicePathPkg
= TempDatabase
->PackageList
->DevicePathPkg
;
690 if (DevicePathPkg
!= NULL
) {
691 CurrentDevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
692 DevicePathSize
= GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) CurrentDevicePath
);
693 if ((CompareMem (DevicePath
, CurrentDevicePath
, DevicePathSize
) == 0)) {
703 Calculate the size of StringSrc and output it. Also copy string text from src
706 This is a internal function.
708 @param StringSrc Points to current null-terminated string.
709 @param BufferSize Length of the buffer.
710 @param StringDest Buffer to store the string text.
712 @retval EFI_SUCCESS The string text was outputed successfully.
713 @retval EFI_OUT_OF_RESOURCES Out of resource.
717 GetUnicodeStringTextAndSize (
719 OUT UINTN
*BufferSize
,
720 OUT EFI_STRING
*StringDest
726 ASSERT (StringSrc
!= NULL
&& BufferSize
!= NULL
&& StringDest
!= NULL
);
728 StringSize
= sizeof (CHAR16
);
729 StringPtr
= StringSrc
;
730 while (ReadUnaligned16 ((UINT16
*) StringPtr
) != 0) {
731 StringSize
+= sizeof (CHAR16
);
732 StringPtr
+= sizeof (CHAR16
);
735 *StringDest
= AllocatePool (StringSize
);
736 if (*StringDest
== NULL
) {
737 return EFI_OUT_OF_RESOURCES
;
740 CopyMem (*StringDest
, StringSrc
, StringSize
);
742 *BufferSize
= StringSize
;
747 Find the string id for the input keyword.
749 @param StringPackage Hii string package instance.
750 @param KeywordValue Input keyword value.
751 @param StringId The string's id, which is unique within PackageList.
754 @retval EFI_SUCCESS The string text and font is retrieved
756 @retval EFI_NOT_FOUND The specified text or font info can not be found
758 @retval EFI_OUT_OF_RESOURCES The system is out of resources to accomplish the
762 GetStringIdFromString (
763 IN HII_STRING_PACKAGE_INSTANCE
*StringPackage
,
764 IN CHAR16
*KeywordValue
,
765 OUT EFI_STRING_ID
*StringId
769 EFI_STRING_ID CurrentStringId
;
772 UINT8
*StringTextPtr
;
777 EFI_HII_SIBT_EXT2_BLOCK Ext2
;
781 CHAR8
*AsciiKeywordValue
;
784 ASSERT (StringPackage
!= NULL
&& KeywordValue
!= NULL
&& StringId
!= NULL
);
785 ASSERT (StringPackage
->Signature
== HII_STRING_PACKAGE_SIGNATURE
);
788 Status
= EFI_SUCCESS
;
790 BlockHdr
= StringPackage
->StringBlock
;
795 // Make a ascii keyword value for later use.
797 AsciiKeywordValue
= AllocatePool (StrLen (KeywordValue
) + 1);
798 if (AsciiKeywordValue
== NULL
) {
799 return EFI_OUT_OF_RESOURCES
;
801 UnicodeStrToAsciiStr(KeywordValue
, AsciiKeywordValue
);
803 while (*BlockHdr
!= EFI_HII_SIBT_END
) {
805 case EFI_HII_SIBT_STRING_SCSU
:
806 Offset
= sizeof (EFI_HII_STRING_BLOCK
);
807 StringTextPtr
= BlockHdr
+ Offset
;
808 BlockSize
+= Offset
+ AsciiStrSize ((CHAR8
*) StringTextPtr
);
809 if (AsciiStrCmp(AsciiKeywordValue
, (CHAR8
*) StringTextPtr
) == 0) {
810 *StringId
= CurrentStringId
;
816 case EFI_HII_SIBT_STRING_SCSU_FONT
:
817 Offset
= sizeof (EFI_HII_SIBT_STRING_SCSU_FONT_BLOCK
) - sizeof (UINT8
);
818 StringTextPtr
= BlockHdr
+ Offset
;
819 if (AsciiStrCmp(AsciiKeywordValue
, (CHAR8
*) StringTextPtr
) == 0) {
820 *StringId
= CurrentStringId
;
823 BlockSize
+= Offset
+ AsciiStrSize ((CHAR8
*) StringTextPtr
);
827 case EFI_HII_SIBT_STRINGS_SCSU
:
828 CopyMem (&StringCount
, BlockHdr
+ sizeof (EFI_HII_STRING_BLOCK
), sizeof (UINT16
));
829 StringTextPtr
= (UINT8
*)((UINTN
)BlockHdr
+ sizeof (EFI_HII_SIBT_STRINGS_SCSU_BLOCK
) - sizeof (UINT8
));
830 BlockSize
+= StringTextPtr
- BlockHdr
;
832 for (Index
= 0; Index
< StringCount
; Index
++) {
833 BlockSize
+= AsciiStrSize ((CHAR8
*) StringTextPtr
);
834 if (AsciiStrCmp(AsciiKeywordValue
, (CHAR8
*) StringTextPtr
) == 0) {
835 *StringId
= CurrentStringId
;
838 StringTextPtr
= StringTextPtr
+ AsciiStrSize ((CHAR8
*) StringTextPtr
);
843 case EFI_HII_SIBT_STRINGS_SCSU_FONT
:
846 (UINT8
*)((UINTN
)BlockHdr
+ sizeof (EFI_HII_STRING_BLOCK
) + sizeof (UINT8
)),
849 StringTextPtr
= (UINT8
*)((UINTN
)BlockHdr
+ sizeof (EFI_HII_SIBT_STRINGS_SCSU_FONT_BLOCK
) - sizeof (UINT8
));
850 BlockSize
+= StringTextPtr
- BlockHdr
;
852 for (Index
= 0; Index
< StringCount
; Index
++) {
853 BlockSize
+= AsciiStrSize ((CHAR8
*) StringTextPtr
);
854 if (AsciiStrCmp(AsciiKeywordValue
, (CHAR8
*) StringTextPtr
) == 0) {
855 *StringId
= CurrentStringId
;
858 StringTextPtr
= StringTextPtr
+ AsciiStrSize ((CHAR8
*) StringTextPtr
);
863 case EFI_HII_SIBT_STRING_UCS2
:
864 Offset
= sizeof (EFI_HII_STRING_BLOCK
);
865 StringTextPtr
= BlockHdr
+ Offset
;
867 // Use StringSize to store the size of the specified string, including the NULL
870 Status
= GetUnicodeStringTextAndSize (StringTextPtr
, &StringSize
, &String
);
871 if (EFI_ERROR (Status
)) {
875 if (StrCmp(KeywordValue
, String
) == 0) {
876 *StringId
= CurrentStringId
;
879 BlockSize
+= Offset
+ StringSize
;
883 case EFI_HII_SIBT_STRING_UCS2_FONT
:
884 Offset
= sizeof (EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK
) - sizeof (CHAR16
);
885 StringTextPtr
= BlockHdr
+ Offset
;
887 // Use StringSize to store the size of the specified string, including the NULL
890 Status
= GetUnicodeStringTextAndSize (StringTextPtr
, &StringSize
, &String
);
891 if (EFI_ERROR (Status
)) {
895 if (StrCmp(KeywordValue
, String
) == 0) {
896 *StringId
= CurrentStringId
;
899 BlockSize
+= Offset
+ StringSize
;
903 case EFI_HII_SIBT_STRINGS_UCS2
:
904 Offset
= sizeof (EFI_HII_SIBT_STRINGS_UCS2_BLOCK
) - sizeof (CHAR16
);
905 StringTextPtr
= BlockHdr
+ Offset
;
907 CopyMem (&StringCount
, BlockHdr
+ sizeof (EFI_HII_STRING_BLOCK
), sizeof (UINT16
));
908 for (Index
= 0; Index
< StringCount
; Index
++) {
909 Status
= GetUnicodeStringTextAndSize (StringTextPtr
, &StringSize
, &String
);
910 if (EFI_ERROR (Status
)) {
914 BlockSize
+= StringSize
;
915 if (StrCmp(KeywordValue
, String
) == 0) {
916 *StringId
= CurrentStringId
;
919 StringTextPtr
= StringTextPtr
+ StringSize
;
924 case EFI_HII_SIBT_STRINGS_UCS2_FONT
:
925 Offset
= sizeof (EFI_HII_SIBT_STRINGS_UCS2_FONT_BLOCK
) - sizeof (CHAR16
);
926 StringTextPtr
= BlockHdr
+ Offset
;
930 (UINT8
*)((UINTN
)BlockHdr
+ sizeof (EFI_HII_STRING_BLOCK
) + sizeof (UINT8
)),
933 for (Index
= 0; Index
< StringCount
; Index
++) {
934 Status
= GetUnicodeStringTextAndSize (StringTextPtr
, &StringSize
, &String
);
935 if (EFI_ERROR (Status
)) {
939 BlockSize
+= StringSize
;
940 if (StrCmp(KeywordValue
, String
) == 0) {
941 *StringId
= CurrentStringId
;
944 StringTextPtr
= StringTextPtr
+ StringSize
;
949 case EFI_HII_SIBT_DUPLICATE
:
950 BlockSize
+= sizeof (EFI_HII_SIBT_DUPLICATE_BLOCK
);
954 case EFI_HII_SIBT_SKIP1
:
955 SkipCount
= (UINT16
) (*(UINT8
*)((UINTN
)BlockHdr
+ sizeof (EFI_HII_STRING_BLOCK
)));
956 CurrentStringId
= (UINT16
) (CurrentStringId
+ SkipCount
);
957 BlockSize
+= sizeof (EFI_HII_SIBT_SKIP1_BLOCK
);
960 case EFI_HII_SIBT_SKIP2
:
961 CopyMem (&SkipCount
, BlockHdr
+ sizeof (EFI_HII_STRING_BLOCK
), sizeof (UINT16
));
962 CurrentStringId
= (UINT16
) (CurrentStringId
+ SkipCount
);
963 BlockSize
+= sizeof (EFI_HII_SIBT_SKIP2_BLOCK
);
966 case EFI_HII_SIBT_EXT1
:
969 (UINT8
*)((UINTN
)BlockHdr
+ sizeof (EFI_HII_STRING_BLOCK
) + sizeof (UINT8
)),
972 BlockSize
+= Length8
;
975 case EFI_HII_SIBT_EXT2
:
976 CopyMem (&Ext2
, BlockHdr
, sizeof (EFI_HII_SIBT_EXT2_BLOCK
));
977 BlockSize
+= Ext2
.Length
;
980 case EFI_HII_SIBT_EXT4
:
983 (UINT8
*)((UINTN
)BlockHdr
+ sizeof (EFI_HII_STRING_BLOCK
) + sizeof (UINT8
)),
987 BlockSize
+= Length32
;
994 if (String
!= NULL
) {
999 BlockHdr
= StringPackage
->StringBlock
+ BlockSize
;
1002 Status
= EFI_NOT_FOUND
;
1005 if (AsciiKeywordValue
!= NULL
) {
1006 FreePool (AsciiKeywordValue
);
1008 if (String
!= NULL
) {
1015 Find the next valid string id for the input string id.
1017 @param StringPackage Hii string package instance.
1018 @param StringId The current string id which is already got.
1019 1 means just begin to get the string id.
1020 @param KeywordValue Return the string for the next string id.
1023 @retval EFI_STRING_ID Not 0 means a valid stringid found.
1024 0 means not found a valid string id.
1028 IN HII_STRING_PACKAGE_INSTANCE
*StringPackage
,
1029 IN EFI_STRING_ID StringId
,
1030 OUT EFI_STRING
*KeywordValue
1034 EFI_STRING_ID CurrentStringId
;
1037 UINT8
*StringTextPtr
;
1042 EFI_HII_SIBT_EXT2_BLOCK Ext2
;
1048 ASSERT (StringPackage
!= NULL
);
1049 ASSERT (StringPackage
->Signature
== HII_STRING_PACKAGE_SIGNATURE
);
1051 CurrentStringId
= 1;
1056 // Parse the string blocks to get the string text and font.
1058 BlockHdr
= StringPackage
->StringBlock
;
1061 while (*BlockHdr
!= EFI_HII_SIBT_END
) {
1062 switch (*BlockHdr
) {
1063 case EFI_HII_SIBT_STRING_SCSU
:
1064 Offset
= sizeof (EFI_HII_STRING_BLOCK
);
1065 StringTextPtr
= BlockHdr
+ Offset
;
1068 *KeywordValue
= AllocatePool (AsciiStrSize ((CHAR8
*) StringTextPtr
) * sizeof (CHAR16
));
1069 if (*KeywordValue
== NULL
) {
1072 AsciiStrToUnicodeStr ((CHAR8
*) StringTextPtr
, *KeywordValue
);
1073 return CurrentStringId
;
1074 } else if (CurrentStringId
== StringId
) {
1078 BlockSize
+= Offset
+ AsciiStrSize ((CHAR8
*) StringTextPtr
);
1082 case EFI_HII_SIBT_STRING_SCSU_FONT
:
1083 Offset
= sizeof (EFI_HII_SIBT_STRING_SCSU_FONT_BLOCK
) - sizeof (UINT8
);
1084 StringTextPtr
= BlockHdr
+ Offset
;
1087 *KeywordValue
= AllocatePool (AsciiStrSize ((CHAR8
*) StringTextPtr
) * sizeof (CHAR16
));
1088 if (*KeywordValue
== NULL
) {
1091 AsciiStrToUnicodeStr ((CHAR8
*) StringTextPtr
, *KeywordValue
);
1092 return CurrentStringId
;
1093 } else if (CurrentStringId
== StringId
) {
1097 BlockSize
+= Offset
+ AsciiStrSize ((CHAR8
*) StringTextPtr
);
1101 case EFI_HII_SIBT_STRINGS_SCSU
:
1102 CopyMem (&StringCount
, BlockHdr
+ sizeof (EFI_HII_STRING_BLOCK
), sizeof (UINT16
));
1103 StringTextPtr
= (UINT8
*)((UINTN
)BlockHdr
+ sizeof (EFI_HII_SIBT_STRINGS_SCSU_BLOCK
) - sizeof (UINT8
));
1104 BlockSize
+= StringTextPtr
- BlockHdr
;
1106 for (Index
= 0; Index
< StringCount
; Index
++) {
1108 *KeywordValue
= AllocatePool (AsciiStrSize ((CHAR8
*) StringTextPtr
) * sizeof (CHAR16
));
1109 if (*KeywordValue
== NULL
) {
1112 AsciiStrToUnicodeStr ((CHAR8
*) StringTextPtr
, *KeywordValue
);
1113 return CurrentStringId
;
1114 } else if (CurrentStringId
== StringId
) {
1118 BlockSize
+= AsciiStrSize ((CHAR8
*) StringTextPtr
);
1119 StringTextPtr
= StringTextPtr
+ AsciiStrSize ((CHAR8
*) StringTextPtr
);
1124 case EFI_HII_SIBT_STRINGS_SCSU_FONT
:
1127 (UINT8
*)((UINTN
)BlockHdr
+ sizeof (EFI_HII_STRING_BLOCK
) + sizeof (UINT8
)),
1130 StringTextPtr
= (UINT8
*)((UINTN
)BlockHdr
+ sizeof (EFI_HII_SIBT_STRINGS_SCSU_FONT_BLOCK
) - sizeof (UINT8
));
1131 BlockSize
+= StringTextPtr
- BlockHdr
;
1133 for (Index
= 0; Index
< StringCount
; Index
++) {
1135 *KeywordValue
= AllocatePool (AsciiStrSize ((CHAR8
*) StringTextPtr
) * sizeof (CHAR16
));
1136 if (*KeywordValue
== NULL
) {
1139 AsciiStrToUnicodeStr ((CHAR8
*) StringTextPtr
, *KeywordValue
);
1140 return CurrentStringId
;
1141 } else if (CurrentStringId
== StringId
) {
1145 BlockSize
+= AsciiStrSize ((CHAR8
*) StringTextPtr
);
1146 StringTextPtr
= StringTextPtr
+ AsciiStrSize ((CHAR8
*) StringTextPtr
);
1151 case EFI_HII_SIBT_STRING_UCS2
:
1152 Offset
= sizeof (EFI_HII_STRING_BLOCK
);
1153 StringTextPtr
= BlockHdr
+ Offset
;
1155 // Use StringSize to store the size of the specified string, including the NULL
1158 GetUnicodeStringTextAndSize (StringTextPtr
, &StringSize
, &String
);
1159 if (FindString
&& (String
!= NULL
) && (*String
!= L
'\0')) {
1161 // String protocol use this type for the string id which has value for other package.
1162 // It will allocate an empty string block for this string id. so here we also check
1163 // *String != L'\0' to prohibit this case.
1165 *KeywordValue
= String
;
1166 return CurrentStringId
;
1167 } else if (CurrentStringId
== StringId
) {
1171 BlockSize
+= Offset
+ StringSize
;
1175 case EFI_HII_SIBT_STRING_UCS2_FONT
:
1176 Offset
= sizeof (EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK
) - sizeof (CHAR16
);
1177 StringTextPtr
= BlockHdr
+ Offset
;
1179 // Use StringSize to store the size of the specified string, including the NULL
1182 GetUnicodeStringTextAndSize (StringTextPtr
, &StringSize
, &String
);
1184 *KeywordValue
= String
;
1185 return CurrentStringId
;
1186 } else if (CurrentStringId
== StringId
) {
1190 BlockSize
+= Offset
+ StringSize
;
1194 case EFI_HII_SIBT_STRINGS_UCS2
:
1195 Offset
= sizeof (EFI_HII_SIBT_STRINGS_UCS2_BLOCK
) - sizeof (CHAR16
);
1196 StringTextPtr
= BlockHdr
+ Offset
;
1197 BlockSize
+= Offset
;
1198 CopyMem (&StringCount
, BlockHdr
+ sizeof (EFI_HII_STRING_BLOCK
), sizeof (UINT16
));
1199 for (Index
= 0; Index
< StringCount
; Index
++) {
1200 GetUnicodeStringTextAndSize (StringTextPtr
, &StringSize
, &String
);
1203 *KeywordValue
= String
;
1204 return CurrentStringId
;
1205 } else if (CurrentStringId
== StringId
) {
1209 BlockSize
+= StringSize
;
1210 StringTextPtr
= StringTextPtr
+ StringSize
;
1215 case EFI_HII_SIBT_STRINGS_UCS2_FONT
:
1216 Offset
= sizeof (EFI_HII_SIBT_STRINGS_UCS2_FONT_BLOCK
) - sizeof (CHAR16
);
1217 StringTextPtr
= BlockHdr
+ Offset
;
1218 BlockSize
+= Offset
;
1221 (UINT8
*)((UINTN
)BlockHdr
+ sizeof (EFI_HII_STRING_BLOCK
) + sizeof (UINT8
)),
1224 for (Index
= 0; Index
< StringCount
; Index
++) {
1225 GetUnicodeStringTextAndSize (StringTextPtr
, &StringSize
, &String
);
1227 *KeywordValue
= String
;
1228 return CurrentStringId
;
1229 } else if (CurrentStringId
== StringId
) {
1233 BlockSize
+= StringSize
;
1234 StringTextPtr
= StringTextPtr
+ StringSize
;
1239 case EFI_HII_SIBT_DUPLICATE
:
1240 BlockSize
+= sizeof (EFI_HII_SIBT_DUPLICATE_BLOCK
);
1244 case EFI_HII_SIBT_SKIP1
:
1245 SkipCount
= (UINT16
) (*(UINT8
*)((UINTN
)BlockHdr
+ sizeof (EFI_HII_STRING_BLOCK
)));
1246 CurrentStringId
= (UINT16
) (CurrentStringId
+ SkipCount
);
1247 BlockSize
+= sizeof (EFI_HII_SIBT_SKIP1_BLOCK
);
1250 case EFI_HII_SIBT_SKIP2
:
1251 CopyMem (&SkipCount
, BlockHdr
+ sizeof (EFI_HII_STRING_BLOCK
), sizeof (UINT16
));
1252 CurrentStringId
= (UINT16
) (CurrentStringId
+ SkipCount
);
1253 BlockSize
+= sizeof (EFI_HII_SIBT_SKIP2_BLOCK
);
1256 case EFI_HII_SIBT_EXT1
:
1259 (UINT8
*)((UINTN
)BlockHdr
+ sizeof (EFI_HII_STRING_BLOCK
) + sizeof (UINT8
)),
1262 BlockSize
+= Length8
;
1265 case EFI_HII_SIBT_EXT2
:
1266 CopyMem (&Ext2
, BlockHdr
, sizeof (EFI_HII_SIBT_EXT2_BLOCK
));
1267 BlockSize
+= Ext2
.Length
;
1270 case EFI_HII_SIBT_EXT4
:
1273 (UINT8
*)((UINTN
)BlockHdr
+ sizeof (EFI_HII_STRING_BLOCK
) + sizeof (UINT8
)),
1277 BlockSize
+= Length32
;
1284 if (String
!= NULL
) {
1289 BlockHdr
= StringPackage
->StringBlock
+ BlockSize
;
1296 Get string package from the input NameSpace string.
1298 This is a internal function.
1300 @param DatabaseRecord HII_DATABASE_RECORD format string.
1301 @param NameSpace NameSpace format string.
1302 @param KeywordValue Keyword value.
1303 @param StringId String Id for this keyword.
1305 @retval KEYWORD_HANDLER_NO_ERROR Get String id succes.
1306 @retval KEYWORD_HANDLER_KEYWORD_NOT_FOUND Not found the string id in the string package.
1307 @retval KEYWORD_HANDLER_NAMESPACE_ID_NOT_FOUND Not found the string package for this namespace.
1308 @retval KEYWORD_HANDLER_UNDEFINED_PROCESSING_ERROR Out of resource error.
1312 GetStringIdFromRecord (
1313 IN HII_DATABASE_RECORD
*DatabaseRecord
,
1314 IN CHAR8
**NameSpace
,
1315 IN CHAR16
*KeywordValue
,
1316 OUT EFI_STRING_ID
*StringId
1320 HII_DATABASE_PACKAGE_LIST_INSTANCE
*PackageListNode
;
1321 HII_STRING_PACKAGE_INSTANCE
*StringPackage
;
1326 ASSERT (DatabaseRecord
!= NULL
&& NameSpace
!= NULL
&& KeywordValue
!= NULL
);
1328 PackageListNode
= DatabaseRecord
->PackageList
;
1329 RetVal
= KEYWORD_HANDLER_NAMESPACE_ID_NOT_FOUND
;
1331 if (*NameSpace
!= NULL
) {
1334 Name
= UEFI_CONFIG_LANG
;
1337 for (Link
= PackageListNode
->StringPkgHdr
.ForwardLink
; Link
!= &PackageListNode
->StringPkgHdr
; Link
= Link
->ForwardLink
) {
1338 StringPackage
= CR (Link
, HII_STRING_PACKAGE_INSTANCE
, StringEntry
, HII_STRING_PACKAGE_SIGNATURE
);
1340 if (AsciiStrnCmp(Name
, StringPackage
->StringPkgHdr
->Language
, AsciiStrLen (Name
)) == 0) {
1341 Status
= GetStringIdFromString (StringPackage
, KeywordValue
, StringId
);
1342 if (EFI_ERROR (Status
)) {
1343 RetVal
= KEYWORD_HANDLER_KEYWORD_NOT_FOUND
;
1346 if (*NameSpace
== NULL
) {
1347 *NameSpace
= AllocateCopyPool (AsciiStrSize (StringPackage
->StringPkgHdr
->Language
), StringPackage
->StringPkgHdr
->Language
);
1348 if (*NameSpace
== NULL
) {
1349 return KEYWORD_HANDLER_UNDEFINED_PROCESSING_ERROR
;
1352 return KEYWORD_HANDLER_NO_ERROR
;
1361 Tell whether this Operand is an Statement OpCode.
1363 @param Operand Operand of an IFR OpCode.
1365 @retval TRUE This is an Statement OpCode.
1366 @retval FALSE Not an Statement OpCode.
1374 if ((Operand
== EFI_IFR_SUBTITLE_OP
) ||
1375 (Operand
== EFI_IFR_TEXT_OP
) ||
1376 (Operand
== EFI_IFR_RESET_BUTTON_OP
) ||
1377 (Operand
== EFI_IFR_REF_OP
) ||
1378 (Operand
== EFI_IFR_ACTION_OP
) ||
1379 (Operand
== EFI_IFR_NUMERIC_OP
) ||
1380 (Operand
== EFI_IFR_ORDERED_LIST_OP
) ||
1381 (Operand
== EFI_IFR_CHECKBOX_OP
) ||
1382 (Operand
== EFI_IFR_STRING_OP
) ||
1383 (Operand
== EFI_IFR_PASSWORD_OP
) ||
1384 (Operand
== EFI_IFR_DATE_OP
) ||
1385 (Operand
== EFI_IFR_TIME_OP
) ||
1386 (Operand
== EFI_IFR_GUID_OP
) ||
1387 (Operand
== EFI_IFR_ONE_OF_OP
)) {
1395 Tell whether this Operand is an Statement OpCode.
1397 @param Operand Operand of an IFR OpCode.
1399 @retval TRUE This is an Statement OpCode.
1400 @retval FALSE Not an Statement OpCode.
1408 if ((Operand
== EFI_IFR_VARSTORE_OP
) ||
1409 (Operand
== EFI_IFR_VARSTORE_NAME_VALUE_OP
) ||
1410 (Operand
== EFI_IFR_VARSTORE_EFI_OP
)) {
1418 Base on the prompt string id to find the question.
1420 @param FormPackage The input form package.
1421 @param KeywordStrId The input prompt string id for one question.
1423 @retval the opcode for the question.
1427 FindQuestionFromStringId (
1428 IN HII_IFR_PACKAGE_INSTANCE
*FormPackage
,
1429 IN EFI_STRING_ID KeywordStrId
1434 EFI_IFR_STATEMENT_HEADER
*StatementHeader
;
1435 EFI_IFR_OP_HEADER
*OpCodeHeader
;
1438 ASSERT (FormPackage
!= NULL
);
1440 FormDataLen
= FormPackage
->FormPkgHdr
.Length
- sizeof (EFI_HII_PACKAGE_HEADER
);
1442 while (Offset
< FormDataLen
) {
1443 OpCodeData
= FormPackage
->IfrData
+ Offset
;
1444 OpCodeHeader
= (EFI_IFR_OP_HEADER
*) OpCodeData
;
1446 if (IsStatementOpCode(OpCodeHeader
->OpCode
)) {
1447 StatementHeader
= (EFI_IFR_STATEMENT_HEADER
*) (OpCodeData
+ sizeof (EFI_IFR_OP_HEADER
));
1448 if (StatementHeader
->Prompt
== KeywordStrId
) {
1453 Offset
+= OpCodeHeader
->Length
;
1460 Base on the varstore id to find the storage info.
1462 @param FormPackage The input form package.
1463 @param VarStoreId The input storage id.
1465 @retval the opcode for the storage.
1469 FindStorageFromVarId (
1470 IN HII_IFR_PACKAGE_INSTANCE
*FormPackage
,
1471 IN EFI_VARSTORE_ID VarStoreId
1476 EFI_IFR_OP_HEADER
*OpCodeHeader
;
1479 ASSERT (FormPackage
!= NULL
);
1481 FormDataLen
= FormPackage
->FormPkgHdr
.Length
- sizeof (EFI_HII_PACKAGE_HEADER
);
1483 while (Offset
< FormDataLen
) {
1484 OpCodeData
= FormPackage
->IfrData
+ Offset
;
1485 OpCodeHeader
= (EFI_IFR_OP_HEADER
*) OpCodeData
;
1487 if (IsStorageOpCode(OpCodeHeader
->OpCode
)) {
1488 switch (OpCodeHeader
->OpCode
) {
1489 case EFI_IFR_VARSTORE_OP
:
1490 if (VarStoreId
== ((EFI_IFR_VARSTORE
*) OpCodeData
)->VarStoreId
) {
1495 case EFI_IFR_VARSTORE_NAME_VALUE_OP
:
1496 if (VarStoreId
== ((EFI_IFR_VARSTORE_NAME_VALUE
*) OpCodeData
)->VarStoreId
) {
1501 case EFI_IFR_VARSTORE_EFI_OP
:
1502 if (VarStoreId
== ((EFI_IFR_VARSTORE_EFI
*) OpCodeData
)->VarStoreId
) {
1512 Offset
+= OpCodeHeader
->Length
;
1519 Get width info for one question.
1521 @param OpCodeData The input opcode for one question.
1523 @retval the width info for one question.
1528 IN UINT8
*OpCodeData
1531 UINT8
*NextOpCodeData
;
1533 ASSERT (OpCodeData
!= NULL
);
1535 switch (((EFI_IFR_OP_HEADER
*) OpCodeData
)->OpCode
) {
1536 case EFI_IFR_REF_OP
:
1537 return (UINT16
) sizeof (EFI_HII_REF
);
1539 case EFI_IFR_ONE_OF_OP
:
1540 case EFI_IFR_NUMERIC_OP
:
1541 switch (((EFI_IFR_ONE_OF
*) OpCodeData
)->Flags
& EFI_IFR_NUMERIC_SIZE
) {
1542 case EFI_IFR_NUMERIC_SIZE_1
:
1543 return (UINT16
) sizeof (UINT8
);
1545 case EFI_IFR_NUMERIC_SIZE_2
:
1546 return (UINT16
) sizeof (UINT16
);
1548 case EFI_IFR_NUMERIC_SIZE_4
:
1549 return (UINT16
) sizeof (UINT32
);
1551 case EFI_IFR_NUMERIC_SIZE_8
:
1552 return (UINT16
) sizeof (UINT64
);
1559 case EFI_IFR_ORDERED_LIST_OP
:
1560 NextOpCodeData
= OpCodeData
+ ((EFI_IFR_ORDERED_LIST
*) OpCodeData
)->Header
.Length
;
1562 // OneOfOption must follow the orderedlist opcode.
1564 ASSERT (((EFI_IFR_OP_HEADER
*) NextOpCodeData
)->OpCode
== EFI_IFR_ONE_OF_OPTION_OP
);
1565 switch (((EFI_IFR_ONE_OF_OPTION
*) NextOpCodeData
)->Type
) {
1566 case EFI_IFR_TYPE_NUM_SIZE_8
:
1567 return (UINT16
) sizeof (UINT8
) * ((EFI_IFR_ORDERED_LIST
*) OpCodeData
)->MaxContainers
;
1569 case EFI_IFR_TYPE_NUM_SIZE_16
:
1570 return (UINT16
) sizeof (UINT16
) * ((EFI_IFR_ORDERED_LIST
*) OpCodeData
)->MaxContainers
;
1572 case EFI_IFR_TYPE_NUM_SIZE_32
:
1573 return (UINT16
) sizeof (UINT32
) * ((EFI_IFR_ORDERED_LIST
*) OpCodeData
)->MaxContainers
;
1575 case EFI_IFR_TYPE_NUM_SIZE_64
:
1576 return (UINT16
) sizeof (UINT64
) * ((EFI_IFR_ORDERED_LIST
*) OpCodeData
)->MaxContainers
;
1583 case EFI_IFR_CHECKBOX_OP
:
1584 return (UINT16
) sizeof (BOOLEAN
);
1586 case EFI_IFR_PASSWORD_OP
:
1587 case EFI_IFR_STRING_OP
:
1588 return (UINT16
)((UINTN
) ((EFI_IFR_STRING
*) OpCodeData
)->MaxSize
* sizeof (CHAR16
));
1590 case EFI_IFR_DATE_OP
:
1591 return (UINT16
) sizeof (EFI_HII_DATE
);
1593 case EFI_IFR_TIME_OP
:
1594 return (UINT16
) sizeof (EFI_HII_TIME
);
1603 Converts all hex dtring characters in range ['A'..'F'] to ['a'..'f'] for
1604 hex digits that appear between a '=' and a '&' in a config string.
1606 If ConfigString is NULL, then ASSERT().
1608 @param[in] ConfigString Pointer to a Null-terminated Unicode string.
1610 @return Pointer to the Null-terminated Unicode result string.
1615 InternalLowerConfigString (
1616 IN EFI_STRING ConfigString
1622 ASSERT (ConfigString
!= NULL
);
1625 // Convert all hex digits in range [A-F] in the configuration header to [a-f]
1627 for (String
= ConfigString
, Lower
= FALSE
; *String
!= L
'\0'; String
++) {
1628 if (*String
== L
'=') {
1630 } else if (*String
== L
'&') {
1632 } else if (Lower
&& *String
>= L
'A' && *String
<= L
'F') {
1633 *String
= (CHAR16
) (*String
- L
'A' + L
'a');
1637 return ConfigString
;
1641 Allocates and returns a Null-terminated Unicode <ConfigHdr> string.
1643 The format of a <ConfigHdr> is as follows:
1645 GUID=<HexCh>32&NAME=<Char>NameLength&PATH=<HexChar>DevicePathSize<Null>
1647 @param[in] OpCodeData The opcode for the storage.
1648 @param[in] DriverHandle The driver handle which supports a Device Path Protocol
1649 that is the routing information PATH. Each byte of
1650 the Device Path associated with DriverHandle is converted
1651 to a 2 Unicode character hexidecimal string.
1653 @retval NULL DriverHandle does not support the Device Path Protocol.
1654 @retval Other A pointer to the Null-terminate Unicode <ConfigHdr> string
1658 ConstructConfigHdr (
1659 IN UINT8
*OpCodeData
,
1660 IN EFI_HANDLE DriverHandle
1664 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
1665 UINTN DevicePathSize
;
1667 CHAR16
*ReturnString
;
1675 ASSERT (OpCodeData
!= NULL
);
1677 switch (((EFI_IFR_OP_HEADER
*)OpCodeData
)->OpCode
) {
1678 case EFI_IFR_VARSTORE_OP
:
1679 Guid
= (EFI_GUID
*)(UINTN
*)&((EFI_IFR_VARSTORE
*) OpCodeData
)->Guid
;
1680 AsciiName
= (CHAR8
*) ((EFI_IFR_VARSTORE
*) OpCodeData
)->Name
;
1683 case EFI_IFR_VARSTORE_NAME_VALUE_OP
:
1684 Guid
= (EFI_GUID
*)(UINTN
*)&((EFI_IFR_VARSTORE_NAME_VALUE
*) OpCodeData
)->Guid
;
1688 case EFI_IFR_VARSTORE_EFI_OP
:
1689 Guid
= (EFI_GUID
*)(UINTN
*)&((EFI_IFR_VARSTORE_EFI
*) OpCodeData
)->Guid
;
1690 AsciiName
= (CHAR8
*) ((EFI_IFR_VARSTORE_EFI
*) OpCodeData
)->Name
;
1700 if (AsciiName
!= NULL
) {
1701 Name
= AllocateZeroPool (AsciiStrSize (AsciiName
) * 2);
1702 ASSERT (Name
!= NULL
);
1703 AsciiStrToUnicodeStr(AsciiName
, Name
);
1709 // Compute the length of Name in Unicode characters.
1710 // If Name is NULL, then the length is 0.
1714 NameLength
= StrLen (Name
);
1720 // Retrieve DevicePath Protocol associated with DriverHandle
1722 if (DriverHandle
!= NULL
) {
1723 DevicePath
= DevicePathFromHandle (DriverHandle
);
1724 if (DevicePath
== NULL
) {
1728 // Compute the size of the device path in bytes
1730 DevicePathSize
= GetDevicePathSize (DevicePath
);
1734 // GUID=<HexCh>32&NAME=<Char>NameLength&PATH=<HexChar>DevicePathSize <Null>
1735 // | 5 | sizeof (EFI_GUID) * 2 | 6 | NameStrLen*4 | 6 | DevicePathSize * 2 | 1 |
1737 MaxLen
= 5 + sizeof (EFI_GUID
) * 2 + 6 + NameLength
* 4 + 6 + DevicePathSize
* 2 + 1;
1738 String
= AllocateZeroPool (MaxLen
* sizeof (CHAR16
));
1739 if (String
== NULL
) {
1744 // Start with L"GUID="
1746 StrCpyS (String
, MaxLen
, L
"GUID=");
1747 ReturnString
= String
;
1748 String
+= StrLen (String
);
1752 // Append Guid converted to <HexCh>32
1754 for (Index
= 0, Buffer
= (UINT8
*)Guid
; Index
< sizeof (EFI_GUID
); Index
++) {
1755 String
+= UnicodeValueToString (String
, PREFIX_ZERO
| RADIX_HEX
, *(Buffer
++), 2);
1762 StrCpyS (String
, MaxLen
, L
"&NAME=");
1763 String
+= StrLen (String
);
1767 // Append Name converted to <Char>NameLength
1769 for (; *Name
!= L
'\0'; Name
++) {
1770 String
+= UnicodeValueToString (String
, PREFIX_ZERO
| RADIX_HEX
, *Name
, 4);
1777 StrCpyS (String
, MaxLen
, L
"&PATH=");
1778 String
+= StrLen (String
);
1781 // Append the device path associated with DriverHandle converted to <HexChar>DevicePathSize
1783 for (Index
= 0, Buffer
= (UINT8
*)DevicePath
; Index
< DevicePathSize
; Index
++) {
1784 String
+= UnicodeValueToString (String
, PREFIX_ZERO
| RADIX_HEX
, *(Buffer
++), 2);
1788 // Null terminate the Unicode string
1793 // Convert all hex digits in range [A-F] in the configuration header to [a-f]
1795 return InternalLowerConfigString (ReturnString
);
1799 Generate the Config request element for one question.
1801 @param Name The name info for one question.
1802 @param Offset The offset info for one question.
1803 @param Width The width info for one question.
1805 @return Pointer to the Null-terminated Unicode request element string.
1809 ConstructRequestElement (
1820 // Add <BlockName> length for each Name
1822 // <BlockName> ::= Name + \0
1825 Length
= StrLen (Name
) + 1;
1828 // Add <BlockName> length for each Offset/Width pair
1830 // <BlockName> ::= OFFSET=1234&WIDTH=1234 + \0
1831 // | 7 | 4 | 7 | 4 | 1
1833 Length
= (7 + 4 + 7 + 4 + 1);
1837 // Allocate buffer for the entire <ConfigRequest>
1839 StringPtr
= AllocateZeroPool (Length
* sizeof (CHAR16
));
1840 ASSERT (StringPtr
!= NULL
);
1848 (StrLen (Name
) + 1) * sizeof (CHAR16
),
1854 // Append OFFSET=XXXX&WIDTH=YYYY\0
1858 (7 + 4 + 7 + 4 + 1) * sizeof (CHAR16
),
1859 L
"OFFSET=%04X&WIDTH=%04X",
1869 Get string value for question's name field.
1871 @param DatabaseRecord HII_DATABASE_RECORD format string.
1872 @param NameId The string id for the name field.
1874 @retval Name string.
1879 IN HII_DATABASE_RECORD
*DatabaseRecord
,
1880 IN EFI_STRING_ID NameId
1884 CHAR8
*PlatformLanguage
;
1885 CHAR8
*SupportedLanguages
;
1886 CHAR8
*BestLanguage
;
1892 BestLanguage
= NULL
;
1893 PlatformLanguage
= NULL
;
1894 SupportedLanguages
= NULL
;
1896 GetEfiGlobalVariable2 (L
"PlatformLang", (VOID
**)&PlatformLanguage
, NULL
);
1897 SupportedLanguages
= GetSupportedLanguages(DatabaseRecord
->Handle
);
1900 // Get the best matching language from SupportedLanguages
1902 BestLanguage
= GetBestLanguage (
1904 FALSE
, // RFC 4646 mode
1905 PlatformLanguage
!= NULL
? PlatformLanguage
: "", // Highest priority
1906 SupportedLanguages
, // Lowest priority
1909 if (BestLanguage
== NULL
) {
1910 BestLanguage
= AllocateCopyPool (AsciiStrLen ("en-US"), "en-US");
1911 ASSERT (BestLanguage
!= NULL
);
1915 Status
= mPrivate
.HiiString
.GetString (
1916 &mPrivate
.HiiString
,
1918 DatabaseRecord
->Handle
,
1924 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
1928 Name
= AllocateZeroPool (StringSize
);
1933 Status
= mPrivate
.HiiString
.GetString (
1934 &mPrivate
.HiiString
,
1936 DatabaseRecord
->Handle
,
1943 if (EFI_ERROR (Status
)) {
1950 if (SupportedLanguages
!= NULL
) {
1951 FreePool(SupportedLanguages
);
1953 if (BestLanguage
!= NULL
) {
1954 FreePool (BestLanguage
);
1956 if (PlatformLanguage
!= NULL
) {
1957 FreePool (PlatformLanguage
);
1964 Base on the input parameter to generate the ConfigRequest string.
1966 This is a internal function.
1968 @param DatabaseRecord HII_DATABASE_RECORD format string.
1969 @param KeywordStrId Keyword string id.
1970 @param OpCodeData The IFR data for this question.
1971 @param ConfigRequest Return the generate ConfigRequest string.
1973 @retval EFI_SUCCESS Generate ConfigResp string success.
1974 @retval EFI_OUT_OF_RESOURCES System out of memory resource error.
1975 @retval EFI_NOT_FOUND Not found the question which use this string id
1976 as the prompt string id.
1979 ExtractConfigRequest (
1980 IN HII_DATABASE_RECORD
*DatabaseRecord
,
1981 IN EFI_STRING_ID KeywordStrId
,
1982 OUT UINT8
**OpCodeData
,
1983 OUT EFI_STRING
*ConfigRequest
1987 HII_DATABASE_PACKAGE_LIST_INSTANCE
*PackageListNode
;
1988 HII_IFR_PACKAGE_INSTANCE
*FormPackage
;
1989 EFI_IFR_QUESTION_HEADER
*Header
;
1996 CHAR16
*RequestElement
;
2000 ASSERT (DatabaseRecord
!= NULL
&& OpCodeData
!= NULL
&& ConfigRequest
!= NULL
);
2007 PackageListNode
= DatabaseRecord
->PackageList
;
2010 // Search the languages in the specified packagelist.
2012 for (Link
= PackageListNode
->FormPkgHdr
.ForwardLink
; Link
!= &PackageListNode
->FormPkgHdr
; Link
= Link
->ForwardLink
) {
2013 FormPackage
= CR (Link
, HII_IFR_PACKAGE_INSTANCE
, IfrEntry
, HII_IFR_PACKAGE_SIGNATURE
);
2015 OpCode
= FindQuestionFromStringId (FormPackage
, KeywordStrId
);
2016 if (OpCode
!= NULL
) {
2017 *OpCodeData
= OpCode
;
2018 Header
= (EFI_IFR_QUESTION_HEADER
*) (OpCode
+ sizeof (EFI_IFR_OP_HEADER
));
2020 // Header->VarStoreId == 0 means no storage for this question.
2022 ASSERT (Header
->VarStoreId
!= 0);
2023 DEBUG ((EFI_D_INFO
, "Varstore Id: 0x%x\n", Header
->VarStoreId
));
2025 Storage
= FindStorageFromVarId (FormPackage
, Header
->VarStoreId
);
2026 ASSERT (Storage
!= NULL
);
2028 if (((EFI_IFR_OP_HEADER
*) Storage
)->OpCode
== EFI_IFR_VARSTORE_NAME_VALUE_OP
) {
2029 Name
= GetNameFromId (DatabaseRecord
, Header
->VarStoreInfo
.VarName
);
2031 Offset
= Header
->VarStoreInfo
.VarOffset
;
2032 Width
= GetWidth (OpCode
);
2034 RequestElement
= ConstructRequestElement(Name
, Offset
, Width
);
2035 ConfigHdr
= ConstructConfigHdr(Storage
, DatabaseRecord
->DriverHandle
);
2036 ASSERT (ConfigHdr
!= NULL
);
2038 MaxLen
= StrLen (ConfigHdr
) + 1 + StrLen(RequestElement
) + 1;
2039 *ConfigRequest
= AllocatePool (MaxLen
* sizeof (CHAR16
));
2040 if (*ConfigRequest
== NULL
) {
2041 FreePool (ConfigHdr
);
2042 FreePool (RequestElement
);
2043 return EFI_OUT_OF_RESOURCES
;
2045 StringPtr
= *ConfigRequest
;
2047 StrCpyS (StringPtr
, MaxLen
, ConfigHdr
);
2048 StringPtr
+= StrLen (StringPtr
);
2053 StrCpyS (StringPtr
, MaxLen
, RequestElement
);
2054 StringPtr
+= StrLen (StringPtr
);
2057 FreePool (ConfigHdr
);
2058 FreePool (RequestElement
);
2064 return EFI_NOT_FOUND
;
2068 Base on the input parameter to generate the ConfigResp string.
2070 This is a internal function.
2072 @param DatabaseRecord HII_DATABASE_RECORD format string.
2073 @param KeywordStrId Keyword string id.
2074 @param ValueElement The value for the question which use keyword string id
2075 as the prompt string id.
2076 @param OpCodeData The IFR data for this question.
2077 @param ConfigResp Return the generate ConfigResp string.
2079 @retval EFI_SUCCESS Generate ConfigResp string success.
2080 @retval EFI_OUT_OF_RESOURCES System out of memory resource error.
2081 @retval EFI_NOT_FOUND Not found the question which use this string id
2082 as the prompt string id.
2086 IN HII_DATABASE_RECORD
*DatabaseRecord
,
2087 IN EFI_STRING_ID KeywordStrId
,
2088 IN EFI_STRING ValueElement
,
2089 OUT UINT8
**OpCodeData
,
2090 OUT EFI_STRING
*ConfigResp
2094 HII_DATABASE_PACKAGE_LIST_INSTANCE
*PackageListNode
;
2095 HII_IFR_PACKAGE_INSTANCE
*FormPackage
;
2096 EFI_IFR_QUESTION_HEADER
*Header
;
2103 CHAR16
*RequestElement
;
2107 ASSERT ((DatabaseRecord
!= NULL
) && (OpCodeData
!= NULL
) && (ConfigResp
!= NULL
) && (ValueElement
!= NULL
));
2114 PackageListNode
= DatabaseRecord
->PackageList
;
2117 // Search the languages in the specified packagelist.
2119 for (Link
= PackageListNode
->FormPkgHdr
.ForwardLink
; Link
!= &PackageListNode
->FormPkgHdr
; Link
= Link
->ForwardLink
) {
2120 FormPackage
= CR (Link
, HII_IFR_PACKAGE_INSTANCE
, IfrEntry
, HII_IFR_PACKAGE_SIGNATURE
);
2122 OpCode
= FindQuestionFromStringId (FormPackage
, KeywordStrId
);
2123 if (OpCode
!= NULL
) {
2124 *OpCodeData
= OpCode
;
2125 Header
= (EFI_IFR_QUESTION_HEADER
*) (OpCode
+ sizeof (EFI_IFR_OP_HEADER
));
2127 // Header->VarStoreId == 0 means no storage for this question.
2129 ASSERT (Header
->VarStoreId
!= 0);
2130 DEBUG ((EFI_D_INFO
, "Varstore Id: 0x%x\n", Header
->VarStoreId
));
2132 Storage
= FindStorageFromVarId (FormPackage
, Header
->VarStoreId
);
2133 ASSERT (Storage
!= NULL
);
2135 if (((EFI_IFR_OP_HEADER
*) Storage
)->OpCode
== EFI_IFR_VARSTORE_NAME_VALUE_OP
) {
2136 Name
= GetNameFromId (DatabaseRecord
, Header
->VarStoreInfo
.VarName
);
2138 Offset
= Header
->VarStoreInfo
.VarOffset
;
2139 Width
= GetWidth (OpCode
);
2141 RequestElement
= ConstructRequestElement(Name
, Offset
, Width
);
2143 ConfigHdr
= ConstructConfigHdr(Storage
, DatabaseRecord
->DriverHandle
);
2144 ASSERT (ConfigHdr
!= NULL
);
2146 MaxLen
= StrLen (ConfigHdr
) + 1 + StrLen(RequestElement
) + 1 + StrLen (L
"VALUE=") + StrLen(ValueElement
) + 1;
2147 *ConfigResp
= AllocatePool (MaxLen
* sizeof (CHAR16
));
2148 if (*ConfigResp
== NULL
) {
2149 FreePool (ConfigHdr
);
2150 FreePool (RequestElement
);
2151 return EFI_OUT_OF_RESOURCES
;
2153 StringPtr
= *ConfigResp
;
2155 StrCpyS (StringPtr
, MaxLen
, ConfigHdr
);
2156 StringPtr
+= StrLen (StringPtr
);
2161 StrCpyS (StringPtr
, MaxLen
, RequestElement
);
2162 StringPtr
+= StrLen (StringPtr
);
2167 StrCpyS (StringPtr
, MaxLen
, L
"VALUE=");
2168 StringPtr
+= StrLen (StringPtr
);
2170 StrCpyS (StringPtr
, MaxLen
, ValueElement
);
2171 StringPtr
+= StrLen (StringPtr
);
2174 FreePool (ConfigHdr
);
2175 FreePool (RequestElement
);
2181 return EFI_NOT_FOUND
;
2185 Get the Value section from the Hii driver.
2187 This is a internal function.
2189 @param ConfigRequest The input ConfigRequest string.
2190 @param ValueElement The respond Value section from the hii driver.
2192 @retval Misc value The error status return from ExtractConfig function.
2193 @retval EFI_OUT_OF_RESOURCES The memory can't be allocated
2194 @retval EFI_SUCCESS Get the value section success.
2198 ExtractValueFromDriver (
2199 IN CHAR16
*ConfigRequest
,
2200 OUT CHAR16
**ValueElement
2205 EFI_STRING Progress
;
2209 ASSERT ((ConfigRequest
!= NULL
) && (ValueElement
!= NULL
));
2211 Status
= mPrivate
.ConfigRouting
.ExtractConfig (
2212 &mPrivate
.ConfigRouting
,
2213 (EFI_STRING
) ConfigRequest
,
2217 if (EFI_ERROR (Status
)) {
2222 // Find Value Section and return it.
2224 StringPtr
= StrStr (Result
, L
"&VALUE=");
2225 ASSERT (StringPtr
!= NULL
);
2226 StringEnd
= StrStr (StringPtr
+ 1, L
"&");
2227 if (StringEnd
!= NULL
) {
2231 *ValueElement
= AllocateCopyPool (StrSize (StringPtr
), StringPtr
);
2232 if (*ValueElement
== NULL
) {
2233 return EFI_OUT_OF_RESOURCES
;
2236 if (StringEnd
!= NULL
) {
2245 Get EFI_STRING_ID info from the input device path, namespace and keyword.
2247 This is a internal function.
2249 @param DevicePath Input device path info.
2250 @param NameSpace NameSpace format string.
2251 @param KeywordData Keyword used to get string id.
2252 @param ProgressErr Return extra error type.
2253 @param KeywordStringId Return EFI_STRING_ID.
2254 @param DataBaseRecord DataBase record data for this driver.
2256 @retval EFI_INVALID_PARAMETER Can't find the database record base on the input device path or namespace.
2257 @retval EFI_NOT_FOUND Can't find the EFI_STRING_ID for the keyword.
2258 @retval EFI_SUCCESS Find the EFI_STRING_ID.
2262 GetStringIdFromDatabase (
2263 IN EFI_DEVICE_PATH_PROTOCOL
**DevicePath
,
2264 IN CHAR8
**NameSpace
,
2265 IN CHAR16
*KeywordData
,
2266 OUT UINT32
*ProgressErr
,
2267 OUT EFI_STRING_ID
*KeywordStringId
,
2268 OUT HII_DATABASE_RECORD
**DataBaseRecord
2271 HII_DATABASE_RECORD
*Record
;
2273 BOOLEAN FindNameSpace
;
2274 EFI_DEVICE_PATH_PROTOCOL
*DestDevicePath
;
2275 UINT8
*DevicePathPkg
;
2276 UINTN DevicePathSize
;
2278 ASSERT ((NameSpace
!= NULL
) && (KeywordData
!= NULL
) && (ProgressErr
!= NULL
) && (KeywordStringId
!= NULL
) && (DataBaseRecord
!= NULL
));
2280 FindNameSpace
= FALSE
;
2282 if (*DevicePath
!= NULL
) {
2284 // Get DataBaseRecord from device path protocol.
2286 Record
= GetRecordFromDevicePath(*DevicePath
);
2287 if (Record
== NULL
) {
2289 // Can't find the DatabaseRecord base on the input device path info.
2290 // NEED TO CONFIRM the return ProgressErr.
2292 *ProgressErr
= KEYWORD_HANDLER_MALFORMED_STRING
;
2293 return EFI_INVALID_PARAMETER
;
2297 // Get string id from the record.
2299 *ProgressErr
= GetStringIdFromRecord (Record
, NameSpace
, KeywordData
, KeywordStringId
);
2300 switch (*ProgressErr
) {
2301 case KEYWORD_HANDLER_NO_ERROR
:
2302 *DataBaseRecord
= Record
;
2305 case KEYWORD_HANDLER_NAMESPACE_ID_NOT_FOUND
:
2306 return EFI_INVALID_PARAMETER
;
2309 ASSERT (*ProgressErr
== KEYWORD_HANDLER_KEYWORD_NOT_FOUND
);
2310 return EFI_NOT_FOUND
;
2314 // Find driver which matches the routing data.
2316 for (Link
= mPrivate
.DatabaseList
.ForwardLink
; Link
!= &mPrivate
.DatabaseList
; Link
= Link
->ForwardLink
) {
2317 Record
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
2319 *ProgressErr
= GetStringIdFromRecord (Record
, NameSpace
, KeywordData
, KeywordStringId
);
2320 if (*ProgressErr
== KEYWORD_HANDLER_NO_ERROR
) {
2321 *DataBaseRecord
= Record
;
2323 if ((DevicePathPkg
= Record
->PackageList
->DevicePathPkg
) != NULL
) {
2324 DestDevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) (DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
));
2325 DevicePathSize
= GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) DestDevicePath
);
2326 *DevicePath
= AllocateCopyPool (DevicePathSize
, DestDevicePath
);
2327 if (*DevicePath
== NULL
) {
2328 return EFI_OUT_OF_RESOURCES
;
2332 // Need to verify this ASSERT.
2338 } else if (*ProgressErr
== KEYWORD_HANDLER_UNDEFINED_PROCESSING_ERROR
) {
2339 return EFI_OUT_OF_RESOURCES
;
2340 } else if (*ProgressErr
== KEYWORD_HANDLER_KEYWORD_NOT_FOUND
) {
2341 FindNameSpace
= TRUE
;
2346 // When PathHdr not input, if ever find the namespace, will return KEYWORD_HANDLER_KEYWORD_NOT_FOUND.
2347 // This is a bit more progress than KEYWORD_HANDLER_NAMESPACE_ID_NOT_FOUND.
2349 if (FindNameSpace
) {
2350 return EFI_NOT_FOUND
;
2352 return EFI_INVALID_PARAMETER
;
2358 Genereate the KeywordResp String.
2360 <KeywordResp> ::= <NameSpaceId><PathHdr>'&'<Keyword>'&VALUE='<Number>['&READONLY']
2362 @param NameSpace NameSpace format string.
2363 @param DevicePath Input device path info.
2364 @param KeywordData Keyword used to get string id.
2365 @param ValueStr The value section for the keyword.
2366 @param ReadOnly Whether this value is readonly.
2367 @param KeywordResp Return the point to the KeywordResp string.
2369 @retval EFI_OUT_OF_RESOURCES The memory can't be allocated.
2370 @retval EFI_SUCCESS Generate the KeywordResp string.
2374 GenerateKeywordResp (
2375 IN CHAR8
*NameSpace
,
2376 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
2377 IN EFI_STRING KeywordData
,
2378 IN EFI_STRING ValueStr
,
2379 IN BOOLEAN ReadOnly
,
2380 OUT EFI_STRING
*KeywordResp
2386 CHAR16
*UnicodeNameSpace
;
2388 ASSERT ((NameSpace
!= NULL
) && (DevicePath
!= NULL
) && (KeywordData
!= NULL
) && (ValueStr
!= NULL
) && (KeywordResp
!= NULL
));
2391 // 1. Calculate the string length.
2394 // 1.1 NameSpaceId size.
2395 // 'NAMESPACE='<String>
2397 RespStrLen
= 10 + AsciiStrLen (NameSpace
);
2398 UnicodeNameSpace
= AllocatePool ((AsciiStrLen (NameSpace
) + 1) * sizeof (CHAR16
));
2399 if (UnicodeNameSpace
== NULL
) {
2400 return EFI_OUT_OF_RESOURCES
;
2402 AsciiStrToUnicodeStr(NameSpace
, UnicodeNameSpace
);
2405 // 1.2 PathHdr size.
2406 // PATH=<UEFI binary Device Path represented as hex number>'&'
2407 // Attention: The output include the '&' at the end.
2411 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) DevicePath
),
2412 (VOID
*) DevicePath
,
2416 RespStrLen
+= StrLen (PathHdr
);
2419 // 1.3 Keyword setion.
2420 // 'KEYWORD='<String>[':'<DecCh>(1/4)]
2422 RespStrLen
+= 8 + StrLen (KeywordData
);
2425 // 1.4 Value section.
2426 // ValueStr = '&VALUE='<Number>
2428 RespStrLen
+= StrLen (ValueStr
);
2431 // 1.5 ReadOnly Section.
2439 // 2. Allocate the buffer and create the KeywordResp string include '\0'.
2442 *KeywordResp
= AllocatePool (RespStrLen
* sizeof (CHAR16
));
2443 if (*KeywordResp
== NULL
) {
2444 if (UnicodeNameSpace
!= NULL
) {
2445 FreePool (UnicodeNameSpace
);
2448 return EFI_OUT_OF_RESOURCES
;
2450 RespStr
= *KeywordResp
;
2453 // 2.1 Copy NameSpaceId section.
2455 StrCpyS (RespStr
, RespStrLen
, L
"NAMESPACE=");
2456 RespStr
+= StrLen (RespStr
);
2457 StrCpyS (RespStr
, RespStrLen
, UnicodeNameSpace
);
2458 RespStr
+= StrLen (RespStr
);
2461 // 2.2 Copy PathHdr section.
2463 StrCpyS (RespStr
, RespStrLen
, PathHdr
);
2464 RespStr
+= StrLen (RespStr
);
2467 // 2.3 Copy Keyword section.
2469 StrCpyS (RespStr
, RespStrLen
, L
"KEYWORD=");
2470 RespStr
+= StrLen (RespStr
);
2471 StrCpyS (RespStr
, RespStrLen
, KeywordData
);
2472 RespStr
+= StrLen (RespStr
);
2475 // 2.4 Copy the Value section.
2477 StrCpyS (RespStr
, RespStrLen
, ValueStr
);
2478 RespStr
+= StrLen (RespStr
);
2481 // 2.5 Copy ReadOnly section if exist.
2484 StrCpyS (RespStr
, RespStrLen
, L
"&READONLY");
2485 RespStr
+= StrLen (RespStr
);
2493 if (UnicodeNameSpace
!= NULL
) {
2494 FreePool (UnicodeNameSpace
);
2496 if (PathHdr
!= NULL
) {
2504 Merge the KeywordResp String to MultiKeywordResp string.
2506 This is a internal function.
2508 @param MultiKeywordResp The existed multikeywordresp string.
2509 @param KeywordResp The input keywordResp string.
2511 @retval EFI_OUT_OF_RESOURCES The memory can't be allocated.
2512 @retval EFI_SUCCESS Generate the MultiKeywordResp string.
2516 MergeToMultiKeywordResp (
2517 IN OUT EFI_STRING
*MultiKeywordResp
,
2518 IN EFI_STRING
*KeywordResp
2521 UINTN MultiKeywordRespLen
;
2522 EFI_STRING StringPtr
;
2524 if (*MultiKeywordResp
== NULL
) {
2525 *MultiKeywordResp
= *KeywordResp
;
2526 *KeywordResp
= NULL
;
2530 MultiKeywordRespLen
= (StrLen (*MultiKeywordResp
) + 1 + StrLen (*KeywordResp
) + 1) * sizeof (CHAR16
);
2532 StringPtr
= AllocateCopyPool (MultiKeywordRespLen
, *MultiKeywordResp
);
2533 if (StringPtr
== NULL
) {
2534 return EFI_OUT_OF_RESOURCES
;
2537 FreePool (*MultiKeywordResp
);
2538 *MultiKeywordResp
= StringPtr
;
2540 StringPtr
+= StrLen (StringPtr
);
2545 StrCpyS (StringPtr
, MultiKeywordRespLen
/ sizeof (CHAR16
), *KeywordResp
);
2551 Enumerate all keyword in the system.
2553 If error occur when parse one keyword, just skip it and parse the next one.
2555 This is a internal function.
2557 @param NameSpace The namespace used to search the string.
2558 @param MultiResp Return the MultiKeywordResp string for the system.
2560 @retval EFI_OUT_OF_RESOURCES The memory can't be allocated.
2561 @retval EFI_SUCCESS Generate the MultiKeywordResp string.
2562 @retval EFI_NOT_FOUND No keyword found.
2566 EnumerateAllKeywords (
2567 IN CHAR8
*NameSpace
,
2568 OUT EFI_STRING
*MultiResp
2572 LIST_ENTRY
*StringLink
;
2573 UINT8
*DevicePathPkg
;
2575 HII_DATABASE_RECORD
*DataBaseRecord
;
2576 HII_DATABASE_PACKAGE_LIST_INSTANCE
*PackageListNode
;
2577 HII_STRING_PACKAGE_INSTANCE
*StringPackage
;
2578 CHAR8
*LocalNameSpace
;
2579 EFI_STRING_ID NextStringId
;
2582 CHAR16
*ConfigRequest
;
2583 CHAR16
*ValueElement
;
2584 CHAR16
*KeywordResp
;
2585 CHAR16
*MultiKeywordResp
;
2586 CHAR16
*KeywordData
;
2589 DataBaseRecord
= NULL
;
2590 Status
= EFI_SUCCESS
;
2591 MultiKeywordResp
= NULL
;
2593 LocalNameSpace
= NULL
;
2594 ConfigRequest
= NULL
;
2595 ValueElement
= NULL
;
2598 if (NameSpace
== NULL
) {
2599 NameSpace
= UEFI_CONFIG_LANG
;
2603 // Find driver which matches the routing data.
2605 for (Link
= mPrivate
.DatabaseList
.ForwardLink
; Link
!= &mPrivate
.DatabaseList
; Link
= Link
->ForwardLink
) {
2606 DataBaseRecord
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
2607 if ((DevicePathPkg
= DataBaseRecord
->PackageList
->DevicePathPkg
) != NULL
) {
2608 DevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
2610 PackageListNode
= DataBaseRecord
->PackageList
;
2612 for (StringLink
= PackageListNode
->StringPkgHdr
.ForwardLink
; StringLink
!= &PackageListNode
->StringPkgHdr
; StringLink
= StringLink
->ForwardLink
) {
2613 StringPackage
= CR (StringLink
, HII_STRING_PACKAGE_INSTANCE
, StringEntry
, HII_STRING_PACKAGE_SIGNATURE
);
2616 // Check whether has keyword string package.
2618 if (AsciiStrnCmp(NameSpace
, StringPackage
->StringPkgHdr
->Language
, AsciiStrLen (NameSpace
)) == 0) {
2620 // Keep the NameSpace string.
2622 LocalNameSpace
= AllocateCopyPool (AsciiStrSize (StringPackage
->StringPkgHdr
->Language
), StringPackage
->StringPkgHdr
->Language
);
2623 if (LocalNameSpace
== NULL
) {
2624 return EFI_OUT_OF_RESOURCES
;
2628 // 1 means just begin the enumerate the valid string ids.
2629 // StringId == 1 is always used to save the language for this string package.
2630 // Any valid string start from 2. so here initial it to 1.
2635 // Enumerate all valid stringid in the package.
2637 while ((NextStringId
= GetNextStringId (StringPackage
, NextStringId
, &KeywordData
)) != 0) {
2639 // 3.3 Construct the ConfigRequest string.
2641 Status
= ExtractConfigRequest (DataBaseRecord
, NextStringId
, &OpCode
, &ConfigRequest
);
2642 if (EFI_ERROR (Status
)) {
2644 // If can't generate ConfigRequest for this question, skip it and start the next.
2650 // 3.4 Extract Value for the input keyword.
2652 Status
= ExtractValueFromDriver(ConfigRequest
, &ValueElement
);
2653 if (EFI_ERROR (Status
)) {
2654 if (Status
!= EFI_OUT_OF_RESOURCES
) {
2656 // If can't generate ConfigRequest for this question, skip it and start the next.
2661 // If EFI_OUT_OF_RESOURCES error occur, no need to continue.
2667 // Extract readonly flag from opcode.
2669 ReadOnly
= ExtractReadOnlyFromOpCode(OpCode
);
2672 // 5. Generate KeywordResp string.
2674 ASSERT (DevicePath
!= NULL
);
2675 Status
= GenerateKeywordResp(LocalNameSpace
, (EFI_DEVICE_PATH_PROTOCOL
*)DevicePath
, KeywordData
, ValueElement
, ReadOnly
, &KeywordResp
);
2676 if (Status
!= EFI_SUCCESS
) {
2678 // If EFI_OUT_OF_RESOURCES error occur, no need to continue.
2684 // 6. Merge to the MultiKeywordResp string.
2686 Status
= MergeToMultiKeywordResp(&MultiKeywordResp
, &KeywordResp
);
2687 if (EFI_ERROR (Status
)) {
2692 // Clean the temp buffer to later use again.
2694 if (ConfigRequest
!= NULL
) {
2695 FreePool (ConfigRequest
);
2696 ConfigRequest
= NULL
;
2698 if (ValueElement
!= NULL
) {
2699 FreePool (ValueElement
);
2700 ValueElement
= NULL
;
2702 if (KeywordResp
!= NULL
) {
2703 FreePool (KeywordResp
);
2708 if (LocalNameSpace
!= NULL
) {
2709 FreePool (LocalNameSpace
);
2710 LocalNameSpace
= NULL
;
2717 // return the already get MultiKeywordString even error occured.
2719 if (MultiKeywordResp
== NULL
) {
2720 Status
= EFI_NOT_FOUND
;
2722 Status
= EFI_SUCCESS
;
2724 *MultiResp
= MultiKeywordResp
;
2727 if (LocalNameSpace
!= NULL
) {
2728 FreePool (LocalNameSpace
);
2730 if (ConfigRequest
!= NULL
) {
2731 FreePool (ConfigRequest
);
2733 if (ValueElement
!= NULL
) {
2734 FreePool (ValueElement
);
2742 This function accepts a <MultiKeywordResp> formatted string, finds the associated
2743 keyword owners, creates a <MultiConfigResp> string from it and forwards it to the
2744 EFI_HII_ROUTING_PROTOCOL.RouteConfig function.
2746 If there is an issue in resolving the contents of the KeywordString, then the
2747 function returns an error and also sets the Progress and ProgressErr with the
2748 appropriate information about where the issue occurred and additional data about
2749 the nature of the issue.
2751 In the case when KeywordString containing multiple keywords, when an EFI_NOT_FOUND
2752 error is generated during processing the second or later keyword element, the system
2753 storage associated with earlier keywords is not modified. All elements of the
2754 KeywordString must successfully pass all tests for format and access prior to making
2755 any modifications to storage.
2757 In the case when EFI_DEVICE_ERROR is returned from the processing of a KeywordString
2758 containing multiple keywords, the state of storage associated with earlier keywords
2762 @param This Pointer to the EFI_KEYWORD_HANDLER _PROTOCOL instance.
2764 @param KeywordString A null-terminated string in <MultiKeywordResp> format.
2766 @param Progress On return, points to a character in the KeywordString.
2767 Points to the string's NULL terminator if the request
2768 was successful. Points to the most recent '&' before
2769 the first failing string element if the request was
2772 @param ProgressErr If during the processing of the KeywordString there was
2773 a failure, this parameter gives additional information
2774 about the possible source of the problem. The various
2775 errors are defined in "Related Definitions" below.
2778 @retval EFI_SUCCESS The specified action was completed successfully.
2780 @retval EFI_INVALID_PARAMETER One or more of the following are TRUE:
2781 1. KeywordString is NULL.
2782 2. Parsing of the KeywordString resulted in an
2783 error. See Progress and ProgressErr for more data.
2785 @retval EFI_NOT_FOUND An element of the KeywordString was not found.
2786 See ProgressErr for more data.
2788 @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
2789 See ProgressErr for more data.
2791 @retval EFI_ACCESS_DENIED The action violated system policy. See ProgressErr
2794 @retval EFI_DEVICE_ERROR An unexpected system error occurred. See ProgressErr
2800 EfiConfigKeywordHandlerSetData (
2801 IN EFI_CONFIG_KEYWORD_HANDLER_PROTOCOL
*This
,
2802 IN CONST EFI_STRING KeywordString
,
2803 OUT EFI_STRING
*Progress
,
2804 OUT UINT32
*ProgressErr
2810 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
2811 CHAR16
*NextStringPtr
;
2812 CHAR16
*KeywordData
;
2813 EFI_STRING_ID KeywordStringId
;
2815 HII_DATABASE_RECORD
*DataBaseRecord
;
2818 CHAR16
*MultiConfigResp
;
2819 CHAR16
*ValueElement
;
2821 EFI_STRING InternalProgress
;
2824 if (This
== NULL
|| Progress
== NULL
|| ProgressErr
== NULL
|| KeywordString
== NULL
) {
2825 return EFI_INVALID_PARAMETER
;
2828 *Progress
= KeywordString
;
2829 *ProgressErr
= KEYWORD_HANDLER_UNDEFINED_PROCESSING_ERROR
;
2830 Status
= EFI_SUCCESS
;
2831 MultiConfigResp
= NULL
;
2835 ValueElement
= NULL
;
2837 KeywordStringId
= 0;
2840 // Use temp string to avoid changing input string buffer.
2842 TempString
= AllocateCopyPool (StrSize (KeywordString
), KeywordString
);
2843 ASSERT (TempString
!= NULL
);
2844 StringPtr
= TempString
;
2846 while ((StringPtr
!= NULL
) && (*StringPtr
!= L
'\0')) {
2848 // 1. Get NameSpace from NameSpaceId keyword.
2850 Status
= ExtractNameSpace (StringPtr
, &NameSpace
, &NextStringPtr
);
2851 if (EFI_ERROR (Status
)) {
2852 *ProgressErr
= KEYWORD_HANDLER_MALFORMED_STRING
;
2855 ASSERT (NameSpace
!= NULL
);
2857 // 1.1 Check whether the input namespace is valid.
2859 if (AsciiStrnCmp(NameSpace
, UEFI_CONFIG_LANG
, AsciiStrLen (UEFI_CONFIG_LANG
)) != 0) {
2860 *ProgressErr
= KEYWORD_HANDLER_UNDEFINED_PROCESSING_ERROR
;
2861 Status
= EFI_INVALID_PARAMETER
;
2865 StringPtr
= NextStringPtr
;
2868 // 2. Get possible Device Path info from KeywordString.
2870 Status
= ExtractDevicePath (StringPtr
, (UINT8
**)&DevicePath
, &NextStringPtr
);
2871 if (EFI_ERROR (Status
)) {
2872 *ProgressErr
= KEYWORD_HANDLER_MALFORMED_STRING
;
2875 StringPtr
= NextStringPtr
;
2878 // 3. Extract keyword from the KeywordRequest string.
2880 Status
= ExtractKeyword(StringPtr
, &KeywordData
, &NextStringPtr
);
2881 if (EFI_ERROR (Status
)) {
2883 // Can't find Keyword base on the input device path info.
2885 *ProgressErr
= KEYWORD_HANDLER_MALFORMED_STRING
;
2886 Status
= EFI_INVALID_PARAMETER
;
2889 StringPtr
= NextStringPtr
;
2892 // 4. Extract Value from the KeywordRequest string.
2894 Status
= ExtractValue (StringPtr
, &ValueElement
, &NextStringPtr
);
2895 if (EFI_ERROR (Status
)) {
2897 // Can't find Value base on the input device path info.
2899 *ProgressErr
= KEYWORD_HANDLER_MALFORMED_STRING
;
2900 Status
= EFI_INVALID_PARAMETER
;
2903 StringPtr
= NextStringPtr
;
2906 // 5. Find ReadOnly filter.
2908 if ((StringPtr
!= NULL
) && StrnCmp (StringPtr
, L
"&ReadOnly", StrLen (L
"&ReadOnly")) == 0) {
2910 StringPtr
+= StrLen (L
"&ReadOnly");
2916 // 6. Get EFI_STRING_ID for the input keyword.
2918 Status
= GetStringIdFromDatabase (&DevicePath
, &NameSpace
, KeywordData
, &RetVal
, &KeywordStringId
, &DataBaseRecord
);
2919 if (EFI_ERROR (Status
)) {
2920 *ProgressErr
= RetVal
;
2925 // 7. Construct the ConfigRequest string.
2927 Status
= ExtractConfigResp (DataBaseRecord
, KeywordStringId
, ValueElement
, &OpCode
, &ConfigResp
);
2928 if (EFI_ERROR (Status
)) {
2933 // 8. Check the readonly flag.
2935 if (ExtractReadOnlyFromOpCode (OpCode
) != ReadOnly
) {
2936 *ProgressErr
= KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED
;
2937 Status
= EFI_INVALID_PARAMETER
;
2942 // 9. Merge to the MultiKeywordResp string.
2944 Status
= MergeToMultiKeywordResp(&MultiConfigResp
, &ConfigResp
);
2945 if (EFI_ERROR (Status
)) {
2950 // 10. Clean the temp buffer point.
2952 FreePool (NameSpace
);
2953 FreePool (DevicePath
);
2954 FreePool (KeywordData
);
2955 FreePool (ValueElement
);
2959 ValueElement
= NULL
;
2960 if (ConfigResp
!= NULL
) {
2961 FreePool (ConfigResp
);
2967 // 11. Set value to driver.
2969 Status
= mPrivate
.ConfigRouting
.RouteConfig(
2970 &mPrivate
.ConfigRouting
,
2971 (EFI_STRING
) MultiConfigResp
,
2974 if (EFI_ERROR (Status
)) {
2975 Status
= EFI_DEVICE_ERROR
;
2979 *ProgressErr
= KEYWORD_HANDLER_NO_ERROR
;
2982 ASSERT (TempString
!= NULL
);
2983 FreePool (TempString
);
2984 if (NameSpace
!= NULL
) {
2985 FreePool (NameSpace
);
2987 if (DevicePath
!= NULL
) {
2988 FreePool (DevicePath
);
2990 if (KeywordData
!= NULL
) {
2991 FreePool (KeywordData
);
2993 if (ValueElement
!= NULL
) {
2994 FreePool (ValueElement
);
2996 if (ConfigResp
!= NULL
) {
2997 FreePool (ConfigResp
);
2999 if (MultiConfigResp
!= NULL
&& MultiConfigResp
!= ConfigResp
) {
3000 FreePool (MultiConfigResp
);
3002 *Progress
= StringPtr
;
3008 This function accepts a <MultiKeywordRequest> formatted string, finds the underlying
3009 keyword owners, creates a <MultiConfigRequest> string from it and forwards it to the
3010 EFI_HII_ROUTING_PROTOCOL.ExtractConfig function.
3012 If there is an issue in resolving the contents of the KeywordString, then the function
3013 returns an EFI_INVALID_PARAMETER and also set the Progress and ProgressErr with the
3014 appropriate information about where the issue occurred and additional data about the
3015 nature of the issue.
3017 In the case when KeywordString is NULL, or contains multiple keywords, or when
3018 EFI_NOT_FOUND is generated while processing the keyword elements, the Results string
3019 contains values returned for all keywords processed prior to the keyword generating the
3020 error but no values for the keyword with error or any following keywords.
3023 @param This Pointer to the EFI_KEYWORD_HANDLER _PROTOCOL instance.
3025 @param NameSpaceId A null-terminated string containing the platform configuration
3026 language to search through in the system. If a NULL is passed
3027 in, then it is assumed that any platform configuration language
3028 with the prefix of "x-UEFI-" are searched.
3030 @param KeywordString A null-terminated string in <MultiKeywordRequest> format. If a
3031 NULL is passed in the KeywordString field, all of the known
3032 keywords in the system for the NameSpaceId specified are
3033 returned in the Results field.
3035 @param Progress On return, points to a character in the KeywordString. Points
3036 to the string's NULL terminator if the request was successful.
3037 Points to the most recent '&' before the first failing string
3038 element if the request was not successful.
3040 @param ProgressErr If during the processing of the KeywordString there was a
3041 failure, this parameter gives additional information about the
3042 possible source of the problem. See the definitions in SetData()
3043 for valid value definitions.
3045 @param Results A null-terminated string in <MultiKeywordResp> format is returned
3046 which has all the values filled in for the keywords in the
3047 KeywordString. This is a callee-allocated field, and must be freed
3048 by the caller after being used.
3050 @retval EFI_SUCCESS The specified action was completed successfully.
3052 @retval EFI_INVALID_PARAMETER One or more of the following are TRUE:
3053 1.Progress, ProgressErr, or Resuts is NULL.
3054 2.Parsing of the KeywordString resulted in an error. See
3055 Progress and ProgressErr for more data.
3058 @retval EFI_NOT_FOUND An element of the KeywordString was not found. See
3059 ProgressErr for more data.
3061 @retval EFI_NOT_FOUND The NamespaceId specified was not found. See ProgressErr
3064 @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated. See
3065 ProgressErr for more data.
3067 @retval EFI_ACCESS_DENIED The action violated system policy. See ProgressErr for
3070 @retval EFI_DEVICE_ERROR An unexpected system error occurred. See ProgressErr
3076 EfiConfigKeywordHandlerGetData (
3077 IN EFI_CONFIG_KEYWORD_HANDLER_PROTOCOL
*This
,
3078 IN CONST EFI_STRING NameSpaceId
, OPTIONAL
3079 IN CONST EFI_STRING KeywordString
, OPTIONAL
3080 OUT EFI_STRING
*Progress
,
3081 OUT UINT32
*ProgressErr
,
3082 OUT EFI_STRING
*Results
3087 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
3088 HII_DATABASE_RECORD
*DataBaseRecord
;
3090 CHAR16
*NextStringPtr
;
3091 CHAR16
*KeywordData
;
3092 EFI_STRING_ID KeywordStringId
;
3094 CHAR16
*ConfigRequest
;
3095 CHAR16
*ValueElement
;
3098 CHAR16
*KeywordResp
;
3099 CHAR16
*MultiKeywordResp
;
3102 if (This
== NULL
|| Progress
== NULL
|| ProgressErr
== NULL
|| Results
== NULL
) {
3103 return EFI_INVALID_PARAMETER
;
3106 *ProgressErr
= KEYWORD_HANDLER_UNDEFINED_PROCESSING_ERROR
;
3107 Status
= EFI_SUCCESS
;
3111 ConfigRequest
= NULL
;
3112 StringPtr
= KeywordString
;
3114 MultiKeywordResp
= NULL
;
3115 KeywordStringId
= 0;
3119 // Use temp string to avoid changing input string buffer.
3121 if (NameSpaceId
!= NULL
) {
3122 TempString
= AllocateCopyPool (StrSize (NameSpaceId
), NameSpaceId
);
3123 ASSERT (TempString
!= NULL
);
3126 // 1. Get NameSpace from NameSpaceId keyword.
3128 Status
= ExtractNameSpace (TempString
, &NameSpace
, NULL
);
3129 if (TempString
!= NULL
) {
3130 FreePool (TempString
);
3133 if (EFI_ERROR (Status
)) {
3134 *ProgressErr
= KEYWORD_HANDLER_NAMESPACE_ID_NOT_FOUND
;
3138 // 1.1 Check whether the input namespace is valid.
3140 if (NameSpace
!= NULL
){
3141 if (AsciiStrnCmp(NameSpace
, UEFI_CONFIG_LANG
, AsciiStrLen (UEFI_CONFIG_LANG
)) != 0) {
3142 *ProgressErr
= KEYWORD_HANDLER_UNDEFINED_PROCESSING_ERROR
;
3143 return EFI_INVALID_PARAMETER
;
3147 if (KeywordString
!= NULL
) {
3149 // Use temp string to avoid changing input string buffer.
3151 TempString
= AllocateCopyPool (StrSize (KeywordString
), KeywordString
);
3152 ASSERT (TempString
!= NULL
);
3153 StringPtr
= TempString
;
3155 while (*StringPtr
!= L
'\0') {
3157 // 2. Get possible Device Path info from KeywordString.
3159 Status
= ExtractDevicePath (StringPtr
, (UINT8
**)&DevicePath
, &NextStringPtr
);
3160 if (EFI_ERROR (Status
)) {
3161 *ProgressErr
= KEYWORD_HANDLER_MALFORMED_STRING
;
3164 StringPtr
= NextStringPtr
;
3168 // 3. Process Keyword section from the input keywordRequest string.
3170 // 3.1 Extract keyword from the KeywordRequest string.
3172 Status
= ExtractKeyword(StringPtr
, &KeywordData
, &NextStringPtr
);
3173 if (EFI_ERROR (Status
)) {
3175 // Can't find Keyword base on the input device path info.
3177 *ProgressErr
= KEYWORD_HANDLER_MALFORMED_STRING
;
3178 Status
= EFI_INVALID_PARAMETER
;
3183 // 3.2 Get EFI_STRING_ID for the input keyword.
3185 Status
= GetStringIdFromDatabase (&DevicePath
, &NameSpace
, KeywordData
, &RetVal
, &KeywordStringId
, &DataBaseRecord
);
3186 if (EFI_ERROR (Status
)) {
3187 *ProgressErr
= RetVal
;
3192 // 3.3 Construct the ConfigRequest string.
3194 Status
= ExtractConfigRequest (DataBaseRecord
, KeywordStringId
, &OpCode
, &ConfigRequest
);
3195 if (EFI_ERROR (Status
)) {
3200 // 3.4 Extract Value for the input keyword.
3202 Status
= ExtractValueFromDriver(ConfigRequest
, &ValueElement
);
3203 if (EFI_ERROR (Status
)) {
3204 if (Status
!= EFI_OUT_OF_RESOURCES
) {
3205 Status
= EFI_DEVICE_ERROR
;
3209 StringPtr
= NextStringPtr
;
3212 // 4. Process the possible filter section.
3214 RetVal
= ValidateFilter (OpCode
, StringPtr
, &NextStringPtr
, &ReadOnly
);
3215 if (RetVal
!= KEYWORD_HANDLER_NO_ERROR
) {
3216 *ProgressErr
= RetVal
;
3217 Status
= EFI_INVALID_PARAMETER
;
3220 StringPtr
= NextStringPtr
;
3224 // 5. Generate KeywordResp string.
3226 Status
= GenerateKeywordResp(NameSpace
, DevicePath
, KeywordData
, ValueElement
, ReadOnly
, &KeywordResp
);
3227 if (Status
!= EFI_SUCCESS
) {
3232 // 6. Merge to the MultiKeywordResp string.
3234 Status
= MergeToMultiKeywordResp(&MultiKeywordResp
, &KeywordResp
);
3235 if (EFI_ERROR (Status
)) {
3240 // 7. Update return value.
3242 *Results
= MultiKeywordResp
;
3245 // 8. Clean the temp buffer.
3247 FreePool (DevicePath
);
3248 FreePool (KeywordData
);
3249 FreePool (ValueElement
);
3250 FreePool (ConfigRequest
);
3253 ValueElement
= NULL
;
3254 ConfigRequest
= NULL
;
3255 if (KeywordResp
!= NULL
) {
3256 FreePool (KeywordResp
);
3262 // Enumerate all keyword in the system.
3264 Status
= EnumerateAllKeywords(NameSpace
, &MultiKeywordResp
);
3265 if (EFI_ERROR (Status
)) {
3268 *Results
= MultiKeywordResp
;
3271 *ProgressErr
= KEYWORD_HANDLER_NO_ERROR
;
3274 if (TempString
!= NULL
) {
3275 FreePool (TempString
);
3277 if (NameSpace
!= NULL
) {
3278 FreePool (NameSpace
);
3280 if (DevicePath
!= NULL
) {
3281 FreePool (DevicePath
);
3283 if (KeywordData
!= NULL
) {
3284 FreePool (KeywordData
);
3286 *Progress
= StringPtr
;