2 Implementation of interfaces function for EFI_CONFIG_KEYWORD_HANDLER_PROTOCOL.
4 Copyright (c) 2015 - 2018, 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 necessary 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
183 ASSERT (NameSpace
!= NULL
);
188 // Input NameSpaceId == NULL
190 if (String
== NULL
) {
192 if (NextString
!= NULL
) {
199 // Skip '&' if exist.
201 if (*String
== L
'&') {
205 if (StrnCmp (String
, L
"NAMESPACE=", StrLen (L
"NAMESPACE=")) != 0) {
206 return EFI_INVALID_PARAMETER
;
208 String
+= StrLen (L
"NAMESPACE=");
210 TmpPtr
= StrStr (String
, L
"&");
211 if (TmpPtr
!= NULL
) {
214 if (NextString
!= NULL
) {
215 *NextString
= String
+ StrLen (String
);
219 // Input NameSpace is unicode string. The language in String package is ascii string.
220 // Here will convert the unicode string to ascii and save it.
222 NameSpaceSize
= StrLen (String
) + 1;
223 *NameSpace
= AllocatePool (NameSpaceSize
);
224 if (*NameSpace
== NULL
) {
225 return EFI_OUT_OF_RESOURCES
;
227 UnicodeStrToAsciiStrS (String
, *NameSpace
, NameSpaceSize
);
229 if (TmpPtr
!= NULL
) {
237 Get Keyword from the input KeywordRequest string.
239 This is a internal function.
241 @param String KeywordRequestformat string.
242 @param Keyword return the extract keyword string.
243 @param NextString return the next string follow this keyword section.
245 @retval EFI_SUCCESS Success to get the keyword string.
246 @retval EFI_INVALID_PARAMETER Parse the input string return error.
251 IN EFI_STRING String
,
252 OUT EFI_STRING
*Keyword
,
253 OUT EFI_STRING
*NextString
258 ASSERT ((Keyword
!= NULL
) && (NextString
!= NULL
));
263 // KeywordRequest == NULL case.
265 if (String
== NULL
) {
272 // Skip '&' if exist.
274 if (*String
== L
'&') {
278 if (StrnCmp (String
, L
"KEYWORD=", StrLen (L
"KEYWORD=")) != 0) {
279 return EFI_INVALID_PARAMETER
;
282 String
+= StrLen (L
"KEYWORD=");
284 TmpPtr
= StrStr (String
, L
"&");
285 if (TmpPtr
!= NULL
) {
288 *NextString
= String
+ StrLen (String
);
290 *Keyword
= AllocateCopyPool (StrSize (String
), String
);
291 if (*Keyword
== NULL
) {
292 return EFI_OUT_OF_RESOURCES
;
295 if (TmpPtr
!= NULL
) {
303 Get value from the input KeywordRequest string.
305 This is a internal function.
307 @param String KeywordRequestformat string.
308 @param Value return the extract value string.
309 @param NextString return the next string follow this keyword section.
311 @retval EFI_SUCCESS Success to get the keyword string.
312 @retval EFI_INVALID_PARAMETER Parse the input string return error.
317 IN EFI_STRING String
,
318 OUT EFI_STRING
*Value
,
319 OUT EFI_STRING
*NextString
324 ASSERT ((Value
!= NULL
) && (NextString
!= NULL
) && (String
!= NULL
));
327 // Skip '&' if exist.
329 if (*String
== L
'&') {
333 if (StrnCmp (String
, L
"VALUE=", StrLen (L
"VALUE=")) != 0) {
334 return EFI_INVALID_PARAMETER
;
337 String
+= StrLen (L
"VALUE=");
339 TmpPtr
= StrStr (String
, L
"&");
340 if (TmpPtr
!= NULL
) {
343 *NextString
= String
+ StrLen (String
);
345 *Value
= AllocateCopyPool (StrSize (String
), String
);
346 if (*Value
== NULL
) {
347 return EFI_OUT_OF_RESOURCES
;
350 if (TmpPtr
!= NULL
) {
358 Get filter from the input KeywordRequest string.
360 This is a internal function.
362 @param String KeywordRequestformat string.
363 @param FilterFlags return the filter condition.
364 @param NextString return the next string follow this keyword section.
366 @retval EFI_SUCCESS Success to get the keyword string.
367 @retval EFI_INVALID_PARAMETER Parse the input string return error.
372 IN EFI_STRING String
,
373 OUT UINT8
*FilterFlags
,
374 OUT EFI_STRING
*NextString
381 ASSERT ((FilterFlags
!= NULL
) && (NextString
!= NULL
));
384 // String end, no filter section.
386 if (String
== NULL
) {
395 // Skip '&' if exist.
397 if (*String
== L
'&') {
401 if (StrnCmp (String
, L
"ReadOnly", StrLen (L
"ReadOnly")) == 0) {
403 // Find ReadOnly filter.
405 *FilterFlags
|= EFI_KEYWORD_FILTER_READONY
;
406 String
+= StrLen (L
"ReadOnly");
407 } else if (StrnCmp (String
, L
"ReadWrite", StrLen (L
"ReadWrite")) == 0) {
409 // Find ReadWrite filter.
411 *FilterFlags
|= EFI_KEYWORD_FILTER_REAWRITE
;
412 String
+= StrLen (L
"ReadWrite");
413 } else if (StrnCmp (String
, L
"Buffer", StrLen (L
"Buffer")) == 0) {
415 // Find Buffer Filter.
417 *FilterFlags
|= EFI_KEYWORD_FILTER_BUFFER
;
418 String
+= StrLen (L
"Buffer");
419 } else if (StrnCmp (String
, L
"Numeric", StrLen (L
"Numeric")) == 0) {
421 // Find Numeric Filter
423 String
+= StrLen (L
"Numeric");
424 if (*String
!= L
':') {
425 *FilterFlags
|= EFI_KEYWORD_FILTER_NUMERIC
;
430 *FilterFlags
|= EFI_KEYWORD_FILTER_NUMERIC_1
;
433 *FilterFlags
|= EFI_KEYWORD_FILTER_NUMERIC_2
;
436 *FilterFlags
|= EFI_KEYWORD_FILTER_NUMERIC_4
;
439 *FilterFlags
|= EFI_KEYWORD_FILTER_NUMERIC_8
;
449 // Check whether other filter item defined by Platform.
451 if ((StrnCmp (String
, L
"&PATH", StrLen (L
"&PATH")) == 0) ||
452 (StrnCmp (String
, L
"&KEYWORD", StrLen (L
"&KEYWORD")) == 0)) {
454 // New KeywordRequest start, no platform defined filter.
458 // Platform defined filter rule.
459 // Just skip platform defined filter rule, return success.
461 PathPtr
= StrStr(String
, L
"&PATH");
462 KeywordPtr
= StrStr(String
, L
"&KEYWORD");
463 if (PathPtr
!= NULL
&& KeywordPtr
!= NULL
) {
465 // If both sections exist, return the first follow string.
467 String
= KeywordPtr
> PathPtr
? PathPtr
: KeywordPtr
;
468 } else if (PathPtr
!= NULL
) {
470 // Should not exist PathPtr != NULL && KeywordPtr == NULL case.
473 } else if (KeywordPtr
!= NULL
) {
475 // Just to the next keyword section.
480 // Only has platform defined filter section, just skip it.
482 String
+= StrLen (String
);
488 *NextString
= String
;
494 Extract Readonly flag from opcode.
496 This is a internal function.
498 @param OpCodeData Input opcode for this question.
500 @retval TRUE This question is readonly.
501 @retval FALSE This question is not readonly.
505 ExtractReadOnlyFromOpCode (
509 EFI_IFR_QUESTION_HEADER
*QuestionHdr
;
511 ASSERT (OpCodeData
!= NULL
);
513 QuestionHdr
= (EFI_IFR_QUESTION_HEADER
*) (OpCodeData
+ sizeof (EFI_IFR_OP_HEADER
));
515 return (QuestionHdr
->Flags
& EFI_IFR_FLAG_READ_ONLY
) != 0;
519 Create a circuit to check the filter section.
521 This is a internal function.
523 @param OpCodeData The question binary ifr data.
524 @param KeywordRequest KeywordRequestformat string.
525 @param NextString return the next string follow this keyword section.
526 @param ReadOnly Return whether this question is read only.
528 @retval KEYWORD_HANDLER_NO_ERROR Success validate.
529 @retval KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED Validate fail.
534 IN UINT8
*OpCodeData
,
535 IN CHAR16
*KeywordRequest
,
536 OUT CHAR16
**NextString
,
537 OUT BOOLEAN
*ReadOnly
543 EFI_IFR_QUESTION_HEADER
*QuestionHdr
;
544 EFI_IFR_OP_HEADER
*OpCodeHdr
;
548 RetVal
= KEYWORD_HANDLER_NO_ERROR
;
549 StringPtr
= KeywordRequest
;
551 OpCodeHdr
= (EFI_IFR_OP_HEADER
*) OpCodeData
;
552 QuestionHdr
= (EFI_IFR_QUESTION_HEADER
*) (OpCodeData
+ sizeof (EFI_IFR_OP_HEADER
));
553 if (OpCodeHdr
->OpCode
== EFI_IFR_ONE_OF_OP
|| OpCodeHdr
->OpCode
== EFI_IFR_NUMERIC_OP
) {
554 Flags
= *(OpCodeData
+ sizeof (EFI_IFR_OP_HEADER
) + sizeof (EFI_IFR_QUESTION_HEADER
));
560 // Get ReadOnly flag from Question.
562 *ReadOnly
= ExtractReadOnlyFromOpCode(OpCodeData
);
564 while (ExtractFilter (StringPtr
, &FilterFlags
, &NextFilter
)) {
565 switch (FilterFlags
) {
566 case EFI_KEYWORD_FILTER_READONY
:
567 if ((QuestionHdr
->Flags
& EFI_IFR_FLAG_READ_ONLY
) == 0) {
568 RetVal
= KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED
;
573 case EFI_KEYWORD_FILTER_REAWRITE
:
574 if ((QuestionHdr
->Flags
& EFI_IFR_FLAG_READ_ONLY
) != 0) {
575 RetVal
= KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED
;
580 case EFI_KEYWORD_FILTER_BUFFER
:
582 // Only these three opcode use numeric value type.
584 if (OpCodeHdr
->OpCode
== EFI_IFR_ONE_OF_OP
|| OpCodeHdr
->OpCode
== EFI_IFR_NUMERIC_OP
|| OpCodeHdr
->OpCode
== EFI_IFR_CHECKBOX_OP
) {
585 RetVal
= KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED
;
590 case EFI_KEYWORD_FILTER_NUMERIC
:
591 if (OpCodeHdr
->OpCode
!= EFI_IFR_ONE_OF_OP
&& OpCodeHdr
->OpCode
!= EFI_IFR_NUMERIC_OP
&& OpCodeHdr
->OpCode
!= EFI_IFR_CHECKBOX_OP
) {
592 RetVal
= KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED
;
597 case EFI_KEYWORD_FILTER_NUMERIC_1
:
598 case EFI_KEYWORD_FILTER_NUMERIC_2
:
599 case EFI_KEYWORD_FILTER_NUMERIC_4
:
600 case EFI_KEYWORD_FILTER_NUMERIC_8
:
601 if (OpCodeHdr
->OpCode
!= EFI_IFR_ONE_OF_OP
&& OpCodeHdr
->OpCode
!= EFI_IFR_NUMERIC_OP
&& OpCodeHdr
->OpCode
!= EFI_IFR_CHECKBOX_OP
) {
602 RetVal
= KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED
;
607 // For numeric and oneof, it has flags field to specify the detail numeric type.
609 if (OpCodeHdr
->OpCode
== EFI_IFR_ONE_OF_OP
|| OpCodeHdr
->OpCode
== EFI_IFR_NUMERIC_OP
) {
610 switch (Flags
& EFI_IFR_NUMERIC_SIZE
) {
611 case EFI_IFR_NUMERIC_SIZE_1
:
612 if (FilterFlags
!= EFI_KEYWORD_FILTER_NUMERIC_1
) {
613 RetVal
= KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED
;
618 case EFI_IFR_NUMERIC_SIZE_2
:
619 if (FilterFlags
!= EFI_KEYWORD_FILTER_NUMERIC_2
) {
620 RetVal
= KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED
;
625 case EFI_IFR_NUMERIC_SIZE_4
:
626 if (FilterFlags
!= EFI_KEYWORD_FILTER_NUMERIC_4
) {
627 RetVal
= KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED
;
632 case EFI_IFR_NUMERIC_SIZE_8
:
633 if (FilterFlags
!= EFI_KEYWORD_FILTER_NUMERIC_8
) {
634 RetVal
= KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED
;
652 // Jump to the next filter.
654 StringPtr
= NextFilter
;
659 // The current filter which is processing.
661 *NextString
= StringPtr
;
667 Get HII_DATABASE_RECORD from the input device path info.
669 This is a internal function.
671 @param DevicePath UEFI device path protocol.
673 @retval Internal data base record.
676 HII_DATABASE_RECORD
*
677 GetRecordFromDevicePath (
678 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
682 UINT8
*DevicePathPkg
;
683 UINT8
*CurrentDevicePath
;
684 UINTN DevicePathSize
;
685 HII_DATABASE_RECORD
*TempDatabase
;
687 ASSERT (DevicePath
!= NULL
);
689 for (Link
= mPrivate
.DatabaseList
.ForwardLink
; Link
!= &mPrivate
.DatabaseList
; Link
= Link
->ForwardLink
) {
690 TempDatabase
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
691 DevicePathPkg
= TempDatabase
->PackageList
->DevicePathPkg
;
692 if (DevicePathPkg
!= NULL
) {
693 CurrentDevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
694 DevicePathSize
= GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) CurrentDevicePath
);
695 if ((CompareMem (DevicePath
, CurrentDevicePath
, DevicePathSize
) == 0)) {
705 Calculate the size of StringSrc and output it. Also copy string text from src
708 This is a internal function.
710 @param StringSrc Points to current null-terminated string.
711 @param BufferSize Length of the buffer.
712 @param StringDest Buffer to store the string text.
714 @retval EFI_SUCCESS The string text was outputted successfully.
715 @retval EFI_OUT_OF_RESOURCES Out of resource.
719 GetUnicodeStringTextAndSize (
721 OUT UINTN
*BufferSize
,
722 OUT EFI_STRING
*StringDest
728 ASSERT (StringSrc
!= NULL
&& BufferSize
!= NULL
&& StringDest
!= NULL
);
730 StringSize
= sizeof (CHAR16
);
731 StringPtr
= StringSrc
;
732 while (ReadUnaligned16 ((UINT16
*) StringPtr
) != 0) {
733 StringSize
+= sizeof (CHAR16
);
734 StringPtr
+= sizeof (CHAR16
);
737 *StringDest
= AllocatePool (StringSize
);
738 if (*StringDest
== NULL
) {
739 return EFI_OUT_OF_RESOURCES
;
742 CopyMem (*StringDest
, StringSrc
, StringSize
);
744 *BufferSize
= StringSize
;
749 Find the string id for the input keyword.
751 @param StringPackage Hii string package instance.
752 @param KeywordValue Input keyword value.
753 @param StringId The string's id, which is unique within PackageList.
756 @retval EFI_SUCCESS The string text and font is retrieved
758 @retval EFI_NOT_FOUND The specified text or font info can not be found
760 @retval EFI_OUT_OF_RESOURCES The system is out of resources to accomplish the
764 GetStringIdFromString (
765 IN HII_STRING_PACKAGE_INSTANCE
*StringPackage
,
766 IN CHAR16
*KeywordValue
,
767 OUT EFI_STRING_ID
*StringId
771 EFI_STRING_ID CurrentStringId
;
774 UINT8
*StringTextPtr
;
779 EFI_HII_SIBT_EXT2_BLOCK Ext2
;
783 CHAR8
*AsciiKeywordValue
;
784 UINTN KeywordValueSize
;
787 ASSERT (StringPackage
!= NULL
&& KeywordValue
!= NULL
&& StringId
!= NULL
);
788 ASSERT (StringPackage
->Signature
== HII_STRING_PACKAGE_SIGNATURE
);
791 Status
= EFI_SUCCESS
;
793 BlockHdr
= StringPackage
->StringBlock
;
798 // Make a ascii keyword value for later use.
800 KeywordValueSize
= StrLen (KeywordValue
) + 1;
801 AsciiKeywordValue
= AllocatePool (KeywordValueSize
);
802 if (AsciiKeywordValue
== NULL
) {
803 return EFI_OUT_OF_RESOURCES
;
805 UnicodeStrToAsciiStrS (KeywordValue
, AsciiKeywordValue
, KeywordValueSize
);
807 while (*BlockHdr
!= EFI_HII_SIBT_END
) {
809 case EFI_HII_SIBT_STRING_SCSU
:
810 Offset
= sizeof (EFI_HII_STRING_BLOCK
);
811 StringTextPtr
= BlockHdr
+ Offset
;
812 BlockSize
+= Offset
+ AsciiStrSize ((CHAR8
*) StringTextPtr
);
813 if (AsciiStrCmp(AsciiKeywordValue
, (CHAR8
*) StringTextPtr
) == 0) {
814 *StringId
= CurrentStringId
;
820 case EFI_HII_SIBT_STRING_SCSU_FONT
:
821 Offset
= sizeof (EFI_HII_SIBT_STRING_SCSU_FONT_BLOCK
) - sizeof (UINT8
);
822 StringTextPtr
= BlockHdr
+ Offset
;
823 if (AsciiStrCmp(AsciiKeywordValue
, (CHAR8
*) StringTextPtr
) == 0) {
824 *StringId
= CurrentStringId
;
827 BlockSize
+= Offset
+ AsciiStrSize ((CHAR8
*) StringTextPtr
);
831 case EFI_HII_SIBT_STRINGS_SCSU
:
832 CopyMem (&StringCount
, BlockHdr
+ sizeof (EFI_HII_STRING_BLOCK
), sizeof (UINT16
));
833 StringTextPtr
= (UINT8
*)((UINTN
)BlockHdr
+ sizeof (EFI_HII_SIBT_STRINGS_SCSU_BLOCK
) - sizeof (UINT8
));
834 BlockSize
+= StringTextPtr
- BlockHdr
;
836 for (Index
= 0; Index
< StringCount
; Index
++) {
837 BlockSize
+= AsciiStrSize ((CHAR8
*) StringTextPtr
);
838 if (AsciiStrCmp(AsciiKeywordValue
, (CHAR8
*) StringTextPtr
) == 0) {
839 *StringId
= CurrentStringId
;
842 StringTextPtr
= StringTextPtr
+ AsciiStrSize ((CHAR8
*) StringTextPtr
);
847 case EFI_HII_SIBT_STRINGS_SCSU_FONT
:
850 (UINT8
*)((UINTN
)BlockHdr
+ sizeof (EFI_HII_STRING_BLOCK
) + sizeof (UINT8
)),
853 StringTextPtr
= (UINT8
*)((UINTN
)BlockHdr
+ sizeof (EFI_HII_SIBT_STRINGS_SCSU_FONT_BLOCK
) - sizeof (UINT8
));
854 BlockSize
+= StringTextPtr
- BlockHdr
;
856 for (Index
= 0; Index
< StringCount
; Index
++) {
857 BlockSize
+= AsciiStrSize ((CHAR8
*) StringTextPtr
);
858 if (AsciiStrCmp(AsciiKeywordValue
, (CHAR8
*) StringTextPtr
) == 0) {
859 *StringId
= CurrentStringId
;
862 StringTextPtr
= StringTextPtr
+ AsciiStrSize ((CHAR8
*) StringTextPtr
);
867 case EFI_HII_SIBT_STRING_UCS2
:
868 Offset
= sizeof (EFI_HII_STRING_BLOCK
);
869 StringTextPtr
= BlockHdr
+ Offset
;
871 // Use StringSize to store the size of the specified string, including the NULL
874 Status
= GetUnicodeStringTextAndSize (StringTextPtr
, &StringSize
, &String
);
875 if (EFI_ERROR (Status
)) {
878 ASSERT (String
!= NULL
);
879 if (StrCmp(KeywordValue
, String
) == 0) {
880 *StringId
= CurrentStringId
;
883 BlockSize
+= Offset
+ StringSize
;
887 case EFI_HII_SIBT_STRING_UCS2_FONT
:
888 Offset
= sizeof (EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK
) - sizeof (CHAR16
);
889 StringTextPtr
= BlockHdr
+ Offset
;
891 // Use StringSize to store the size of the specified string, including the NULL
894 Status
= GetUnicodeStringTextAndSize (StringTextPtr
, &StringSize
, &String
);
895 if (EFI_ERROR (Status
)) {
898 ASSERT (String
!= NULL
);
899 if (StrCmp(KeywordValue
, String
) == 0) {
900 *StringId
= CurrentStringId
;
903 BlockSize
+= Offset
+ StringSize
;
907 case EFI_HII_SIBT_STRINGS_UCS2
:
908 Offset
= sizeof (EFI_HII_SIBT_STRINGS_UCS2_BLOCK
) - sizeof (CHAR16
);
909 StringTextPtr
= BlockHdr
+ Offset
;
911 CopyMem (&StringCount
, BlockHdr
+ sizeof (EFI_HII_STRING_BLOCK
), sizeof (UINT16
));
912 for (Index
= 0; Index
< StringCount
; Index
++) {
913 Status
= GetUnicodeStringTextAndSize (StringTextPtr
, &StringSize
, &String
);
914 if (EFI_ERROR (Status
)) {
917 ASSERT (String
!= NULL
);
918 BlockSize
+= StringSize
;
919 if (StrCmp(KeywordValue
, String
) == 0) {
920 *StringId
= CurrentStringId
;
923 StringTextPtr
= StringTextPtr
+ StringSize
;
928 case EFI_HII_SIBT_STRINGS_UCS2_FONT
:
929 Offset
= sizeof (EFI_HII_SIBT_STRINGS_UCS2_FONT_BLOCK
) - sizeof (CHAR16
);
930 StringTextPtr
= BlockHdr
+ Offset
;
934 (UINT8
*)((UINTN
)BlockHdr
+ sizeof (EFI_HII_STRING_BLOCK
) + sizeof (UINT8
)),
937 for (Index
= 0; Index
< StringCount
; Index
++) {
938 Status
= GetUnicodeStringTextAndSize (StringTextPtr
, &StringSize
, &String
);
939 if (EFI_ERROR (Status
)) {
942 ASSERT (String
!= NULL
);
943 BlockSize
+= StringSize
;
944 if (StrCmp(KeywordValue
, String
) == 0) {
945 *StringId
= CurrentStringId
;
948 StringTextPtr
= StringTextPtr
+ StringSize
;
953 case EFI_HII_SIBT_DUPLICATE
:
954 BlockSize
+= sizeof (EFI_HII_SIBT_DUPLICATE_BLOCK
);
958 case EFI_HII_SIBT_SKIP1
:
959 SkipCount
= (UINT16
) (*(UINT8
*)((UINTN
)BlockHdr
+ sizeof (EFI_HII_STRING_BLOCK
)));
960 CurrentStringId
= (UINT16
) (CurrentStringId
+ SkipCount
);
961 BlockSize
+= sizeof (EFI_HII_SIBT_SKIP1_BLOCK
);
964 case EFI_HII_SIBT_SKIP2
:
965 CopyMem (&SkipCount
, BlockHdr
+ sizeof (EFI_HII_STRING_BLOCK
), sizeof (UINT16
));
966 CurrentStringId
= (UINT16
) (CurrentStringId
+ SkipCount
);
967 BlockSize
+= sizeof (EFI_HII_SIBT_SKIP2_BLOCK
);
970 case EFI_HII_SIBT_EXT1
:
973 (UINT8
*)((UINTN
)BlockHdr
+ sizeof (EFI_HII_STRING_BLOCK
) + sizeof (UINT8
)),
976 BlockSize
+= Length8
;
979 case EFI_HII_SIBT_EXT2
:
980 CopyMem (&Ext2
, BlockHdr
, sizeof (EFI_HII_SIBT_EXT2_BLOCK
));
981 BlockSize
+= Ext2
.Length
;
984 case EFI_HII_SIBT_EXT4
:
987 (UINT8
*)((UINTN
)BlockHdr
+ sizeof (EFI_HII_STRING_BLOCK
) + sizeof (UINT8
)),
991 BlockSize
+= Length32
;
998 if (String
!= NULL
) {
1003 BlockHdr
= StringPackage
->StringBlock
+ BlockSize
;
1006 Status
= EFI_NOT_FOUND
;
1009 if (AsciiKeywordValue
!= NULL
) {
1010 FreePool (AsciiKeywordValue
);
1012 if (String
!= NULL
) {
1019 Find the next valid string id for the input string id.
1021 @param StringPackage Hii string package instance.
1022 @param StringId The current string id which is already got.
1023 1 means just begin to get the string id.
1024 @param KeywordValue Return the string for the next string id.
1027 @retval EFI_STRING_ID Not 0 means a valid stringid found.
1028 0 means not found a valid string id.
1032 IN HII_STRING_PACKAGE_INSTANCE
*StringPackage
,
1033 IN EFI_STRING_ID StringId
,
1034 OUT EFI_STRING
*KeywordValue
1038 EFI_STRING_ID CurrentStringId
;
1041 UINT8
*StringTextPtr
;
1046 EFI_HII_SIBT_EXT2_BLOCK Ext2
;
1052 ASSERT (StringPackage
!= NULL
);
1053 ASSERT (StringPackage
->Signature
== HII_STRING_PACKAGE_SIGNATURE
);
1055 CurrentStringId
= 1;
1060 // Parse the string blocks to get the string text and font.
1062 BlockHdr
= StringPackage
->StringBlock
;
1065 while (*BlockHdr
!= EFI_HII_SIBT_END
) {
1066 switch (*BlockHdr
) {
1067 case EFI_HII_SIBT_STRING_SCSU
:
1068 Offset
= sizeof (EFI_HII_STRING_BLOCK
);
1069 StringTextPtr
= BlockHdr
+ Offset
;
1072 StringSize
= AsciiStrSize ((CHAR8
*) StringTextPtr
);
1073 *KeywordValue
= AllocatePool (StringSize
* sizeof (CHAR16
));
1074 if (*KeywordValue
== NULL
) {
1077 AsciiStrToUnicodeStrS ((CHAR8
*) StringTextPtr
, *KeywordValue
, StringSize
);
1078 return CurrentStringId
;
1079 } else if (CurrentStringId
== StringId
) {
1083 BlockSize
+= Offset
+ AsciiStrSize ((CHAR8
*) StringTextPtr
);
1087 case EFI_HII_SIBT_STRING_SCSU_FONT
:
1088 Offset
= sizeof (EFI_HII_SIBT_STRING_SCSU_FONT_BLOCK
) - sizeof (UINT8
);
1089 StringTextPtr
= BlockHdr
+ Offset
;
1092 StringSize
= AsciiStrSize ((CHAR8
*) StringTextPtr
);
1093 *KeywordValue
= AllocatePool (StringSize
* sizeof (CHAR16
));
1094 if (*KeywordValue
== NULL
) {
1097 AsciiStrToUnicodeStrS ((CHAR8
*) StringTextPtr
, *KeywordValue
, StringSize
);
1098 return CurrentStringId
;
1099 } else if (CurrentStringId
== StringId
) {
1103 BlockSize
+= Offset
+ AsciiStrSize ((CHAR8
*) StringTextPtr
);
1107 case EFI_HII_SIBT_STRINGS_SCSU
:
1108 CopyMem (&StringCount
, BlockHdr
+ sizeof (EFI_HII_STRING_BLOCK
), sizeof (UINT16
));
1109 StringTextPtr
= (UINT8
*)((UINTN
)BlockHdr
+ sizeof (EFI_HII_SIBT_STRINGS_SCSU_BLOCK
) - sizeof (UINT8
));
1110 BlockSize
+= StringTextPtr
- BlockHdr
;
1112 for (Index
= 0; Index
< StringCount
; Index
++) {
1114 StringSize
= AsciiStrSize ((CHAR8
*) StringTextPtr
);
1115 *KeywordValue
= AllocatePool (StringSize
* sizeof (CHAR16
));
1116 if (*KeywordValue
== NULL
) {
1119 AsciiStrToUnicodeStrS ((CHAR8
*) StringTextPtr
, *KeywordValue
, StringSize
);
1120 return CurrentStringId
;
1121 } else if (CurrentStringId
== StringId
) {
1125 BlockSize
+= AsciiStrSize ((CHAR8
*) StringTextPtr
);
1126 StringTextPtr
= StringTextPtr
+ AsciiStrSize ((CHAR8
*) StringTextPtr
);
1131 case EFI_HII_SIBT_STRINGS_SCSU_FONT
:
1134 (UINT8
*)((UINTN
)BlockHdr
+ sizeof (EFI_HII_STRING_BLOCK
) + sizeof (UINT8
)),
1137 StringTextPtr
= (UINT8
*)((UINTN
)BlockHdr
+ sizeof (EFI_HII_SIBT_STRINGS_SCSU_FONT_BLOCK
) - sizeof (UINT8
));
1138 BlockSize
+= StringTextPtr
- BlockHdr
;
1140 for (Index
= 0; Index
< StringCount
; Index
++) {
1142 StringSize
= AsciiStrSize ((CHAR8
*) StringTextPtr
);
1143 *KeywordValue
= AllocatePool (StringSize
* sizeof (CHAR16
));
1144 if (*KeywordValue
== NULL
) {
1147 AsciiStrToUnicodeStrS ((CHAR8
*) StringTextPtr
, *KeywordValue
, StringSize
);
1148 return CurrentStringId
;
1149 } else if (CurrentStringId
== StringId
) {
1153 BlockSize
+= AsciiStrSize ((CHAR8
*) StringTextPtr
);
1154 StringTextPtr
= StringTextPtr
+ AsciiStrSize ((CHAR8
*) StringTextPtr
);
1159 case EFI_HII_SIBT_STRING_UCS2
:
1160 Offset
= sizeof (EFI_HII_STRING_BLOCK
);
1161 StringTextPtr
= BlockHdr
+ Offset
;
1163 // Use StringSize to store the size of the specified string, including the NULL
1166 GetUnicodeStringTextAndSize (StringTextPtr
, &StringSize
, &String
);
1167 if (FindString
&& (String
!= NULL
) && (*String
!= L
'\0')) {
1169 // String protocol use this type for the string id which has value for other package.
1170 // It will allocate an empty string block for this string id. so here we also check
1171 // *String != L'\0' to prohibit this case.
1173 *KeywordValue
= String
;
1174 return CurrentStringId
;
1175 } else if (CurrentStringId
== StringId
) {
1179 BlockSize
+= Offset
+ StringSize
;
1183 case EFI_HII_SIBT_STRING_UCS2_FONT
:
1184 Offset
= sizeof (EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK
) - sizeof (CHAR16
);
1185 StringTextPtr
= BlockHdr
+ Offset
;
1187 // Use StringSize to store the size of the specified string, including the NULL
1190 GetUnicodeStringTextAndSize (StringTextPtr
, &StringSize
, &String
);
1192 *KeywordValue
= String
;
1193 return CurrentStringId
;
1194 } else if (CurrentStringId
== StringId
) {
1198 BlockSize
+= Offset
+ StringSize
;
1202 case EFI_HII_SIBT_STRINGS_UCS2
:
1203 Offset
= sizeof (EFI_HII_SIBT_STRINGS_UCS2_BLOCK
) - sizeof (CHAR16
);
1204 StringTextPtr
= BlockHdr
+ Offset
;
1205 BlockSize
+= Offset
;
1206 CopyMem (&StringCount
, BlockHdr
+ sizeof (EFI_HII_STRING_BLOCK
), sizeof (UINT16
));
1207 for (Index
= 0; Index
< StringCount
; Index
++) {
1208 GetUnicodeStringTextAndSize (StringTextPtr
, &StringSize
, &String
);
1211 *KeywordValue
= String
;
1212 return CurrentStringId
;
1213 } else if (CurrentStringId
== StringId
) {
1217 BlockSize
+= StringSize
;
1218 StringTextPtr
= StringTextPtr
+ StringSize
;
1223 case EFI_HII_SIBT_STRINGS_UCS2_FONT
:
1224 Offset
= sizeof (EFI_HII_SIBT_STRINGS_UCS2_FONT_BLOCK
) - sizeof (CHAR16
);
1225 StringTextPtr
= BlockHdr
+ Offset
;
1226 BlockSize
+= Offset
;
1229 (UINT8
*)((UINTN
)BlockHdr
+ sizeof (EFI_HII_STRING_BLOCK
) + sizeof (UINT8
)),
1232 for (Index
= 0; Index
< StringCount
; Index
++) {
1233 GetUnicodeStringTextAndSize (StringTextPtr
, &StringSize
, &String
);
1235 *KeywordValue
= String
;
1236 return CurrentStringId
;
1237 } else if (CurrentStringId
== StringId
) {
1241 BlockSize
+= StringSize
;
1242 StringTextPtr
= StringTextPtr
+ StringSize
;
1247 case EFI_HII_SIBT_DUPLICATE
:
1248 BlockSize
+= sizeof (EFI_HII_SIBT_DUPLICATE_BLOCK
);
1252 case EFI_HII_SIBT_SKIP1
:
1253 SkipCount
= (UINT16
) (*(UINT8
*)((UINTN
)BlockHdr
+ sizeof (EFI_HII_STRING_BLOCK
)));
1254 CurrentStringId
= (UINT16
) (CurrentStringId
+ SkipCount
);
1255 BlockSize
+= sizeof (EFI_HII_SIBT_SKIP1_BLOCK
);
1258 case EFI_HII_SIBT_SKIP2
:
1259 CopyMem (&SkipCount
, BlockHdr
+ sizeof (EFI_HII_STRING_BLOCK
), sizeof (UINT16
));
1260 CurrentStringId
= (UINT16
) (CurrentStringId
+ SkipCount
);
1261 BlockSize
+= sizeof (EFI_HII_SIBT_SKIP2_BLOCK
);
1264 case EFI_HII_SIBT_EXT1
:
1267 (UINT8
*)((UINTN
)BlockHdr
+ sizeof (EFI_HII_STRING_BLOCK
) + sizeof (UINT8
)),
1270 BlockSize
+= Length8
;
1273 case EFI_HII_SIBT_EXT2
:
1274 CopyMem (&Ext2
, BlockHdr
, sizeof (EFI_HII_SIBT_EXT2_BLOCK
));
1275 BlockSize
+= Ext2
.Length
;
1278 case EFI_HII_SIBT_EXT4
:
1281 (UINT8
*)((UINTN
)BlockHdr
+ sizeof (EFI_HII_STRING_BLOCK
) + sizeof (UINT8
)),
1285 BlockSize
+= Length32
;
1292 if (String
!= NULL
) {
1297 BlockHdr
= StringPackage
->StringBlock
+ BlockSize
;
1304 Get string package from the input NameSpace string.
1306 This is a internal function.
1308 @param DatabaseRecord HII_DATABASE_RECORD format string.
1309 @param NameSpace NameSpace format string.
1310 @param KeywordValue Keyword value.
1311 @param StringId String Id for this keyword.
1313 @retval KEYWORD_HANDLER_NO_ERROR Get String id successfully.
1314 @retval KEYWORD_HANDLER_KEYWORD_NOT_FOUND Not found the string id in the string package.
1315 @retval KEYWORD_HANDLER_NAMESPACE_ID_NOT_FOUND Not found the string package for this namespace.
1316 @retval KEYWORD_HANDLER_UNDEFINED_PROCESSING_ERROR Out of resource error.
1320 GetStringIdFromRecord (
1321 IN HII_DATABASE_RECORD
*DatabaseRecord
,
1322 IN CHAR8
**NameSpace
,
1323 IN CHAR16
*KeywordValue
,
1324 OUT EFI_STRING_ID
*StringId
1328 HII_DATABASE_PACKAGE_LIST_INSTANCE
*PackageListNode
;
1329 HII_STRING_PACKAGE_INSTANCE
*StringPackage
;
1334 ASSERT (DatabaseRecord
!= NULL
&& NameSpace
!= NULL
&& KeywordValue
!= NULL
);
1336 PackageListNode
= DatabaseRecord
->PackageList
;
1337 RetVal
= KEYWORD_HANDLER_NAMESPACE_ID_NOT_FOUND
;
1339 if (*NameSpace
!= NULL
) {
1342 Name
= UEFI_CONFIG_LANG
;
1345 for (Link
= PackageListNode
->StringPkgHdr
.ForwardLink
; Link
!= &PackageListNode
->StringPkgHdr
; Link
= Link
->ForwardLink
) {
1346 StringPackage
= CR (Link
, HII_STRING_PACKAGE_INSTANCE
, StringEntry
, HII_STRING_PACKAGE_SIGNATURE
);
1348 if (AsciiStrnCmp(Name
, StringPackage
->StringPkgHdr
->Language
, AsciiStrLen (Name
)) == 0) {
1349 Status
= GetStringIdFromString (StringPackage
, KeywordValue
, StringId
);
1350 if (EFI_ERROR (Status
)) {
1351 return KEYWORD_HANDLER_KEYWORD_NOT_FOUND
;
1353 if (*NameSpace
== NULL
) {
1354 *NameSpace
= AllocateCopyPool (AsciiStrSize (StringPackage
->StringPkgHdr
->Language
), StringPackage
->StringPkgHdr
->Language
);
1355 if (*NameSpace
== NULL
) {
1356 return KEYWORD_HANDLER_UNDEFINED_PROCESSING_ERROR
;
1359 return KEYWORD_HANDLER_NO_ERROR
;
1368 Tell whether this Operand is an Statement OpCode.
1370 @param Operand Operand of an IFR OpCode.
1372 @retval TRUE This is an Statement OpCode.
1373 @retval FALSE Not an Statement OpCode.
1381 if ((Operand
== EFI_IFR_SUBTITLE_OP
) ||
1382 (Operand
== EFI_IFR_TEXT_OP
) ||
1383 (Operand
== EFI_IFR_RESET_BUTTON_OP
) ||
1384 (Operand
== EFI_IFR_REF_OP
) ||
1385 (Operand
== EFI_IFR_ACTION_OP
) ||
1386 (Operand
== EFI_IFR_NUMERIC_OP
) ||
1387 (Operand
== EFI_IFR_ORDERED_LIST_OP
) ||
1388 (Operand
== EFI_IFR_CHECKBOX_OP
) ||
1389 (Operand
== EFI_IFR_STRING_OP
) ||
1390 (Operand
== EFI_IFR_PASSWORD_OP
) ||
1391 (Operand
== EFI_IFR_DATE_OP
) ||
1392 (Operand
== EFI_IFR_TIME_OP
) ||
1393 (Operand
== EFI_IFR_GUID_OP
) ||
1394 (Operand
== EFI_IFR_ONE_OF_OP
)) {
1402 Tell whether this Operand is an Statement OpCode.
1404 @param Operand Operand of an IFR OpCode.
1406 @retval TRUE This is an Statement OpCode.
1407 @retval FALSE Not an Statement OpCode.
1415 if ((Operand
== EFI_IFR_VARSTORE_OP
) ||
1416 (Operand
== EFI_IFR_VARSTORE_NAME_VALUE_OP
) ||
1417 (Operand
== EFI_IFR_VARSTORE_EFI_OP
)) {
1425 Base on the prompt string id to find the question.
1427 @param FormPackage The input form package.
1428 @param KeywordStrId The input prompt string id for one question.
1430 @retval the opcode for the question.
1434 FindQuestionFromStringId (
1435 IN HII_IFR_PACKAGE_INSTANCE
*FormPackage
,
1436 IN EFI_STRING_ID KeywordStrId
1441 EFI_IFR_STATEMENT_HEADER
*StatementHeader
;
1442 EFI_IFR_OP_HEADER
*OpCodeHeader
;
1445 ASSERT (FormPackage
!= NULL
);
1447 FormDataLen
= FormPackage
->FormPkgHdr
.Length
- sizeof (EFI_HII_PACKAGE_HEADER
);
1449 while (Offset
< FormDataLen
) {
1450 OpCodeData
= FormPackage
->IfrData
+ Offset
;
1451 OpCodeHeader
= (EFI_IFR_OP_HEADER
*) OpCodeData
;
1453 if (IsStatementOpCode(OpCodeHeader
->OpCode
)) {
1454 StatementHeader
= (EFI_IFR_STATEMENT_HEADER
*) (OpCodeData
+ sizeof (EFI_IFR_OP_HEADER
));
1455 if (StatementHeader
->Prompt
== KeywordStrId
) {
1460 Offset
+= OpCodeHeader
->Length
;
1467 Base on the varstore id to find the storage info.
1469 @param FormPackage The input form package.
1470 @param VarStoreId The input storage id.
1472 @retval the opcode for the storage.
1476 FindStorageFromVarId (
1477 IN HII_IFR_PACKAGE_INSTANCE
*FormPackage
,
1478 IN EFI_VARSTORE_ID VarStoreId
1483 EFI_IFR_OP_HEADER
*OpCodeHeader
;
1486 ASSERT (FormPackage
!= NULL
);
1488 FormDataLen
= FormPackage
->FormPkgHdr
.Length
- sizeof (EFI_HII_PACKAGE_HEADER
);
1490 while (Offset
< FormDataLen
) {
1491 OpCodeData
= FormPackage
->IfrData
+ Offset
;
1492 OpCodeHeader
= (EFI_IFR_OP_HEADER
*) OpCodeData
;
1494 if (IsStorageOpCode(OpCodeHeader
->OpCode
)) {
1495 switch (OpCodeHeader
->OpCode
) {
1496 case EFI_IFR_VARSTORE_OP
:
1497 if (VarStoreId
== ((EFI_IFR_VARSTORE
*) OpCodeData
)->VarStoreId
) {
1502 case EFI_IFR_VARSTORE_NAME_VALUE_OP
:
1503 if (VarStoreId
== ((EFI_IFR_VARSTORE_NAME_VALUE
*) OpCodeData
)->VarStoreId
) {
1508 case EFI_IFR_VARSTORE_EFI_OP
:
1509 if (VarStoreId
== ((EFI_IFR_VARSTORE_EFI
*) OpCodeData
)->VarStoreId
) {
1519 Offset
+= OpCodeHeader
->Length
;
1526 Get width info for one question.
1528 @param OpCodeData The input opcode for one question.
1530 @retval the width info for one question.
1535 IN UINT8
*OpCodeData
1538 UINT8
*NextOpCodeData
;
1540 ASSERT (OpCodeData
!= NULL
);
1542 switch (((EFI_IFR_OP_HEADER
*) OpCodeData
)->OpCode
) {
1543 case EFI_IFR_REF_OP
:
1544 return (UINT16
) sizeof (EFI_HII_REF
);
1546 case EFI_IFR_ONE_OF_OP
:
1547 case EFI_IFR_NUMERIC_OP
:
1548 switch (((EFI_IFR_ONE_OF
*) OpCodeData
)->Flags
& EFI_IFR_NUMERIC_SIZE
) {
1549 case EFI_IFR_NUMERIC_SIZE_1
:
1550 return (UINT16
) sizeof (UINT8
);
1552 case EFI_IFR_NUMERIC_SIZE_2
:
1553 return (UINT16
) sizeof (UINT16
);
1555 case EFI_IFR_NUMERIC_SIZE_4
:
1556 return (UINT16
) sizeof (UINT32
);
1558 case EFI_IFR_NUMERIC_SIZE_8
:
1559 return (UINT16
) sizeof (UINT64
);
1566 case EFI_IFR_ORDERED_LIST_OP
:
1567 NextOpCodeData
= OpCodeData
+ ((EFI_IFR_ORDERED_LIST
*) OpCodeData
)->Header
.Length
;
1569 // OneOfOption must follow the orderedlist opcode.
1571 ASSERT (((EFI_IFR_OP_HEADER
*) NextOpCodeData
)->OpCode
== EFI_IFR_ONE_OF_OPTION_OP
);
1572 switch (((EFI_IFR_ONE_OF_OPTION
*) NextOpCodeData
)->Type
) {
1573 case EFI_IFR_TYPE_NUM_SIZE_8
:
1574 return (UINT16
) sizeof (UINT8
) * ((EFI_IFR_ORDERED_LIST
*) OpCodeData
)->MaxContainers
;
1576 case EFI_IFR_TYPE_NUM_SIZE_16
:
1577 return (UINT16
) sizeof (UINT16
) * ((EFI_IFR_ORDERED_LIST
*) OpCodeData
)->MaxContainers
;
1579 case EFI_IFR_TYPE_NUM_SIZE_32
:
1580 return (UINT16
) sizeof (UINT32
) * ((EFI_IFR_ORDERED_LIST
*) OpCodeData
)->MaxContainers
;
1582 case EFI_IFR_TYPE_NUM_SIZE_64
:
1583 return (UINT16
) sizeof (UINT64
) * ((EFI_IFR_ORDERED_LIST
*) OpCodeData
)->MaxContainers
;
1590 case EFI_IFR_CHECKBOX_OP
:
1591 return (UINT16
) sizeof (BOOLEAN
);
1593 case EFI_IFR_PASSWORD_OP
:
1594 return (UINT16
)((UINTN
) ((EFI_IFR_PASSWORD
*) OpCodeData
)->MaxSize
* sizeof (CHAR16
));
1596 case EFI_IFR_STRING_OP
:
1597 return (UINT16
)((UINTN
) ((EFI_IFR_STRING
*) OpCodeData
)->MaxSize
* sizeof (CHAR16
));
1599 case EFI_IFR_DATE_OP
:
1600 return (UINT16
) sizeof (EFI_HII_DATE
);
1602 case EFI_IFR_TIME_OP
:
1603 return (UINT16
) sizeof (EFI_HII_TIME
);
1612 Converts all hex string characters in range ['A'..'F'] to ['a'..'f'] for
1613 hex digits that appear between a '=' and a '&' in a config string.
1615 If ConfigString is NULL, then ASSERT().
1617 @param[in] ConfigString Pointer to a Null-terminated Unicode string.
1619 @return Pointer to the Null-terminated Unicode result string.
1624 InternalLowerConfigString (
1625 IN EFI_STRING ConfigString
1631 ASSERT (ConfigString
!= NULL
);
1634 // Convert all hex digits in range [A-F] in the configuration header to [a-f]
1636 for (String
= ConfigString
, Lower
= FALSE
; *String
!= L
'\0'; String
++) {
1637 if (*String
== L
'=') {
1639 } else if (*String
== L
'&') {
1641 } else if (Lower
&& *String
>= L
'A' && *String
<= L
'F') {
1642 *String
= (CHAR16
) (*String
- L
'A' + L
'a');
1646 return ConfigString
;
1650 Allocates and returns a Null-terminated Unicode <ConfigHdr> string.
1652 The format of a <ConfigHdr> is as follows:
1654 GUID=<HexCh>32&NAME=<Char>NameLength&PATH=<HexChar>DevicePathSize<Null>
1656 @param[in] OpCodeData The opcode for the storage.
1657 @param[in] DriverHandle The driver handle which supports a Device Path Protocol
1658 that is the routing information PATH. Each byte of
1659 the Device Path associated with DriverHandle is converted
1660 to a 2 Unicode character hexadecimal string.
1662 @retval NULL DriverHandle does not support the Device Path Protocol.
1663 @retval Other A pointer to the Null-terminate Unicode <ConfigHdr> string
1667 ConstructConfigHdr (
1668 IN UINT8
*OpCodeData
,
1669 IN EFI_HANDLE DriverHandle
1673 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
1674 UINTN DevicePathSize
;
1676 CHAR16
*ReturnString
;
1685 ASSERT (OpCodeData
!= NULL
);
1687 switch (((EFI_IFR_OP_HEADER
*)OpCodeData
)->OpCode
) {
1688 case EFI_IFR_VARSTORE_OP
:
1689 Guid
= (EFI_GUID
*)(UINTN
*)&((EFI_IFR_VARSTORE
*) OpCodeData
)->Guid
;
1690 AsciiName
= (CHAR8
*) ((EFI_IFR_VARSTORE
*) OpCodeData
)->Name
;
1693 case EFI_IFR_VARSTORE_NAME_VALUE_OP
:
1694 Guid
= (EFI_GUID
*)(UINTN
*)&((EFI_IFR_VARSTORE_NAME_VALUE
*) OpCodeData
)->Guid
;
1698 case EFI_IFR_VARSTORE_EFI_OP
:
1699 Guid
= (EFI_GUID
*)(UINTN
*)&((EFI_IFR_VARSTORE_EFI
*) OpCodeData
)->Guid
;
1700 AsciiName
= (CHAR8
*) ((EFI_IFR_VARSTORE_EFI
*) OpCodeData
)->Name
;
1710 if (AsciiName
!= NULL
) {
1711 NameSize
= AsciiStrSize (AsciiName
);
1712 Name
= AllocateZeroPool (NameSize
* sizeof (CHAR16
));
1713 ASSERT (Name
!= NULL
);
1714 AsciiStrToUnicodeStrS (AsciiName
, Name
, NameSize
);
1720 // Compute the length of Name in Unicode characters.
1721 // If Name is NULL, then the length is 0.
1725 NameLength
= StrLen (Name
);
1731 // Retrieve DevicePath Protocol associated with DriverHandle
1733 if (DriverHandle
!= NULL
) {
1734 DevicePath
= DevicePathFromHandle (DriverHandle
);
1735 if (DevicePath
== NULL
) {
1739 // Compute the size of the device path in bytes
1741 DevicePathSize
= GetDevicePathSize (DevicePath
);
1745 // GUID=<HexCh>32&NAME=<Char>NameLength&PATH=<HexChar>DevicePathSize <Null>
1746 // | 5 | sizeof (EFI_GUID) * 2 | 6 | NameStrLen*4 | 6 | DevicePathSize * 2 | 1 |
1748 MaxLen
= 5 + sizeof (EFI_GUID
) * 2 + 6 + NameLength
* 4 + 6 + DevicePathSize
* 2 + 1;
1749 String
= AllocateZeroPool (MaxLen
* sizeof (CHAR16
));
1750 if (String
== NULL
) {
1755 // Start with L"GUID="
1757 StrCpyS (String
, MaxLen
, L
"GUID=");
1758 ReturnString
= String
;
1759 String
+= StrLen (String
);
1763 // Append Guid converted to <HexCh>32
1765 for (Index
= 0, Buffer
= (UINT8
*)Guid
; Index
< sizeof (EFI_GUID
); Index
++) {
1766 UnicodeValueToStringS (
1768 MaxLen
* sizeof (CHAR16
) - ((UINTN
)String
- (UINTN
)ReturnString
),
1769 PREFIX_ZERO
| RADIX_HEX
,
1773 String
+= StrnLenS (String
, MaxLen
- ((UINTN
)String
- (UINTN
)ReturnString
) / sizeof (CHAR16
));
1780 StrCatS (ReturnString
, MaxLen
, L
"&NAME=");
1781 String
+= StrLen (String
);
1785 // Append Name converted to <Char>NameLength
1787 for (; *Name
!= L
'\0'; Name
++) {
1788 UnicodeValueToStringS (
1790 MaxLen
* sizeof (CHAR16
) - ((UINTN
)String
- (UINTN
)ReturnString
),
1791 PREFIX_ZERO
| RADIX_HEX
,
1795 String
+= StrnLenS (String
, MaxLen
- ((UINTN
)String
- (UINTN
)ReturnString
) / sizeof (CHAR16
));
1802 StrCatS (ReturnString
, MaxLen
, L
"&PATH=");
1803 String
+= StrLen (String
);
1806 // Append the device path associated with DriverHandle converted to <HexChar>DevicePathSize
1808 for (Index
= 0, Buffer
= (UINT8
*)DevicePath
; Index
< DevicePathSize
; Index
++) {
1809 UnicodeValueToStringS (
1811 MaxLen
* sizeof (CHAR16
) - ((UINTN
)String
- (UINTN
)ReturnString
),
1812 PREFIX_ZERO
| RADIX_HEX
,
1816 String
+= StrnLenS (String
, MaxLen
- ((UINTN
)String
- (UINTN
)ReturnString
) / sizeof (CHAR16
));
1820 // Null terminate the Unicode string
1825 // Convert all hex digits in range [A-F] in the configuration header to [a-f]
1827 return InternalLowerConfigString (ReturnString
);
1831 Generate the Config request element for one question.
1833 @param Name The name info for one question.
1834 @param Offset The offset info for one question.
1835 @param Width The width info for one question.
1837 @return Pointer to the Null-terminated Unicode request element string.
1841 ConstructRequestElement (
1852 // Add <BlockName> length for each Name
1854 // <BlockName> ::= Name + \0
1857 Length
= StrLen (Name
) + 1;
1860 // Add <BlockName> length for each Offset/Width pair
1862 // <BlockName> ::= OFFSET=1234&WIDTH=1234 + \0
1863 // | 7 | 4 | 7 | 4 | 1
1865 Length
= (7 + 4 + 7 + 4 + 1);
1869 // Allocate buffer for the entire <ConfigRequest>
1871 StringPtr
= AllocateZeroPool (Length
* sizeof (CHAR16
));
1872 ASSERT (StringPtr
!= NULL
);
1880 (StrLen (Name
) + 1) * sizeof (CHAR16
),
1886 // Append OFFSET=XXXX&WIDTH=YYYY\0
1890 (7 + 4 + 7 + 4 + 1) * sizeof (CHAR16
),
1891 L
"OFFSET=%04X&WIDTH=%04X",
1901 Get string value for question's name field.
1903 @param DatabaseRecord HII_DATABASE_RECORD format string.
1904 @param NameId The string id for the name field.
1906 @retval Name string.
1911 IN HII_DATABASE_RECORD
*DatabaseRecord
,
1912 IN EFI_STRING_ID NameId
1916 CHAR8
*PlatformLanguage
;
1917 CHAR8
*SupportedLanguages
;
1918 CHAR8
*BestLanguage
;
1924 BestLanguage
= NULL
;
1925 PlatformLanguage
= NULL
;
1926 SupportedLanguages
= NULL
;
1928 GetEfiGlobalVariable2 (L
"PlatformLang", (VOID
**)&PlatformLanguage
, NULL
);
1929 SupportedLanguages
= GetSupportedLanguages(DatabaseRecord
->Handle
);
1932 // Get the best matching language from SupportedLanguages
1934 BestLanguage
= GetBestLanguage (
1936 FALSE
, // RFC 4646 mode
1937 PlatformLanguage
!= NULL
? PlatformLanguage
: "", // Highest priority
1938 SupportedLanguages
, // Lowest priority
1941 if (BestLanguage
== NULL
) {
1942 BestLanguage
= AllocateCopyPool (AsciiStrLen ("en-US"), "en-US");
1943 ASSERT (BestLanguage
!= NULL
);
1947 Status
= mPrivate
.HiiString
.GetString (
1948 &mPrivate
.HiiString
,
1950 DatabaseRecord
->Handle
,
1956 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
1960 Name
= AllocateZeroPool (StringSize
);
1965 Status
= mPrivate
.HiiString
.GetString (
1966 &mPrivate
.HiiString
,
1968 DatabaseRecord
->Handle
,
1975 if (EFI_ERROR (Status
)) {
1982 if (SupportedLanguages
!= NULL
) {
1983 FreePool(SupportedLanguages
);
1985 if (BestLanguage
!= NULL
) {
1986 FreePool (BestLanguage
);
1988 if (PlatformLanguage
!= NULL
) {
1989 FreePool (PlatformLanguage
);
1996 Base on the input parameter to generate the ConfigRequest string.
1998 This is a internal function.
2000 @param DatabaseRecord HII_DATABASE_RECORD format string.
2001 @param KeywordStrId Keyword string id.
2002 @param OpCodeData The IFR data for this question.
2003 @param ConfigRequest Return the generate ConfigRequest string.
2005 @retval EFI_SUCCESS Generate ConfigResp string success.
2006 @retval EFI_OUT_OF_RESOURCES System out of memory resource error.
2007 @retval EFI_NOT_FOUND Not found the question which use this string id
2008 as the prompt string id.
2011 ExtractConfigRequest (
2012 IN HII_DATABASE_RECORD
*DatabaseRecord
,
2013 IN EFI_STRING_ID KeywordStrId
,
2014 OUT UINT8
**OpCodeData
,
2015 OUT EFI_STRING
*ConfigRequest
2019 HII_DATABASE_PACKAGE_LIST_INSTANCE
*PackageListNode
;
2020 HII_IFR_PACKAGE_INSTANCE
*FormPackage
;
2021 EFI_IFR_QUESTION_HEADER
*Header
;
2028 CHAR16
*RequestElement
;
2032 ASSERT (DatabaseRecord
!= NULL
&& OpCodeData
!= NULL
&& ConfigRequest
!= NULL
);
2039 PackageListNode
= DatabaseRecord
->PackageList
;
2042 // Search the languages in the specified packagelist.
2044 for (Link
= PackageListNode
->FormPkgHdr
.ForwardLink
; Link
!= &PackageListNode
->FormPkgHdr
; Link
= Link
->ForwardLink
) {
2045 FormPackage
= CR (Link
, HII_IFR_PACKAGE_INSTANCE
, IfrEntry
, HII_IFR_PACKAGE_SIGNATURE
);
2047 OpCode
= FindQuestionFromStringId (FormPackage
, KeywordStrId
);
2048 if (OpCode
!= NULL
) {
2049 *OpCodeData
= OpCode
;
2050 Header
= (EFI_IFR_QUESTION_HEADER
*) (OpCode
+ sizeof (EFI_IFR_OP_HEADER
));
2052 // Header->VarStoreId == 0 means no storage for this question.
2054 ASSERT (Header
->VarStoreId
!= 0);
2055 DEBUG ((EFI_D_INFO
, "Varstore Id: 0x%x\n", Header
->VarStoreId
));
2057 Storage
= FindStorageFromVarId (FormPackage
, Header
->VarStoreId
);
2058 ASSERT (Storage
!= NULL
);
2060 if (((EFI_IFR_OP_HEADER
*) Storage
)->OpCode
== EFI_IFR_VARSTORE_NAME_VALUE_OP
) {
2061 Name
= GetNameFromId (DatabaseRecord
, Header
->VarStoreInfo
.VarName
);
2063 Offset
= Header
->VarStoreInfo
.VarOffset
;
2064 Width
= GetWidth (OpCode
);
2066 RequestElement
= ConstructRequestElement(Name
, Offset
, Width
);
2067 ConfigHdr
= ConstructConfigHdr(Storage
, DatabaseRecord
->DriverHandle
);
2068 ASSERT (ConfigHdr
!= NULL
);
2070 MaxLen
= StrLen (ConfigHdr
) + 1 + StrLen(RequestElement
) + 1;
2071 *ConfigRequest
= AllocatePool (MaxLen
* sizeof (CHAR16
));
2072 if (*ConfigRequest
== NULL
) {
2073 FreePool (ConfigHdr
);
2074 FreePool (RequestElement
);
2075 return EFI_OUT_OF_RESOURCES
;
2077 StringPtr
= *ConfigRequest
;
2079 StrCpyS (StringPtr
, MaxLen
, ConfigHdr
);
2081 StrCatS (StringPtr
, MaxLen
, L
"&");
2083 StrCatS (StringPtr
, MaxLen
, RequestElement
);
2085 FreePool (ConfigHdr
);
2086 FreePool (RequestElement
);
2092 return EFI_NOT_FOUND
;
2096 Base on the input parameter to generate the ConfigResp string.
2098 This is a internal function.
2100 @param DatabaseRecord HII_DATABASE_RECORD format string.
2101 @param KeywordStrId Keyword string id.
2102 @param ValueElement The value for the question which use keyword string id
2103 as the prompt string id.
2104 @param OpCodeData The IFR data for this question.
2105 @param ConfigResp Return the generate ConfigResp string.
2107 @retval EFI_SUCCESS Generate ConfigResp string success.
2108 @retval EFI_OUT_OF_RESOURCES System out of memory resource error.
2109 @retval EFI_NOT_FOUND Not found the question which use this string id
2110 as the prompt string id.
2114 IN HII_DATABASE_RECORD
*DatabaseRecord
,
2115 IN EFI_STRING_ID KeywordStrId
,
2116 IN EFI_STRING ValueElement
,
2117 OUT UINT8
**OpCodeData
,
2118 OUT EFI_STRING
*ConfigResp
2122 HII_DATABASE_PACKAGE_LIST_INSTANCE
*PackageListNode
;
2123 HII_IFR_PACKAGE_INSTANCE
*FormPackage
;
2124 EFI_IFR_QUESTION_HEADER
*Header
;
2131 CHAR16
*RequestElement
;
2135 ASSERT ((DatabaseRecord
!= NULL
) && (OpCodeData
!= NULL
) && (ConfigResp
!= NULL
) && (ValueElement
!= NULL
));
2142 PackageListNode
= DatabaseRecord
->PackageList
;
2145 // Search the languages in the specified packagelist.
2147 for (Link
= PackageListNode
->FormPkgHdr
.ForwardLink
; Link
!= &PackageListNode
->FormPkgHdr
; Link
= Link
->ForwardLink
) {
2148 FormPackage
= CR (Link
, HII_IFR_PACKAGE_INSTANCE
, IfrEntry
, HII_IFR_PACKAGE_SIGNATURE
);
2150 OpCode
= FindQuestionFromStringId (FormPackage
, KeywordStrId
);
2151 if (OpCode
!= NULL
) {
2152 *OpCodeData
= OpCode
;
2153 Header
= (EFI_IFR_QUESTION_HEADER
*) (OpCode
+ sizeof (EFI_IFR_OP_HEADER
));
2155 // Header->VarStoreId == 0 means no storage for this question.
2157 ASSERT (Header
->VarStoreId
!= 0);
2158 DEBUG ((EFI_D_INFO
, "Varstore Id: 0x%x\n", Header
->VarStoreId
));
2160 Storage
= FindStorageFromVarId (FormPackage
, Header
->VarStoreId
);
2161 ASSERT (Storage
!= NULL
);
2163 if (((EFI_IFR_OP_HEADER
*) Storage
)->OpCode
== EFI_IFR_VARSTORE_NAME_VALUE_OP
) {
2164 Name
= GetNameFromId (DatabaseRecord
, Header
->VarStoreInfo
.VarName
);
2166 Offset
= Header
->VarStoreInfo
.VarOffset
;
2167 Width
= GetWidth (OpCode
);
2169 RequestElement
= ConstructRequestElement(Name
, Offset
, Width
);
2171 ConfigHdr
= ConstructConfigHdr(Storage
, DatabaseRecord
->DriverHandle
);
2172 ASSERT (ConfigHdr
!= NULL
);
2174 MaxLen
= StrLen (ConfigHdr
) + 1 + StrLen(RequestElement
) + 1 + StrLen (L
"VALUE=") + StrLen(ValueElement
) + 1;
2175 *ConfigResp
= AllocatePool (MaxLen
* sizeof (CHAR16
));
2176 if (*ConfigResp
== NULL
) {
2177 FreePool (ConfigHdr
);
2178 FreePool (RequestElement
);
2179 return EFI_OUT_OF_RESOURCES
;
2181 StringPtr
= *ConfigResp
;
2183 StrCpyS (StringPtr
, MaxLen
, ConfigHdr
);
2185 StrCatS (StringPtr
, MaxLen
, L
"&");
2188 StrCatS (StringPtr
, MaxLen
, RequestElement
);
2190 StrCatS (StringPtr
, MaxLen
, L
"&");
2192 StrCatS (StringPtr
, MaxLen
, L
"VALUE=");
2194 StrCatS (StringPtr
, MaxLen
, ValueElement
);
2196 FreePool (ConfigHdr
);
2197 FreePool (RequestElement
);
2203 return EFI_NOT_FOUND
;
2207 Get the Value section from the Hii driver.
2209 This is a internal function.
2211 @param ConfigRequest The input ConfigRequest string.
2212 @param ValueElement The respond Value section from the hii driver.
2214 @retval Misc value The error status return from ExtractConfig function.
2215 @retval EFI_OUT_OF_RESOURCES The memory can't be allocated
2216 @retval EFI_SUCCESS Get the value section success.
2220 ExtractValueFromDriver (
2221 IN CHAR16
*ConfigRequest
,
2222 OUT CHAR16
**ValueElement
2227 EFI_STRING Progress
;
2231 ASSERT ((ConfigRequest
!= NULL
) && (ValueElement
!= NULL
));
2233 Status
= mPrivate
.ConfigRouting
.ExtractConfig (
2234 &mPrivate
.ConfigRouting
,
2235 (EFI_STRING
) ConfigRequest
,
2239 if (EFI_ERROR (Status
)) {
2244 // Find Value Section and return it.
2246 StringPtr
= StrStr (Result
, L
"&VALUE=");
2247 ASSERT (StringPtr
!= NULL
);
2248 StringEnd
= StrStr (StringPtr
+ 1, L
"&");
2249 if (StringEnd
!= NULL
) {
2253 *ValueElement
= AllocateCopyPool (StrSize (StringPtr
), StringPtr
);
2254 if (*ValueElement
== NULL
) {
2255 return EFI_OUT_OF_RESOURCES
;
2258 if (StringEnd
!= NULL
) {
2267 Get EFI_STRING_ID info from the input device path, namespace and keyword.
2269 This is a internal function.
2271 @param DevicePath Input device path info.
2272 @param NameSpace NameSpace format string.
2273 @param KeywordData Keyword used to get string id.
2274 @param ProgressErr Return extra error type.
2275 @param KeywordStringId Return EFI_STRING_ID.
2276 @param DataBaseRecord DataBase record data for this driver.
2278 @retval EFI_INVALID_PARAMETER Can't find the database record base on the input device path or namespace.
2279 @retval EFI_NOT_FOUND Can't find the EFI_STRING_ID for the keyword.
2280 @retval EFI_SUCCESS Find the EFI_STRING_ID.
2284 GetStringIdFromDatabase (
2285 IN EFI_DEVICE_PATH_PROTOCOL
**DevicePath
,
2286 IN CHAR8
**NameSpace
,
2287 IN CHAR16
*KeywordData
,
2288 OUT UINT32
*ProgressErr
,
2289 OUT EFI_STRING_ID
*KeywordStringId
,
2290 OUT HII_DATABASE_RECORD
**DataBaseRecord
2293 HII_DATABASE_RECORD
*Record
;
2295 BOOLEAN FindNameSpace
;
2296 EFI_DEVICE_PATH_PROTOCOL
*DestDevicePath
;
2297 UINT8
*DevicePathPkg
;
2298 UINTN DevicePathSize
;
2300 ASSERT ((NameSpace
!= NULL
) && (KeywordData
!= NULL
) && (ProgressErr
!= NULL
) && (KeywordStringId
!= NULL
) && (DataBaseRecord
!= NULL
));
2302 FindNameSpace
= FALSE
;
2304 if (*DevicePath
!= NULL
) {
2306 // Get DataBaseRecord from device path protocol.
2308 Record
= GetRecordFromDevicePath(*DevicePath
);
2309 if (Record
== NULL
) {
2311 // Can't find the DatabaseRecord base on the input device path info.
2312 // NEED TO CONFIRM the return ProgressErr.
2314 *ProgressErr
= KEYWORD_HANDLER_MALFORMED_STRING
;
2315 return EFI_INVALID_PARAMETER
;
2319 // Get string id from the record.
2321 *ProgressErr
= GetStringIdFromRecord (Record
, NameSpace
, KeywordData
, KeywordStringId
);
2322 switch (*ProgressErr
) {
2323 case KEYWORD_HANDLER_NO_ERROR
:
2324 *DataBaseRecord
= Record
;
2327 case KEYWORD_HANDLER_NAMESPACE_ID_NOT_FOUND
:
2328 return EFI_INVALID_PARAMETER
;
2331 ASSERT (*ProgressErr
== KEYWORD_HANDLER_KEYWORD_NOT_FOUND
);
2332 return EFI_NOT_FOUND
;
2336 // Find driver which matches the routing data.
2338 for (Link
= mPrivate
.DatabaseList
.ForwardLink
; Link
!= &mPrivate
.DatabaseList
; Link
= Link
->ForwardLink
) {
2339 Record
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
2341 *ProgressErr
= GetStringIdFromRecord (Record
, NameSpace
, KeywordData
, KeywordStringId
);
2342 if (*ProgressErr
== KEYWORD_HANDLER_NO_ERROR
) {
2343 *DataBaseRecord
= Record
;
2345 if ((DevicePathPkg
= Record
->PackageList
->DevicePathPkg
) != NULL
) {
2346 DestDevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) (DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
));
2347 DevicePathSize
= GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) DestDevicePath
);
2348 *DevicePath
= AllocateCopyPool (DevicePathSize
, DestDevicePath
);
2349 if (*DevicePath
== NULL
) {
2350 return EFI_OUT_OF_RESOURCES
;
2354 // Need to verify this ASSERT.
2360 } else if (*ProgressErr
== KEYWORD_HANDLER_UNDEFINED_PROCESSING_ERROR
) {
2361 return EFI_OUT_OF_RESOURCES
;
2362 } else if (*ProgressErr
== KEYWORD_HANDLER_KEYWORD_NOT_FOUND
) {
2363 FindNameSpace
= TRUE
;
2368 // When PathHdr not input, if ever find the namespace, will return KEYWORD_HANDLER_KEYWORD_NOT_FOUND.
2369 // This is a bit more progress than KEYWORD_HANDLER_NAMESPACE_ID_NOT_FOUND.
2371 if (FindNameSpace
) {
2372 return EFI_NOT_FOUND
;
2374 return EFI_INVALID_PARAMETER
;
2380 Generate the KeywordResp String.
2382 <KeywordResp> ::= <NameSpaceId><PathHdr>'&'<Keyword>'&VALUE='<Number>['&READONLY']
2384 @param NameSpace NameSpace format string.
2385 @param DevicePath Input device path info.
2386 @param KeywordData Keyword used to get string id.
2387 @param ValueStr The value section for the keyword.
2388 @param ReadOnly Whether this value is readonly.
2389 @param KeywordResp Return the point to the KeywordResp string.
2391 @retval EFI_OUT_OF_RESOURCES The memory can't be allocated.
2392 @retval EFI_SUCCESS Generate the KeywordResp string.
2396 GenerateKeywordResp (
2397 IN CHAR8
*NameSpace
,
2398 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
2399 IN EFI_STRING KeywordData
,
2400 IN EFI_STRING ValueStr
,
2401 IN BOOLEAN ReadOnly
,
2402 OUT EFI_STRING
*KeywordResp
2408 CHAR16
*UnicodeNameSpace
;
2409 UINTN NameSpaceLength
;
2411 ASSERT ((NameSpace
!= NULL
) && (DevicePath
!= NULL
) && (KeywordData
!= NULL
) && (ValueStr
!= NULL
) && (KeywordResp
!= NULL
));
2414 // 1. Calculate the string length.
2417 // 1.1 NameSpaceId size.
2418 // 'NAMESPACE='<String>
2420 NameSpaceLength
= AsciiStrLen (NameSpace
);
2421 RespStrLen
= 10 + NameSpaceLength
;
2422 UnicodeNameSpace
= AllocatePool ((NameSpaceLength
+ 1) * sizeof (CHAR16
));
2423 if (UnicodeNameSpace
== NULL
) {
2424 return EFI_OUT_OF_RESOURCES
;
2426 AsciiStrToUnicodeStrS (NameSpace
, UnicodeNameSpace
, NameSpaceLength
+ 1);
2429 // 1.2 PathHdr size.
2430 // PATH=<UEFI binary Device Path represented as hex number>'&'
2431 // Attention: The output include the '&' at the end.
2435 GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL
*) DevicePath
),
2436 (VOID
*) DevicePath
,
2440 RespStrLen
+= StrLen (PathHdr
);
2443 // 1.3 Keyword section.
2444 // 'KEYWORD='<String>[':'<DecCh>(1/4)]
2446 RespStrLen
+= 8 + StrLen (KeywordData
);
2449 // 1.4 Value section.
2450 // ValueStr = '&VALUE='<Number>
2452 RespStrLen
+= StrLen (ValueStr
);
2455 // 1.5 ReadOnly Section.
2463 // 2. Allocate the buffer and create the KeywordResp string include '\0'.
2466 *KeywordResp
= AllocatePool (RespStrLen
* sizeof (CHAR16
));
2467 if (*KeywordResp
== NULL
) {
2468 if (UnicodeNameSpace
!= NULL
) {
2469 FreePool (UnicodeNameSpace
);
2472 return EFI_OUT_OF_RESOURCES
;
2474 RespStr
= *KeywordResp
;
2477 // 2.1 Copy NameSpaceId section.
2479 StrCpyS (RespStr
, RespStrLen
, L
"NAMESPACE=");
2481 StrCatS (RespStr
, RespStrLen
, UnicodeNameSpace
);
2484 // 2.2 Copy PathHdr section.
2486 StrCatS (RespStr
, RespStrLen
, PathHdr
);
2489 // 2.3 Copy Keyword section.
2491 StrCatS (RespStr
, RespStrLen
, L
"KEYWORD=");
2493 StrCatS (RespStr
, RespStrLen
, KeywordData
);
2496 // 2.4 Copy the Value section.
2498 StrCatS (RespStr
, RespStrLen
, ValueStr
);
2501 // 2.5 Copy ReadOnly section if exist.
2504 StrCatS (RespStr
, RespStrLen
, L
"&READONLY");
2507 if (UnicodeNameSpace
!= NULL
) {
2508 FreePool (UnicodeNameSpace
);
2510 if (PathHdr
!= NULL
) {
2518 Merge the KeywordResp String to MultiKeywordResp string.
2520 This is a internal function.
2522 @param MultiKeywordResp The existed multikeywordresp string.
2523 @param KeywordResp The input keywordResp string.
2525 @retval EFI_OUT_OF_RESOURCES The memory can't be allocated.
2526 @retval EFI_SUCCESS Generate the MultiKeywordResp string.
2530 MergeToMultiKeywordResp (
2531 IN OUT EFI_STRING
*MultiKeywordResp
,
2532 IN EFI_STRING
*KeywordResp
2535 UINTN MultiKeywordRespLen
;
2536 EFI_STRING StringPtr
;
2538 if (*MultiKeywordResp
== NULL
) {
2539 *MultiKeywordResp
= *KeywordResp
;
2540 *KeywordResp
= NULL
;
2544 MultiKeywordRespLen
= (StrLen (*MultiKeywordResp
) + 1 + StrLen (*KeywordResp
) + 1) * sizeof (CHAR16
);
2546 StringPtr
= ReallocatePool (
2547 StrSize (*MultiKeywordResp
),
2548 MultiKeywordRespLen
,
2551 if (StringPtr
== NULL
) {
2552 return EFI_OUT_OF_RESOURCES
;
2555 *MultiKeywordResp
= StringPtr
;
2557 StrCatS (StringPtr
, MultiKeywordRespLen
/ sizeof (CHAR16
), L
"&");
2559 StrCatS (StringPtr
, MultiKeywordRespLen
/ sizeof (CHAR16
), *KeywordResp
);
2565 Enumerate all keyword in the system.
2567 If error occur when parse one keyword, just skip it and parse the next one.
2569 This is a internal function.
2571 @param NameSpace The namespace used to search the string.
2572 @param MultiResp Return the MultiKeywordResp string for the system.
2573 @param ProgressErr Return the error status.
2575 @retval EFI_OUT_OF_RESOURCES The memory can't be allocated.
2576 @retval EFI_SUCCESS Generate the MultiKeywordResp string.
2577 @retval EFI_NOT_FOUND No keyword found.
2581 EnumerateAllKeywords (
2582 IN CHAR8
*NameSpace
,
2583 OUT EFI_STRING
*MultiResp
,
2584 OUT UINT32
*ProgressErr
2588 LIST_ENTRY
*StringLink
;
2589 UINT8
*DevicePathPkg
;
2591 HII_DATABASE_RECORD
*DataBaseRecord
;
2592 HII_DATABASE_PACKAGE_LIST_INSTANCE
*PackageListNode
;
2593 HII_STRING_PACKAGE_INSTANCE
*StringPackage
;
2594 CHAR8
*LocalNameSpace
;
2595 EFI_STRING_ID NextStringId
;
2598 CHAR16
*ConfigRequest
;
2599 CHAR16
*ValueElement
;
2600 CHAR16
*KeywordResp
;
2601 CHAR16
*MultiKeywordResp
;
2602 CHAR16
*KeywordData
;
2604 BOOLEAN FindKeywordPackages
;
2606 DataBaseRecord
= NULL
;
2607 Status
= EFI_SUCCESS
;
2608 MultiKeywordResp
= NULL
;
2610 LocalNameSpace
= NULL
;
2611 ConfigRequest
= NULL
;
2612 ValueElement
= NULL
;
2614 FindKeywordPackages
= FALSE
;
2616 if (NameSpace
== NULL
) {
2617 NameSpace
= UEFI_CONFIG_LANG
;
2621 // Find driver which matches the routing data.
2623 for (Link
= mPrivate
.DatabaseList
.ForwardLink
; Link
!= &mPrivate
.DatabaseList
; Link
= Link
->ForwardLink
) {
2624 DataBaseRecord
= CR (Link
, HII_DATABASE_RECORD
, DatabaseEntry
, HII_DATABASE_RECORD_SIGNATURE
);
2625 if ((DevicePathPkg
= DataBaseRecord
->PackageList
->DevicePathPkg
) != NULL
) {
2626 DevicePath
= DevicePathPkg
+ sizeof (EFI_HII_PACKAGE_HEADER
);
2628 PackageListNode
= DataBaseRecord
->PackageList
;
2630 for (StringLink
= PackageListNode
->StringPkgHdr
.ForwardLink
; StringLink
!= &PackageListNode
->StringPkgHdr
; StringLink
= StringLink
->ForwardLink
) {
2631 StringPackage
= CR (StringLink
, HII_STRING_PACKAGE_INSTANCE
, StringEntry
, HII_STRING_PACKAGE_SIGNATURE
);
2634 // Check whether has keyword string package.
2636 if (AsciiStrnCmp(NameSpace
, StringPackage
->StringPkgHdr
->Language
, AsciiStrLen (NameSpace
)) == 0) {
2637 FindKeywordPackages
= TRUE
;
2639 // Keep the NameSpace string.
2641 LocalNameSpace
= AllocateCopyPool (AsciiStrSize (StringPackage
->StringPkgHdr
->Language
), StringPackage
->StringPkgHdr
->Language
);
2642 if (LocalNameSpace
== NULL
) {
2643 return EFI_OUT_OF_RESOURCES
;
2647 // 1 means just begin the enumerate the valid string ids.
2648 // StringId == 1 is always used to save the language for this string package.
2649 // Any valid string start from 2. so here initial it to 1.
2654 // Enumerate all valid stringid in the package.
2656 while ((NextStringId
= GetNextStringId (StringPackage
, NextStringId
, &KeywordData
)) != 0) {
2658 // 3.3 Construct the ConfigRequest string.
2660 Status
= ExtractConfigRequest (DataBaseRecord
, NextStringId
, &OpCode
, &ConfigRequest
);
2661 if (EFI_ERROR (Status
)) {
2663 // If can't generate ConfigRequest for this question, skip it and start the next.
2669 // 3.4 Extract Value for the input keyword.
2671 Status
= ExtractValueFromDriver(ConfigRequest
, &ValueElement
);
2672 if (EFI_ERROR (Status
)) {
2673 if (Status
!= EFI_OUT_OF_RESOURCES
) {
2675 // If can't generate ConfigRequest for this question, skip it and start the next.
2680 // If EFI_OUT_OF_RESOURCES error occur, no need to continue.
2686 // Extract readonly flag from opcode.
2688 ReadOnly
= ExtractReadOnlyFromOpCode(OpCode
);
2691 // 5. Generate KeywordResp string.
2693 ASSERT (DevicePath
!= NULL
);
2694 Status
= GenerateKeywordResp(LocalNameSpace
, (EFI_DEVICE_PATH_PROTOCOL
*)DevicePath
, KeywordData
, ValueElement
, ReadOnly
, &KeywordResp
);
2695 if (Status
!= EFI_SUCCESS
) {
2697 // If EFI_OUT_OF_RESOURCES error occur, no need to continue.
2703 // 6. Merge to the MultiKeywordResp string.
2705 Status
= MergeToMultiKeywordResp(&MultiKeywordResp
, &KeywordResp
);
2706 if (EFI_ERROR (Status
)) {
2711 // Clean the temp buffer to later use again.
2713 if (ConfigRequest
!= NULL
) {
2714 FreePool (ConfigRequest
);
2715 ConfigRequest
= NULL
;
2717 if (ValueElement
!= NULL
) {
2718 FreePool (ValueElement
);
2719 ValueElement
= NULL
;
2721 if (KeywordResp
!= NULL
) {
2722 FreePool (KeywordResp
);
2727 if (LocalNameSpace
!= NULL
) {
2728 FreePool (LocalNameSpace
);
2729 LocalNameSpace
= NULL
;
2736 // return the already get MultiKeywordString even error occurred.
2738 if (MultiKeywordResp
== NULL
) {
2739 Status
= EFI_NOT_FOUND
;
2740 if (!FindKeywordPackages
) {
2741 *ProgressErr
= KEYWORD_HANDLER_NAMESPACE_ID_NOT_FOUND
;
2743 *ProgressErr
= KEYWORD_HANDLER_KEYWORD_NOT_FOUND
;
2746 Status
= EFI_SUCCESS
;
2748 *MultiResp
= MultiKeywordResp
;
2751 if (LocalNameSpace
!= NULL
) {
2752 FreePool (LocalNameSpace
);
2754 if (ConfigRequest
!= NULL
) {
2755 FreePool (ConfigRequest
);
2757 if (ValueElement
!= NULL
) {
2758 FreePool (ValueElement
);
2766 This function accepts a <MultiKeywordResp> formatted string, finds the associated
2767 keyword owners, creates a <MultiConfigResp> string from it and forwards it to the
2768 EFI_HII_ROUTING_PROTOCOL.RouteConfig function.
2770 If there is an issue in resolving the contents of the KeywordString, then the
2771 function returns an error and also sets the Progress and ProgressErr with the
2772 appropriate information about where the issue occurred and additional data about
2773 the nature of the issue.
2775 In the case when KeywordString containing multiple keywords, when an EFI_NOT_FOUND
2776 error is generated during processing the second or later keyword element, the system
2777 storage associated with earlier keywords is not modified. All elements of the
2778 KeywordString must successfully pass all tests for format and access prior to making
2779 any modifications to storage.
2781 In the case when EFI_DEVICE_ERROR is returned from the processing of a KeywordString
2782 containing multiple keywords, the state of storage associated with earlier keywords
2786 @param This Pointer to the EFI_KEYWORD_HANDLER _PROTOCOL instance.
2788 @param KeywordString A null-terminated string in <MultiKeywordResp> format.
2790 @param Progress On return, points to a character in the KeywordString.
2791 Points to the string's NULL terminator if the request
2792 was successful. Points to the most recent '&' before
2793 the first failing name / value pair (or the beginning
2794 of the string if the failure is in the first name / value
2795 pair) if the request was not successful.
2797 @param ProgressErr If during the processing of the KeywordString there was
2798 a failure, this parameter gives additional information
2799 about the possible source of the problem. The various
2800 errors are defined in "Related Definitions" below.
2803 @retval EFI_SUCCESS The specified action was completed successfully.
2805 @retval EFI_INVALID_PARAMETER One or more of the following are TRUE:
2806 1. KeywordString is NULL.
2807 2. Parsing of the KeywordString resulted in an
2808 error. See Progress and ProgressErr for more data.
2810 @retval EFI_NOT_FOUND An element of the KeywordString was not found.
2811 See ProgressErr for more data.
2813 @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
2814 See ProgressErr for more data.
2816 @retval EFI_ACCESS_DENIED The action violated system policy. See ProgressErr
2819 @retval EFI_DEVICE_ERROR An unexpected system error occurred. See ProgressErr
2825 EfiConfigKeywordHandlerSetData (
2826 IN EFI_CONFIG_KEYWORD_HANDLER_PROTOCOL
*This
,
2827 IN CONST EFI_STRING KeywordString
,
2828 OUT EFI_STRING
*Progress
,
2829 OUT UINT32
*ProgressErr
2835 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
2836 CHAR16
*NextStringPtr
;
2837 CHAR16
*KeywordData
;
2838 EFI_STRING_ID KeywordStringId
;
2840 HII_DATABASE_RECORD
*DataBaseRecord
;
2843 CHAR16
*MultiConfigResp
;
2844 CHAR16
*ValueElement
;
2846 EFI_STRING InternalProgress
;
2848 CHAR16
*KeywordStartPos
;
2850 if (This
== NULL
|| Progress
== NULL
|| ProgressErr
== NULL
|| KeywordString
== NULL
) {
2851 return EFI_INVALID_PARAMETER
;
2854 *Progress
= KeywordString
;
2855 *ProgressErr
= KEYWORD_HANDLER_UNDEFINED_PROCESSING_ERROR
;
2856 Status
= EFI_SUCCESS
;
2857 MultiConfigResp
= NULL
;
2861 ValueElement
= NULL
;
2863 KeywordStartPos
= NULL
;
2864 KeywordStringId
= 0;
2867 // Use temp string to avoid changing input string buffer.
2869 TempString
= AllocateCopyPool (StrSize (KeywordString
), KeywordString
);
2870 ASSERT (TempString
!= NULL
);
2871 StringPtr
= TempString
;
2873 while ((StringPtr
!= NULL
) && (*StringPtr
!= L
'\0')) {
2875 // 1. Get NameSpace from NameSpaceId keyword.
2877 Status
= ExtractNameSpace (StringPtr
, &NameSpace
, &NextStringPtr
);
2878 if (EFI_ERROR (Status
)) {
2879 *ProgressErr
= KEYWORD_HANDLER_MALFORMED_STRING
;
2882 ASSERT (NameSpace
!= NULL
);
2884 // 1.1 Check whether the input namespace is valid.
2886 if (AsciiStrnCmp(NameSpace
, UEFI_CONFIG_LANG
, AsciiStrLen (UEFI_CONFIG_LANG
)) != 0) {
2887 *ProgressErr
= KEYWORD_HANDLER_MALFORMED_STRING
;
2888 Status
= EFI_INVALID_PARAMETER
;
2892 StringPtr
= NextStringPtr
;
2895 // 2. Get possible Device Path info from KeywordString.
2897 Status
= ExtractDevicePath (StringPtr
, (UINT8
**)&DevicePath
, &NextStringPtr
);
2898 if (EFI_ERROR (Status
)) {
2899 *ProgressErr
= KEYWORD_HANDLER_MALFORMED_STRING
;
2902 StringPtr
= NextStringPtr
;
2905 // 3. Extract keyword from the KeywordRequest string.
2907 KeywordStartPos
= StringPtr
;
2908 Status
= ExtractKeyword(StringPtr
, &KeywordData
, &NextStringPtr
);
2909 if (EFI_ERROR (Status
)) {
2911 // Can't find Keyword base on the input device path info.
2913 *ProgressErr
= KEYWORD_HANDLER_MALFORMED_STRING
;
2914 Status
= EFI_INVALID_PARAMETER
;
2917 StringPtr
= NextStringPtr
;
2920 // 4. Extract Value from the KeywordRequest string.
2922 Status
= ExtractValue (StringPtr
, &ValueElement
, &NextStringPtr
);
2923 if (EFI_ERROR (Status
)) {
2925 // Can't find Value base on the input device path info.
2927 *ProgressErr
= KEYWORD_HANDLER_MALFORMED_STRING
;
2928 Status
= EFI_INVALID_PARAMETER
;
2931 StringPtr
= NextStringPtr
;
2934 // 5. Find READONLY tag.
2936 if ((StringPtr
!= NULL
) && StrnCmp (StringPtr
, L
"&READONLY", StrLen (L
"&READONLY")) == 0) {
2938 StringPtr
+= StrLen (L
"&READONLY");
2944 // 6. Get EFI_STRING_ID for the input keyword.
2946 Status
= GetStringIdFromDatabase (&DevicePath
, &NameSpace
, KeywordData
, &RetVal
, &KeywordStringId
, &DataBaseRecord
);
2947 if (EFI_ERROR (Status
)) {
2948 *ProgressErr
= RetVal
;
2953 // 7. Construct the ConfigRequest string.
2955 Status
= ExtractConfigResp (DataBaseRecord
, KeywordStringId
, ValueElement
, &OpCode
, &ConfigResp
);
2956 if (EFI_ERROR (Status
)) {
2961 // 8. Check the readonly flag.
2963 if (ExtractReadOnlyFromOpCode (OpCode
) != ReadOnly
) {
2965 // Extracting readonly flag form opcode and extracting "READONLY" tag form KeywordString should have the same results.
2966 // If not, the input KeywordString must be incorrect, return the error status to caller.
2968 *ProgressErr
= KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED
;
2969 Status
= EFI_INVALID_PARAMETER
;
2973 *ProgressErr
= KEYWORD_HANDLER_ACCESS_NOT_PERMITTED
;
2974 Status
= EFI_ACCESS_DENIED
;
2979 // 9. Merge to the MultiKeywordResp string.
2981 Status
= MergeToMultiKeywordResp(&MultiConfigResp
, &ConfigResp
);
2982 if (EFI_ERROR (Status
)) {
2987 // 10. Clean the temp buffer point.
2989 FreePool (NameSpace
);
2990 FreePool (DevicePath
);
2991 FreePool (KeywordData
);
2992 FreePool (ValueElement
);
2996 ValueElement
= NULL
;
2997 if (ConfigResp
!= NULL
) {
2998 FreePool (ConfigResp
);
3001 KeywordStartPos
= NULL
;
3005 // 11. Set value to driver.
3007 Status
= mPrivate
.ConfigRouting
.RouteConfig(
3008 &mPrivate
.ConfigRouting
,
3009 (EFI_STRING
) MultiConfigResp
,
3012 if (EFI_ERROR (Status
)) {
3013 Status
= EFI_DEVICE_ERROR
;
3017 *ProgressErr
= KEYWORD_HANDLER_NO_ERROR
;
3020 if (KeywordStartPos
!= NULL
) {
3021 *Progress
= KeywordString
+ (KeywordStartPos
- TempString
);
3023 *Progress
= KeywordString
+ (StringPtr
- TempString
);
3026 ASSERT (TempString
!= NULL
);
3027 FreePool (TempString
);
3028 if (NameSpace
!= NULL
) {
3029 FreePool (NameSpace
);
3031 if (DevicePath
!= NULL
) {
3032 FreePool (DevicePath
);
3034 if (KeywordData
!= NULL
) {
3035 FreePool (KeywordData
);
3037 if (ValueElement
!= NULL
) {
3038 FreePool (ValueElement
);
3040 if (ConfigResp
!= NULL
) {
3041 FreePool (ConfigResp
);
3043 if (MultiConfigResp
!= NULL
&& MultiConfigResp
!= ConfigResp
) {
3044 FreePool (MultiConfigResp
);
3052 This function accepts a <MultiKeywordRequest> formatted string, finds the underlying
3053 keyword owners, creates a <MultiConfigRequest> string from it and forwards it to the
3054 EFI_HII_ROUTING_PROTOCOL.ExtractConfig function.
3056 If there is an issue in resolving the contents of the KeywordString, then the function
3057 returns an EFI_INVALID_PARAMETER and also set the Progress and ProgressErr with the
3058 appropriate information about where the issue occurred and additional data about the
3059 nature of the issue.
3061 In the case when KeywordString is NULL, or contains multiple keywords, or when
3062 EFI_NOT_FOUND is generated while processing the keyword elements, the Results string
3063 contains values returned for all keywords processed prior to the keyword generating the
3064 error but no values for the keyword with error or any following keywords.
3067 @param This Pointer to the EFI_KEYWORD_HANDLER _PROTOCOL instance.
3069 @param NameSpaceId A null-terminated string containing the platform configuration
3070 language to search through in the system. If a NULL is passed
3071 in, then it is assumed that any platform configuration language
3072 with the prefix of "x-UEFI-" are searched.
3074 @param KeywordString A null-terminated string in <MultiKeywordRequest> format. If a
3075 NULL is passed in the KeywordString field, all of the known
3076 keywords in the system for the NameSpaceId specified are
3077 returned in the Results field.
3079 @param Progress On return, points to a character in the KeywordString. Points
3080 to the string's NULL terminator if the request was successful.
3081 Points to the most recent '&' before the first failing name / value
3082 pair (or the beginning of the string if the failure is in the first
3083 name / value pair) if the request was not successful.
3085 @param ProgressErr If during the processing of the KeywordString there was a
3086 failure, this parameter gives additional information about the
3087 possible source of the problem. See the definitions in SetData()
3088 for valid value definitions.
3090 @param Results A null-terminated string in <MultiKeywordResp> format is returned
3091 which has all the values filled in for the keywords in the
3092 KeywordString. This is a callee-allocated field, and must be freed
3093 by the caller after being used.
3095 @retval EFI_SUCCESS The specified action was completed successfully.
3097 @retval EFI_INVALID_PARAMETER One or more of the following are TRUE:
3098 1.Progress, ProgressErr, or Results is NULL.
3099 2.Parsing of the KeywordString resulted in an error. See
3100 Progress and ProgressErr for more data.
3103 @retval EFI_NOT_FOUND An element of the KeywordString was not found. See
3104 ProgressErr for more data.
3106 @retval EFI_NOT_FOUND The NamespaceId specified was not found. See ProgressErr
3109 @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated. See
3110 ProgressErr for more data.
3112 @retval EFI_ACCESS_DENIED The action violated system policy. See ProgressErr for
3115 @retval EFI_DEVICE_ERROR An unexpected system error occurred. See ProgressErr
3121 EfiConfigKeywordHandlerGetData (
3122 IN EFI_CONFIG_KEYWORD_HANDLER_PROTOCOL
*This
,
3123 IN CONST EFI_STRING NameSpaceId
, OPTIONAL
3124 IN CONST EFI_STRING KeywordString
, OPTIONAL
3125 OUT EFI_STRING
*Progress
,
3126 OUT UINT32
*ProgressErr
,
3127 OUT EFI_STRING
*Results
3132 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
3133 HII_DATABASE_RECORD
*DataBaseRecord
;
3135 CHAR16
*NextStringPtr
;
3136 CHAR16
*KeywordData
;
3137 EFI_STRING_ID KeywordStringId
;
3139 CHAR16
*ConfigRequest
;
3140 CHAR16
*ValueElement
;
3143 CHAR16
*KeywordResp
;
3144 CHAR16
*MultiKeywordResp
;
3147 if (This
== NULL
|| Progress
== NULL
|| ProgressErr
== NULL
|| Results
== NULL
) {
3148 return EFI_INVALID_PARAMETER
;
3151 *ProgressErr
= KEYWORD_HANDLER_UNDEFINED_PROCESSING_ERROR
;
3152 Status
= EFI_SUCCESS
;
3156 ConfigRequest
= NULL
;
3157 StringPtr
= KeywordString
;
3159 MultiKeywordResp
= NULL
;
3160 KeywordStringId
= 0;
3164 // Use temp string to avoid changing input string buffer.
3166 if (NameSpaceId
!= NULL
) {
3167 TempString
= AllocateCopyPool (StrSize (NameSpaceId
), NameSpaceId
);
3168 ASSERT (TempString
!= NULL
);
3171 // 1. Get NameSpace from NameSpaceId keyword.
3173 Status
= ExtractNameSpace (TempString
, &NameSpace
, NULL
);
3174 if (TempString
!= NULL
) {
3175 FreePool (TempString
);
3178 if (EFI_ERROR (Status
)) {
3179 *ProgressErr
= KEYWORD_HANDLER_MALFORMED_STRING
;
3183 // 1.1 Check whether the input namespace is valid.
3185 if (NameSpace
!= NULL
){
3186 if (AsciiStrnCmp(NameSpace
, UEFI_CONFIG_LANG
, AsciiStrLen (UEFI_CONFIG_LANG
)) != 0) {
3187 *ProgressErr
= KEYWORD_HANDLER_MALFORMED_STRING
;
3188 return EFI_INVALID_PARAMETER
;
3192 if (KeywordString
!= NULL
) {
3194 // Use temp string to avoid changing input string buffer.
3196 TempString
= AllocateCopyPool (StrSize (KeywordString
), KeywordString
);
3197 ASSERT (TempString
!= NULL
);
3198 StringPtr
= TempString
;
3200 while (*StringPtr
!= L
'\0') {
3202 // 2. Get possible Device Path info from KeywordString.
3204 Status
= ExtractDevicePath (StringPtr
, (UINT8
**)&DevicePath
, &NextStringPtr
);
3205 if (EFI_ERROR (Status
)) {
3206 *ProgressErr
= KEYWORD_HANDLER_MALFORMED_STRING
;
3209 StringPtr
= NextStringPtr
;
3213 // 3. Process Keyword section from the input keywordRequest string.
3215 // 3.1 Extract keyword from the KeywordRequest string.
3217 Status
= ExtractKeyword(StringPtr
, &KeywordData
, &NextStringPtr
);
3218 if (EFI_ERROR (Status
)) {
3220 // Can't find Keyword base on the input device path info.
3222 *ProgressErr
= KEYWORD_HANDLER_MALFORMED_STRING
;
3223 Status
= EFI_INVALID_PARAMETER
;
3228 // 3.2 Get EFI_STRING_ID for the input keyword.
3230 Status
= GetStringIdFromDatabase (&DevicePath
, &NameSpace
, KeywordData
, &RetVal
, &KeywordStringId
, &DataBaseRecord
);
3231 if (EFI_ERROR (Status
)) {
3232 *ProgressErr
= RetVal
;
3237 // 3.3 Construct the ConfigRequest string.
3239 Status
= ExtractConfigRequest (DataBaseRecord
, KeywordStringId
, &OpCode
, &ConfigRequest
);
3240 if (EFI_ERROR (Status
)) {
3245 // 3.4 Extract Value for the input keyword.
3247 Status
= ExtractValueFromDriver(ConfigRequest
, &ValueElement
);
3248 if (EFI_ERROR (Status
)) {
3249 if (Status
!= EFI_OUT_OF_RESOURCES
) {
3250 Status
= EFI_DEVICE_ERROR
;
3254 StringPtr
= NextStringPtr
;
3257 // 4. Process the possible filter section.
3259 RetVal
= ValidateFilter (OpCode
, StringPtr
, &NextStringPtr
, &ReadOnly
);
3260 if (RetVal
!= KEYWORD_HANDLER_NO_ERROR
) {
3261 *ProgressErr
= RetVal
;
3262 Status
= EFI_INVALID_PARAMETER
;
3265 StringPtr
= NextStringPtr
;
3269 // 5. Generate KeywordResp string.
3271 Status
= GenerateKeywordResp(NameSpace
, DevicePath
, KeywordData
, ValueElement
, ReadOnly
, &KeywordResp
);
3272 if (Status
!= EFI_SUCCESS
) {
3277 // 6. Merge to the MultiKeywordResp string.
3279 Status
= MergeToMultiKeywordResp(&MultiKeywordResp
, &KeywordResp
);
3280 if (EFI_ERROR (Status
)) {
3285 // 7. Update return value.
3287 *Results
= MultiKeywordResp
;
3290 // 8. Clean the temp buffer.
3292 FreePool (DevicePath
);
3293 FreePool (KeywordData
);
3294 FreePool (ValueElement
);
3295 FreePool (ConfigRequest
);
3298 ValueElement
= NULL
;
3299 ConfigRequest
= NULL
;
3300 if (KeywordResp
!= NULL
) {
3301 FreePool (KeywordResp
);
3307 // Enumerate all keyword in the system.
3309 Status
= EnumerateAllKeywords(NameSpace
, &MultiKeywordResp
, ProgressErr
);
3310 if (EFI_ERROR (Status
)) {
3313 *Results
= MultiKeywordResp
;
3316 *ProgressErr
= KEYWORD_HANDLER_NO_ERROR
;
3319 *Progress
= KeywordString
+ (StringPtr
- TempString
);
3321 if (TempString
!= NULL
) {
3322 FreePool (TempString
);
3324 if (NameSpace
!= NULL
) {
3325 FreePool (NameSpace
);
3327 if (DevicePath
!= NULL
) {
3328 FreePool (DevicePath
);
3330 if (KeywordData
!= NULL
) {
3331 FreePool (KeywordData
);