2 Implementation of interfaces function for EFI_CONFIG_KEYWORD_HANDLER_PROTOCOL.
4 Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
10 #include "HiiDatabase.h"
12 extern HII_DATABASE_PRIVATE_DATA mPrivate
;
15 Convert the hex UNICODE %02x encoding of a UEFI device path to binary
16 from <PathHdr> of <MultiKeywordRequest>.
18 This is a internal function.
20 @param String MultiKeywordRequest string.
21 @param DevicePathData Binary of a UEFI device path.
22 @param NextString string follow the possible PathHdr string.
24 @retval EFI_INVALID_PARAMETER The device path is not valid or the incoming parameter is invalid.
25 @retval EFI_OUT_OF_RESOURCES Lake of resources to store necessary structures.
26 @retval EFI_SUCCESS The device path is retrieved and translated to binary format.
27 The Input string not include PathHdr section.
33 OUT UINT8
**DevicePathData
,
34 OUT EFI_STRING
*NextString
39 UINT8
*DevicePathBuffer
;
43 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
45 ASSERT (NextString
!= NULL
&& DevicePathData
!= NULL
);
48 // KeywordRequest == NULL case.
51 *DevicePathData
= NULL
;
59 if (*String
== L
'&') {
64 // Find the 'PATH=' of <PathHdr>.
66 if (StrnCmp (String
, L
"PATH=", StrLen (L
"PATH=")) != 0) {
67 if (StrnCmp (String
, L
"KEYWORD=", StrLen (L
"KEYWORD=")) != 0) {
68 return EFI_INVALID_PARAMETER
;
71 // Not include PathHdr, return success and DevicePath = NULL.
73 *DevicePathData
= NULL
;
80 // Check whether path data does exist.
82 String
+= StrLen (L
"PATH=");
84 return EFI_INVALID_PARAMETER
;
89 // The content between 'PATH=' of <ConfigHdr> and '&' of next element
90 // or '\0' (end of configuration string) is the UNICODE %02x bytes encoding
91 // of UEFI device path.
93 for (Length
= 0; *String
!= 0 && *String
!= L
'&'; String
++, Length
++);
96 // Save the return next keyword string value.
101 // Check DevicePath Length
103 if (((Length
+ 1) / 2) < sizeof (EFI_DEVICE_PATH_PROTOCOL
)) {
104 return EFI_INVALID_PARAMETER
;
108 // The data in <PathHdr> is encoded as hex UNICODE %02x bytes in the same order
109 // as the device path resides in RAM memory.
110 // Translate the data into binary.
112 DevicePathBuffer
= (UINT8
*) AllocateZeroPool ((Length
+ 1) / 2);
113 if (DevicePathBuffer
== NULL
) {
114 return EFI_OUT_OF_RESOURCES
;
118 // Convert DevicePath
120 ZeroMem (TemStr
, sizeof (TemStr
));
121 for (Index
= 0; Index
< Length
; Index
++) {
122 TemStr
[0] = PathHdr
[Index
];
123 DigitUint8
= (UINT8
) StrHexToUint64 (TemStr
);
124 if ((Index
& 1) == 0) {
125 DevicePathBuffer
[Index
/2] = DigitUint8
;
127 DevicePathBuffer
[Index
/2] = (UINT8
) ((DevicePathBuffer
[Index
/2] << 4) + DigitUint8
);
132 // Validate DevicePath
134 DevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) DevicePathBuffer
;
135 while (!IsDevicePathEnd (DevicePath
)) {
136 if ((DevicePath
->Type
== 0) || (DevicePath
->SubType
== 0) || (DevicePathNodeLength (DevicePath
) < sizeof (EFI_DEVICE_PATH_PROTOCOL
))) {
138 // Invalid device path
140 FreePool (DevicePathBuffer
);
141 return EFI_INVALID_PARAMETER
;
143 DevicePath
= NextDevicePathNode (DevicePath
);
147 // return the device path
149 *DevicePathData
= DevicePathBuffer
;
155 Get NameSpace from the input NameSpaceId string.
157 This is a internal function.
159 @param String <NameSpaceId> format string.
160 @param NameSpace Return the name space string.
161 @param NextString Return the next string follow namespace.
163 @retval EFI_SUCCESS Get the namespace string success.
164 @retval EFI_INVALID_PARAMETER The NameSpaceId string not follow spec definition.
169 IN EFI_STRING String
,
170 OUT CHAR8
**NameSpace
,
171 OUT EFI_STRING
*NextString
177 ASSERT (NameSpace
!= NULL
);
182 // Input NameSpaceId == NULL
184 if (String
== NULL
) {
186 if (NextString
!= NULL
) {
193 // Skip '&' if exist.
195 if (*String
== L
'&') {
199 if (StrnCmp (String
, L
"NAMESPACE=", StrLen (L
"NAMESPACE=")) != 0) {
200 return EFI_INVALID_PARAMETER
;
202 String
+= StrLen (L
"NAMESPACE=");
204 TmpPtr
= StrStr (String
, L
"&");
205 if (TmpPtr
!= NULL
) {
208 if (NextString
!= NULL
) {
209 *NextString
= String
+ StrLen (String
);
213 // Input NameSpace is unicode string. The language in String package is ascii string.
214 // Here will convert the unicode string to ascii and save it.
216 NameSpaceSize
= StrLen (String
) + 1;
217 *NameSpace
= AllocatePool (NameSpaceSize
);
218 if (*NameSpace
== NULL
) {
219 return EFI_OUT_OF_RESOURCES
;
221 UnicodeStrToAsciiStrS (String
, *NameSpace
, NameSpaceSize
);
223 if (TmpPtr
!= NULL
) {
231 Get Keyword from the input KeywordRequest string.
233 This is a internal function.
235 @param String KeywordRequestformat string.
236 @param Keyword return the extract keyword string.
237 @param NextString return the next string follow this keyword section.
239 @retval EFI_SUCCESS Success to get the keyword string.
240 @retval EFI_INVALID_PARAMETER Parse the input string return error.
245 IN EFI_STRING String
,
246 OUT EFI_STRING
*Keyword
,
247 OUT EFI_STRING
*NextString
252 ASSERT ((Keyword
!= NULL
) && (NextString
!= NULL
));
257 // KeywordRequest == NULL case.
259 if (String
== NULL
) {
266 // Skip '&' if exist.
268 if (*String
== L
'&') {
272 if (StrnCmp (String
, L
"KEYWORD=", StrLen (L
"KEYWORD=")) != 0) {
273 return EFI_INVALID_PARAMETER
;
276 String
+= StrLen (L
"KEYWORD=");
278 TmpPtr
= StrStr (String
, L
"&");
279 if (TmpPtr
!= NULL
) {
282 *NextString
= String
+ StrLen (String
);
284 *Keyword
= AllocateCopyPool (StrSize (String
), String
);
285 if (*Keyword
== NULL
) {
286 return EFI_OUT_OF_RESOURCES
;
289 if (TmpPtr
!= NULL
) {
297 Get value from the input KeywordRequest string.
299 This is a internal function.
301 @param String KeywordRequestformat string.
302 @param Value return the extract value string.
303 @param NextString return the next string follow this keyword section.
305 @retval EFI_SUCCESS Success to get the keyword string.
306 @retval EFI_INVALID_PARAMETER Parse the input string return error.
311 IN EFI_STRING String
,
312 OUT EFI_STRING
*Value
,
313 OUT EFI_STRING
*NextString
318 ASSERT ((Value
!= NULL
) && (NextString
!= NULL
) && (String
!= NULL
));
321 // Skip '&' if exist.
323 if (*String
== L
'&') {
327 if (StrnCmp (String
, L
"VALUE=", StrLen (L
"VALUE=")) != 0) {
328 return EFI_INVALID_PARAMETER
;
331 String
+= StrLen (L
"VALUE=");
333 TmpPtr
= StrStr (String
, L
"&");
334 if (TmpPtr
!= NULL
) {
337 *NextString
= String
+ StrLen (String
);
339 *Value
= AllocateCopyPool (StrSize (String
), String
);
340 if (*Value
== NULL
) {
341 return EFI_OUT_OF_RESOURCES
;
344 if (TmpPtr
!= NULL
) {
352 Get filter from the input KeywordRequest string.
354 This is a internal function.
356 @param String KeywordRequestformat string.
357 @param FilterFlags return the filter condition.
358 @param NextString return the next string follow this keyword section.
360 @retval EFI_SUCCESS Success to get the keyword string.
361 @retval EFI_INVALID_PARAMETER Parse the input string return error.
366 IN EFI_STRING String
,
367 OUT UINT8
*FilterFlags
,
368 OUT EFI_STRING
*NextString
375 ASSERT ((FilterFlags
!= NULL
) && (NextString
!= NULL
));
378 // String end, no filter section.
380 if (String
== NULL
) {
389 // Skip '&' if exist.
391 if (*String
== L
'&') {
395 if (StrnCmp (String
, L
"ReadOnly", StrLen (L
"ReadOnly")) == 0) {
397 // Find ReadOnly filter.
399 *FilterFlags
|= EFI_KEYWORD_FILTER_READONY
;
400 String
+= StrLen (L
"ReadOnly");
401 } else if (StrnCmp (String
, L
"ReadWrite", StrLen (L
"ReadWrite")) == 0) {
403 // Find ReadWrite filter.
405 *FilterFlags
|= EFI_KEYWORD_FILTER_REAWRITE
;
406 String
+= StrLen (L
"ReadWrite");
407 } else if (StrnCmp (String
, L
"Buffer", StrLen (L
"Buffer")) == 0) {
409 // Find Buffer Filter.
411 *FilterFlags
|= EFI_KEYWORD_FILTER_BUFFER
;
412 String
+= StrLen (L
"Buffer");
413 } else if (StrnCmp (String
, L
"Numeric", StrLen (L
"Numeric")) == 0) {
415 // Find Numeric Filter
417 String
+= StrLen (L
"Numeric");
418 if (*String
!= L
':') {
419 *FilterFlags
|= EFI_KEYWORD_FILTER_NUMERIC
;
424 *FilterFlags
|= EFI_KEYWORD_FILTER_NUMERIC_1
;
427 *FilterFlags
|= EFI_KEYWORD_FILTER_NUMERIC_2
;
430 *FilterFlags
|= EFI_KEYWORD_FILTER_NUMERIC_4
;
433 *FilterFlags
|= EFI_KEYWORD_FILTER_NUMERIC_8
;
443 // Check whether other filter item defined by Platform.
445 if ((StrnCmp (String
, L
"&PATH", StrLen (L
"&PATH")) == 0) ||
446 (StrnCmp (String
, L
"&KEYWORD", StrLen (L
"&KEYWORD")) == 0)) {
448 // New KeywordRequest start, no platform defined filter.
452 // Platform defined filter rule.
453 // Just skip platform defined filter rule, return success.
455 PathPtr
= StrStr(String
, L
"&PATH");
456 KeywordPtr
= StrStr(String
, L
"&KEYWORD");
457 if (PathPtr
!= NULL
&& KeywordPtr
!= NULL
) {
459 // If both sections exist, return the first follow string.
461 String
= KeywordPtr
> PathPtr
? PathPtr
: KeywordPtr
;
462 } else if (PathPtr
!= NULL
) {
464 // Should not exist PathPtr != NULL && KeywordPtr == NULL case.
467 } else if (KeywordPtr
!= NULL
) {
469 // Just to the next keyword section.
474 // Only has platform defined filter section, just skip it.
476 String
+= StrLen (String
);
482 *NextString
= String
;
488 Extract Readonly flag from opcode.
490 This is a internal function.
492 @param OpCodeData Input opcode for this question.
494 @retval TRUE This question is readonly.
495 @retval FALSE This question is not readonly.
499 ExtractReadOnlyFromOpCode (
503 EFI_IFR_QUESTION_HEADER
*QuestionHdr
;
505 ASSERT (OpCodeData
!= NULL
);
507 QuestionHdr
= (EFI_IFR_QUESTION_HEADER
*) (OpCodeData
+ sizeof (EFI_IFR_OP_HEADER
));
509 return (QuestionHdr
->Flags
& EFI_IFR_FLAG_READ_ONLY
) != 0;
513 Create a circuit to check the filter section.
515 This is a internal function.
517 @param OpCodeData The question binary ifr data.
518 @param KeywordRequest KeywordRequestformat string.
519 @param NextString return the next string follow this keyword section.
520 @param ReadOnly Return whether this question is read only.
522 @retval KEYWORD_HANDLER_NO_ERROR Success validate.
523 @retval KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED Validate fail.
528 IN UINT8
*OpCodeData
,
529 IN CHAR16
*KeywordRequest
,
530 OUT CHAR16
**NextString
,
531 OUT BOOLEAN
*ReadOnly
537 EFI_IFR_QUESTION_HEADER
*QuestionHdr
;
538 EFI_IFR_OP_HEADER
*OpCodeHdr
;
542 RetVal
= KEYWORD_HANDLER_NO_ERROR
;
543 StringPtr
= KeywordRequest
;
545 OpCodeHdr
= (EFI_IFR_OP_HEADER
*) OpCodeData
;
546 QuestionHdr
= (EFI_IFR_QUESTION_HEADER
*) (OpCodeData
+ sizeof (EFI_IFR_OP_HEADER
));
547 if (OpCodeHdr
->OpCode
== EFI_IFR_ONE_OF_OP
|| OpCodeHdr
->OpCode
== EFI_IFR_NUMERIC_OP
) {
548 Flags
= *(OpCodeData
+ sizeof (EFI_IFR_OP_HEADER
) + sizeof (EFI_IFR_QUESTION_HEADER
));
554 // Get ReadOnly flag from Question.
556 *ReadOnly
= ExtractReadOnlyFromOpCode(OpCodeData
);
558 while (ExtractFilter (StringPtr
, &FilterFlags
, &NextFilter
)) {
559 switch (FilterFlags
) {
560 case EFI_KEYWORD_FILTER_READONY
:
561 if ((QuestionHdr
->Flags
& EFI_IFR_FLAG_READ_ONLY
) == 0) {
562 RetVal
= KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED
;
567 case EFI_KEYWORD_FILTER_REAWRITE
:
568 if ((QuestionHdr
->Flags
& EFI_IFR_FLAG_READ_ONLY
) != 0) {
569 RetVal
= KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED
;
574 case EFI_KEYWORD_FILTER_BUFFER
:
576 // Only these three opcode use numeric value type.
578 if (OpCodeHdr
->OpCode
== EFI_IFR_ONE_OF_OP
|| OpCodeHdr
->OpCode
== EFI_IFR_NUMERIC_OP
|| OpCodeHdr
->OpCode
== EFI_IFR_CHECKBOX_OP
) {
579 RetVal
= KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED
;
584 case EFI_KEYWORD_FILTER_NUMERIC
:
585 if (OpCodeHdr
->OpCode
!= EFI_IFR_ONE_OF_OP
&& OpCodeHdr
->OpCode
!= EFI_IFR_NUMERIC_OP
&& OpCodeHdr
->OpCode
!= EFI_IFR_CHECKBOX_OP
) {
586 RetVal
= KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED
;
591 case EFI_KEYWORD_FILTER_NUMERIC_1
:
592 case EFI_KEYWORD_FILTER_NUMERIC_2
:
593 case EFI_KEYWORD_FILTER_NUMERIC_4
:
594 case EFI_KEYWORD_FILTER_NUMERIC_8
:
595 if (OpCodeHdr
->OpCode
!= EFI_IFR_ONE_OF_OP
&& OpCodeHdr
->OpCode
!= EFI_IFR_NUMERIC_OP
&& OpCodeHdr
->OpCode
!= EFI_IFR_CHECKBOX_OP
) {
596 RetVal
= KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED
;
601 // For numeric and oneof, it has flags field to specify the detail numeric type.
603 if (OpCodeHdr
->OpCode
== EFI_IFR_ONE_OF_OP
|| OpCodeHdr
->OpCode
== EFI_IFR_NUMERIC_OP
) {
604 switch (Flags
& EFI_IFR_NUMERIC_SIZE
) {
605 case EFI_IFR_NUMERIC_SIZE_1
:
606 if (FilterFlags
!= EFI_KEYWORD_FILTER_NUMERIC_1
) {
607 RetVal
= KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED
;
612 case EFI_IFR_NUMERIC_SIZE_2
:
613 if (FilterFlags
!= EFI_KEYWORD_FILTER_NUMERIC_2
) {
614 RetVal
= KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED
;
619 case EFI_IFR_NUMERIC_SIZE_4
:
620 if (FilterFlags
!= EFI_KEYWORD_FILTER_NUMERIC_4
) {
621 RetVal
= KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED
;
626 case EFI_IFR_NUMERIC_SIZE_8
:
627 if (FilterFlags
!= EFI_KEYWORD_FILTER_NUMERIC_8
) {
628 RetVal
= KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED
;
646 // Jump to the next filter.
648 StringPtr
= NextFilter
;
653 // The current filter which is processing.
655 *NextString
= StringPtr
;
661 Get HII_DATABASE_RECORD from the input device path info.
663 This is a internal function.
665 @param DevicePath UEFI device path protocol.
667 @retval Internal data base record.
670 HII_DATABASE_RECORD
*
671 GetRecordFromDevicePath (
672 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
676 UINT8
*DevicePathPkg
;
677 UINT8
*CurrentDevicePath
;
678 UINTN DevicePathSize
;
679 HII_DATABASE_RECORD
*TempDatabase
;
681 ASSERT (DevicePath
!= NULL
);
683 for (Link
= mPrivate
.DatabaseList
.ForwardLink
; Link
!= &mPrivate
.DatabaseList
; Link
= Link
->ForwardLink
) {
684 TempDatabase
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
685 DevicePathPkg
= TempDatabase
->PackageList
->DevicePathPkg
;
686 if (DevicePathPkg
!= NULL
) {
687 CurrentDevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
688 DevicePathSize
= GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) CurrentDevicePath
);
689 if ((CompareMem (DevicePath
, CurrentDevicePath
, DevicePathSize
) == 0)) {
699 Calculate the size of StringSrc and output it. Also copy string text from src
702 This is a internal function.
704 @param StringSrc Points to current null-terminated string.
705 @param BufferSize Length of the buffer.
706 @param StringDest Buffer to store the string text.
708 @retval EFI_SUCCESS The string text was outputted successfully.
709 @retval EFI_OUT_OF_RESOURCES Out of resource.
713 GetUnicodeStringTextAndSize (
715 OUT UINTN
*BufferSize
,
716 OUT EFI_STRING
*StringDest
722 ASSERT (StringSrc
!= NULL
&& BufferSize
!= NULL
&& StringDest
!= NULL
);
724 StringSize
= sizeof (CHAR16
);
725 StringPtr
= StringSrc
;
726 while (ReadUnaligned16 ((UINT16
*) StringPtr
) != 0) {
727 StringSize
+= sizeof (CHAR16
);
728 StringPtr
+= sizeof (CHAR16
);
731 *StringDest
= AllocatePool (StringSize
);
732 if (*StringDest
== NULL
) {
733 return EFI_OUT_OF_RESOURCES
;
736 CopyMem (*StringDest
, StringSrc
, StringSize
);
738 *BufferSize
= StringSize
;
743 Find the string id for the input keyword.
745 @param StringPackage Hii string package instance.
746 @param KeywordValue Input keyword value.
747 @param StringId The string's id, which is unique within PackageList.
750 @retval EFI_SUCCESS The string text and font is retrieved
752 @retval EFI_NOT_FOUND The specified text or font info can not be found
754 @retval EFI_OUT_OF_RESOURCES The system is out of resources to accomplish the
758 GetStringIdFromString (
759 IN HII_STRING_PACKAGE_INSTANCE
*StringPackage
,
760 IN CHAR16
*KeywordValue
,
761 OUT EFI_STRING_ID
*StringId
765 EFI_STRING_ID CurrentStringId
;
768 UINT8
*StringTextPtr
;
773 EFI_HII_SIBT_EXT2_BLOCK Ext2
;
777 CHAR8
*AsciiKeywordValue
;
778 UINTN KeywordValueSize
;
781 ASSERT (StringPackage
!= NULL
&& KeywordValue
!= NULL
&& StringId
!= NULL
);
782 ASSERT (StringPackage
->Signature
== HII_STRING_PACKAGE_SIGNATURE
);
785 Status
= EFI_SUCCESS
;
787 BlockHdr
= StringPackage
->StringBlock
;
792 // Make a ascii keyword value for later use.
794 KeywordValueSize
= StrLen (KeywordValue
) + 1;
795 AsciiKeywordValue
= AllocatePool (KeywordValueSize
);
796 if (AsciiKeywordValue
== NULL
) {
797 return EFI_OUT_OF_RESOURCES
;
799 UnicodeStrToAsciiStrS (KeywordValue
, AsciiKeywordValue
, KeywordValueSize
);
801 while (*BlockHdr
!= EFI_HII_SIBT_END
) {
803 case EFI_HII_SIBT_STRING_SCSU
:
804 Offset
= sizeof (EFI_HII_STRING_BLOCK
);
805 StringTextPtr
= BlockHdr
+ Offset
;
806 BlockSize
+= Offset
+ AsciiStrSize ((CHAR8
*) StringTextPtr
);
807 if (AsciiStrCmp(AsciiKeywordValue
, (CHAR8
*) StringTextPtr
) == 0) {
808 *StringId
= CurrentStringId
;
814 case EFI_HII_SIBT_STRING_SCSU_FONT
:
815 Offset
= sizeof (EFI_HII_SIBT_STRING_SCSU_FONT_BLOCK
) - sizeof (UINT8
);
816 StringTextPtr
= BlockHdr
+ Offset
;
817 if (AsciiStrCmp(AsciiKeywordValue
, (CHAR8
*) StringTextPtr
) == 0) {
818 *StringId
= CurrentStringId
;
821 BlockSize
+= Offset
+ AsciiStrSize ((CHAR8
*) StringTextPtr
);
825 case EFI_HII_SIBT_STRINGS_SCSU
:
826 CopyMem (&StringCount
, BlockHdr
+ sizeof (EFI_HII_STRING_BLOCK
), sizeof (UINT16
));
827 StringTextPtr
= (UINT8
*)((UINTN
)BlockHdr
+ sizeof (EFI_HII_SIBT_STRINGS_SCSU_BLOCK
) - sizeof (UINT8
));
828 BlockSize
+= StringTextPtr
- BlockHdr
;
830 for (Index
= 0; Index
< StringCount
; Index
++) {
831 BlockSize
+= AsciiStrSize ((CHAR8
*) StringTextPtr
);
832 if (AsciiStrCmp(AsciiKeywordValue
, (CHAR8
*) StringTextPtr
) == 0) {
833 *StringId
= CurrentStringId
;
836 StringTextPtr
= StringTextPtr
+ AsciiStrSize ((CHAR8
*) StringTextPtr
);
841 case EFI_HII_SIBT_STRINGS_SCSU_FONT
:
844 (UINT8
*)((UINTN
)BlockHdr
+ sizeof (EFI_HII_STRING_BLOCK
) + sizeof (UINT8
)),
847 StringTextPtr
= (UINT8
*)((UINTN
)BlockHdr
+ sizeof (EFI_HII_SIBT_STRINGS_SCSU_FONT_BLOCK
) - sizeof (UINT8
));
848 BlockSize
+= StringTextPtr
- BlockHdr
;
850 for (Index
= 0; Index
< StringCount
; Index
++) {
851 BlockSize
+= AsciiStrSize ((CHAR8
*) StringTextPtr
);
852 if (AsciiStrCmp(AsciiKeywordValue
, (CHAR8
*) StringTextPtr
) == 0) {
853 *StringId
= CurrentStringId
;
856 StringTextPtr
= StringTextPtr
+ AsciiStrSize ((CHAR8
*) StringTextPtr
);
861 case EFI_HII_SIBT_STRING_UCS2
:
862 Offset
= sizeof (EFI_HII_STRING_BLOCK
);
863 StringTextPtr
= BlockHdr
+ Offset
;
865 // Use StringSize to store the size of the specified string, including the NULL
868 Status
= GetUnicodeStringTextAndSize (StringTextPtr
, &StringSize
, &String
);
869 if (EFI_ERROR (Status
)) {
872 ASSERT (String
!= NULL
);
873 if (StrCmp(KeywordValue
, String
) == 0) {
874 *StringId
= CurrentStringId
;
877 BlockSize
+= Offset
+ StringSize
;
881 case EFI_HII_SIBT_STRING_UCS2_FONT
:
882 Offset
= sizeof (EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK
) - sizeof (CHAR16
);
883 StringTextPtr
= BlockHdr
+ Offset
;
885 // Use StringSize to store the size of the specified string, including the NULL
888 Status
= GetUnicodeStringTextAndSize (StringTextPtr
, &StringSize
, &String
);
889 if (EFI_ERROR (Status
)) {
892 ASSERT (String
!= NULL
);
893 if (StrCmp(KeywordValue
, String
) == 0) {
894 *StringId
= CurrentStringId
;
897 BlockSize
+= Offset
+ StringSize
;
901 case EFI_HII_SIBT_STRINGS_UCS2
:
902 Offset
= sizeof (EFI_HII_SIBT_STRINGS_UCS2_BLOCK
) - sizeof (CHAR16
);
903 StringTextPtr
= BlockHdr
+ Offset
;
905 CopyMem (&StringCount
, BlockHdr
+ sizeof (EFI_HII_STRING_BLOCK
), sizeof (UINT16
));
906 for (Index
= 0; Index
< StringCount
; Index
++) {
907 Status
= GetUnicodeStringTextAndSize (StringTextPtr
, &StringSize
, &String
);
908 if (EFI_ERROR (Status
)) {
911 ASSERT (String
!= NULL
);
912 BlockSize
+= StringSize
;
913 if (StrCmp(KeywordValue
, String
) == 0) {
914 *StringId
= CurrentStringId
;
917 StringTextPtr
= StringTextPtr
+ StringSize
;
922 case EFI_HII_SIBT_STRINGS_UCS2_FONT
:
923 Offset
= sizeof (EFI_HII_SIBT_STRINGS_UCS2_FONT_BLOCK
) - sizeof (CHAR16
);
924 StringTextPtr
= BlockHdr
+ Offset
;
928 (UINT8
*)((UINTN
)BlockHdr
+ sizeof (EFI_HII_STRING_BLOCK
) + sizeof (UINT8
)),
931 for (Index
= 0; Index
< StringCount
; Index
++) {
932 Status
= GetUnicodeStringTextAndSize (StringTextPtr
, &StringSize
, &String
);
933 if (EFI_ERROR (Status
)) {
936 ASSERT (String
!= NULL
);
937 BlockSize
+= StringSize
;
938 if (StrCmp(KeywordValue
, String
) == 0) {
939 *StringId
= CurrentStringId
;
942 StringTextPtr
= StringTextPtr
+ StringSize
;
947 case EFI_HII_SIBT_DUPLICATE
:
948 BlockSize
+= sizeof (EFI_HII_SIBT_DUPLICATE_BLOCK
);
952 case EFI_HII_SIBT_SKIP1
:
953 SkipCount
= (UINT16
) (*(UINT8
*)((UINTN
)BlockHdr
+ sizeof (EFI_HII_STRING_BLOCK
)));
954 CurrentStringId
= (UINT16
) (CurrentStringId
+ SkipCount
);
955 BlockSize
+= sizeof (EFI_HII_SIBT_SKIP1_BLOCK
);
958 case EFI_HII_SIBT_SKIP2
:
959 CopyMem (&SkipCount
, BlockHdr
+ sizeof (EFI_HII_STRING_BLOCK
), sizeof (UINT16
));
960 CurrentStringId
= (UINT16
) (CurrentStringId
+ SkipCount
);
961 BlockSize
+= sizeof (EFI_HII_SIBT_SKIP2_BLOCK
);
964 case EFI_HII_SIBT_EXT1
:
967 (UINT8
*)((UINTN
)BlockHdr
+ sizeof (EFI_HII_STRING_BLOCK
) + sizeof (UINT8
)),
970 BlockSize
+= Length8
;
973 case EFI_HII_SIBT_EXT2
:
974 CopyMem (&Ext2
, BlockHdr
, sizeof (EFI_HII_SIBT_EXT2_BLOCK
));
975 BlockSize
+= Ext2
.Length
;
978 case EFI_HII_SIBT_EXT4
:
981 (UINT8
*)((UINTN
)BlockHdr
+ sizeof (EFI_HII_STRING_BLOCK
) + sizeof (UINT8
)),
985 BlockSize
+= Length32
;
992 if (String
!= NULL
) {
997 BlockHdr
= StringPackage
->StringBlock
+ BlockSize
;
1000 Status
= EFI_NOT_FOUND
;
1003 if (AsciiKeywordValue
!= NULL
) {
1004 FreePool (AsciiKeywordValue
);
1006 if (String
!= NULL
) {
1013 Find the next valid string id for the input string id.
1015 @param StringPackage Hii string package instance.
1016 @param StringId The current string id which is already got.
1017 1 means just begin to get the string id.
1018 @param KeywordValue Return the string for the next string id.
1021 @retval EFI_STRING_ID Not 0 means a valid stringid found.
1022 0 means not found a valid string id.
1026 IN HII_STRING_PACKAGE_INSTANCE
*StringPackage
,
1027 IN EFI_STRING_ID StringId
,
1028 OUT EFI_STRING
*KeywordValue
1032 EFI_STRING_ID CurrentStringId
;
1035 UINT8
*StringTextPtr
;
1040 EFI_HII_SIBT_EXT2_BLOCK Ext2
;
1046 ASSERT (StringPackage
!= NULL
);
1047 ASSERT (StringPackage
->Signature
== HII_STRING_PACKAGE_SIGNATURE
);
1049 CurrentStringId
= 1;
1054 // Parse the string blocks to get the string text and font.
1056 BlockHdr
= StringPackage
->StringBlock
;
1059 while (*BlockHdr
!= EFI_HII_SIBT_END
) {
1060 switch (*BlockHdr
) {
1061 case EFI_HII_SIBT_STRING_SCSU
:
1062 Offset
= sizeof (EFI_HII_STRING_BLOCK
);
1063 StringTextPtr
= BlockHdr
+ Offset
;
1066 StringSize
= AsciiStrSize ((CHAR8
*) StringTextPtr
);
1067 *KeywordValue
= AllocatePool (StringSize
* sizeof (CHAR16
));
1068 if (*KeywordValue
== NULL
) {
1071 AsciiStrToUnicodeStrS ((CHAR8
*) StringTextPtr
, *KeywordValue
, StringSize
);
1072 return CurrentStringId
;
1073 } else if (CurrentStringId
== StringId
) {
1077 BlockSize
+= Offset
+ AsciiStrSize ((CHAR8
*) StringTextPtr
);
1081 case EFI_HII_SIBT_STRING_SCSU_FONT
:
1082 Offset
= sizeof (EFI_HII_SIBT_STRING_SCSU_FONT_BLOCK
) - sizeof (UINT8
);
1083 StringTextPtr
= BlockHdr
+ Offset
;
1086 StringSize
= AsciiStrSize ((CHAR8
*) StringTextPtr
);
1087 *KeywordValue
= AllocatePool (StringSize
* sizeof (CHAR16
));
1088 if (*KeywordValue
== NULL
) {
1091 AsciiStrToUnicodeStrS ((CHAR8
*) StringTextPtr
, *KeywordValue
, StringSize
);
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 StringSize
= AsciiStrSize ((CHAR8
*) StringTextPtr
);
1109 *KeywordValue
= AllocatePool (StringSize
* sizeof (CHAR16
));
1110 if (*KeywordValue
== NULL
) {
1113 AsciiStrToUnicodeStrS ((CHAR8
*) StringTextPtr
, *KeywordValue
, StringSize
);
1114 return CurrentStringId
;
1115 } else if (CurrentStringId
== StringId
) {
1119 BlockSize
+= AsciiStrSize ((CHAR8
*) StringTextPtr
);
1120 StringTextPtr
= StringTextPtr
+ AsciiStrSize ((CHAR8
*) StringTextPtr
);
1125 case EFI_HII_SIBT_STRINGS_SCSU_FONT
:
1128 (UINT8
*)((UINTN
)BlockHdr
+ sizeof (EFI_HII_STRING_BLOCK
) + sizeof (UINT8
)),
1131 StringTextPtr
= (UINT8
*)((UINTN
)BlockHdr
+ sizeof (EFI_HII_SIBT_STRINGS_SCSU_FONT_BLOCK
) - sizeof (UINT8
));
1132 BlockSize
+= StringTextPtr
- BlockHdr
;
1134 for (Index
= 0; Index
< StringCount
; Index
++) {
1136 StringSize
= AsciiStrSize ((CHAR8
*) StringTextPtr
);
1137 *KeywordValue
= AllocatePool (StringSize
* sizeof (CHAR16
));
1138 if (*KeywordValue
== NULL
) {
1141 AsciiStrToUnicodeStrS ((CHAR8
*) StringTextPtr
, *KeywordValue
, StringSize
);
1142 return CurrentStringId
;
1143 } else if (CurrentStringId
== StringId
) {
1147 BlockSize
+= AsciiStrSize ((CHAR8
*) StringTextPtr
);
1148 StringTextPtr
= StringTextPtr
+ AsciiStrSize ((CHAR8
*) StringTextPtr
);
1153 case EFI_HII_SIBT_STRING_UCS2
:
1154 Offset
= sizeof (EFI_HII_STRING_BLOCK
);
1155 StringTextPtr
= BlockHdr
+ Offset
;
1157 // Use StringSize to store the size of the specified string, including the NULL
1160 GetUnicodeStringTextAndSize (StringTextPtr
, &StringSize
, &String
);
1161 if (FindString
&& (String
!= NULL
) && (*String
!= L
'\0')) {
1163 // String protocol use this type for the string id which has value for other package.
1164 // It will allocate an empty string block for this string id. so here we also check
1165 // *String != L'\0' to prohibit this case.
1167 *KeywordValue
= String
;
1168 return CurrentStringId
;
1169 } else if (CurrentStringId
== StringId
) {
1173 BlockSize
+= Offset
+ StringSize
;
1177 case EFI_HII_SIBT_STRING_UCS2_FONT
:
1178 Offset
= sizeof (EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK
) - sizeof (CHAR16
);
1179 StringTextPtr
= BlockHdr
+ Offset
;
1181 // Use StringSize to store the size of the specified string, including the NULL
1184 GetUnicodeStringTextAndSize (StringTextPtr
, &StringSize
, &String
);
1186 *KeywordValue
= String
;
1187 return CurrentStringId
;
1188 } else if (CurrentStringId
== StringId
) {
1192 BlockSize
+= Offset
+ StringSize
;
1196 case EFI_HII_SIBT_STRINGS_UCS2
:
1197 Offset
= sizeof (EFI_HII_SIBT_STRINGS_UCS2_BLOCK
) - sizeof (CHAR16
);
1198 StringTextPtr
= BlockHdr
+ Offset
;
1199 BlockSize
+= Offset
;
1200 CopyMem (&StringCount
, BlockHdr
+ sizeof (EFI_HII_STRING_BLOCK
), sizeof (UINT16
));
1201 for (Index
= 0; Index
< StringCount
; Index
++) {
1202 GetUnicodeStringTextAndSize (StringTextPtr
, &StringSize
, &String
);
1205 *KeywordValue
= String
;
1206 return CurrentStringId
;
1207 } else if (CurrentStringId
== StringId
) {
1211 BlockSize
+= StringSize
;
1212 StringTextPtr
= StringTextPtr
+ StringSize
;
1217 case EFI_HII_SIBT_STRINGS_UCS2_FONT
:
1218 Offset
= sizeof (EFI_HII_SIBT_STRINGS_UCS2_FONT_BLOCK
) - sizeof (CHAR16
);
1219 StringTextPtr
= BlockHdr
+ Offset
;
1220 BlockSize
+= Offset
;
1223 (UINT8
*)((UINTN
)BlockHdr
+ sizeof (EFI_HII_STRING_BLOCK
) + sizeof (UINT8
)),
1226 for (Index
= 0; Index
< StringCount
; Index
++) {
1227 GetUnicodeStringTextAndSize (StringTextPtr
, &StringSize
, &String
);
1229 *KeywordValue
= String
;
1230 return CurrentStringId
;
1231 } else if (CurrentStringId
== StringId
) {
1235 BlockSize
+= StringSize
;
1236 StringTextPtr
= StringTextPtr
+ StringSize
;
1241 case EFI_HII_SIBT_DUPLICATE
:
1242 BlockSize
+= sizeof (EFI_HII_SIBT_DUPLICATE_BLOCK
);
1246 case EFI_HII_SIBT_SKIP1
:
1247 SkipCount
= (UINT16
) (*(UINT8
*)((UINTN
)BlockHdr
+ sizeof (EFI_HII_STRING_BLOCK
)));
1248 CurrentStringId
= (UINT16
) (CurrentStringId
+ SkipCount
);
1249 BlockSize
+= sizeof (EFI_HII_SIBT_SKIP1_BLOCK
);
1252 case EFI_HII_SIBT_SKIP2
:
1253 CopyMem (&SkipCount
, BlockHdr
+ sizeof (EFI_HII_STRING_BLOCK
), sizeof (UINT16
));
1254 CurrentStringId
= (UINT16
) (CurrentStringId
+ SkipCount
);
1255 BlockSize
+= sizeof (EFI_HII_SIBT_SKIP2_BLOCK
);
1258 case EFI_HII_SIBT_EXT1
:
1261 (UINT8
*)((UINTN
)BlockHdr
+ sizeof (EFI_HII_STRING_BLOCK
) + sizeof (UINT8
)),
1264 BlockSize
+= Length8
;
1267 case EFI_HII_SIBT_EXT2
:
1268 CopyMem (&Ext2
, BlockHdr
, sizeof (EFI_HII_SIBT_EXT2_BLOCK
));
1269 BlockSize
+= Ext2
.Length
;
1272 case EFI_HII_SIBT_EXT4
:
1275 (UINT8
*)((UINTN
)BlockHdr
+ sizeof (EFI_HII_STRING_BLOCK
) + sizeof (UINT8
)),
1279 BlockSize
+= Length32
;
1286 if (String
!= NULL
) {
1291 BlockHdr
= StringPackage
->StringBlock
+ BlockSize
;
1298 Get string package from the input NameSpace string.
1300 This is a internal function.
1302 @param DatabaseRecord HII_DATABASE_RECORD format string.
1303 @param NameSpace NameSpace format string.
1304 @param KeywordValue Keyword value.
1305 @param StringId String Id for this keyword.
1307 @retval KEYWORD_HANDLER_NO_ERROR Get String id successfully.
1308 @retval KEYWORD_HANDLER_KEYWORD_NOT_FOUND Not found the string id in the string package.
1309 @retval KEYWORD_HANDLER_NAMESPACE_ID_NOT_FOUND Not found the string package for this namespace.
1310 @retval KEYWORD_HANDLER_UNDEFINED_PROCESSING_ERROR Out of resource error.
1314 GetStringIdFromRecord (
1315 IN HII_DATABASE_RECORD
*DatabaseRecord
,
1316 IN CHAR8
**NameSpace
,
1317 IN CHAR16
*KeywordValue
,
1318 OUT EFI_STRING_ID
*StringId
1322 HII_DATABASE_PACKAGE_LIST_INSTANCE
*PackageListNode
;
1323 HII_STRING_PACKAGE_INSTANCE
*StringPackage
;
1328 ASSERT (DatabaseRecord
!= NULL
&& NameSpace
!= NULL
&& KeywordValue
!= NULL
);
1330 PackageListNode
= DatabaseRecord
->PackageList
;
1331 RetVal
= KEYWORD_HANDLER_NAMESPACE_ID_NOT_FOUND
;
1333 if (*NameSpace
!= NULL
) {
1336 Name
= UEFI_CONFIG_LANG
;
1339 for (Link
= PackageListNode
->StringPkgHdr
.ForwardLink
; Link
!= &PackageListNode
->StringPkgHdr
; Link
= Link
->ForwardLink
) {
1340 StringPackage
= CR (Link
, HII_STRING_PACKAGE_INSTANCE
, StringEntry
, HII_STRING_PACKAGE_SIGNATURE
);
1342 if (AsciiStrnCmp(Name
, StringPackage
->StringPkgHdr
->Language
, AsciiStrLen (Name
)) == 0) {
1343 Status
= GetStringIdFromString (StringPackage
, KeywordValue
, StringId
);
1344 if (EFI_ERROR (Status
)) {
1345 return KEYWORD_HANDLER_KEYWORD_NOT_FOUND
;
1347 if (*NameSpace
== NULL
) {
1348 *NameSpace
= AllocateCopyPool (AsciiStrSize (StringPackage
->StringPkgHdr
->Language
), StringPackage
->StringPkgHdr
->Language
);
1349 if (*NameSpace
== NULL
) {
1350 return KEYWORD_HANDLER_UNDEFINED_PROCESSING_ERROR
;
1353 return KEYWORD_HANDLER_NO_ERROR
;
1362 Tell whether this Operand is an Statement OpCode.
1364 @param Operand Operand of an IFR OpCode.
1366 @retval TRUE This is an Statement OpCode.
1367 @retval FALSE Not an Statement OpCode.
1375 if ((Operand
== EFI_IFR_SUBTITLE_OP
) ||
1376 (Operand
== EFI_IFR_TEXT_OP
) ||
1377 (Operand
== EFI_IFR_RESET_BUTTON_OP
) ||
1378 (Operand
== EFI_IFR_REF_OP
) ||
1379 (Operand
== EFI_IFR_ACTION_OP
) ||
1380 (Operand
== EFI_IFR_NUMERIC_OP
) ||
1381 (Operand
== EFI_IFR_ORDERED_LIST_OP
) ||
1382 (Operand
== EFI_IFR_CHECKBOX_OP
) ||
1383 (Operand
== EFI_IFR_STRING_OP
) ||
1384 (Operand
== EFI_IFR_PASSWORD_OP
) ||
1385 (Operand
== EFI_IFR_DATE_OP
) ||
1386 (Operand
== EFI_IFR_TIME_OP
) ||
1387 (Operand
== EFI_IFR_GUID_OP
) ||
1388 (Operand
== EFI_IFR_ONE_OF_OP
)) {
1396 Tell whether this Operand is an Statement OpCode.
1398 @param Operand Operand of an IFR OpCode.
1400 @retval TRUE This is an Statement OpCode.
1401 @retval FALSE Not an Statement OpCode.
1409 if ((Operand
== EFI_IFR_VARSTORE_OP
) ||
1410 (Operand
== EFI_IFR_VARSTORE_NAME_VALUE_OP
) ||
1411 (Operand
== EFI_IFR_VARSTORE_EFI_OP
)) {
1419 Base on the prompt string id to find the question.
1421 @param FormPackage The input form package.
1422 @param KeywordStrId The input prompt string id for one question.
1424 @retval the opcode for the question.
1428 FindQuestionFromStringId (
1429 IN HII_IFR_PACKAGE_INSTANCE
*FormPackage
,
1430 IN EFI_STRING_ID KeywordStrId
1435 EFI_IFR_STATEMENT_HEADER
*StatementHeader
;
1436 EFI_IFR_OP_HEADER
*OpCodeHeader
;
1439 ASSERT (FormPackage
!= NULL
);
1441 FormDataLen
= FormPackage
->FormPkgHdr
.Length
- sizeof (EFI_HII_PACKAGE_HEADER
);
1443 while (Offset
< FormDataLen
) {
1444 OpCodeData
= FormPackage
->IfrData
+ Offset
;
1445 OpCodeHeader
= (EFI_IFR_OP_HEADER
*) OpCodeData
;
1447 if (IsStatementOpCode(OpCodeHeader
->OpCode
)) {
1448 StatementHeader
= (EFI_IFR_STATEMENT_HEADER
*) (OpCodeData
+ sizeof (EFI_IFR_OP_HEADER
));
1449 if (StatementHeader
->Prompt
== KeywordStrId
) {
1454 Offset
+= OpCodeHeader
->Length
;
1461 Base on the varstore id to find the storage info.
1463 @param FormPackage The input form package.
1464 @param VarStoreId The input storage id.
1466 @retval the opcode for the storage.
1470 FindStorageFromVarId (
1471 IN HII_IFR_PACKAGE_INSTANCE
*FormPackage
,
1472 IN EFI_VARSTORE_ID VarStoreId
1477 EFI_IFR_OP_HEADER
*OpCodeHeader
;
1480 ASSERT (FormPackage
!= NULL
);
1482 FormDataLen
= FormPackage
->FormPkgHdr
.Length
- sizeof (EFI_HII_PACKAGE_HEADER
);
1484 while (Offset
< FormDataLen
) {
1485 OpCodeData
= FormPackage
->IfrData
+ Offset
;
1486 OpCodeHeader
= (EFI_IFR_OP_HEADER
*) OpCodeData
;
1488 if (IsStorageOpCode(OpCodeHeader
->OpCode
)) {
1489 switch (OpCodeHeader
->OpCode
) {
1490 case EFI_IFR_VARSTORE_OP
:
1491 if (VarStoreId
== ((EFI_IFR_VARSTORE
*) OpCodeData
)->VarStoreId
) {
1496 case EFI_IFR_VARSTORE_NAME_VALUE_OP
:
1497 if (VarStoreId
== ((EFI_IFR_VARSTORE_NAME_VALUE
*) OpCodeData
)->VarStoreId
) {
1502 case EFI_IFR_VARSTORE_EFI_OP
:
1503 if (VarStoreId
== ((EFI_IFR_VARSTORE_EFI
*) OpCodeData
)->VarStoreId
) {
1513 Offset
+= OpCodeHeader
->Length
;
1520 Get width info for one question.
1522 @param OpCodeData The input opcode for one question.
1524 @retval the width info for one question.
1529 IN UINT8
*OpCodeData
1532 UINT8
*NextOpCodeData
;
1534 ASSERT (OpCodeData
!= NULL
);
1536 switch (((EFI_IFR_OP_HEADER
*) OpCodeData
)->OpCode
) {
1537 case EFI_IFR_REF_OP
:
1538 return (UINT16
) sizeof (EFI_HII_REF
);
1540 case EFI_IFR_ONE_OF_OP
:
1541 case EFI_IFR_NUMERIC_OP
:
1542 switch (((EFI_IFR_ONE_OF
*) OpCodeData
)->Flags
& EFI_IFR_NUMERIC_SIZE
) {
1543 case EFI_IFR_NUMERIC_SIZE_1
:
1544 return (UINT16
) sizeof (UINT8
);
1546 case EFI_IFR_NUMERIC_SIZE_2
:
1547 return (UINT16
) sizeof (UINT16
);
1549 case EFI_IFR_NUMERIC_SIZE_4
:
1550 return (UINT16
) sizeof (UINT32
);
1552 case EFI_IFR_NUMERIC_SIZE_8
:
1553 return (UINT16
) sizeof (UINT64
);
1560 case EFI_IFR_ORDERED_LIST_OP
:
1561 NextOpCodeData
= OpCodeData
+ ((EFI_IFR_ORDERED_LIST
*) OpCodeData
)->Header
.Length
;
1563 // OneOfOption must follow the orderedlist opcode.
1565 ASSERT (((EFI_IFR_OP_HEADER
*) NextOpCodeData
)->OpCode
== EFI_IFR_ONE_OF_OPTION_OP
);
1566 switch (((EFI_IFR_ONE_OF_OPTION
*) NextOpCodeData
)->Type
) {
1567 case EFI_IFR_TYPE_NUM_SIZE_8
:
1568 return (UINT16
) sizeof (UINT8
) * ((EFI_IFR_ORDERED_LIST
*) OpCodeData
)->MaxContainers
;
1570 case EFI_IFR_TYPE_NUM_SIZE_16
:
1571 return (UINT16
) sizeof (UINT16
) * ((EFI_IFR_ORDERED_LIST
*) OpCodeData
)->MaxContainers
;
1573 case EFI_IFR_TYPE_NUM_SIZE_32
:
1574 return (UINT16
) sizeof (UINT32
) * ((EFI_IFR_ORDERED_LIST
*) OpCodeData
)->MaxContainers
;
1576 case EFI_IFR_TYPE_NUM_SIZE_64
:
1577 return (UINT16
) sizeof (UINT64
) * ((EFI_IFR_ORDERED_LIST
*) OpCodeData
)->MaxContainers
;
1584 case EFI_IFR_CHECKBOX_OP
:
1585 return (UINT16
) sizeof (BOOLEAN
);
1587 case EFI_IFR_PASSWORD_OP
:
1588 return (UINT16
)((UINTN
) ((EFI_IFR_PASSWORD
*) OpCodeData
)->MaxSize
* sizeof (CHAR16
));
1590 case EFI_IFR_STRING_OP
:
1591 return (UINT16
)((UINTN
) ((EFI_IFR_STRING
*) OpCodeData
)->MaxSize
* sizeof (CHAR16
));
1593 case EFI_IFR_DATE_OP
:
1594 return (UINT16
) sizeof (EFI_HII_DATE
);
1596 case EFI_IFR_TIME_OP
:
1597 return (UINT16
) sizeof (EFI_HII_TIME
);
1606 Converts all hex string characters in range ['A'..'F'] to ['a'..'f'] for
1607 hex digits that appear between a '=' and a '&' in a config string.
1609 If ConfigString is NULL, then ASSERT().
1611 @param[in] ConfigString Pointer to a Null-terminated Unicode string.
1613 @return Pointer to the Null-terminated Unicode result string.
1618 InternalLowerConfigString (
1619 IN EFI_STRING ConfigString
1625 ASSERT (ConfigString
!= NULL
);
1628 // Convert all hex digits in range [A-F] in the configuration header to [a-f]
1630 for (String
= ConfigString
, Lower
= FALSE
; *String
!= L
'\0'; String
++) {
1631 if (*String
== L
'=') {
1633 } else if (*String
== L
'&') {
1635 } else if (Lower
&& *String
>= L
'A' && *String
<= L
'F') {
1636 *String
= (CHAR16
) (*String
- L
'A' + L
'a');
1640 return ConfigString
;
1644 Allocates and returns a Null-terminated Unicode <ConfigHdr> string.
1646 The format of a <ConfigHdr> is as follows:
1648 GUID=<HexCh>32&NAME=<Char>NameLength&PATH=<HexChar>DevicePathSize<Null>
1650 @param[in] OpCodeData The opcode for the storage.
1651 @param[in] DriverHandle The driver handle which supports a Device Path Protocol
1652 that is the routing information PATH. Each byte of
1653 the Device Path associated with DriverHandle is converted
1654 to a 2 Unicode character hexadecimal string.
1656 @retval NULL DriverHandle does not support the Device Path Protocol.
1657 @retval Other A pointer to the Null-terminate Unicode <ConfigHdr> string
1661 ConstructConfigHdr (
1662 IN UINT8
*OpCodeData
,
1663 IN EFI_HANDLE DriverHandle
1667 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
1668 UINTN DevicePathSize
;
1670 CHAR16
*ReturnString
;
1679 ASSERT (OpCodeData
!= NULL
);
1681 switch (((EFI_IFR_OP_HEADER
*)OpCodeData
)->OpCode
) {
1682 case EFI_IFR_VARSTORE_OP
:
1683 Guid
= (EFI_GUID
*)(UINTN
*)&((EFI_IFR_VARSTORE
*) OpCodeData
)->Guid
;
1684 AsciiName
= (CHAR8
*) ((EFI_IFR_VARSTORE
*) OpCodeData
)->Name
;
1687 case EFI_IFR_VARSTORE_NAME_VALUE_OP
:
1688 Guid
= (EFI_GUID
*)(UINTN
*)&((EFI_IFR_VARSTORE_NAME_VALUE
*) OpCodeData
)->Guid
;
1692 case EFI_IFR_VARSTORE_EFI_OP
:
1693 Guid
= (EFI_GUID
*)(UINTN
*)&((EFI_IFR_VARSTORE_EFI
*) OpCodeData
)->Guid
;
1694 AsciiName
= (CHAR8
*) ((EFI_IFR_VARSTORE_EFI
*) OpCodeData
)->Name
;
1704 if (AsciiName
!= NULL
) {
1705 NameSize
= AsciiStrSize (AsciiName
);
1706 Name
= AllocateZeroPool (NameSize
* sizeof (CHAR16
));
1707 ASSERT (Name
!= NULL
);
1708 AsciiStrToUnicodeStrS (AsciiName
, Name
, NameSize
);
1714 // Compute the length of Name in Unicode characters.
1715 // If Name is NULL, then the length is 0.
1719 NameLength
= StrLen (Name
);
1725 // Retrieve DevicePath Protocol associated with DriverHandle
1727 if (DriverHandle
!= NULL
) {
1728 DevicePath
= DevicePathFromHandle (DriverHandle
);
1729 if (DevicePath
== NULL
) {
1733 // Compute the size of the device path in bytes
1735 DevicePathSize
= GetDevicePathSize (DevicePath
);
1739 // GUID=<HexCh>32&NAME=<Char>NameLength&PATH=<HexChar>DevicePathSize <Null>
1740 // | 5 | sizeof (EFI_GUID) * 2 | 6 | NameStrLen*4 | 6 | DevicePathSize * 2 | 1 |
1742 MaxLen
= 5 + sizeof (EFI_GUID
) * 2 + 6 + NameLength
* 4 + 6 + DevicePathSize
* 2 + 1;
1743 String
= AllocateZeroPool (MaxLen
* sizeof (CHAR16
));
1744 if (String
== NULL
) {
1749 // Start with L"GUID="
1751 StrCpyS (String
, MaxLen
, L
"GUID=");
1752 ReturnString
= String
;
1753 String
+= StrLen (String
);
1757 // Append Guid converted to <HexCh>32
1759 for (Index
= 0, Buffer
= (UINT8
*)Guid
; Index
< sizeof (EFI_GUID
); Index
++) {
1760 UnicodeValueToStringS (
1762 MaxLen
* sizeof (CHAR16
) - ((UINTN
)String
- (UINTN
)ReturnString
),
1763 PREFIX_ZERO
| RADIX_HEX
,
1767 String
+= StrnLenS (String
, MaxLen
- ((UINTN
)String
- (UINTN
)ReturnString
) / sizeof (CHAR16
));
1774 StrCatS (ReturnString
, MaxLen
, L
"&NAME=");
1775 String
+= StrLen (String
);
1779 // Append Name converted to <Char>NameLength
1781 for (; *Name
!= L
'\0'; Name
++) {
1782 UnicodeValueToStringS (
1784 MaxLen
* sizeof (CHAR16
) - ((UINTN
)String
- (UINTN
)ReturnString
),
1785 PREFIX_ZERO
| RADIX_HEX
,
1789 String
+= StrnLenS (String
, MaxLen
- ((UINTN
)String
- (UINTN
)ReturnString
) / sizeof (CHAR16
));
1796 StrCatS (ReturnString
, MaxLen
, L
"&PATH=");
1797 String
+= StrLen (String
);
1800 // Append the device path associated with DriverHandle converted to <HexChar>DevicePathSize
1802 for (Index
= 0, Buffer
= (UINT8
*)DevicePath
; Index
< DevicePathSize
; Index
++) {
1803 UnicodeValueToStringS (
1805 MaxLen
* sizeof (CHAR16
) - ((UINTN
)String
- (UINTN
)ReturnString
),
1806 PREFIX_ZERO
| RADIX_HEX
,
1810 String
+= StrnLenS (String
, MaxLen
- ((UINTN
)String
- (UINTN
)ReturnString
) / sizeof (CHAR16
));
1814 // Null terminate the Unicode string
1819 // Convert all hex digits in range [A-F] in the configuration header to [a-f]
1821 return InternalLowerConfigString (ReturnString
);
1825 Generate the Config request element for one question.
1827 @param Name The name info for one question.
1828 @param Offset The offset info for one question.
1829 @param Width The width info for one question.
1831 @return Pointer to the Null-terminated Unicode request element string.
1835 ConstructRequestElement (
1846 // Add <BlockName> length for each Name
1848 // <BlockName> ::= Name + \0
1851 Length
= StrLen (Name
) + 1;
1854 // Add <BlockName> length for each Offset/Width pair
1856 // <BlockName> ::= OFFSET=1234&WIDTH=1234 + \0
1857 // | 7 | 4 | 7 | 4 | 1
1859 Length
= (7 + 4 + 7 + 4 + 1);
1863 // Allocate buffer for the entire <ConfigRequest>
1865 StringPtr
= AllocateZeroPool (Length
* sizeof (CHAR16
));
1866 ASSERT (StringPtr
!= NULL
);
1874 (StrLen (Name
) + 1) * sizeof (CHAR16
),
1880 // Append OFFSET=XXXX&WIDTH=YYYY\0
1884 (7 + 4 + 7 + 4 + 1) * sizeof (CHAR16
),
1885 L
"OFFSET=%04X&WIDTH=%04X",
1895 Get string value for question's name field.
1897 @param DatabaseRecord HII_DATABASE_RECORD format string.
1898 @param NameId The string id for the name field.
1900 @retval Name string.
1905 IN HII_DATABASE_RECORD
*DatabaseRecord
,
1906 IN EFI_STRING_ID NameId
1910 CHAR8
*PlatformLanguage
;
1911 CHAR8
*SupportedLanguages
;
1912 CHAR8
*BestLanguage
;
1918 BestLanguage
= NULL
;
1919 PlatformLanguage
= NULL
;
1920 SupportedLanguages
= NULL
;
1922 GetEfiGlobalVariable2 (L
"PlatformLang", (VOID
**)&PlatformLanguage
, NULL
);
1923 SupportedLanguages
= GetSupportedLanguages(DatabaseRecord
->Handle
);
1926 // Get the best matching language from SupportedLanguages
1928 BestLanguage
= GetBestLanguage (
1930 FALSE
, // RFC 4646 mode
1931 PlatformLanguage
!= NULL
? PlatformLanguage
: "", // Highest priority
1932 SupportedLanguages
, // Lowest priority
1935 if (BestLanguage
== NULL
) {
1936 BestLanguage
= AllocateCopyPool (AsciiStrLen ("en-US"), "en-US");
1937 ASSERT (BestLanguage
!= NULL
);
1941 Status
= mPrivate
.HiiString
.GetString (
1942 &mPrivate
.HiiString
,
1944 DatabaseRecord
->Handle
,
1950 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
1954 Name
= AllocateZeroPool (StringSize
);
1959 Status
= mPrivate
.HiiString
.GetString (
1960 &mPrivate
.HiiString
,
1962 DatabaseRecord
->Handle
,
1969 if (EFI_ERROR (Status
)) {
1976 if (SupportedLanguages
!= NULL
) {
1977 FreePool(SupportedLanguages
);
1979 if (BestLanguage
!= NULL
) {
1980 FreePool (BestLanguage
);
1982 if (PlatformLanguage
!= NULL
) {
1983 FreePool (PlatformLanguage
);
1990 Base on the input parameter to generate the ConfigRequest string.
1992 This is a internal function.
1994 @param DatabaseRecord HII_DATABASE_RECORD format string.
1995 @param KeywordStrId Keyword string id.
1996 @param OpCodeData The IFR data for this question.
1997 @param ConfigRequest Return the generate ConfigRequest string.
1999 @retval EFI_SUCCESS Generate ConfigResp string success.
2000 @retval EFI_OUT_OF_RESOURCES System out of memory resource error.
2001 @retval EFI_NOT_FOUND Not found the question which use this string id
2002 as the prompt string id.
2005 ExtractConfigRequest (
2006 IN HII_DATABASE_RECORD
*DatabaseRecord
,
2007 IN EFI_STRING_ID KeywordStrId
,
2008 OUT UINT8
**OpCodeData
,
2009 OUT EFI_STRING
*ConfigRequest
2013 HII_DATABASE_PACKAGE_LIST_INSTANCE
*PackageListNode
;
2014 HII_IFR_PACKAGE_INSTANCE
*FormPackage
;
2015 EFI_IFR_QUESTION_HEADER
*Header
;
2022 CHAR16
*RequestElement
;
2026 ASSERT (DatabaseRecord
!= NULL
&& OpCodeData
!= NULL
&& ConfigRequest
!= NULL
);
2033 PackageListNode
= DatabaseRecord
->PackageList
;
2036 // Search the languages in the specified packagelist.
2038 for (Link
= PackageListNode
->FormPkgHdr
.ForwardLink
; Link
!= &PackageListNode
->FormPkgHdr
; Link
= Link
->ForwardLink
) {
2039 FormPackage
= CR (Link
, HII_IFR_PACKAGE_INSTANCE
, IfrEntry
, HII_IFR_PACKAGE_SIGNATURE
);
2041 OpCode
= FindQuestionFromStringId (FormPackage
, KeywordStrId
);
2042 if (OpCode
!= NULL
) {
2043 *OpCodeData
= OpCode
;
2044 Header
= (EFI_IFR_QUESTION_HEADER
*) (OpCode
+ sizeof (EFI_IFR_OP_HEADER
));
2046 // Header->VarStoreId == 0 means no storage for this question.
2048 ASSERT (Header
->VarStoreId
!= 0);
2049 DEBUG ((EFI_D_INFO
, "Varstore Id: 0x%x\n", Header
->VarStoreId
));
2051 Storage
= FindStorageFromVarId (FormPackage
, Header
->VarStoreId
);
2052 ASSERT (Storage
!= NULL
);
2054 if (((EFI_IFR_OP_HEADER
*) Storage
)->OpCode
== EFI_IFR_VARSTORE_NAME_VALUE_OP
) {
2055 Name
= GetNameFromId (DatabaseRecord
, Header
->VarStoreInfo
.VarName
);
2057 Offset
= Header
->VarStoreInfo
.VarOffset
;
2058 Width
= GetWidth (OpCode
);
2060 RequestElement
= ConstructRequestElement(Name
, Offset
, Width
);
2061 ConfigHdr
= ConstructConfigHdr(Storage
, DatabaseRecord
->DriverHandle
);
2062 ASSERT (ConfigHdr
!= NULL
);
2064 MaxLen
= StrLen (ConfigHdr
) + 1 + StrLen(RequestElement
) + 1;
2065 *ConfigRequest
= AllocatePool (MaxLen
* sizeof (CHAR16
));
2066 if (*ConfigRequest
== NULL
) {
2067 FreePool (ConfigHdr
);
2068 FreePool (RequestElement
);
2069 return EFI_OUT_OF_RESOURCES
;
2071 StringPtr
= *ConfigRequest
;
2073 StrCpyS (StringPtr
, MaxLen
, ConfigHdr
);
2075 StrCatS (StringPtr
, MaxLen
, L
"&");
2077 StrCatS (StringPtr
, MaxLen
, RequestElement
);
2079 FreePool (ConfigHdr
);
2080 FreePool (RequestElement
);
2086 return EFI_NOT_FOUND
;
2090 Base on the input parameter to generate the ConfigResp string.
2092 This is a internal function.
2094 @param DatabaseRecord HII_DATABASE_RECORD format string.
2095 @param KeywordStrId Keyword string id.
2096 @param ValueElement The value for the question which use keyword string id
2097 as the prompt string id.
2098 @param OpCodeData The IFR data for this question.
2099 @param ConfigResp Return the generate ConfigResp string.
2101 @retval EFI_SUCCESS Generate ConfigResp string success.
2102 @retval EFI_OUT_OF_RESOURCES System out of memory resource error.
2103 @retval EFI_NOT_FOUND Not found the question which use this string id
2104 as the prompt string id.
2108 IN HII_DATABASE_RECORD
*DatabaseRecord
,
2109 IN EFI_STRING_ID KeywordStrId
,
2110 IN EFI_STRING ValueElement
,
2111 OUT UINT8
**OpCodeData
,
2112 OUT EFI_STRING
*ConfigResp
2116 HII_DATABASE_PACKAGE_LIST_INSTANCE
*PackageListNode
;
2117 HII_IFR_PACKAGE_INSTANCE
*FormPackage
;
2118 EFI_IFR_QUESTION_HEADER
*Header
;
2125 CHAR16
*RequestElement
;
2129 ASSERT ((DatabaseRecord
!= NULL
) && (OpCodeData
!= NULL
) && (ConfigResp
!= NULL
) && (ValueElement
!= NULL
));
2136 PackageListNode
= DatabaseRecord
->PackageList
;
2139 // Search the languages in the specified packagelist.
2141 for (Link
= PackageListNode
->FormPkgHdr
.ForwardLink
; Link
!= &PackageListNode
->FormPkgHdr
; Link
= Link
->ForwardLink
) {
2142 FormPackage
= CR (Link
, HII_IFR_PACKAGE_INSTANCE
, IfrEntry
, HII_IFR_PACKAGE_SIGNATURE
);
2144 OpCode
= FindQuestionFromStringId (FormPackage
, KeywordStrId
);
2145 if (OpCode
!= NULL
) {
2146 *OpCodeData
= OpCode
;
2147 Header
= (EFI_IFR_QUESTION_HEADER
*) (OpCode
+ sizeof (EFI_IFR_OP_HEADER
));
2149 // Header->VarStoreId == 0 means no storage for this question.
2151 ASSERT (Header
->VarStoreId
!= 0);
2152 DEBUG ((EFI_D_INFO
, "Varstore Id: 0x%x\n", Header
->VarStoreId
));
2154 Storage
= FindStorageFromVarId (FormPackage
, Header
->VarStoreId
);
2155 ASSERT (Storage
!= NULL
);
2157 if (((EFI_IFR_OP_HEADER
*) Storage
)->OpCode
== EFI_IFR_VARSTORE_NAME_VALUE_OP
) {
2158 Name
= GetNameFromId (DatabaseRecord
, Header
->VarStoreInfo
.VarName
);
2160 Offset
= Header
->VarStoreInfo
.VarOffset
;
2161 Width
= GetWidth (OpCode
);
2163 RequestElement
= ConstructRequestElement(Name
, Offset
, Width
);
2165 ConfigHdr
= ConstructConfigHdr(Storage
, DatabaseRecord
->DriverHandle
);
2166 ASSERT (ConfigHdr
!= NULL
);
2168 MaxLen
= StrLen (ConfigHdr
) + 1 + StrLen(RequestElement
) + 1 + StrLen (L
"VALUE=") + StrLen(ValueElement
) + 1;
2169 *ConfigResp
= AllocatePool (MaxLen
* sizeof (CHAR16
));
2170 if (*ConfigResp
== NULL
) {
2171 FreePool (ConfigHdr
);
2172 FreePool (RequestElement
);
2173 return EFI_OUT_OF_RESOURCES
;
2175 StringPtr
= *ConfigResp
;
2177 StrCpyS (StringPtr
, MaxLen
, ConfigHdr
);
2179 StrCatS (StringPtr
, MaxLen
, L
"&");
2182 StrCatS (StringPtr
, MaxLen
, RequestElement
);
2184 StrCatS (StringPtr
, MaxLen
, L
"&");
2186 StrCatS (StringPtr
, MaxLen
, L
"VALUE=");
2188 StrCatS (StringPtr
, MaxLen
, ValueElement
);
2190 FreePool (ConfigHdr
);
2191 FreePool (RequestElement
);
2197 return EFI_NOT_FOUND
;
2201 Get the Value section from the Hii driver.
2203 This is a internal function.
2205 @param ConfigRequest The input ConfigRequest string.
2206 @param ValueElement The respond Value section from the hii driver.
2208 @retval Misc value The error status return from ExtractConfig function.
2209 @retval EFI_OUT_OF_RESOURCES The memory can't be allocated
2210 @retval EFI_SUCCESS Get the value section success.
2214 ExtractValueFromDriver (
2215 IN CHAR16
*ConfigRequest
,
2216 OUT CHAR16
**ValueElement
2221 EFI_STRING Progress
;
2225 ASSERT ((ConfigRequest
!= NULL
) && (ValueElement
!= NULL
));
2227 Status
= mPrivate
.ConfigRouting
.ExtractConfig (
2228 &mPrivate
.ConfigRouting
,
2229 (EFI_STRING
) ConfigRequest
,
2233 if (EFI_ERROR (Status
)) {
2238 // Find Value Section and return it.
2240 StringPtr
= StrStr (Result
, L
"&VALUE=");
2241 ASSERT (StringPtr
!= NULL
);
2242 StringEnd
= StrStr (StringPtr
+ 1, L
"&");
2243 if (StringEnd
!= NULL
) {
2247 *ValueElement
= AllocateCopyPool (StrSize (StringPtr
), StringPtr
);
2248 if (*ValueElement
== NULL
) {
2249 return EFI_OUT_OF_RESOURCES
;
2252 if (StringEnd
!= NULL
) {
2261 Get EFI_STRING_ID info from the input device path, namespace and keyword.
2263 This is a internal function.
2265 @param DevicePath Input device path info.
2266 @param NameSpace NameSpace format string.
2267 @param KeywordData Keyword used to get string id.
2268 @param ProgressErr Return extra error type.
2269 @param KeywordStringId Return EFI_STRING_ID.
2270 @param DataBaseRecord DataBase record data for this driver.
2272 @retval EFI_INVALID_PARAMETER Can't find the database record base on the input device path or namespace.
2273 @retval EFI_NOT_FOUND Can't find the EFI_STRING_ID for the keyword.
2274 @retval EFI_SUCCESS Find the EFI_STRING_ID.
2278 GetStringIdFromDatabase (
2279 IN EFI_DEVICE_PATH_PROTOCOL
**DevicePath
,
2280 IN CHAR8
**NameSpace
,
2281 IN CHAR16
*KeywordData
,
2282 OUT UINT32
*ProgressErr
,
2283 OUT EFI_STRING_ID
*KeywordStringId
,
2284 OUT HII_DATABASE_RECORD
**DataBaseRecord
2287 HII_DATABASE_RECORD
*Record
;
2289 BOOLEAN FindNameSpace
;
2290 EFI_DEVICE_PATH_PROTOCOL
*DestDevicePath
;
2291 UINT8
*DevicePathPkg
;
2292 UINTN DevicePathSize
;
2294 ASSERT ((NameSpace
!= NULL
) && (KeywordData
!= NULL
) && (ProgressErr
!= NULL
) && (KeywordStringId
!= NULL
) && (DataBaseRecord
!= NULL
));
2296 FindNameSpace
= FALSE
;
2298 if (*DevicePath
!= NULL
) {
2300 // Get DataBaseRecord from device path protocol.
2302 Record
= GetRecordFromDevicePath(*DevicePath
);
2303 if (Record
== NULL
) {
2305 // Can't find the DatabaseRecord base on the input device path info.
2306 // NEED TO CONFIRM the return ProgressErr.
2308 *ProgressErr
= KEYWORD_HANDLER_MALFORMED_STRING
;
2309 return EFI_INVALID_PARAMETER
;
2313 // Get string id from the record.
2315 *ProgressErr
= GetStringIdFromRecord (Record
, NameSpace
, KeywordData
, KeywordStringId
);
2316 switch (*ProgressErr
) {
2317 case KEYWORD_HANDLER_NO_ERROR
:
2318 *DataBaseRecord
= Record
;
2321 case KEYWORD_HANDLER_NAMESPACE_ID_NOT_FOUND
:
2322 return EFI_INVALID_PARAMETER
;
2325 ASSERT (*ProgressErr
== KEYWORD_HANDLER_KEYWORD_NOT_FOUND
);
2326 return EFI_NOT_FOUND
;
2330 // Find driver which matches the routing data.
2332 for (Link
= mPrivate
.DatabaseList
.ForwardLink
; Link
!= &mPrivate
.DatabaseList
; Link
= Link
->ForwardLink
) {
2333 Record
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
2335 *ProgressErr
= GetStringIdFromRecord (Record
, NameSpace
, KeywordData
, KeywordStringId
);
2336 if (*ProgressErr
== KEYWORD_HANDLER_NO_ERROR
) {
2337 *DataBaseRecord
= Record
;
2339 if ((DevicePathPkg
= Record
->PackageList
->DevicePathPkg
) != NULL
) {
2340 DestDevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) (DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
));
2341 DevicePathSize
= GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) DestDevicePath
);
2342 *DevicePath
= AllocateCopyPool (DevicePathSize
, DestDevicePath
);
2343 if (*DevicePath
== NULL
) {
2344 return EFI_OUT_OF_RESOURCES
;
2348 // Need to verify this ASSERT.
2354 } else if (*ProgressErr
== KEYWORD_HANDLER_UNDEFINED_PROCESSING_ERROR
) {
2355 return EFI_OUT_OF_RESOURCES
;
2356 } else if (*ProgressErr
== KEYWORD_HANDLER_KEYWORD_NOT_FOUND
) {
2357 FindNameSpace
= TRUE
;
2362 // When PathHdr not input, if ever find the namespace, will return KEYWORD_HANDLER_KEYWORD_NOT_FOUND.
2363 // This is a bit more progress than KEYWORD_HANDLER_NAMESPACE_ID_NOT_FOUND.
2365 if (FindNameSpace
) {
2366 return EFI_NOT_FOUND
;
2368 return EFI_INVALID_PARAMETER
;
2374 Generate the KeywordResp String.
2376 <KeywordResp> ::= <NameSpaceId><PathHdr>'&'<Keyword>'&VALUE='<Number>['&READONLY']
2378 @param NameSpace NameSpace format string.
2379 @param DevicePath Input device path info.
2380 @param KeywordData Keyword used to get string id.
2381 @param ValueStr The value section for the keyword.
2382 @param ReadOnly Whether this value is readonly.
2383 @param KeywordResp Return the point to the KeywordResp string.
2385 @retval EFI_OUT_OF_RESOURCES The memory can't be allocated.
2386 @retval EFI_SUCCESS Generate the KeywordResp string.
2390 GenerateKeywordResp (
2391 IN CHAR8
*NameSpace
,
2392 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
2393 IN EFI_STRING KeywordData
,
2394 IN EFI_STRING ValueStr
,
2395 IN BOOLEAN ReadOnly
,
2396 OUT EFI_STRING
*KeywordResp
2402 CHAR16
*UnicodeNameSpace
;
2403 UINTN NameSpaceLength
;
2405 ASSERT ((NameSpace
!= NULL
) && (DevicePath
!= NULL
) && (KeywordData
!= NULL
) && (ValueStr
!= NULL
) && (KeywordResp
!= NULL
));
2408 // 1. Calculate the string length.
2411 // 1.1 NameSpaceId size.
2412 // 'NAMESPACE='<String>
2414 NameSpaceLength
= AsciiStrLen (NameSpace
);
2415 RespStrLen
= 10 + NameSpaceLength
;
2416 UnicodeNameSpace
= AllocatePool ((NameSpaceLength
+ 1) * sizeof (CHAR16
));
2417 if (UnicodeNameSpace
== NULL
) {
2418 return EFI_OUT_OF_RESOURCES
;
2420 AsciiStrToUnicodeStrS (NameSpace
, UnicodeNameSpace
, NameSpaceLength
+ 1);
2423 // 1.2 PathHdr size.
2424 // PATH=<UEFI binary Device Path represented as hex number>'&'
2425 // Attention: The output include the '&' at the end.
2429 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) DevicePath
),
2430 (VOID
*) DevicePath
,
2434 RespStrLen
+= StrLen (PathHdr
);
2437 // 1.3 Keyword section.
2438 // 'KEYWORD='<String>[':'<DecCh>(1/4)]
2440 RespStrLen
+= 8 + StrLen (KeywordData
);
2443 // 1.4 Value section.
2444 // ValueStr = '&VALUE='<Number>
2446 RespStrLen
+= StrLen (ValueStr
);
2449 // 1.5 ReadOnly Section.
2457 // 2. Allocate the buffer and create the KeywordResp string include '\0'.
2460 *KeywordResp
= AllocatePool (RespStrLen
* sizeof (CHAR16
));
2461 if (*KeywordResp
== NULL
) {
2462 if (UnicodeNameSpace
!= NULL
) {
2463 FreePool (UnicodeNameSpace
);
2466 return EFI_OUT_OF_RESOURCES
;
2468 RespStr
= *KeywordResp
;
2471 // 2.1 Copy NameSpaceId section.
2473 StrCpyS (RespStr
, RespStrLen
, L
"NAMESPACE=");
2475 StrCatS (RespStr
, RespStrLen
, UnicodeNameSpace
);
2478 // 2.2 Copy PathHdr section.
2480 StrCatS (RespStr
, RespStrLen
, PathHdr
);
2483 // 2.3 Copy Keyword section.
2485 StrCatS (RespStr
, RespStrLen
, L
"KEYWORD=");
2487 StrCatS (RespStr
, RespStrLen
, KeywordData
);
2490 // 2.4 Copy the Value section.
2492 StrCatS (RespStr
, RespStrLen
, ValueStr
);
2495 // 2.5 Copy ReadOnly section if exist.
2498 StrCatS (RespStr
, RespStrLen
, L
"&READONLY");
2501 if (UnicodeNameSpace
!= NULL
) {
2502 FreePool (UnicodeNameSpace
);
2504 if (PathHdr
!= NULL
) {
2512 Merge the KeywordResp String to MultiKeywordResp string.
2514 This is a internal function.
2516 @param MultiKeywordResp The existed multikeywordresp string.
2517 @param KeywordResp The input keywordResp string.
2519 @retval EFI_OUT_OF_RESOURCES The memory can't be allocated.
2520 @retval EFI_SUCCESS Generate the MultiKeywordResp string.
2524 MergeToMultiKeywordResp (
2525 IN OUT EFI_STRING
*MultiKeywordResp
,
2526 IN EFI_STRING
*KeywordResp
2529 UINTN MultiKeywordRespLen
;
2530 EFI_STRING StringPtr
;
2532 if (*MultiKeywordResp
== NULL
) {
2533 *MultiKeywordResp
= *KeywordResp
;
2534 *KeywordResp
= NULL
;
2538 MultiKeywordRespLen
= (StrLen (*MultiKeywordResp
) + 1 + StrLen (*KeywordResp
) + 1) * sizeof (CHAR16
);
2540 StringPtr
= ReallocatePool (
2541 StrSize (*MultiKeywordResp
),
2542 MultiKeywordRespLen
,
2545 if (StringPtr
== NULL
) {
2546 return EFI_OUT_OF_RESOURCES
;
2549 *MultiKeywordResp
= StringPtr
;
2551 StrCatS (StringPtr
, MultiKeywordRespLen
/ sizeof (CHAR16
), L
"&");
2553 StrCatS (StringPtr
, MultiKeywordRespLen
/ sizeof (CHAR16
), *KeywordResp
);
2559 Enumerate all keyword in the system.
2561 If error occur when parse one keyword, just skip it and parse the next one.
2563 This is a internal function.
2565 @param NameSpace The namespace used to search the string.
2566 @param MultiResp Return the MultiKeywordResp string for the system.
2567 @param ProgressErr Return the error status.
2569 @retval EFI_OUT_OF_RESOURCES The memory can't be allocated.
2570 @retval EFI_SUCCESS Generate the MultiKeywordResp string.
2571 @retval EFI_NOT_FOUND No keyword found.
2575 EnumerateAllKeywords (
2576 IN CHAR8
*NameSpace
,
2577 OUT EFI_STRING
*MultiResp
,
2578 OUT UINT32
*ProgressErr
2582 LIST_ENTRY
*StringLink
;
2583 UINT8
*DevicePathPkg
;
2585 HII_DATABASE_RECORD
*DataBaseRecord
;
2586 HII_DATABASE_PACKAGE_LIST_INSTANCE
*PackageListNode
;
2587 HII_STRING_PACKAGE_INSTANCE
*StringPackage
;
2588 CHAR8
*LocalNameSpace
;
2589 EFI_STRING_ID NextStringId
;
2592 CHAR16
*ConfigRequest
;
2593 CHAR16
*ValueElement
;
2594 CHAR16
*KeywordResp
;
2595 CHAR16
*MultiKeywordResp
;
2596 CHAR16
*KeywordData
;
2598 BOOLEAN FindKeywordPackages
;
2600 DataBaseRecord
= NULL
;
2601 Status
= EFI_SUCCESS
;
2602 MultiKeywordResp
= NULL
;
2604 LocalNameSpace
= NULL
;
2605 ConfigRequest
= NULL
;
2606 ValueElement
= NULL
;
2608 FindKeywordPackages
= FALSE
;
2610 if (NameSpace
== NULL
) {
2611 NameSpace
= UEFI_CONFIG_LANG
;
2615 // Find driver which matches the routing data.
2617 for (Link
= mPrivate
.DatabaseList
.ForwardLink
; Link
!= &mPrivate
.DatabaseList
; Link
= Link
->ForwardLink
) {
2618 DataBaseRecord
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
2619 if ((DevicePathPkg
= DataBaseRecord
->PackageList
->DevicePathPkg
) != NULL
) {
2620 DevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
2622 PackageListNode
= DataBaseRecord
->PackageList
;
2624 for (StringLink
= PackageListNode
->StringPkgHdr
.ForwardLink
; StringLink
!= &PackageListNode
->StringPkgHdr
; StringLink
= StringLink
->ForwardLink
) {
2625 StringPackage
= CR (StringLink
, HII_STRING_PACKAGE_INSTANCE
, StringEntry
, HII_STRING_PACKAGE_SIGNATURE
);
2628 // Check whether has keyword string package.
2630 if (AsciiStrnCmp(NameSpace
, StringPackage
->StringPkgHdr
->Language
, AsciiStrLen (NameSpace
)) == 0) {
2631 FindKeywordPackages
= TRUE
;
2633 // Keep the NameSpace string.
2635 LocalNameSpace
= AllocateCopyPool (AsciiStrSize (StringPackage
->StringPkgHdr
->Language
), StringPackage
->StringPkgHdr
->Language
);
2636 if (LocalNameSpace
== NULL
) {
2637 return EFI_OUT_OF_RESOURCES
;
2641 // 1 means just begin the enumerate the valid string ids.
2642 // StringId == 1 is always used to save the language for this string package.
2643 // Any valid string start from 2. so here initial it to 1.
2648 // Enumerate all valid stringid in the package.
2650 while ((NextStringId
= GetNextStringId (StringPackage
, NextStringId
, &KeywordData
)) != 0) {
2652 // 3.3 Construct the ConfigRequest string.
2654 Status
= ExtractConfigRequest (DataBaseRecord
, NextStringId
, &OpCode
, &ConfigRequest
);
2655 if (EFI_ERROR (Status
)) {
2657 // If can't generate ConfigRequest for this question, skip it and start the next.
2663 // 3.4 Extract Value for the input keyword.
2665 Status
= ExtractValueFromDriver(ConfigRequest
, &ValueElement
);
2666 if (EFI_ERROR (Status
)) {
2667 if (Status
!= EFI_OUT_OF_RESOURCES
) {
2669 // If can't generate ConfigRequest for this question, skip it and start the next.
2674 // If EFI_OUT_OF_RESOURCES error occur, no need to continue.
2680 // Extract readonly flag from opcode.
2682 ReadOnly
= ExtractReadOnlyFromOpCode(OpCode
);
2685 // 5. Generate KeywordResp string.
2687 ASSERT (DevicePath
!= NULL
);
2688 Status
= GenerateKeywordResp(LocalNameSpace
, (EFI_DEVICE_PATH_PROTOCOL
*)DevicePath
, KeywordData
, ValueElement
, ReadOnly
, &KeywordResp
);
2689 if (Status
!= EFI_SUCCESS
) {
2691 // If EFI_OUT_OF_RESOURCES error occur, no need to continue.
2697 // 6. Merge to the MultiKeywordResp string.
2699 Status
= MergeToMultiKeywordResp(&MultiKeywordResp
, &KeywordResp
);
2700 if (EFI_ERROR (Status
)) {
2705 // Clean the temp buffer to later use again.
2707 if (ConfigRequest
!= NULL
) {
2708 FreePool (ConfigRequest
);
2709 ConfigRequest
= NULL
;
2711 if (ValueElement
!= NULL
) {
2712 FreePool (ValueElement
);
2713 ValueElement
= NULL
;
2715 if (KeywordResp
!= NULL
) {
2716 FreePool (KeywordResp
);
2721 if (LocalNameSpace
!= NULL
) {
2722 FreePool (LocalNameSpace
);
2723 LocalNameSpace
= NULL
;
2730 // return the already get MultiKeywordString even error occurred.
2732 if (MultiKeywordResp
== NULL
) {
2733 Status
= EFI_NOT_FOUND
;
2734 if (!FindKeywordPackages
) {
2735 *ProgressErr
= KEYWORD_HANDLER_NAMESPACE_ID_NOT_FOUND
;
2737 *ProgressErr
= KEYWORD_HANDLER_KEYWORD_NOT_FOUND
;
2740 Status
= EFI_SUCCESS
;
2742 *MultiResp
= MultiKeywordResp
;
2745 if (LocalNameSpace
!= NULL
) {
2746 FreePool (LocalNameSpace
);
2748 if (ConfigRequest
!= NULL
) {
2749 FreePool (ConfigRequest
);
2751 if (ValueElement
!= NULL
) {
2752 FreePool (ValueElement
);
2760 This function accepts a <MultiKeywordResp> formatted string, finds the associated
2761 keyword owners, creates a <MultiConfigResp> string from it and forwards it to the
2762 EFI_HII_ROUTING_PROTOCOL.RouteConfig function.
2764 If there is an issue in resolving the contents of the KeywordString, then the
2765 function returns an error and also sets the Progress and ProgressErr with the
2766 appropriate information about where the issue occurred and additional data about
2767 the nature of the issue.
2769 In the case when KeywordString containing multiple keywords, when an EFI_NOT_FOUND
2770 error is generated during processing the second or later keyword element, the system
2771 storage associated with earlier keywords is not modified. All elements of the
2772 KeywordString must successfully pass all tests for format and access prior to making
2773 any modifications to storage.
2775 In the case when EFI_DEVICE_ERROR is returned from the processing of a KeywordString
2776 containing multiple keywords, the state of storage associated with earlier keywords
2780 @param This Pointer to the EFI_KEYWORD_HANDLER _PROTOCOL instance.
2782 @param KeywordString A null-terminated string in <MultiKeywordResp> format.
2784 @param Progress On return, points to a character in the KeywordString.
2785 Points to the string's NULL terminator if the request
2786 was successful. Points to the most recent '&' before
2787 the first failing name / value pair (or the beginning
2788 of the string if the failure is in the first name / value
2789 pair) if the request was not successful.
2791 @param ProgressErr If during the processing of the KeywordString there was
2792 a failure, this parameter gives additional information
2793 about the possible source of the problem. The various
2794 errors are defined in "Related Definitions" below.
2797 @retval EFI_SUCCESS The specified action was completed successfully.
2799 @retval EFI_INVALID_PARAMETER One or more of the following are TRUE:
2800 1. KeywordString is NULL.
2801 2. Parsing of the KeywordString resulted in an
2802 error. See Progress and ProgressErr for more data.
2804 @retval EFI_NOT_FOUND An element of the KeywordString was not found.
2805 See ProgressErr for more data.
2807 @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
2808 See ProgressErr for more data.
2810 @retval EFI_ACCESS_DENIED The action violated system policy. See ProgressErr
2813 @retval EFI_DEVICE_ERROR An unexpected system error occurred. See ProgressErr
2819 EfiConfigKeywordHandlerSetData (
2820 IN EFI_CONFIG_KEYWORD_HANDLER_PROTOCOL
*This
,
2821 IN CONST EFI_STRING KeywordString
,
2822 OUT EFI_STRING
*Progress
,
2823 OUT UINT32
*ProgressErr
2829 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
2830 CHAR16
*NextStringPtr
;
2831 CHAR16
*KeywordData
;
2832 EFI_STRING_ID KeywordStringId
;
2834 HII_DATABASE_RECORD
*DataBaseRecord
;
2837 CHAR16
*MultiConfigResp
;
2838 CHAR16
*ValueElement
;
2840 EFI_STRING InternalProgress
;
2842 CHAR16
*KeywordStartPos
;
2844 if (This
== NULL
|| Progress
== NULL
|| ProgressErr
== NULL
|| KeywordString
== NULL
) {
2845 return EFI_INVALID_PARAMETER
;
2848 *Progress
= KeywordString
;
2849 *ProgressErr
= KEYWORD_HANDLER_UNDEFINED_PROCESSING_ERROR
;
2850 Status
= EFI_SUCCESS
;
2851 MultiConfigResp
= NULL
;
2855 ValueElement
= NULL
;
2857 KeywordStartPos
= NULL
;
2858 KeywordStringId
= 0;
2861 // Use temp string to avoid changing input string buffer.
2863 TempString
= AllocateCopyPool (StrSize (KeywordString
), KeywordString
);
2864 ASSERT (TempString
!= NULL
);
2865 StringPtr
= TempString
;
2867 while ((StringPtr
!= NULL
) && (*StringPtr
!= L
'\0')) {
2869 // 1. Get NameSpace from NameSpaceId keyword.
2871 Status
= ExtractNameSpace (StringPtr
, &NameSpace
, &NextStringPtr
);
2872 if (EFI_ERROR (Status
)) {
2873 *ProgressErr
= KEYWORD_HANDLER_MALFORMED_STRING
;
2876 ASSERT (NameSpace
!= NULL
);
2878 // 1.1 Check whether the input namespace is valid.
2880 if (AsciiStrnCmp(NameSpace
, UEFI_CONFIG_LANG
, AsciiStrLen (UEFI_CONFIG_LANG
)) != 0) {
2881 *ProgressErr
= KEYWORD_HANDLER_MALFORMED_STRING
;
2882 Status
= EFI_INVALID_PARAMETER
;
2886 StringPtr
= NextStringPtr
;
2889 // 2. Get possible Device Path info from KeywordString.
2891 Status
= ExtractDevicePath (StringPtr
, (UINT8
**)&DevicePath
, &NextStringPtr
);
2892 if (EFI_ERROR (Status
)) {
2893 *ProgressErr
= KEYWORD_HANDLER_MALFORMED_STRING
;
2896 StringPtr
= NextStringPtr
;
2899 // 3. Extract keyword from the KeywordRequest string.
2901 KeywordStartPos
= StringPtr
;
2902 Status
= ExtractKeyword(StringPtr
, &KeywordData
, &NextStringPtr
);
2903 if (EFI_ERROR (Status
)) {
2905 // Can't find Keyword base on the input device path info.
2907 *ProgressErr
= KEYWORD_HANDLER_MALFORMED_STRING
;
2908 Status
= EFI_INVALID_PARAMETER
;
2911 StringPtr
= NextStringPtr
;
2914 // 4. Extract Value from the KeywordRequest string.
2916 Status
= ExtractValue (StringPtr
, &ValueElement
, &NextStringPtr
);
2917 if (EFI_ERROR (Status
)) {
2919 // Can't find Value base on the input device path info.
2921 *ProgressErr
= KEYWORD_HANDLER_MALFORMED_STRING
;
2922 Status
= EFI_INVALID_PARAMETER
;
2925 StringPtr
= NextStringPtr
;
2928 // 5. Find READONLY tag.
2930 if ((StringPtr
!= NULL
) && StrnCmp (StringPtr
, L
"&READONLY", StrLen (L
"&READONLY")) == 0) {
2932 StringPtr
+= StrLen (L
"&READONLY");
2938 // 6. Get EFI_STRING_ID for the input keyword.
2940 Status
= GetStringIdFromDatabase (&DevicePath
, &NameSpace
, KeywordData
, &RetVal
, &KeywordStringId
, &DataBaseRecord
);
2941 if (EFI_ERROR (Status
)) {
2942 *ProgressErr
= RetVal
;
2947 // 7. Construct the ConfigRequest string.
2949 Status
= ExtractConfigResp (DataBaseRecord
, KeywordStringId
, ValueElement
, &OpCode
, &ConfigResp
);
2950 if (EFI_ERROR (Status
)) {
2955 // 8. Check the readonly flag.
2957 if (ExtractReadOnlyFromOpCode (OpCode
) != ReadOnly
) {
2959 // Extracting readonly flag form opcode and extracting "READONLY" tag form KeywordString should have the same results.
2960 // If not, the input KeywordString must be incorrect, return the error status to caller.
2962 *ProgressErr
= KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED
;
2963 Status
= EFI_INVALID_PARAMETER
;
2967 *ProgressErr
= KEYWORD_HANDLER_ACCESS_NOT_PERMITTED
;
2968 Status
= EFI_ACCESS_DENIED
;
2973 // 9. Merge to the MultiKeywordResp string.
2975 Status
= MergeToMultiKeywordResp(&MultiConfigResp
, &ConfigResp
);
2976 if (EFI_ERROR (Status
)) {
2981 // 10. Clean the temp buffer point.
2983 FreePool (NameSpace
);
2984 FreePool (DevicePath
);
2985 FreePool (KeywordData
);
2986 FreePool (ValueElement
);
2990 ValueElement
= NULL
;
2991 if (ConfigResp
!= NULL
) {
2992 FreePool (ConfigResp
);
2995 KeywordStartPos
= NULL
;
2999 // 11. Set value to driver.
3001 Status
= mPrivate
.ConfigRouting
.RouteConfig(
3002 &mPrivate
.ConfigRouting
,
3003 (EFI_STRING
) MultiConfigResp
,
3006 if (EFI_ERROR (Status
)) {
3007 Status
= EFI_DEVICE_ERROR
;
3011 *ProgressErr
= KEYWORD_HANDLER_NO_ERROR
;
3014 if (KeywordStartPos
!= NULL
) {
3015 *Progress
= KeywordString
+ (KeywordStartPos
- TempString
);
3017 *Progress
= KeywordString
+ (StringPtr
- TempString
);
3020 ASSERT (TempString
!= NULL
);
3021 FreePool (TempString
);
3022 if (NameSpace
!= NULL
) {
3023 FreePool (NameSpace
);
3025 if (DevicePath
!= NULL
) {
3026 FreePool (DevicePath
);
3028 if (KeywordData
!= NULL
) {
3029 FreePool (KeywordData
);
3031 if (ValueElement
!= NULL
) {
3032 FreePool (ValueElement
);
3034 if (ConfigResp
!= NULL
) {
3035 FreePool (ConfigResp
);
3037 if (MultiConfigResp
!= NULL
&& MultiConfigResp
!= ConfigResp
) {
3038 FreePool (MultiConfigResp
);
3046 This function accepts a <MultiKeywordRequest> formatted string, finds the underlying
3047 keyword owners, creates a <MultiConfigRequest> string from it and forwards it to the
3048 EFI_HII_ROUTING_PROTOCOL.ExtractConfig function.
3050 If there is an issue in resolving the contents of the KeywordString, then the function
3051 returns an EFI_INVALID_PARAMETER and also set the Progress and ProgressErr with the
3052 appropriate information about where the issue occurred and additional data about the
3053 nature of the issue.
3055 In the case when KeywordString is NULL, or contains multiple keywords, or when
3056 EFI_NOT_FOUND is generated while processing the keyword elements, the Results string
3057 contains values returned for all keywords processed prior to the keyword generating the
3058 error but no values for the keyword with error or any following keywords.
3061 @param This Pointer to the EFI_KEYWORD_HANDLER _PROTOCOL instance.
3063 @param NameSpaceId A null-terminated string containing the platform configuration
3064 language to search through in the system. If a NULL is passed
3065 in, then it is assumed that any platform configuration language
3066 with the prefix of "x-UEFI-" are searched.
3068 @param KeywordString A null-terminated string in <MultiKeywordRequest> format. If a
3069 NULL is passed in the KeywordString field, all of the known
3070 keywords in the system for the NameSpaceId specified are
3071 returned in the Results field.
3073 @param Progress On return, points to a character in the KeywordString. Points
3074 to the string's NULL terminator if the request was successful.
3075 Points to the most recent '&' before the first failing name / value
3076 pair (or the beginning of the string if the failure is in the first
3077 name / value pair) if the request was not successful.
3079 @param ProgressErr If during the processing of the KeywordString there was a
3080 failure, this parameter gives additional information about the
3081 possible source of the problem. See the definitions in SetData()
3082 for valid value definitions.
3084 @param Results A null-terminated string in <MultiKeywordResp> format is returned
3085 which has all the values filled in for the keywords in the
3086 KeywordString. This is a callee-allocated field, and must be freed
3087 by the caller after being used.
3089 @retval EFI_SUCCESS The specified action was completed successfully.
3091 @retval EFI_INVALID_PARAMETER One or more of the following are TRUE:
3092 1.Progress, ProgressErr, or Results is NULL.
3093 2.Parsing of the KeywordString resulted in an error. See
3094 Progress and ProgressErr for more data.
3097 @retval EFI_NOT_FOUND An element of the KeywordString was not found. See
3098 ProgressErr for more data.
3100 @retval EFI_NOT_FOUND The NamespaceId specified was not found. See ProgressErr
3103 @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated. See
3104 ProgressErr for more data.
3106 @retval EFI_ACCESS_DENIED The action violated system policy. See ProgressErr for
3109 @retval EFI_DEVICE_ERROR An unexpected system error occurred. See ProgressErr
3115 EfiConfigKeywordHandlerGetData (
3116 IN EFI_CONFIG_KEYWORD_HANDLER_PROTOCOL
*This
,
3117 IN CONST EFI_STRING NameSpaceId
, OPTIONAL
3118 IN CONST EFI_STRING KeywordString
, OPTIONAL
3119 OUT EFI_STRING
*Progress
,
3120 OUT UINT32
*ProgressErr
,
3121 OUT EFI_STRING
*Results
3126 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
3127 HII_DATABASE_RECORD
*DataBaseRecord
;
3129 CHAR16
*NextStringPtr
;
3130 CHAR16
*KeywordData
;
3131 EFI_STRING_ID KeywordStringId
;
3133 CHAR16
*ConfigRequest
;
3134 CHAR16
*ValueElement
;
3137 CHAR16
*KeywordResp
;
3138 CHAR16
*MultiKeywordResp
;
3141 if (This
== NULL
|| Progress
== NULL
|| ProgressErr
== NULL
|| Results
== NULL
) {
3142 return EFI_INVALID_PARAMETER
;
3145 *ProgressErr
= KEYWORD_HANDLER_UNDEFINED_PROCESSING_ERROR
;
3146 Status
= EFI_SUCCESS
;
3150 ConfigRequest
= NULL
;
3151 StringPtr
= KeywordString
;
3153 MultiKeywordResp
= NULL
;
3154 KeywordStringId
= 0;
3158 // Use temp string to avoid changing input string buffer.
3160 if (NameSpaceId
!= NULL
) {
3161 TempString
= AllocateCopyPool (StrSize (NameSpaceId
), NameSpaceId
);
3162 ASSERT (TempString
!= NULL
);
3165 // 1. Get NameSpace from NameSpaceId keyword.
3167 Status
= ExtractNameSpace (TempString
, &NameSpace
, NULL
);
3168 if (TempString
!= NULL
) {
3169 FreePool (TempString
);
3172 if (EFI_ERROR (Status
)) {
3173 *ProgressErr
= KEYWORD_HANDLER_MALFORMED_STRING
;
3177 // 1.1 Check whether the input namespace is valid.
3179 if (NameSpace
!= NULL
){
3180 if (AsciiStrnCmp(NameSpace
, UEFI_CONFIG_LANG
, AsciiStrLen (UEFI_CONFIG_LANG
)) != 0) {
3181 *ProgressErr
= KEYWORD_HANDLER_MALFORMED_STRING
;
3182 return EFI_INVALID_PARAMETER
;
3186 if (KeywordString
!= NULL
) {
3188 // Use temp string to avoid changing input string buffer.
3190 TempString
= AllocateCopyPool (StrSize (KeywordString
), KeywordString
);
3191 ASSERT (TempString
!= NULL
);
3192 StringPtr
= TempString
;
3194 while (*StringPtr
!= L
'\0') {
3196 // 2. Get possible Device Path info from KeywordString.
3198 Status
= ExtractDevicePath (StringPtr
, (UINT8
**)&DevicePath
, &NextStringPtr
);
3199 if (EFI_ERROR (Status
)) {
3200 *ProgressErr
= KEYWORD_HANDLER_MALFORMED_STRING
;
3203 StringPtr
= NextStringPtr
;
3207 // 3. Process Keyword section from the input keywordRequest string.
3209 // 3.1 Extract keyword from the KeywordRequest string.
3211 Status
= ExtractKeyword(StringPtr
, &KeywordData
, &NextStringPtr
);
3212 if (EFI_ERROR (Status
)) {
3214 // Can't find Keyword base on the input device path info.
3216 *ProgressErr
= KEYWORD_HANDLER_MALFORMED_STRING
;
3217 Status
= EFI_INVALID_PARAMETER
;
3222 // 3.2 Get EFI_STRING_ID for the input keyword.
3224 Status
= GetStringIdFromDatabase (&DevicePath
, &NameSpace
, KeywordData
, &RetVal
, &KeywordStringId
, &DataBaseRecord
);
3225 if (EFI_ERROR (Status
)) {
3226 *ProgressErr
= RetVal
;
3231 // 3.3 Construct the ConfigRequest string.
3233 Status
= ExtractConfigRequest (DataBaseRecord
, KeywordStringId
, &OpCode
, &ConfigRequest
);
3234 if (EFI_ERROR (Status
)) {
3239 // 3.4 Extract Value for the input keyword.
3241 Status
= ExtractValueFromDriver(ConfigRequest
, &ValueElement
);
3242 if (EFI_ERROR (Status
)) {
3243 if (Status
!= EFI_OUT_OF_RESOURCES
) {
3244 Status
= EFI_DEVICE_ERROR
;
3248 StringPtr
= NextStringPtr
;
3251 // 4. Process the possible filter section.
3253 RetVal
= ValidateFilter (OpCode
, StringPtr
, &NextStringPtr
, &ReadOnly
);
3254 if (RetVal
!= KEYWORD_HANDLER_NO_ERROR
) {
3255 *ProgressErr
= RetVal
;
3256 Status
= EFI_INVALID_PARAMETER
;
3259 StringPtr
= NextStringPtr
;
3263 // 5. Generate KeywordResp string.
3265 Status
= GenerateKeywordResp(NameSpace
, DevicePath
, KeywordData
, ValueElement
, ReadOnly
, &KeywordResp
);
3266 if (Status
!= EFI_SUCCESS
) {
3271 // 6. Merge to the MultiKeywordResp string.
3273 Status
= MergeToMultiKeywordResp(&MultiKeywordResp
, &KeywordResp
);
3274 if (EFI_ERROR (Status
)) {
3279 // 7. Update return value.
3281 *Results
= MultiKeywordResp
;
3284 // 8. Clean the temp buffer.
3286 FreePool (DevicePath
);
3287 FreePool (KeywordData
);
3288 FreePool (ValueElement
);
3289 FreePool (ConfigRequest
);
3292 ValueElement
= NULL
;
3293 ConfigRequest
= NULL
;
3294 if (KeywordResp
!= NULL
) {
3295 FreePool (KeywordResp
);
3301 // Enumerate all keyword in the system.
3303 Status
= EnumerateAllKeywords(NameSpace
, &MultiKeywordResp
, ProgressErr
);
3304 if (EFI_ERROR (Status
)) {
3307 *Results
= MultiKeywordResp
;
3310 *ProgressErr
= KEYWORD_HANDLER_NO_ERROR
;
3313 *Progress
= KeywordString
+ (StringPtr
- TempString
);
3315 if (TempString
!= NULL
) {
3316 FreePool (TempString
);
3318 if (NameSpace
!= NULL
) {
3319 FreePool (NameSpace
);
3321 if (DevicePath
!= NULL
) {
3322 FreePool (DevicePath
);
3324 if (KeywordData
!= NULL
) {
3325 FreePool (KeywordData
);